Commit 3529e208 authored by catch's avatar catch

Issue #1848686 by Johnny vd Laar, Berdir, JeroenT, geertvd, mogtofu33,...

Issue #1848686 by Johnny vd Laar, Berdir, JeroenT, geertvd, mogtofu33, hauruck, Manuel Garcia, pfrenssen, Bambell, realityloop, ParisLiakos, webflo, cyborg_572, Algeron, zniki.ru, xjm, Wim Leers, dawehner, yoroy: Add a dedicated permission to access the term overview page (without 'administer taxonomy' permission)
parent 5f9fe909
...@@ -58,21 +58,30 @@ public function buildForm(array $form, FormStateInterface $form_state) { ...@@ -58,21 +58,30 @@ public function buildForm(array $form, FormStateInterface $form_state) {
foreach (Element::children($form['terms']) as $key) { foreach (Element::children($form['terms']) as $key) {
if (isset($form['terms'][$key]['#term'])) { if (isset($form['terms'][$key]['#term'])) {
/** @var \Drupal\taxonomy\TermInterface $term */
$term = $form['terms'][$key]['#term']; $term = $form['terms'][$key]['#term'];
$form['terms'][$key]['term']['#url'] = Url::fromRoute('forum.page', ['taxonomy_term' => $term->id()]); $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)) { if (!empty($term->forum_container->value)) {
$form['terms'][$key]['operations']['#links']['edit']['title'] = $this->t('edit container'); $title = $this->t('edit container');
$form['terms'][$key]['operations']['#links']['edit']['url'] = Url::fromRoute('entity.taxonomy_term.forum_edit_container_form', $route_parameters); $url = Url::fromRoute('entity.taxonomy_term.forum_edit_container_form', ['taxonomy_term' => $term->id()]);
} }
else { else {
$form['terms'][$key]['operations']['#links']['edit']['title'] = $this->t('edit forum'); $title = $this->t('edit forum');
$form['terms'][$key]['operations']['#links']['edit']['url'] = Url::fromRoute('entity.taxonomy_term.forum_edit_form', $route_parameters); $url = Url::fromRoute('entity.taxonomy_term.forum_edit_form', ['taxonomy_term' => $term->id()]);
} }
// We don't want the redirect from the link so we can redirect the
// delete action. // Re-create the operations column and add only the edit link.
unset($form['terms'][$key]['operations']['#links']['edit']['query']['destination']); $form['terms'][$key]['operations'] = [
'#type' => 'operations',
'#links' => [
'edit' => [
'title' => $title,
'url' => $url,
],
],
];
} }
} }
......
...@@ -57,6 +57,8 @@ public function testForumIndexStatus() { ...@@ -57,6 +57,8 @@ public function testForumIndexStatus() {
'parent[0]' => $tid, 'parent[0]' => $tid,
]; ];
$this->drupalPostForm('admin/structure/forum/add/forum', $edit, t('Save')); $this->drupalPostForm('admin/structure/forum/add/forum', $edit, t('Save'));
$this->assertSession()->linkExists(t('edit forum'));
$tid_child = $tid + 1; $tid_child = $tid + 1;
// Verify that the node appears on the index. // Verify that the node appears on the index.
......
...@@ -41,16 +41,23 @@ protected function setUpAuthorization($method) { ...@@ -41,16 +41,23 @@ protected function setUpAuthorization($method) {
case 'GET': case 'GET':
$this->grantPermissionsToTestedRole(['access content']); $this->grantPermissionsToTestedRole(['access content']);
break; break;
case 'POST': case 'POST':
$this->grantPermissionsToTestedRole(['create terms in camelids']);
break;
case 'PATCH': case 'PATCH':
case 'DELETE':
// Grant the 'create url aliases' permission to test the case when // Grant the 'create url aliases' permission to test the case when
// the path field is accessible, see // the path field is accessible, see
// \Drupal\Tests\rest\Functional\EntityResource\Node\NodeResourceTestBase // \Drupal\Tests\rest\Functional\EntityResource\Node\NodeResourceTestBase
// for a negative test. // for a negative test.
// @todo Update once https://www.drupal.org/node/2824408 lands. $this->grantPermissionsToTestedRole(['edit terms in camelids', 'create url aliases']);
$this->grantPermissionsToTestedRole(['administer taxonomy', 'create url aliases']);
break; break;
case 'DELETE':
$this->grantPermissionsToTestedRole(['delete terms in camelids']);
break;
} }
} }
...@@ -168,7 +175,7 @@ protected function getExpectedUnauthorizedAccessMessage($method) { ...@@ -168,7 +175,7 @@ protected function getExpectedUnauthorizedAccessMessage($method) {
case 'GET': case 'GET':
return "The 'access content' permission is required."; return "The 'access content' permission is required.";
case 'POST': case 'POST':
return "The 'administer taxonomy' permission is required."; return "The following permissions are required: 'create terms in camelids' OR 'administer taxonomy'.";
case 'PATCH': case 'PATCH':
return "The following permissions are required: 'edit terms in camelids' OR 'administer taxonomy'."; return "The following permissions are required: 'edit terms in camelids' OR 'administer taxonomy'.";
case 'DELETE': case 'DELETE':
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
* "storage" = "Drupal\taxonomy\TermStorage", * "storage" = "Drupal\taxonomy\TermStorage",
* "storage_schema" = "Drupal\taxonomy\TermStorageSchema", * "storage_schema" = "Drupal\taxonomy\TermStorageSchema",
* "view_builder" = "Drupal\taxonomy\TermViewBuilder", * "view_builder" = "Drupal\taxonomy\TermViewBuilder",
* "list_builder" = "Drupal\Core\Entity\EntityListBuilder",
* "access" = "Drupal\taxonomy\TermAccessControlHandler", * "access" = "Drupal\taxonomy\TermAccessControlHandler",
* "views_data" = "Drupal\taxonomy\TermViewsData", * "views_data" = "Drupal\taxonomy\TermViewsData",
* "form" = { * "form" = {
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
* handlers = { * handlers = {
* "storage" = "Drupal\taxonomy\VocabularyStorage", * "storage" = "Drupal\taxonomy\VocabularyStorage",
* "list_builder" = "Drupal\taxonomy\VocabularyListBuilder", * "list_builder" = "Drupal\taxonomy\VocabularyListBuilder",
* "access" = "Drupal\taxonomy\VocabularyAccessControlHandler",
* "form" = { * "form" = {
* "default" = "Drupal\taxonomy\VocabularyForm", * "default" = "Drupal\taxonomy\VocabularyForm",
* "reset" = "Drupal\taxonomy\Form\VocabularyResetForm", * "reset" = "Drupal\taxonomy\Form\VocabularyResetForm",
......
...@@ -2,10 +2,13 @@ ...@@ -2,10 +2,13 @@
namespace Drupal\taxonomy\Form; namespace Drupal\taxonomy\Form;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Entity\EntityManagerInterface; use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\Core\Form\FormBase; use Drupal\Core\Form\FormBase;
use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\RendererInterface;
use Drupal\Core\Url;
use Drupal\taxonomy\VocabularyInterface; use Drupal\taxonomy\VocabularyInterface;
use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\ContainerInterface;
...@@ -35,6 +38,20 @@ class OverviewTerms extends FormBase { ...@@ -35,6 +38,20 @@ class OverviewTerms extends FormBase {
*/ */
protected $storageController; protected $storageController;
/**
* The term list builder.
*
* @var \Drupal\Core\Entity\EntityListBuilderInterface
*/
protected $termListBuilder;
/**
* The renderer service.
*
* @var \Drupal\Core\Render\RendererInterface
*/
protected $renderer;
/** /**
* Constructs an OverviewTerms object. * Constructs an OverviewTerms object.
* *
...@@ -42,11 +59,15 @@ class OverviewTerms extends FormBase { ...@@ -42,11 +59,15 @@ class OverviewTerms extends FormBase {
* The module handler service. * The module handler service.
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
* The entity manager service. * The entity manager service.
* @param \Drupal\Core\Render\RendererInterface $renderer
* The renderer service.
*/ */
public function __construct(ModuleHandlerInterface $module_handler, EntityManagerInterface $entity_manager) { public function __construct(ModuleHandlerInterface $module_handler, EntityManagerInterface $entity_manager, RendererInterface $renderer = NULL) {
$this->moduleHandler = $module_handler; $this->moduleHandler = $module_handler;
$this->entityManager = $entity_manager; $this->entityManager = $entity_manager;
$this->storageController = $entity_manager->getStorage('taxonomy_term'); $this->storageController = $entity_manager->getStorage('taxonomy_term');
$this->termListBuilder = $entity_manager->getListBuilder('taxonomy_term');
$this->renderer = $renderer ?: \Drupal::service('renderer');
} }
/** /**
...@@ -55,7 +76,8 @@ public function __construct(ModuleHandlerInterface $module_handler, EntityManage ...@@ -55,7 +76,8 @@ public function __construct(ModuleHandlerInterface $module_handler, EntityManage
public static function create(ContainerInterface $container) { public static function create(ContainerInterface $container) {
return new static( return new static(
$container->get('module_handler'), $container->get('module_handler'),
$container->get('entity.manager') $container->get('entity.manager'),
$container->get('renderer')
); );
} }
...@@ -204,17 +226,28 @@ public function buildForm(array $form, FormStateInterface $form_state, Vocabular ...@@ -204,17 +226,28 @@ public function buildForm(array $form, FormStateInterface $form_state, Vocabular
} }
$errors = $form_state->getErrors(); $errors = $form_state->getErrors();
$destination = $this->getDestinationArray();
$row_position = 0; $row_position = 0;
// Build the actual form. // Build the actual form.
$access_control_handler = $this->entityManager->getAccessControlHandler('taxonomy_term');
$create_access = $access_control_handler->createAccess($taxonomy_vocabulary->id(), NULL, [], TRUE);
if ($create_access->isAllowed()) {
$empty = $this->t('No terms available. <a href=":link">Add term</a>.', [':link' => Url::fromRoute('entity.taxonomy_term.add_form', ['taxonomy_vocabulary' => $taxonomy_vocabulary->id()])->toString()]);
}
else {
$empty = $this->t('No terms available.');
}
$form['terms'] = [ $form['terms'] = [
'#type' => 'table', '#type' => 'table',
'#header' => [$this->t('Name'), $this->t('Weight'), $this->t('Operations')], '#empty' => $empty,
'#empty' => $this->t('No terms available. <a href=":link">Add term</a>.', [':link' => $this->url('entity.taxonomy_term.add_form', ['taxonomy_vocabulary' => $taxonomy_vocabulary->id()])]),
'#attributes' => [ '#attributes' => [
'id' => 'taxonomy', 'id' => 'taxonomy',
], ],
]; ];
$this->renderer->addCacheableDependency($form['terms'], $create_access);
// Only allow access to changing weights if the user has update access for
// all terms.
$change_weight_access = AccessResult::allowed();
foreach ($current_page as $key => $term) { foreach ($current_page as $key => $term) {
/** @var $term \Drupal\Core\Entity\EntityInterface */ /** @var $term \Drupal\Core\Entity\EntityInterface */
$term = $this->entityManager->getTranslationFromContext($term); $term = $this->entityManager->getTranslationFromContext($term);
...@@ -260,39 +293,26 @@ public function buildForm(array $form, FormStateInterface $form_state, Vocabular ...@@ -260,39 +293,26 @@ public function buildForm(array $form, FormStateInterface $form_state, Vocabular
], ],
]; ];
} }
$form['terms'][$key]['weight'] = [ $update_access = $term->access('update', NULL, TRUE);
'#type' => 'weight', $change_weight_access = $change_weight_access->andIf($update_access);
'#delta' => $delta,
'#title' => $this->t('Weight for added term'), if ($update_access->isAllowed()) {
'#title_display' => 'invisible', $form['terms'][$key]['weight'] = [
'#default_value' => $term->getWeight(), '#type' => 'weight',
'#attributes' => [ '#delta' => $delta,
'class' => ['term-weight'], '#title' => $this->t('Weight for added term'),
], '#title_display' => 'invisible',
]; '#default_value' => $term->getWeight(),
$operations = [ '#attributes' => ['class' => ['term-weight']],
'edit' => [ ];
'title' => $this->t('Edit'), }
'query' => $destination,
'url' => $term->urlInfo('edit-form'), if ($operations = $this->termListBuilder->getOperations($term)) {
], $form['terms'][$key]['operations'] = [
'delete' => [ '#type' => 'operations',
'title' => $this->t('Delete'), '#links' => $operations,
'query' => $destination,
'url' => $term->urlInfo('delete-form'),
],
];
if ($this->moduleHandler->moduleExists('content_translation') && content_translation_translate_access($term)->isAllowed()) {
$operations['translate'] = [
'title' => $this->t('Translate'),
'query' => $destination,
'url' => $term->urlInfo('drupal:content-translation-overview'),
]; ];
} }
$form['terms'][$key]['operations'] = [
'#type' => 'operations',
'#links' => $operations,
];
$form['terms'][$key]['#attributes']['class'] = []; $form['terms'][$key]['#attributes']['class'] = [];
if ($parent_fields) { if ($parent_fields) {
...@@ -322,34 +342,42 @@ public function buildForm(array $form, FormStateInterface $form_state, Vocabular ...@@ -322,34 +342,42 @@ public function buildForm(array $form, FormStateInterface $form_state, Vocabular
$row_position++; $row_position++;
} }
if ($parent_fields) { $form['terms']['#header'] = [$this->t('Name')];
$form['terms']['#tabledrag'][] = [
'action' => 'match', $this->renderer->addCacheableDependency($form['terms'], $change_weight_access);
'relationship' => 'parent', if ($change_weight_access->isAllowed()) {
'group' => 'term-parent', $form['terms']['#header'][] = $this->t('Weight');
'subgroup' => 'term-parent', if ($parent_fields) {
'source' => 'term-id', $form['terms']['#tabledrag'][] = [
'hidden' => FALSE, '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'][] = [ $form['terms']['#tabledrag'][] = [
'action' => 'depth', 'action' => 'order',
'relationship' => 'group', 'relationship' => 'sibling',
'group' => 'term-depth', 'group' => 'term-weight',
'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',
];
if ($taxonomy_vocabulary->getHierarchy() != VocabularyInterface::HIERARCHY_MULTIPLE && count($tree) > 1) { $form['terms']['#header'][] = $this->t('Operations');
if (($taxonomy_vocabulary->getHierarchy() !== VocabularyInterface::HIERARCHY_MULTIPLE && count($tree) > 1) && $change_weight_access->isAllowed()) {
$form['actions'] = ['#type' => 'actions', '#tree' => FALSE]; $form['actions'] = ['#type' => 'actions', '#tree' => FALSE];
$form['actions']['submit'] = [ $form['actions']['submit'] = [
'#type' => 'submit', '#type' => 'submit',
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
use Drupal\Core\DependencyInjection\ContainerInjectionInterface; use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\Core\Entity\EntityManagerInterface; use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait; use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\taxonomy\Entity\Vocabulary;
use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\ContainerInterface;
/** /**
...@@ -48,19 +49,30 @@ public static function create(ContainerInterface $container) { ...@@ -48,19 +49,30 @@ public static function create(ContainerInterface $container) {
*/ */
public function permissions() { public function permissions() {
$permissions = []; $permissions = [];
foreach ($this->entityManager->getStorage('taxonomy_vocabulary')->loadMultiple() as $vocabulary) { foreach (Vocabulary::loadMultiple() as $vocabulary) {
$permissions += [ $permissions += $this->buildPermissions($vocabulary);
'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()]),
],
];
} }
return $permissions; return $permissions;
} }
/**
* Builds a standard list of taxonomy term permissions for a given vocabulary.
*
* @param \Drupal\taxonomy\VocabularyInterface $vocabulary
* The vocabulary.
*
* @return array
* An array of permission names and descriptions.
*/
protected function buildPermissions(VocabularyInterface $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)],
];
}
} }
...@@ -38,7 +38,7 @@ protected function checkAccess(EntityInterface $entity, $operation, AccountInter ...@@ -38,7 +38,7 @@ protected function checkAccess(EntityInterface $entity, $operation, AccountInter
* {@inheritdoc} * {@inheritdoc}
*/ */
protected function checkCreateAccess(AccountInterface $account, array $context, $entity_bundle = NULL) { 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');
} }
} }
<?php
namespace Drupal\taxonomy;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Entity\EntityAccessControlHandler;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Session\AccountInterface;
/**
* Defines the access control handler for the taxonomy vocabulary entity type.
*
* @see \Drupal\taxonomy\Entity\Vocabulary
*/
class VocabularyAccessControlHandler extends EntityAccessControlHandler {
/**
* {@inheritdoc}
*/
protected function checkAccess(EntityInterface $entity, $operation, AccountInterface $account) {
switch ($operation) {
case 'access taxonomy overview':
return AccessResult::allowedIfHasPermissions($account, ['access taxonomy overview', 'administer taxonomy'], 'OR');
default:
return parent::checkAccess($entity, $operation, $account);
}
}
}
...@@ -4,8 +4,13 @@ ...@@ -4,8 +4,13 @@
use Drupal\Core\Config\Entity\DraggableListBuilder; use Drupal\Core\Config\Entity\DraggableListBuilder;
use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\RendererInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Url; use Drupal\Core\Url;
use Symfony\Component\DependencyInjection\ContainerInterface;
/** /**
* Defines a class to build a listing of taxonomy vocabulary entities. * Defines a class to build a listing of taxonomy vocabulary entities.
...@@ -19,6 +24,59 @@ class VocabularyListBuilder extends DraggableListBuilder { ...@@ -19,6 +24,59 @@ class VocabularyListBuilder extends DraggableListBuilder {
*/ */
protected $entitiesKey = 'vocabularies'; protected $entitiesKey = 'vocabularies';
/**
* The current user.
*
* @var \Drupal\Core\Session\AccountInterface
*/
protected $currentUser;
/**
* The entity manager.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* The renderer service.
*
* @var \Drupal\Core\Render\RendererInterface
*/
protected $renderer;
/**
* Constructs a new VocabularyListBuilder object.
*
* @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
* The entity type definition.
* @param \Drupal\Core\Session\AccountInterface $current_user
* The current user.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity manager service.
* @param \Drupal\Core\Render\RendererInterface $renderer
* The renderer service.
*/
public function __construct(EntityTypeInterface $entity_type, AccountInterface $current_user, EntityTypeManagerInterface $entity_type_manager, RendererInterface $renderer = NULL) {
parent::__construct($entity_type, $entity_type_manager->getStorage($entity_type->id()));
$this->currentUser = $current_user;
$this->entityTypeManager = $entity_type_manager;
$this->renderer = $renderer;
}
/**
* {@inheritdoc}
*/
public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) {
return new static(
$entity_type,
$container->get('current_user'),
$container->get('entity_type.manager'),
$container->get('renderer')
);
}
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
...@@ -36,16 +94,23 @@ public function getDefaultOperations(EntityInterface $entity) { ...@@ -36,16 +94,23 @@ public function getDefaultOperations(EntityInterface $entity) {
$operations['edit']['title'] = t('Edit vocabulary'); $operations['edit']['title'] = t('Edit vocabulary');
} }
$operations['list'] = [ if ($entity->access('access taxonomy overview')) {
'title' => t('List terms'), $operations['list'] = [
'weight' => 0, 'title' => t('List terms'),
'url' => $entity->urlInfo('overview-form'), 'weight' => 0,
]; 'url' => $entity->toUrl('overview-form'),
$operations['add'] = [ ];
'title' => t('Add terms'), }
'weight' => 10,
'url' => Url::fromRoute('entity.taxonomy_term.add_form', ['taxonomy_vocabulary' => $entity->id()]), $taxonomy_term_access_control_handler = $this->entityTypeManager->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']); unset($operations['delete']);
return $operations; return $operations;
...@@ -57,6 +122,11 @@ public function getDefaultOperations(EntityInterface $entity) { ...@@ -57,6 +122,11 @@ public function getDefaultOperations(EntityInterface $entity) {
public function buildHeader() { public function buildHeader() {
$header['label'] = t('Vocabulary name'); $header['label'] = t('Vocabulary name');
$header['description'] = t('Description'); $header['description'] = t('Description');
if ($this->currentUser->hasPermission('administer vocabularies')) {
$header['weight'] = t('Weight');
}
return $header + parent::buildHeader(); return $header + parent::buildHeader();
} }
...@@ -80,7 +150,25 @@ public function render() { ...@@ -80,7 +150,25 @@ public function render() {
unset($this->weightKey); unset($this->weightKey);
} }
$build = parent::render(); $build = parent::render();
$build['table']['#empty'] = t('No vocabularies available. <a href=":link">Add vocabulary</a>.', [':link' => \Drupal::url('entity.taxonomy_vocabulary.add_form')]);
// If the weight key was unset then the table is in the 'table' key,
// otherwise in vocabularies. The empty message is only needed if the table
// is possibly empty, so there is no need to support the vocabularies key
// here.
if (isset($build['table'])) {
$access_control_handler = $this->entityTypeManager->getAccessControlHandler('taxonomy_vocabulary');
$create_access = $access_control_handler->createAccess(NULL, NULL, [], TRUE);
$this->renderer->addCacheableDependency($build['table'], $create_access);
if ($create_access->isAllowed()) {
$build['table']['#empty'] = t('No vocabularies available. <a href=":link">Add vocabulary</a>.', [
':link' => Url::fromRoute('entity.taxonomy_vocabulary.add_form')->toString()
]);
}
else {
$build['table']['#empty'] = t('No vocabularies available.');
}
}
return $build; return $build;
} }
......
...@@ -75,13 +75,25 @@ function taxonomy_help($route_name, RouteMatchInterface $route_match) { ...@@ -75,13 +75,25 @@ function taxonomy_help($route_name, RouteMatchInterface $route_match) {
case 'entity.taxonomy_vocabulary.overview_form': case 'entity.taxonomy_vocabulary.overview_form':
$vocabulary = $route_match->getParameter('taxonomy_vocabulary'); $vocabulary = $route_match->getParameter('taxonomy_vocabulary');
switch ($vocabulary->getHierarchy()) { if (\Drupal::currentUser()->hasPermission('administer taxonomy') || \Drupal::currentUser()->hasPermission('edit terms in ' . $vocabulary->id())) {
case VocabularyInterface::HIERARCHY_DISABLED: switch ($vocabulary->getHierarchy()) {
return '<p>' . 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.', ['%capital_name' => Unicode::ucfirst($vocabulary->label()), '%name' => $vocabulary->label()]) . '</p>'; case VocabularyInterface::HIERARCHY_DISABLED:
case VocabularyInterface::HIERARCHY_SINGLE: return '<p>' . 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.', ['%capital_name' => Unicode::ucfirst($vocabulary->label()), '%name' => $vocabulary->label()]) . '</p>';
return '<p>' . t('%capital_name contains terms grouped under parent terms. You can reorganize the terms in %capital_name using their drag-and-drop handles.', ['%capital_name' => Unicode::ucfirst($vocabulary->label()), '%name' => $vocabulary->label()]) . '</p>'; case VocabularyInterface::HIERARCHY_SINGLE:
case VocabularyInterface::HIERARCHY_MULTIPLE: return '<p>' . t('%capital_name contains terms grouped under parent terms. You can reorganize the terms in %capital_name using their drag-and-drop handles.', ['%capital_name' => Unicode::ucfirst($vocabulary->label()), '%name' => $vocabulary->label()]) . '</p>';
return '<p>' . t('%capital_name contains terms with multiple parents. Drag and drop of terms with multiple parents is not supported, but you can re-enable drag-and-drop support by editing each term to include only a single parent.', ['%capital_name' => Unicode::ucfirst($vocabulary->label())]) . '</p>'; case VocabularyInterface::HIERARCHY_MULTIPLE:
return '<p>' . t('%capital_name contains terms with multiple parents. Drag and drop of terms with multiple parents is not supported, but you can re-enable drag-and-drop support by editing each term to include only a single parent.', ['%capital_name' => Unicode::ucfirst($vocabulary->label())]) . '</p>';
}
}
else {
switch ($vocabulary->getHierarchy()) {
case VocabularyInterface::HIERARCHY_DISABLED:
return '<p>' . t('%capital_name contains the following terms.', ['%capital_name' => Unicode::ucfirst($vocabulary->label())]) . '</p>';
case VocabularyInterface::HIERARCHY_SINGLE: