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