Upgraded drupal core with security updates
[yaffs-website] / web / core / lib / Drupal / Core / Access / AccessManager.php
1 <?php
2
3 namespace Drupal\Core\Access;
4
5 use Drupal\Core\ParamConverter\ParamConverterManagerInterface;
6 use Drupal\Core\ParamConverter\ParamNotConvertedException;
7 use Drupal\Core\Routing\RouteMatch;
8 use Drupal\Core\Routing\RouteMatchInterface;
9 use Drupal\Core\Routing\RouteProviderInterface;
10 use Drupal\Core\Session\AccountInterface;
11 use Drupal\Component\Utility\ArgumentsResolverInterface;
12 use Symfony\Component\HttpFoundation\Request;
13 use Symfony\Component\Routing\Exception\RouteNotFoundException;
14 use Symfony\Cmf\Component\Routing\RouteObjectInterface;
15
16 /**
17  * Attaches access check services to routes and runs them on request.
18  *
19  * @see \Drupal\Tests\Core\Access\AccessManagerTest
20  */
21 class AccessManager implements AccessManagerInterface {
22   /**
23    * The route provider.
24    *
25    * @var \Drupal\Core\Routing\RouteProviderInterface
26    */
27   protected $routeProvider;
28
29   /**
30    * The paramconverter manager.
31    *
32    * @var \Drupal\Core\ParamConverter\ParamConverterManagerInterface
33    */
34   protected $paramConverterManager;
35
36   /**
37    * The access arguments resolver.
38    *
39    * @var \Drupal\Core\Access\AccessArgumentsResolverFactoryInterface
40    */
41   protected $argumentsResolverFactory;
42
43   /**
44    * The current user.
45    *
46    * @var \Drupal\Core\Session\AccountInterface
47    */
48   protected $currentUser;
49
50   /**
51    * The check provider.
52    *
53    * @var \Drupal\Core\Access\CheckProviderInterface
54    */
55   protected $checkProvider;
56
57   /**
58    * Constructs a AccessManager instance.
59    *
60    * @param \Drupal\Core\Routing\RouteProviderInterface $route_provider
61    *   The route provider.
62    * @param \Drupal\Core\ParamConverter\ParamConverterManagerInterface $paramconverter_manager
63    *   The param converter manager.
64    * @param \Drupal\Core\Access\AccessArgumentsResolverFactoryInterface $arguments_resolver_factory
65    *   The access arguments resolver.
66    * @param \Drupal\Core\Session\AccountInterface $current_user
67    *   The current user.
68    * @param CheckProviderInterface $check_provider
69    */
70   public function __construct(RouteProviderInterface $route_provider, ParamConverterManagerInterface $paramconverter_manager, AccessArgumentsResolverFactoryInterface $arguments_resolver_factory, AccountInterface $current_user, CheckProviderInterface $check_provider) {
71     $this->routeProvider = $route_provider;
72     $this->paramConverterManager = $paramconverter_manager;
73     $this->argumentsResolverFactory = $arguments_resolver_factory;
74     $this->currentUser = $current_user;
75     $this->checkProvider = $check_provider;
76   }
77
78   /**
79    * {@inheritdoc}
80    */
81   public function checkNamedRoute($route_name, array $parameters = [], AccountInterface $account = NULL, $return_as_object = FALSE) {
82     try {
83       $route = $this->routeProvider->getRouteByName($route_name, $parameters);
84
85       // ParamConverterManager relies on the route name and object being
86       // available from the parameters array.
87       $parameters[RouteObjectInterface::ROUTE_NAME] = $route_name;
88       $parameters[RouteObjectInterface::ROUTE_OBJECT] = $route;
89       $upcasted_parameters = $this->paramConverterManager->convert($parameters + $route->getDefaults());
90
91       $route_match = new RouteMatch($route_name, $route, $upcasted_parameters, $parameters);
92       return $this->check($route_match, $account, NULL, $return_as_object);
93     }
94     catch (RouteNotFoundException $e) {
95       // Cacheable until extensions change.
96       $result = AccessResult::forbidden()->addCacheTags(['config:core.extension']);
97       return $return_as_object ? $result : $result->isAllowed();
98     }
99     catch (ParamNotConvertedException $e) {
100       // Uncacheable because conversion of the parameter may not have been
101       // possible due to dynamic circumstances.
102       $result = AccessResult::forbidden()->setCacheMaxAge(0);
103       return $return_as_object ? $result : $result->isAllowed();
104     }
105   }
106
107   /**
108    * {@inheritdoc}
109    */
110   public function checkRequest(Request $request, AccountInterface $account = NULL, $return_as_object = FALSE) {
111     $route_match = RouteMatch::createFromRequest($request);
112     return $this->check($route_match, $account, $request, $return_as_object);
113   }
114
115   /**
116    * {@inheritdoc}
117    */
118   public function check(RouteMatchInterface $route_match, AccountInterface $account = NULL, Request $request = NULL, $return_as_object = FALSE) {
119     if (!isset($account)) {
120       $account = $this->currentUser;
121     }
122     $route = $route_match->getRouteObject();
123     $checks = $route->getOption('_access_checks') ?: [];
124
125     // Filter out checks which require the incoming request.
126     if (!isset($request)) {
127       $checks = array_diff($checks, $this->checkProvider->getChecksNeedRequest());
128     }
129
130     $result = AccessResult::neutral();
131     if (!empty($checks)) {
132       $arguments_resolver = $this->argumentsResolverFactory->getArgumentsResolver($route_match, $account, $request);
133       $result = AccessResult::allowed();
134       foreach ($checks as $service_id) {
135         $result = $result->andIf($this->performCheck($service_id, $arguments_resolver));
136       }
137     }
138     return $return_as_object ? $result : $result->isAllowed();
139   }
140
141   /**
142    * Performs the specified access check.
143    *
144    * @param string $service_id
145    *   The access check service ID to use.
146    * @param \Drupal\Component\Utility\ArgumentsResolverInterface $arguments_resolver
147    *   The parametrized arguments resolver instance.
148    *
149    * @return \Drupal\Core\Access\AccessResultInterface
150    *   The access result.
151    *
152    * @throws \Drupal\Core\Access\AccessException
153    *   Thrown when the access check returns an invalid value.
154    */
155   protected function performCheck($service_id, ArgumentsResolverInterface $arguments_resolver) {
156     $callable = $this->checkProvider->loadCheck($service_id);
157     $arguments = $arguments_resolver->getArguments($callable);
158     /** @var \Drupal\Core\Access\AccessResultInterface $service_access **/
159     $service_access = call_user_func_array($callable, $arguments);
160
161     if (!$service_access instanceof AccessResultInterface) {
162       throw new AccessException("Access error in $service_id. Access services must return an object that implements AccessResultInterface.");
163     }
164
165     return $service_access;
166   }
167
168 }