Index: modules/field/modules/options/options.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/field/modules/options/options.module,v
retrieving revision 1.3
diff -u -p -r1.3 options.module
--- modules/field/modules/options/options.module 10 Feb 2009 03:16:15 -0000 1.3
+++ modules/field/modules/options/options.module 24 Mar 2009 18:34:30 -0000
@@ -44,7 +44,7 @@ function options_field_widget_info() {
return array(
'options_select' => array(
'label' => t('Select list'),
- 'field types' => array('list', 'list_boolean', 'list_text', 'list_number'),
+ 'field types' => array('list', 'list_boolean', 'list_text', 'list_number', 'term'),
'behaviors' => array(
'multiple values' => FIELD_BEHAVIOR_CUSTOM,
'default value' => FIELD_BEHAVIOR_DEFAULT,
@@ -52,7 +52,7 @@ function options_field_widget_info() {
),
'options_buttons' => array(
'label' => t('Check boxes/radio buttons'),
- 'field types' => array('list', 'list_boolean', 'list_text', 'list_number'),
+ 'field types' => array('list', 'list_boolean', 'list_text', 'list_number', 'term'),
'behaviors' => array(
'multiple values' => FIELD_BEHAVIOR_CUSTOM,
'default value' => FIELD_BEHAVIOR_DEFAULT,
Index: modules/taxonomy/taxonomy.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/taxonomy/taxonomy.admin.inc,v
retrieving revision 1.47
diff -u -p -r1.47 taxonomy.admin.inc
--- modules/taxonomy/taxonomy.admin.inc 14 Mar 2009 20:13:27 -0000 1.47
+++ modules/taxonomy/taxonomy.admin.inc 24 Mar 2009 18:34:31 -0000
@@ -25,7 +25,6 @@ function taxonomy_overview_vocabularies(
$form[$vocabulary->vid]['#vocabulary'] = $vocabulary;
$form[$vocabulary->vid]['name'] = array('#markup' => check_plain($vocabulary->name));
$form[$vocabulary->vid]['types'] = array('#markup' => implode(', ', $types));
- $form[$vocabulary->vid]['weight'] = array('#type' => 'weight', '#delta' => 10, '#default_value' => $vocabulary->weight);
$form[$vocabulary->vid]['edit'] = array('#markup' => l(t('edit vocabulary'), "admin/content/taxonomy/$vocabulary->vid"));
$form[$vocabulary->vid]['list'] = array('#markup' => l(t('list terms'), "admin/content/taxonomy/$vocabulary->vid/list"));
$form[$vocabulary->vid]['add'] = array('#markup' => l(t('add terms'), "admin/content/taxonomy/$vocabulary->vid/add"));
@@ -36,9 +35,6 @@ function taxonomy_overview_vocabularies(
if (count($vocabularies) > 1) {
$form['submit'] = array('#type' => 'submit', '#value' => t('Save'));
}
- elseif (isset($vocabulary)) {
- unset($form[$vocabulary->vid]['weight']);
- }
return $form;
}
@@ -49,8 +45,7 @@ function taxonomy_overview_vocabularies(
*/
function taxonomy_overview_vocabularies_submit($form, &$form_state) {
foreach ($form_state['values'] as $vid => $vocabulary) {
- if (is_numeric($vid) && $form[$vid]['#vocabulary']->weight != $form_state['values'][$vid]['weight']) {
- $form[$vid]['#vocabulary']->weight = $form_state['values'][$vid]['weight'];
+ if (is_numeric($vid)) {
taxonomy_vocabulary_save($form[$vid]['#vocabulary']);
}
}
@@ -71,10 +66,6 @@ function theme_taxonomy_overview_vocabul
$row = array();
$row[] = drupal_render($vocabulary['name']);
$row[] = drupal_render($vocabulary['types']);
- if (isset($vocabulary['weight'])) {
- $vocabulary['weight']['#attributes']['class'] = 'vocabulary-weight';
- $row[] = drupal_render($vocabulary['weight']);
- }
$row[] = drupal_render($vocabulary['edit']);
$row[] = drupal_render($vocabulary['list']);
$row[] = drupal_render($vocabulary['add']);
@@ -87,13 +78,24 @@ function theme_taxonomy_overview_vocabul
$header = array(t('Vocabulary name'), t('Content types'));
if (isset($form['submit'])) {
- $header[] = t('Weight');
- drupal_add_tabledrag('taxonomy', 'order', 'sibling', 'vocabulary-weight');
+ drupal_add_tabledrag('taxonomy', 'order', 'sibling');
}
$header[] = array('data' => t('Operations'), 'colspan' => '3');
return theme('table', $header, $rows, array('id' => 'taxonomy')) . drupal_render_children($form);
}
+
+/**
+ * Take a user-entered name and make it machine-safe.
+ *
+ * Replace spaces and all unknown characters with underscores and lowercase.
+ *
+ * @TODO get this into common.inc
+ */
+function drupal_system_string($string, $replacement = '_') {
+ return preg_replace('/[^a-z0-9]+/', $replacement, strtolower($string));
+}
+
/**
* Display form for adding and editing vocabularies.
*
@@ -103,18 +105,16 @@ function theme_taxonomy_overview_vocabul
function taxonomy_form_vocabulary(&$form_state, $edit = array()) {
if (!is_array($edit)) {
$edit = (array)$edit;
- }
+ }
$edit += array(
'name' => '',
'description' => '',
'help' => '',
- 'nodes' => array(),
'hierarchy' => 0,
'relations' => 0,
'tags' => 0,
'multiple' => 0,
'required' => 0,
- 'weight' => 0,
);
// Check whether we need a deletion confirmation form.
if (isset($form_state['confirm_delete']) && isset($form_state['values']['vid'])) {
@@ -127,6 +127,7 @@ function taxonomy_form_vocabulary(&$form
'#maxlength' => 255,
'#description' => t('The name for this vocabulary, e.g., "Tags".'),
'#required' => TRUE,
+ '#field_suffix' => ' ',
);
$form['help'] = array(
'#type' => 'textfield',
@@ -141,13 +142,37 @@ function taxonomy_form_vocabulary(&$form
'#default_value' => $edit['description'],
'#description' => t('Description of the vocabulary; can be used by modules.'),
);
- $form['nodes'] = array(
- '#type' => 'checkboxes',
- '#title' => t('Content types'),
- '#default_value' => $edit['nodes'],
- '#options' => array_map('check_plain', node_get_types('names')),
- '#description' => t('Select content types to categorize using this vocabulary.'),
- );
+ if (module_exists('term')) {
+ $edit['field_name'] = '';
+ $edit['nodes'] = array();
+ if (array_key_exists('vid', $edit)) {
+ $instances = array();
+ foreach (field_read_fields(array('module' => 'term')) as $field) {
+ if ($field['settings']['vid'] == $edit['vid']) {
+ $edit['field_name'] = $field['field_name'];
+ $fields[] = $field['field_name'];
+ $instances = array_merge(field_read_instances(array('field_name' => $fields)), $instances);
+ }
+ }
+ foreach ($instances as $instance) {
+ $edit['nodes'][] = $instance['bundle'];
+ }
+ }
+ $form['field_name'] = array(
+ '#type' => 'textfield',
+ '#title' => t('Field name'),
+ '#default_value' => $edit['field_name'],
+ '#maxlength' => 32,
+ '#description' => t('The machine-readable name for this vocabulary\'s field. This name must contain only lowercase letters, numbers, and underscores. This name must be unique.'),
+ );
+ $form['nodes'] = array(
+ '#type' => 'checkboxes',
+ '#title' => t('Content types'),
+ '#default_value' => $edit['nodes'],
+ '#options' => array_map('check_plain', node_get_types('names')),
+ '#description' => t('Select content types to categorize using this vocabulary.'),
+ );
+ }
$form['settings'] = array(
'#type' => 'fieldset',
'#title' => t('Settings'),
@@ -158,7 +183,7 @@ function taxonomy_form_vocabulary(&$form
'#title' => t('Tags'),
'#default_value' => $edit['tags'],
'#description' => t('Terms are created by users when submitting posts by typing a comma separated list.'),
- );
+ );
$form['settings']['multiple'] = array(
'#type' => 'checkbox',
'#title' => t('Multiple select'),
@@ -171,6 +196,8 @@ function taxonomy_form_vocabulary(&$form
'#default_value' => $edit['required'],
'#description' => t('At least one term in this vocabulary must be selected when submitting a post.'),
);
+
+ // @TODO - what? this *disables* multiple parents, and there's no UI way to turn it on!?!
// Set the hierarchy to "multiple parents" by default. This simplifies the
// vocabulary form and standardizes the term form.
$form['hierarchy'] = array(
@@ -215,6 +242,36 @@ function taxonomy_form_vocabulary_submit
watchdog('taxonomy', 'Updated vocabulary %name.', array('%name' => $vocabulary->name), WATCHDOG_NOTICE, l(t('edit'), 'admin/content/taxonomy/' . $vocabulary->vid));
break;
}
+ if (module_exists('term')) {
+ if (!field_read_field($vocabulary->field_name)) {
+ $field = array(
+ 'field_name' => $vocabulary->field_name,
+ 'module' => 'term',
+ 'type' => 'term',
+ 'cardinality' => ($vocabulary->multiple ? FIELD_CARDINALITY_UNLIMITED : 1),
+ 'settings' => array(
+ 'vid' => $vocabulary->vid,
+ ),
+ );
+ field_create_field($field);
+ }
+ $instance = array(
+ 'field_name' => $vocabulary->field_name,
+ 'bundle' => '',
+ 'label' => $vocabulary->name,
+ 'description' => $vocabulary->description,
+ 'required' => $vocabulary->required,
+ 'widget' => array(
+ 'type' => 'options_select',
+ ),
+ );
+ foreach ($vocabulary->nodes as $node_type) {
+ $instance['bundle'] = $node_type;
+ if (!field_read_instance($vocabulary->field_name, $node_type)) {
+ field_create_instance($instance);
+ }
+ }
+ }
$form_state['vid'] = $vocabulary->vid;
$form_state['redirect'] = 'admin/content/taxonomy';
@@ -265,7 +322,7 @@ function taxonomy_overview_terms(&$form_
if ($vocabulary->tags) {
// We are not calling taxonomy_get_tree because that might fail with a big
// number of tags in the freetagging vocabulary.
- $results = pager_query(db_rewrite_sql('SELECT t.*, h.parent FROM {taxonomy_term_data} t INNER JOIN {taxonomy_term_hierarchy} h ON t.tid = h.tid WHERE t.vid = %d ORDER BY weight, name', 't', 'tid'), $page_increment, 0, NULL, $vocabulary->vid);
+ $results = pager_query(db_rewrite_sql('SELECT t.*, h.parent FROM {taxonomy_term_data} t INNER JOIN {taxonomy_term_hierarchy} h ON t.tid = h.tid WHERE t.vid = %d ORDER BY name', 't', 'tid'), $page_increment, 0, NULL, $vocabulary->vid);
$total_entries = db_query(db_rewrite_sql('SELECT COUNT(*) FROM {taxonomy_term_data} t INNER JOIN {taxonomy_term_hierarchy} h ON t.tid = h.tid WHERE t.vid = :vid'), array(':vid' => $vocabulary->vid));
while ($term = db_fetch_object($results)) {
$key = 'tid:' . $term->tid . ':0';
Index: modules/taxonomy/taxonomy.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/taxonomy/taxonomy.module,v
retrieving revision 1.463
diff -u -p -r1.463 taxonomy.module
--- modules/taxonomy/taxonomy.module 21 Mar 2009 00:59:02 -0000 1.463
+++ modules/taxonomy/taxonomy.module 24 Mar 2009 18:34:32 -0000
@@ -212,17 +212,10 @@ function taxonomy_vocabulary_save($vocab
if (!empty($vocabulary->vid) && !empty($vocabulary->name)) {
$status = drupal_write_record('taxonomy_vocabulary', $vocabulary, 'vid');
- db_query("DELETE FROM {taxonomy_vocabulary_node_type} WHERE vid = %d", $vocabulary->vid);
- foreach ($vocabulary->nodes as $type => $selected) {
- db_query("INSERT INTO {taxonomy_vocabulary_node_type} (vid, type) VALUES (%d, '%s')", $vocabulary->vid, $type);
- }
module_invoke_all('taxonomy_vocabulary_update', $vocabulary);
}
elseif (empty($vocabulary->vid)) {
$status = drupal_write_record('taxonomy_vocabulary', $vocabulary);
- foreach ($vocabulary->nodes as $type => $selected) {
- db_query("INSERT INTO {taxonomy_vocabulary_node_type} (vid, type) VALUES (%d, '%s')", $vocabulary->vid, $type);
- }
module_invoke_all('taxonomy_vocabulary_insert', $vocabulary);
}
Index: modules/taxonomy/term.info
===================================================================
RCS file: modules/taxonomy/term.info
diff -N modules/taxonomy/term.info
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ modules/taxonomy/term.info 24 Mar 2009 18:34:32 -0000
@@ -0,0 +1,6 @@
+; $Id$
+name = Term
+description = Defines taxonomy term field types. Use with Options to create selection lists.
+package = Core - fields
+core = 7.x
+files[]=term.module
Index: modules/taxonomy/term.module
===================================================================
RCS file: modules/taxonomy/term.module
diff -N modules/taxonomy/term.module
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ modules/taxonomy/term.module 24 Mar 2009 18:34:32 -0000
@@ -0,0 +1,154 @@
+ array(
+ 'arguments' => array('element' => NULL),
+ ),
+ 'field_formatter_term_key' => array(
+ 'arguments' => array('element' => NULL),
+ ),
+ );
+}
+
+/**
+ * Implementation of hook_field_info().
+ */
+function term_field_info() {
+ return array(
+ 'term' => array(
+ 'label' => t('Term'),
+ 'description' => t('This field stores keys from key/value terms of allowed numbers where the stored numeric key has significance and must be preserved, i.e. \'Lifetime in days\': 1|1 day, 7|1 week, 31|1 month.'),
+ 'settings' => array('allowed_values_function' => ''),
+ 'default_widget' => 'options_select',
+ 'default_formatter' => 'term_default',
+ 'settings' => array('vid' => 0),
+ ),
+ );
+}
+
+/**
+ * Implementation of hook_field_columns().
+ *
+ * @TODO text.module calls this an implementation of hook_field_schema(),
+ * any deep meaning in that or just correct it in text.module?
+ */
+function term_field_columns($field) {
+ $columns = array(
+ 'value' => array(
+ 'type' => 'int',
+ 'unsigned' => TRUE,
+ 'not null' => FALSE,
+ ),
+ );
+ return $columns;
+}
+
+/**
+ * Implementation of hook_field_validate().
+ */
+function term_field_validate($obj_type, $object, $field, $instance, $items, $form) {
+ $allowed_values = term_allowed_values($field);
+ if (is_array($items)) {
+ foreach ($items as $delta => $item) {
+ $error_element = isset($item['_error_element']) ? $item['_error_element'] : '';
+ if (is_array($item) && isset($item['_error_element'])) unset($item['_error_element']);
+ if (!empty($item['value'])) {
+ if (count($allowed_values) && !array_key_exists($item['value'], $allowed_values)) {
+ form_set_error($error_element, t('%name: illegal value.', array('%name' => t($instance['label']))));
+ }
+ }
+ }
+ }
+}
+
+/**
+ * Implementation of hook_field_is_empty().
+ */
+function term_field_is_empty($item, $field) {
+ if (empty($item['value']) && (string)$item['value'] !== '0') {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * Implementation of hook_field_formatter_info().
+ */
+function term_field_formatter_info() {
+ return array(
+ 'term_default' => array(
+ 'label' => t('Default'),
+ 'field types' => array('term'),
+ 'behaviors' => array(
+ 'multiple values' => FIELD_BEHAVIOR_DEFAULT,
+ ),
+ ),
+ 'term_id' => array( // why this second one..?
+ 'label' => t('Id'),
+ 'field types' => array('term'),
+ 'behaviors' => array(
+ 'multiple values' => FIELD_BEHAVIOR_DEFAULT,
+ ),
+ ),
+ );
+}
+
+/**
+ * Theme function for 'default' term field formatter.
+ */
+function theme_field_formatter_term_default($element) {
+ $field = field_info_field($element['#field_name']);
+ if (($allowed_values = term_allowed_values($field)) && isset($allowed_values[$element['#item']['value']])) {
+ return $allowed_values[$element['#item']['value']];
+ }
+ // If no match was found in allowed values, fall back to the key.
+ return $element['#item']['safe'];
+}
+
+/**
+ * Theme function for 'key' term field formatter.
+ */
+function theme_field_formatter_term_key($element) {
+ return $element['#item']['safe'];
+}
+
+/**
+ * Create an array of the allowed values for this field.
+ *
+ * Call the allowed_values_function to retrieve the allowed
+ * values array.
+ *
+ * This function should imitate the features of _taxonomy_term_select
+ *
+ * TODO Rework this to create a method of selecting plugable allowed values terms
+ * TODO deal with excluded tids
+ *
+ */
+function term_allowed_values($field) {
+ $tree = taxonomy_get_tree($field['settings']['vid']);
+ $options = array();
+
+// if ($blank) {
+// $options[0] = $blank;
+// }
+ if ($tree) {
+ foreach ($tree as $term) {
+// if (!in_array($term->tid, $exclude)) {
+ $choice = new stdClass();
+ $choice->option = array($term->tid => str_repeat('-', $term->depth) . $term->name);
+ $options[] = $choice;
+// }
+ }
+ }
+ return $options;
+}