Issue #3183036 by claudiu.cristea, jibran, Berdir: Don't instantiate access checkers not used by any route

merge-requests/826/head
catch 2021-06-21 16:12:12 +01:00
parent 1d5e219f85
commit f992a8bf1d
3 changed files with 18 additions and 16 deletions

View File

@ -129,12 +129,14 @@ class CheckProvider implements CheckProviderInterface, ContainerAwareInterface {
foreach ($route->getRequirements() as $key => $value) {
if (isset($this->staticRequirementMap[$key])) {
foreach ($this->staticRequirementMap[$key] as $service_id) {
$this->loadCheck($service_id);
$checks[] = $service_id;
}
}
}
// Finally, see if any dynamic access checkers apply.
foreach ($this->dynamicRequirementMap as $service_id) {
$this->loadCheck($service_id);
if ($this->checks[$service_id]->applies($route)) {
$checks[] = $service_id;
}
@ -147,22 +149,8 @@ class CheckProvider implements CheckProviderInterface, ContainerAwareInterface {
* Compiles a mapping of requirement keys to access checker service IDs.
*/
protected function loadDynamicRequirementMap() {
if (isset($this->dynamicRequirementMap)) {
return;
}
// Set them here, so we can use the isset() check above.
$this->dynamicRequirementMap = [];
foreach ($this->checkIds as $service_id) {
if (empty($this->checks[$service_id])) {
$this->loadCheck($service_id);
}
// Add the service ID to an array that will be iterated over.
if ($this->checks[$service_id] instanceof AccessCheckInterface) {
$this->dynamicRequirementMap[] = $service_id;
}
if (!isset($this->dynamicRequirementMap)) {
$this->dynamicRequirementMap = $this->container->getParameter('dynamic_access_check_services');
}
}

View File

@ -2,6 +2,7 @@
namespace Drupal\Core\DependencyInjection\Compiler;
use Drupal\Core\Access\AccessCheckInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
@ -17,6 +18,7 @@ class RegisterAccessChecksPass implements CompilerPassInterface {
if (!$container->hasDefinition('access_manager')) {
return;
}
$dynamic_access_check_services = [];
// Add services tagged 'access_check' to the access_manager service.
$access_manager = $container->getDefinition('access_manager.check_provider');
foreach ($container->findTaggedServiceIds('access_check') as $id => $attributes) {
@ -35,7 +37,15 @@ class RegisterAccessChecksPass implements CompilerPassInterface {
}
}
$access_manager->addMethodCall('addCheckService', [$id, $method, $applies, $needs_incoming_request]);
// Collect dynamic access checker services.
$class = $container->getDefinition($id)->getClass();
if (in_array(AccessCheckInterface::class, class_implements($class), TRUE)) {
$dynamic_access_check_services[] = $id;
}
}
$container->setParameter('dynamic_access_check_services', $dynamic_access_check_services);
}
}

View File

@ -97,6 +97,7 @@ class AccessManagerTest extends UnitTestCase {
$this->container = new ContainerBuilder();
$cache_contexts_manager = $this->prophesize(CacheContextsManager::class)->reveal();
$this->container->set('cache_contexts_manager', $cache_contexts_manager);
$this->container->setParameter('dynamic_access_check_services', []);
\Drupal::setContainer($this->container);
$this->routeCollection = new RouteCollection();
@ -162,6 +163,7 @@ class AccessManagerTest extends UnitTestCase {
// 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->addCheckService('test_access', 'access');
$route = new Route('/test-path', [], ['_foo' => '1', '_bar' => '1']);
@ -398,6 +400,7 @@ class AccessManagerTest extends UnitTestCase {
->will($this->returnValue(AccessResult::forbidden()));
$this->container->set('test_access', $access_check);
$this->container->setParameter('dynamic_access_check_services', ['test_access']);
$this->checkProvider->addCheckService('test_access', 'access');
$this->checkProvider->setChecks($this->routeCollection);
@ -446,6 +449,7 @@ class AccessManagerTest extends UnitTestCase {
->will($this->returnValue(AccessResult::forbidden()));
$this->container->set('test_access', $access_check);
$this->container->setParameter('dynamic_access_check_services', ['test_access']);
$this->checkProvider->addCheckService('test_access', 'access');
$this->checkProvider->setChecks($this->routeCollection);