Mercurial > hg > isophonics-drupal-site
comparison vendor/symfony-cmf/routing/DynamicRouter.php @ 0:4c8ae668cc8c
Initial import (non-working)
author | Chris Cannam |
---|---|
date | Wed, 29 Nov 2017 16:09:58 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4c8ae668cc8c |
---|---|
1 <?php | |
2 | |
3 /* | |
4 * This file is part of the Symfony CMF package. | |
5 * | |
6 * (c) 2011-2015 Symfony CMF | |
7 * | |
8 * For the full copyright and license information, please view the LICENSE | |
9 * file that was distributed with this source code. | |
10 */ | |
11 | |
12 namespace Symfony\Cmf\Component\Routing; | |
13 | |
14 use Symfony\Component\HttpFoundation\Request; | |
15 use Symfony\Component\Routing\RequestContext; | |
16 use Symfony\Component\Routing\Route; | |
17 use Symfony\Component\Routing\RouteCollection; | |
18 use Symfony\Component\Routing\RouterInterface; | |
19 use Symfony\Component\Routing\Generator\UrlGeneratorInterface; | |
20 use Symfony\Component\Routing\Matcher\RequestMatcherInterface; | |
21 use Symfony\Component\Routing\Matcher\UrlMatcherInterface; | |
22 use Symfony\Component\Routing\RequestContextAwareInterface; | |
23 use Symfony\Component\Routing\Exception\RouteNotFoundException; | |
24 use Symfony\Component\Routing\Exception\ResourceNotFoundException; | |
25 use Symfony\Component\Routing\Exception\MethodNotAllowedException; | |
26 use Symfony\Cmf\Component\Routing\Enhancer\RouteEnhancerInterface; | |
27 use Symfony\Component\EventDispatcher\EventDispatcherInterface; | |
28 use Symfony\Cmf\Component\Routing\Event\Events; | |
29 use Symfony\Cmf\Component\Routing\Event\RouterMatchEvent; | |
30 use Symfony\Cmf\Component\Routing\Event\RouterGenerateEvent; | |
31 | |
32 /** | |
33 * A flexible router accepting matcher and generator through injection and | |
34 * using the RouteEnhancer concept to generate additional data on the routes. | |
35 * | |
36 * @author Larry Garfield | |
37 * @author David Buchmann | |
38 */ | |
39 class DynamicRouter implements RouterInterface, RequestMatcherInterface, ChainedRouterInterface | |
40 { | |
41 /** | |
42 * @var RequestMatcherInterface|UrlMatcherInterface | |
43 */ | |
44 protected $matcher; | |
45 | |
46 /** | |
47 * @var UrlGeneratorInterface | |
48 */ | |
49 protected $generator; | |
50 | |
51 /** | |
52 * @var EventDispatcherInterface | |
53 */ | |
54 protected $eventDispatcher; | |
55 | |
56 /** | |
57 * @var RouteEnhancerInterface[] | |
58 */ | |
59 protected $enhancers = array(); | |
60 | |
61 /** | |
62 * Cached sorted list of enhancers. | |
63 * | |
64 * @var RouteEnhancerInterface[] | |
65 */ | |
66 protected $sortedEnhancers = array(); | |
67 | |
68 /** | |
69 * The regexp pattern that needs to be matched before a dynamic lookup is | |
70 * made. | |
71 * | |
72 * @var string | |
73 */ | |
74 protected $uriFilterRegexp; | |
75 | |
76 /** | |
77 * @var RequestContext | |
78 */ | |
79 protected $context; | |
80 | |
81 /** | |
82 * @var RouteCollection | |
83 */ | |
84 private $routeCollection; | |
85 | |
86 /** | |
87 * @param RequestContext $context | |
88 * @param RequestMatcherInterface|UrlMatcherInterface $matcher | |
89 * @param UrlGeneratorInterface $generator | |
90 * @param string $uriFilterRegexp | |
91 * @param EventDispatcherInterface|null $eventDispatcher | |
92 * @param RouteProviderInterface $provider | |
93 */ | |
94 public function __construct(RequestContext $context, | |
95 $matcher, | |
96 UrlGeneratorInterface $generator, | |
97 $uriFilterRegexp = '', | |
98 EventDispatcherInterface $eventDispatcher = null, | |
99 RouteProviderInterface $provider = null | |
100 ) { | |
101 $this->context = $context; | |
102 if (!$matcher instanceof RequestMatcherInterface && !$matcher instanceof UrlMatcherInterface) { | |
103 throw new \InvalidArgumentException('Matcher must implement either Symfony\Component\Routing\Matcher\RequestMatcherInterface or Symfony\Component\Routing\Matcher\UrlMatcherInterface'); | |
104 } | |
105 $this->matcher = $matcher; | |
106 $this->generator = $generator; | |
107 $this->eventDispatcher = $eventDispatcher; | |
108 $this->uriFilterRegexp = $uriFilterRegexp; | |
109 $this->provider = $provider; | |
110 | |
111 $this->generator->setContext($context); | |
112 } | |
113 | |
114 /** | |
115 * {@inheritdoc} | |
116 */ | |
117 public function getRouteCollection() | |
118 { | |
119 if (!$this->routeCollection instanceof RouteCollection) { | |
120 $this->routeCollection = $this->provider | |
121 ? new LazyRouteCollection($this->provider) : new RouteCollection(); | |
122 } | |
123 | |
124 return $this->routeCollection; | |
125 } | |
126 | |
127 /** | |
128 * @return RequestMatcherInterface|UrlMatcherInterface | |
129 */ | |
130 public function getMatcher() | |
131 { | |
132 /* we may not set the context in DynamicRouter::setContext as this | |
133 * would lead to symfony cache warmup problems. | |
134 * a request matcher does not need the request context separately as it | |
135 * can get it from the request. | |
136 */ | |
137 if ($this->matcher instanceof RequestContextAwareInterface) { | |
138 $this->matcher->setContext($this->getContext()); | |
139 } | |
140 | |
141 return $this->matcher; | |
142 } | |
143 | |
144 /** | |
145 * @return UrlGeneratorInterface | |
146 */ | |
147 public function getGenerator() | |
148 { | |
149 $this->generator->setContext($this->getContext()); | |
150 | |
151 return $this->generator; | |
152 } | |
153 | |
154 /** | |
155 * Generates a URL from the given parameters. | |
156 * | |
157 * If the generator is not able to generate the url, it must throw the | |
158 * RouteNotFoundException as documented below. | |
159 * | |
160 * @param string|Route $name The name of the route or the Route instance | |
161 * @param mixed $parameters An array of parameters | |
162 * @param bool|string $referenceType The type of reference to be generated (one of the constants in UrlGeneratorInterface) | |
163 * | |
164 * @return string The generated URL | |
165 * | |
166 * @throws RouteNotFoundException if route doesn't exist | |
167 * | |
168 * @api | |
169 */ | |
170 public function generate($name, $parameters = array(), $referenceType = UrlGeneratorInterface::ABSOLUTE_PATH) | |
171 { | |
172 if ($this->eventDispatcher) { | |
173 $event = new RouterGenerateEvent($name, $parameters, $referenceType); | |
174 $this->eventDispatcher->dispatch(Events::PRE_DYNAMIC_GENERATE, $event); | |
175 $name = $event->getRoute(); | |
176 $parameters = $event->getParameters(); | |
177 $referenceType = $event->getReferenceType(); | |
178 } | |
179 | |
180 return $this->getGenerator()->generate($name, $parameters, $referenceType); | |
181 } | |
182 | |
183 /** | |
184 * Delegate to our generator. | |
185 * | |
186 * {@inheritdoc} | |
187 */ | |
188 public function supports($name) | |
189 { | |
190 if ($this->generator instanceof VersatileGeneratorInterface) { | |
191 return $this->generator->supports($name); | |
192 } | |
193 | |
194 return is_string($name); | |
195 } | |
196 | |
197 /** | |
198 * Tries to match a URL path with a set of routes. | |
199 * | |
200 * If the matcher can not find information, it must throw one of the | |
201 * exceptions documented below. | |
202 * | |
203 * @param string $pathinfo The path info to be parsed (raw format, i.e. not | |
204 * urldecoded) | |
205 * | |
206 * @return array An array of parameters | |
207 * | |
208 * @throws ResourceNotFoundException If the resource could not be found | |
209 * @throws MethodNotAllowedException If the resource was found but the | |
210 * request method is not allowed | |
211 * | |
212 * @deprecated Use matchRequest exclusively to avoid problems. This method will be removed in version 2.0 | |
213 * | |
214 * @api | |
215 */ | |
216 public function match($pathinfo) | |
217 { | |
218 @trigger_error(__METHOD__.'() is deprecated since version 1.3 and will be removed in 2.0. Use matchRequest() instead.', E_USER_DEPRECATED); | |
219 | |
220 $request = Request::create($pathinfo); | |
221 if ($this->eventDispatcher) { | |
222 $event = new RouterMatchEvent(); | |
223 $this->eventDispatcher->dispatch(Events::PRE_DYNAMIC_MATCH, $event); | |
224 } | |
225 | |
226 if (!empty($this->uriFilterRegexp) && !preg_match($this->uriFilterRegexp, $pathinfo)) { | |
227 throw new ResourceNotFoundException("$pathinfo does not match the '{$this->uriFilterRegexp}' pattern"); | |
228 } | |
229 | |
230 $matcher = $this->getMatcher(); | |
231 if (!$matcher instanceof UrlMatcherInterface) { | |
232 throw new \InvalidArgumentException('Wrong matcher type, you need to call matchRequest'); | |
233 } | |
234 | |
235 $defaults = $matcher->match($pathinfo); | |
236 | |
237 return $this->applyRouteEnhancers($defaults, $request); | |
238 } | |
239 | |
240 /** | |
241 * Tries to match a request with a set of routes and returns the array of | |
242 * information for that route. | |
243 * | |
244 * If the matcher can not find information, it must throw one of the | |
245 * exceptions documented below. | |
246 * | |
247 * @param Request $request The request to match | |
248 * | |
249 * @return array An array of parameters | |
250 * | |
251 * @throws ResourceNotFoundException If no matching resource could be found | |
252 * @throws MethodNotAllowedException If a matching resource was found but | |
253 * the request method is not allowed | |
254 */ | |
255 public function matchRequest(Request $request) | |
256 { | |
257 if ($this->eventDispatcher) { | |
258 $event = new RouterMatchEvent($request); | |
259 $this->eventDispatcher->dispatch(Events::PRE_DYNAMIC_MATCH_REQUEST, $event); | |
260 } | |
261 | |
262 if (!empty($this->uriFilterRegexp) | |
263 && !preg_match($this->uriFilterRegexp, $request->getPathInfo()) | |
264 ) { | |
265 throw new ResourceNotFoundException("{$request->getPathInfo()} does not match the '{$this->uriFilterRegexp}' pattern"); | |
266 } | |
267 | |
268 $matcher = $this->getMatcher(); | |
269 if ($matcher instanceof UrlMatcherInterface) { | |
270 $defaults = $matcher->match($request->getPathInfo()); | |
271 } else { | |
272 $defaults = $matcher->matchRequest($request); | |
273 } | |
274 | |
275 return $this->applyRouteEnhancers($defaults, $request); | |
276 } | |
277 | |
278 /** | |
279 * Apply the route enhancers to the defaults, according to priorities. | |
280 * | |
281 * @param array $defaults | |
282 * @param Request $request | |
283 * | |
284 * @return array | |
285 */ | |
286 protected function applyRouteEnhancers($defaults, Request $request) | |
287 { | |
288 foreach ($this->getRouteEnhancers() as $enhancer) { | |
289 $defaults = $enhancer->enhance($defaults, $request); | |
290 } | |
291 | |
292 return $defaults; | |
293 } | |
294 | |
295 /** | |
296 * Add route enhancers to the router to let them generate information on | |
297 * matched routes. | |
298 * | |
299 * The order of the enhancers is determined by the priority, the higher the | |
300 * value, the earlier the enhancer is run. | |
301 * | |
302 * @param RouteEnhancerInterface $enhancer | |
303 * @param int $priority | |
304 */ | |
305 public function addRouteEnhancer(RouteEnhancerInterface $enhancer, $priority = 0) | |
306 { | |
307 if (empty($this->enhancers[$priority])) { | |
308 $this->enhancers[$priority] = array(); | |
309 } | |
310 | |
311 $this->enhancers[$priority][] = $enhancer; | |
312 $this->sortedEnhancers = array(); | |
313 | |
314 return $this; | |
315 } | |
316 | |
317 /** | |
318 * Sorts the enhancers and flattens them. | |
319 * | |
320 * @return RouteEnhancerInterface[] the enhancers ordered by priority | |
321 */ | |
322 public function getRouteEnhancers() | |
323 { | |
324 if (empty($this->sortedEnhancers)) { | |
325 $this->sortedEnhancers = $this->sortRouteEnhancers(); | |
326 } | |
327 | |
328 return $this->sortedEnhancers; | |
329 } | |
330 | |
331 /** | |
332 * Sort enhancers by priority. | |
333 * | |
334 * The highest priority number is the highest priority (reverse sorting). | |
335 * | |
336 * @return RouteEnhancerInterface[] the sorted enhancers | |
337 */ | |
338 protected function sortRouteEnhancers() | |
339 { | |
340 $sortedEnhancers = array(); | |
341 krsort($this->enhancers); | |
342 | |
343 foreach ($this->enhancers as $enhancers) { | |
344 $sortedEnhancers = array_merge($sortedEnhancers, $enhancers); | |
345 } | |
346 | |
347 return $sortedEnhancers; | |
348 } | |
349 | |
350 /** | |
351 * Sets the request context. | |
352 * | |
353 * @param RequestContext $context The context | |
354 * | |
355 * @api | |
356 */ | |
357 public function setContext(RequestContext $context) | |
358 { | |
359 $this->context = $context; | |
360 } | |
361 | |
362 /** | |
363 * Gets the request context. | |
364 * | |
365 * @return RequestContext The context | |
366 * | |
367 * @api | |
368 */ | |
369 public function getContext() | |
370 { | |
371 return $this->context; | |
372 } | |
373 | |
374 /** | |
375 * {@inheritdoc} | |
376 * | |
377 * Forwards to the generator. | |
378 */ | |
379 public function getRouteDebugMessage($name, array $parameters = array()) | |
380 { | |
381 if ($this->generator instanceof VersatileGeneratorInterface) { | |
382 return $this->generator->getRouteDebugMessage($name, $parameters); | |
383 } | |
384 | |
385 return "Route '$name' not found"; | |
386 } | |
387 } |