Unverified Commit 7c1de1ef authored by alexpott's avatar alexpott

Issue #2405241 by philipnorton42, jibran, dawehner, andrewmacpherson: Add...

Issue #2405241 by philipnorton42, jibran, dawehner, andrewmacpherson: Add helpful exception message in CustomAccessCheck
parent 8ce2a3ec
......@@ -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);
......
......@@ -9,8 +9,13 @@
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\Tests\UnitTestCase;
use Symfony\Component\Routing\Route;
use Drupal\Core\DependencyInjection\ClassResolverInterface;
use Symfony\Bridge\PsrHttpMessage\HttpMessageFactoryInterface;
/**
* @coversDefaultClass \Drupal\Core\Access\CustomAccessCheck
......@@ -106,6 +111,34 @@ public function testAccess() {
$this->assertEquals(AccessResult::allowed(), $this->accessChecker->access($route, $route_match, $account));
}
/**
* Tests the access method exception for invalid access callbacks.
*/
public function testAccessException() {
// Create two mocks for the ControllerResolver constructor.
$httpMessageFactory = $this->getMockBuilder(HttpMessageFactoryInterface::class)->getMock();
$controllerResolver = $this->getMockBuilder(ClassResolverInterface::class)->getMock();
// Re-create the controllerResolver mock with proxy to original methods.
$this->controllerResolver = $this->getMockBuilder(ControllerResolver::class)
->setConstructorArgs([$httpMessageFactory, $controllerResolver])
->enableProxyingToOriginalMethods()
->getMock();
// Overwrite the access checker using the newly mocked controller resolve.
$this->accessChecker = new CustomAccessCheck($this->controllerResolver, $this->argumentsResolverFactory);
// Add a route with a _custom_access route that doesn't exist.
$route = new Route('/test-route', [], ['_custom_access' => '\Drupal\Tests\Core\Access\NonExistentController::nonExistentMethod']);
$route_match = $this->getMock(RouteMatchInterface::class);
$account = $this->getMock(AccountInterface::class);
$this->setExpectedException(\BadMethodCallException::class, 'The "\Drupal\Tests\Core\Access\NonExistentController::nonExistentMethod" method is not callable as a _custom_access callback in route "/test-route"');
// Run the access check.
$this->accessChecker->access($route, $route_match, $account);
}
}
class TestController {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment