diff --git a/core/lib/Drupal/Core/Access/CustomAccessCheck.php b/core/lib/Drupal/Core/Access/CustomAccessCheck.php index e7a3b08..353d09c 100644 --- a/core/lib/Drupal/Core/Access/CustomAccessCheck.php +++ b/core/lib/Drupal/Core/Access/CustomAccessCheck.php @@ -61,7 +61,14 @@ public function __construct(ControllerResolverInterface $controller_resolver, Ac * The access result. */ public function access(Route $route, RouteMatchInterface $route_match, AccountInterface $account) { - $callable = $this->controllerResolver->getControllerFromDefinition($route->getRequirement('_custom_access')); + try { + $callable = $this->controllerResolver->getControllerFromDefinition($route->getRequirement('_custom_access')); + } + catch (\InvalidArgumentException $e) { + // The custom access controller method was not found. + throw new \BadMethodCallException(sprintf('The "%s" method is not callable as a _custom_access callback in route "%s"', $route->getRequirement('_custom_access'), $route->getPath())); + } + $arguments_resolver = $this->argumentsResolverFactory->getArgumentsResolver($route_match, $account); $arguments = $arguments_resolver->getArguments($callable); diff --git a/core/tests/Drupal/Tests/Core/Access/CustomAccessCheckTest.php b/core/tests/Drupal/Tests/Core/Access/CustomAccessCheckTest.php index 36d330d..3aa682c 100644 --- a/core/tests/Drupal/Tests/Core/Access/CustomAccessCheckTest.php +++ b/core/tests/Drupal/Tests/Core/Access/CustomAccessCheckTest.php @@ -9,8 +9,12 @@ use Drupal\Core\Access\AccessResult; use Drupal\Core\Access\CustomAccessCheck; +use Drupal\Core\Controller\ControllerResolver; use Drupal\Tests\UnitTestCase; use Symfony\Component\Routing\Route; +use Symfony\Bridge\PsrHttpMessage\Factory\DiactorosFactory; +use Drupal\Core\DependencyInjection\ClassResolver; +use Symfony\Component\DependencyInjection\ContainerBuilder; /** * @coversDefaultClass \Drupal\Core\Access\CustomAccessCheck @@ -106,6 +110,28 @@ public function testAccess() { $this->assertEquals(AccessResult::allowed(), $this->accessChecker->access($route, $route_match, $account)); } + /* + * Test that the access method throws an exception for invalid access callbacks. + */ + public function testAccessException() { + + $this->setExpectedException('\BadMethodCallException'); + + $container = new ContainerBuilder(); + $class_resolver = new ClassResolver(); + $class_resolver->setContainer($container); + $httpMessageFactory = new DiactorosFactory(); + $controllerResolver = new ControllerResolver($httpMessageFactory, $class_resolver); + + $this->argumentsResolverFactory = $this->getMock('Drupal\Core\Access\AccessArgumentsResolverFactoryInterface'); + $this->accessChecker = new CustomAccessCheck($controllerResolver, $this->argumentsResolverFactory); + + $route = new Route('/test-route', array(), array('_custom_access' => '\Drupal\Tests\Core\Access\NonExistantController::nonexistantmethod')); + $route_match = $this->getMock('Drupal\Core\Routing\RouteMatchInterface'); + $account = $this->getMock('Drupal\Core\Session\AccountInterface'); + + $this->accessChecker->access($route, $route_match, $account); + } } class TestController {