diff --git a/core/lib/Drupal/Core/Entity/EntityCreateAccessCheck.php b/core/lib/Drupal/Core/Entity/EntityCreateAccessCheck.php index 7f8e1a7..5314e7a 100644 --- a/core/lib/Drupal/Core/Entity/EntityCreateAccessCheck.php +++ b/core/lib/Drupal/Core/Entity/EntityCreateAccessCheck.php @@ -52,6 +52,19 @@ public function appliesTo() { */ public function access(Route $route, Request $request) { list($entity_type, $bundle) = explode(':', $route->getRequirement($this->requirementsKey) . ':'); + + // The bundle argument can contain request argument placeholders like + // {name}, loop over the raw variables and attempt to replace them in the + // bundle name. If a placeholder does not exist, it won't get replaced. + if ($bundle && strpos($bundle, '{') !== FALSE) { + foreach ($request->get('_raw_variables')->all() as $name => $value) { + $bundle = str_replace('{' . $name . '}', $value, $bundle); + } + // If we were unable to replace all placeholders, deny access. + if (strpos($bundle, '{') !== FALSE) { + return static::DENY; + } + } return $this->entityManager->getAccessController($entity_type)->createAccess($bundle) ? static::ALLOW : static::DENY; } diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Access/TaxonomyTermCreateAccess.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Access/TaxonomyTermCreateAccess.php deleted file mode 100644 index db620cb..0000000 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/Access/TaxonomyTermCreateAccess.php +++ /dev/null @@ -1,35 +0,0 @@ -getRequirement($this->requirementsKey); - if ($vocabulary = $request->attributes->get('taxonomy_vocabulary')) { - return $this->entityManager->getAccessController($entity_type)->createAccess($vocabulary->id()) ? static::ALLOW : static::DENY; - } - return parent::access($route, $request); - } - -} diff --git a/core/modules/taxonomy/taxonomy.routing.yml b/core/modules/taxonomy/taxonomy.routing.yml index 0245c19..2e154cf 100644 --- a/core/modules/taxonomy/taxonomy.routing.yml +++ b/core/modules/taxonomy/taxonomy.routing.yml @@ -10,7 +10,7 @@ taxonomy_term_add: defaults: _content: '\Drupal\taxonomy\Controller\TaxonomyController::addForm' requirements: - _access_taxonomy_term_create: 'taxonomy_term' + _entity_create_access: 'taxonomy_term:{taxonomy_vocabulary}' taxonomy_term_edit: pattern: '/taxonomy/term/{taxonomy_term}/edit' diff --git a/core/modules/taxonomy/taxonomy.services.yml b/core/modules/taxonomy/taxonomy.services.yml deleted file mode 100644 index 265eb5d..0000000 --- a/core/modules/taxonomy/taxonomy.services.yml +++ /dev/null @@ -1,6 +0,0 @@ -services: - access_check.taxonomy_term.create: - class: Drupal\taxonomy\Access\TaxonomyTermCreateAccess - arguments: ['@plugin.manager.entity'] - tags: - - { name: access_check } diff --git a/core/tests/Drupal/Tests/Core/Entity/EntityCreateAccessCheckTest.php b/core/tests/Drupal/Tests/Core/Entity/EntityCreateAccessCheckTest.php index d5f50d0..ad091b8 100644 --- a/core/tests/Drupal/Tests/Core/Entity/EntityCreateAccessCheckTest.php +++ b/core/tests/Drupal/Tests/Core/Entity/EntityCreateAccessCheckTest.php @@ -10,6 +10,7 @@ use Drupal\Core\Access\AccessCheckInterface; use Drupal\Core\Entity\EntityCreateAccessCheck; use Drupal\Tests\UnitTestCase; +use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; use Symfony\Component\HttpFoundation\Request; /** @@ -65,6 +66,12 @@ public function providerTestAccess() { array('', 'entity_test',TRUE, AccessCheckInterface::ALLOW), array('test_entity', 'entity_test:test_entity', TRUE, AccessCheckInterface::ALLOW), array('test_entity', 'entity_test:test_entity', FALSE, AccessCheckInterface::DENY), + array('test_entity', 'entity_test:{bundle_argument}', TRUE, AccessCheckInterface::ALLOW), + array('test_entity', 'entity_test:{bundle_argument}', FALSE, AccessCheckInterface::DENY), + array('', 'entity_test:{bundle_argument}', FALSE, AccessCheckInterface::DENY), + // When the bundle is not provided, access should be denied even if the + // access controller would allow access. + array('', 'entity_test:{bundle_argument}', TRUE, AccessCheckInterface::DENY), ); } @@ -74,23 +81,23 @@ public function providerTestAccess() { * @dataProvider providerTestAccess */ public function testAccess($entity_bundle, $requirement, $access, $expected) { - $entity = $this->getMockBuilder('Drupal\Core\Entity\Entity') - ->disableOriginalConstructor() - ->getMock(); - $entity_manager = $this->getMockBuilder('Drupal\Core\Entity\EntityManager') ->disableOriginalConstructor() ->getMock(); - $access_controller = $this->getMock('Drupal\Core\Entity\EntityAccessControllerInterface'); - $access_controller->expects($this->once()) - ->method('createAccess') - ->with($entity_bundle) - ->will($this->returnValue($access)); + // Don't expect a call to the access controller when we have a bundle + // argument requirement but no bundle is provided. + if ($entity_bundle || strpos($requirement, '{') === FALSE) { + $access_controller = $this->getMock('Drupal\Core\Entity\EntityAccessControllerInterface'); + $access_controller->expects($this->once()) + ->method('createAccess') + ->with($entity_bundle) + ->will($this->returnValue($access)); - $entity_manager->expects($this->any()) - ->method('getAccessController') - ->will($this->returnValue($access_controller)); + $entity_manager->expects($this->any()) + ->method('getAccessController') + ->will($this->returnValue($access_controller)); + } $applies_check = new EntityCreateAccessCheck($entity_manager); @@ -103,6 +110,13 @@ public function testAccess($entity_bundle, $requirement, $access, $expected) { ->will($this->returnValue($requirement)); $request = new Request(); + $raw_variables = new ParameterBag(); + if ($entity_bundle) { + // Add the bundle as a raw variable and an upcasted attribute. + $request->attributes->set('bundle_argument', new \stdClass()); + $raw_variables->set('bundle_argument', $entity_bundle); + } + $request->attributes->set('_raw_variables', $raw_variables); $this->assertEquals($expected, $applies_check->access($route, $request)); }