Issue #3363423 by _shY, vbouchet: Use CallableResolver for \Drupal\Core\Access\CustomAccessCheck::access()

merge-requests/5892/head
Alex Pott 2023-12-17 09:25:40 +00:00
parent d16f491577
commit 9e3a13aad4
No known key found for this signature in database
GPG Key ID: BDA67E7EE836E5CE
3 changed files with 32 additions and 28 deletions

View File

@ -1336,7 +1336,7 @@ services:
- { name: access_check, applies_to: _access_theme }
access_check.custom:
class: Drupal\Core\Access\CustomAccessCheck
arguments: ['@controller_resolver', '@access_arguments_resolver_factory']
arguments: ['@callable_resolver', '@access_arguments_resolver_factory']
tags:
- { name: access_check, applies_to: _custom_access }
access_check.csrf:

View File

@ -4,9 +4,10 @@ namespace Drupal\Core\Access;
use Drupal\Core\Controller\ControllerResolverInterface;
use Drupal\Core\Routing\Access\AccessInterface as RoutingAccessInterface;
use Symfony\Component\HttpFoundation\Request;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Utility\CallableResolver;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Route;
/**
@ -22,11 +23,11 @@ use Symfony\Component\Routing\Route;
class CustomAccessCheck implements RoutingAccessInterface {
/**
* The controller resolver.
* The callable resolver.
*
* @var \Drupal\Core\Controller\ControllerResolverInterface
* @var \Drupal\Core\Utility\CallableResolver
*/
protected $controllerResolver;
protected CallableResolver $callableResolver;
/**
* The arguments resolver.
@ -38,13 +39,17 @@ class CustomAccessCheck implements RoutingAccessInterface {
/**
* Constructs a CustomAccessCheck instance.
*
* @param \Drupal\Core\Controller\ControllerResolverInterface $controller_resolver
* The controller resolver.
* @param \Drupal\Core\Utility\CallableResolver|\Drupal\Core\Controller\ControllerResolverInterface $callable_resolver
* The callable resolver.
* @param \Drupal\Core\Access\AccessArgumentsResolverFactoryInterface $arguments_resolver_factory
* The arguments resolver factory.
*/
public function __construct(ControllerResolverInterface $controller_resolver, AccessArgumentsResolverFactoryInterface $arguments_resolver_factory) {
$this->controllerResolver = $controller_resolver;
public function __construct(ControllerResolverInterface|CallableResolver $callable_resolver, AccessArgumentsResolverFactoryInterface $arguments_resolver_factory) {
if ($callable_resolver instanceof ControllerResolverInterface) {
@trigger_error('Calling ' . __METHOD__ . '() with an argument of ControllerResolverInterface is deprecated in drupal:10.3.0 and is removed in drupal:11.0.0. Use \Drupal\Core\Utility\CallableResolver instead. See https://www.drupal.org/node/3397706', E_USER_DEPRECATED);
$callable_resolver = \Drupal::service('callable_resolver');
}
$this->callableResolver = $callable_resolver;
$this->argumentsResolverFactory = $arguments_resolver_factory;
}
@ -66,7 +71,7 @@ class CustomAccessCheck implements RoutingAccessInterface {
*/
public function access(Route $route, RouteMatchInterface $route_match, AccountInterface $account, Request $request = NULL) {
try {
$callable = $this->controllerResolver->getControllerFromDefinition($route->getRequirement('_custom_access'));
$callable = $this->callableResolver->getCallableFromDefinition($route->getRequirement('_custom_access'));
}
catch (\InvalidArgumentException $e) {
// The custom access controller method was not found.

View File

@ -4,7 +4,6 @@ namespace Drupal\Tests\Core\Access;
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\Utility\CallableResolver;
@ -26,11 +25,11 @@ class CustomAccessCheckTest extends UnitTestCase {
protected $accessChecker;
/**
* The mocked controller resolver.
* The mocked callable resolver.
*
* @var \Drupal\Core\Controller\ControllerResolverInterface|\PHPUnit\Framework\MockObject\MockObject
* @var \Drupal\Core\Utility\CallableResolver|\PHPUnit\Framework\MockObject\MockObject
*/
protected $controllerResolver;
protected $callableResolver;
/**
* The mocked arguments resolver.
@ -45,9 +44,9 @@ class CustomAccessCheckTest extends UnitTestCase {
protected function setUp(): void {
parent::setUp();
$this->controllerResolver = $this->createMock('Drupal\Core\Controller\ControllerResolverInterface');
$this->callableResolver = $this->createMock(CallableResolver::class);
$this->argumentsResolverFactory = $this->createMock('Drupal\Core\Access\AccessArgumentsResolverFactoryInterface');
$this->accessChecker = new CustomAccessCheck($this->controllerResolver, $this->argumentsResolverFactory);
$this->accessChecker = new CustomAccessCheck($this->callableResolver, $this->argumentsResolverFactory);
}
/**
@ -56,8 +55,9 @@ class CustomAccessCheckTest extends UnitTestCase {
public function testAccess() {
$route_match = $this->createMock('Drupal\Core\Routing\RouteMatchInterface');
$this->controllerResolver->expects($this->exactly(4))
->method('getControllerFromDefinition')
$this->callableResolver
->expects($this->exactly(4))
->method('getCallableFromDefinition')
->willReturnMap([
['\Drupal\Tests\Core\Access\TestController::accessDeny', [new TestController(), 'accessDeny']],
['\Drupal\Tests\Core\Access\TestController::accessAllow', [new TestController(), 'accessAllow']],
@ -110,18 +110,17 @@ class CustomAccessCheckTest extends UnitTestCase {
* Tests the access method exception for invalid access callbacks.
*/
public function testAccessException() {
$callableResolver = $this->createMock(CallableResolver::class);
$callableResolver->method('getCallableFromDefinition')
->willThrowException(new \InvalidArgumentException());
// Re-create the controllerResolver mock with proxy to original methods.
$this->controllerResolver = $this->getMockBuilder(ControllerResolver::class)
->setConstructorArgs([$callableResolver])
->enableProxyingToOriginalMethods()
// Create callableResolver mock to return InvalidArgumentException.
$this->callableResolver = $this->getMockBuilder(CallableResolver::class)
->disableOriginalConstructor()
->getMock();
// Overwrite the access checker using the newly mocked controller resolve.
$this->accessChecker = new CustomAccessCheck($this->controllerResolver, $this->argumentsResolverFactory);
$this->callableResolver->expects($this->any())
->method('getCallableFromDefinition')
->willThrowException(new \InvalidArgumentException());
// Overwrite the access checker using the newly mocked callable resolve.
$this->accessChecker = new CustomAccessCheck($this->callableResolver, $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']);