diff --git a/core/lib/Drupal/Core/Config/Entity/DraggableListBuilder.php b/core/lib/Drupal/Core/Config/Entity/DraggableListBuilder.php index f6bf463b16..81d94b5c40 100644 --- a/core/lib/Drupal/Core/Config/Entity/DraggableListBuilder.php +++ b/core/lib/Drupal/Core/Config/Entity/DraggableListBuilder.php @@ -2,6 +2,7 @@ namespace Drupal\Core\Config\Entity; +use Drupal\Core\Entity\EntityAccessControlHandlerInterface; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityStorageInterface; use Drupal\Core\Entity\EntityTypeInterface; @@ -47,10 +48,17 @@ protected $formBuilder; /** - * {@inheritdoc} + * Constructs a new DraggableListBuilder 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\Entity\EntityAccessControlHandlerInterface $access_control_handler + * The access control handler. */ - public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage) { - parent::__construct($entity_type, $storage); + public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage, EntityAccessControlHandlerInterface $access_control_handler) { + parent::__construct($entity_type, $storage, $access_control_handler); // Check if the entity type supports weighting. if ($this->entityType->hasKey('weight')) { diff --git a/core/lib/Drupal/Core/Entity/EntityListBuilder.php b/core/lib/Drupal/Core/Entity/EntityListBuilder.php index 7191fae8d4..feb3d59649 100644 --- a/core/lib/Drupal/Core/Entity/EntityListBuilder.php +++ b/core/lib/Drupal/Core/Entity/EntityListBuilder.php @@ -22,6 +22,13 @@ class EntityListBuilder extends EntityHandlerBase implements EntityListBuilderIn */ protected $storage; + /** + * The access control handler. + * + * @var \Drupal\Core\Entity\EntityAccessControlHandlerInterface + */ + protected $accessControlHandler; + /** * The entity type ID. * @@ -52,7 +59,8 @@ class EntityListBuilder extends EntityHandlerBase implements EntityListBuilderIn public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) { return new static( $entity_type, - $container->get('entity.manager')->getStorage($entity_type->id()) + $container->get('entity.manager')->getStorage($entity_type->id()), + $container->get('entity_type.manager')->getAccessControlHandler($entity_type->id()) ); } @@ -63,11 +71,14 @@ public static function createInstance(ContainerInterface $container, EntityTypeI * The entity type definition. * @param \Drupal\Core\Entity\EntityStorageInterface $storage * The entity storage class. + * @param \Drupal\Core\Entity\EntityAccessControlHandlerInterface $access_control_handler + * The access control handler. */ - public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage) { + public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage, EntityAccessControlHandlerInterface $access_control_handler) { $this->entityTypeId = $entity_type->id(); $this->storage = $storage; $this->entityType = $entity_type; + $this->accessControlHandler = $access_control_handler; } /** @@ -214,8 +225,6 @@ public function buildOperations(EntityInterface $entity) { * {@inheritdoc} * * Builds the entity listing as renderable array for table.html.twig. - * - * @todo Add a link to add a new item to the #empty text. */ public function render() { $build['table'] = [ @@ -223,7 +232,7 @@ public function render() { '#header' => $this->buildHeader(), '#title' => $this->getTitle(), '#rows' => [], - '#empty' => $this->t('There is no @label yet.', ['@label' => $this->entityType->getLabel()]), + '#empty' => $this->getEmptyText(), '#cache' => [ 'contexts' => $this->entityType->getListCacheContexts(), 'tags' => $this->entityType->getListCacheTags(), @@ -264,4 +273,63 @@ protected function ensureDestination(Url $url) { return $url->mergeOptions(['query' => $this->getRedirectDestination()->getAsArray()]); } + /** + * Returns the text to display when the list is empty. + * + * @return string + * The translated empty text. + */ + protected function getEmptyText() { + $empty_text = (string) $this->t('There is no @label yet.', [ + '@label' => $this->entityType->getLabel(), + ]); + + // Append the add link if it exists and is accessible. + $add_link = $this->getAddLink(); + if (!empty($add_link)) { + $empty_text = $empty_text . ' ' . (string) $add_link; + } + + return $empty_text; + } + + /** + * Returns the text for the "Add new entity" link. + * + * @return \Drupal\Core\StringTranslation\TranslatableMarkup + * The translatable link text. + */ + protected function getAddLinkText() { + return $this->t('Add a new @label entity.', [ + '@label' => $this->entityType->getLabel(), + ]); + } + + /** + * Returns a link to add a new entity. + * + * @return string|false + * The HTML link or FALSE if no link is available. + */ + protected function getAddLink() { + if (!$this->accessControlHandler->createAccess()) { + return FALSE; + } + + if ($this->entityType->hasLinkTemplate('add-page')) { + return \Drupal::linkGenerator()->generate( + $this->getAddLinkText(), + Url::fromUri('internal:' . $this->entityType->getLinkTemplate('add-page')) + ); + } + elseif ($this->entityType->hasLinkTemplate('add-form')) { + return \Drupal::linkGenerator()->generate( + $this->getAddLinkText(), + Url::fromUri('internal:' . $this->entityType->getLinkTemplate('add-form')) + ); + } + + return FALSE; + } + } diff --git a/core/modules/action/src/ActionListBuilder.php b/core/modules/action/src/ActionListBuilder.php index 2167d8e094..0453b0d6e3 100644 --- a/core/modules/action/src/ActionListBuilder.php +++ b/core/modules/action/src/ActionListBuilder.php @@ -3,6 +3,7 @@ namespace Drupal\action; use Drupal\Core\Action\ActionManager; +use Drupal\Core\Entity\EntityAccessControlHandlerInterface; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Config\Entity\ConfigEntityListBuilder; use Drupal\Core\Entity\EntityStorageInterface; @@ -36,11 +37,13 @@ class ActionListBuilder extends ConfigEntityListBuilder { * The entity type definition. * @param \Drupal\Core\Entity\EntityStorageInterface $storage * The action storage. + * @param \Drupal\Core\Entity\EntityAccessControlHandlerInterface $access_control_handler + * The access control handler. * @param \Drupal\Core\Action\ActionManager $action_manager * The action plugin manager. */ - public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage, ActionManager $action_manager) { - parent::__construct($entity_type, $storage); + public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage, EntityAccessControlHandlerInterface $access_control_handler, ActionManager $action_manager) { + parent::__construct($entity_type, $storage, $access_control_handler); $this->actionManager = $action_manager; } @@ -52,6 +55,7 @@ public static function createInstance(ContainerInterface $container, EntityTypeI return new static( $entity_type, $container->get('entity.manager')->getStorage($entity_type->id()), + $container->get('entity_type.manager')->getAccessControlHandler($entity_type->id()), $container->get('plugin.manager.action') ); } diff --git a/core/modules/aggregator/src/Entity/Feed.php b/core/modules/aggregator/src/Entity/Feed.php index 3b14e8c24e..cbfe61102f 100644 --- a/core/modules/aggregator/src/Entity/Feed.php +++ b/core/modules/aggregator/src/Entity/Feed.php @@ -31,6 +31,7 @@ * }, * links = { * "canonical" = "/aggregator/sources/{aggregator_feed}", + * "add-form": "/aggregator/sources/add", * "edit-form" = "/aggregator/sources/{aggregator_feed}/configure", * "delete-form" = "/aggregator/sources/{aggregator_feed}/delete", * }, diff --git a/core/modules/block/src/BlockListBuilder.php b/core/modules/block/src/BlockListBuilder.php index 37b2e8bfc3..8dc47b23e6 100644 --- a/core/modules/block/src/BlockListBuilder.php +++ b/core/modules/block/src/BlockListBuilder.php @@ -5,6 +5,7 @@ use Drupal\Component\Utility\Html; use Drupal\Component\Serialization\Json; use Drupal\Core\Config\Entity\ConfigEntityListBuilder; +use Drupal\Core\Entity\EntityAccessControlHandlerInterface; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityStorageInterface; use Drupal\Core\Entity\EntityTypeInterface; @@ -63,13 +64,15 @@ class BlockListBuilder extends ConfigEntityListBuilder implements FormInterface * The entity type definition. * @param \Drupal\Core\Entity\EntityStorageInterface $storage * The entity storage class. + * @param \Drupal\Core\Entity\EntityAccessControlHandlerInterface $access_control_handler + * The access control handler. * @param \Drupal\Core\Theme\ThemeManagerInterface $theme_manager * The theme manager. * @param \Drupal\Core\Form\FormBuilderInterface $form_builder * The form builder. */ - public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage, ThemeManagerInterface $theme_manager, FormBuilderInterface $form_builder) { - parent::__construct($entity_type, $storage); + public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage, EntityAccessControlHandlerInterface $access_control_handler, ThemeManagerInterface $theme_manager, FormBuilderInterface $form_builder) { + parent::__construct($entity_type, $storage, $access_control_handler); $this->themeManager = $theme_manager; $this->formBuilder = $form_builder; @@ -82,6 +85,7 @@ public static function createInstance(ContainerInterface $container, EntityTypeI return new static( $entity_type, $container->get('entity.manager')->getStorage($entity_type->id()), + $container->get('entity_type.manager')->getAccessControlHandler($entity_type->id()), $container->get('theme.manager'), $container->get('form_builder') ); diff --git a/core/modules/block_content/src/Entity/BlockContent.php b/core/modules/block_content/src/Entity/BlockContent.php index 3c8858ff88..19b416a327 100644 --- a/core/modules/block_content/src/Entity/BlockContent.php +++ b/core/modules/block_content/src/Entity/BlockContent.php @@ -38,6 +38,8 @@ * show_revision_ui = TRUE, * links = { * "canonical" = "/block/{block_content}", + * "add-page" = "/block/add", + * "add-form" = "/block/add/{block_content_type}", * "delete-form" = "/block/{block_content}/delete", * "edit-form" = "/block/{block_content}", * "collection" = "/admin/structure/block/block-content", diff --git a/core/modules/block_content/src/Entity/BlockContentType.php b/core/modules/block_content/src/Entity/BlockContentType.php index 339b4e5033..f4e126f4b4 100644 --- a/core/modules/block_content/src/Entity/BlockContentType.php +++ b/core/modules/block_content/src/Entity/BlockContentType.php @@ -2,8 +2,9 @@ namespace Drupal\block_content\Entity; -use Drupal\Core\Config\Entity\ConfigEntityBundleBase; use Drupal\block_content\BlockContentTypeInterface; +use Drupal\Core\Config\Entity\ConfigEntityBundleBase; +use Drupal\Core\Url; /** * Defines the custom block type entity. @@ -28,6 +29,7 @@ * "label" = "label" * }, * links = { + * "add-form" = "/admin/structure/block/block-content/types/add", * "delete-form" = "/admin/structure/block/block-content/manage/{block_content_type}/delete", * "edit-form" = "/admin/structure/block/block-content/manage/{block_content_type}", * "collection" = "/admin/structure/block/block-content/types", @@ -84,4 +86,23 @@ public function shouldCreateNewRevision() { return $this->revision; } + /** + * {@inheritdoc} + */ + public function toUrl($rel = 'edit-form', array $options = []) { + // When the 'add-form' link template is requested, return the legacy route. + // This route was created before we had structured entity paths so it is not + // discovered by the parent method. + if ($rel === 'add-form') { + $uri = new Url('block_content.type_add'); + $options += [ + 'language' => NULL, + 'entity_type' => $this->getEntityTypeId(), + 'entity' => $this, + ]; + return $uri->setOptions($options); + } + return parent::toUrl($rel, $options); + } + } diff --git a/core/modules/config_translation/src/Controller/ConfigTranslationBlockListBuilder.php b/core/modules/config_translation/src/Controller/ConfigTranslationBlockListBuilder.php index c226dfbd60..06624688f1 100644 --- a/core/modules/config_translation/src/Controller/ConfigTranslationBlockListBuilder.php +++ b/core/modules/config_translation/src/Controller/ConfigTranslationBlockListBuilder.php @@ -2,6 +2,7 @@ namespace Drupal\config_translation\Controller; +use Drupal\Core\Entity\EntityAccessControlHandlerInterface; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityStorageInterface; use Drupal\Core\Entity\EntityTypeInterface; @@ -21,10 +22,19 @@ class ConfigTranslationBlockListBuilder extends ConfigTranslationEntityListBuild protected $themes = []; /** - * {@inheritdoc} + * Constructs a ConfigTranslationBlockListBuilder 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\Entity\EntityAccessControlHandlerInterface $access_control_handler + * The access control handler. + * @param ThemeHandlerInterface $theme_handler + * The theme handler. */ - public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage, ThemeHandlerInterface $theme_handler) { - parent::__construct($entity_type, $storage); + public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage, EntityAccessControlHandlerInterface $access_control_handler, ThemeHandlerInterface $theme_handler) { + parent::__construct($entity_type, $storage, $access_control_handler); $this->themes = $theme_handler->listInfo(); } @@ -35,6 +45,7 @@ public static function createInstance(ContainerInterface $container, EntityTypeI return new static( $entity_type, $container->get('entity.manager')->getStorage($entity_type->id()), + $container->get('entity_type.manager')->getAccessControlHandler($entity_type->id()), $container->get('theme_handler') ); } diff --git a/core/modules/config_translation/src/Controller/ConfigTranslationFieldListBuilder.php b/core/modules/config_translation/src/Controller/ConfigTranslationFieldListBuilder.php index 566afdbb23..4e3c4a5de2 100644 --- a/core/modules/config_translation/src/Controller/ConfigTranslationFieldListBuilder.php +++ b/core/modules/config_translation/src/Controller/ConfigTranslationFieldListBuilder.php @@ -3,6 +3,7 @@ namespace Drupal\config_translation\Controller; use Drupal\Component\Utility\Unicode; +use Drupal\Core\Entity\EntityAccessControlHandlerInterface; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityManagerInterface; use Drupal\Core\Entity\EntityStorageInterface; @@ -50,6 +51,7 @@ public static function createInstance(ContainerInterface $container, EntityTypeI return new static( $entity_type, $entity_manager->getStorage($entity_type->id()), + $container->get('entity_type.manager')->getAccessControlHandler($entity_type->id()), $entity_manager ); } @@ -61,11 +63,13 @@ public static function createInstance(ContainerInterface $container, EntityTypeI * The entity type definition. * @param \Drupal\Core\Entity\EntityStorageInterface $storage * The entity storage class. + * @param \Drupal\Core\Entity\EntityAccessControlHandlerInterface $access_control_handler + * The access control handler. * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager * The entity manager. */ - public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage, EntityManagerInterface $entity_manager) { - parent::__construct($entity_type, $storage); + public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage, EntityAccessControlHandlerInterface $access_control_handler, EntityManagerInterface $entity_manager) { + parent::__construct($entity_type, $storage, $access_control_handler); $this->entityManager = $entity_manager; } diff --git a/core/modules/field_ui/src/EntityDisplayModeListBuilder.php b/core/modules/field_ui/src/EntityDisplayModeListBuilder.php index c9d8966278..6475f83c42 100644 --- a/core/modules/field_ui/src/EntityDisplayModeListBuilder.php +++ b/core/modules/field_ui/src/EntityDisplayModeListBuilder.php @@ -3,6 +3,7 @@ namespace Drupal\field_ui; use Drupal\Core\Config\Entity\ConfigEntityListBuilder; +use Drupal\Core\Entity\EntityAccessControlHandlerInterface; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityStorageInterface; use Drupal\Core\Entity\EntityTypeInterface; @@ -30,11 +31,13 @@ class EntityDisplayModeListBuilder extends ConfigEntityListBuilder { * The entity type definition. * @param \Drupal\Core\Entity\EntityStorageInterface $storage * The entity storage class. + * @param \Drupal\Core\Entity\EntityAccessControlHandlerInterface $access_control_handler + * The access control handler. * @param \Drupal\Core\Entity\EntityTypeInterface[] $entity_types * List of all entity types. */ - public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage, array $entity_types) { - parent::__construct($entity_type, $storage); + public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage, EntityAccessControlHandlerInterface $access_control_handler, array $entity_types) { + parent::__construct($entity_type, $storage, $access_control_handler); $this->entityTypes = $entity_types; } @@ -47,6 +50,7 @@ public static function createInstance(ContainerInterface $container, EntityTypeI return new static( $entity_type, $entity_manager->getStorage($entity_type->id()), + $container->get('entity_type.manager')->getAccessControlHandler($entity_type->id()), $entity_manager->getDefinitions() ); } diff --git a/core/modules/field_ui/src/FieldConfigListBuilder.php b/core/modules/field_ui/src/FieldConfigListBuilder.php index cb720c32a9..5988f5424e 100644 --- a/core/modules/field_ui/src/FieldConfigListBuilder.php +++ b/core/modules/field_ui/src/FieldConfigListBuilder.php @@ -4,6 +4,7 @@ use Drupal\Component\Utility\Html; use Drupal\Core\Config\Entity\ConfigEntityListBuilder; +use Drupal\Core\Entity\EntityAccessControlHandlerInterface; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityManagerInterface; use Drupal\Core\Entity\EntityTypeInterface; @@ -52,11 +53,13 @@ class FieldConfigListBuilder extends ConfigEntityListBuilder { * The entity type definition. * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager * The entity manager. + * @param \Drupal\Core\Entity\EntityAccessControlHandlerInterface $access_control_handler + * The access control handler. * @param \Drupal\Core\Field\FieldTypePluginManagerInterface $field_type_manager * The field type manager */ - public function __construct(EntityTypeInterface $entity_type, EntityManagerInterface $entity_manager, FieldTypePluginManagerInterface $field_type_manager) { - parent::__construct($entity_type, $entity_manager->getStorage($entity_type->id())); + public function __construct(EntityTypeInterface $entity_type, EntityManagerInterface $entity_manager, EntityAccessControlHandlerInterface $access_control_handler, FieldTypePluginManagerInterface $field_type_manager) { + parent::__construct($entity_type, $entity_manager->getStorage($entity_type->id()), $access_control_handler); $this->entityManager = $entity_manager; $this->fieldTypeManager = $field_type_manager; @@ -66,7 +69,12 @@ public function __construct(EntityTypeInterface $entity_type, EntityManagerInter * {@inheritdoc} */ public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) { - return new static($entity_type, $container->get('entity.manager'), $container->get('plugin.manager.field.field_type')); + return new static( + $entity_type, + $container->get('entity.manager'), + $container->get('entity_type.manager')->getAccessControlHandler($entity_type->id()), + $container->get('plugin.manager.field.field_type') + ); } /** diff --git a/core/modules/field_ui/src/FieldStorageConfigListBuilder.php b/core/modules/field_ui/src/FieldStorageConfigListBuilder.php index f82bd9df1d..74db6d67b5 100644 --- a/core/modules/field_ui/src/FieldStorageConfigListBuilder.php +++ b/core/modules/field_ui/src/FieldStorageConfigListBuilder.php @@ -3,6 +3,7 @@ namespace Drupal\field_ui; use Drupal\Core\Config\Entity\ConfigEntityListBuilder; +use Drupal\Core\Entity\EntityAccessControlHandlerInterface; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityManagerInterface; use Drupal\Core\Entity\EntityTypeInterface; @@ -53,11 +54,13 @@ class FieldStorageConfigListBuilder extends ConfigEntityListBuilder { * The entity type definition. * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager * The entity manager. + * @param \Drupal\Core\Entity\EntityAccessControlHandlerInterface $access_control_handler + * The access control handler. * @param \Drupal\Core\Field\FieldTypePluginManagerInterface $field_type_manager * The 'field type' plugin manager. */ - public function __construct(EntityTypeInterface $entity_type, EntityManagerInterface $entity_manager, FieldTypePluginManagerInterface $field_type_manager, EntityTypeBundleInfoInterface $bundle_info_service) { - parent::__construct($entity_type, $entity_manager->getStorage($entity_type->id())); + public function __construct(EntityTypeInterface $entity_type, EntityManagerInterface $entity_manager, EntityAccessControlHandlerInterface $access_control_handler, FieldTypePluginManagerInterface $field_type_manager, EntityTypeBundleInfoInterface $bundle_info_service) { + parent::__construct($entity_type, $entity_manager->getStorage($entity_type->id()), $access_control_handler); $this->entityManager = $entity_manager; $this->bundles = $bundle_info_service->getAllBundleInfo(); @@ -72,6 +75,7 @@ public static function createInstance(ContainerInterface $container, EntityTypeI return new static( $entity_type, $container->get('entity.manager'), + $container->get('entity_type.manager')->getAccessControlHandler($entity_type->id()), $container->get('plugin.manager.field.field_type'), $container->get('entity_type.bundle.info') ); diff --git a/core/modules/filter/src/FilterFormatListBuilder.php b/core/modules/filter/src/FilterFormatListBuilder.php index cf084564c0..8343095ad2 100644 --- a/core/modules/filter/src/FilterFormatListBuilder.php +++ b/core/modules/filter/src/FilterFormatListBuilder.php @@ -4,6 +4,7 @@ use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\Config\Entity\DraggableListBuilder; +use Drupal\Core\Entity\EntityAccessControlHandlerInterface; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityStorageInterface; use Drupal\Core\Entity\EntityTypeInterface; @@ -36,11 +37,13 @@ class FilterFormatListBuilder extends DraggableListBuilder { * The entity type definition. * @param \Drupal\Core\Entity\EntityStorageInterface $storage * The entity storage class. + * @param \Drupal\Core\Entity\EntityAccessControlHandlerInterface $access_control_handler + * The access control handler. * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory * The config factory. */ - public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage, ConfigFactoryInterface $config_factory) { - parent::__construct($entity_type, $storage); + public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage, EntityAccessControlHandlerInterface $access_control_handler, ConfigFactoryInterface $config_factory) { + parent::__construct($entity_type, $storage, $access_control_handler); $this->configFactory = $config_factory; } @@ -52,6 +55,7 @@ public static function createInstance(ContainerInterface $container, EntityTypeI return new static( $entity_type, $container->get('entity.manager')->getStorage($entity_type->id()), + $container->get('entity_type.manager')->getAccessControlHandler($entity_type->id()), $container->get('config.factory') ); } diff --git a/core/modules/language/src/LanguageListBuilder.php b/core/modules/language/src/LanguageListBuilder.php index 8d15152204..168e4e88db 100644 --- a/core/modules/language/src/LanguageListBuilder.php +++ b/core/modules/language/src/LanguageListBuilder.php @@ -4,6 +4,7 @@ use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\Config\Entity\DraggableListBuilder; +use Drupal\Core\Entity\EntityAccessControlHandlerInterface; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityStorageInterface; use Drupal\Core\Entity\EntityTypeInterface; @@ -44,6 +45,7 @@ public static function createInstance(ContainerInterface $container, EntityTypeI return new static( $entity_type, $container->get('entity.manager')->getStorage($entity_type->id()), + $container->get('entity_type.manager')->getAccessControlHandler($entity_type->id()), $container->get('language_manager'), $container->get('config.factory') ); @@ -56,13 +58,15 @@ public static function createInstance(ContainerInterface $container, EntityTypeI * The entity type definition. * @param \Drupal\Core\Entity\EntityStorageInterface $storage * The entity storage handler class. + * @param \Drupal\Core\Entity\EntityAccessControlHandlerInterface $access_control_handler + * The access control handler. * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager * The language manager. * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory * The factory for configuration objects. */ - public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage, LanguageManagerInterface $language_manager, ConfigFactoryInterface $config_factory) { - parent::__construct($entity_type, $storage); + public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage, EntityAccessControlHandlerInterface $access_control_handler, LanguageManagerInterface $language_manager, ConfigFactoryInterface $config_factory) { + parent::__construct($entity_type, $storage, $access_control_handler); $this->languageManager = $language_manager; $this->configFactory = $config_factory; } diff --git a/core/modules/node/src/Entity/Node.php b/core/modules/node/src/Entity/Node.php index 368ce1b596..968ae5d06b 100644 --- a/core/modules/node/src/Entity/Node.php +++ b/core/modules/node/src/Entity/Node.php @@ -70,6 +70,8 @@ * permission_granularity = "bundle", * links = { * "canonical" = "/node/{node}", + * "add-page": "/node/add", + * "add-form": "/node/add/{node_type}", * "delete-form" = "/node/{node}/delete", * "edit-form" = "/node/{node}/edit", * "version-history" = "/node/{node}/revisions", diff --git a/core/modules/node/src/NodeListBuilder.php b/core/modules/node/src/NodeListBuilder.php index eac48fda31..174281a20e 100644 --- a/core/modules/node/src/NodeListBuilder.php +++ b/core/modules/node/src/NodeListBuilder.php @@ -3,6 +3,7 @@ namespace Drupal\node; use Drupal\Core\Datetime\DateFormatterInterface; +use Drupal\Core\Entity\EntityAccessControlHandlerInterface; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityListBuilder; use Drupal\Core\Entity\EntityStorageInterface; @@ -32,13 +33,15 @@ class NodeListBuilder extends EntityListBuilder { * The entity type definition. * @param \Drupal\Core\Entity\EntityStorageInterface $storage * The entity storage class. + * @param \Drupal\Core\Entity\EntityAccessControlHandlerInterface $access_control_handler + * The access control handler. * @param \Drupal\Core\Datetime\DateFormatterInterface $date_formatter * The date formatter service. * @param \Drupal\Core\Routing\RedirectDestinationInterface $redirect_destination * The redirect destination service. */ - public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage, DateFormatterInterface $date_formatter, RedirectDestinationInterface $redirect_destination) { - parent::__construct($entity_type, $storage); + public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage, EntityAccessControlHandlerInterface $access_control_handler, DateFormatterInterface $date_formatter, RedirectDestinationInterface $redirect_destination) { + parent::__construct($entity_type, $storage, $access_control_handler); $this->dateFormatter = $date_formatter; $this->redirectDestination = $redirect_destination; @@ -51,6 +54,7 @@ public static function createInstance(ContainerInterface $container, EntityTypeI return new static( $entity_type, $container->get('entity.manager')->getStorage($entity_type->id()), + $container->get('entity_type.manager')->getAccessControlHandler($entity_type->id()), $container->get('date.formatter'), $container->get('redirect.destination') ); diff --git a/core/modules/search/src/SearchPageListBuilder.php b/core/modules/search/src/SearchPageListBuilder.php index 9a8f6deb30..96389659fd 100644 --- a/core/modules/search/src/SearchPageListBuilder.php +++ b/core/modules/search/src/SearchPageListBuilder.php @@ -4,6 +4,7 @@ use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\Config\Entity\DraggableListBuilder; +use Drupal\Core\Entity\EntityAccessControlHandlerInterface; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityStorageInterface; use Drupal\Core\Entity\EntityTypeInterface; @@ -49,13 +50,15 @@ class SearchPageListBuilder extends DraggableListBuilder implements FormInterfac * The entity type definition. * @param \Drupal\Core\Entity\EntityStorageInterface $storage * The entity storage class. + * @param \Drupal\Core\Entity\EntityAccessControlHandlerInterface $access_control_handler + * The access control handler. * @param \Drupal\search\SearchPluginManager $search_manager * The search plugin manager. * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory * The factory for configuration objects. */ - public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage, SearchPluginManager $search_manager, ConfigFactoryInterface $config_factory) { - parent::__construct($entity_type, $storage); + public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage, EntityAccessControlHandlerInterface $access_control_handler, SearchPluginManager $search_manager, ConfigFactoryInterface $config_factory) { + parent::__construct($entity_type, $storage, $access_control_handler); $this->configFactory = $config_factory; $this->searchManager = $search_manager; } @@ -67,6 +70,7 @@ public static function createInstance(ContainerInterface $container, EntityTypeI return new static( $entity_type, $container->get('entity.manager')->getStorage($entity_type->id()), + $container->get('entity_type.manager')->getAccessControlHandler($entity_type->id()), $container->get('plugin.manager.search'), $container->get('config.factory') ); diff --git a/core/modules/system/src/DateFormatListBuilder.php b/core/modules/system/src/DateFormatListBuilder.php index c0e2c366f0..df9e23a662 100644 --- a/core/modules/system/src/DateFormatListBuilder.php +++ b/core/modules/system/src/DateFormatListBuilder.php @@ -4,6 +4,7 @@ use Drupal\Core\Config\Entity\ConfigEntityListBuilder; use Drupal\Core\Datetime\DateFormatterInterface; +use Drupal\Core\Entity\EntityAccessControlHandlerInterface; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityStorageInterface; use Drupal\Core\Entity\EntityTypeInterface; @@ -30,11 +31,13 @@ class DateFormatListBuilder extends ConfigEntityListBuilder { * The entity type definition. * @param \Drupal\Core\Entity\EntityStorageInterface $storage * The entity storage class. + * @param \Drupal\Core\Entity\EntityAccessControlHandlerInterface $access_control_handler + * The access control handler. * @param \Drupal\Core\Datetime\DateFormatterInterface $date_formatter * The date formatter service. */ - public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage, DateFormatterInterface $date_formatter) { - parent::__construct($entity_type, $storage); + public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage, EntityAccessControlHandlerInterface $access_control_handler, DateFormatterInterface $date_formatter) { + parent::__construct($entity_type, $storage, $access_control_handler); $this->dateFormatter = $date_formatter; } @@ -46,6 +49,7 @@ public static function createInstance(ContainerInterface $container, EntityTypeI return new static( $entity_type, $container->get('entity.manager')->getStorage($entity_type->id()), + $container->get('entity_type.manager')->getAccessControlHandler($entity_type->id()), $container->get('date.formatter') ); } diff --git a/core/modules/taxonomy/src/VocabularyListBuilder.php b/core/modules/taxonomy/src/VocabularyListBuilder.php index e7c021b4d7..0b5055455d 100644 --- a/core/modules/taxonomy/src/VocabularyListBuilder.php +++ b/core/modules/taxonomy/src/VocabularyListBuilder.php @@ -3,6 +3,7 @@ namespace Drupal\taxonomy; use Drupal\Core\Config\Entity\DraggableListBuilder; +use Drupal\Core\Entity\EntityAccessControlHandlerInterface; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\Entity\EntityTypeManagerInterface; @@ -52,13 +53,15 @@ class VocabularyListBuilder extends DraggableListBuilder { * The entity type definition. * @param \Drupal\Core\Session\AccountInterface $current_user * The current user. + * @param \Drupal\Core\Entity\EntityAccessControlHandlerInterface $access_control_handler + * The access control handler. * @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())); + public function __construct(EntityTypeInterface $entity_type, AccountInterface $current_user, EntityAccessControlHandlerInterface $access_control_handler, EntityTypeManagerInterface $entity_type_manager, RendererInterface $renderer = NULL) { + parent::__construct($entity_type, $entity_type_manager->getStorage($entity_type->id()), $access_control_handler); $this->currentUser = $current_user; $this->entityTypeManager = $entity_type_manager; @@ -69,10 +72,12 @@ public function __construct(EntityTypeInterface $entity_type, AccountInterface $ * {@inheritdoc} */ public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) { + $entity_type_manager = $container->get('entity_type.manager'); return new static( $entity_type, $container->get('current_user'), - $container->get('entity_type.manager'), + $entity_type_manager->getAccessControlHandler($entity_type->id()), + $entity_type_manager, $container->get('renderer') ); } diff --git a/core/modules/user/src/Entity/User.php b/core/modules/user/src/Entity/User.php index f254ccff93..0b62ee7201 100644 --- a/core/modules/user/src/Entity/User.php +++ b/core/modules/user/src/Entity/User.php @@ -49,6 +49,7 @@ * }, * links = { * "canonical" = "/user/{user}", + * "add-form" = "/admin/people/create", * "edit-form" = "/user/{user}/edit", * "cancel-form" = "/user/{user}/cancel", * "collection" = "/admin/people", diff --git a/core/modules/user/src/UserListBuilder.php b/core/modules/user/src/UserListBuilder.php index 306d04609e..06a513e062 100644 --- a/core/modules/user/src/UserListBuilder.php +++ b/core/modules/user/src/UserListBuilder.php @@ -4,6 +4,7 @@ use Drupal\Core\Cache\CacheableMetadata; use Drupal\Core\Datetime\DateFormatterInterface; +use Drupal\Core\Entity\EntityAccessControlHandlerInterface; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityListBuilder; use Drupal\Core\Entity\EntityStorageInterface; @@ -39,13 +40,15 @@ class UserListBuilder extends EntityListBuilder { * The entity type definition. * @param \Drupal\Core\Entity\EntityStorageInterface $storage * The entity storage class. + * @param \Drupal\Core\Entity\EntityAccessControlHandlerInterface $access_control_handler + * The access control handler. * @param \Drupal\Core\Datetime\DateFormatterInterface $date_formatter * The date formatter service. * @param \Drupal\Core\Routing\RedirectDestinationInterface $redirect_destination * The redirect destination service. */ - public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage, DateFormatterInterface $date_formatter, RedirectDestinationInterface $redirect_destination) { - parent::__construct($entity_type, $storage); + public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage, EntityAccessControlHandlerInterface $access_control_handler, DateFormatterInterface $date_formatter, RedirectDestinationInterface $redirect_destination) { + parent::__construct($entity_type, $storage, $access_control_handler); $this->dateFormatter = $date_formatter; $this->redirectDestination = $redirect_destination; } @@ -57,6 +60,7 @@ public static function createInstance(ContainerInterface $container, EntityTypeI return new static( $entity_type, $container->get('entity.manager')->getStorage($entity_type->id()), + $container->get('entity_type.manager')->getAccessControlHandler($entity_type->id()), $container->get('date.formatter'), $container->get('redirect.destination') ); diff --git a/core/modules/views_ui/src/ViewListBuilder.php b/core/modules/views_ui/src/ViewListBuilder.php index 628408e997..8f2cc5704c 100644 --- a/core/modules/views_ui/src/ViewListBuilder.php +++ b/core/modules/views_ui/src/ViewListBuilder.php @@ -3,6 +3,7 @@ namespace Drupal\views_ui; use Drupal\Component\Plugin\PluginManagerInterface; +use Drupal\Core\Entity\EntityAccessControlHandlerInterface; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Config\Entity\ConfigEntityListBuilder; use Drupal\Core\Entity\EntityStorageInterface; @@ -37,6 +38,7 @@ public static function createInstance(ContainerInterface $container, EntityTypeI return new static( $entity_type, $container->get('entity.manager')->getStorage($entity_type->id()), + $container->get('entity_type.manager')->getAccessControlHandler($entity_type->id()), $container->get('plugin.manager.views.display') ); } @@ -48,11 +50,13 @@ public static function createInstance(ContainerInterface $container, EntityTypeI * The entity type definition. * @param \Drupal\Core\Entity\EntityStorageInterface $storage * The entity storage class. + * @param \Drupal\Core\Entity\EntityAccessControlHandlerInterface $access_control_handler + * The access control handler. * @param \Drupal\Component\Plugin\PluginManagerInterface $display_manager * The views display plugin manager to use. */ - public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage, PluginManagerInterface $display_manager) { - parent::__construct($entity_type, $storage); + public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage, EntityAccessControlHandlerInterface $access_control_handler, PluginManagerInterface $display_manager) { + parent::__construct($entity_type, $storage, $access_control_handler); $this->displayManager = $display_manager; // This list builder uses client-side filters which requires all entities to diff --git a/core/modules/workflows/src/WorkflowListBuilder.php b/core/modules/workflows/src/WorkflowListBuilder.php index c36171aa6e..2dc15dd4ed 100644 --- a/core/modules/workflows/src/WorkflowListBuilder.php +++ b/core/modules/workflows/src/WorkflowListBuilder.php @@ -4,6 +4,7 @@ use Drupal\Component\Plugin\PluginManagerInterface; use Drupal\Core\Config\Entity\ConfigEntityListBuilder; +use Drupal\Core\Entity\EntityAccessControlHandlerInterface; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityStorageInterface; use Drupal\Core\Entity\EntityTypeInterface; @@ -28,6 +29,7 @@ public static function createInstance(ContainerInterface $container, EntityTypeI return new static( $entity_type, $container->get('entity_type.manager')->getStorage($entity_type->id()), + $container->get('entity_type.manager')->getAccessControlHandler($entity_type->id()), $container->get('plugin.manager.workflows.type') ); } @@ -39,11 +41,13 @@ public static function createInstance(ContainerInterface $container, EntityTypeI * The entity type definition. * @param \Drupal\Core\Entity\EntityStorageInterface $storage * The entity storage class. + * @param \Drupal\Core\Entity\EntityAccessControlHandlerInterface $access_control_handler + * The access control handler. * @param \Drupal\Component\Plugin\PluginManagerInterface $workflow_type_manager * The workflow type plugin manager. */ - public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage, PluginManagerInterface $workflow_type_manager) { - parent::__construct($entity_type, $storage); + public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage, EntityAccessControlHandlerInterface $access_control_handler, PluginManagerInterface $workflow_type_manager) { + parent::__construct($entity_type, $storage, $access_control_handler); $this->workflowTypeManager = $workflow_type_manager; } diff --git a/core/tests/Drupal/Tests/Core/Entity/EntityListBuilderTest.php b/core/tests/Drupal/Tests/Core/Entity/EntityListBuilderTest.php index ad68e2df68..8068cb7dc4 100644 --- a/core/tests/Drupal/Tests/Core/Entity/EntityListBuilderTest.php +++ b/core/tests/Drupal/Tests/Core/Entity/EntityListBuilderTest.php @@ -9,6 +9,7 @@ use Drupal\Core\Access\AccessResult; use Drupal\Core\DependencyInjection\ContainerBuilder; +use Drupal\Core\Entity\EntityAccessControlHandlerInterface; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityListBuilder; use Drupal\Core\Routing\RedirectDestinationInterface; @@ -70,6 +71,13 @@ class EntityListBuilderTest extends UnitTestCase { */ protected $redirectDestination; + /** + * The access control handler. + * + * @var \Drupal\Core\Entity\EntityAccessControlHandlerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $accessControlHandler; + /** * The EntityListBuilder object to test. * @@ -88,7 +96,8 @@ protected function setUp() { $this->moduleHandler = $this->getMock('\Drupal\Core\Extension\ModuleHandlerInterface'); $this->entityType = $this->getMock('\Drupal\Core\Entity\EntityTypeInterface'); $this->translationManager = $this->getMock('\Drupal\Core\StringTranslation\TranslationInterface'); - $this->entityListBuilder = new TestEntityListBuilder($this->entityType, $this->roleStorage); + $this->accessControlHandler = $this->getMock(EntityAccessControlHandlerInterface::class); + $this->entityListBuilder = new TestEntityListBuilder($this->entityType, $this->roleStorage, $this->accessControlHandler); $this->redirectDestination = $this->getMock(RedirectDestinationInterface::class); $this->container = new ContainerBuilder(); \Drupal::setContainer($this->container); @@ -137,7 +146,7 @@ public function testGetOperations() { ->method('getAsArray') ->willReturn(['destination' => '/foo/bar']); - $list = new EntityListBuilder($this->entityType, $this->roleStorage); + $list = new EntityListBuilder($this->entityType, $this->roleStorage, $this->accessControlHandler); $list->setStringTranslation($this->translationManager); $list->setRedirectDestination($this->redirectDestination);