diff --git a/core/core.services.yml b/core/core.services.yml index a360dedb6d5d2484c2576e156a218a8a4a698094..b3cddc3653d1f555ce0c2abc4de30b2c95a0301e 100644 --- a/core/core.services.yml +++ b/core/core.services.yml @@ -1308,8 +1308,7 @@ services: Drupal\Core\Access\AccessManagerInterface: '@access_manager' access_manager.check_provider: class: Drupal\Core\Access\CheckProvider - calls: - - [setContainer, ['@service_container']] + arguments: ['%dynamic_access_check_services%'] public: false Drupal\Core\Access\CheckProviderInterface: '@access_manager.check_provider' access_check.default: diff --git a/core/lib/Drupal/Core/Access/CheckProvider.php b/core/lib/Drupal/Core/Access/CheckProvider.php index 87cc66c3be65709c00fc981df4403af0002ea160..fda08b5865243a3ed0ef6a3e90e1e2ade2e7ded0 100644 --- a/core/lib/Drupal/Core/Access/CheckProvider.php +++ b/core/lib/Drupal/Core/Access/CheckProvider.php @@ -3,17 +3,14 @@ namespace Drupal\Core\Access; use Drupal\Core\Routing\Access\AccessInterface; -use Symfony\Component\DependencyInjection\ContainerAwareInterface; -use Symfony\Component\DependencyInjection\ContainerAwareTrait; +use Psr\Container\ContainerInterface; use Symfony\Component\Routing\Route; use Symfony\Component\Routing\RouteCollection; /** * Loads access checkers from the container. */ -class CheckProvider implements CheckProviderInterface, ContainerAwareInterface { - - use ContainerAwareTrait; +class CheckProvider implements CheckProviderInterface { /** * Array of registered access check service ids. @@ -55,6 +52,29 @@ class CheckProvider implements CheckProviderInterface, ContainerAwareInterface { */ protected $dynamicRequirementMap; + /** + * Constructs a CheckProvider object. + * + * @param array|null $dynamic_requirements_map + * An array to map dynamic requirement keys to service IDs. + * @param \Psr\Container\ContainerInterface|null $container + * The check provider service locator. + */ + public function __construct( + array $dynamic_requirements_map = NULL, + protected ?ContainerInterface $container = NULL, + ) { + $this->dynamicRequirementMap = $dynamic_requirements_map; + if (is_null($this->dynamicRequirementMap)) { + @trigger_error('Calling ' . __METHOD__ . ' without the $dynamic_requirements_map argument is deprecated in drupal:10.3.0 and it will be required in drupal:11.0.0. See https://www.drupal.org/node/3416353', E_USER_DEPRECATED); + $this->dynamicRequirementMap = \Drupal::getContainer()->getParameter('dynamic_access_check_services'); + } + if (!$this->container) { + @trigger_error('Calling ' . __METHOD__ . ' without the $container argument is deprecated in drupal:10.3.0 and it will be required in drupal:11.0.0. See https://www.drupal.org/node/3416353', E_USER_DEPRECATED); + $this->container = \Drupal::getContainer(); + } + } + /** * {@inheritdoc} */ @@ -80,7 +100,6 @@ public function getChecksNeedRequest() { * {@inheritdoc} */ public function setChecks(RouteCollection $routes) { - $this->loadDynamicRequirementMap(); foreach ($routes as $route) { if ($checks = $this->applies($route)) { $route->setOption('_access_checks', $checks); diff --git a/core/lib/Drupal/Core/DependencyInjection/Compiler/RegisterAccessChecksPass.php b/core/lib/Drupal/Core/DependencyInjection/Compiler/RegisterAccessChecksPass.php index 046001a282df1e0f4a824c1078f8017d5765736f..4efbc4f624f5e6aeec855bdeb480844565d75bc5 100644 --- a/core/lib/Drupal/Core/DependencyInjection/Compiler/RegisterAccessChecksPass.php +++ b/core/lib/Drupal/Core/DependencyInjection/Compiler/RegisterAccessChecksPass.php @@ -3,8 +3,10 @@ namespace Drupal\Core\DependencyInjection\Compiler; use Drupal\Core\Access\AccessCheckInterface; +use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\Reference; /** * Adds services tagged 'access_check' to the access_manager service. @@ -18,6 +20,7 @@ public function process(ContainerBuilder $container) { if (!$container->hasDefinition('access_manager')) { return; } + $services = []; $dynamic_access_check_services = []; // Add services tagged 'access_check' to the access_manager service. $access_manager = $container->getDefinition('access_manager.check_provider'); @@ -43,7 +46,10 @@ public function process(ContainerBuilder $container) { if (in_array(AccessCheckInterface::class, class_implements($class), TRUE)) { $dynamic_access_check_services[] = $id; } + + $services[$id] = new Reference($id); } + $access_manager->addArgument(ServiceLocatorTagPass::register($container, $services)); $container->setParameter('dynamic_access_check_services', $dynamic_access_check_services); } diff --git a/core/phpstan-baseline.neon b/core/phpstan-baseline.neon index f7797dde59b85d8274ecedf2acd1cc8f0947e1be..97abae995103584a28d12c07df76a3efb2847534 100644 --- a/core/phpstan-baseline.neon +++ b/core/phpstan-baseline.neon @@ -192,22 +192,6 @@ parameters: count: 1 path: lib/Drupal/Core/Access/AccessResult.php - - - message: """ - #^Class Drupal\\\\Core\\\\Access\\\\CheckProvider implements deprecated interface Symfony\\\\Component\\\\DependencyInjection\\\\ContainerAwareInterface\\: - since Symfony 6\\.4, use dependency injection instead$# - """ - count: 1 - path: lib/Drupal/Core/Access/CheckProvider.php - - - - message: """ - #^Usage of deprecated trait Symfony\\\\Component\\\\DependencyInjection\\\\ContainerAwareTrait in class Drupal\\\\Core\\\\Access\\\\CheckProvider\\: - since Symfony 6\\.4, use dependency injection instead$# - """ - count: 1 - path: lib/Drupal/Core/Access/CheckProvider.php - - message: "#^Method Drupal\\\\Core\\\\Access\\\\CsrfRequestHeaderAccessCheck\\:\\:applies\\(\\) should return bool but return statement is missing\\.$#" count: 1 diff --git a/core/tests/Drupal/Tests/Core/Access/AccessManagerTest.php b/core/tests/Drupal/Tests/Core/Access/AccessManagerTest.php index 74de788258ea36a98fc7acf31bb4eeda69a58859..3b66a4f835aef926abfb15b4aab81d3b3bf588fe 100644 --- a/core/tests/Drupal/Tests/Core/Access/AccessManagerTest.php +++ b/core/tests/Drupal/Tests/Core/Access/AccessManagerTest.php @@ -124,8 +124,7 @@ protected function setUp(): void { $this->account = $this->createMock('Drupal\Core\Session\AccountInterface'); $this->currentUser = $this->createMock('Drupal\Core\Session\AccountInterface'); $this->argumentsResolverFactory = $this->createMock('Drupal\Core\Access\AccessArgumentsResolverFactoryInterface'); - $this->checkProvider = new CheckProvider(); - $this->checkProvider->setContainer($this->container); + $this->checkProvider = new CheckProvider([], $this->container); $this->accessManager = new AccessManager($this->routeProvider, $this->paramConverter, $this->argumentsResolverFactory, $this->currentUser, $this->checkProvider); } @@ -154,15 +153,15 @@ public function testSetChecks() { * Tests setChecks with a dynamic access checker. */ public function testSetChecksWithDynamicAccessChecker() { - // Setup the access manager. - $this->accessManager = new AccessManager($this->routeProvider, $this->paramConverter, $this->argumentsResolverFactory, $this->currentUser, $this->checkProvider); - // Setup the dynamic access checker. $access_check = $this->createMock('Drupal\Tests\Core\Access\TestAccessCheckInterface'); $this->container->set('test_access', $access_check); - $this->container->setParameter('dynamic_access_check_services', ['test_access']); + $this->checkProvider = new CheckProvider(['test_access'], $this->container); $this->checkProvider->addCheckService('test_access', 'access'); + // Setup the access manager. + $this->accessManager = new AccessManager($this->routeProvider, $this->paramConverter, $this->argumentsResolverFactory, $this->currentUser, $this->checkProvider); + $route = new Route('/test-path', [], ['_foo' => '1', '_bar' => '1']); $route2 = new Route('/test-path', [], ['_foo' => '1', '_bar' => '2']); $collection = new RouteCollection(); @@ -375,8 +374,6 @@ public function testCheckNamedRouteWithUpcastedValues() { return $route_match->getParameters()->get('value') == 'upcasted_value'; })); - $this->accessManager = new AccessManager($this->routeProvider, $this->paramConverter, $this->argumentsResolverFactory, $this->currentUser, $this->checkProvider); - $access_check = $this->createMock('Drupal\Tests\Core\Access\TestAccessCheckInterface'); $access_check->expects($this->atLeastOnce()) ->method('applies') @@ -386,11 +383,12 @@ public function testCheckNamedRouteWithUpcastedValues() { ->willReturn(AccessResult::forbidden()); $this->container->set('test_access', $access_check); - $this->container->setParameter('dynamic_access_check_services', ['test_access']); - + $this->checkProvider = new CheckProvider(['test_access'], $this->container); $this->checkProvider->addCheckService('test_access', 'access'); $this->checkProvider->setChecks($this->routeCollection); + $this->accessManager = new AccessManager($this->routeProvider, $this->paramConverter, $this->argumentsResolverFactory, $this->currentUser, $this->checkProvider); + $this->assertEquals(FALSE, $this->accessManager->checkNamedRoute('test_route_1', ['value' => 'example'], $this->account)); $this->assertEquals(AccessResult::forbidden(), $this->accessManager->checkNamedRoute('test_route_1', ['value' => 'example'], $this->account, TRUE)); } @@ -424,8 +422,6 @@ public function testCheckNamedRouteWithDefaultValue() { return $route_match->getParameters()->get('value') == 'upcasted_value'; })); - $this->accessManager = new AccessManager($this->routeProvider, $this->paramConverter, $this->argumentsResolverFactory, $this->currentUser, $this->checkProvider); - $access_check = $this->createMock('Drupal\Tests\Core\Access\TestAccessCheckInterface'); $access_check->expects($this->atLeastOnce()) ->method('applies') @@ -435,11 +431,12 @@ public function testCheckNamedRouteWithDefaultValue() { ->willReturn(AccessResult::forbidden()); $this->container->set('test_access', $access_check); - $this->container->setParameter('dynamic_access_check_services', ['test_access']); - + $this->checkProvider = new CheckProvider(['test_access'], $this->container); $this->checkProvider->addCheckService('test_access', 'access'); $this->checkProvider->setChecks($this->routeCollection); + $this->accessManager = new AccessManager($this->routeProvider, $this->paramConverter, $this->argumentsResolverFactory, $this->currentUser, $this->checkProvider); + $this->assertEquals(FALSE, $this->accessManager->checkNamedRoute('test_route_1', [], $this->account)); $this->assertEquals(AccessResult::forbidden(), $this->accessManager->checkNamedRoute('test_route_1', [], $this->account, TRUE)); } @@ -497,9 +494,9 @@ public function testCheckException($return_value) { ->willReturn($return_value); $container->set('test_incorrect_value', $access_check); - $access_manager = new AccessManager($route_provider, $this->paramConverter, $this->argumentsResolverFactory, $this->currentUser, $this->checkProvider); - $this->checkProvider->setContainer($container); + $this->checkProvider = new CheckProvider([], $container); $this->checkProvider->addCheckService('test_incorrect_value', 'access'); + $access_manager = new AccessManager($route_provider, $this->paramConverter, $this->argumentsResolverFactory, $this->currentUser, $this->checkProvider); $this->expectException(AccessException::class); $access_manager->checkNamedRoute('test_incorrect_value', [], $this->account);