Mercurial > hg > isophonics-drupal-site
diff core/lib/Drupal/Core/Access/CheckProvider.php @ 0:4c8ae668cc8c
Initial import (non-working)
author | Chris Cannam |
---|---|
date | Wed, 29 Nov 2017 16:09:58 +0000 |
parents | |
children | 129ea1e6d783 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/lib/Drupal/Core/Access/CheckProvider.php Wed Nov 29 16:09:58 2017 +0000 @@ -0,0 +1,168 @@ +<?php + +namespace Drupal\Core\Access; + +use Drupal\Core\Routing\Access\AccessInterface; +use Symfony\Component\DependencyInjection\ContainerAwareInterface; +use Symfony\Component\DependencyInjection\ContainerAwareTrait; +use Symfony\Component\Routing\Route; +use Symfony\Component\Routing\RouteCollection; + +/** + * Loads access checkers from the container. + */ +class CheckProvider implements CheckProviderInterface, ContainerAwareInterface { + + use ContainerAwareTrait; + + /** + * 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; + + /** + * {@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) { + $this->loadDynamicRequirementMap(); + 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) { + $checks[] = $service_id; + } + } + } + // Finally, see if any dynamic access checkers apply. + foreach ($this->dynamicRequirementMap as $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)) { + 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; + } + } + } + +}