diff --git a/core/lib/Drupal/Core/CoreBundle.php b/core/lib/Drupal/Core/CoreBundle.php index 35b1b6d..d637f90 100644 --- a/core/lib/Drupal/Core/CoreBundle.php +++ b/core/lib/Drupal/Core/CoreBundle.php @@ -255,6 +255,8 @@ public function build(ContainerBuilder $container) { ->addTag('event_subscriber'); $container->register('access_check.default', 'Drupal\Core\Access\DefaultAccessCheck') ->addTag('access_check'); + $container->register('access_check.entity', 'Drupal\Core\Entity\EntityAccessCheck') + ->addTag('access_check'); $container->register('maintenance_mode_subscriber', 'Drupal\Core\EventSubscriber\MaintenanceModeSubscriber') ->addTag('event_subscriber'); $container->register('path_subscriber', 'Drupal\Core\EventSubscriber\PathSubscriber') diff --git a/core/lib/Drupal/Core/Entity/EntityAccessCheck.php b/core/lib/Drupal/Core/Entity/EntityAccessCheck.php new file mode 100644 index 0000000..029d6e1 --- /dev/null +++ b/core/lib/Drupal/Core/Entity/EntityAccessCheck.php @@ -0,0 +1,53 @@ +getRequirements()); + } + + /** + * Implements \Drupal\Core\Access\AccessCheckInterface::access(). + * + * The value of the '_entity_access' key must be in the pattern + * 'slug.operation.' The slug corresponds to the named param {slug}. + * This will check a node for 'update' access: + * @code + * pattern: '/foo/{node}/bar' + * requirements: + * _entity_access: 'node.update' + * @endcode + */ + public function access(Route $route, Request $request) { + $requirements = $route->getRequirements(); + // Split the slug and the operation. + list($slug, $operation) = $route->getRequirement('_entity_access'); + + // If this slug is in the request, and it is an entity, check its access. + if ($request->attributes->has($slug)) { + $entity = $request->attributes->get($slug); + if ($entity instanceof EntityInterface) { + return $entity->access($operation); + } + } + } + +} diff --git a/core/modules/system/tests/modules/entity_test/entity_test.routing.yml b/core/modules/system/tests/modules/entity_test/entity_test.routing.yml new file mode 100644 index 0000000..fcb7ea4 --- /dev/null +++ b/core/modules/system/tests/modules/entity_test/entity_test.routing.yml @@ -0,0 +1,6 @@ +entity_test_access: + pattern: '/entity_test/{entity_test}/delete' + defaults: + _content: 'Drupal\entity_test\Controller\EntityTestController::deletePage' + requirements: + _entity_access: 'entity_test.delete' diff --git a/core/tests/Drupal/Tests/Core/Entity/EntityAccessCheckTest.php b/core/tests/Drupal/Tests/Core/Entity/EntityAccessCheckTest.php new file mode 100644 index 0000000..d773fad --- /dev/null +++ b/core/tests/Drupal/Tests/Core/Entity/EntityAccessCheckTest.php @@ -0,0 +1,71 @@ + 'Entity access check test', + 'description' => 'Unit test of entity access checking system.', + 'group' => 'Entity' + ); + } + + /** + * Tests the method for checking if the access check applies to a route. + */ + public function testApplies() { + $applies_check = new EntityAccessCheck(); + + $route = $this->getMockBuilder('Symfony\Component\Routing\Route') + ->disableOriginalConstructor() + ->getMock(); + $route->expects($this->any()) + ->method('getRequirements') + ->will($this->returnValue(array('_entity_access' => ''))); + $res = $applies_check->applies($route); + $this->assertEquals(TRUE, $res); + + $route = $this->getMockBuilder('Symfony\Component\Routing\Route') + ->disableOriginalConstructor() + ->getMock(); + $route->expects($this->any()) + ->method('getRequirements') + ->will($this->returnValue(array())); + $res = $applies_check->applies($route); + $this->assertEquals(FALSE, $res); + } + + + /** + * Tests the method for checking access to routes. + */ + public function testAccess() { + $args = array('/foo', array(), array('_entity_access' => 'node.update')); + $route = $this->getMockBuilder('Symfony\Component\Routing\Route') + ->setConstructorArgs($args) + ->getMock(); + $request = $this->getMockBuilder('Symfony\Component\HttpFoundation\Request') + ->disableOriginalConstructor() + ->getMock(); + $access_check = new EntityAccessCheck(); + $operation = $access_check->access($route, $request); + $this->assertEquals(TRUE, $operation); + } +} +