comparison vendor/symfony/routing/RouteCollectionBuilder.php @ 0:c75dbcec494b

Initial commit from drush-created site
author Chris Cannam
date Thu, 05 Jul 2018 14:24:15 +0000
parents
children a9cd425dd02b
comparison
equal deleted inserted replaced
-1:000000000000 0:c75dbcec494b
1 <?php
2
3 /*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
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\Component\Routing;
13
14 use Symfony\Component\Config\Exception\FileLoaderLoadException;
15 use Symfony\Component\Config\Loader\LoaderInterface;
16 use Symfony\Component\Config\Resource\ResourceInterface;
17
18 /**
19 * Helps add and import routes into a RouteCollection.
20 *
21 * @author Ryan Weaver <ryan@knpuniversity.com>
22 */
23 class RouteCollectionBuilder
24 {
25 /**
26 * @var Route[]|RouteCollectionBuilder[]
27 */
28 private $routes = array();
29
30 private $loader;
31 private $defaults = array();
32 private $prefix;
33 private $host;
34 private $condition;
35 private $requirements = array();
36 private $options = array();
37 private $schemes;
38 private $methods;
39 private $resources = array();
40
41 public function __construct(LoaderInterface $loader = null)
42 {
43 $this->loader = $loader;
44 }
45
46 /**
47 * Import an external routing resource and returns the RouteCollectionBuilder.
48 *
49 * $routes->import('blog.yml', '/blog');
50 *
51 * @param mixed $resource
52 * @param string|null $prefix
53 * @param string $type
54 *
55 * @return self
56 *
57 * @throws FileLoaderLoadException
58 */
59 public function import($resource, $prefix = '/', $type = null)
60 {
61 /** @var RouteCollection[] $collection */
62 $collections = $this->load($resource, $type);
63
64 // create a builder from the RouteCollection
65 $builder = $this->createBuilder();
66
67 foreach ($collections as $collection) {
68 if (null === $collection) {
69 continue;
70 }
71
72 foreach ($collection->all() as $name => $route) {
73 $builder->addRoute($route, $name);
74 }
75
76 foreach ($collection->getResources() as $resource) {
77 $builder->addResource($resource);
78 }
79 }
80
81 // mount into this builder
82 $this->mount($prefix, $builder);
83
84 return $builder;
85 }
86
87 /**
88 * Adds a route and returns it for future modification.
89 *
90 * @param string $path The route path
91 * @param string $controller The route's controller
92 * @param string|null $name The name to give this route
93 *
94 * @return Route
95 */
96 public function add($path, $controller, $name = null)
97 {
98 $route = new Route($path);
99 $route->setDefault('_controller', $controller);
100 $this->addRoute($route, $name);
101
102 return $route;
103 }
104
105 /**
106 * Returns a RouteCollectionBuilder that can be configured and then added with mount().
107 *
108 * @return self
109 */
110 public function createBuilder()
111 {
112 return new self($this->loader);
113 }
114
115 /**
116 * Add a RouteCollectionBuilder.
117 *
118 * @param string $prefix
119 * @param RouteCollectionBuilder $builder
120 */
121 public function mount($prefix, self $builder)
122 {
123 $builder->prefix = trim(trim($prefix), '/');
124 $this->routes[] = $builder;
125 }
126
127 /**
128 * Adds a Route object to the builder.
129 *
130 * @param Route $route
131 * @param string|null $name
132 *
133 * @return $this
134 */
135 public function addRoute(Route $route, $name = null)
136 {
137 if (null === $name) {
138 // used as a flag to know which routes will need a name later
139 $name = '_unnamed_route_'.spl_object_hash($route);
140 }
141
142 $this->routes[$name] = $route;
143
144 return $this;
145 }
146
147 /**
148 * Sets the host on all embedded routes (unless already set).
149 *
150 * @param string $pattern
151 *
152 * @return $this
153 */
154 public function setHost($pattern)
155 {
156 $this->host = $pattern;
157
158 return $this;
159 }
160
161 /**
162 * Sets a condition on all embedded routes (unless already set).
163 *
164 * @param string $condition
165 *
166 * @return $this
167 */
168 public function setCondition($condition)
169 {
170 $this->condition = $condition;
171
172 return $this;
173 }
174
175 /**
176 * Sets a default value that will be added to all embedded routes (unless that
177 * default value is already set).
178 *
179 * @param string $key
180 * @param mixed $value
181 *
182 * @return $this
183 */
184 public function setDefault($key, $value)
185 {
186 $this->defaults[$key] = $value;
187
188 return $this;
189 }
190
191 /**
192 * Sets a requirement that will be added to all embedded routes (unless that
193 * requirement is already set).
194 *
195 * @param string $key
196 * @param mixed $regex
197 *
198 * @return $this
199 */
200 public function setRequirement($key, $regex)
201 {
202 $this->requirements[$key] = $regex;
203
204 return $this;
205 }
206
207 /**
208 * Sets an option that will be added to all embedded routes (unless that
209 * option is already set).
210 *
211 * @param string $key
212 * @param mixed $value
213 *
214 * @return $this
215 */
216 public function setOption($key, $value)
217 {
218 $this->options[$key] = $value;
219
220 return $this;
221 }
222
223 /**
224 * Sets the schemes on all embedded routes (unless already set).
225 *
226 * @param array|string $schemes
227 *
228 * @return $this
229 */
230 public function setSchemes($schemes)
231 {
232 $this->schemes = $schemes;
233
234 return $this;
235 }
236
237 /**
238 * Sets the methods on all embedded routes (unless already set).
239 *
240 * @param array|string $methods
241 *
242 * @return $this
243 */
244 public function setMethods($methods)
245 {
246 $this->methods = $methods;
247
248 return $this;
249 }
250
251 /**
252 * Adds a resource for this collection.
253 *
254 * @return $this
255 */
256 private function addResource(ResourceInterface $resource)
257 {
258 $this->resources[] = $resource;
259
260 return $this;
261 }
262
263 /**
264 * Creates the final RouteCollection and returns it.
265 *
266 * @return RouteCollection
267 */
268 public function build()
269 {
270 $routeCollection = new RouteCollection();
271
272 foreach ($this->routes as $name => $route) {
273 if ($route instanceof Route) {
274 $route->setDefaults(array_merge($this->defaults, $route->getDefaults()));
275 $route->setOptions(array_merge($this->options, $route->getOptions()));
276
277 foreach ($this->requirements as $key => $val) {
278 if (!$route->hasRequirement($key)) {
279 $route->setRequirement($key, $val);
280 }
281 }
282
283 if (null !== $this->prefix) {
284 $route->setPath('/'.$this->prefix.$route->getPath());
285 }
286
287 if (!$route->getHost()) {
288 $route->setHost($this->host);
289 }
290
291 if (!$route->getCondition()) {
292 $route->setCondition($this->condition);
293 }
294
295 if (!$route->getSchemes()) {
296 $route->setSchemes($this->schemes);
297 }
298
299 if (!$route->getMethods()) {
300 $route->setMethods($this->methods);
301 }
302
303 // auto-generate the route name if it's been marked
304 if ('_unnamed_route_' === substr($name, 0, 15)) {
305 $name = $this->generateRouteName($route);
306 }
307
308 $routeCollection->add($name, $route);
309 } else {
310 /* @var self $route */
311 $subCollection = $route->build();
312 $subCollection->addPrefix($this->prefix);
313
314 $routeCollection->addCollection($subCollection);
315 }
316 }
317
318 foreach ($this->resources as $resource) {
319 $routeCollection->addResource($resource);
320 }
321
322 return $routeCollection;
323 }
324
325 /**
326 * Generates a route name based on details of this route.
327 *
328 * @return string
329 */
330 private function generateRouteName(Route $route)
331 {
332 $methods = implode('_', $route->getMethods()).'_';
333
334 $routeName = $methods.$route->getPath();
335 $routeName = str_replace(array('/', ':', '|', '-'), '_', $routeName);
336 $routeName = preg_replace('/[^a-z0-9A-Z_.]+/', '', $routeName);
337
338 // Collapse consecutive underscores down into a single underscore.
339 $routeName = preg_replace('/_+/', '_', $routeName);
340
341 return $routeName;
342 }
343
344 /**
345 * Finds a loader able to load an imported resource and loads it.
346 *
347 * @param mixed $resource A resource
348 * @param string|null $type The resource type or null if unknown
349 *
350 * @return RouteCollection[]
351 *
352 * @throws FileLoaderLoadException If no loader is found
353 */
354 private function load($resource, $type = null)
355 {
356 if (null === $this->loader) {
357 throw new \BadMethodCallException('Cannot import other routing resources: you must pass a LoaderInterface when constructing RouteCollectionBuilder.');
358 }
359
360 if ($this->loader->supports($resource, $type)) {
361 $collections = $this->loader->load($resource, $type);
362
363 return is_array($collections) ? $collections : array($collections);
364 }
365
366 if (null === $resolver = $this->loader->getResolver()) {
367 throw new FileLoaderLoadException($resource, null, null, null, $type);
368 }
369
370 if (false === $loader = $resolver->resolve($resource, $type)) {
371 throw new FileLoaderLoadException($resource, null, null, null, $type);
372 }
373
374 $collections = $loader->load($resource, $type);
375
376 return is_array($collections) ? $collections : array($collections);
377 }
378 }