? .DS_Store ? .swp ? vocabulary_checkboxes_02.patch ? vocabulary_checkboxes_03.patch ? vocabulary_checkboxes_04.patch ? modules/.DS_Store ? profiles/.DS_Store ? sites/.DS_Store ? sites/default/files ? sites/default/settings.php Index: modules/taxonomy/taxonomy.admin.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/taxonomy/taxonomy.admin.inc,v retrieving revision 1.58 diff -u -p -r1.58 taxonomy.admin.inc --- modules/taxonomy/taxonomy.admin.inc 28 Jun 2009 13:37:29 -0000 1.58 +++ modules/taxonomy/taxonomy.admin.inc 28 Jun 2009 14:37:27 -0000 @@ -114,8 +114,8 @@ function taxonomy_form_vocabulary(&$form 'nodes' => array(), 'hierarchy' => 0, 'relations' => 0, - 'tags' => 0, - 'multiple' => 0, + 'widget' => 'select', + 'multiple' => TRUE, 'required' => 0, 'weight' => 0, ); @@ -158,28 +158,26 @@ function taxonomy_form_vocabulary(&$form '#default_value' => $edit['nodes'], '#options' => array_map('check_plain', node_type_get_names()), ); - $form['settings'] = array( - '#type' => 'fieldset', - '#title' => t('Settings'), - '#collapsible' => TRUE, + $form['widget'] = array( + '#type' => 'radios', + '#title' => t('Term selection widget'), + '#default_value' => $edit['widget'], + '#options' => array( + 'select' => t('Select list'), + 'text' => t('Text input'), + ), ); - $form['settings']['tags'] = array( - '#type' => 'checkbox', - '#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( + $form['multiple'] = array( '#type' => 'checkbox', '#title' => t('Multiple select'), '#default_value' => $edit['multiple'], - '#description' => t('Allows posts to have more than one term from this vocabulary (always true for tags).'), + '#description' => t('Content can have more than one term from this vocabulary.'), ); - $form['settings']['required'] = array( + $form['required'] = array( '#type' => 'checkbox', '#title' => t('Required'), '#default_value' => $edit['required'], - '#description' => t('At least one term in this vocabulary must be selected when submitting a post.'), + '#description' => t('Content must have at least one term form this vocabulary.'), ); // Set the hierarchy to "multiple parents" by default. This simplifies the // vocabulary form and standardizes the term form. @@ -299,7 +297,7 @@ function taxonomy_overview_terms(&$form_ $current_page = array(); // Case for free tagging. - if ($vocabulary->tags) { + if ($vocabulary->widget == 'tags') { // We are not calling taxonomy_get_tree because that might fail with a big // number of tags in the freetagging vocabulary. $query = db_select('taxonomy_term_data', 't')->extend('PagerDefault'); @@ -425,7 +423,7 @@ function taxonomy_overview_terms(&$form_ } $form[$key]['view'] = array('#markup' => l($term->name, "taxonomy/term/$term->tid")); - if (!$vocabulary->tags && $vocabulary->hierarchy < 2 && count($tree) > 1) { + if ($vocabulary->widget != 'tags' && $vocabulary->hierarchy < 2 && count($tree) > 1) { $form['#parent_fields'] = TRUE; $form[$key]['tid'] = array( '#type' => 'hidden', @@ -452,7 +450,7 @@ function taxonomy_overview_terms(&$form_ $form['#forward_peddle'] = $forward_peddle; $form['#empty_text'] = t('No terms available.'); - if (!$vocabulary->tags && $vocabulary->hierarchy < 2 && count($tree) > 1) { + if ($vocabulary->widget != 'tags' && $vocabulary->hierarchy < 2 && count($tree) > 1) { $form['submit'] = array( '#type' => 'submit', '#value' => t('Save') @@ -812,7 +810,7 @@ function taxonomy_form_term_submit($form return; } // Rebuild the form to confirm enabling multiple parents. - elseif ($form_state['clicked_button']['#value'] == t('Save') && !$form['#vocabulary']->tags && count($form_state['values']['parent']) > 1 && $form['#vocabulary']->hierarchy < 2) { + elseif ($form_state['clicked_button']['#value'] == t('Save') && count($form_state['values']['parent']) > 1 && $form['#vocabulary']->hierarchy < 2) { $form_state['rebuild'] = TRUE; $form_state['confirm_parents'] = TRUE; return; @@ -832,26 +830,24 @@ function taxonomy_form_term_submit($form break; } - if (!$form['#vocabulary']->tags) { - $current_parent_count = count($form_state['values']['parent']); - $previous_parent_count = count($form['#term']['parent']); - // Root doesn't count if it's the only parent. - if ($current_parent_count == 1 && isset($form_state['values']['parent'][0])) { - $current_parent_count = 0; - $form_state['values']['parent'] = array(); - } - - // If the number of parents has been reduced to one or none, do a check on the - // parents of every term in the vocabulary value. - if ($current_parent_count < $previous_parent_count && $current_parent_count < 2) { - taxonomy_check_vocabulary_hierarchy($form['#vocabulary'], $form_state['values']); - } - // If we've increased the number of parents and this is a single or flat - // hierarchy, update the vocabulary immediately. - elseif ($current_parent_count > $previous_parent_count && $form['#vocabulary']->hierarchy < 2) { - $form['#vocabulary']->hierarchy = $current_parent_count == 1 ? 1 : 2; - taxonomy_vocabulary_save($form['#vocabulary']); - } + $current_parent_count = count($form_state['values']['parent']); + $previous_parent_count = count($form['#term']['parent']); + // Root doesn't count if it's the only parent. + if ($current_parent_count == 1 && isset($form_state['values']['parent'][0])) { + $current_parent_count = 0; + $form_state['values']['parent'] = array(); + } + + // If the number of parents has been reduced to one or none, do a check on the + // parents of every term in the vocabulary value. + if ($current_parent_count < $previous_parent_count && $current_parent_count < 2) { + taxonomy_check_vocabulary_hierarchy($form['#vocabulary'], $form_state['values']); + } + // If we've increased the number of parents and this is a single or flat + // hierarchy, update the vocabulary immediately. + elseif ($current_parent_count > $previous_parent_count && $form['#vocabulary']->hierarchy < 2) { + $form['#vocabulary']->hierarchy = $current_parent_count == 1 ? 1 : 2; + taxonomy_vocabulary_save($form['#vocabulary']); } $form_state['tid'] = $term->tid; Index: modules/taxonomy/taxonomy.install =================================================================== RCS file: /cvs/drupal/drupal/modules/taxonomy/taxonomy.install,v retrieving revision 1.20 diff -u -p -r1.20 taxonomy.install --- modules/taxonomy/taxonomy.install 18 Jun 2009 15:46:30 -0000 1.20 +++ modules/taxonomy/taxonomy.install 28 Jun 2009 14:37:27 -0000 @@ -21,8 +21,7 @@ function taxonomy_uninstall() { // Remove tables. drupal_uninstall_schema('taxonomy'); - // Remove variables. - variable_del('taxonomy_override_selector'); + // Remove variable. variable_del('taxonomy_terms_per_page_admin'); } @@ -278,13 +277,12 @@ function taxonomy_schema() { 'size' => 'tiny', 'description' => 'Whether or not terms are required for nodes using this vocabulary. (0 = disabled, 1 = enabled)', ), - 'tags' => array( - 'type' => 'int', - 'unsigned' => TRUE, + 'widget' => array( + 'type' => 'varchar', + 'length' => 255, 'not null' => TRUE, - 'default' => 0, - 'size' => 'tiny', - 'description' => 'Whether or not free tagging is enabled for the vocabulary. (0 = disabled, 1 = enabled)', + 'default' => '', + 'description' => 'The selection widget used to apply terms from this vocabulary.', ), 'module' => array( 'type' => 'varchar', @@ -362,3 +360,31 @@ function taxonomy_update_7002() { } return $ret; } + + +/** + * Change 'tags' column to 'widget'. + */ +function taxonomy_update_7003() { + $ret = array(); + $field = array( + 'widget' => array( + 'type' => 'varchar', + 'length' => 255, + 'not null' => TRUE, + 'default' => '', + 'description' => 'The selection widget used to apply terms from this vocabulary.', + ), + ); + db_change_field($ret, 'taxonomy_vocabulary', 'tags', 'widget', $field); + + foreach (taxonomy_get_vocabularies() as $vid => $vocabulary) { + $widget = $vocabulary->tags ? 'tags' : 'select'; + db_update('taxonomy_vocabulary') + ->fields(array('widget' => $widget)) + ->condition('vid', $vid) + ->execute(); + } + + return $ret; +} Index: modules/taxonomy/taxonomy.module =================================================================== RCS file: /cvs/drupal/drupal/modules/taxonomy/taxonomy.module,v retrieving revision 1.481 diff -u -p -r1.481 taxonomy.module --- modules/taxonomy/taxonomy.module 27 Jun 2009 19:49:07 -0000 1.481 +++ modules/taxonomy/taxonomy.module 28 Jun 2009 14:37:27 -0000 @@ -586,7 +586,7 @@ function taxonomy_form_all($free_tags = $vocabularies = taxonomy_get_vocabularies(); $options = array(); foreach ($vocabularies as $vid => $vocabulary) { - if ($vocabulary->tags && !$free_tags) { + if ($vocabulary->widget == 'tags' && !$free_tags) { continue; } $tree = taxonomy_get_tree($vid); @@ -634,7 +634,7 @@ function taxonomy_vocabulary_get_names() * and provide scalable alternatives. */ function taxonomy_form_alter(&$form, $form_state, $form_id) { - if (!variable_get('taxonomy_override_selector', FALSE) && !empty($form['#node_edit_form'])) { + if (!empty($form['#node_edit_form'])) { $node = $form['#node']; if (!isset($node->taxonomy)) { @@ -659,7 +659,8 @@ function taxonomy_form_alter(&$form, $fo ->execute(); foreach ($result as $vocabulary) { - if ($vocabulary->tags) { + // Render a tags widget. + if ($vocabulary->widget == 'text') { if (isset($form_state['node_preview'])) { // Typed string can be changed by the user before preview, // so we just insert the tags directly as provided in the form. @@ -668,10 +669,12 @@ function taxonomy_form_alter(&$form, $fo else { $typed_string = taxonomy_implode_tags($terms, $vocabulary->vid) . (array_key_exists('tags', $terms) ? $terms['tags'][$vocabulary->vid] : NULL); } + + $help = ''; if ($vocabulary->help) { $help = filter_xss_admin($vocabulary->help); } - else { + elseif ($vocabulary->multiple) { $help = t('A comma-separated list of terms describing this content. Example: funny, bungee jumping, "Company, Inc."'); } $form['taxonomy']['tags'][$vocabulary->vid] = array('#type' => 'textfield', @@ -684,6 +687,7 @@ function taxonomy_form_alter(&$form, $fo '#maxlength' => 1024, ); } + // Render a select list widget. else { // Extract terms belonging to the vocabulary in question. $default_terms = array(); @@ -845,6 +849,11 @@ function taxonomy_node_save($node, $term $vocabulary = taxonomy_vocabulary_load($vid); $typed_terms = drupal_explode_tags($vid_value); + // Prevent multiple terms from being applied if that's disabled. + if (!$vocabulary->multiple) { + $typed_terms = array($typed_terms[0]); + } + $inserted = array(); foreach ($typed_terms as $typed_term) { // See if the term exists in the chosen vocabulary @@ -1692,7 +1701,7 @@ function taxonomy_node_validate($node, $ if (!empty($terms['tags'])) { foreach ($terms['tags'] as $vid => $vid_value) { $vocabulary = taxonomy_vocabulary_load($vid); - if (empty($vocabulary->tags)) { + if ($vocabulary->widget != 'text') { // see form_get_error $key = implode('][', $element['#parents']); // on why this is the key form_set_error("taxonomy][tags][$vid", t('The %name vocabulary can not be modified in this way.', array('%name' => $vocabulary->name))); @@ -1762,7 +1771,7 @@ function taxonomy_help($path, $arg) { return $output; case 'admin/build/taxonomy/%/list': $vocabulary = taxonomy_vocabulary_load($arg[3]); - if ($vocabulary->tags) { + if ($vocabulary->widget == 'tags') { return '
' . t('%capital_name is a free-tagging vocabulary. To change the name or description of a term, click the edit link next to the term.', array('%capital_name' => drupal_ucfirst($vocabulary->name))) . '
'; } switch ($vocabulary->hierarchy) { Index: modules/taxonomy/taxonomy.pages.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/taxonomy/taxonomy.pages.inc,v retrieving revision 1.30 diff -u -p -r1.30 taxonomy.pages.inc --- modules/taxonomy/taxonomy.pages.inc 28 Jun 2009 13:37:29 -0000 1.30 +++ modules/taxonomy/taxonomy.pages.inc 28 Jun 2009 14:37:27 -0000 @@ -123,10 +123,17 @@ function taxonomy_term_edit($term) { * Helper function for autocompletion */ function taxonomy_autocomplete($vid = 0, $tags_typed = '') { - // The user enters a comma-separated list of tags. We only autocomplete the last tag. + // The user enters a comma-separated list of tags. $tags_typed = drupal_explode_tags($tags_typed); - $tag_last = drupal_strtolower(array_pop($tags_typed)); + // Prevent autocomplete for non-multiple vocabularies if more than one term + // was entered. + $vocabulary = taxonomy_vocabulary_load($vid); + if (!$vocabulary->multiple && count($array) > 1) { + return drupal_json(array()); + } + + $tag_last = drupal_strtolower(array_pop($tags_typed)); $matches = array(); if ($tag_last != '') { $query = db_select('taxonomy_term_data', 't'); Index: modules/taxonomy/taxonomy.test =================================================================== RCS file: /cvs/drupal/drupal/modules/taxonomy/taxonomy.test,v retrieving revision 1.38 diff -u -p -r1.38 taxonomy.test --- modules/taxonomy/taxonomy.test 27 Jun 2009 19:49:07 -0000 1.38 +++ modules/taxonomy/taxonomy.test 28 Jun 2009 14:37:27 -0000 @@ -507,7 +507,7 @@ class TaxonomyTermTestCase extends Taxon */ function testNodeTermCreation() { // Enable tags in the vocabulary. - $this->vocabulary->tags = 1; + $this->vocabulary->widget = 'text'; taxonomy_vocabulary_save($this->vocabulary); $terms = array( $this->randomName(), Index: profiles/default/default.profile =================================================================== RCS file: /cvs/drupal/drupal/profiles/default/default.profile,v retrieving revision 1.51 diff -u -p -r1.51 default.profile --- profiles/default/default.profile 27 Jun 2009 17:32:00 -0000 1.51 +++ profiles/default/default.profile 28 Jun 2009 14:37:27 -0000 @@ -209,7 +209,7 @@ function default_profile_tasks(&$task, $ 'hierarchy' => 0, 'multiple' => 0, 'required' => 0, - 'tags' => 1, + 'widget' => 'text', 'module' => 'taxonomy', 'weight' => 0, ))->execute();