diff --git a/core/includes/entity.api.php b/core/includes/entity.api.php index 8e60f00..9609404 100644 --- a/core/includes/entity.api.php +++ b/core/includes/entity.api.php @@ -11,6 +11,74 @@ */ /** + * Checks entity operation access. + * + * @see \Drupal\Core\Entity\EntityAccessController + * + * @param \Drupal\Core\Entity\EntityInterface $entity + * @param string $operation + * @param \Drupal\Core\Session\AccountInterface $account + * @param string $langcode + * + * @return bool|null + * A boolean to explicitly allow or deny access, or NULL to neither allow nor + * deny access. + */ +function hook_entity_access(\Drupal\Core\Entity\EntityInterface $entity, $operation, \Drupal\Core\Session\AccountInterface $account, $langcode) { + return NULL; +} + +/** + * Checks entity operation access for a specific entity type. + * + * @see \Drupal\Core\Entity\EntityAccessController + * + * @param \Drupal\Core\Entity\EntityInterface $entity + * @param string $operation + * @param \Drupal\Core\Session\AccountInterface $account + * @param string $langcode + * + * @return bool|null + * A boolean to explicitly allow or deny access, or NULL to neither allow nor + * deny access. + */ +function hook_ENTITY_TYPE_access(\Drupal\Core\Entity\EntityInterface $entity, $operation, \Drupal\Core\Session\AccountInterface $account, $langcode) { + return NULL; +} + +/** + * Checks entity create access. + * + * @see \Drupal\Core\Entity\EntityAccessController + * + * @param \Drupal\Core\Session\AccountInterface $account + * @param string $langcode + * + * @return bool|null + * A boolean to explicitly allow or deny access, or NULL to neither allow nor + * deny access. + */ +function hook_entity_create_access(\Drupal\Core\Session\AccountInterface $account, $langcode) { + return NULL; +} + +/** + * Checks entity create access for a specific entity type. + * + * @see \Drupal\Core\Entity\EntityAccessController + * + * @param \Drupal\Core\Session\AccountInterface $account + * @param string $langcode + * + * @return bool|null + * A boolean to explicitly allow or deny access, or NULL to neither allow nor + * deny access. + */ +function hook_ENTITY_TYPE_create_access(\Drupal\Core\Session\AccountInterface $account, $langcode) { + return NULL; +} + +/** * Add to entity type definitions. * * Modules may implement this hook to add information to defined entity types. diff --git a/core/lib/Drupal/Core/Entity/EntityAccessController.php b/core/lib/Drupal/Core/Entity/EntityAccessController.php index 4658d50..aeb1df3 100644 --- a/core/lib/Drupal/Core/Entity/EntityAccessController.php +++ b/core/lib/Drupal/Core/Entity/EntityAccessController.php @@ -7,13 +7,16 @@ namespace Drupal\Core\Entity; +use Drupal\Core\Entity\EntityControllerInterface; +use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Language\Language; use Drupal\Core\Session\AccountInterface; +use Symfony\Component\DependencyInjection\ContainerInterface; /** * Defines a default implementation for entity access controllers. */ -class EntityAccessController implements EntityAccessControllerInterface { +class EntityAccessController implements EntityAccessControllerInterface, EntityControllerInterface { /** * Stores calculcated access check results. @@ -30,13 +33,29 @@ class EntityAccessController implements EntityAccessControllerInterface { protected $entityType; /** + * The module handler. + * + * @var \Drupal\Core\Extension\ModuleHandlerInterface + */ + protected $moduleHandler; + + /** * Constructs an access controller instance. * * @param string $entity_type * The entity type of the access controller instance. + * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler */ - public function __construct($entity_type) { - $this->entity_type = $entity_type; + public function __construct($entity_type, ModuleHandlerInterface $module_handler) { + $this->entityType = $entity_type; + $this->moduleHandler = $module_handler; + } + + /** + * {@inheritdoc} + */ + public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info) { + return new static($entity_type, $container->get('module_handler')); } /** @@ -50,15 +69,18 @@ public function access(EntityInterface $entity, $operation, $langcode = Language return $access; } - // Invoke hook_entity_access(), hook results take precedence over overridden - // implementations of EntityAccessController::checkAccess(). Entities - // that have checks that need to be done before the hook is invoked should - // do so by overridding this method. - + // Invoke hook_entity_access() and hook_ENTITY_TYPE_access(). Hook results + // take precedence over overridden implementations of + // EntityAccessController::checkAccess(). Entities that have checks that + // need to be done before the hook is invoked should do so by overriding + // this method. // We grant access to the entity if both of these conditions are met: // - No modules say to deny access. // - At least one module says to grant access. - $access = module_invoke_all($entity->entityType() . '_access', $entity, $operation, $account, $langcode); + $access = array_merge( + $this->moduleHandler->invokeAll('entity_access', $entity, $operation, $account, $langcode), + $this->moduleHandler->invokeAll($entity->entityType() . '_access', $entity, $operation, $account, $langcode) + ); if (($return = $this->processAccessHookResults($access)) === NULL) { // No module had an opinion about the access, so let's the access @@ -188,15 +210,18 @@ public function createAccess($entity_bundle = NULL, AccountInterface $account = return $access; } - // Invoke hook_entity_access(), hook results take precedence over overridden - // implementations of EntityAccessController::checkAccess(). Entities - // that have checks that need to be done before the hook is invoked should - // do so by overridding this method. - + // Invoke hook_entity_create_access() and hook_ENTITY_TYPE_create_access(). + // Hook results take precedence over overridden implementations of + // EntityAccessController::checkAccess(). Entities that have checks that + // need to be done before the hook is invoked should do so by overriding + // this method. // We grant access to the entity if both of these conditions are met: // - No modules say to deny access. // - At least one module says to grant access. - $access = module_invoke_all($this->entity_type . '_create_access', $account, $context['langcode']); + $access = array_merge( + $this->moduleHandler->invokeAll('entity_create_access', $account, $context['langcode']), + $this->moduleHandler->invokeAll($this->entityType . '_create_access', $account, $context['langcode']) + ); if (($return = $this->processAccessHookResults($access)) === NULL) { // No module had an opinion about the access, so let's the access diff --git a/core/modules/block/lib/Drupal/block/BlockAccessController.php b/core/modules/block/lib/Drupal/block/BlockAccessController.php index 85f449e..8d3ed39 100644 --- a/core/modules/block/lib/Drupal/block/BlockAccessController.php +++ b/core/modules/block/lib/Drupal/block/BlockAccessController.php @@ -9,7 +9,7 @@ use Drupal\Core\Entity\EntityAccessController; use Drupal\Core\Entity\EntityControllerInterface; -use Drupal\Core\Entity\EntityInterface; +use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Session\AccountInterface; use Drupal\Core\Path\AliasManagerInterface; use Drupal\Component\Utility\Unicode; @@ -34,9 +34,10 @@ class BlockAccessController extends EntityAccessController implements EntityCont * The entity type of the access controller instance. * @param \Drupal\Core\Path\AliasManagerInterface $alias_manager * The alias manager. + * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler */ - public function __construct($entity_type, AliasManagerInterface $alias_manager) { - parent::__construct($entity_type); + public function __construct($entity_type, AliasManagerInterface $alias_manager, ModuleHandlerInterface $module_handler) { + parent::__construct($entity_type, $module_handler); $this->aliasManager = $alias_manager; } @@ -46,7 +47,8 @@ public function __construct($entity_type, AliasManagerInterface $alias_manager) public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info) { return new static( $entity_type, - $container->get('path.alias_manager') + $container->get('path.alias_manager'), + $container->get('module_handler') ); } diff --git a/core/modules/node/lib/Drupal/node/NodeAccessController.php b/core/modules/node/lib/Drupal/node/NodeAccessController.php index b1f120a..9e6d329 100644 --- a/core/modules/node/lib/Drupal/node/NodeAccessController.php +++ b/core/modules/node/lib/Drupal/node/NodeAccessController.php @@ -31,13 +31,6 @@ class NodeAccessController extends EntityAccessController implements NodeAccessC */ protected $grantStorage; - /** - * The module handler. - * - * @var \Drupal\Core\Extension\ModuleHandlerInterface - */ - protected $moduleHandler; - /** * Constructs a NodeAccessController object. * @@ -47,11 +40,11 @@ class NodeAccessController extends EntityAccessController implements NodeAccessC * The node grant storage. * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler * The module handler to invoke the alter hook with. + * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler */ public function __construct($entity_type, NodeGrantDatabaseStorageInterface $grant_storage, ModuleHandlerInterface $module_handler) { - parent::__construct($entity_type); + parent::__construct($entity_type, $module_handler); $this->grantStorage = $grant_storage; - $this->moduleHandler = $module_handler; } /**