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..b1e7629 100644 --- a/core/tests/Drupal/Tests/Core/Access/CustomAccessCheckTest.php +++ b/core/tests/Drupal/Tests/Core/Access/CustomAccessCheckTest.php @@ -7,9 +7,16 @@ namespace Drupal\Tests\Core\Access; +use Drupal\Core\Access\AccessArgumentsResolverFactoryInterface; use Drupal\Core\Access\AccessResult; use Drupal\Core\Access\CustomAccessCheck; +use Drupal\Core\Controller\ControllerResolver; +use Drupal\Core\Routing\RouteMatchInterface; +use Drupal\Core\Session\AccountInterface; +use Drupal\Core\DependencyInjection\ClassResolver; use Drupal\Tests\UnitTestCase; +use Symfony\Bridge\PsrHttpMessage\Factory\DiactorosFactory; +use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\Routing\Route; /** @@ -106,6 +113,28 @@ public function testAccess() { $this->assertEquals(AccessResult::allowed(), $this->accessChecker->access($route, $route_match, $account)); } + /* + * Test the access method exception for invalid access callbacks. + */ + public function testAccessException() { + + $container = new ContainerBuilder(); + $class_resolver = new ClassResolver(); + $class_resolver->setContainer($container); + $httpMessageFactory = new DiactorosFactory(); + $controllerResolver = new ControllerResolver($httpMessageFactory, $class_resolver); + + $this->argumentsResolverFactory = $this->getMock(AccessArgumentsResolverFactoryInterface::class); + $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(RouteMatchInterface::class); + $account = $this->getMock(AccountInterface::class); + + $this->setExpectedException(\BadMethodCallException::class); + + $this->accessChecker->access($route, $route_match, $account); + } } class TestController {