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