diff --git a/core/includes/entity.inc b/core/includes/entity.inc
index a686ec6..d81d49c 100644
--- a/core/includes/entity.inc
+++ b/core/includes/entity.inc
@@ -742,3 +742,22 @@ function entity_query($entity_type, $conjunction = 'AND') {
function entity_page_access(EntityInterface $entity, $operation = 'view') {
return $entity->access($operation);
}
+
+/**
+ * Generic access callback for create entity pages.
+ *
+ * Some entity types might have create access per bundle or something else.
+ * In that case you have to create a custom access callback.
+ *
+ * @param string $entity_type
+ * The entity type.
+ *
+ * @return bool
+ * TRUE if the access is granted. FALSE if access is denied.
+ */
+function entity_page_create_access($entity_type) {
+ $entity = drupal_container()->get('plugin.manager.entity')
+ ->getStorageController($entity_type)
+ ->create(array());
+ return $entity->access('create');
+}
diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/Core/Entity/Term.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/Core/Entity/Term.php
index d1a9314..132fc2c 100644
--- a/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/Core/Entity/Term.php
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/Core/Entity/Term.php
@@ -22,6 +22,7 @@
* module = "taxonomy",
* controller_class = "Drupal\taxonomy\TermStorageController",
* render_controller_class = "Drupal\taxonomy\TermRenderController",
+ * access_controller_class = "Drupal\taxonomy\TermAccessController",
* form_controller_class = {
* "default" = "Drupal\taxonomy\TermFormController"
* },
diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/Core/Entity/Vocabulary.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/Core/Entity/Vocabulary.php
index ec2607c..79fa073 100644
--- a/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/Core/Entity/Vocabulary.php
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/Core/Entity/Vocabulary.php
@@ -19,6 +19,7 @@
* label = @Translation("Taxonomy vocabulary"),
* module = "taxonomy",
* controller_class = "Drupal\taxonomy\VocabularyStorageController",
+ * access_controller_class = "Drupal\taxonomy\VocabularyAccessController",
* form_controller_class = {
* "default" = "Drupal\taxonomy\VocabularyFormController"
* },
diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/views/field/LinkEdit.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/views/field/LinkEdit.php
index 1d990d1..346e0b4 100644
--- a/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/views/field/LinkEdit.php
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/views/field/LinkEdit.php
@@ -65,7 +65,7 @@ function render($values) {
$term = entity_create('taxonomy_term', array(
'vid' => $values->{$this->aliases['vid']},
));
- if (taxonomy_term_access('edit', $term)) {
+ if ($term->access('update')) {
$text = !empty($this->options['text']) ? $this->options['text'] : t('edit');
return l($text, 'taxonomy/term/'. $tid . '/edit', array('query' => drupal_get_destination()));
}
diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/TermAccessController.php b/core/modules/taxonomy/lib/Drupal/taxonomy/TermAccessController.php
new file mode 100644
index 0000000..c45aa02
--- /dev/null
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/TermAccessController.php
@@ -0,0 +1,49 @@
+bundle()}", $account) || user_access('administer taxonomy', $account);
+ }
+
+ /**
+ * Implements \Drupal\Core\Entity\EntityAccessControllerInterface::deleteAccess().
+ */
+ public function deleteAccess(EntityInterface $entity, $langcode = LANGUAGE_DEFAULT, User $account = NULL) {
+ return user_access("delete terms in {$entity->bundle()}", $account) || user_access('administer taxonomy', $account);
+ }
+
+}
diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/TermTranslationController.php b/core/modules/taxonomy/lib/Drupal/taxonomy/TermTranslationController.php
index 59226fd..ab36a79 100644
--- a/core/modules/taxonomy/lib/Drupal/taxonomy/TermTranslationController.php
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/TermTranslationController.php
@@ -16,20 +16,6 @@
class TermTranslationController extends EntityTranslationController {
/**
- * Overrides EntityTranslationController::getAccess().
- */
- public function getAccess(EntityInterface $entity, $op) {
- switch ($op) {
- case 'create':
- case 'update':
- return taxonomy_term_access('edit', $entity);
- case 'delete':
- return taxonomy_term_access('delete', $entity);
- }
- return parent::getAccess($entity, $op);
- }
-
- /**
* Overrides EntityTranslationController::entityFormAlter().
*/
public function entityFormAlter(array &$form, array &$form_state, EntityInterface $entity) {
@@ -53,4 +39,5 @@ function entityFormSave(array $form, array &$form_state) {
$form_state['redirect'] = $this->getEditPath($entity);
}
}
+
}
diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyAccessController.php b/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyAccessController.php
new file mode 100644
index 0000000..b1ec119
--- /dev/null
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyAccessController.php
@@ -0,0 +1,49 @@
+id()]['#vocabulary'] = $vocabulary;
$form[$vocabulary->id()]['name'] = array('#markup' => check_plain($vocabulary->name));
- $form[$vocabulary->id()]['weight'] = array(
- '#type' => 'weight',
- '#title' => t('Weight for @title', array('@title' => $vocabulary->name)),
- '#title_display' => 'invisible',
- '#delta' => 10,
- '#default_value' => $vocabulary->weight,
- );
+ if ($admin_access) {
+ $form[$vocabulary->id()]['weight'] = array(
+ '#type' => 'weight',
+ '#title' => t('Weight for @title', array('@title' => $vocabulary->name)),
+ '#title_display' => 'invisible',
+ '#delta' => 10,
+ '#default_value' => $vocabulary->weight,
+ '#access' => $vocabulary->access('update'),
+ );
+ }
$links = array();
- $links['edit'] = array(
- 'title' => t('edit vocabulary'),
- 'href' => "admin/structure/taxonomy/{$vocabulary->id()}/edit",
- );
+ if ($vocabulary->access('update')) {
+ $links['edit'] = array(
+ 'title' => t('edit vocabulary'),
+ 'href' => "admin/structure/taxonomy/{$vocabulary->id()}/edit",
+ );
+ }
$links['list'] = array(
'title' => t('list terms'),
'href' => "admin/structure/taxonomy/{$vocabulary->id()}",
);
- $links['add'] = array(
- 'title' => t('add terms'),
- 'href' => "admin/structure/taxonomy/{$vocabulary->id()}/add",
- );
+ if ($vocabulary->access('create')) {
+ $links['add'] = array(
+ 'title' => t('add terms'),
+ 'href' => "admin/structure/taxonomy/{$vocabulary->id()}/add",
+ );
+ }
$form[$vocabulary->id()]['operations'] = array(
'#type' => 'operations',
'#links' => $links,
@@ -50,11 +58,15 @@ function taxonomy_overview_vocabularies($form) {
// Only make this form include a submit button and weight if more than one
// vocabulary exists.
- if (count($vocabularies) > 1) {
+ if (count($vocabularies) > 1 && $admin_access) {
$form['actions'] = array('#type' => 'actions');
- $form['actions']['submit'] = array('#type' => 'submit', '#value' => t('Save'), '#button_type' => 'primary');
+ $form['actions']['submit'] = array(
+ '#type' => 'submit',
+ '#value' => t('Save'),
+ '#button_type' => 'primary',
+ );
}
- elseif (isset($vocabulary)) {
+ elseif (isset($vocabulary) && $admin_access) {
unset($form[$vocabulary->id()]['weight']);
}
return $form;
@@ -87,7 +99,7 @@ function taxonomy_overview_vocabularies_submit($form, &$form_state) {
*/
function theme_taxonomy_overview_vocabularies($variables) {
$form = $variables['form'];
-
+ $draggable = FALSE;
$rows = array();
foreach (element_children($form) as $key) {
@@ -111,7 +123,12 @@ function theme_taxonomy_overview_vocabularies($variables) {
drupal_add_tabledrag('taxonomy', 'order', 'sibling', 'vocabulary-weight');
}
$header[] = t('Operations');
- return theme('table', array('header' => $header, 'rows' => $rows, 'empty' => t('No vocabularies available. Add vocabulary.', array('@link' => url('admin/structure/taxonomy/add'))), 'attributes' => array('id' => 'taxonomy'))) . drupal_render_children($form);
+ $empty_text = t('No vocabularies available.');
+ // Create a vocabulary object to check create access.
+ if (entity_create('taxonomy_vocabulary', array())->access('create')) {
+ $empty_text .= ' ' . l(t('Add vocabulary'), 'admin/structure/taxonomy/add');
+ }
+ return theme('table', array('header' => $header, 'rows' => $rows, 'empty' => $empty_text, 'attributes' => array('id' => 'taxonomy'))) . drupal_render_children($form);
}
/**
@@ -151,6 +168,7 @@ function taxonomy_overview_terms($form, &$form_state, Vocabulary $vocabulary) {
$form['#tree'] = TRUE;
$form['#parent_fields'] = FALSE;
+ $admin_access = user_access('administer taxonomy');
$page = isset($_GET['page']) ? $_GET['page'] : 0;
$page_increment = config('taxonomy.settings')->get('terms_per_page_admin'); // Number of terms per page.
$page_entries = 0; // Elements shown on this page.
@@ -261,7 +279,7 @@ function taxonomy_overview_terms($form, &$form_state, Vocabulary $vocabulary) {
}
$form[$key]['view'] = array('#type' => 'link', '#title' => $term->label(), '#href' => "taxonomy/term/$term->tid");
- if ($vocabulary->hierarchy != TAXONOMY_HIERARCHY_MULTIPLE && count($tree) > 1) {
+ if ($vocabulary->hierarchy != TAXONOMY_HIERARCHY_MULTIPLE && count($tree) > 1 && $admin_access) {
$form['#parent_fields'] = TRUE;
$form[$key]['tid'] = array(
'#type' => 'hidden',
@@ -285,10 +303,14 @@ function taxonomy_overview_terms($form, &$form_state, Vocabulary $vocabulary) {
'#default_value' => $term->weight,
);
}
- $operations = array(
- 'edit' => array('title' => t('edit'), 'href' => 'taxonomy/term/' . $term->tid . '/edit', 'query' => $destination),
- 'delete' => array('title' => t('delete'), 'href' => 'taxonomy/term/' . $term->tid . '/delete', 'query' => $destination),
- );
+ $operations = array();
+ if ($term->access('update')) {
+ $operations['edit'] = array('title' => t('edit'), 'href' => 'taxonomy/term/' . $term->tid . '/edit', 'query' => $destination);
+ }
+ if ($term->access('delete')) {
+ $operations['delete'] = array('title' => t('delete'), 'href' => 'taxonomy/term/' . $term->tid . '/delete', 'query' => $destination);
+ }
+
if (module_invoke('translation_entity', 'translate_access', $term)) {
$operations['translate'] = array(
'title' => t('translate'),
@@ -307,9 +329,14 @@ function taxonomy_overview_terms($form, &$form_state, Vocabulary $vocabulary) {
$form['#page_entries'] = $page_entries;
$form['#back_step'] = $back_step;
$form['#forward_step'] = $forward_step;
- $form['#empty_text'] = t('No terms available. Add term.', array('@link' => url('admin/structure/taxonomy/' . $vocabulary->id() . '/add')));
+ $form['#empty_text'] = t('No terms available.');
+ // Create a test term object that belongs to this vocabulary
+ // to check create access against.
+ if (entity_create('taxonomy_term', array('vid' => $vocabulary->id()))->access('create')) {
+ $form['#empty_text'] .= ' ' . l(t('Add term'), 'admin/structure/taxonomy/' . $vocabulary->id() . '/add');
+ }
- if ($vocabulary->hierarchy != TAXONOMY_HIERARCHY_MULTIPLE && count($tree) > 1) {
+ if ($vocabulary->hierarchy != TAXONOMY_HIERARCHY_MULTIPLE && count($tree) > 1 && $admin_access) {
$form['actions'] = array('#type' => 'actions', '#tree' => FALSE);
$form['actions']['submit'] = array(
'#type' => 'submit',
@@ -457,19 +484,22 @@ function taxonomy_overview_terms_submit($form, &$form_state) {
function theme_taxonomy_overview_terms($variables) {
$form = $variables['form'];
+ $admin_access = user_access('administer taxonomy');
$page_increment = $form['#page_increment'];
$page_entries = $form['#page_entries'];
$back_step = $form['#back_step'];
$forward_step = $form['#forward_step'];
- // Add drag and drop if parent fields are present in the form.
- if ($form['#parent_fields']) {
- drupal_add_tabledrag('taxonomy', 'match', 'parent', 'term-parent', 'term-parent', 'term-id', FALSE);
- drupal_add_tabledrag('taxonomy', 'depth', 'group', 'term-depth', NULL, NULL, FALSE);
- drupal_add_library('taxonomy', 'drupal.taxonomy');
- drupal_add_js(array('taxonomy' => array('backStep' => $back_step, 'forwardStep' => $forward_step)), 'setting');
+ if ($admin_access) {
+ // Add drag and drop if parent fields are present in the form.
+ if ($form['#parent_fields']) {
+ drupal_add_tabledrag('taxonomy', 'match', 'parent', 'term-parent', 'term-parent', 'term-id', FALSE);
+ drupal_add_tabledrag('taxonomy', 'depth', 'group', 'term-depth', NULL, NULL, FALSE);
+ drupal_add_library('taxonomy', 'drupal.taxonomy');
+ drupal_add_js(array('taxonomy' => array('backStep' => $back_step, 'forwardStep' => $forward_step)), 'setting');
+ }
+ drupal_add_tabledrag('taxonomy', 'order', 'sibling', 'term-weight');
}
- drupal_add_tabledrag('taxonomy', 'order', 'sibling', 'term-weight');
$errors = form_get_errors() != FALSE ? form_get_errors() : array();
$rows = array();
diff --git a/core/modules/taxonomy/taxonomy.module b/core/modules/taxonomy/taxonomy.module
index 16d1019..648527a 100644
--- a/core/modules/taxonomy/taxonomy.module
+++ b/core/modules/taxonomy/taxonomy.module
@@ -89,9 +89,20 @@ function taxonomy_permission() {
'administer taxonomy' => array(
'title' => t('Administer vocabularies and terms'),
),
+ 'access taxonomy overview' => array(
+ 'title' => t('Access the taxonomy overview page'),
+ 'description' => t('Access the taxonomy overview page at admin/structure/taxonomy.', array(
+ '@url' => url('admin/structure/taxonomy'),
+ )),
+ ),
);
foreach (taxonomy_vocabulary_load_multiple() as $vocabulary) {
$permissions += array(
+ 'create terms in ' . $vocabulary->id() => array(
+ 'title' => t('Add terms in %vocabulary', array('%vocabulary' => $vocabulary->name)),
+ ),
+ );
+ $permissions += array(
'edit terms in ' . $vocabulary->id() => array(
'title' => t('Edit terms in %vocabulary', array('%vocabulary' => $vocabulary->name)),
),
@@ -260,7 +271,7 @@ function taxonomy_menu() {
'description' => 'Manage tagging, categorization, and classification of your content.',
'page callback' => 'drupal_get_form',
'page arguments' => array('taxonomy_overview_vocabularies'),
- 'access arguments' => array('administer taxonomy'),
+ 'access arguments' => array('access taxonomy overview'),
'file' => 'taxonomy.admin.inc',
);
$items['admin/structure/taxonomy/list'] = array(
@@ -271,7 +282,8 @@ function taxonomy_menu() {
$items['admin/structure/taxonomy/add'] = array(
'title' => 'Add vocabulary',
'page callback' => 'taxonomy_vocabulary_add',
- 'access arguments' => array('administer taxonomy'),
+ 'access callback' => 'entity_page_create_access',
+ 'access arguments' => array('taxonomy_vocabulary'),
'type' => MENU_LOCAL_ACTION,
'file' => 'taxonomy.admin.inc',
);
@@ -282,7 +294,8 @@ function taxonomy_menu() {
'title arguments' => array(2),
'page callback' => 'taxonomy_term_page',
'page arguments' => array(2),
- 'access arguments' => array('access content'),
+ 'access callback' => 'entity_page_access',
+ 'access arguments' => array(2, 'view'),
'file' => 'taxonomy.pages.inc',
);
$items['taxonomy/term/%taxonomy_term/view'] = array(
@@ -295,8 +308,8 @@ function taxonomy_menu() {
// Pass a NULL argument to ensure that additional path components are not
// passed to taxonomy_term_form() as the vocabulary machine name argument.
'page arguments' => array(2),
- 'access callback' => 'taxonomy_term_access',
- 'access arguments' => array('edit', 2),
+ 'access callback' => 'entity_page_access',
+ 'access arguments' => array(2, 'update'),
'type' => MENU_LOCAL_TASK,
'weight' => 10,
'file' => 'taxonomy.admin.inc',
@@ -305,8 +318,8 @@ function taxonomy_menu() {
'title' => 'Delete',
'page callback' => 'drupal_get_form',
'page arguments' => array('taxonomy_term_confirm_delete', 2),
- 'access callback' => 'taxonomy_term_access',
- 'access arguments' => array('delete', 2),
+ 'access callback' => 'entity_page_access',
+ 'access arguments' => array(2, 'delete'),
'type' => MENU_LOCAL_TASK,
'weight' => 11,
'file' => 'taxonomy.admin.inc',
@@ -317,7 +330,8 @@ function taxonomy_menu() {
'title arguments' => array(2),
'page callback' => 'taxonomy_term_feed',
'page arguments' => array(2),
- 'access arguments' => array('access content'),
+ 'access callback' => 'entity_page_access',
+ 'access arguments' => array(2, 'view'),
'type' => MENU_CALLBACK,
'file' => 'taxonomy.pages.inc',
);
@@ -335,7 +349,7 @@ function taxonomy_menu() {
'title arguments' => array(3),
'page callback' => 'drupal_get_form',
'page arguments' => array('taxonomy_overview_terms', 3),
- 'access arguments' => array('administer taxonomy'),
+ 'access arguments' => array('access taxonomy overview'),
'file' => 'taxonomy.admin.inc',
);
$items['admin/structure/taxonomy/%taxonomy_vocabulary/list'] = array(
@@ -347,7 +361,8 @@ function taxonomy_menu() {
'title' => 'Edit',
'page callback' => 'entity_get_form',
'page arguments' => array(3),
- 'access arguments' => array('administer taxonomy'),
+ 'access callback' => 'entity_page_access',
+ 'access arguments' => array(3, 'update'),
'type' => MENU_LOCAL_TASK,
'weight' => -10,
'file' => 'taxonomy.admin.inc',
@@ -357,7 +372,8 @@ function taxonomy_menu() {
'title' => 'Add term',
'page callback' => 'taxonomy_term_add',
'page arguments' => array(3),
- 'access arguments' => array('administer taxonomy'),
+ 'access callback' => 'entity_page_create_access',
+ 'access arguments' => array('taxonomy_term'),
'type' => MENU_LOCAL_ACTION,
'file' => 'taxonomy.admin.inc',
);
@@ -379,32 +395,6 @@ function taxonomy_admin_paths() {
}
/**
- * Access callback: Checks a user's permission for performing a taxonomy term
- * operation.
- *
- * @param $op
- * The operation to be performed on the taxonomy term. Possible values are:
- * - "edit"
- * - "delete"
- * @param $term
- * The $term object on which the operation is to be performed.
- *
- * @return
- * TRUE if the operation may be performed, FALSE otherwise.
- *
- * @see taxonomy_menu()
- */
-function taxonomy_term_access($op, $term) {
- if (!$term || !in_array($op, array('edit', 'delete'), TRUE)) {
- // If there was no term to check against, or the $op was not one of the
- // supported ones, we return access denied.
- return FALSE;
- }
-
- return user_access("$op terms in {$term->bundle()}") || user_access('administer taxonomy');
-}
-
-/**
* Saves a vocabulary.
*
* @param Drupal\taxonomy\Plugin\Core\Entity\Vocabulary $vocabulary