diff --git a/core/modules/forum/src/Form/Overview.php b/core/modules/forum/src/Form/Overview.php index ba9c033..1bbbc34 100644 --- a/core/modules/forum/src/Form/Overview.php +++ b/core/modules/forum/src/Form/Overview.php @@ -60,19 +60,24 @@ public function buildForm(array $form, FormStateInterface $form_state) { if (isset($form['terms'][$key]['#term'])) { $term = $form['terms'][$key]['#term']; $form['terms'][$key]['term']['#url'] = Url::fromRoute('forum.page', ['taxonomy_term' => $term->id()]); - unset($form['terms'][$key]['operations']['#links']['delete']); - $route_parameters = $form['terms'][$key]['operations']['#links']['edit']['url']->getRouteParameters(); - if (!empty($term->forum_container->value)) { - $form['terms'][$key]['operations']['#links']['edit']['title'] = $this->t('edit container'); - $form['terms'][$key]['operations']['#links']['edit']['url'] = Url::fromRoute('entity.taxonomy_term.forum_edit_container_form', $route_parameters); + if ($form['terms'][$key]['#term']->access('delete')) { + unset($form['terms'][$key]['operations']['#links']['delete']); } - else { - $form['terms'][$key]['operations']['#links']['edit']['title'] = $this->t('edit forum'); - $form['terms'][$key]['operations']['#links']['edit']['url'] = Url::fromRoute('entity.taxonomy_term.forum_edit_form', $route_parameters); + + if($form['terms'][$key]['#term']->access('update')) { + $route_parameters = $form['terms'][$key]['operations']['#links']['edit']['url']->getRouteParameters(); + if (!empty($term->forum_container->value)) { + $form['terms'][$key]['operations']['#links']['edit']['title'] = $this->t('edit container'); + $form['terms'][$key]['operations']['#links']['edit']['url'] = Url::fromRoute('entity.taxonomy_term.forum_edit_container_form', $route_parameters); + } + else { + $form['terms'][$key]['operations']['#links']['edit']['title'] = $this->t('edit forum'); + $form['terms'][$key]['operations']['#links']['edit']['url'] = Url::fromRoute('entity.taxonomy_term.forum_edit_form', $route_parameters); + } + // We don't want the redirect from the link so we can redirect the + // delete action. + unset($form['terms'][$key]['operations']['#links']['edit']['query']['destination']); } - // We don't want the redirect from the link so we can redirect the - // delete action. - unset($form['terms'][$key]['operations']['#links']['edit']['query']['destination']); } } diff --git a/core/modules/node/src/Tests/NodeAccessBaseTableTest.php b/core/modules/node/src/Tests/NodeAccessBaseTableTest.php index 74e2340..c1ad579 100644 --- a/core/modules/node/src/Tests/NodeAccessBaseTableTest.php +++ b/core/modules/node/src/Tests/NodeAccessBaseTableTest.php @@ -94,7 +94,7 @@ function testNodeAccessBasic() { // Array of nids marked private. $private_nodes = []; for ($i = 0; $i < $num_simple_users; $i++) { - $simple_users[$i] = $this->drupalCreateUser(array('access content', 'create article content')); + $simple_users[$i] = $this->drupalCreateUser(['access content', 'create article content', 'create terms in tags']); } foreach ($simple_users as $this->webUser) { $this->drupalLogin($this->webUser); diff --git a/core/modules/taxonomy/src/Form/OverviewTerms.php b/core/modules/taxonomy/src/Form/OverviewTerms.php index 4c8cee3..bbc7c9e 100644 --- a/core/modules/taxonomy/src/Form/OverviewTerms.php +++ b/core/modules/taxonomy/src/Form/OverviewTerms.php @@ -22,6 +22,13 @@ class OverviewTerms extends FormBase { protected $moduleHandler; /** + * The entity manager. + * + * @var \Drupal\Core\Entity\EntityManagerInterface + */ + protected $entityManager; + + /** * The term storage handler. * * @var \Drupal\taxonomy\TermStorageInterface @@ -38,6 +45,7 @@ class OverviewTerms extends FormBase { */ public function __construct(ModuleHandlerInterface $module_handler, EntityManagerInterface $entity_manager) { $this->moduleHandler = $module_handler; + $this->entityManager = $entity_manager; $this->storageController = $entity_manager->getStorage('taxonomy_term'); } @@ -199,14 +207,22 @@ public function buildForm(array $form, FormStateInterface $form_state, Vocabular $destination = $this->getDestinationArray(); $row_position = 0; // Build the actual form. + $access_control_handler = $this->entityManager->getAccessControlHandler('taxonomy_term'); + if ($access_control_handler->createAccess($taxonomy_vocabulary->id())) { + $empty = $this->t('No terms available. Add term.', ['@link' => $this->url('entity.taxonomy_term.add_form', ['taxonomy_vocabulary' => $taxonomy_vocabulary->id()])]); + } + else { + $empty = $this->t('No terms available.'); + } $form['terms'] = array( '#type' => 'table', - '#header' => array($this->t('Name'), $this->t('Weight'), $this->t('Operations')), - '#empty' => $this->t('No terms available. Add term.', array(':link' => $this->url('entity.taxonomy_term.add_form', array('taxonomy_vocabulary' => $taxonomy_vocabulary->id())))), + '#empty' => $empty, '#attributes' => array( 'id' => 'taxonomy', ), ); + $change_weight_access = TRUE; + $operations_access = TRUE; foreach ($current_page as $key => $term) { /** @var $term \Drupal\Core\Entity\EntityInterface */ $form['terms'][$key]['#term'] = $term; @@ -251,28 +267,36 @@ public function buildForm(array $form, FormStateInterface $form_state, Vocabular ), ); } - $form['terms'][$key]['weight'] = array( - '#type' => 'weight', - '#delta' => $delta, - '#title' => $this->t('Weight for added term'), - '#title_display' => 'invisible', - '#default_value' => $term->getWeight(), - '#attributes' => array( - 'class' => array('term-weight'), - ), - ); - $operations = array( - 'edit' => array( + $edit_access = $term->access('update'); + $change_weight_access &= $edit_access; + + if ($edit_access) { + $form['terms'][$key]['weight'] = [ + '#type' => 'weight', + '#delta' => $delta, + '#title' => $this->t('Weight for added term'), + '#title_display' => 'invisible', + '#default_value' => $term->getWeight(), + '#attributes' => ['class' => ['term-weight']], + '#access' => $edit_access, + ]; + } + $operations = []; + + if ($edit_access) { + $operations['edit'] = [ 'title' => $this->t('Edit'), 'query' => $destination, 'url' => $term->urlInfo('edit-form'), - ), - 'delete' => array( + ]; + } + if ($term->access('delete')) { + $operations['delete'] = [ 'title' => $this->t('Delete'), 'query' => $destination, 'url' => $term->urlInfo('delete-form'), - ), - ); + ]; + } if ($this->moduleHandler->moduleExists('content_translation') && content_translation_translate_access($term)->isAllowed()) { $operations['translate'] = array( 'title' => $this->t('Translate'), @@ -280,10 +304,14 @@ public function buildForm(array $form, FormStateInterface $form_state, Vocabular 'url' => $term->urlInfo('drupal:content-translation-overview'), ); } - $form['terms'][$key]['operations'] = array( - '#type' => 'operations', - '#links' => $operations, - ); + + $operations_access &= count($operations) > 0; + if (count($operations)) { + $form['terms'][$key]['operations'] = [ + '#type' => 'operations', + '#links' => $operations, + ]; + } $form['terms'][$key]['#attributes']['class'] = array(); if ($parent_fields) { @@ -313,44 +341,54 @@ public function buildForm(array $form, FormStateInterface $form_state, Vocabular $row_position++; } - if ($parent_fields) { - $form['terms']['#tabledrag'][] = array( - 'action' => 'match', - 'relationship' => 'parent', - 'group' => 'term-parent', - 'subgroup' => 'term-parent', - 'source' => 'term-id', - 'hidden' => FALSE, - ); - $form['terms']['#tabledrag'][] = array( - 'action' => 'depth', - 'relationship' => 'group', - 'group' => 'term-depth', - 'hidden' => FALSE, - ); - $form['terms']['#attached']['library'][] = 'taxonomy/drupal.taxonomy'; - $form['terms']['#attached']['drupalSettings']['taxonomy'] = [ - 'backStep' => $back_step, - 'forwardStep' => $forward_step, + $form['terms']['#header'] = array($this->t('Name')); + if ($change_weight_access) { + $form['terms']['#header'][] = $this->t('Weight'); + if ($parent_fields) { + $form['terms']['#tabledrag'][] = [ + 'action' => 'match', + 'relationship' => 'parent', + 'group' => 'term-parent', + 'subgroup' => 'term-parent', + 'source' => 'term-id', + 'hidden' => FALSE, + ]; + $form['terms']['#tabledrag'][] = [ + 'action' => 'depth', + 'relationship' => 'group', + 'group' => 'term-depth', + 'hidden' => FALSE, + ]; + $form['terms']['#attached']['library'][] = 'taxonomy/drupal.taxonomy'; + $form['terms']['#attached']['drupalSettings']['taxonomy'] = [ + 'backStep' => $back_step, + 'forwardStep' => $forward_step, + ]; + } + $form['terms']['#tabledrag'][] = [ + 'action' => 'order', + 'relationship' => 'sibling', + 'group' => 'term-weight', ]; } - $form['terms']['#tabledrag'][] = array( - 'action' => 'order', - 'relationship' => 'sibling', - 'group' => 'term-weight', - ); - if ($taxonomy_vocabulary->getHierarchy() != VocabularyInterface::HIERARCHY_MULTIPLE && count($tree) > 1) { + if ($operations_access) { + $form['terms']['#header'][] = $this->t('Operations'); + } + + if (($taxonomy_vocabulary->getHierarchy() != VocabularyInterface::HIERARCHY_MULTIPLE && count($tree) > 1) && $change_weight_access) { $form['actions'] = array('#type' => 'actions', '#tree' => FALSE); $form['actions']['submit'] = array( '#type' => 'submit', '#value' => $this->t('Save'), '#button_type' => 'primary', + '#access' => $change_weight_access, ); $form['actions']['reset_alphabetical'] = array( '#type' => 'submit', '#submit' => array('::submitReset'), '#value' => $this->t('Reset to alphabetical'), + '#access' => $change_weight_access, ); } diff --git a/core/modules/taxonomy/src/TaxonomyPermissions.php b/core/modules/taxonomy/src/TaxonomyPermissions.php index 196c5a5..5ec9984 100644 --- a/core/modules/taxonomy/src/TaxonomyPermissions.php +++ b/core/modules/taxonomy/src/TaxonomyPermissions.php @@ -5,6 +5,7 @@ use Drupal\Core\DependencyInjection\ContainerInjectionInterface; use Drupal\Core\Entity\EntityManagerInterface; use Drupal\Core\StringTranslation\StringTranslationTrait; +use Drupal\taxonomy\Entity\Vocabulary; use Symfony\Component\DependencyInjection\ContainerInterface; /** @@ -48,19 +49,30 @@ public static function create(ContainerInterface $container) { */ public function permissions() { $permissions = []; - foreach ($this->entityManager->getStorage('taxonomy_vocabulary')->loadMultiple() as $vocabulary) { - $permissions += [ - 'edit terms in ' . $vocabulary->id() => [ - 'title' => $this->t('Edit terms in %vocabulary', ['%vocabulary' => $vocabulary->label()]), - ], - ]; - $permissions += [ - 'delete terms in ' . $vocabulary->id() => [ - 'title' => $this->t('Delete terms from %vocabulary', ['%vocabulary' => $vocabulary->label()]), - ], - ]; + foreach (Vocabulary::loadMultiple() as $vocabulary) { + $permissions += $this->buildPermissions($vocabulary); } return $permissions; } + /** + * Builds a standard list of taxonomy term permissions for a given vocabulary. + * + * @param \Drupal\taxonomy\Entity\Vocabulary + * The vocabulary. + * + * @return array + * An array of permission names and descriptions. + */ + protected function buildPermissions(Vocabulary $vocabulary) { + $id = $vocabulary->id(); + $args = ['%vocabulary' => $vocabulary->label()]; + + return [ + "create terms in $id" => ['title' => $this->t('%vocabulary: Create terms', $args)], + "delete terms in $id" => ['title' => $this->t('%vocabulary: Delete terms', $args)], + "edit terms in $id" => ['title' => $this->t('%vocabulary: Edit terms', $args)], + ]; + } + } diff --git a/core/modules/taxonomy/src/TermAccessControlHandler.php b/core/modules/taxonomy/src/TermAccessControlHandler.php index 04c2c4f..1d48463 100644 --- a/core/modules/taxonomy/src/TermAccessControlHandler.php +++ b/core/modules/taxonomy/src/TermAccessControlHandler.php @@ -38,7 +38,7 @@ protected function checkAccess(EntityInterface $entity, $operation, AccountInter * {@inheritdoc} */ protected function checkCreateAccess(AccountInterface $account, array $context, $entity_bundle = NULL) { - return AccessResult::allowedIfHasPermission($account, 'administer taxonomy'); + return AccessResult::allowedIfHasPermissions($account, ["create terms in $entity_bundle", 'administer taxonomy'], 'OR'); } } diff --git a/core/modules/taxonomy/src/VocabularyListBuilder.php b/core/modules/taxonomy/src/VocabularyListBuilder.php index 9c24311..2dbb955 100644 --- a/core/modules/taxonomy/src/VocabularyListBuilder.php +++ b/core/modules/taxonomy/src/VocabularyListBuilder.php @@ -4,8 +4,14 @@ use Drupal\Core\Config\Entity\DraggableListBuilder; use Drupal\Core\Entity\EntityInterface; +use Drupal\Core\Entity\EntityManagerInterface; +use Drupal\Core\Entity\EntityStorageInterface; +use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\Form\FormStateInterface; +use Drupal\Core\Session\AccountInterface; use Drupal\Core\Url; +use Drupal\taxonomy\Access\TaxonomyOverviewAccessCheck; +use Symfony\Component\DependencyInjection\ContainerInterface; /** * Defines a class to build a listing of taxonomy vocabulary entities. @@ -20,6 +26,55 @@ class VocabularyListBuilder extends DraggableListBuilder { protected $entitiesKey = 'vocabularies'; /** + * The current user. + * + * @var \Drupal\Core\Session\AccountInterface + */ + protected $currentUser; + + /** + * The entity manager. + * + * @var \Drupal\Core\Entity\EntityManagerInterface + */ + protected $entityManager; + + /** + * Constructs a new VocabularyListBuilder object. + * + * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type + * The entity type definition. + * @param \Drupal\Core\Entity\EntityStorageInterface $storage + * The entity storage class. + * @param \Drupal\Core\Session\AccountInterface $current_user + * The current user. + * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager + * The entity manager service. + * @param \Drupal\taxonomy\Access\TaxonomyOverviewAccessCheck $access_view + * The access check service. + */ + public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage, AccountInterface $current_user, EntityManagerInterface $entity_manager, TaxonomyOverviewAccessCheck $access_view) { + parent::__construct($entity_type, $storage); + + $this->current_user = $current_user; + $this->entityManager = $entity_manager; + $this->access_view = $access_view; + } + + /** + * {@inheritdoc} + */ + public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) { + return new static( + $entity_type, + $container->get('entity.manager')->getStorage($entity_type->id()), + $container->get('current_user'), + $container->get('entity.manager'), + $container->get('access_check.taxonomy.taxonomy_overview') + ); + } + + /** * {@inheritdoc} */ public function getFormId() { @@ -36,16 +91,22 @@ public function getDefaultOperations(EntityInterface $entity) { $operations['edit']['title'] = t('Edit vocabulary'); } - $operations['list'] = array( - 'title' => t('List terms'), - 'weight' => 0, - 'url' => $entity->urlInfo('overview-form'), - ); - $operations['add'] = array( - 'title' => t('Add terms'), - 'weight' => 10, - 'url' => Url::fromRoute('entity.taxonomy_term.add_form', ['taxonomy_vocabulary' => $entity->id()]), - ); + if($this->access_view->access($this->current_user)) { + $operations['list'] = array( + 'title' => t('List terms'), + 'weight' => 0, + 'url' => $entity->urlInfo('overview-form'), + ); + } + + $taxonomy_term_access_control_handler = $this->entityManager->getAccessControlHandler('taxonomy_term'); + if ($taxonomy_term_access_control_handler->createAccess($entity->id())) { + $operations['add'] = [ + 'title' => t('Add terms'), + 'weight' => 10, + 'url' => Url::fromRoute('entity.taxonomy_term.add_form', ['taxonomy_vocabulary' => $entity->id()]), + ]; + } unset($operations['delete']); return $operations; @@ -57,6 +118,11 @@ public function getDefaultOperations(EntityInterface $entity) { public function buildHeader() { $header['label'] = t('Vocabulary name'); $header['description'] = t('Description'); + + if ($this->current_user->hasPermission('administer vocabularies')) { + $header['weight'] = t('Weight'); + } + return $header + parent::buildHeader(); } @@ -80,7 +146,12 @@ public function render() { unset($this->weightKey); } $build = parent::render(); - $build['table']['#empty'] = t('No vocabularies available. Add vocabulary.', array(':link' => \Drupal::url('entity.taxonomy_vocabulary.add_form'))); + if ($this->current_user->hasPermission('administer vocabularies')) { + $build['table']['#empty'] = t('No vocabularies available. Add vocabulary.', ['@link' => \Drupal::url('entity.taxonomy_vocabulary.add_form')]); + } + else { + $build['table']['#empty'] = t('No vocabularies available.'); + } return $build; } diff --git a/core/modules/taxonomy/taxonomy.module b/core/modules/taxonomy/taxonomy.module index 8088432..d0915b4 100644 --- a/core/modules/taxonomy/taxonomy.module +++ b/core/modules/taxonomy/taxonomy.module @@ -75,6 +75,17 @@ function taxonomy_help($route_name, RouteMatchInterface $route_match) { case 'entity.taxonomy_vocabulary.overview_form': $vocabulary = $route_match->getParameter('taxonomy_vocabulary'); + if (!\Drupal::currentUser()->hasPermission('administer taxonomy')) { + // There is no drag-and-drop handles. + switch ($vocabulary->getHierarchy()) { + case TAXONOMY_HIERARCHY_DISABLED: + return '

' . t('%capital_name contains the following terms.', array('%capital_name' => Unicode::ucfirst($vocabulary->label()))) . '

'; + case TAXONOMY_HIERARCHY_SINGLE: + return '

' . t('%capital_name contains terms grouped under parent terms', array('%capital_name' => Unicode::ucfirst($vocabulary->label()))) . '

'; + case TAXONOMY_HIERARCHY_MULTIPLE: + return '

' . t('%capital_name contains terms with multiple parents.', array('%capital_name' => Unicode::ucfirst($vocabulary->label()))) . '

'; + } + } switch ($vocabulary->getHierarchy()) { case VocabularyInterface::HIERARCHY_DISABLED: return '

' . t('You can reorganize the terms in %capital_name using their drag-and-drop handles, and group terms under a parent term by sliding them under and to the right of the parent.', array('%capital_name' => Unicode::ucfirst($vocabulary->label()), '%name' => $vocabulary->label())) . '

'; diff --git a/core/modules/taxonomy/taxonomy.permissions.yml b/core/modules/taxonomy/taxonomy.permissions.yml index d485949..bb71e93 100644 --- a/core/modules/taxonomy/taxonomy.permissions.yml +++ b/core/modules/taxonomy/taxonomy.permissions.yml @@ -1,5 +1,9 @@ administer taxonomy: title: 'Administer vocabularies and terms' +access taxonomy overview: + title: 'Access the taxonomy vocabulary overview page' + description: 'Get an overview of all taxonomy vocabularies.' + permission_callbacks: - Drupal\taxonomy\TaxonomyPermissions::permissions diff --git a/core/modules/taxonomy/taxonomy.routing.yml b/core/modules/taxonomy/taxonomy.routing.yml index 8a3bd1a..e7e41e2 100644 --- a/core/modules/taxonomy/taxonomy.routing.yml +++ b/core/modules/taxonomy/taxonomy.routing.yml @@ -4,7 +4,7 @@ entity.taxonomy_vocabulary.collection: _entity_list: 'taxonomy_vocabulary' _title: 'Taxonomy' requirements: - _permission: 'administer taxonomy' + _permission: 'administer taxonomy+access taxonomy overview' entity.taxonomy_term.add_form: path: '/admin/structure/taxonomy/manage/{taxonomy_vocabulary}/add' @@ -74,7 +74,7 @@ entity.taxonomy_vocabulary.overview_form: _form: 'Drupal\taxonomy\Form\OverviewTerms' _title_callback: 'Drupal\taxonomy\Controller\TaxonomyController::vocabularyTitle' requirements: - _entity_access: 'taxonomy_vocabulary.view' + _permission: 'administer taxonomy+access taxonomy overview' entity.taxonomy_term.canonical: path: '/taxonomy/term/{taxonomy_term}' diff --git a/core/modules/taxonomy/taxonomy.services.yml b/core/modules/taxonomy/taxonomy.services.yml index a8153ed..b521c7f 100644 --- a/core/modules/taxonomy/taxonomy.services.yml +++ b/core/modules/taxonomy/taxonomy.services.yml @@ -4,3 +4,7 @@ services: arguments: ['@entity.manager'] tags: - { name: breadcrumb_builder, priority: 1002 } + access_check.taxonomy.taxonomy_overview: + class: Drupal\taxonomy\Access\TaxonomyOverviewAccessCheck + tags: + - { name: access_check, applies_to: _access_taxonomy_overview } diff --git a/core/modules/taxonomy/tests/src/Functional/VocabularyPermissionsTest.php b/core/modules/taxonomy/tests/src/Functional/VocabularyPermissionsTest.php index 1b83d84..e3f2d3a 100644 --- a/core/modules/taxonomy/tests/src/Functional/VocabularyPermissionsTest.php +++ b/core/modules/taxonomy/tests/src/Functional/VocabularyPermissionsTest.php @@ -16,6 +16,34 @@ protected function setUp() { } /** + * Create, edit and delete a vocabulary via the user interface. + */ + function testVocabularyPermissionsVocabulary() { + // VocabularyTest.php already tests for user with "administer taxonomy" + // permission. + + // Test as user without proper permissions. + $authenticated_user = $this->drupalCreateUser([]); + $this->drupalLogin($authenticated_user); + + // Visit the main taxonomy administration page. + $this->drupalGet('admin/structure/taxonomy'); + $this->assertResponse(403, 'Vocabulary overview open failed.'); + + // Test as user with "access taxonomy overview" permissions. + $proper_user = $this->drupalCreateUser(['access taxonomy overview']); + $this->drupalLogin($proper_user); + + // Visit the main taxonomy administration page. + $this->drupalGet('admin/structure/taxonomy'); + $this->assertResponse(200); + $this->assertText(t('Vocabulary name'), 'Vocabulary overview opened successfully.'); + + // Create a new vocabulary. + $this->assertNoLink(t('Add vocabulary')); + } + + /** * Create, edit and delete a taxonomy term via the user interface. */ function testVocabularyPermissionsTaxonomyTerm() { @@ -62,8 +90,35 @@ function testVocabularyPermissionsTaxonomyTerm() { $this->drupalPostForm(NULL, NULL, t('Delete')); $this->assertRaw(t('Deleted term %name.', array('%name' => $edit['name[0][value]'])), 'Term deleted.'); + // Test as user with "create" permissions. + $user = $this->drupalCreateUser(["access taxonomy overview", "create terms in {$vocabulary->id()}"]); + $this->drupalLogin($user); + + // Visit the main taxonomy administration page. + $this->drupalGet('admin/structure/taxonomy/manage/' . $vocabulary->id() . '/add'); + $this->assertResponse(200); + $this->assertFieldByName('name[0][value]', NULL, 'Add taxonomy term form opened successfully.'); + + // Submit the term. + $edit = array(); + $edit['name[0][value]'] = $this->randomMachineName(); + + $this->drupalPostForm(NULL, $edit, t('Save')); + $this->assertRaw(t('Created new term %name.', ['%name' => $edit['name[0][value]']]), 'Term created successfully.'); + + $terms = taxonomy_term_load_multiple_by_name($edit['name[0][value]']); + $term = reset($terms); + + // Edit the term. + $this->drupalGet('taxonomy/term/' . $term->id() . '/edit'); + $this->assertResponse(403, 'Edit taxonomy term form open failed.'); + + // Delete the vocabulary. + $this->drupalGet('taxonomy/term/' . $term->id() . '/delete'); + $this->assertResponse(403, 'Delete taxonomy term form open failed.'); + // Test as user with "edit" permissions. - $user = $this->drupalCreateUser(array("edit terms in {$vocabulary->id()}")); + $user = $this->drupalCreateUser(["access taxonomy overview", "edit terms in {$vocabulary->id()}"]); $this->drupalLogin($user); // Visit the main taxonomy administration page. @@ -91,7 +146,7 @@ function testVocabularyPermissionsTaxonomyTerm() { $this->assertResponse(403, 'Delete taxonomy term form open failed.'); // Test as user with "delete" permissions. - $user = $this->drupalCreateUser(array("delete terms in {$vocabulary->id()}")); + $user = $this->drupalCreateUser(["access taxonomy overview", "delete terms in {$vocabulary->id()}"]); $this->drupalLogin($user); // Visit the main taxonomy administration page.