class CheckProvider

Same name and namespace in other branches
  1. 9 core/lib/Drupal/Core/Access/CheckProvider.php \Drupal\Core\Access\CheckProvider
  2. 8.9.x core/lib/Drupal/Core/Access/CheckProvider.php \Drupal\Core\Access\CheckProvider
  3. 11.x core/lib/Drupal/Core/Access/CheckProvider.php \Drupal\Core\Access\CheckProvider

Loads access checkers from the container.

Hierarchy

Expanded class hierarchy of CheckProvider

1 file declares its use of CheckProvider
AccessManagerTest.php in core/tests/Drupal/Tests/Core/Access/AccessManagerTest.php
1 string reference to 'CheckProvider'
core.services.yml in core/core.services.yml
core/core.services.yml
1 service uses CheckProvider
access_manager.check_provider in core/core.services.yml
Drupal\Core\Access\CheckProvider

File

core/lib/Drupal/Core/Access/CheckProvider.php, line 13

Namespace

Drupal\Core\Access
View source
class CheckProvider implements CheckProviderInterface {
  
  /**
   * Array of registered access check service ids.
   *
   * @var array
   */
  protected $checkIds = [];
  
  /**
   * Array of access check objects keyed by service id.
   *
   * @var \Drupal\Core\Routing\Access\AccessInterface[]
   */
  protected $checks;
  
  /**
   * Array of access check method names keyed by service ID.
   *
   * @var array
   */
  protected $checkMethods = [];
  
  /**
   * Array of access checks which only will be run on the incoming request.
   */
  protected $checksNeedsRequest = [];
  
  /**
   * An array to map static requirement keys to service IDs.
   *
   * @var array
   */
  protected $staticRequirementMap;
  
  /**
   * An array to map dynamic requirement keys to service IDs.
   *
   * @var array
   */
  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}
   */
  public function addCheckService($service_id, $service_method, array $applies_checks = [], $needs_incoming_request = FALSE) {
    $this->checkIds[] = $service_id;
    $this->checkMethods[$service_id] = $service_method;
    if ($needs_incoming_request) {
      $this->checksNeedsRequest[$service_id] = $service_id;
    }
    foreach ($applies_checks as $applies_check) {
      $this->staticRequirementMap[$applies_check][] = $service_id;
    }
  }
  
  /**
   * {@inheritdoc}
   */
  public function getChecksNeedRequest() {
    return $this->checksNeedsRequest;
  }
  
  /**
   * {@inheritdoc}
   */
  public function setChecks(RouteCollection $routes) {
    foreach ($routes as $route) {
      if ($checks = $this->applies($route)) {
        $route->setOption('_access_checks', $checks);
      }
    }
  }
  
  /**
   * {@inheritdoc}
   */
  public function loadCheck($service_id) {
    if (empty($this->checks[$service_id])) {
      if (!in_array($service_id, $this->checkIds)) {
        throw new \InvalidArgumentException(sprintf('No check has been registered for %s', $service_id));
      }
      $check = $this->container
        ->get($service_id);
      if (!$check instanceof AccessInterface) {
        throw new AccessException('All access checks must implement AccessInterface.');
      }
      if (!is_callable([
        $check,
        $this->checkMethods[$service_id],
      ])) {
        throw new AccessException(sprintf('Access check method %s in service %s must be callable.', $this->checkMethods[$service_id], $service_id));
      }
      $this->checks[$service_id] = $check;
    }
    return [
      $this->checks[$service_id],
      $this->checkMethods[$service_id],
    ];
  }
  
  /**
   * Determine which registered access checks apply to a route.
   *
   * @param \Symfony\Component\Routing\Route $route
   *   The route to get list of access checks for.
   *
   * @return array
   *   An array of service ids for the access checks that apply to passed
   *   route.
   */
  protected function applies(Route $route) {
    $checks = [];
    // Iterate through map requirements from appliesTo() on access checkers.
    // Only iterate through all checkIds if this is not used.
    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;
      }
    }
    return $checks;
  }
  
  /**
   * Compiles a mapping of requirement keys to access checker service IDs.
   */
  protected function loadDynamicRequirementMap() {
    if (!isset($this->dynamicRequirementMap)) {
      $this->dynamicRequirementMap = $this->container
        ->getParameter('dynamic_access_check_services');
    }
  }

}

Members

Title Sort descending Modifiers Object type Summary Overriden Title
CheckProvider::$checkIds protected property Array of registered access check service ids.
CheckProvider::$checkMethods protected property Array of access check method names keyed by service ID.
CheckProvider::$checks protected property Array of access check objects keyed by service id.
CheckProvider::$checksNeedsRequest protected property Array of access checks which only will be run on the incoming request.
CheckProvider::$dynamicRequirementMap protected property An array to map dynamic requirement keys to service IDs.
CheckProvider::$staticRequirementMap protected property An array to map static requirement keys to service IDs.
CheckProvider::addCheckService public function Registers a new AccessCheck by service ID. Overrides CheckProviderInterface::addCheckService
CheckProvider::applies protected function Determine which registered access checks apply to a route.
CheckProvider::getChecksNeedRequest public function A list of checks that needs the request. Overrides CheckProviderInterface::getChecksNeedRequest
CheckProvider::loadCheck public function Lazy-loads access check services. Overrides CheckProviderInterface::loadCheck
CheckProvider::loadDynamicRequirementMap protected function Compiles a mapping of requirement keys to access checker service IDs.
CheckProvider::setChecks public function For each route, saves a list of applicable access checks to the route. Overrides CheckProviderInterface::setChecks
CheckProvider::__construct public function Constructs a CheckProvider object.

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.