Chris@0: checkIds[] = $service_id; Chris@0: $this->checkMethods[$service_id] = $service_method; Chris@0: if ($needs_incoming_request) { Chris@0: $this->checksNeedsRequest[$service_id] = $service_id; Chris@0: } Chris@0: foreach ($applies_checks as $applies_check) { Chris@0: $this->staticRequirementMap[$applies_check][] = $service_id; Chris@0: } Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function getChecksNeedRequest() { Chris@0: return $this->checksNeedsRequest; Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function setChecks(RouteCollection $routes) { Chris@0: $this->loadDynamicRequirementMap(); Chris@0: foreach ($routes as $route) { Chris@0: if ($checks = $this->applies($route)) { Chris@0: $route->setOption('_access_checks', $checks); Chris@0: } Chris@0: } Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function loadCheck($service_id) { Chris@0: if (empty($this->checks[$service_id])) { Chris@0: if (!in_array($service_id, $this->checkIds)) { Chris@0: throw new \InvalidArgumentException(sprintf('No check has been registered for %s', $service_id)); Chris@0: } Chris@0: Chris@0: $check = $this->container->get($service_id); Chris@0: Chris@0: if (!($check instanceof AccessInterface)) { Chris@0: throw new AccessException('All access checks must implement AccessInterface.'); Chris@0: } Chris@0: if (!is_callable([$check, $this->checkMethods[$service_id]])) { Chris@0: throw new AccessException(sprintf('Access check method %s in service %s must be callable.', $this->checkMethods[$service_id], $service_id)); Chris@0: } Chris@0: Chris@0: $this->checks[$service_id] = $check; Chris@0: } Chris@0: return [$this->checks[$service_id], $this->checkMethods[$service_id]]; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Determine which registered access checks apply to a route. Chris@0: * Chris@0: * @param \Symfony\Component\Routing\Route $route Chris@0: * The route to get list of access checks for. Chris@0: * Chris@0: * @return array Chris@0: * An array of service ids for the access checks that apply to passed Chris@0: * route. Chris@0: */ Chris@0: protected function applies(Route $route) { Chris@0: $checks = []; Chris@0: Chris@0: // Iterate through map requirements from appliesTo() on access checkers. Chris@0: // Only iterate through all checkIds if this is not used. Chris@0: foreach ($route->getRequirements() as $key => $value) { Chris@0: if (isset($this->staticRequirementMap[$key])) { Chris@0: foreach ($this->staticRequirementMap[$key] as $service_id) { Chris@0: $checks[] = $service_id; Chris@0: } Chris@0: } Chris@0: } Chris@0: // Finally, see if any dynamic access checkers apply. Chris@0: foreach ($this->dynamicRequirementMap as $service_id) { Chris@0: if ($this->checks[$service_id]->applies($route)) { Chris@0: $checks[] = $service_id; Chris@0: } Chris@0: } Chris@0: Chris@0: return $checks; Chris@0: } Chris@17: Chris@0: /** Chris@0: * Compiles a mapping of requirement keys to access checker service IDs. Chris@0: */ Chris@0: protected function loadDynamicRequirementMap() { Chris@0: if (isset($this->dynamicRequirementMap)) { Chris@0: return; Chris@0: } Chris@0: Chris@0: // Set them here, so we can use the isset() check above. Chris@0: $this->dynamicRequirementMap = []; Chris@0: Chris@0: foreach ($this->checkIds as $service_id) { Chris@0: if (empty($this->checks[$service_id])) { Chris@0: $this->loadCheck($service_id); Chris@0: } Chris@0: Chris@0: // Add the service ID to an array that will be iterated over. Chris@0: if ($this->checks[$service_id] instanceof AccessCheckInterface) { Chris@0: $this->dynamicRequirementMap[] = $service_id; Chris@0: } Chris@0: } Chris@0: } Chris@0: Chris@0: }