diff --git a/core/includes/entity.inc b/core/includes/entity.inc index fe30114..2b3885e 100644 --- a/core/includes/entity.inc +++ b/core/includes/entity.inc @@ -865,21 +865,11 @@ function entity_page_access(EntityInterface $entity, $operation = 'view') { * The entity type. * @param string $bundle * (optional) The bundle of the entity. Required if the entity supports - * bundles, defaults to the entity type otherwise. + * bundles, defaults to NULL otherwise. * * @return bool * TRUE if the access is granted. FALSE if access is denied. */ function entity_page_create_access($entity_type, $bundle = NULL) { - $definition = Drupal::entityManager()->getDefinition($entity_type); - - // Pass in the entity bundle if given and required. - $values = array(); - if ($bundle && isset($definition['entity_keys']['bundle'])) { - $values[$definition['entity_keys']['bundle']] = $bundle; - } - $entity = Drupal::entityManager() - ->getStorageController($entity_type) - ->create($values); - return $entity->access('create'); + return Drupal::entityManager()->getAccessController($entity_type)->createAccess($bundle); } diff --git a/core/lib/Drupal/Core/Entity/Entity.php b/core/lib/Drupal/Core/Entity/Entity.php index 33a62ce..ec05c1a 100644 --- a/core/lib/Drupal/Core/Entity/Entity.php +++ b/core/lib/Drupal/Core/Entity/Entity.php @@ -273,6 +273,11 @@ public function getIterator() { * Implements \Drupal\Core\TypedData\AccessibleInterface::access(). */ public function access($operation = 'view', AccountInterface $account = NULL) { + if ($operation == 'create') { + return \Drupal::entityManager() + ->getAccessController($this->entityType) + ->createAccess($this->bundle(), $account); + } return \Drupal::entityManager() ->getAccessController($this->entityType) ->access($this, $operation, Language::LANGCODE_DEFAULT, $account); diff --git a/core/lib/Drupal/Core/Entity/EntityAccessController.php b/core/lib/Drupal/Core/Entity/EntityAccessController.php index a328443..164b83e 100644 --- a/core/lib/Drupal/Core/Entity/EntityAccessController.php +++ b/core/lib/Drupal/Core/Entity/EntityAccessController.php @@ -23,14 +23,29 @@ class EntityAccessController implements EntityAccessControllerInterface { protected $accessCache = array(); /** + * The entity type of the access controller instance. + * + * @var string + */ + protected $entityType; + + /** + * Constructs an access controller instance. + * + * @param string $entity_type + * The entity type of the access controller instance. + */ + public function __construct($entity_type) { + $this->entity_type = $entity_type; + } + + /** * {@inheritdoc} */ public function access(EntityInterface $entity, $operation, $langcode = Language::LANGCODE_DEFAULT, AccountInterface $account = NULL) { - if (!$account) { - $account = $GLOBALS['user']; - } + $account = $this->prepareUser($account); - if (($access = $this->getCache($entity, $operation, $langcode, $account)) !== NULL) { + if (($access = $this->getCache($entity->uuid(), $operation, $langcode, $account)) !== NULL) { // Cache hit, no work necessary. return $access; } @@ -45,17 +60,36 @@ public function access(EntityInterface $entity, $operation, $langcode = Language // - At least one module says to grant access. $access = module_invoke_all($entity->entityType() . '_access', $entity->getBCEntity(), $operation, $account, $langcode); + if (($return = $this->processAccessHookResults($access)) === NULL) { + // No module had an opinion about the access, so let's the access + // controller check create access. + $return = (bool) $this->checkAccess($entity, $operation, $langcode, $account); + } + return $this->setCache($return, $entity->uuid(), $operation, $langcode, $account); + } + + /** + * 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. + * + * @param array $access + * An array of access results of the fired access hook. + * + * @return bool|NULL + * Returns FALSE if access should be denied, TRUE if access should be + * granted and NULL if no module denied access. + */ + protected function processAccessHookResults(array $access) { if (in_array(FALSE, $access, TRUE)) { - $return = FALSE; + return FALSE; } elseif (in_array(TRUE, $access, TRUE)) { - $return = TRUE; + return TRUE; } else { - // No result from hook, so entity checks are done. - $return = (bool) $this->checkAccess($entity, $operation, $langcode, $account); + return; } - return $this->setCache($return, $entity, $operation, $langcode, $account); } /** @@ -85,8 +119,9 @@ protected function checkAccess(EntityInterface $entity, $operation, $langcode, A /** * Tries to retrieve a previously cached access value from the static cache. * - * @param \Drupal\Core\Entity\EntityInterface $entity - * The entity for which to check 'create' access. + * @param string $cid + * Unique string identifier for the entity/operation, for example the + * entity UUID or a custom string. * @param string $operation * The entity operation. Usually one of 'view', 'update', 'create' or * 'delete'. @@ -100,13 +135,10 @@ protected function checkAccess(EntityInterface $entity, $operation, $langcode, A * is no record for the given user, operation, langcode and entity in the * cache. */ - protected function getCache(EntityInterface $entity, $operation, $langcode, AccountInterface $account) { - $uid = $account ? $account->id() : 0; - $uuid = $entity->uuid(); - + protected function getCache($cid, $operation, $langcode, AccountInterface $account) { // Return from cache if a value has been set for it previously. - if (isset($this->accessCache[$uid][$uuid][$langcode][$operation])) { - return $this->accessCache[$uid][$uuid][$langcode][$operation]; + if (isset($this->accessCache[$account->id()][$cid][$langcode][$operation])) { + return $this->accessCache[$account->id()][$cid][$langcode][$operation]; } } @@ -115,8 +147,9 @@ protected function getCache(EntityInterface $entity, $operation, $langcode, Acco * * @param bool $access * TRUE if the user has access, FALSE otherwise. - * @param \Drupal\Core\Entity\EntityInterface $entity - * The entity for which to check 'create' access. + * @param string $cid + * Unique string identifier for the entity/operation, for example the + * entity UUID or a custom string. * @param string $operation * The entity operation. Usually one of 'view', 'update', 'create' or * 'delete'. @@ -128,12 +161,9 @@ protected function getCache(EntityInterface $entity, $operation, $langcode, Acco * @return bool * TRUE if access was granted, FALSE otherwise. */ - protected function setCache($access, EntityInterface $entity, $operation, $langcode, AccountInterface $account) { - $uid = $account ? $account->id() : 0; - $uuid = $entity->uuid(); - + protected function setCache($access, $cid, $operation, $langcode, AccountInterface $account) { // Save the given value in the static cache and directly return it. - return $this->accessCache[$uid][$uuid][$langcode][$operation] = (bool) $access; + return $this->accessCache[$account->id()][$cid][$langcode][$operation] = (bool) $access; } /** @@ -143,4 +173,75 @@ public function resetCache() { $this->accessCache = array(); } + /** + * {@inheritdoc} + */ + public function createAccess($entity_bundle = NULL, AccountInterface $account = NULL, array $context = array()) { + $account = $this->prepareUser($account); + $context += array( + 'langcode' => Language::LANGCODE_DEFAULT, + ); + + $cid = $entity_bundle ? 'create:' . $entity_bundle : 'create'; + if (($access = $this->getCache($cid, 'create', $context['langcode'], $account)) !== NULL) { + // Cache hit, no work necessary. + 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. + + // 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']); + + if (($return = $this->processAccessHookResults($access)) === NULL) { + // No module had an opinion about the access, so let's the access + // controller check create access. + $return = (bool) $this->checkCreateAccess($account, $context, $entity_bundle); + } + return $this->setCache($return, $cid, 'create', $context['langcode'], $account); + } + + /** + * Performs create access checks. + * + * This method is supposed to be overwritten by extending classes that + * do their own custom access checking. + * + * @param \Drupal\Core\Session\AccountInterface $account + * The user for which to check access. + * @param array $context + * An array of key-value pairs to pass additional context when needed. + * @param string|null $entity_bundle + * (optional) The bundle of the entity. Required if the entity supports + * bundles, defaults to NULL otherwise. + * + * @return bool|null + * TRUE if access was granted, FALSE if access was denied and NULL if access + * could not be determined. + */ + protected function checkCreateAccess(AccountInterface $account, array $context, $entity_bundle = NULL) { + return NULL; + } + + /** + * Loads the current account object, if it does not exist yet. + * + * @param \Drupal\Core\Session\AccountInterface $account + * The account interface instance. + * + * @return \Drupal\Core\Session\AccountInterface + * Returns the current account object. + */ + protected function prepareUser(AccountInterface $account = NULL) { + if (!$account) { + $account = $GLOBALS['user']; + } + return $account; + } + } diff --git a/core/lib/Drupal/Core/Entity/EntityAccessControllerInterface.php b/core/lib/Drupal/Core/Entity/EntityAccessControllerInterface.php index f7b4348..c0296dd 100644 --- a/core/lib/Drupal/Core/Entity/EntityAccessControllerInterface.php +++ b/core/lib/Drupal/Core/Entity/EntityAccessControllerInterface.php @@ -18,11 +18,14 @@ /** * Checks access to an operation on a given entity or entity translation. * + * Use \Drupal\Core\Entity\EntityAccessControllerInterface::createAccess() + * to check access to create an entity. + * * @param \Drupal\Core\Entity\EntityInterface $entity * The entity for which to check access. * @param string $operation * The operation access should be checked for. - * Usually one of "view", "create", "update" or "delete". + * Usually one of "view", "update" or "delete". * @param string $langcode * (optional) The language code for which to check access. Defaults to * Language::LANGCODE_DEFAULT. @@ -36,6 +39,21 @@ public function access(EntityInterface $entity, $operation, $langcode = Language::LANGCODE_DEFAULT, AccountInterface $account = NULL); /** + * Checks access to create an entity. + * + * @param string $entity_bundle + * (optional) The bundle of the entity. Required if the entity supports + * bundles, defaults to NULL otherwise. + * @param \Drupal\Core\Session\AccountInterface $account + * (optional) The user session for which to check access, or NULL to check + * access for the current user. Defaults to NULL. + * @param array $context + * (optional) An array of key-value pairs to pass additional context when + * needed. + */ + public function createAccess($entity_bundle = NULL, AccountInterface $account = NULL, array $context = array()); + + /** * Clears all cached access checks. */ public function resetCache(); diff --git a/core/lib/Drupal/Core/Entity/EntityCreateAccessCheck.php b/core/lib/Drupal/Core/Entity/EntityCreateAccessCheck.php index 2cce92a..db6f991 100644 --- a/core/lib/Drupal/Core/Entity/EntityCreateAccessCheck.php +++ b/core/lib/Drupal/Core/Entity/EntityCreateAccessCheck.php @@ -52,35 +52,7 @@ public function applies(Route $route) { */ public function access(Route $route, Request $request) { list($entity_type, $bundle) = explode(':', $route->getRequirement($this->requirementsKey) . ':'); - - $definition = $this->entityManager->getDefinition($entity_type); - - $values = $this->prepareEntityValues($definition, $request, $bundle); - $entity = $this->entityManager->getStorageController($entity_type) - ->create($values); - - return $this->entityManager->getAccessController($entity_type)->access($entity, 'create'); - } - - /** - * Prepare the values passed into the storage controller. - * - * @param array $definition - * The entity type definition. - * @param \Symfony\Component\HttpFoundation\Request $request - * The request object. - * @param string $bundle - * (optional) The bundle to check access for. - * - * @return array - * An array of values to be used when creating the entity. - */ - protected function prepareEntityValues(array $definition, Request $request, $bundle = NULL) { - $values = array(); - if ($bundle && isset($definition['entity_keys']['bundle'])) { - $values[$definition['entity_keys']['bundle']] = $bundle; - } - return $values; + return $this->entityManager->getAccessController($entity_type)->createAccess($bundle); } } diff --git a/core/lib/Drupal/Core/Entity/EntityNG.php b/core/lib/Drupal/Core/Entity/EntityNG.php index a6768e8..62b5bfb 100644 --- a/core/lib/Drupal/Core/Entity/EntityNG.php +++ b/core/lib/Drupal/Core/Entity/EntityNG.php @@ -413,6 +413,11 @@ public function isEmpty() { * {@inheritdoc} */ public function access($operation = 'view', AccountInterface $account = NULL) { + if ($operation == 'create') { + return \Drupal::entityManager() + ->getAccessController($this->entityType) + ->createAccess($this->bundle(), $account); + } return \Drupal::entityManager() ->getAccessController($this->entityType) ->access($this, $operation, $this->activeLangcode, $account); diff --git a/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockAccessController.php b/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockAccessController.php index 8ac282a..9990a2e 100644 --- a/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockAccessController.php +++ b/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockAccessController.php @@ -23,9 +23,16 @@ protected function checkAccess(EntityInterface $entity, $operation, $langcode, A if ($operation === 'view') { return TRUE; } - elseif (in_array($operation, array('create', 'update', 'delete'))) { + elseif (in_array($operation, array('update', 'delete'))) { return user_access('administer blocks', $account); } } + /** + * {@inheritdoc} + */ + protected function checkCreateAccess(AccountInterface $account, array $context, $entity_bundle = NULL) { + return user_access('administer blocks', $account); + } + } diff --git a/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockTypeAccessController.php b/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockTypeAccessController.php index 3aa95ce..95b74ac 100644 --- a/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockTypeAccessController.php +++ b/core/modules/block/custom_block/lib/Drupal/custom_block/CustomBlockTypeAccessController.php @@ -23,9 +23,16 @@ protected function checkAccess(EntityInterface $entity, $operation, $langcode, A if ($operation === 'view') { return TRUE; } - elseif (in_array($operation, array('create', 'update', 'delete'))) { + elseif (in_array($operation, array('update', 'delete'))) { return user_access('administer blocks', $account); } } + /** + * {@inheritdoc} + */ + protected function checkCreateAccess(AccountInterface $account, array $context, $entity_bundle = NULL) { + return user_access('administer blocks', $account); + } + } diff --git a/core/modules/comment/lib/Drupal/comment/CommentAccessController.php b/core/modules/comment/lib/Drupal/comment/CommentAccessController.php index da728d5..98e03e1 100644 --- a/core/modules/comment/lib/Drupal/comment/CommentAccessController.php +++ b/core/modules/comment/lib/Drupal/comment/CommentAccessController.php @@ -27,10 +27,6 @@ protected function checkAccess(EntityInterface $entity, $operation, $langcode, A return user_access('access comments', $account); break; - case 'create': - return user_access('post comments', $account); - break; - case 'update': return ($account->id() && $account->id() == $entity->uid->value && $entity->status->value == COMMENT_PUBLISHED && user_access('edit own comments', $account)) || user_access('administer comments', $account); break; @@ -45,4 +41,11 @@ protected function checkAccess(EntityInterface $entity, $operation, $langcode, A } } + /** + * {@inheritdoc} + */ + protected function checkCreateAccess(AccountInterface $account, array $context, $entity_bundle = NULL) { + return user_access('post comments', $account); + } + } diff --git a/core/modules/config/tests/config_test/lib/Drupal/config_test/ConfigTestAccessController.php b/core/modules/config/tests/config_test/lib/Drupal/config_test/ConfigTestAccessController.php index cde6f41..f084453 100644 --- a/core/modules/config/tests/config_test/lib/Drupal/config_test/ConfigTestAccessController.php +++ b/core/modules/config/tests/config_test/lib/Drupal/config_test/ConfigTestAccessController.php @@ -24,4 +24,11 @@ public function access(EntityInterface $entity, $operation, $langcode = Language return TRUE; } + /** + * {@inheritdoc} + */ + protected function checkCreateAccess(AccountInterface $account, array $context, $entity_bundle = NULL) { + return TRUE; + } + } diff --git a/core/modules/filter/lib/Drupal/filter/FilterFormatAccessController.php b/core/modules/filter/lib/Drupal/filter/FilterFormatAccessController.php index 133c309..1242b94 100644 --- a/core/modules/filter/lib/Drupal/filter/FilterFormatAccessController.php +++ b/core/modules/filter/lib/Drupal/filter/FilterFormatAccessController.php @@ -36,4 +36,11 @@ protected function checkAccess(EntityInterface $entity, $operation, $langcode, A return !empty($permission) && user_access($permission, $account); } + /** + * {@inheritdoc} + */ + protected function checkCreateAccess(AccountInterface $account, array $context, $entity_bundle = NULL) { + return user_access('administer filters', $account); + } + } diff --git a/core/modules/menu/lib/Drupal/menu/MenuAccessController.php b/core/modules/menu/lib/Drupal/menu/MenuAccessController.php index 4cb2962..b7128c0 100644 --- a/core/modules/menu/lib/Drupal/menu/MenuAccessController.php +++ b/core/modules/menu/lib/Drupal/menu/MenuAccessController.php @@ -31,9 +31,16 @@ protected function checkAccess(EntityInterface $entity, $operation, $langcode, A } } - if (in_array($operation, array('create', 'update', 'delete'))) { + if (in_array($operation, array('update', 'delete'))) { return user_access('administer menu', $account); } } + /** + * {@inheritdoc} + */ + protected function checkCreateAccess(AccountInterface $account, array $context, $entity_bundle = NULL) { + return user_access('administer menu', $account); + } + } diff --git a/core/modules/node/lib/Drupal/node/NodeAccessController.php b/core/modules/node/lib/Drupal/node/NodeAccessController.php index c0106a7..2556d76 100644 --- a/core/modules/node/lib/Drupal/node/NodeAccessController.php +++ b/core/modules/node/lib/Drupal/node/NodeAccessController.php @@ -41,12 +41,17 @@ class NodeAccessController extends EntityAccessController implements NodeAccessC /** * Constructs a NodeAccessController object. * + * @param string $entity_type + * The entity type of the access controller instance. * @param \Drupal\node\NodeGrantDatabaseStorageInterface $grant_storage * The node grant storage. + * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler + * The module handler to invoke the alter hook with. */ - public function __construct(NodeGrantDatabaseStorageInterface $grant_storage, ModuleHandlerInterface $module_handler) { - $this->grantStorage = $grant_storage; - $this->moduleHandler = $module_handler; + public function __construct($entity_type, NodeGrantDatabaseStorageInterface $grant_storage, ModuleHandlerInterface $module_handler) { + parent::__construct($entity_type); + $this->grantStorage = $grant_storage; + $this->moduleHandler = $module_handler; } /** @@ -54,6 +59,7 @@ public function __construct(NodeGrantDatabaseStorageInterface $grant_storage, Mo */ public static function createInstance(ContainerInterface $container, $entity_type, array $entity_info) { return new static( + $entity_type, $container->get('node.grant_storage'), $container->get('module_handler') ); @@ -76,6 +82,22 @@ public function access(EntityInterface $entity, $operation, $langcode = Language /** * {@inheritdoc} */ + public function createAccess($entity_bundle = NULL, AccountInterface $account = NULL, array $context = array()) { + $account = $this->prepareUser($account); + + if (user_access('bypass node access', $account)) { + return TRUE; + } + if (!user_access('access content', $account)) { + return FALSE; + } + + return parent::createAccess($entity_bundle, $account, $context); + } + + /** + * {@inheritdoc} + */ protected function checkAccess(EntityInterface $node, $operation, $langcode, AccountInterface $account) { // Fetch information from the node object if possible. $status = isset($node->status) ? $node->status : NULL; @@ -110,6 +132,16 @@ protected function checkAccess(EntityInterface $node, $operation, $langcode, Acc /** * {@inheritdoc} */ + protected function checkCreateAccess(AccountInterface $account, array $context, $entity_bundle = NULL) { + $configured_types = node_permissions_get_configured_types(); + if (isset($configured_types[$entity_bundle])) { + return user_access('create ' . $entity_bundle . ' content', $account); + } + } + + /** + * {@inheritdoc} + */ public function acquireGrants(NodeInterface $node) { $grants = $this->moduleHandler->invokeAll('node_access_records', array($node)); // Let modules alter the grants. diff --git a/core/modules/node/lib/Drupal/node/NodeTypeAccessController.php b/core/modules/node/lib/Drupal/node/NodeTypeAccessController.php index 40327e3..55238a6 100644 --- a/core/modules/node/lib/Drupal/node/NodeTypeAccessController.php +++ b/core/modules/node/lib/Drupal/node/NodeTypeAccessController.php @@ -28,4 +28,11 @@ protected function checkAccess(EntityInterface $entity, $operation, $langcode, A return user_access('administer content types', $account); } + /** + * {@inheritdoc} + */ + protected function checkCreateAccess(AccountInterface $account, array $context, $entity_bundle = NULL) { + return user_access('administer content types', $account); + } + } diff --git a/core/modules/node/node.module b/core/modules/node/node.module index 293c64e..45f19c7 100644 --- a/core/modules/node/node.module +++ b/core/modules/node/node.module @@ -2028,11 +2028,19 @@ function node_form_system_themes_admin_form_submit($form, &$form_state) { * @see node_menu() */ function node_access($op, $node, $account = NULL, $langcode = NULL) { - if (!$node instanceof EntityInterface) { - $node = entity_create('node', array('type' => $node)); - } - elseif ($node instanceof NodeTypeInterface) { - $node = entity_create('node', array('type' => $node->id())); + $access_controller = Drupal::entityManager()->getAccessController('node'); + + if ($op == 'create') { + if (!$node instanceof EntityInterface) { + $bundle = $node; + } + elseif ($node instanceof NodeTypeInterface) { + $bundle = $node->id(); + } + else { + $bundle = $node->bundle(); + } + return $access_controller->createAccess($bundle, $account, array('langcode' => $langcode)); } // If no language code was provided, default to the node's langcode. @@ -2051,14 +2059,7 @@ function node_access($op, $node, $account = NULL, $langcode = NULL) { } } } - - // Make sure that if an account is passed, that it is a fully loaded user - // object. - if ($account && !($account instanceof UserInterface)) { - $account = user_load($account->id()); - } - - return Drupal::entityManager()->getAccessController('node')->access($node, $op, $langcode, $account); + return $access_controller->access($node, $op, $langcode, $account); } /** diff --git a/core/modules/picture/lib/Drupal/picture/PictureMappingAccessController.php b/core/modules/picture/lib/Drupal/picture/PictureMappingAccessController.php index 5ee0ade..2696100 100644 --- a/core/modules/picture/lib/Drupal/picture/PictureMappingAccessController.php +++ b/core/modules/picture/lib/Drupal/picture/PictureMappingAccessController.php @@ -23,9 +23,16 @@ protected function checkAccess(EntityInterface $entity, $operation, $langcode, A if ($operation === 'view') { return TRUE; } - elseif (in_array($operation, array('create', 'update', 'delete'))) { + elseif (in_array($operation, array('update', 'delete'))) { return user_access('administer pictures', $account); } } + /** + * {@inheritdoc} + */ + protected function checkCreateAccess(AccountInterface $account, array $context, $entity_bundle = NULL) { + return user_access('administer pictures', $account); + } + } diff --git a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/EntityTestAccessController.php b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/EntityTestAccessController.php index c2b5594..034caa3 100644 --- a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/EntityTestAccessController.php +++ b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/EntityTestAccessController.php @@ -27,9 +27,16 @@ protected function checkAccess(EntityInterface $entity, $operation, $langcode, A } return user_access('view test entity', $account); } - elseif (in_array($operation, array('create', 'update', 'delete'))) { + elseif (in_array($operation, array('update', 'delete'))) { return user_access('administer entity_test content', $account); } } + /** + * {@inheritdoc} + */ + protected function checkCreateAccess(AccountInterface $account, array $context, $entity_bundle = NULL) { + return user_access('administer entity_test content', $account); + } + } diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Access/TaxonomyTermCreateAccess.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Access/TaxonomyTermCreateAccess.php index dbf7d06..b6305e6 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/Access/TaxonomyTermCreateAccess.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Access/TaxonomyTermCreateAccess.php @@ -9,6 +9,7 @@ use Drupal\Core\Entity\EntityCreateAccessCheck; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\Routing\Route; /** * Provides an access check for taxonomy term creation. @@ -23,12 +24,12 @@ class TaxonomyTermCreateAccess extends EntityCreateAccessCheck { /** * {@inheritdoc} */ - protected function prepareEntityValues(array $definition, Request $request, $bundle = NULL) { - $values = array(); + public function access(Route $route, Request $request) { + $entity_type = $route->getRequirement($this->requirementsKey); if ($vocabulary = $request->attributes->get('taxonomy_vocabulary')) { - $values = parent::prepareEntityValues($definition, $request, $vocabulary->id()); + return $this->entityManager->getAccessController($entity_type)->createAccess($vocabulary->id()); } - return $values; + return parent::access($route, $request); } } diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/TermAccessController.php b/core/modules/taxonomy/lib/Drupal/taxonomy/TermAccessController.php index d562e84..d945ef5 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/TermAccessController.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/TermAccessController.php @@ -27,10 +27,6 @@ protected function checkAccess(EntityInterface $entity, $operation, $langcode, A return user_access('access content', $account); break; - case 'create': - return user_access('administer taxonomy', $account); - break; - case 'update': return user_access("edit terms in {$entity->bundle()}", $account) || user_access('administer taxonomy', $account); break; @@ -41,4 +37,11 @@ protected function checkAccess(EntityInterface $entity, $operation, $langcode, A } } + /** + * {@inheritdoc} + */ + protected function checkCreateAccess(AccountInterface $account, array $context, $entity_bundle = NULL) { + return user_access('administer taxonomy', $account); + } + } diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyAccessController.php b/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyAccessController.php index 0750593..ac5ebe9 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyAccessController.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/VocabularyAccessController.php @@ -25,4 +25,11 @@ protected function checkAccess(EntityInterface $entity, $operation, $langcode, A return user_access('administer taxonomy', $account); } + /** + * {@inheritdoc} + */ + protected function checkCreateAccess(AccountInterface $account, array $context, $entity_bundle = NULL) { + return user_access('administer taxonomy', $account); + } + } diff --git a/core/modules/translation/translation.module b/core/modules/translation/translation.module index 993cf13..562f0b2 100644 --- a/core/modules/translation/translation.module +++ b/core/modules/translation/translation.module @@ -121,14 +121,14 @@ function translation_permission() { } /** - * Implements hook_node_access(). + * Implements hook_node_create_access(). */ -function translation_node_access($node, $op, $account, $langcode) { +function translation_node_create_access($account) { $query = Drupal::request()->query; $translation = $query->get('translation'); $target = $query->get('target'); $request_has_translation_arg = !empty($translation) && !empty($target) && is_numeric($translation); - if ($op == 'create' && $request_has_translation_arg) { + if ($request_has_translation_arg) { $source_node = node_load($translation); if (empty($source_node) || !translation_user_can_translate_node($source_node, $account)){ return NODE_ACCESS_DENY; diff --git a/core/modules/user/lib/Drupal/user/RoleAccessController.php b/core/modules/user/lib/Drupal/user/RoleAccessController.php index 13afa61..e98c540 100644 --- a/core/modules/user/lib/Drupal/user/RoleAccessController.php +++ b/core/modules/user/lib/Drupal/user/RoleAccessController.php @@ -31,4 +31,11 @@ protected function checkAccess(EntityInterface $entity, $operation, $langcode, A } } + /** + * {@inheritdoc} + */ + protected function checkCreateAccess(AccountInterface $account, array $context, $entity_bundle = NULL) { + return user_access('administer permissions', $account); + } + } diff --git a/core/modules/user/lib/Drupal/user/UserAccessController.php b/core/modules/user/lib/Drupal/user/UserAccessController.php index fd46efa..e6f6ed6 100644 --- a/core/modules/user/lib/Drupal/user/UserAccessController.php +++ b/core/modules/user/lib/Drupal/user/UserAccessController.php @@ -25,10 +25,6 @@ protected function checkAccess(EntityInterface $entity, $operation, $langcode, A return $this->viewAccess($entity, $langcode, $account); break; - case 'create': - return user_access('administer users', $account); - break; - case 'update': // Users can always edit their own account. Users with the 'administer // users' permission can edit any account except the anonymous account. @@ -45,6 +41,13 @@ protected function checkAccess(EntityInterface $entity, $operation, $langcode, A } /** + * {@inheritdoc} + */ + protected function checkCreateAccess(AccountInterface $account, array $context, $entity_bundle = NULL) { + return user_access('administer users', $account); + } + + /** * Check view access. * * See EntityAccessControllerInterface::view() for parameters. diff --git a/core/modules/views/lib/Drupal/views/ViewAccessController.php b/core/modules/views/lib/Drupal/views/ViewAccessController.php index a4aaae6..80ad8a9 100644 --- a/core/modules/views/lib/Drupal/views/ViewAccessController.php +++ b/core/modules/views/lib/Drupal/views/ViewAccessController.php @@ -24,4 +24,11 @@ public function access(EntityInterface $entity, $operation, $langcode = Language return $operation == 'view' || user_access('administer views', $account); } + /** + * {@inheritdoc} + */ + protected function checkCreateAccess(AccountInterface $account, array $context, $entity_bundle = NULL) { + return user_access('administer views', $account); + } + } diff --git a/core/tests/Drupal/Tests/Core/Entity/EntityCreateAccessCheckTest.php b/core/tests/Drupal/Tests/Core/Entity/EntityCreateAccessCheckTest.php index 0d4689e..23819dd 100644 --- a/core/tests/Drupal/Tests/Core/Entity/EntityCreateAccessCheckTest.php +++ b/core/tests/Drupal/Tests/Core/Entity/EntityCreateAccessCheckTest.php @@ -100,28 +100,13 @@ public function testAccess($entity_bundle, $requirement, $access, $expected) { ->disableOriginalConstructor() ->getMock(); - $entity_manager->expects($this->any()) - ->method('getDefinition') - ->with($this->equalTo('entity_test')) - ->will($this->returnValue(array('entity_keys' => array('bundle' => 'type')))); - - $storage_controller = $this->getMock('Drupal\Core\Entity\EntityStorageControllerInterface'); - $values = $entity_bundle ? array('type' => $entity_bundle) : array(); - $storage_controller->expects($this->any()) - ->method('create') - ->with($this->equalTo($values)) - ->will($this->returnValue($entity)); - $access_controller = $this->getMock('Drupal\Core\Entity\EntityAccessControllerInterface'); $access_controller->expects($this->once()) - ->method('access') - ->with($entity, 'create') + ->method('createAccess') + ->with($entity_bundle) ->will($this->returnValue($access)); $entity_manager->expects($this->any()) - ->method('getStorageController') - ->will($this->returnValue($storage_controller)); - $entity_manager->expects($this->any()) ->method('getAccessController') ->will($this->returnValue($access_controller));