]> git.immae.eu Git - github/wallabag/wallabag.git/blob - vendor/symfony/routing/Symfony/Component/Routing/Route.php
060e978116c7eb20b24934b08493f2b52d32ace8
[github/wallabag/wallabag.git] / vendor / symfony / routing / Symfony / Component / Routing / Route.php
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 /**
15 * A Route describes a route and its parameters.
16 *
17 * @author Fabien Potencier <fabien@symfony.com>
18 * @author Tobias Schultze <http://tobion.de>
19 *
20 * @api
21 */
22 class Route implements \Serializable
23 {
24 /**
25 * @var string
26 */
27 private $path = '/';
28
29 /**
30 * @var string
31 */
32 private $host = '';
33
34 /**
35 * @var array
36 */
37 private $schemes = array();
38
39 /**
40 * @var array
41 */
42 private $methods = array();
43
44 /**
45 * @var array
46 */
47 private $defaults = array();
48
49 /**
50 * @var array
51 */
52 private $requirements = array();
53
54 /**
55 * @var array
56 */
57 private $options = array();
58
59 /**
60 * @var null|RouteCompiler
61 */
62 private $compiled;
63
64 /**
65 * Constructor.
66 *
67 * Available options:
68 *
69 * * compiler_class: A class name able to compile this route instance (RouteCompiler by default)
70 *
71 * @param string $path The path pattern to match
72 * @param array $defaults An array of default parameter values
73 * @param array $requirements An array of requirements for parameters (regexes)
74 * @param array $options An array of options
75 * @param string $host The host pattern to match
76 * @param string|array $schemes A required URI scheme or an array of restricted schemes
77 * @param string|array $methods A required HTTP method or an array of restricted methods
78 *
79 * @api
80 */
81 public function __construct($path, array $defaults = array(), array $requirements = array(), array $options = array(), $host = '', $schemes = array(), $methods = array())
82 {
83 $this->setPath($path);
84 $this->setDefaults($defaults);
85 $this->setRequirements($requirements);
86 $this->setOptions($options);
87 $this->setHost($host);
88 // The conditions make sure that an initial empty $schemes/$methods does not override the corresponding requirement.
89 // They can be removed when the BC layer is removed.
90 if ($schemes) {
91 $this->setSchemes($schemes);
92 }
93 if ($methods) {
94 $this->setMethods($methods);
95 }
96 }
97
98 public function serialize()
99 {
100 return serialize(array(
101 'path' => $this->path,
102 'host' => $this->host,
103 'defaults' => $this->defaults,
104 'requirements' => $this->requirements,
105 'options' => $this->options,
106 'schemes' => $this->schemes,
107 'methods' => $this->methods,
108 ));
109 }
110
111 public function unserialize($data)
112 {
113 $data = unserialize($data);
114 $this->path = $data['path'];
115 $this->host = $data['host'];
116 $this->defaults = $data['defaults'];
117 $this->requirements = $data['requirements'];
118 $this->options = $data['options'];
119 $this->schemes = $data['schemes'];
120 $this->methods = $data['methods'];
121 }
122
123 /**
124 * Returns the pattern for the path.
125 *
126 * @return string The pattern
127 *
128 * @deprecated Deprecated in 2.2, to be removed in 3.0. Use getPath instead.
129 */
130 public function getPattern()
131 {
132 return $this->path;
133 }
134
135 /**
136 * Sets the pattern for the path.
137 *
138 * This method implements a fluent interface.
139 *
140 * @param string $pattern The path pattern
141 *
142 * @return Route The current Route instance
143 *
144 * @deprecated Deprecated in 2.2, to be removed in 3.0. Use setPath instead.
145 */
146 public function setPattern($pattern)
147 {
148 return $this->setPath($pattern);
149 }
150
151 /**
152 * Returns the pattern for the path.
153 *
154 * @return string The path pattern
155 */
156 public function getPath()
157 {
158 return $this->path;
159 }
160
161 /**
162 * Sets the pattern for the path.
163 *
164 * This method implements a fluent interface.
165 *
166 * @param string $pattern The path pattern
167 *
168 * @return Route The current Route instance
169 */
170 public function setPath($pattern)
171 {
172 // A pattern must start with a slash and must not have multiple slashes at the beginning because the
173 // generated path for this route would be confused with a network path, e.g. '//domain.com/path'.
174 $this->path = '/'.ltrim(trim($pattern), '/');
175 $this->compiled = null;
176
177 return $this;
178 }
179
180 /**
181 * Returns the pattern for the host.
182 *
183 * @return string The host pattern
184 */
185 public function getHost()
186 {
187 return $this->host;
188 }
189
190 /**
191 * Sets the pattern for the host.
192 *
193 * This method implements a fluent interface.
194 *
195 * @param string $pattern The host pattern
196 *
197 * @return Route The current Route instance
198 */
199 public function setHost($pattern)
200 {
201 $this->host = (string) $pattern;
202 $this->compiled = null;
203
204 return $this;
205 }
206
207 /**
208 * Returns the lowercased schemes this route is restricted to.
209 * So an empty array means that any scheme is allowed.
210 *
211 * @return array The schemes
212 */
213 public function getSchemes()
214 {
215 return $this->schemes;
216 }
217
218 /**
219 * Sets the schemes (e.g. 'https') this route is restricted to.
220 * So an empty array means that any scheme is allowed.
221 *
222 * This method implements a fluent interface.
223 *
224 * @param string|array $schemes The scheme or an array of schemes
225 *
226 * @return Route The current Route instance
227 */
228 public function setSchemes($schemes)
229 {
230 $this->schemes = array_map('strtolower', (array) $schemes);
231
232 // this is to keep BC and will be removed in a future version
233 if ($this->schemes) {
234 $this->requirements['_scheme'] = implode('|', $this->schemes);
235 } else {
236 unset($this->requirements['_scheme']);
237 }
238
239 $this->compiled = null;
240
241 return $this;
242 }
243
244 /**
245 * Returns the uppercased HTTP methods this route is restricted to.
246 * So an empty array means that any method is allowed.
247 *
248 * @return array The schemes
249 */
250 public function getMethods()
251 {
252 return $this->methods;
253 }
254
255 /**
256 * Sets the HTTP methods (e.g. 'POST') this route is restricted to.
257 * So an empty array means that any method is allowed.
258 *
259 * This method implements a fluent interface.
260 *
261 * @param string|array $methods The method or an array of methods
262 *
263 * @return Route The current Route instance
264 */
265 public function setMethods($methods)
266 {
267 $this->methods = array_map('strtoupper', (array) $methods);
268
269 // this is to keep BC and will be removed in a future version
270 if ($this->methods) {
271 $this->requirements['_method'] = implode('|', $this->methods);
272 } else {
273 unset($this->requirements['_method']);
274 }
275
276 $this->compiled = null;
277
278 return $this;
279 }
280
281 /**
282 * Returns the options.
283 *
284 * @return array The options
285 */
286 public function getOptions()
287 {
288 return $this->options;
289 }
290
291 /**
292 * Sets the options.
293 *
294 * This method implements a fluent interface.
295 *
296 * @param array $options The options
297 *
298 * @return Route The current Route instance
299 */
300 public function setOptions(array $options)
301 {
302 $this->options = array(
303 'compiler_class' => 'Symfony\\Component\\Routing\\RouteCompiler',
304 );
305
306 return $this->addOptions($options);
307 }
308
309 /**
310 * Adds options.
311 *
312 * This method implements a fluent interface.
313 *
314 * @param array $options The options
315 *
316 * @return Route The current Route instance
317 */
318 public function addOptions(array $options)
319 {
320 foreach ($options as $name => $option) {
321 $this->options[$name] = $option;
322 }
323 $this->compiled = null;
324
325 return $this;
326 }
327
328 /**
329 * Sets an option value.
330 *
331 * This method implements a fluent interface.
332 *
333 * @param string $name An option name
334 * @param mixed $value The option value
335 *
336 * @return Route The current Route instance
337 *
338 * @api
339 */
340 public function setOption($name, $value)
341 {
342 $this->options[$name] = $value;
343 $this->compiled = null;
344
345 return $this;
346 }
347
348 /**
349 * Get an option value.
350 *
351 * @param string $name An option name
352 *
353 * @return mixed The option value or null when not given
354 */
355 public function getOption($name)
356 {
357 return isset($this->options[$name]) ? $this->options[$name] : null;
358 }
359
360 /**
361 * Checks if an option has been set
362 *
363 * @param string $name An option name
364 *
365 * @return Boolean true if the option is set, false otherwise
366 */
367 public function hasOption($name)
368 {
369 return array_key_exists($name, $this->options);
370 }
371
372 /**
373 * Returns the defaults.
374 *
375 * @return array The defaults
376 */
377 public function getDefaults()
378 {
379 return $this->defaults;
380 }
381
382 /**
383 * Sets the defaults.
384 *
385 * This method implements a fluent interface.
386 *
387 * @param array $defaults The defaults
388 *
389 * @return Route The current Route instance
390 */
391 public function setDefaults(array $defaults)
392 {
393 $this->defaults = array();
394
395 return $this->addDefaults($defaults);
396 }
397
398 /**
399 * Adds defaults.
400 *
401 * This method implements a fluent interface.
402 *
403 * @param array $defaults The defaults
404 *
405 * @return Route The current Route instance
406 */
407 public function addDefaults(array $defaults)
408 {
409 foreach ($defaults as $name => $default) {
410 $this->defaults[$name] = $default;
411 }
412 $this->compiled = null;
413
414 return $this;
415 }
416
417 /**
418 * Gets a default value.
419 *
420 * @param string $name A variable name
421 *
422 * @return mixed The default value or null when not given
423 */
424 public function getDefault($name)
425 {
426 return isset($this->defaults[$name]) ? $this->defaults[$name] : null;
427 }
428
429 /**
430 * Checks if a default value is set for the given variable.
431 *
432 * @param string $name A variable name
433 *
434 * @return Boolean true if the default value is set, false otherwise
435 */
436 public function hasDefault($name)
437 {
438 return array_key_exists($name, $this->defaults);
439 }
440
441 /**
442 * Sets a default value.
443 *
444 * @param string $name A variable name
445 * @param mixed $default The default value
446 *
447 * @return Route The current Route instance
448 *
449 * @api
450 */
451 public function setDefault($name, $default)
452 {
453 $this->defaults[$name] = $default;
454 $this->compiled = null;
455
456 return $this;
457 }
458
459 /**
460 * Returns the requirements.
461 *
462 * @return array The requirements
463 */
464 public function getRequirements()
465 {
466 return $this->requirements;
467 }
468
469 /**
470 * Sets the requirements.
471 *
472 * This method implements a fluent interface.
473 *
474 * @param array $requirements The requirements
475 *
476 * @return Route The current Route instance
477 */
478 public function setRequirements(array $requirements)
479 {
480 $this->requirements = array();
481
482 return $this->addRequirements($requirements);
483 }
484
485 /**
486 * Adds requirements.
487 *
488 * This method implements a fluent interface.
489 *
490 * @param array $requirements The requirements
491 *
492 * @return Route The current Route instance
493 */
494 public function addRequirements(array $requirements)
495 {
496 foreach ($requirements as $key => $regex) {
497 $this->requirements[$key] = $this->sanitizeRequirement($key, $regex);
498 }
499 $this->compiled = null;
500
501 return $this;
502 }
503
504 /**
505 * Returns the requirement for the given key.
506 *
507 * @param string $key The key
508 *
509 * @return string|null The regex or null when not given
510 */
511 public function getRequirement($key)
512 {
513 return isset($this->requirements[$key]) ? $this->requirements[$key] : null;
514 }
515
516 /**
517 * Checks if a requirement is set for the given key.
518 *
519 * @param string $key A variable name
520 *
521 * @return Boolean true if a requirement is specified, false otherwise
522 */
523 public function hasRequirement($key)
524 {
525 return array_key_exists($key, $this->requirements);
526 }
527
528 /**
529 * Sets a requirement for the given key.
530 *
531 * @param string $key The key
532 * @param string $regex The regex
533 *
534 * @return Route The current Route instance
535 *
536 * @api
537 */
538 public function setRequirement($key, $regex)
539 {
540 $this->requirements[$key] = $this->sanitizeRequirement($key, $regex);
541 $this->compiled = null;
542
543 return $this;
544 }
545
546 /**
547 * Compiles the route.
548 *
549 * @return CompiledRoute A CompiledRoute instance
550 *
551 * @throws \LogicException If the Route cannot be compiled because the
552 * path or host pattern is invalid
553 *
554 * @see RouteCompiler which is responsible for the compilation process
555 */
556 public function compile()
557 {
558 if (null !== $this->compiled) {
559 return $this->compiled;
560 }
561
562 $class = $this->getOption('compiler_class');
563
564 return $this->compiled = $class::compile($this);
565 }
566
567 private function sanitizeRequirement($key, $regex)
568 {
569 if (!is_string($regex)) {
570 throw new \InvalidArgumentException(sprintf('Routing requirement for "%s" must be a string.', $key));
571 }
572
573 if ('' !== $regex && '^' === $regex[0]) {
574 $regex = (string) substr($regex, 1); // returns false for a single character
575 }
576
577 if ('$' === substr($regex, -1)) {
578 $regex = substr($regex, 0, -1);
579 }
580
581 if ('' === $regex) {
582 throw new \InvalidArgumentException(sprintf('Routing requirement for "%s" cannot be empty.', $key));
583 }
584
585 // this is to keep BC and will be removed in a future version
586 if ('_scheme' === $key) {
587 $this->setSchemes(explode('|', $regex));
588 } elseif ('_method' === $key) {
589 $this->setMethods(explode('|', $regex));
590 }
591
592 return $regex;
593 }
594 }