Index: modules/taxonomy/taxonomy.admin.inc =================================================================== RCS file: /cvs/drupal/drupal/modules/taxonomy/taxonomy.admin.inc,v retrieving revision 1.37 diff -u -p -r1.37 taxonomy.admin.inc --- modules/taxonomy/taxonomy.admin.inc 13 Nov 2008 08:13:56 -0000 1.37 +++ modules/taxonomy/taxonomy.admin.inc 1 Dec 2008 21:20:20 -0000 @@ -160,14 +160,14 @@ function taxonomy_form_vocabulary(&$form '#collapsible' => TRUE, ); $form['settings']['tags'] = array('#type' => 'checkbox', - '#title' => t('Tags'), + '#title' => t('Autocomplete'), '#default_value' => $edit['tags'], - '#description' => t('Terms are created by users when submitting posts by typing a comma separated list.'), + '#description' => t('Use autocomplete selection when posting content. Users with the appropriate permission may create new terms.'), ); $form['settings']['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('Allows posts to have more than one term from this vocabulary (always true for autocomplete).'), ); $form['settings']['required'] = array('#type' => 'checkbox', '#title' => t('Required'), @@ -701,12 +701,16 @@ function taxonomy_form_term(&$form_state '#value' => t('Save')); if ($edit['tid']) { - $form['delete'] = array( - '#type' => 'submit', - '#value' => t('Delete')); + if (user_access("delete terms in $vocabulary->vid") || user_access('administer taxonomy')) { + $form['delete'] = array( + '#type' => 'submit', + '#value' => t('Delete'), + ); + } $form['tid'] = array( '#type' => 'value', - '#value' => $edit['tid']); + '#value' => $edit['tid'], + ); } else { $form['destination'] = array('#type' => 'hidden', '#value' => $_GET['q']); Index: modules/taxonomy/taxonomy.module =================================================================== RCS file: /cvs/drupal/drupal/modules/taxonomy/taxonomy.module,v retrieving revision 1.442 diff -u -p -r1.442 taxonomy.module --- modules/taxonomy/taxonomy.module 13 Nov 2008 08:13:56 -0000 1.442 +++ modules/taxonomy/taxonomy.module 1 Dec 2008 21:20:34 -0000 @@ -10,12 +10,33 @@ * Implementation of hook_perm(). */ function taxonomy_perm() { - return array( + $permissions = array( 'administer taxonomy' => array( 'title' => t('Administer taxonomy'), 'description' => t('Manage taxonomy vocabularies and terms.'), ), ); + foreach (taxonomy_get_vocabularies() as $vocabulary) { + $permissions += array( + "create terms in $vocabulary->vid" => array( + 'title' => t('Create terms in %vocabulary', array('%vocabulary' => $vocabulary->name)), + 'description' => t('Create terms in the %vocabulary vocabulary.', array('%vocabulary' => $vocabulary->name)), + ), + ); + $permissions += array( + "edit terms in $vocabulary->vid" => array( + 'title' => t('Edit terms in %vocabulary', array('%vocabulary' => $vocabulary->name)), + 'description' => t('Edit terms in the %vocabulary vocabulary.', array('%vocabulary' => $vocabulary->name)), + ), + ); + $permissions += array( + "delete terms in $vocabulary->vid" => array( + 'title' => t('Delete terms in %vocabulary', array('%vocabulary' => $vocabulary->name)), + 'description' => t('Delete terms in the %vocabulary vocabulary.', array('%vocabulary' => $vocabulary->name)), + ), + ); + } + return $permissions; } /** @@ -153,7 +174,8 @@ function taxonomy_menu() { 'title' => 'Edit term', 'page callback' => 'taxonomy_term_edit', 'page arguments' => array(2), - 'access arguments' => array('administer taxonomy'), + 'access callback' => 'taxonomy_term_edit_access', + 'access arguments' => array(2), 'type' => MENU_LOCAL_TASK, 'weight' => 10, ); @@ -209,6 +231,13 @@ function taxonomy_admin_vocabulary_title } /** + * Return edit access for a given term. + */ +function taxonomy_term_edit_access($term) { + return user_access("edit terms in $term->vid") || user_access('administer taxonomy'); +} + +/** * Save a vocabulary given a vocabulary object. */ function taxonomy_vocabulary_save($vocabulary) { @@ -637,25 +666,6 @@ function taxonomy_node_get_terms($node, } /** - * Make sure incoming vids are free tagging enabled. - */ -function taxonomy_node_validate(&$node) { - if (!empty($node->taxonomy)) { - $terms = $node->taxonomy; - if (!empty($terms['tags'])) { - foreach ($terms['tags'] as $vid => $vid_value) { - $vocabulary = taxonomy_vocabulary_load($vid); - if (empty($vocabulary->tags)) { - // 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))); - } - } - } - } -} - -/** * Save term associations for a given node. */ function taxonomy_node_save($node, $terms) { @@ -670,6 +680,7 @@ function taxonomy_node_save($node, $term foreach ($typed_input as $vid => $vid_value) { $typed_terms = drupal_explode_tags($vid_value); + $rejected_terms = array(); $inserted = array(); foreach ($typed_terms as $typed_term) { @@ -684,18 +695,25 @@ function taxonomy_node_save($node, $term } if (!$typed_term_tid) { - $edit = array('vid' => $vid, 'name' => $typed_term); - $term = (object)$edit; - $status = taxonomy_term_save($term); - $typed_term_tid = $term->tid; + if (user_access("create terms in $vid") || user_access('administer taxonomy')) { + $edit = array('vid' => $vid, 'name' => $typed_term); + $term = (object)$edit; + $status = taxonomy_term_save($term); + $typed_term_tid = $term->tid; + } + else { + $rejected_terms[] = $typed_term; + } } - // Defend against duplicate, differently cased tags if (!isset($inserted[$typed_term_tid])) { db_query('INSERT INTO {term_node} (nid, vid, tid) VALUES (%d, %d, %d)', $node->nid, $node->vid, $typed_term_tid); $inserted[$typed_term_tid] = TRUE; } } + if (!empty($rejected_terms)) { + drupal_set_message(t('You do not permissions to save the terms: %terms.', array('%terms' => implode(', ', $rejected_terms)))); + } } } @@ -1246,13 +1264,6 @@ function taxonomy_nodeapi_delete_revisio } /** - * Implementation of hook_nodeapi_validate(). - */ -function taxonomy_nodeapi_validate($node, $arg = 0) { - taxonomy_node_validate($node); -} - -/** * Implementation of hook_nodeapi_rss_item(). */ function taxonomy_nodeapi_rss_item($node, $arg = 0) { Index: modules/taxonomy/taxonomy.test =================================================================== RCS file: /cvs/drupal/drupal/modules/taxonomy/taxonomy.test,v retrieving revision 1.15 diff -u -p -r1.15 taxonomy.test --- modules/taxonomy/taxonomy.test 22 Nov 2008 13:43:13 -0000 1.15 +++ modules/taxonomy/taxonomy.test 1 Dec 2008 21:20:39 -0000 @@ -252,6 +252,7 @@ class TaxonomyTermTestCase extends Taxon function setUp() { parent::setUp('taxonomy'); $this->admin_user = $this->drupalCreateUser(array('administer taxonomy', 'bypass node access')); + $this->normal_user = $this->drupalCreateUser(array('create article content')); $this->drupalLogin($this->admin_user); $this->vocabulary = $this->createVocabulary(); } @@ -380,6 +381,15 @@ class TaxonomyTermTestCase extends Taxon foreach ($terms as $term) { $this->assertText($term, t('The term was saved and appears on the node page')); } + + // Test attempted creation of tags by a user without sufficient permissions. + $this->drupalLogout(); + $this->drupalLogin($this->normal_user); + $extra_term = $this->randomName(); + $terms[] = $extra_term; + $edit['taxonomy[tags][' . $this->vocabulary->vid .']'] = implode(', ', $terms); + $this->drupalPost('node/add/article', $edit, t('Save')); + $this->assertRaw(t('The following terms were not saved beause you do not have permission to create new terms in this vocabulary: %terms.', array('%terms' => $extra_term))); } /**