diff options
Diffstat (limited to 'vendor/symfony/routing')
107 files changed, 10594 insertions, 0 deletions
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/.gitignore b/vendor/symfony/routing/Symfony/Component/Routing/.gitignore new file mode 100644 index 00000000..44de97a3 --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/.gitignore | |||
@@ -0,0 +1,4 @@ | |||
1 | vendor/ | ||
2 | composer.lock | ||
3 | phpunit.xml | ||
4 | |||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Annotation/Route.php b/vendor/symfony/routing/Symfony/Component/Routing/Annotation/Route.php new file mode 100644 index 00000000..abdbea27 --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Annotation/Route.php | |||
@@ -0,0 +1,156 @@ | |||
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\Annotation; | ||
13 | |||
14 | /** | ||
15 | * Annotation class for @Route(). | ||
16 | * | ||
17 | * @Annotation | ||
18 | * | ||
19 | * @author Fabien Potencier <fabien@symfony.com> | ||
20 | */ | ||
21 | class Route | ||
22 | { | ||
23 | private $path; | ||
24 | private $name; | ||
25 | private $requirements; | ||
26 | private $options; | ||
27 | private $defaults; | ||
28 | private $host; | ||
29 | private $methods; | ||
30 | private $schemes; | ||
31 | |||
32 | /** | ||
33 | * Constructor. | ||
34 | * | ||
35 | * @param array $data An array of key/value parameters. | ||
36 | * | ||
37 | * @throws \BadMethodCallException | ||
38 | */ | ||
39 | public function __construct(array $data) | ||
40 | { | ||
41 | $this->requirements = array(); | ||
42 | $this->options = array(); | ||
43 | $this->defaults = array(); | ||
44 | $this->methods = array(); | ||
45 | $this->schemes = array(); | ||
46 | |||
47 | if (isset($data['value'])) { | ||
48 | $data['path'] = $data['value']; | ||
49 | unset($data['value']); | ||
50 | } | ||
51 | |||
52 | foreach ($data as $key => $value) { | ||
53 | $method = 'set'.str_replace('_', '', $key); | ||
54 | if (!method_exists($this, $method)) { | ||
55 | throw new \BadMethodCallException(sprintf("Unknown property '%s' on annotation '%s'.", $key, get_class($this))); | ||
56 | } | ||
57 | $this->$method($value); | ||
58 | } | ||
59 | } | ||
60 | |||
61 | /** | ||
62 | * @deprecated Deprecated in 2.2, to be removed in 3.0. Use setPath instead. | ||
63 | */ | ||
64 | public function setPattern($pattern) | ||
65 | { | ||
66 | $this->path = $pattern; | ||
67 | } | ||
68 | |||
69 | /** | ||
70 | * @deprecated Deprecated in 2.2, to be removed in 3.0. Use getPath instead. | ||
71 | */ | ||
72 | public function getPattern() | ||
73 | { | ||
74 | return $this->path; | ||
75 | } | ||
76 | |||
77 | public function setPath($path) | ||
78 | { | ||
79 | $this->path = $path; | ||
80 | } | ||
81 | |||
82 | public function getPath() | ||
83 | { | ||
84 | return $this->path; | ||
85 | } | ||
86 | |||
87 | public function setHost($pattern) | ||
88 | { | ||
89 | $this->host = $pattern; | ||
90 | } | ||
91 | |||
92 | public function getHost() | ||
93 | { | ||
94 | return $this->host; | ||
95 | } | ||
96 | |||
97 | public function setName($name) | ||
98 | { | ||
99 | $this->name = $name; | ||
100 | } | ||
101 | |||
102 | public function getName() | ||
103 | { | ||
104 | return $this->name; | ||
105 | } | ||
106 | |||
107 | public function setRequirements($requirements) | ||
108 | { | ||
109 | $this->requirements = $requirements; | ||
110 | } | ||
111 | |||
112 | public function getRequirements() | ||
113 | { | ||
114 | return $this->requirements; | ||
115 | } | ||
116 | |||
117 | public function setOptions($options) | ||
118 | { | ||
119 | $this->options = $options; | ||
120 | } | ||
121 | |||
122 | public function getOptions() | ||
123 | { | ||
124 | return $this->options; | ||
125 | } | ||
126 | |||
127 | public function setDefaults($defaults) | ||
128 | { | ||
129 | $this->defaults = $defaults; | ||
130 | } | ||
131 | |||
132 | public function getDefaults() | ||
133 | { | ||
134 | return $this->defaults; | ||
135 | } | ||
136 | |||
137 | public function setSchemes($schemes) | ||
138 | { | ||
139 | $this->schemes = is_array($schemes) ? $schemes : array($schemes); | ||
140 | } | ||
141 | |||
142 | public function getSchemes() | ||
143 | { | ||
144 | return $this->schemes; | ||
145 | } | ||
146 | |||
147 | public function setMethods($methods) | ||
148 | { | ||
149 | $this->methods = is_array($methods) ? $methods : array($methods); | ||
150 | } | ||
151 | |||
152 | public function getMethods() | ||
153 | { | ||
154 | return $this->methods; | ||
155 | } | ||
156 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/CHANGELOG.md b/vendor/symfony/routing/Symfony/Component/Routing/CHANGELOG.md new file mode 100644 index 00000000..f0c616d0 --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/CHANGELOG.md | |||
@@ -0,0 +1,162 @@ | |||
1 | CHANGELOG | ||
2 | ========= | ||
3 | |||
4 | 2.3.0 | ||
5 | ----- | ||
6 | |||
7 | * added RequestContext::getQueryString() | ||
8 | |||
9 | 2.2.0 | ||
10 | ----- | ||
11 | |||
12 | * [DEPRECATION] Several route settings have been renamed (the old ones will be removed in 3.0): | ||
13 | |||
14 | * The `pattern` setting for a route has been deprecated in favor of `path` | ||
15 | * The `_scheme` and `_method` requirements have been moved to the `schemes` and `methods` settings | ||
16 | |||
17 | Before: | ||
18 | |||
19 | ``` | ||
20 | article_edit: | ||
21 | pattern: /article/{id} | ||
22 | requirements: { '_method': 'POST|PUT', '_scheme': 'https', 'id': '\d+' } | ||
23 | |||
24 | <route id="article_edit" pattern="/article/{id}"> | ||
25 | <requirement key="_method">POST|PUT</requirement> | ||
26 | <requirement key="_scheme">https</requirement> | ||
27 | <requirement key="id">\d+</requirement> | ||
28 | </route> | ||
29 | |||
30 | $route = new Route(); | ||
31 | $route->setPattern('/article/{id}'); | ||
32 | $route->setRequirement('_method', 'POST|PUT'); | ||
33 | $route->setRequirement('_scheme', 'https'); | ||
34 | ``` | ||
35 | |||
36 | After: | ||
37 | |||
38 | ``` | ||
39 | article_edit: | ||
40 | path: /article/{id} | ||
41 | methods: [POST, PUT] | ||
42 | schemes: https | ||
43 | requirements: { 'id': '\d+' } | ||
44 | |||
45 | <route id="article_edit" pattern="/article/{id}" methods="POST PUT" schemes="https"> | ||
46 | <requirement key="id">\d+</requirement> | ||
47 | </route> | ||
48 | |||
49 | $route = new Route(); | ||
50 | $route->setPath('/article/{id}'); | ||
51 | $route->setMethods(array('POST', 'PUT')); | ||
52 | $route->setSchemes('https'); | ||
53 | ``` | ||
54 | |||
55 | * [BC BREAK] RouteCollection does not behave like a tree structure anymore but as | ||
56 | a flat array of Routes. So when using PHP to build the RouteCollection, you must | ||
57 | make sure to add routes to the sub-collection before adding it to the parent | ||
58 | collection (this is not relevant when using YAML or XML for Route definitions). | ||
59 | |||
60 | Before: | ||
61 | |||
62 | ``` | ||
63 | $rootCollection = new RouteCollection(); | ||
64 | $subCollection = new RouteCollection(); | ||
65 | $rootCollection->addCollection($subCollection); | ||
66 | $subCollection->add('foo', new Route('/foo')); | ||
67 | ``` | ||
68 | |||
69 | After: | ||
70 | |||
71 | ``` | ||
72 | $rootCollection = new RouteCollection(); | ||
73 | $subCollection = new RouteCollection(); | ||
74 | $subCollection->add('foo', new Route('/foo')); | ||
75 | $rootCollection->addCollection($subCollection); | ||
76 | ``` | ||
77 | |||
78 | Also one must call `addCollection` from the bottom to the top hierarchy. | ||
79 | So the correct sequence is the following (and not the reverse): | ||
80 | |||
81 | ``` | ||
82 | $childCollection->->addCollection($grandchildCollection); | ||
83 | $rootCollection->addCollection($childCollection); | ||
84 | ``` | ||
85 | |||
86 | * [DEPRECATION] The methods `RouteCollection::getParent()` and `RouteCollection::getRoot()` | ||
87 | have been deprecated and will be removed in Symfony 2.3. | ||
88 | * [BC BREAK] Misusing the `RouteCollection::addPrefix` method to add defaults, requirements | ||
89 | or options without adding a prefix is not supported anymore. So if you called `addPrefix` | ||
90 | with an empty prefix or `/` only (both have no relevance), like | ||
91 | `addPrefix('', $defaultsArray, $requirementsArray, $optionsArray)` | ||
92 | you need to use the new dedicated methods `addDefaults($defaultsArray)`, | ||
93 | `addRequirements($requirementsArray)` or `addOptions($optionsArray)` instead. | ||
94 | * [DEPRECATION] The `$options` parameter to `RouteCollection::addPrefix()` has been deprecated | ||
95 | because adding options has nothing to do with adding a path prefix. If you want to add options | ||
96 | to all child routes of a RouteCollection, you can use `addOptions()`. | ||
97 | * [DEPRECATION] The method `RouteCollection::getPrefix()` has been deprecated | ||
98 | because it suggested that all routes in the collection would have this prefix, which is | ||
99 | not necessarily true. On top of that, since there is no tree structure anymore, this method | ||
100 | is also useless. Don't worry about performance, prefix optimization for matching is still done | ||
101 | in the dumper, which was also improved in 2.2.0 to find even more grouping possibilities. | ||
102 | * [DEPRECATION] `RouteCollection::addCollection(RouteCollection $collection)` should now only be | ||
103 | used with a single parameter. The other params `$prefix`, `$default`, `$requirements` and `$options` | ||
104 | will still work, but have been deprecated. The `addPrefix` method should be used for this | ||
105 | use-case instead. | ||
106 | Before: `$parentCollection->addCollection($collection, '/prefix', array(...), array(...))` | ||
107 | After: | ||
108 | ``` | ||
109 | $collection->addPrefix('/prefix', array(...), array(...)); | ||
110 | $parentCollection->addCollection($collection); | ||
111 | ``` | ||
112 | * added support for the method default argument values when defining a @Route | ||
113 | * Adjacent placeholders without separator work now, e.g. `/{x}{y}{z}.{_format}`. | ||
114 | * Characters that function as separator between placeholders are now whitelisted | ||
115 | to fix routes with normal text around a variable, e.g. `/prefix{var}suffix`. | ||
116 | * [BC BREAK] The default requirement of a variable has been changed slightly. | ||
117 | Previously it disallowed the previous and the next char around a variable. Now | ||
118 | it disallows the slash (`/`) and the next char. Using the previous char added | ||
119 | no value and was problematic because the route `/index.{_format}` would be | ||
120 | matched by `/index.ht/ml`. | ||
121 | * The default requirement now uses possessive quantifiers when possible which | ||
122 | improves matching performance by up to 20% because it prevents backtracking | ||
123 | when it's not needed. | ||
124 | * The ConfigurableRequirementsInterface can now also be used to disable the requirements | ||
125 | check on URL generation completely by calling `setStrictRequirements(null)`. It | ||
126 | improves performance in production environment as you should know that params always | ||
127 | pass the requirements (otherwise it would break your link anyway). | ||
128 | * There is no restriction on the route name anymore. So non-alphanumeric characters | ||
129 | are now also allowed. | ||
130 | * [BC BREAK] `RouteCompilerInterface::compile(Route $route)` was made static | ||
131 | (only relevant if you implemented your own RouteCompiler). | ||
132 | * Added possibility to generate relative paths and network paths in the UrlGenerator, e.g. | ||
133 | "../parent-file" and "//example.com/dir/file". The third parameter in | ||
134 | `UrlGeneratorInterface::generate($name, $parameters = array(), $referenceType = self::ABSOLUTE_PATH)` | ||
135 | now accepts more values and you should use the constants defined in `UrlGeneratorInterface` for | ||
136 | claritiy. The old method calls with a Boolean parameter will continue to work because they | ||
137 | equal the signature using the constants. | ||
138 | |||
139 | 2.1.0 | ||
140 | ----- | ||
141 | |||
142 | * added RequestMatcherInterface | ||
143 | * added RequestContext::fromRequest() | ||
144 | * the UrlMatcher does not throw a \LogicException anymore when the required | ||
145 | scheme is not the current one | ||
146 | * added TraceableUrlMatcher | ||
147 | * added the possibility to define options, default values and requirements | ||
148 | for placeholders in prefix, including imported routes | ||
149 | * added RouterInterface::getRouteCollection | ||
150 | * [BC BREAK] the UrlMatcher urldecodes the route parameters only once, they | ||
151 | were decoded twice before. Note that the `urldecode()` calls have been | ||
152 | changed for a single `rawurldecode()` in order to support `+` for input | ||
153 | paths. | ||
154 | * added RouteCollection::getRoot method to retrieve the root of a | ||
155 | RouteCollection tree | ||
156 | * [BC BREAK] made RouteCollection::setParent private which could not have | ||
157 | been used anyway without creating inconsistencies | ||
158 | * [BC BREAK] RouteCollection::remove also removes a route from parent | ||
159 | collections (not only from its children) | ||
160 | * added ConfigurableRequirementsInterface that allows to disable exceptions | ||
161 | (and generate empty URLs instead) when generating a route with an invalid | ||
162 | parameter value | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/CompiledRoute.php b/vendor/symfony/routing/Symfony/Component/Routing/CompiledRoute.php new file mode 100644 index 00000000..78784554 --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/CompiledRoute.php | |||
@@ -0,0 +1,134 @@ | |||
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 | * CompiledRoutes are returned by the RouteCompiler class. | ||
16 | * | ||
17 | * @author Fabien Potencier <fabien@symfony.com> | ||
18 | */ | ||
19 | class CompiledRoute | ||
20 | { | ||
21 | private $variables; | ||
22 | private $tokens; | ||
23 | private $staticPrefix; | ||
24 | private $regex; | ||
25 | private $pathVariables; | ||
26 | private $hostVariables; | ||
27 | private $hostRegex; | ||
28 | private $hostTokens; | ||
29 | |||
30 | /** | ||
31 | * Constructor. | ||
32 | * | ||
33 | * @param string $staticPrefix The static prefix of the compiled route | ||
34 | * @param string $regex The regular expression to use to match this route | ||
35 | * @param array $tokens An array of tokens to use to generate URL for this route | ||
36 | * @param array $pathVariables An array of path variables | ||
37 | * @param string|null $hostRegex Host regex | ||
38 | * @param array $hostTokens Host tokens | ||
39 | * @param array $hostVariables An array of host variables | ||
40 | * @param array $variables An array of variables (variables defined in the path and in the host patterns) | ||
41 | */ | ||
42 | public function __construct($staticPrefix, $regex, array $tokens, array $pathVariables, $hostRegex = null, array $hostTokens = array(), array $hostVariables = array(), array $variables = array()) | ||
43 | { | ||
44 | $this->staticPrefix = (string) $staticPrefix; | ||
45 | $this->regex = $regex; | ||
46 | $this->tokens = $tokens; | ||
47 | $this->pathVariables = $pathVariables; | ||
48 | $this->hostRegex = $hostRegex; | ||
49 | $this->hostTokens = $hostTokens; | ||
50 | $this->hostVariables = $hostVariables; | ||
51 | $this->variables = $variables; | ||
52 | } | ||
53 | |||
54 | /** | ||
55 | * Returns the static prefix. | ||
56 | * | ||
57 | * @return string The static prefix | ||
58 | */ | ||
59 | public function getStaticPrefix() | ||
60 | { | ||
61 | return $this->staticPrefix; | ||
62 | } | ||
63 | |||
64 | /** | ||
65 | * Returns the regex. | ||
66 | * | ||
67 | * @return string The regex | ||
68 | */ | ||
69 | public function getRegex() | ||
70 | { | ||
71 | return $this->regex; | ||
72 | } | ||
73 | |||
74 | /** | ||
75 | * Returns the host regex | ||
76 | * | ||
77 | * @return string|null The host regex or null | ||
78 | */ | ||
79 | public function getHostRegex() | ||
80 | { | ||
81 | return $this->hostRegex; | ||
82 | } | ||
83 | |||
84 | /** | ||
85 | * Returns the tokens. | ||
86 | * | ||
87 | * @return array The tokens | ||
88 | */ | ||
89 | public function getTokens() | ||
90 | { | ||
91 | return $this->tokens; | ||
92 | } | ||
93 | |||
94 | /** | ||
95 | * Returns the host tokens. | ||
96 | * | ||
97 | * @return array The tokens | ||
98 | */ | ||
99 | public function getHostTokens() | ||
100 | { | ||
101 | return $this->hostTokens; | ||
102 | } | ||
103 | |||
104 | /** | ||
105 | * Returns the variables. | ||
106 | * | ||
107 | * @return array The variables | ||
108 | */ | ||
109 | public function getVariables() | ||
110 | { | ||
111 | return $this->variables; | ||
112 | } | ||
113 | |||
114 | /** | ||
115 | * Returns the path variables. | ||
116 | * | ||
117 | * @return array The variables | ||
118 | */ | ||
119 | public function getPathVariables() | ||
120 | { | ||
121 | return $this->pathVariables; | ||
122 | } | ||
123 | |||
124 | /** | ||
125 | * Returns the host variables. | ||
126 | * | ||
127 | * @return array The variables | ||
128 | */ | ||
129 | public function getHostVariables() | ||
130 | { | ||
131 | return $this->hostVariables; | ||
132 | } | ||
133 | |||
134 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Exception/ExceptionInterface.php b/vendor/symfony/routing/Symfony/Component/Routing/Exception/ExceptionInterface.php new file mode 100644 index 00000000..5289f525 --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Exception/ExceptionInterface.php | |||
@@ -0,0 +1,23 @@ | |||
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\Exception; | ||
13 | |||
14 | /** | ||
15 | * ExceptionInterface | ||
16 | * | ||
17 | * @author Alexandre Salomé <alexandre.salome@gmail.com> | ||
18 | * | ||
19 | * @api | ||
20 | */ | ||
21 | interface ExceptionInterface | ||
22 | { | ||
23 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Exception/InvalidParameterException.php b/vendor/symfony/routing/Symfony/Component/Routing/Exception/InvalidParameterException.php new file mode 100644 index 00000000..4f124695 --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Exception/InvalidParameterException.php | |||
@@ -0,0 +1,23 @@ | |||
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\Exception; | ||
13 | |||
14 | /** | ||
15 | * Exception thrown when a parameter is not valid | ||
16 | * | ||
17 | * @author Alexandre Salomé <alexandre.salome@gmail.com> | ||
18 | * | ||
19 | * @api | ||
20 | */ | ||
21 | class InvalidParameterException extends \InvalidArgumentException implements ExceptionInterface | ||
22 | { | ||
23 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Exception/MethodNotAllowedException.php b/vendor/symfony/routing/Symfony/Component/Routing/Exception/MethodNotAllowedException.php new file mode 100644 index 00000000..32f10913 --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Exception/MethodNotAllowedException.php | |||
@@ -0,0 +1,46 @@ | |||
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\Exception; | ||
13 | |||
14 | /** | ||
15 | * The resource was found but the request method is not allowed. | ||
16 | * | ||
17 | * This exception should trigger an HTTP 405 response in your application code. | ||
18 | * | ||
19 | * @author Kris Wallsmith <kris@symfony.com> | ||
20 | * | ||
21 | * @api | ||
22 | */ | ||
23 | class MethodNotAllowedException extends \RuntimeException implements ExceptionInterface | ||
24 | { | ||
25 | /** | ||
26 | * @var array | ||
27 | */ | ||
28 | protected $allowedMethods = array(); | ||
29 | |||
30 | public function __construct(array $allowedMethods, $message = null, $code = 0, \Exception $previous = null) | ||
31 | { | ||
32 | $this->allowedMethods = array_map('strtoupper', $allowedMethods); | ||
33 | |||
34 | parent::__construct($message, $code, $previous); | ||
35 | } | ||
36 | |||
37 | /** | ||
38 | * Gets the allowed HTTP methods. | ||
39 | * | ||
40 | * @return array | ||
41 | */ | ||
42 | public function getAllowedMethods() | ||
43 | { | ||
44 | return $this->allowedMethods; | ||
45 | } | ||
46 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Exception/MissingMandatoryParametersException.php b/vendor/symfony/routing/Symfony/Component/Routing/Exception/MissingMandatoryParametersException.php new file mode 100644 index 00000000..5a523fa5 --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Exception/MissingMandatoryParametersException.php | |||
@@ -0,0 +1,24 @@ | |||
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\Exception; | ||
13 | |||
14 | /** | ||
15 | * Exception thrown when a route cannot be generated because of missing | ||
16 | * mandatory parameters. | ||
17 | * | ||
18 | * @author Alexandre Salomé <alexandre.salome@gmail.com> | ||
19 | * | ||
20 | * @api | ||
21 | */ | ||
22 | class MissingMandatoryParametersException extends \InvalidArgumentException implements ExceptionInterface | ||
23 | { | ||
24 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Exception/ResourceNotFoundException.php b/vendor/symfony/routing/Symfony/Component/Routing/Exception/ResourceNotFoundException.php new file mode 100644 index 00000000..362a0d61 --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Exception/ResourceNotFoundException.php | |||
@@ -0,0 +1,25 @@ | |||
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\Exception; | ||
13 | |||
14 | /** | ||
15 | * The resource was not found. | ||
16 | * | ||
17 | * This exception should trigger an HTTP 404 response in your application code. | ||
18 | * | ||
19 | * @author Kris Wallsmith <kris@symfony.com> | ||
20 | * | ||
21 | * @api | ||
22 | */ | ||
23 | class ResourceNotFoundException extends \RuntimeException implements ExceptionInterface | ||
24 | { | ||
25 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Exception/RouteNotFoundException.php b/vendor/symfony/routing/Symfony/Component/Routing/Exception/RouteNotFoundException.php new file mode 100644 index 00000000..4d5f288e --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Exception/RouteNotFoundException.php | |||
@@ -0,0 +1,23 @@ | |||
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\Exception; | ||
13 | |||
14 | /** | ||
15 | * Exception thrown when a route does not exists | ||
16 | * | ||
17 | * @author Alexandre Salomé <alexandre.salome@gmail.com> | ||
18 | * | ||
19 | * @api | ||
20 | */ | ||
21 | class RouteNotFoundException extends \InvalidArgumentException implements ExceptionInterface | ||
22 | { | ||
23 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Generator/ConfigurableRequirementsInterface.php b/vendor/symfony/routing/Symfony/Component/Routing/Generator/ConfigurableRequirementsInterface.php new file mode 100644 index 00000000..5925838c --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Generator/ConfigurableRequirementsInterface.php | |||
@@ -0,0 +1,55 @@ | |||
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\Generator; | ||
13 | |||
14 | /** | ||
15 | * ConfigurableRequirementsInterface must be implemented by URL generators that | ||
16 | * can be configured whether an exception should be generated when the parameters | ||
17 | * do not match the requirements. It is also possible to disable the requirements | ||
18 | * check for URL generation completely. | ||
19 | * | ||
20 | * The possible configurations and use-cases: | ||
21 | * - setStrictRequirements(true): Throw an exception for mismatching requirements. This | ||
22 | * is mostly useful in development environment. | ||
23 | * - setStrictRequirements(false): Don't throw an exception but return null as URL for | ||
24 | * mismatching requirements and log the problem. Useful when you cannot control all | ||
25 | * params because they come from third party libs but don't want to have a 404 in | ||
26 | * production environment. It should log the mismatch so one can review it. | ||
27 | * - setStrictRequirements(null): Return the URL with the given parameters without | ||
28 | * checking the requirements at all. When generating an URL you should either trust | ||
29 | * your params or you validated them beforehand because otherwise it would break your | ||
30 | * link anyway. So in production environment you should know that params always pass | ||
31 | * the requirements. Thus this option allows to disable the check on URL generation for | ||
32 | * performance reasons (saving a preg_match for each requirement every time a URL is | ||
33 | * generated). | ||
34 | * | ||
35 | * @author Fabien Potencier <fabien@symfony.com> | ||
36 | * @author Tobias Schultze <http://tobion.de> | ||
37 | */ | ||
38 | interface ConfigurableRequirementsInterface | ||
39 | { | ||
40 | /** | ||
41 | * Enables or disables the exception on incorrect parameters. | ||
42 | * Passing null will deactivate the requirements check completely. | ||
43 | * | ||
44 | * @param Boolean|null $enabled | ||
45 | */ | ||
46 | public function setStrictRequirements($enabled); | ||
47 | |||
48 | /** | ||
49 | * Returns whether to throw an exception on incorrect parameters. | ||
50 | * Null means the requirements check is deactivated completely. | ||
51 | * | ||
52 | * @return Boolean|null | ||
53 | */ | ||
54 | public function isStrictRequirements(); | ||
55 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Generator/Dumper/GeneratorDumper.php b/vendor/symfony/routing/Symfony/Component/Routing/Generator/Dumper/GeneratorDumper.php new file mode 100644 index 00000000..4739bd83 --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Generator/Dumper/GeneratorDumper.php | |||
@@ -0,0 +1,45 @@ | |||
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\Generator\Dumper; | ||
13 | |||
14 | use Symfony\Component\Routing\RouteCollection; | ||
15 | |||
16 | /** | ||
17 | * GeneratorDumper is the base class for all built-in generator dumpers. | ||
18 | * | ||
19 | * @author Fabien Potencier <fabien@symfony.com> | ||
20 | */ | ||
21 | abstract class GeneratorDumper implements GeneratorDumperInterface | ||
22 | { | ||
23 | /** | ||
24 | * @var RouteCollection | ||
25 | */ | ||
26 | private $routes; | ||
27 | |||
28 | /** | ||
29 | * Constructor. | ||
30 | * | ||
31 | * @param RouteCollection $routes The RouteCollection to dump | ||
32 | */ | ||
33 | public function __construct(RouteCollection $routes) | ||
34 | { | ||
35 | $this->routes = $routes; | ||
36 | } | ||
37 | |||
38 | /** | ||
39 | * {@inheritdoc} | ||
40 | */ | ||
41 | public function getRoutes() | ||
42 | { | ||
43 | return $this->routes; | ||
44 | } | ||
45 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Generator/Dumper/GeneratorDumperInterface.php b/vendor/symfony/routing/Symfony/Component/Routing/Generator/Dumper/GeneratorDumperInterface.php new file mode 100644 index 00000000..deb0c0a2 --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Generator/Dumper/GeneratorDumperInterface.php | |||
@@ -0,0 +1,41 @@ | |||
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\Generator\Dumper; | ||
13 | |||
14 | use Symfony\Component\Routing\RouteCollection; | ||
15 | |||
16 | /** | ||
17 | * GeneratorDumperInterface is the interface that all generator dumper classes must implement. | ||
18 | * | ||
19 | * @author Fabien Potencier <fabien@symfony.com> | ||
20 | * | ||
21 | * @api | ||
22 | */ | ||
23 | interface GeneratorDumperInterface | ||
24 | { | ||
25 | /** | ||
26 | * Dumps a set of routes to a string representation of executable code | ||
27 | * that can then be used to generate a URL of such a route. | ||
28 | * | ||
29 | * @param array $options An array of options | ||
30 | * | ||
31 | * @return string Executable code | ||
32 | */ | ||
33 | public function dump(array $options = array()); | ||
34 | |||
35 | /** | ||
36 | * Gets the routes to dump. | ||
37 | * | ||
38 | * @return RouteCollection A RouteCollection instance | ||
39 | */ | ||
40 | public function getRoutes(); | ||
41 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Generator/Dumper/PhpGeneratorDumper.php b/vendor/symfony/routing/Symfony/Component/Routing/Generator/Dumper/PhpGeneratorDumper.php new file mode 100644 index 00000000..42cd9108 --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Generator/Dumper/PhpGeneratorDumper.php | |||
@@ -0,0 +1,123 @@ | |||
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\Generator\Dumper; | ||
13 | |||
14 | /** | ||
15 | * PhpGeneratorDumper creates a PHP class able to generate URLs for a given set of routes. | ||
16 | * | ||
17 | * @author Fabien Potencier <fabien@symfony.com> | ||
18 | * @author Tobias Schultze <http://tobion.de> | ||
19 | * | ||
20 | * @api | ||
21 | */ | ||
22 | class PhpGeneratorDumper extends GeneratorDumper | ||
23 | { | ||
24 | /** | ||
25 | * Dumps a set of routes to a PHP class. | ||
26 | * | ||
27 | * Available options: | ||
28 | * | ||
29 | * * class: The class name | ||
30 | * * base_class: The base class name | ||
31 | * | ||
32 | * @param array $options An array of options | ||
33 | * | ||
34 | * @return string A PHP class representing the generator class | ||
35 | * | ||
36 | * @api | ||
37 | */ | ||
38 | public function dump(array $options = array()) | ||
39 | { | ||
40 | $options = array_merge(array( | ||
41 | 'class' => 'ProjectUrlGenerator', | ||
42 | 'base_class' => 'Symfony\\Component\\Routing\\Generator\\UrlGenerator', | ||
43 | ), $options); | ||
44 | |||
45 | return <<<EOF | ||
46 | <?php | ||
47 | |||
48 | use Symfony\Component\Routing\RequestContext; | ||
49 | use Symfony\Component\Routing\Exception\RouteNotFoundException; | ||
50 | use Psr\Log\LoggerInterface; | ||
51 | |||
52 | /** | ||
53 | * {$options['class']} | ||
54 | * | ||
55 | * This class has been auto-generated | ||
56 | * by the Symfony Routing Component. | ||
57 | */ | ||
58 | class {$options['class']} extends {$options['base_class']} | ||
59 | { | ||
60 | static private \$declaredRoutes = {$this->generateDeclaredRoutes()}; | ||
61 | |||
62 | /** | ||
63 | * Constructor. | ||
64 | */ | ||
65 | public function __construct(RequestContext \$context, LoggerInterface \$logger = null) | ||
66 | { | ||
67 | \$this->context = \$context; | ||
68 | \$this->logger = \$logger; | ||
69 | } | ||
70 | |||
71 | {$this->generateGenerateMethod()} | ||
72 | } | ||
73 | |||
74 | EOF; | ||
75 | } | ||
76 | |||
77 | /** | ||
78 | * Generates PHP code representing an array of defined routes | ||
79 | * together with the routes properties (e.g. requirements). | ||
80 | * | ||
81 | * @return string PHP code | ||
82 | */ | ||
83 | private function generateDeclaredRoutes() | ||
84 | { | ||
85 | $routes = "array(\n"; | ||
86 | foreach ($this->getRoutes()->all() as $name => $route) { | ||
87 | $compiledRoute = $route->compile(); | ||
88 | |||
89 | $properties = array(); | ||
90 | $properties[] = $compiledRoute->getVariables(); | ||
91 | $properties[] = $route->getDefaults(); | ||
92 | $properties[] = $route->getRequirements(); | ||
93 | $properties[] = $compiledRoute->getTokens(); | ||
94 | $properties[] = $compiledRoute->getHostTokens(); | ||
95 | |||
96 | $routes .= sprintf(" '%s' => %s,\n", $name, str_replace("\n", '', var_export($properties, true))); | ||
97 | } | ||
98 | $routes .= ' )'; | ||
99 | |||
100 | return $routes; | ||
101 | } | ||
102 | |||
103 | /** | ||
104 | * Generates PHP code representing the `generate` method that implements the UrlGeneratorInterface. | ||
105 | * | ||
106 | * @return string PHP code | ||
107 | */ | ||
108 | private function generateGenerateMethod() | ||
109 | { | ||
110 | return <<<EOF | ||
111 | public function generate(\$name, \$parameters = array(), \$referenceType = self::ABSOLUTE_PATH) | ||
112 | { | ||
113 | if (!isset(self::\$declaredRoutes[\$name])) { | ||
114 | throw new RouteNotFoundException(sprintf('Unable to generate a URL for the named route "%s" as such route does not exist.', \$name)); | ||
115 | } | ||
116 | |||
117 | list(\$variables, \$defaults, \$requirements, \$tokens, \$hostTokens) = self::\$declaredRoutes[\$name]; | ||
118 | |||
119 | return \$this->doGenerate(\$variables, \$defaults, \$requirements, \$tokens, \$parameters, \$name, \$referenceType, \$hostTokens); | ||
120 | } | ||
121 | EOF; | ||
122 | } | ||
123 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Generator/UrlGenerator.php b/vendor/symfony/routing/Symfony/Component/Routing/Generator/UrlGenerator.php new file mode 100644 index 00000000..f224cb3f --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Generator/UrlGenerator.php | |||
@@ -0,0 +1,322 @@ | |||
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\Generator; | ||
13 | |||
14 | use Symfony\Component\Routing\RouteCollection; | ||
15 | use Symfony\Component\Routing\RequestContext; | ||
16 | use Symfony\Component\Routing\Exception\InvalidParameterException; | ||
17 | use Symfony\Component\Routing\Exception\RouteNotFoundException; | ||
18 | use Symfony\Component\Routing\Exception\MissingMandatoryParametersException; | ||
19 | use Psr\Log\LoggerInterface; | ||
20 | |||
21 | /** | ||
22 | * UrlGenerator can generate a URL or a path for any route in the RouteCollection | ||
23 | * based on the passed parameters. | ||
24 | * | ||
25 | * @author Fabien Potencier <fabien@symfony.com> | ||
26 | * @author Tobias Schultze <http://tobion.de> | ||
27 | * | ||
28 | * @api | ||
29 | */ | ||
30 | class UrlGenerator implements UrlGeneratorInterface, ConfigurableRequirementsInterface | ||
31 | { | ||
32 | /** | ||
33 | * @var RouteCollection | ||
34 | */ | ||
35 | protected $routes; | ||
36 | |||
37 | /** | ||
38 | * @var RequestContext | ||
39 | */ | ||
40 | protected $context; | ||
41 | |||
42 | /** | ||
43 | * @var Boolean|null | ||
44 | */ | ||
45 | protected $strictRequirements = true; | ||
46 | |||
47 | /** | ||
48 | * @var LoggerInterface|null | ||
49 | */ | ||
50 | protected $logger; | ||
51 | |||
52 | /** | ||
53 | * This array defines the characters (besides alphanumeric ones) that will not be percent-encoded in the path segment of the generated URL. | ||
54 | * | ||
55 | * PHP's rawurlencode() encodes all chars except "a-zA-Z0-9-._~" according to RFC 3986. But we want to allow some chars | ||
56 | * to be used in their literal form (reasons below). Other chars inside the path must of course be encoded, e.g. | ||
57 | * "?" and "#" (would be interpreted wrongly as query and fragment identifier), | ||
58 | * "'" and """ (are used as delimiters in HTML). | ||
59 | */ | ||
60 | protected $decodedChars = array( | ||
61 | // the slash can be used to designate a hierarchical structure and we want allow using it with this meaning | ||
62 | // some webservers don't allow the slash in encoded form in the path for security reasons anyway | ||
63 | // see http://stackoverflow.com/questions/4069002/http-400-if-2f-part-of-get-url-in-jboss | ||
64 | '%2F' => '/', | ||
65 | // the following chars are general delimiters in the URI specification but have only special meaning in the authority component | ||
66 | // so they can safely be used in the path in unencoded form | ||
67 | '%40' => '@', | ||
68 | '%3A' => ':', | ||
69 | // these chars are only sub-delimiters that have no predefined meaning and can therefore be used literally | ||
70 | // so URI producing applications can use these chars to delimit subcomponents in a path segment without being encoded for better readability | ||
71 | '%3B' => ';', | ||
72 | '%2C' => ',', | ||
73 | '%3D' => '=', | ||
74 | '%2B' => '+', | ||
75 | '%21' => '!', | ||
76 | '%2A' => '*', | ||
77 | '%7C' => '|', | ||
78 | ); | ||
79 | |||
80 | /** | ||
81 | * Constructor. | ||
82 | * | ||
83 | * @param RouteCollection $routes A RouteCollection instance | ||
84 | * @param RequestContext $context The context | ||
85 | * @param LoggerInterface|null $logger A logger instance | ||
86 | * | ||
87 | * @api | ||
88 | */ | ||
89 | public function __construct(RouteCollection $routes, RequestContext $context, LoggerInterface $logger = null) | ||
90 | { | ||
91 | $this->routes = $routes; | ||
92 | $this->context = $context; | ||
93 | $this->logger = $logger; | ||
94 | } | ||
95 | |||
96 | /** | ||
97 | * {@inheritdoc} | ||
98 | */ | ||
99 | public function setContext(RequestContext $context) | ||
100 | { | ||
101 | $this->context = $context; | ||
102 | } | ||
103 | |||
104 | /** | ||
105 | * {@inheritdoc} | ||
106 | */ | ||
107 | public function getContext() | ||
108 | { | ||
109 | return $this->context; | ||
110 | } | ||
111 | |||
112 | /** | ||
113 | * {@inheritdoc} | ||
114 | */ | ||
115 | public function setStrictRequirements($enabled) | ||
116 | { | ||
117 | $this->strictRequirements = null === $enabled ? null : (Boolean) $enabled; | ||
118 | } | ||
119 | |||
120 | /** | ||
121 | * {@inheritdoc} | ||
122 | */ | ||
123 | public function isStrictRequirements() | ||
124 | { | ||
125 | return $this->strictRequirements; | ||
126 | } | ||
127 | |||
128 | /** | ||
129 | * {@inheritDoc} | ||
130 | */ | ||
131 | public function generate($name, $parameters = array(), $referenceType = self::ABSOLUTE_PATH) | ||
132 | { | ||
133 | if (null === $route = $this->routes->get($name)) { | ||
134 | throw new RouteNotFoundException(sprintf('Unable to generate a URL for the named route "%s" as such route does not exist.', $name)); | ||
135 | } | ||
136 | |||
137 | // the Route has a cache of its own and is not recompiled as long as it does not get modified | ||
138 | $compiledRoute = $route->compile(); | ||
139 | |||
140 | return $this->doGenerate($compiledRoute->getVariables(), $route->getDefaults(), $route->getRequirements(), $compiledRoute->getTokens(), $parameters, $name, $referenceType, $compiledRoute->getHostTokens()); | ||
141 | } | ||
142 | |||
143 | /** | ||
144 | * @throws MissingMandatoryParametersException When some parameters are missing that are mandatory for the route | ||
145 | * @throws InvalidParameterException When a parameter value for a placeholder is not correct because | ||
146 | * it does not match the requirement | ||
147 | */ | ||
148 | protected function doGenerate($variables, $defaults, $requirements, $tokens, $parameters, $name, $referenceType, $hostTokens) | ||
149 | { | ||
150 | $variables = array_flip($variables); | ||
151 | $mergedParams = array_replace($defaults, $this->context->getParameters(), $parameters); | ||
152 | |||
153 | // all params must be given | ||
154 | if ($diff = array_diff_key($variables, $mergedParams)) { | ||
155 | throw new MissingMandatoryParametersException(sprintf('Some mandatory parameters are missing ("%s") to generate a URL for route "%s".', implode('", "', array_keys($diff)), $name)); | ||
156 | } | ||
157 | |||
158 | $url = ''; | ||
159 | $optional = true; | ||
160 | foreach ($tokens as $token) { | ||
161 | if ('variable' === $token[0]) { | ||
162 | if (!$optional || !array_key_exists($token[3], $defaults) || null !== $mergedParams[$token[3]] && (string) $mergedParams[$token[3]] !== (string) $defaults[$token[3]]) { | ||
163 | // check requirement | ||
164 | if (null !== $this->strictRequirements && !preg_match('#^'.$token[2].'$#', $mergedParams[$token[3]])) { | ||
165 | $message = sprintf('Parameter "%s" for route "%s" must match "%s" ("%s" given) to generate a corresponding URL.', $token[3], $name, $token[2], $mergedParams[$token[3]]); | ||
166 | if ($this->strictRequirements) { | ||
167 | throw new InvalidParameterException($message); | ||
168 | } | ||
169 | |||
170 | if ($this->logger) { | ||
171 | $this->logger->error($message); | ||
172 | } | ||
173 | |||
174 | return null; | ||
175 | } | ||
176 | |||
177 | $url = $token[1].$mergedParams[$token[3]].$url; | ||
178 | $optional = false; | ||
179 | } | ||
180 | } else { | ||
181 | // static text | ||
182 | $url = $token[1].$url; | ||
183 | $optional = false; | ||
184 | } | ||
185 | } | ||
186 | |||
187 | if ('' === $url) { | ||
188 | $url = '/'; | ||
189 | } | ||
190 | |||
191 | // the contexts base url is already encoded (see Symfony\Component\HttpFoundation\Request) | ||
192 | $url = strtr(rawurlencode($url), $this->decodedChars); | ||
193 | |||
194 | // the path segments "." and ".." are interpreted as relative reference when resolving a URI; see http://tools.ietf.org/html/rfc3986#section-3.3 | ||
195 | // so we need to encode them as they are not used for this purpose here | ||
196 | // otherwise we would generate a URI that, when followed by a user agent (e.g. browser), does not match this route | ||
197 | $url = strtr($url, array('/../' => '/%2E%2E/', '/./' => '/%2E/')); | ||
198 | if ('/..' === substr($url, -3)) { | ||
199 | $url = substr($url, 0, -2).'%2E%2E'; | ||
200 | } elseif ('/.' === substr($url, -2)) { | ||
201 | $url = substr($url, 0, -1).'%2E'; | ||
202 | } | ||
203 | |||
204 | $schemeAuthority = ''; | ||
205 | if ($host = $this->context->getHost()) { | ||
206 | $scheme = $this->context->getScheme(); | ||
207 | if (isset($requirements['_scheme']) && ($req = strtolower($requirements['_scheme'])) && $scheme !== $req) { | ||
208 | $referenceType = self::ABSOLUTE_URL; | ||
209 | $scheme = $req; | ||
210 | } | ||
211 | |||
212 | if ($hostTokens) { | ||
213 | $routeHost = ''; | ||
214 | foreach ($hostTokens as $token) { | ||
215 | if ('variable' === $token[0]) { | ||
216 | if (null !== $this->strictRequirements && !preg_match('#^'.$token[2].'$#', $mergedParams[$token[3]])) { | ||
217 | $message = sprintf('Parameter "%s" for route "%s" must match "%s" ("%s" given) to generate a corresponding URL.', $token[3], $name, $token[2], $mergedParams[$token[3]]); | ||
218 | |||
219 | if ($this->strictRequirements) { | ||
220 | throw new InvalidParameterException($message); | ||
221 | } | ||
222 | |||
223 | if ($this->logger) { | ||
224 | $this->logger->error($message); | ||
225 | } | ||
226 | |||
227 | return null; | ||
228 | } | ||
229 | |||
230 | $routeHost = $token[1].$mergedParams[$token[3]].$routeHost; | ||
231 | } else { | ||
232 | $routeHost = $token[1].$routeHost; | ||
233 | } | ||
234 | } | ||
235 | |||
236 | if ($routeHost !== $host) { | ||
237 | $host = $routeHost; | ||
238 | if (self::ABSOLUTE_URL !== $referenceType) { | ||
239 | $referenceType = self::NETWORK_PATH; | ||
240 | } | ||
241 | } | ||
242 | } | ||
243 | |||
244 | if (self::ABSOLUTE_URL === $referenceType || self::NETWORK_PATH === $referenceType) { | ||
245 | $port = ''; | ||
246 | if ('http' === $scheme && 80 != $this->context->getHttpPort()) { | ||
247 | $port = ':'.$this->context->getHttpPort(); | ||
248 | } elseif ('https' === $scheme && 443 != $this->context->getHttpsPort()) { | ||
249 | $port = ':'.$this->context->getHttpsPort(); | ||
250 | } | ||
251 | |||
252 | $schemeAuthority = self::NETWORK_PATH === $referenceType ? '//' : "$scheme://"; | ||
253 | $schemeAuthority .= $host.$port; | ||
254 | } | ||
255 | } | ||
256 | |||
257 | if (self::RELATIVE_PATH === $referenceType) { | ||
258 | $url = self::getRelativePath($this->context->getPathInfo(), $url); | ||
259 | } else { | ||
260 | $url = $schemeAuthority.$this->context->getBaseUrl().$url; | ||
261 | } | ||
262 | |||
263 | // add a query string if needed | ||
264 | $extra = array_diff_key($parameters, $variables, $defaults); | ||
265 | if ($extra && $query = http_build_query($extra, '', '&')) { | ||
266 | $url .= '?'.$query; | ||
267 | } | ||
268 | |||
269 | return $url; | ||
270 | } | ||
271 | |||
272 | /** | ||
273 | * Returns the target path as relative reference from the base path. | ||
274 | * | ||
275 | * Only the URIs path component (no schema, host etc.) is relevant and must be given, starting with a slash. | ||
276 | * Both paths must be absolute and not contain relative parts. | ||
277 | * Relative URLs from one resource to another are useful when generating self-contained downloadable document archives. | ||
278 | * Furthermore, they can be used to reduce the link size in documents. | ||
279 | * | ||
280 | * Example target paths, given a base path of "/a/b/c/d": | ||
281 | * - "/a/b/c/d" -> "" | ||
282 | * - "/a/b/c/" -> "./" | ||
283 | * - "/a/b/" -> "../" | ||
284 | * - "/a/b/c/other" -> "other" | ||
285 | * - "/a/x/y" -> "../../x/y" | ||
286 | * | ||
287 | * @param string $basePath The base path | ||
288 | * @param string $targetPath The target path | ||
289 | * | ||
290 | * @return string The relative target path | ||
291 | */ | ||
292 | public static function getRelativePath($basePath, $targetPath) | ||
293 | { | ||
294 | if ($basePath === $targetPath) { | ||
295 | return ''; | ||
296 | } | ||
297 | |||
298 | $sourceDirs = explode('/', isset($basePath[0]) && '/' === $basePath[0] ? substr($basePath, 1) : $basePath); | ||
299 | $targetDirs = explode('/', isset($targetPath[0]) && '/' === $targetPath[0] ? substr($targetPath, 1) : $targetPath); | ||
300 | array_pop($sourceDirs); | ||
301 | $targetFile = array_pop($targetDirs); | ||
302 | |||
303 | foreach ($sourceDirs as $i => $dir) { | ||
304 | if (isset($targetDirs[$i]) && $dir === $targetDirs[$i]) { | ||
305 | unset($sourceDirs[$i], $targetDirs[$i]); | ||
306 | } else { | ||
307 | break; | ||
308 | } | ||
309 | } | ||
310 | |||
311 | $targetDirs[] = $targetFile; | ||
312 | $path = str_repeat('../', count($sourceDirs)).implode('/', $targetDirs); | ||
313 | |||
314 | // A reference to the same base directory or an empty subdirectory must be prefixed with "./". | ||
315 | // This also applies to a segment with a colon character (e.g., "file:colon") that cannot be used | ||
316 | // as the first segment of a relative-path reference, as it would be mistaken for a scheme name | ||
317 | // (see http://tools.ietf.org/html/rfc3986#section-4.2). | ||
318 | return '' === $path || '/' === $path[0] | ||
319 | || false !== ($colonPos = strpos($path, ':')) && ($colonPos < ($slashPos = strpos($path, '/')) || false === $slashPos) | ||
320 | ? "./$path" : $path; | ||
321 | } | ||
322 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Generator/UrlGeneratorInterface.php b/vendor/symfony/routing/Symfony/Component/Routing/Generator/UrlGeneratorInterface.php new file mode 100644 index 00000000..8e3b2778 --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Generator/UrlGeneratorInterface.php | |||
@@ -0,0 +1,87 @@ | |||
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\Generator; | ||
13 | |||
14 | use Symfony\Component\Routing\Exception\InvalidParameterException; | ||
15 | use Symfony\Component\Routing\Exception\MissingMandatoryParametersException; | ||
16 | use Symfony\Component\Routing\Exception\RouteNotFoundException; | ||
17 | use Symfony\Component\Routing\RequestContextAwareInterface; | ||
18 | |||
19 | /** | ||
20 | * UrlGeneratorInterface is the interface that all URL generator classes must implement. | ||
21 | * | ||
22 | * The constants in this interface define the different types of resource references that | ||
23 | * are declared in RFC 3986: http://tools.ietf.org/html/rfc3986 | ||
24 | * We are using the term "URL" instead of "URI" as this is more common in web applications | ||
25 | * and we do not need to distinguish them as the difference is mostly semantical and | ||
26 | * less technical. Generating URIs, i.e. representation-independent resource identifiers, | ||
27 | * is also possible. | ||
28 | * | ||
29 | * @author Fabien Potencier <fabien@symfony.com> | ||
30 | * @author Tobias Schultze <http://tobion.de> | ||
31 | * | ||
32 | * @api | ||
33 | */ | ||
34 | interface UrlGeneratorInterface extends RequestContextAwareInterface | ||
35 | { | ||
36 | /** | ||
37 | * Generates an absolute URL, e.g. "http://example.com/dir/file". | ||
38 | */ | ||
39 | const ABSOLUTE_URL = true; | ||
40 | |||
41 | /** | ||
42 | * Generates an absolute path, e.g. "/dir/file". | ||
43 | */ | ||
44 | const ABSOLUTE_PATH = false; | ||
45 | |||
46 | /** | ||
47 | * Generates a relative path based on the current request path, e.g. "../parent-file". | ||
48 | * @see UrlGenerator::getRelativePath() | ||
49 | */ | ||
50 | const RELATIVE_PATH = 'relative'; | ||
51 | |||
52 | /** | ||
53 | * Generates a network path, e.g. "//example.com/dir/file". | ||
54 | * Such reference reuses the current scheme but specifies the host. | ||
55 | */ | ||
56 | const NETWORK_PATH = 'network'; | ||
57 | |||
58 | /** | ||
59 | * Generates a URL or path for a specific route based on the given parameters. | ||
60 | * | ||
61 | * Parameters that reference placeholders in the route pattern will substitute them in the | ||
62 | * path or host. Extra params are added as query string to the URL. | ||
63 | * | ||
64 | * When the passed reference type cannot be generated for the route because it requires a different | ||
65 | * host or scheme than the current one, the method will return a more comprehensive reference | ||
66 | * that includes the required params. For example, when you call this method with $referenceType = ABSOLUTE_PATH | ||
67 | * but the route requires the https scheme whereas the current scheme is http, it will instead return an | ||
68 | * ABSOLUTE_URL with the https scheme and the current host. This makes sure the generated URL matches | ||
69 | * the route in any case. | ||
70 | * | ||
71 | * If there is no route with the given name, the generator must throw the RouteNotFoundException. | ||
72 | * | ||
73 | * @param string $name The name of the route | ||
74 | * @param mixed $parameters An array of parameters | ||
75 | * @param Boolean|string $referenceType The type of reference to be generated (one of the constants) | ||
76 | * | ||
77 | * @return string The generated URL | ||
78 | * | ||
79 | * @throws RouteNotFoundException If the named route doesn't exist | ||
80 | * @throws MissingMandatoryParametersException When some parameters are missing that are mandatory for the route | ||
81 | * @throws InvalidParameterException When a parameter value for a placeholder is not correct because | ||
82 | * it does not match the requirement | ||
83 | * | ||
84 | * @api | ||
85 | */ | ||
86 | public function generate($name, $parameters = array(), $referenceType = self::ABSOLUTE_PATH); | ||
87 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/LICENSE b/vendor/symfony/routing/Symfony/Component/Routing/LICENSE new file mode 100644 index 00000000..88a57f8d --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/LICENSE | |||
@@ -0,0 +1,19 @@ | |||
1 | Copyright (c) 2004-2013 Fabien Potencier | ||
2 | |||
3 | Permission is hereby granted, free of charge, to any person obtaining a copy | ||
4 | of this software and associated documentation files (the "Software"), to deal | ||
5 | in the Software without restriction, including without limitation the rights | ||
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
7 | copies of the Software, and to permit persons to whom the Software is furnished | ||
8 | to do so, subject to the following conditions: | ||
9 | |||
10 | The above copyright notice and this permission notice shall be included in all | ||
11 | copies or substantial portions of the Software. | ||
12 | |||
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
19 | THE SOFTWARE. | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Loader/AnnotationClassLoader.php b/vendor/symfony/routing/Symfony/Component/Routing/Loader/AnnotationClassLoader.php new file mode 100644 index 00000000..9831d85a --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Loader/AnnotationClassLoader.php | |||
@@ -0,0 +1,246 @@ | |||
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\Loader; | ||
13 | |||
14 | use Doctrine\Common\Annotations\Reader; | ||
15 | use Symfony\Component\Config\Resource\FileResource; | ||
16 | use Symfony\Component\Routing\Route; | ||
17 | use Symfony\Component\Routing\RouteCollection; | ||
18 | use Symfony\Component\Config\Loader\LoaderInterface; | ||
19 | use Symfony\Component\Config\Loader\LoaderResolverInterface; | ||
20 | |||
21 | /** | ||
22 | * AnnotationClassLoader loads routing information from a PHP class and its methods. | ||
23 | * | ||
24 | * You need to define an implementation for the getRouteDefaults() method. Most of the | ||
25 | * time, this method should define some PHP callable to be called for the route | ||
26 | * (a controller in MVC speak). | ||
27 | * | ||
28 | * The @Route annotation can be set on the class (for global parameters), | ||
29 | * and on each method. | ||
30 | * | ||
31 | * The @Route annotation main value is the route path. The annotation also | ||
32 | * recognizes several parameters: requirements, options, defaults, schemes, | ||
33 | * methods, host, and name. The name parameter is mandatory. | ||
34 | * Here is an example of how you should be able to use it: | ||
35 | * | ||
36 | * /** | ||
37 | * * @Route("/Blog") | ||
38 | * * / | ||
39 | * class Blog | ||
40 | * { | ||
41 | * /** | ||
42 | * * @Route("/", name="blog_index") | ||
43 | * * / | ||
44 | * public function index() | ||
45 | * { | ||
46 | * } | ||
47 | * | ||
48 | * /** | ||
49 | * * @Route("/{id}", name="blog_post", requirements = {"id" = "\d+"}) | ||
50 | * * / | ||
51 | * public function show() | ||
52 | * { | ||
53 | * } | ||
54 | * } | ||
55 | * | ||
56 | * @author Fabien Potencier <fabien@symfony.com> | ||
57 | */ | ||
58 | abstract class AnnotationClassLoader implements LoaderInterface | ||
59 | { | ||
60 | /** | ||
61 | * @var Reader | ||
62 | */ | ||
63 | protected $reader; | ||
64 | |||
65 | /** | ||
66 | * @var string | ||
67 | */ | ||
68 | protected $routeAnnotationClass = 'Symfony\\Component\\Routing\\Annotation\\Route'; | ||
69 | |||
70 | /** | ||
71 | * @var integer | ||
72 | */ | ||
73 | protected $defaultRouteIndex = 0; | ||
74 | |||
75 | /** | ||
76 | * Constructor. | ||
77 | * | ||
78 | * @param Reader $reader | ||
79 | */ | ||
80 | public function __construct(Reader $reader) | ||
81 | { | ||
82 | $this->reader = $reader; | ||
83 | } | ||
84 | |||
85 | /** | ||
86 | * Sets the annotation class to read route properties from. | ||
87 | * | ||
88 | * @param string $class A fully-qualified class name | ||
89 | */ | ||
90 | public function setRouteAnnotationClass($class) | ||
91 | { | ||
92 | $this->routeAnnotationClass = $class; | ||
93 | } | ||
94 | |||
95 | /** | ||
96 | * Loads from annotations from a class. | ||
97 | * | ||
98 | * @param string $class A class name | ||
99 | * @param string|null $type The resource type | ||
100 | * | ||
101 | * @return RouteCollection A RouteCollection instance | ||
102 | * | ||
103 | * @throws \InvalidArgumentException When route can't be parsed | ||
104 | */ | ||
105 | public function load($class, $type = null) | ||
106 | { | ||
107 | if (!class_exists($class)) { | ||
108 | throw new \InvalidArgumentException(sprintf('Class "%s" does not exist.', $class)); | ||
109 | } | ||
110 | |||
111 | $globals = array( | ||
112 | 'path' => '', | ||
113 | 'requirements' => array(), | ||
114 | 'options' => array(), | ||
115 | 'defaults' => array(), | ||
116 | 'schemes' => array(), | ||
117 | 'methods' => array(), | ||
118 | 'host' => '', | ||
119 | ); | ||
120 | |||
121 | $class = new \ReflectionClass($class); | ||
122 | if ($class->isAbstract()) { | ||
123 | throw new \InvalidArgumentException(sprintf('Annotations from class "%s" cannot be read as it is abstract.', $class)); | ||
124 | } | ||
125 | |||
126 | if ($annot = $this->reader->getClassAnnotation($class, $this->routeAnnotationClass)) { | ||
127 | // for BC reasons | ||
128 | if (null !== $annot->getPath()) { | ||
129 | $globals['path'] = $annot->getPath(); | ||
130 | } elseif (null !== $annot->getPattern()) { | ||
131 | $globals['path'] = $annot->getPattern(); | ||
132 | } | ||
133 | |||
134 | if (null !== $annot->getRequirements()) { | ||
135 | $globals['requirements'] = $annot->getRequirements(); | ||
136 | } | ||
137 | |||
138 | if (null !== $annot->getOptions()) { | ||
139 | $globals['options'] = $annot->getOptions(); | ||
140 | } | ||
141 | |||
142 | if (null !== $annot->getDefaults()) { | ||
143 | $globals['defaults'] = $annot->getDefaults(); | ||
144 | } | ||
145 | |||
146 | if (null !== $annot->getSchemes()) { | ||
147 | $globals['schemes'] = $annot->getSchemes(); | ||
148 | } | ||
149 | |||
150 | if (null !== $annot->getMethods()) { | ||
151 | $globals['methods'] = $annot->getMethods(); | ||
152 | } | ||
153 | |||
154 | if (null !== $annot->getHost()) { | ||
155 | $globals['host'] = $annot->getHost(); | ||
156 | } | ||
157 | } | ||
158 | |||
159 | $collection = new RouteCollection(); | ||
160 | $collection->addResource(new FileResource($class->getFileName())); | ||
161 | |||
162 | foreach ($class->getMethods() as $method) { | ||
163 | $this->defaultRouteIndex = 0; | ||
164 | foreach ($this->reader->getMethodAnnotations($method) as $annot) { | ||
165 | if ($annot instanceof $this->routeAnnotationClass) { | ||
166 | $this->addRoute($collection, $annot, $globals, $class, $method); | ||
167 | } | ||
168 | } | ||
169 | } | ||
170 | |||
171 | return $collection; | ||
172 | } | ||
173 | |||
174 | protected function addRoute(RouteCollection $collection, $annot, $globals, \ReflectionClass $class, \ReflectionMethod $method) | ||
175 | { | ||
176 | $name = $annot->getName(); | ||
177 | if (null === $name) { | ||
178 | $name = $this->getDefaultRouteName($class, $method); | ||
179 | } | ||
180 | |||
181 | $defaults = array_replace($globals['defaults'], $annot->getDefaults()); | ||
182 | foreach ($method->getParameters() as $param) { | ||
183 | if ($param->isOptional()) { | ||
184 | $defaults[$param->getName()] = $param->getDefaultValue(); | ||
185 | } | ||
186 | } | ||
187 | $requirements = array_replace($globals['requirements'], $annot->getRequirements()); | ||
188 | $options = array_replace($globals['options'], $annot->getOptions()); | ||
189 | $schemes = array_replace($globals['schemes'], $annot->getSchemes()); | ||
190 | $methods = array_replace($globals['methods'], $annot->getMethods()); | ||
191 | |||
192 | $host = $annot->getHost(); | ||
193 | if (null === $host) { | ||
194 | $host = $globals['host']; | ||
195 | } | ||
196 | |||
197 | $route = new Route($globals['path'].$annot->getPath(), $defaults, $requirements, $options, $host, $schemes, $methods); | ||
198 | |||
199 | $this->configureRoute($route, $class, $method, $annot); | ||
200 | |||
201 | $collection->add($name, $route); | ||
202 | } | ||
203 | |||
204 | /** | ||
205 | * {@inheritdoc} | ||
206 | */ | ||
207 | public function supports($resource, $type = null) | ||
208 | { | ||
209 | return is_string($resource) && preg_match('/^(?:\\\\?[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)+$/', $resource) && (!$type || 'annotation' === $type); | ||
210 | } | ||
211 | |||
212 | /** | ||
213 | * {@inheritdoc} | ||
214 | */ | ||
215 | public function setResolver(LoaderResolverInterface $resolver) | ||
216 | { | ||
217 | } | ||
218 | |||
219 | /** | ||
220 | * {@inheritdoc} | ||
221 | */ | ||
222 | public function getResolver() | ||
223 | { | ||
224 | } | ||
225 | |||
226 | /** | ||
227 | * Gets the default route name for a class method. | ||
228 | * | ||
229 | * @param \ReflectionClass $class | ||
230 | * @param \ReflectionMethod $method | ||
231 | * | ||
232 | * @return string | ||
233 | */ | ||
234 | protected function getDefaultRouteName(\ReflectionClass $class, \ReflectionMethod $method) | ||
235 | { | ||
236 | $name = strtolower(str_replace('\\', '_', $class->name).'_'.$method->name); | ||
237 | if ($this->defaultRouteIndex > 0) { | ||
238 | $name .= '_'.$this->defaultRouteIndex; | ||
239 | } | ||
240 | $this->defaultRouteIndex++; | ||
241 | |||
242 | return $name; | ||
243 | } | ||
244 | |||
245 | abstract protected function configureRoute(Route $route, \ReflectionClass $class, \ReflectionMethod $method, $annot); | ||
246 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Loader/AnnotationDirectoryLoader.php b/vendor/symfony/routing/Symfony/Component/Routing/Loader/AnnotationDirectoryLoader.php new file mode 100644 index 00000000..abd68ed6 --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Loader/AnnotationDirectoryLoader.php | |||
@@ -0,0 +1,77 @@ | |||
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\Loader; | ||
13 | |||
14 | use Symfony\Component\Routing\RouteCollection; | ||
15 | use Symfony\Component\Config\Resource\DirectoryResource; | ||
16 | |||
17 | /** | ||
18 | * AnnotationDirectoryLoader loads routing information from annotations set | ||
19 | * on PHP classes and methods. | ||
20 | * | ||
21 | * @author Fabien Potencier <fabien@symfony.com> | ||
22 | */ | ||
23 | class AnnotationDirectoryLoader extends AnnotationFileLoader | ||
24 | { | ||
25 | /** | ||
26 | * Loads from annotations from a directory. | ||
27 | * | ||
28 | * @param string $path A directory path | ||
29 | * @param string|null $type The resource type | ||
30 | * | ||
31 | * @return RouteCollection A RouteCollection instance | ||
32 | * | ||
33 | * @throws \InvalidArgumentException When the directory does not exist or its routes cannot be parsed | ||
34 | */ | ||
35 | public function load($path, $type = null) | ||
36 | { | ||
37 | $dir = $this->locator->locate($path); | ||
38 | |||
39 | $collection = new RouteCollection(); | ||
40 | $collection->addResource(new DirectoryResource($dir, '/\.php$/')); | ||
41 | $files = iterator_to_array(new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($dir), \RecursiveIteratorIterator::LEAVES_ONLY)); | ||
42 | usort($files, function (\SplFileInfo $a, \SplFileInfo $b) { | ||
43 | return (string) $a > (string) $b ? 1 : -1; | ||
44 | }); | ||
45 | |||
46 | foreach ($files as $file) { | ||
47 | if (!$file->isFile() || '.php' !== substr($file->getFilename(), -4)) { | ||
48 | continue; | ||
49 | } | ||
50 | |||
51 | if ($class = $this->findClass($file)) { | ||
52 | $refl = new \ReflectionClass($class); | ||
53 | if ($refl->isAbstract()) { | ||
54 | continue; | ||
55 | } | ||
56 | |||
57 | $collection->addCollection($this->loader->load($class, $type)); | ||
58 | } | ||
59 | } | ||
60 | |||
61 | return $collection; | ||
62 | } | ||
63 | |||
64 | /** | ||
65 | * {@inheritdoc} | ||
66 | */ | ||
67 | public function supports($resource, $type = null) | ||
68 | { | ||
69 | try { | ||
70 | $path = $this->locator->locate($resource); | ||
71 | } catch (\Exception $e) { | ||
72 | return false; | ||
73 | } | ||
74 | |||
75 | return is_string($resource) && is_dir($path) && (!$type || 'annotation' === $type); | ||
76 | } | ||
77 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Loader/AnnotationFileLoader.php b/vendor/symfony/routing/Symfony/Component/Routing/Loader/AnnotationFileLoader.php new file mode 100644 index 00000000..33776fdc --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Loader/AnnotationFileLoader.php | |||
@@ -0,0 +1,122 @@ | |||
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\Loader; | ||
13 | |||
14 | use Symfony\Component\Routing\RouteCollection; | ||
15 | use Symfony\Component\Config\Resource\FileResource; | ||
16 | use Symfony\Component\Config\Loader\FileLoader; | ||
17 | use Symfony\Component\Config\FileLocatorInterface; | ||
18 | |||
19 | /** | ||
20 | * AnnotationFileLoader loads routing information from annotations set | ||
21 | * on a PHP class and its methods. | ||
22 | * | ||
23 | * @author Fabien Potencier <fabien@symfony.com> | ||
24 | */ | ||
25 | class AnnotationFileLoader extends FileLoader | ||
26 | { | ||
27 | protected $loader; | ||
28 | |||
29 | /** | ||
30 | * Constructor. | ||
31 | * | ||
32 | * @param FileLocatorInterface $locator A FileLocator instance | ||
33 | * @param AnnotationClassLoader $loader An AnnotationClassLoader instance | ||
34 | * @param string|array $paths A path or an array of paths where to look for resources | ||
35 | * | ||
36 | * @throws \RuntimeException | ||
37 | */ | ||
38 | public function __construct(FileLocatorInterface $locator, AnnotationClassLoader $loader, $paths = array()) | ||
39 | { | ||
40 | if (!function_exists('token_get_all')) { | ||
41 | throw new \RuntimeException('The Tokenizer extension is required for the routing annotation loaders.'); | ||
42 | } | ||
43 | |||
44 | parent::__construct($locator, $paths); | ||
45 | |||
46 | $this->loader = $loader; | ||
47 | } | ||
48 | |||
49 | /** | ||
50 | * Loads from annotations from a file. | ||
51 | * | ||
52 | * @param string $file A PHP file path | ||
53 | * @param string|null $type The resource type | ||
54 | * | ||
55 | * @return RouteCollection A RouteCollection instance | ||
56 | * | ||
57 | * @throws \InvalidArgumentException When the file does not exist or its routes cannot be parsed | ||
58 | */ | ||
59 | public function load($file, $type = null) | ||
60 | { | ||
61 | $path = $this->locator->locate($file); | ||
62 | |||
63 | $collection = new RouteCollection(); | ||
64 | if ($class = $this->findClass($path)) { | ||
65 | $collection->addResource(new FileResource($path)); | ||
66 | $collection->addCollection($this->loader->load($class, $type)); | ||
67 | } | ||
68 | |||
69 | return $collection; | ||
70 | } | ||
71 | |||
72 | /** | ||
73 | * {@inheritdoc} | ||
74 | */ | ||
75 | public function supports($resource, $type = null) | ||
76 | { | ||
77 | return is_string($resource) && 'php' === pathinfo($resource, PATHINFO_EXTENSION) && (!$type || 'annotation' === $type); | ||
78 | } | ||
79 | |||
80 | /** | ||
81 | * Returns the full class name for the first class in the file. | ||
82 | * | ||
83 | * @param string $file A PHP file path | ||
84 | * | ||
85 | * @return string|false Full class name if found, false otherwise | ||
86 | */ | ||
87 | protected function findClass($file) | ||
88 | { | ||
89 | $class = false; | ||
90 | $namespace = false; | ||
91 | $tokens = token_get_all(file_get_contents($file)); | ||
92 | for ($i = 0, $count = count($tokens); $i < $count; $i++) { | ||
93 | $token = $tokens[$i]; | ||
94 | |||
95 | if (!is_array($token)) { | ||
96 | continue; | ||
97 | } | ||
98 | |||
99 | if (true === $class && T_STRING === $token[0]) { | ||
100 | return $namespace.'\\'.$token[1]; | ||
101 | } | ||
102 | |||
103 | if (true === $namespace && T_STRING === $token[0]) { | ||
104 | $namespace = ''; | ||
105 | do { | ||
106 | $namespace .= $token[1]; | ||
107 | $token = $tokens[++$i]; | ||
108 | } while ($i < $count && is_array($token) && in_array($token[0], array(T_NS_SEPARATOR, T_STRING))); | ||
109 | } | ||
110 | |||
111 | if (T_CLASS === $token[0]) { | ||
112 | $class = true; | ||
113 | } | ||
114 | |||
115 | if (T_NAMESPACE === $token[0]) { | ||
116 | $namespace = true; | ||
117 | } | ||
118 | } | ||
119 | |||
120 | return false; | ||
121 | } | ||
122 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Loader/ClosureLoader.php b/vendor/symfony/routing/Symfony/Component/Routing/Loader/ClosureLoader.php new file mode 100644 index 00000000..8212c291 --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Loader/ClosureLoader.php | |||
@@ -0,0 +1,52 @@ | |||
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\Loader; | ||
13 | |||
14 | use Symfony\Component\Config\Loader\Loader; | ||
15 | use Symfony\Component\Routing\RouteCollection; | ||
16 | |||
17 | /** | ||
18 | * ClosureLoader loads routes from a PHP closure. | ||
19 | * | ||
20 | * The Closure must return a RouteCollection instance. | ||
21 | * | ||
22 | * @author Fabien Potencier <fabien@symfony.com> | ||
23 | * | ||
24 | * @api | ||
25 | */ | ||
26 | class ClosureLoader extends Loader | ||
27 | { | ||
28 | /** | ||
29 | * Loads a Closure. | ||
30 | * | ||
31 | * @param \Closure $closure A Closure | ||
32 | * @param string|null $type The resource type | ||
33 | * | ||
34 | * @return RouteCollection A RouteCollection instance | ||
35 | * | ||
36 | * @api | ||
37 | */ | ||
38 | public function load($closure, $type = null) | ||
39 | { | ||
40 | return call_user_func($closure); | ||
41 | } | ||
42 | |||
43 | /** | ||
44 | * {@inheritdoc} | ||
45 | * | ||
46 | * @api | ||
47 | */ | ||
48 | public function supports($resource, $type = null) | ||
49 | { | ||
50 | return $resource instanceof \Closure && (!$type || 'closure' === $type); | ||
51 | } | ||
52 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Loader/PhpFileLoader.php b/vendor/symfony/routing/Symfony/Component/Routing/Loader/PhpFileLoader.php new file mode 100644 index 00000000..98b7efbf --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Loader/PhpFileLoader.php | |||
@@ -0,0 +1,62 @@ | |||
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\Loader; | ||
13 | |||
14 | use Symfony\Component\Config\Loader\FileLoader; | ||
15 | use Symfony\Component\Config\Resource\FileResource; | ||
16 | use Symfony\Component\Routing\RouteCollection; | ||
17 | |||
18 | /** | ||
19 | * PhpFileLoader loads routes from a PHP file. | ||
20 | * | ||
21 | * The file must return a RouteCollection instance. | ||
22 | * | ||
23 | * @author Fabien Potencier <fabien@symfony.com> | ||
24 | * | ||
25 | * @api | ||
26 | */ | ||
27 | class PhpFileLoader extends FileLoader | ||
28 | { | ||
29 | /** | ||
30 | * Loads a PHP file. | ||
31 | * | ||
32 | * @param string $file A PHP file path | ||
33 | * @param string|null $type The resource type | ||
34 | * | ||
35 | * @return RouteCollection A RouteCollection instance | ||
36 | * | ||
37 | * @api | ||
38 | */ | ||
39 | public function load($file, $type = null) | ||
40 | { | ||
41 | // the loader variable is exposed to the included file below | ||
42 | $loader = $this; | ||
43 | |||
44 | $path = $this->locator->locate($file); | ||
45 | $this->setCurrentDir(dirname($path)); | ||
46 | |||
47 | $collection = include $path; | ||
48 | $collection->addResource(new FileResource($path)); | ||
49 | |||
50 | return $collection; | ||
51 | } | ||
52 | |||
53 | /** | ||
54 | * {@inheritdoc} | ||
55 | * | ||
56 | * @api | ||
57 | */ | ||
58 | public function supports($resource, $type = null) | ||
59 | { | ||
60 | return is_string($resource) && 'php' === pathinfo($resource, PATHINFO_EXTENSION) && (!$type || 'php' === $type); | ||
61 | } | ||
62 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Loader/XmlFileLoader.php b/vendor/symfony/routing/Symfony/Component/Routing/Loader/XmlFileLoader.php new file mode 100644 index 00000000..da7b33d8 --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Loader/XmlFileLoader.php | |||
@@ -0,0 +1,238 @@ | |||
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\Loader; | ||
13 | |||
14 | use Symfony\Component\Routing\RouteCollection; | ||
15 | use Symfony\Component\Routing\Route; | ||
16 | use Symfony\Component\Config\Resource\FileResource; | ||
17 | use Symfony\Component\Config\Loader\FileLoader; | ||
18 | use Symfony\Component\Config\Util\XmlUtils; | ||
19 | |||
20 | /** | ||
21 | * XmlFileLoader loads XML routing files. | ||
22 | * | ||
23 | * @author Fabien Potencier <fabien@symfony.com> | ||
24 | * @author Tobias Schultze <http://tobion.de> | ||
25 | * | ||
26 | * @api | ||
27 | */ | ||
28 | class XmlFileLoader extends FileLoader | ||
29 | { | ||
30 | const NAMESPACE_URI = 'http://symfony.com/schema/routing'; | ||
31 | const SCHEME_PATH = '/schema/routing/routing-1.0.xsd'; | ||
32 | |||
33 | /** | ||
34 | * Loads an XML file. | ||
35 | * | ||
36 | * @param string $file An XML file path | ||
37 | * @param string|null $type The resource type | ||
38 | * | ||
39 | * @return RouteCollection A RouteCollection instance | ||
40 | * | ||
41 | * @throws \InvalidArgumentException When the file cannot be loaded or when the XML cannot be | ||
42 | * parsed because it does not validate against the scheme. | ||
43 | * | ||
44 | * @api | ||
45 | */ | ||
46 | public function load($file, $type = null) | ||
47 | { | ||
48 | $path = $this->locator->locate($file); | ||
49 | |||
50 | $xml = $this->loadFile($path); | ||
51 | |||
52 | $collection = new RouteCollection(); | ||
53 | $collection->addResource(new FileResource($path)); | ||
54 | |||
55 | // process routes and imports | ||
56 | foreach ($xml->documentElement->childNodes as $node) { | ||
57 | if (!$node instanceof \DOMElement) { | ||
58 | continue; | ||
59 | } | ||
60 | |||
61 | $this->parseNode($collection, $node, $path, $file); | ||
62 | } | ||
63 | |||
64 | return $collection; | ||
65 | } | ||
66 | |||
67 | /** | ||
68 | * Parses a node from a loaded XML file. | ||
69 | * | ||
70 | * @param RouteCollection $collection Collection to associate with the node | ||
71 | * @param \DOMElement $node Element to parse | ||
72 | * @param string $path Full path of the XML file being processed | ||
73 | * @param string $file Loaded file name | ||
74 | * | ||
75 | * @throws \InvalidArgumentException When the XML is invalid | ||
76 | */ | ||
77 | protected function parseNode(RouteCollection $collection, \DOMElement $node, $path, $file) | ||
78 | { | ||
79 | if (self::NAMESPACE_URI !== $node->namespaceURI) { | ||
80 | return; | ||
81 | } | ||
82 | |||
83 | switch ($node->localName) { | ||
84 | case 'route': | ||
85 | $this->parseRoute($collection, $node, $path); | ||
86 | break; | ||
87 | case 'import': | ||
88 | $this->parseImport($collection, $node, $path, $file); | ||
89 | break; | ||
90 | default: | ||
91 | throw new \InvalidArgumentException(sprintf('Unknown tag "%s" used in file "%s". Expected "route" or "import".', $node->localName, $path)); | ||
92 | } | ||
93 | } | ||
94 | |||
95 | /** | ||
96 | * {@inheritdoc} | ||
97 | * | ||
98 | * @api | ||
99 | */ | ||
100 | public function supports($resource, $type = null) | ||
101 | { | ||
102 | return is_string($resource) && 'xml' === pathinfo($resource, PATHINFO_EXTENSION) && (!$type || 'xml' === $type); | ||
103 | } | ||
104 | |||
105 | /** | ||
106 | * Parses a route and adds it to the RouteCollection. | ||
107 | * | ||
108 | * @param RouteCollection $collection RouteCollection instance | ||
109 | * @param \DOMElement $node Element to parse that represents a Route | ||
110 | * @param string $path Full path of the XML file being processed | ||
111 | * | ||
112 | * @throws \InvalidArgumentException When the XML is invalid | ||
113 | */ | ||
114 | protected function parseRoute(RouteCollection $collection, \DOMElement $node, $path) | ||
115 | { | ||
116 | if ('' === ($id = $node->getAttribute('id')) || (!$node->hasAttribute('pattern') && !$node->hasAttribute('path'))) { | ||
117 | throw new \InvalidArgumentException(sprintf('The <route> element in file "%s" must have an "id" and a "path" attribute.', $path)); | ||
118 | } | ||
119 | |||
120 | if ($node->hasAttribute('pattern')) { | ||
121 | if ($node->hasAttribute('path')) { | ||
122 | throw new \InvalidArgumentException(sprintf('The <route> element in file "%s" cannot define both a "path" and a "pattern" attribute. Use only "path".', $path)); | ||
123 | } | ||
124 | |||
125 | $node->setAttribute('path', $node->getAttribute('pattern')); | ||
126 | $node->removeAttribute('pattern'); | ||
127 | } | ||
128 | |||
129 | $schemes = preg_split('/[\s,\|]++/', $node->getAttribute('schemes'), -1, PREG_SPLIT_NO_EMPTY); | ||
130 | $methods = preg_split('/[\s,\|]++/', $node->getAttribute('methods'), -1, PREG_SPLIT_NO_EMPTY); | ||
131 | |||
132 | list($defaults, $requirements, $options) = $this->parseConfigs($node, $path); | ||
133 | |||
134 | $route = new Route($node->getAttribute('path'), $defaults, $requirements, $options, $node->getAttribute('host'), $schemes, $methods); | ||
135 | $collection->add($id, $route); | ||
136 | } | ||
137 | |||
138 | /** | ||
139 | * Parses an import and adds the routes in the resource to the RouteCollection. | ||
140 | * | ||
141 | * @param RouteCollection $collection RouteCollection instance | ||
142 | * @param \DOMElement $node Element to parse that represents a Route | ||
143 | * @param string $path Full path of the XML file being processed | ||
144 | * @param string $file Loaded file name | ||
145 | * | ||
146 | * @throws \InvalidArgumentException When the XML is invalid | ||
147 | */ | ||
148 | protected function parseImport(RouteCollection $collection, \DOMElement $node, $path, $file) | ||
149 | { | ||
150 | if ('' === $resource = $node->getAttribute('resource')) { | ||
151 | throw new \InvalidArgumentException(sprintf('The <import> element in file "%s" must have a "resource" attribute.', $path)); | ||
152 | } | ||
153 | |||
154 | $type = $node->getAttribute('type'); | ||
155 | $prefix = $node->getAttribute('prefix'); | ||
156 | $host = $node->hasAttribute('host') ? $node->getAttribute('host') : null; | ||
157 | $schemes = $node->hasAttribute('schemes') ? preg_split('/[\s,\|]++/', $node->getAttribute('schemes'), -1, PREG_SPLIT_NO_EMPTY) : null; | ||
158 | $methods = $node->hasAttribute('methods') ? preg_split('/[\s,\|]++/', $node->getAttribute('methods'), -1, PREG_SPLIT_NO_EMPTY) : null; | ||
159 | |||
160 | list($defaults, $requirements, $options) = $this->parseConfigs($node, $path); | ||
161 | |||
162 | $this->setCurrentDir(dirname($path)); | ||
163 | |||
164 | $subCollection = $this->import($resource, ('' !== $type ? $type : null), false, $file); | ||
165 | /* @var $subCollection RouteCollection */ | ||
166 | $subCollection->addPrefix($prefix); | ||
167 | if (null !== $host) { | ||
168 | $subCollection->setHost($host); | ||
169 | } | ||
170 | if (null !== $schemes) { | ||
171 | $subCollection->setSchemes($schemes); | ||
172 | } | ||
173 | if (null !== $methods) { | ||
174 | $subCollection->setMethods($methods); | ||
175 | } | ||
176 | $subCollection->addDefaults($defaults); | ||
177 | $subCollection->addRequirements($requirements); | ||
178 | $subCollection->addOptions($options); | ||
179 | |||
180 | $collection->addCollection($subCollection); | ||
181 | } | ||
182 | |||
183 | /** | ||
184 | * Loads an XML file. | ||
185 | * | ||
186 | * @param string $file An XML file path | ||
187 | * | ||
188 | * @return \DOMDocument | ||
189 | * | ||
190 | * @throws \InvalidArgumentException When loading of XML file fails because of syntax errors | ||
191 | * or when the XML structure is not as expected by the scheme - | ||
192 | * see validate() | ||
193 | */ | ||
194 | protected function loadFile($file) | ||
195 | { | ||
196 | return XmlUtils::loadFile($file, __DIR__.static::SCHEME_PATH); | ||
197 | } | ||
198 | |||
199 | /** | ||
200 | * Parses the config elements (default, requirement, option). | ||
201 | * | ||
202 | * @param \DOMElement $node Element to parse that contains the configs | ||
203 | * @param string $path Full path of the XML file being processed | ||
204 | * | ||
205 | * @return array An array with the defaults as first item, requirements as second and options as third. | ||
206 | * | ||
207 | * @throws \InvalidArgumentException When the XML is invalid | ||
208 | */ | ||
209 | private function parseConfigs(\DOMElement $node, $path) | ||
210 | { | ||
211 | $defaults = array(); | ||
212 | $requirements = array(); | ||
213 | $options = array(); | ||
214 | |||
215 | foreach ($node->getElementsByTagNameNS(self::NAMESPACE_URI, '*') as $n) { | ||
216 | switch ($n->localName) { | ||
217 | case 'default': | ||
218 | if ($n->hasAttribute('xsi:nil') && 'true' == $n->getAttribute('xsi:nil')) { | ||
219 | $defaults[$n->getAttribute('key')] = null; | ||
220 | } else { | ||
221 | $defaults[$n->getAttribute('key')] = trim($n->textContent); | ||
222 | } | ||
223 | |||
224 | break; | ||
225 | case 'requirement': | ||
226 | $requirements[$n->getAttribute('key')] = trim($n->textContent); | ||
227 | break; | ||
228 | case 'option': | ||
229 | $options[$n->getAttribute('key')] = trim($n->textContent); | ||
230 | break; | ||
231 | default: | ||
232 | throw new \InvalidArgumentException(sprintf('Unknown tag "%s" used in file "%s". Expected "default", "requirement" or "option".', $n->localName, $path)); | ||
233 | } | ||
234 | } | ||
235 | |||
236 | return array($defaults, $requirements, $options); | ||
237 | } | ||
238 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Loader/YamlFileLoader.php b/vendor/symfony/routing/Symfony/Component/Routing/Loader/YamlFileLoader.php new file mode 100644 index 00000000..9deea7fe --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Loader/YamlFileLoader.php | |||
@@ -0,0 +1,212 @@ | |||
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\Loader; | ||
13 | |||
14 | use Symfony\Component\Routing\RouteCollection; | ||
15 | use Symfony\Component\Routing\Route; | ||
16 | use Symfony\Component\Config\Resource\FileResource; | ||
17 | use Symfony\Component\Yaml\Parser as YamlParser; | ||
18 | use Symfony\Component\Config\Loader\FileLoader; | ||
19 | |||
20 | /** | ||
21 | * YamlFileLoader loads Yaml routing files. | ||
22 | * | ||
23 | * @author Fabien Potencier <fabien@symfony.com> | ||
24 | * @author Tobias Schultze <http://tobion.de> | ||
25 | * | ||
26 | * @api | ||
27 | */ | ||
28 | class YamlFileLoader extends FileLoader | ||
29 | { | ||
30 | private static $availableKeys = array( | ||
31 | 'resource', 'type', 'prefix', 'pattern', 'path', 'host', 'schemes', 'methods', 'defaults', 'requirements', 'options', | ||
32 | ); | ||
33 | private $yamlParser; | ||
34 | |||
35 | /** | ||
36 | * Loads a Yaml file. | ||
37 | * | ||
38 | * @param string $file A Yaml file path | ||
39 | * @param string|null $type The resource type | ||
40 | * | ||
41 | * @return RouteCollection A RouteCollection instance | ||
42 | * | ||
43 | * @throws \InvalidArgumentException When a route can't be parsed because YAML is invalid | ||
44 | * | ||
45 | * @api | ||
46 | */ | ||
47 | public function load($file, $type = null) | ||
48 | { | ||
49 | $path = $this->locator->locate($file); | ||
50 | |||
51 | if (!stream_is_local($path)) { | ||
52 | throw new \InvalidArgumentException(sprintf('This is not a local file "%s".', $path)); | ||
53 | } | ||
54 | |||
55 | if (!file_exists($path)) { | ||
56 | throw new \InvalidArgumentException(sprintf('File "%s" not found.', $path)); | ||
57 | } | ||
58 | |||
59 | if (null === $this->yamlParser) { | ||
60 | $this->yamlParser = new YamlParser(); | ||
61 | } | ||
62 | |||
63 | $config = $this->yamlParser->parse(file_get_contents($path)); | ||
64 | |||
65 | $collection = new RouteCollection(); | ||
66 | $collection->addResource(new FileResource($path)); | ||
67 | |||
68 | // empty file | ||
69 | if (null === $config) { | ||
70 | return $collection; | ||
71 | } | ||
72 | |||
73 | // not an array | ||
74 | if (!is_array($config)) { | ||
75 | throw new \InvalidArgumentException(sprintf('The file "%s" must contain a YAML array.', $path)); | ||
76 | } | ||
77 | |||
78 | foreach ($config as $name => $config) { | ||
79 | if (isset($config['pattern'])) { | ||
80 | if (isset($config['path'])) { | ||
81 | throw new \InvalidArgumentException(sprintf('The file "%s" cannot define both a "path" and a "pattern" attribute. Use only "path".', $path)); | ||
82 | } | ||
83 | |||
84 | $config['path'] = $config['pattern']; | ||
85 | unset($config['pattern']); | ||
86 | } | ||
87 | |||
88 | $this->validate($config, $name, $path); | ||
89 | |||
90 | if (isset($config['resource'])) { | ||
91 | $this->parseImport($collection, $config, $path, $file); | ||
92 | } else { | ||
93 | $this->parseRoute($collection, $name, $config, $path); | ||
94 | } | ||
95 | } | ||
96 | |||
97 | return $collection; | ||
98 | } | ||
99 | |||
100 | /** | ||
101 | * {@inheritdoc} | ||
102 | * | ||
103 | * @api | ||
104 | */ | ||
105 | public function supports($resource, $type = null) | ||
106 | { | ||
107 | return is_string($resource) && 'yml' === pathinfo($resource, PATHINFO_EXTENSION) && (!$type || 'yaml' === $type); | ||
108 | } | ||
109 | |||
110 | /** | ||
111 | * Parses a route and adds it to the RouteCollection. | ||
112 | * | ||
113 | * @param RouteCollection $collection A RouteCollection instance | ||
114 | * @param string $name Route name | ||
115 | * @param array $config Route definition | ||
116 | * @param string $path Full path of the YAML file being processed | ||
117 | */ | ||
118 | protected function parseRoute(RouteCollection $collection, $name, array $config, $path) | ||
119 | { | ||
120 | $defaults = isset($config['defaults']) ? $config['defaults'] : array(); | ||
121 | $requirements = isset($config['requirements']) ? $config['requirements'] : array(); | ||
122 | $options = isset($config['options']) ? $config['options'] : array(); | ||
123 | $host = isset($config['host']) ? $config['host'] : ''; | ||
124 | $schemes = isset($config['schemes']) ? $config['schemes'] : array(); | ||
125 | $methods = isset($config['methods']) ? $config['methods'] : array(); | ||
126 | |||
127 | $route = new Route($config['path'], $defaults, $requirements, $options, $host, $schemes, $methods); | ||
128 | |||
129 | $collection->add($name, $route); | ||
130 | } | ||
131 | |||
132 | /** | ||
133 | * Parses an import and adds the routes in the resource to the RouteCollection. | ||
134 | * | ||
135 | * @param RouteCollection $collection A RouteCollection instance | ||
136 | * @param array $config Route definition | ||
137 | * @param string $path Full path of the YAML file being processed | ||
138 | * @param string $file Loaded file name | ||
139 | */ | ||
140 | protected function parseImport(RouteCollection $collection, array $config, $path, $file) | ||
141 | { | ||
142 | $type = isset($config['type']) ? $config['type'] : null; | ||
143 | $prefix = isset($config['prefix']) ? $config['prefix'] : ''; | ||
144 | $defaults = isset($config['defaults']) ? $config['defaults'] : array(); | ||
145 | $requirements = isset($config['requirements']) ? $config['requirements'] : array(); | ||
146 | $options = isset($config['options']) ? $config['options'] : array(); | ||
147 | $host = isset($config['host']) ? $config['host'] : null; | ||
148 | $schemes = isset($config['schemes']) ? $config['schemes'] : null; | ||
149 | $methods = isset($config['methods']) ? $config['methods'] : null; | ||
150 | |||
151 | $this->setCurrentDir(dirname($path)); | ||
152 | |||
153 | $subCollection = $this->import($config['resource'], $type, false, $file); | ||
154 | /* @var $subCollection RouteCollection */ | ||
155 | $subCollection->addPrefix($prefix); | ||
156 | if (null !== $host) { | ||
157 | $subCollection->setHost($host); | ||
158 | } | ||
159 | if (null !== $schemes) { | ||
160 | $subCollection->setSchemes($schemes); | ||
161 | } | ||
162 | if (null !== $methods) { | ||
163 | $subCollection->setMethods($methods); | ||
164 | } | ||
165 | $subCollection->addDefaults($defaults); | ||
166 | $subCollection->addRequirements($requirements); | ||
167 | $subCollection->addOptions($options); | ||
168 | |||
169 | $collection->addCollection($subCollection); | ||
170 | } | ||
171 | |||
172 | /** | ||
173 | * Validates the route configuration. | ||
174 | * | ||
175 | * @param array $config A resource config | ||
176 | * @param string $name The config key | ||
177 | * @param string $path The loaded file path | ||
178 | * | ||
179 | * @throws \InvalidArgumentException If one of the provided config keys is not supported, | ||
180 | * something is missing or the combination is nonsense | ||
181 | */ | ||
182 | protected function validate($config, $name, $path) | ||
183 | { | ||
184 | if (!is_array($config)) { | ||
185 | throw new \InvalidArgumentException(sprintf('The definition of "%s" in "%s" must be a YAML array.', $name, $path)); | ||
186 | } | ||
187 | if ($extraKeys = array_diff(array_keys($config), self::$availableKeys)) { | ||
188 | throw new \InvalidArgumentException(sprintf( | ||
189 | 'The routing file "%s" contains unsupported keys for "%s": "%s". Expected one of: "%s".', | ||
190 | $path, $name, implode('", "', $extraKeys), implode('", "', self::$availableKeys) | ||
191 | )); | ||
192 | } | ||
193 | if (isset($config['resource']) && isset($config['path'])) { | ||
194 | throw new \InvalidArgumentException(sprintf( | ||
195 | 'The routing file "%s" must not specify both the "resource" key and the "path" key for "%s". Choose between an import and a route definition.', | ||
196 | $path, $name | ||
197 | )); | ||
198 | } | ||
199 | if (!isset($config['resource']) && isset($config['type'])) { | ||
200 | throw new \InvalidArgumentException(sprintf( | ||
201 | 'The "type" key for the route definition "%s" in "%s" is unsupported. It is only available for imports in combination with the "resource" key.', | ||
202 | $name, $path | ||
203 | )); | ||
204 | } | ||
205 | if (!isset($config['resource']) && !isset($config['path'])) { | ||
206 | throw new \InvalidArgumentException(sprintf( | ||
207 | 'You must define a "path" for the route "%s" in file "%s".', | ||
208 | $name, $path | ||
209 | )); | ||
210 | } | ||
211 | } | ||
212 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Loader/schema/routing/routing-1.0.xsd b/vendor/symfony/routing/Symfony/Component/Routing/Loader/schema/routing/routing-1.0.xsd new file mode 100644 index 00000000..daea8143 --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Loader/schema/routing/routing-1.0.xsd | |||
@@ -0,0 +1,64 @@ | |||
1 | <?xml version="1.0" encoding="UTF-8" ?> | ||
2 | |||
3 | <xsd:schema xmlns="http://symfony.com/schema/routing" | ||
4 | xmlns:xsd="http://www.w3.org/2001/XMLSchema" | ||
5 | targetNamespace="http://symfony.com/schema/routing" | ||
6 | elementFormDefault="qualified"> | ||
7 | |||
8 | <xsd:annotation> | ||
9 | <xsd:documentation><![CDATA[ | ||
10 | Symfony XML Routing Schema, version 1.0 | ||
11 | Authors: Fabien Potencier, Tobias Schultze | ||
12 | |||
13 | This scheme defines the elements and attributes that can be used to define | ||
14 | routes. A route maps an HTTP request to a set of configuration variables. | ||
15 | ]]></xsd:documentation> | ||
16 | </xsd:annotation> | ||
17 | |||
18 | <xsd:element name="routes" type="routes" /> | ||
19 | |||
20 | <xsd:complexType name="routes"> | ||
21 | <xsd:choice minOccurs="0" maxOccurs="unbounded"> | ||
22 | <xsd:element name="import" type="import" /> | ||
23 | <xsd:element name="route" type="route" /> | ||
24 | </xsd:choice> | ||
25 | </xsd:complexType> | ||
26 | |||
27 | <xsd:group name="configs"> | ||
28 | <xsd:choice> | ||
29 | <xsd:element name="default" nillable="true" type="element" /> | ||
30 | <xsd:element name="requirement" type="element" /> | ||
31 | <xsd:element name="option" type="element" /> | ||
32 | </xsd:choice> | ||
33 | </xsd:group> | ||
34 | |||
35 | <xsd:complexType name="route"> | ||
36 | <xsd:group ref="configs" minOccurs="0" maxOccurs="unbounded" /> | ||
37 | |||
38 | <xsd:attribute name="id" type="xsd:string" use="required" /> | ||
39 | <xsd:attribute name="path" type="xsd:string" /> | ||
40 | <xsd:attribute name="pattern" type="xsd:string" /> | ||
41 | <xsd:attribute name="host" type="xsd:string" /> | ||
42 | <xsd:attribute name="schemes" type="xsd:string" /> | ||
43 | <xsd:attribute name="methods" type="xsd:string" /> | ||
44 | </xsd:complexType> | ||
45 | |||
46 | <xsd:complexType name="import"> | ||
47 | <xsd:group ref="configs" minOccurs="0" maxOccurs="unbounded" /> | ||
48 | |||
49 | <xsd:attribute name="resource" type="xsd:string" use="required" /> | ||
50 | <xsd:attribute name="type" type="xsd:string" /> | ||
51 | <xsd:attribute name="prefix" type="xsd:string" /> | ||
52 | <xsd:attribute name="host" type="xsd:string" /> | ||
53 | <xsd:attribute name="schemes" type="xsd:string" /> | ||
54 | <xsd:attribute name="methods" type="xsd:string" /> | ||
55 | </xsd:complexType> | ||
56 | |||
57 | <xsd:complexType name="element"> | ||
58 | <xsd:simpleContent> | ||
59 | <xsd:extension base="xsd:string"> | ||
60 | <xsd:attribute name="key" type="xsd:string" use="required" /> | ||
61 | </xsd:extension> | ||
62 | </xsd:simpleContent> | ||
63 | </xsd:complexType> | ||
64 | </xsd:schema> | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Matcher/ApacheUrlMatcher.php b/vendor/symfony/routing/Symfony/Component/Routing/Matcher/ApacheUrlMatcher.php new file mode 100644 index 00000000..76612e61 --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Matcher/ApacheUrlMatcher.php | |||
@@ -0,0 +1,94 @@ | |||
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\Matcher; | ||
13 | |||
14 | use Symfony\Component\Routing\Exception\MethodNotAllowedException; | ||
15 | |||
16 | /** | ||
17 | * ApacheUrlMatcher matches URL based on Apache mod_rewrite matching (see ApacheMatcherDumper). | ||
18 | * | ||
19 | * @author Fabien Potencier <fabien@symfony.com> | ||
20 | * @author Arnaud Le Blanc <arnaud.lb@gmail.com> | ||
21 | */ | ||
22 | class ApacheUrlMatcher extends UrlMatcher | ||
23 | { | ||
24 | /** | ||
25 | * Tries to match a URL based on Apache mod_rewrite matching. | ||
26 | * | ||
27 | * Returns false if no route matches the URL. | ||
28 | * | ||
29 | * @param string $pathinfo The pathinfo to be parsed | ||
30 | * | ||
31 | * @return array An array of parameters | ||
32 | * | ||
33 | * @throws MethodNotAllowedException If the current method is not allowed | ||
34 | */ | ||
35 | public function match($pathinfo) | ||
36 | { | ||
37 | $parameters = array(); | ||
38 | $defaults = array(); | ||
39 | $allow = array(); | ||
40 | $route = null; | ||
41 | |||
42 | foreach ($_SERVER as $key => $value) { | ||
43 | $name = $key; | ||
44 | |||
45 | // skip non-routing variables | ||
46 | // this improves performance when $_SERVER contains many usual | ||
47 | // variables like HTTP_*, DOCUMENT_ROOT, REQUEST_URI, ... | ||
48 | if (false === strpos($name, '_ROUTING_')) { | ||
49 | continue; | ||
50 | } | ||
51 | |||
52 | while (0 === strpos($name, 'REDIRECT_')) { | ||
53 | $name = substr($name, 9); | ||
54 | } | ||
55 | |||
56 | // expect _ROUTING_<type>_<name> | ||
57 | // or _ROUTING_<type> | ||
58 | |||
59 | if (0 !== strpos($name, '_ROUTING_')) { | ||
60 | continue; | ||
61 | } | ||
62 | if (false !== $pos = strpos($name, '_', 9)) { | ||
63 | $type = substr($name, 9, $pos-9); | ||
64 | $name = substr($name, $pos+1); | ||
65 | } else { | ||
66 | $type = substr($name, 9); | ||
67 | } | ||
68 | |||
69 | if ('param' === $type) { | ||
70 | if ('' !== $value) { | ||
71 | $parameters[$name] = $value; | ||
72 | } | ||
73 | } elseif ('default' === $type) { | ||
74 | $defaults[$name] = $value; | ||
75 | } elseif ('route' === $type) { | ||
76 | $route = $value; | ||
77 | } elseif ('allow' === $type) { | ||
78 | $allow[] = $name; | ||
79 | } | ||
80 | |||
81 | unset($_SERVER[$key]); | ||
82 | } | ||
83 | |||
84 | if (null !== $route) { | ||
85 | $parameters['_route'] = $route; | ||
86 | |||
87 | return $this->mergeDefaults($parameters, $defaults); | ||
88 | } elseif (0 < count($allow)) { | ||
89 | throw new MethodNotAllowedException($allow); | ||
90 | } else { | ||
91 | return parent::match($pathinfo); | ||
92 | } | ||
93 | } | ||
94 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Matcher/Dumper/ApacheMatcherDumper.php b/vendor/symfony/routing/Symfony/Component/Routing/Matcher/Dumper/ApacheMatcherDumper.php new file mode 100644 index 00000000..804da19d --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Matcher/Dumper/ApacheMatcherDumper.php | |||
@@ -0,0 +1,252 @@ | |||
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\Matcher\Dumper; | ||
13 | |||
14 | use Symfony\Component\Routing\Route; | ||
15 | |||
16 | /** | ||
17 | * Dumps a set of Apache mod_rewrite rules. | ||
18 | * | ||
19 | * @author Fabien Potencier <fabien@symfony.com> | ||
20 | * @author Kris Wallsmith <kris@symfony.com> | ||
21 | */ | ||
22 | class ApacheMatcherDumper extends MatcherDumper | ||
23 | { | ||
24 | /** | ||
25 | * Dumps a set of Apache mod_rewrite rules. | ||
26 | * | ||
27 | * Available options: | ||
28 | * | ||
29 | * * script_name: The script name (app.php by default) | ||
30 | * * base_uri: The base URI ("" by default) | ||
31 | * | ||
32 | * @param array $options An array of options | ||
33 | * | ||
34 | * @return string A string to be used as Apache rewrite rules | ||
35 | * | ||
36 | * @throws \LogicException When the route regex is invalid | ||
37 | */ | ||
38 | public function dump(array $options = array()) | ||
39 | { | ||
40 | $options = array_merge(array( | ||
41 | 'script_name' => 'app.php', | ||
42 | 'base_uri' => '', | ||
43 | ), $options); | ||
44 | |||
45 | $options['script_name'] = self::escape($options['script_name'], ' ', '\\'); | ||
46 | |||
47 | $rules = array("# skip \"real\" requests\nRewriteCond %{REQUEST_FILENAME} -f\nRewriteRule .* - [QSA,L]"); | ||
48 | $methodVars = array(); | ||
49 | $hostRegexUnique = 0; | ||
50 | $prevHostRegex = ''; | ||
51 | |||
52 | foreach ($this->getRoutes()->all() as $name => $route) { | ||
53 | |||
54 | $compiledRoute = $route->compile(); | ||
55 | $hostRegex = $compiledRoute->getHostRegex(); | ||
56 | |||
57 | if (null !== $hostRegex && $prevHostRegex !== $hostRegex) { | ||
58 | $prevHostRegex = $hostRegex; | ||
59 | $hostRegexUnique++; | ||
60 | |||
61 | $rule = array(); | ||
62 | |||
63 | $regex = $this->regexToApacheRegex($hostRegex); | ||
64 | $regex = self::escape($regex, ' ', '\\'); | ||
65 | |||
66 | $rule[] = sprintf('RewriteCond %%{HTTP:Host} %s', $regex); | ||
67 | |||
68 | $variables = array(); | ||
69 | $variables[] = sprintf('E=__ROUTING_host_%s:1', $hostRegexUnique); | ||
70 | |||
71 | foreach ($compiledRoute->getHostVariables() as $i => $variable) { | ||
72 | $variables[] = sprintf('E=__ROUTING_host_%s_%s:%%%d', $hostRegexUnique, $variable, $i+1); | ||
73 | } | ||
74 | |||
75 | $variables = implode(',', $variables); | ||
76 | |||
77 | $rule[] = sprintf('RewriteRule .? - [%s]', $variables); | ||
78 | |||
79 | $rules[] = implode("\n", $rule); | ||
80 | } | ||
81 | |||
82 | $rules[] = $this->dumpRoute($name, $route, $options, $hostRegexUnique); | ||
83 | |||
84 | if ($req = $route->getRequirement('_method')) { | ||
85 | $methods = explode('|', strtoupper($req)); | ||
86 | $methodVars = array_merge($methodVars, $methods); | ||
87 | } | ||
88 | } | ||
89 | if (0 < count($methodVars)) { | ||
90 | $rule = array('# 405 Method Not Allowed'); | ||
91 | $methodVars = array_values(array_unique($methodVars)); | ||
92 | if (in_array('GET', $methodVars) && !in_array('HEAD', $methodVars)) { | ||
93 | $methodVars[] = 'HEAD'; | ||
94 | } | ||
95 | foreach ($methodVars as $i => $methodVar) { | ||
96 | $rule[] = sprintf('RewriteCond %%{ENV:_ROUTING__allow_%s} =1%s', $methodVar, isset($methodVars[$i + 1]) ? ' [OR]' : ''); | ||
97 | } | ||
98 | $rule[] = sprintf('RewriteRule .* %s [QSA,L]', $options['script_name']); | ||
99 | |||
100 | $rules[] = implode("\n", $rule); | ||
101 | } | ||
102 | |||
103 | return implode("\n\n", $rules)."\n"; | ||
104 | } | ||
105 | |||
106 | /** | ||
107 | * Dumps a single route | ||
108 | * | ||
109 | * @param string $name Route name | ||
110 | * @param Route $route The route | ||
111 | * @param array $options Options | ||
112 | * @param bool $hostRegexUnique Unique identifier for the host regex | ||
113 | * | ||
114 | * @return string The compiled route | ||
115 | */ | ||
116 | private function dumpRoute($name, $route, array $options, $hostRegexUnique) | ||
117 | { | ||
118 | $compiledRoute = $route->compile(); | ||
119 | |||
120 | // prepare the apache regex | ||
121 | $regex = $this->regexToApacheRegex($compiledRoute->getRegex()); | ||
122 | $regex = '^'.self::escape(preg_quote($options['base_uri']).substr($regex, 1), ' ', '\\'); | ||
123 | |||
124 | $methods = $this->getRouteMethods($route); | ||
125 | |||
126 | $hasTrailingSlash = (!$methods || in_array('HEAD', $methods)) && '/$' === substr($regex, -2) && '^/$' !== $regex; | ||
127 | |||
128 | $variables = array('E=_ROUTING_route:'.$name); | ||
129 | foreach ($compiledRoute->getHostVariables() as $variable) { | ||
130 | $variables[] = sprintf('E=_ROUTING_param_%s:%%{ENV:__ROUTING_host_%s_%s}', $variable, $hostRegexUnique, $variable); | ||
131 | } | ||
132 | foreach ($compiledRoute->getPathVariables() as $i => $variable) { | ||
133 | $variables[] = 'E=_ROUTING_param_'.$variable.':%'.($i + 1); | ||
134 | } | ||
135 | foreach ($route->getDefaults() as $key => $value) { | ||
136 | $variables[] = 'E=_ROUTING_default_'.$key.':'.strtr($value, array( | ||
137 | ':' => '\\:', | ||
138 | '=' => '\\=', | ||
139 | '\\' => '\\\\', | ||
140 | ' ' => '\\ ', | ||
141 | )); | ||
142 | } | ||
143 | $variables = implode(',', $variables); | ||
144 | |||
145 | $rule = array("# $name"); | ||
146 | |||
147 | // method mismatch | ||
148 | if (0 < count($methods)) { | ||
149 | $allow = array(); | ||
150 | foreach ($methods as $method) { | ||
151 | $allow[] = 'E=_ROUTING_allow_'.$method.':1'; | ||
152 | } | ||
153 | |||
154 | if ($hostRegex = $compiledRoute->getHostRegex()) { | ||
155 | $rule[] = sprintf("RewriteCond %%{ENV:__ROUTING_host_%s} =1", $hostRegexUnique); | ||
156 | } | ||
157 | |||
158 | $rule[] = "RewriteCond %{REQUEST_URI} $regex"; | ||
159 | $rule[] = sprintf("RewriteCond %%{REQUEST_METHOD} !^(%s)$ [NC]", implode('|', $methods)); | ||
160 | $rule[] = sprintf('RewriteRule .* - [S=%d,%s]', $hasTrailingSlash ? 2 : 1, implode(',', $allow)); | ||
161 | } | ||
162 | |||
163 | // redirect with trailing slash appended | ||
164 | if ($hasTrailingSlash) { | ||
165 | |||
166 | if ($hostRegex = $compiledRoute->getHostRegex()) { | ||
167 | $rule[] = sprintf("RewriteCond %%{ENV:__ROUTING_host_%s} =1", $hostRegexUnique); | ||
168 | } | ||
169 | |||
170 | $rule[] = 'RewriteCond %{REQUEST_URI} '.substr($regex, 0, -2).'$'; | ||
171 | $rule[] = 'RewriteRule .* $0/ [QSA,L,R=301]'; | ||
172 | } | ||
173 | |||
174 | // the main rule | ||
175 | |||
176 | if ($hostRegex = $compiledRoute->getHostRegex()) { | ||
177 | $rule[] = sprintf("RewriteCond %%{ENV:__ROUTING_host_%s} =1", $hostRegexUnique); | ||
178 | } | ||
179 | |||
180 | $rule[] = "RewriteCond %{REQUEST_URI} $regex"; | ||
181 | $rule[] = "RewriteRule .* {$options['script_name']} [QSA,L,$variables]"; | ||
182 | |||
183 | return implode("\n", $rule); | ||
184 | } | ||
185 | |||
186 | /** | ||
187 | * Returns methods allowed for a route | ||
188 | * | ||
189 | * @param Route $route The route | ||
190 | * | ||
191 | * @return array The methods | ||
192 | */ | ||
193 | private function getRouteMethods(Route $route) | ||
194 | { | ||
195 | $methods = array(); | ||
196 | if ($req = $route->getRequirement('_method')) { | ||
197 | $methods = explode('|', strtoupper($req)); | ||
198 | // GET and HEAD are equivalent | ||
199 | if (in_array('GET', $methods) && !in_array('HEAD', $methods)) { | ||
200 | $methods[] = 'HEAD'; | ||
201 | } | ||
202 | } | ||
203 | |||
204 | return $methods; | ||
205 | } | ||
206 | |||
207 | /** | ||
208 | * Converts a regex to make it suitable for mod_rewrite | ||
209 | * | ||
210 | * @param string $regex The regex | ||
211 | * | ||
212 | * @return string The converted regex | ||
213 | */ | ||
214 | private function regexToApacheRegex($regex) | ||
215 | { | ||
216 | $regexPatternEnd = strrpos($regex, $regex[0]); | ||
217 | |||
218 | return preg_replace('/\?P<.+?>/', '', substr($regex, 1, $regexPatternEnd - 1)); | ||
219 | } | ||
220 | |||
221 | /** | ||
222 | * Escapes a string. | ||
223 | * | ||
224 | * @param string $string The string to be escaped | ||
225 | * @param string $char The character to be escaped | ||
226 | * @param string $with The character to be used for escaping | ||
227 | * | ||
228 | * @return string The escaped string | ||
229 | */ | ||
230 | private static function escape($string, $char, $with) | ||
231 | { | ||
232 | $escaped = false; | ||
233 | $output = ''; | ||
234 | foreach (str_split($string) as $symbol) { | ||
235 | if ($escaped) { | ||
236 | $output .= $symbol; | ||
237 | $escaped = false; | ||
238 | continue; | ||
239 | } | ||
240 | if ($symbol === $char) { | ||
241 | $output .= $with.$char; | ||
242 | continue; | ||
243 | } | ||
244 | if ($symbol === $with) { | ||
245 | $escaped = true; | ||
246 | } | ||
247 | $output .= $symbol; | ||
248 | } | ||
249 | |||
250 | return $output; | ||
251 | } | ||
252 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Matcher/Dumper/DumperCollection.php b/vendor/symfony/routing/Symfony/Component/Routing/Matcher/Dumper/DumperCollection.php new file mode 100644 index 00000000..612ac0d2 --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Matcher/Dumper/DumperCollection.php | |||
@@ -0,0 +1,159 @@ | |||
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\Matcher\Dumper; | ||
13 | |||
14 | /** | ||
15 | * Collection of routes. | ||
16 | * | ||
17 | * @author Arnaud Le Blanc <arnaud.lb@gmail.com> | ||
18 | */ | ||
19 | class DumperCollection implements \IteratorAggregate | ||
20 | { | ||
21 | /** | ||
22 | * @var DumperCollection|null | ||
23 | */ | ||
24 | private $parent; | ||
25 | |||
26 | /** | ||
27 | * @var (DumperCollection|DumperRoute)[] | ||
28 | */ | ||
29 | private $children = array(); | ||
30 | |||
31 | /** | ||
32 | * @var array | ||
33 | */ | ||
34 | private $attributes = array(); | ||
35 | |||
36 | /** | ||
37 | * Returns the children routes and collections. | ||
38 | * | ||
39 | * @return (DumperCollection|DumperRoute)[] Array of DumperCollection|DumperRoute | ||
40 | */ | ||
41 | public function all() | ||
42 | { | ||
43 | return $this->children; | ||
44 | } | ||
45 | |||
46 | /** | ||
47 | * Adds a route or collection | ||
48 | * | ||
49 | * @param DumperRoute|DumperCollection The route or collection | ||
50 | */ | ||
51 | public function add($child) | ||
52 | { | ||
53 | if ($child instanceof DumperCollection) { | ||
54 | $child->setParent($this); | ||
55 | } | ||
56 | $this->children[] = $child; | ||
57 | } | ||
58 | |||
59 | /** | ||
60 | * Sets children. | ||
61 | * | ||
62 | * @param array $children The children | ||
63 | */ | ||
64 | public function setAll(array $children) | ||
65 | { | ||
66 | foreach ($children as $child) { | ||
67 | if ($child instanceof DumperCollection) { | ||
68 | $child->setParent($this); | ||
69 | } | ||
70 | } | ||
71 | $this->children = $children; | ||
72 | } | ||
73 | |||
74 | /** | ||
75 | * Returns an iterator over the children. | ||
76 | * | ||
77 | * @return \Iterator The iterator | ||
78 | */ | ||
79 | public function getIterator() | ||
80 | { | ||
81 | return new \ArrayIterator($this->children); | ||
82 | } | ||
83 | |||
84 | /** | ||
85 | * Returns the root of the collection. | ||
86 | * | ||
87 | * @return DumperCollection The root collection | ||
88 | */ | ||
89 | public function getRoot() | ||
90 | { | ||
91 | return (null !== $this->parent) ? $this->parent->getRoot() : $this; | ||
92 | } | ||
93 | |||
94 | /** | ||
95 | * Returns the parent collection. | ||
96 | * | ||
97 | * @return DumperCollection|null The parent collection or null if the collection has no parent | ||
98 | */ | ||
99 | protected function getParent() | ||
100 | { | ||
101 | return $this->parent; | ||
102 | } | ||
103 | |||
104 | /** | ||
105 | * Sets the parent collection. | ||
106 | * | ||
107 | * @param DumperCollection $parent The parent collection | ||
108 | */ | ||
109 | protected function setParent(DumperCollection $parent) | ||
110 | { | ||
111 | $this->parent = $parent; | ||
112 | } | ||
113 | |||
114 | /** | ||
115 | * Returns true if the attribute is defined. | ||
116 | * | ||
117 | * @param string $name The attribute name | ||
118 | * | ||
119 | * @return Boolean true if the attribute is defined, false otherwise | ||
120 | */ | ||
121 | public function hasAttribute($name) | ||
122 | { | ||
123 | return array_key_exists($name, $this->attributes); | ||
124 | } | ||
125 | |||
126 | /** | ||
127 | * Returns an attribute by name. | ||
128 | * | ||
129 | * @param string $name The attribute name | ||
130 | * @param mixed $default Default value is the attribute doesn't exist | ||
131 | * | ||
132 | * @return mixed The attribute value | ||
133 | */ | ||
134 | public function getAttribute($name, $default = null) | ||
135 | { | ||
136 | return $this->hasAttribute($name) ? $this->attributes[$name] : $default; | ||
137 | } | ||
138 | |||
139 | /** | ||
140 | * Sets an attribute by name. | ||
141 | * | ||
142 | * @param string $name The attribute name | ||
143 | * @param mixed $value The attribute value | ||
144 | */ | ||
145 | public function setAttribute($name, $value) | ||
146 | { | ||
147 | $this->attributes[$name] = $value; | ||
148 | } | ||
149 | |||
150 | /** | ||
151 | * Sets multiple attributes. | ||
152 | * | ||
153 | * @param array $attributes The attributes | ||
154 | */ | ||
155 | public function setAttributes($attributes) | ||
156 | { | ||
157 | $this->attributes = $attributes; | ||
158 | } | ||
159 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Matcher/Dumper/DumperPrefixCollection.php b/vendor/symfony/routing/Symfony/Component/Routing/Matcher/Dumper/DumperPrefixCollection.php new file mode 100644 index 00000000..26382b0b --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Matcher/Dumper/DumperPrefixCollection.php | |||
@@ -0,0 +1,108 @@ | |||
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\Matcher\Dumper; | ||
13 | |||
14 | /** | ||
15 | * Prefix tree of routes preserving routes order. | ||
16 | * | ||
17 | * @author Arnaud Le Blanc <arnaud.lb@gmail.com> | ||
18 | */ | ||
19 | class DumperPrefixCollection extends DumperCollection | ||
20 | { | ||
21 | /** | ||
22 | * @var string | ||
23 | */ | ||
24 | private $prefix = ''; | ||
25 | |||
26 | /** | ||
27 | * Returns the prefix. | ||
28 | * | ||
29 | * @return string The prefix | ||
30 | */ | ||
31 | public function getPrefix() | ||
32 | { | ||
33 | return $this->prefix; | ||
34 | } | ||
35 | |||
36 | /** | ||
37 | * Sets the prefix. | ||
38 | * | ||
39 | * @param string $prefix The prefix | ||
40 | */ | ||
41 | public function setPrefix($prefix) | ||
42 | { | ||
43 | $this->prefix = $prefix; | ||
44 | } | ||
45 | |||
46 | /** | ||
47 | * Adds a route in the tree. | ||
48 | * | ||
49 | * @param DumperRoute $route The route | ||
50 | * | ||
51 | * @return DumperPrefixCollection The node the route was added to | ||
52 | * | ||
53 | * @throws \LogicException | ||
54 | */ | ||
55 | public function addPrefixRoute(DumperRoute $route) | ||
56 | { | ||
57 | $prefix = $route->getRoute()->compile()->getStaticPrefix(); | ||
58 | |||
59 | // Same prefix, add to current leave | ||
60 | if ($this->prefix === $prefix) { | ||
61 | $this->add($route); | ||
62 | |||
63 | return $this; | ||
64 | } | ||
65 | |||
66 | // Prefix starts with route's prefix | ||
67 | if ('' === $this->prefix || 0 === strpos($prefix, $this->prefix)) { | ||
68 | $collection = new DumperPrefixCollection(); | ||
69 | $collection->setPrefix(substr($prefix, 0, strlen($this->prefix)+1)); | ||
70 | $this->add($collection); | ||
71 | |||
72 | return $collection->addPrefixRoute($route); | ||
73 | } | ||
74 | |||
75 | // No match, fallback to parent (recursively) | ||
76 | |||
77 | if (null === $parent = $this->getParent()) { | ||
78 | throw new \LogicException("The collection root must not have a prefix"); | ||
79 | } | ||
80 | |||
81 | return $parent->addPrefixRoute($route); | ||
82 | } | ||
83 | |||
84 | /** | ||
85 | * Merges nodes whose prefix ends with a slash | ||
86 | * | ||
87 | * Children of a node whose prefix ends with a slash are moved to the parent node | ||
88 | */ | ||
89 | public function mergeSlashNodes() | ||
90 | { | ||
91 | $children = array(); | ||
92 | |||
93 | foreach ($this as $child) { | ||
94 | if ($child instanceof self) { | ||
95 | $child->mergeSlashNodes(); | ||
96 | if ('/' === substr($child->prefix, -1)) { | ||
97 | $children = array_merge($children, $child->all()); | ||
98 | } else { | ||
99 | $children[] = $child; | ||
100 | } | ||
101 | } else { | ||
102 | $children[] = $child; | ||
103 | } | ||
104 | } | ||
105 | |||
106 | $this->setAll($children); | ||
107 | } | ||
108 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Matcher/Dumper/DumperRoute.php b/vendor/symfony/routing/Symfony/Component/Routing/Matcher/Dumper/DumperRoute.php new file mode 100644 index 00000000..2928cdcc --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Matcher/Dumper/DumperRoute.php | |||
@@ -0,0 +1,64 @@ | |||
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\Matcher\Dumper; | ||
13 | |||
14 | use Symfony\Component\Routing\Route; | ||
15 | |||
16 | /** | ||
17 | * Container for a Route. | ||
18 | * | ||
19 | * @author Arnaud Le Blanc <arnaud.lb@gmail.com> | ||
20 | */ | ||
21 | class DumperRoute | ||
22 | { | ||
23 | /** | ||
24 | * @var string | ||
25 | */ | ||
26 | private $name; | ||
27 | |||
28 | /** | ||
29 | * @var Route | ||
30 | */ | ||
31 | private $route; | ||
32 | |||
33 | /** | ||
34 | * Constructor. | ||
35 | * | ||
36 | * @param string $name The route name | ||
37 | * @param Route $route The route | ||
38 | */ | ||
39 | public function __construct($name, Route $route) | ||
40 | { | ||
41 | $this->name = $name; | ||
42 | $this->route = $route; | ||
43 | } | ||
44 | |||
45 | /** | ||
46 | * Returns the route name. | ||
47 | * | ||
48 | * @return string The route name | ||
49 | */ | ||
50 | public function getName() | ||
51 | { | ||
52 | return $this->name; | ||
53 | } | ||
54 | |||
55 | /** | ||
56 | * Returns the route. | ||
57 | * | ||
58 | * @return Route The route | ||
59 | */ | ||
60 | public function getRoute() | ||
61 | { | ||
62 | return $this->route; | ||
63 | } | ||
64 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Matcher/Dumper/MatcherDumper.php b/vendor/symfony/routing/Symfony/Component/Routing/Matcher/Dumper/MatcherDumper.php new file mode 100644 index 00000000..52edc017 --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Matcher/Dumper/MatcherDumper.php | |||
@@ -0,0 +1,45 @@ | |||
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\Matcher\Dumper; | ||
13 | |||
14 | use Symfony\Component\Routing\RouteCollection; | ||
15 | |||
16 | /** | ||
17 | * MatcherDumper is the abstract class for all built-in matcher dumpers. | ||
18 | * | ||
19 | * @author Fabien Potencier <fabien@symfony.com> | ||
20 | */ | ||
21 | abstract class MatcherDumper implements MatcherDumperInterface | ||
22 | { | ||
23 | /** | ||
24 | * @var RouteCollection | ||
25 | */ | ||
26 | private $routes; | ||
27 | |||
28 | /** | ||
29 | * Constructor. | ||
30 | * | ||
31 | * @param RouteCollection $routes The RouteCollection to dump | ||
32 | */ | ||
33 | public function __construct(RouteCollection $routes) | ||
34 | { | ||
35 | $this->routes = $routes; | ||
36 | } | ||
37 | |||
38 | /** | ||
39 | * {@inheritdoc} | ||
40 | */ | ||
41 | public function getRoutes() | ||
42 | { | ||
43 | return $this->routes; | ||
44 | } | ||
45 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Matcher/Dumper/MatcherDumperInterface.php b/vendor/symfony/routing/Symfony/Component/Routing/Matcher/Dumper/MatcherDumperInterface.php new file mode 100644 index 00000000..f85e4cef --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Matcher/Dumper/MatcherDumperInterface.php | |||
@@ -0,0 +1,37 @@ | |||
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\Matcher\Dumper; | ||
13 | |||
14 | /** | ||
15 | * MatcherDumperInterface is the interface that all matcher dumper classes must implement. | ||
16 | * | ||
17 | * @author Fabien Potencier <fabien@symfony.com> | ||
18 | */ | ||
19 | interface MatcherDumperInterface | ||
20 | { | ||
21 | /** | ||
22 | * Dumps a set of routes to a string representation of executable code | ||
23 | * that can then be used to match a request against these routes. | ||
24 | * | ||
25 | * @param array $options An array of options | ||
26 | * | ||
27 | * @return string Executable code | ||
28 | */ | ||
29 | public function dump(array $options = array()); | ||
30 | |||
31 | /** | ||
32 | * Gets the routes to dump. | ||
33 | * | ||
34 | * @return RouteCollection A RouteCollection instance | ||
35 | */ | ||
36 | public function getRoutes(); | ||
37 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php b/vendor/symfony/routing/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php new file mode 100644 index 00000000..dc17ffbe --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php | |||
@@ -0,0 +1,378 @@ | |||
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\Matcher\Dumper; | ||
13 | |||
14 | use Symfony\Component\Routing\Route; | ||
15 | use Symfony\Component\Routing\RouteCollection; | ||
16 | |||
17 | /** | ||
18 | * PhpMatcherDumper creates a PHP class able to match URLs for a given set of routes. | ||
19 | * | ||
20 | * @author Fabien Potencier <fabien@symfony.com> | ||
21 | * @author Tobias Schultze <http://tobion.de> | ||
22 | * @author Arnaud Le Blanc <arnaud.lb@gmail.com> | ||
23 | */ | ||
24 | class PhpMatcherDumper extends MatcherDumper | ||
25 | { | ||
26 | /** | ||
27 | * Dumps a set of routes to a PHP class. | ||
28 | * | ||
29 | * Available options: | ||
30 | * | ||
31 | * * class: The class name | ||
32 | * * base_class: The base class name | ||
33 | * | ||
34 | * @param array $options An array of options | ||
35 | * | ||
36 | * @return string A PHP class representing the matcher class | ||
37 | */ | ||
38 | public function dump(array $options = array()) | ||
39 | { | ||
40 | $options = array_replace(array( | ||
41 | 'class' => 'ProjectUrlMatcher', | ||
42 | 'base_class' => 'Symfony\\Component\\Routing\\Matcher\\UrlMatcher', | ||
43 | ), $options); | ||
44 | |||
45 | // trailing slash support is only enabled if we know how to redirect the user | ||
46 | $interfaces = class_implements($options['base_class']); | ||
47 | $supportsRedirections = isset($interfaces['Symfony\\Component\\Routing\\Matcher\\RedirectableUrlMatcherInterface']); | ||
48 | |||
49 | return <<<EOF | ||
50 | <?php | ||
51 | |||
52 | use Symfony\Component\Routing\Exception\MethodNotAllowedException; | ||
53 | use Symfony\Component\Routing\Exception\ResourceNotFoundException; | ||
54 | use Symfony\Component\Routing\RequestContext; | ||
55 | |||
56 | /** | ||
57 | * {$options['class']} | ||
58 | * | ||
59 | * This class has been auto-generated | ||
60 | * by the Symfony Routing Component. | ||
61 | */ | ||
62 | class {$options['class']} extends {$options['base_class']} | ||
63 | { | ||
64 | /** | ||
65 | * Constructor. | ||
66 | */ | ||
67 | public function __construct(RequestContext \$context) | ||
68 | { | ||
69 | \$this->context = \$context; | ||
70 | } | ||
71 | |||
72 | {$this->generateMatchMethod($supportsRedirections)} | ||
73 | } | ||
74 | |||
75 | EOF; | ||
76 | } | ||
77 | |||
78 | /** | ||
79 | * Generates the code for the match method implementing UrlMatcherInterface. | ||
80 | * | ||
81 | * @param Boolean $supportsRedirections Whether redirections are supported by the base class | ||
82 | * | ||
83 | * @return string Match method as PHP code | ||
84 | */ | ||
85 | private function generateMatchMethod($supportsRedirections) | ||
86 | { | ||
87 | $code = rtrim($this->compileRoutes($this->getRoutes(), $supportsRedirections), "\n"); | ||
88 | |||
89 | return <<<EOF | ||
90 | public function match(\$pathinfo) | ||
91 | { | ||
92 | \$allow = array(); | ||
93 | \$pathinfo = rawurldecode(\$pathinfo); | ||
94 | |||
95 | $code | ||
96 | |||
97 | throw 0 < count(\$allow) ? new MethodNotAllowedException(array_unique(\$allow)) : new ResourceNotFoundException(); | ||
98 | } | ||
99 | EOF; | ||
100 | } | ||
101 | |||
102 | /** | ||
103 | * Generates PHP code to match a RouteCollection with all its routes. | ||
104 | * | ||
105 | * @param RouteCollection $routes A RouteCollection instance | ||
106 | * @param Boolean $supportsRedirections Whether redirections are supported by the base class | ||
107 | * | ||
108 | * @return string PHP code | ||
109 | */ | ||
110 | private function compileRoutes(RouteCollection $routes, $supportsRedirections) | ||
111 | { | ||
112 | $fetchedHost = false; | ||
113 | |||
114 | $groups = $this->groupRoutesByHostRegex($routes); | ||
115 | $code = ''; | ||
116 | |||
117 | foreach ($groups as $collection) { | ||
118 | if (null !== $regex = $collection->getAttribute('host_regex')) { | ||
119 | if (!$fetchedHost) { | ||
120 | $code .= " \$host = \$this->context->getHost();\n\n"; | ||
121 | $fetchedHost = true; | ||
122 | } | ||
123 | |||
124 | $code .= sprintf(" if (preg_match(%s, \$host, \$hostMatches)) {\n", var_export($regex, true)); | ||
125 | } | ||
126 | |||
127 | $tree = $this->buildPrefixTree($collection); | ||
128 | $groupCode = $this->compilePrefixRoutes($tree, $supportsRedirections); | ||
129 | |||
130 | if (null !== $regex) { | ||
131 | // apply extra indention at each line (except empty ones) | ||
132 | $groupCode = preg_replace('/^.{2,}$/m', ' $0', $groupCode); | ||
133 | $code .= $groupCode; | ||
134 | $code .= " }\n\n"; | ||
135 | } else { | ||
136 | $code .= $groupCode; | ||
137 | } | ||
138 | } | ||
139 | |||
140 | return $code; | ||
141 | } | ||
142 | |||
143 | /** | ||
144 | * Generates PHP code recursively to match a tree of routes | ||
145 | * | ||
146 | * @param DumperPrefixCollection $collection A DumperPrefixCollection instance | ||
147 | * @param Boolean $supportsRedirections Whether redirections are supported by the base class | ||
148 | * @param string $parentPrefix Prefix of the parent collection | ||
149 | * | ||
150 | * @return string PHP code | ||
151 | */ | ||
152 | private function compilePrefixRoutes(DumperPrefixCollection $collection, $supportsRedirections, $parentPrefix = '') | ||
153 | { | ||
154 | $code = ''; | ||
155 | $prefix = $collection->getPrefix(); | ||
156 | $optimizable = 1 < strlen($prefix) && 1 < count($collection->all()); | ||
157 | $optimizedPrefix = $parentPrefix; | ||
158 | |||
159 | if ($optimizable) { | ||
160 | $optimizedPrefix = $prefix; | ||
161 | |||
162 | $code .= sprintf(" if (0 === strpos(\$pathinfo, %s)) {\n", var_export($prefix, true)); | ||
163 | } | ||
164 | |||
165 | foreach ($collection as $route) { | ||
166 | if ($route instanceof DumperCollection) { | ||
167 | $code .= $this->compilePrefixRoutes($route, $supportsRedirections, $optimizedPrefix); | ||
168 | } else { | ||
169 | $code .= $this->compileRoute($route->getRoute(), $route->getName(), $supportsRedirections, $optimizedPrefix)."\n"; | ||
170 | } | ||
171 | } | ||
172 | |||
173 | if ($optimizable) { | ||
174 | $code .= " }\n\n"; | ||
175 | // apply extra indention at each line (except empty ones) | ||
176 | $code = preg_replace('/^.{2,}$/m', ' $0', $code); | ||
177 | } | ||
178 | |||
179 | return $code; | ||
180 | } | ||
181 | |||
182 | /** | ||
183 | * Compiles a single Route to PHP code used to match it against the path info. | ||
184 | * | ||
185 | * @param Route $route A Route instance | ||
186 | * @param string $name The name of the Route | ||
187 | * @param Boolean $supportsRedirections Whether redirections are supported by the base class | ||
188 | * @param string|null $parentPrefix The prefix of the parent collection used to optimize the code | ||
189 | * | ||
190 | * @return string PHP code | ||
191 | * | ||
192 | * @throws \LogicException | ||
193 | */ | ||
194 | private function compileRoute(Route $route, $name, $supportsRedirections, $parentPrefix = null) | ||
195 | { | ||
196 | $code = ''; | ||
197 | $compiledRoute = $route->compile(); | ||
198 | $conditions = array(); | ||
199 | $hasTrailingSlash = false; | ||
200 | $matches = false; | ||
201 | $hostMatches = false; | ||
202 | $methods = array(); | ||
203 | |||
204 | if ($req = $route->getRequirement('_method')) { | ||
205 | $methods = explode('|', strtoupper($req)); | ||
206 | // GET and HEAD are equivalent | ||
207 | if (in_array('GET', $methods) && !in_array('HEAD', $methods)) { | ||
208 | $methods[] = 'HEAD'; | ||
209 | } | ||
210 | } | ||
211 | |||
212 | $supportsTrailingSlash = $supportsRedirections && (!$methods || in_array('HEAD', $methods)); | ||
213 | |||
214 | if (!count($compiledRoute->getPathVariables()) && false !== preg_match('#^(.)\^(?P<url>.*?)\$\1#', $compiledRoute->getRegex(), $m)) { | ||
215 | if ($supportsTrailingSlash && substr($m['url'], -1) === '/') { | ||
216 | $conditions[] = sprintf("rtrim(\$pathinfo, '/') === %s", var_export(rtrim(str_replace('\\', '', $m['url']), '/'), true)); | ||
217 | $hasTrailingSlash = true; | ||
218 | } else { | ||
219 | $conditions[] = sprintf("\$pathinfo === %s", var_export(str_replace('\\', '', $m['url']), true)); | ||
220 | } | ||
221 | } else { | ||
222 | if ($compiledRoute->getStaticPrefix() && $compiledRoute->getStaticPrefix() !== $parentPrefix) { | ||
223 | $conditions[] = sprintf("0 === strpos(\$pathinfo, %s)", var_export($compiledRoute->getStaticPrefix(), true)); | ||
224 | } | ||
225 | |||
226 | $regex = $compiledRoute->getRegex(); | ||
227 | if ($supportsTrailingSlash && $pos = strpos($regex, '/$')) { | ||
228 | $regex = substr($regex, 0, $pos).'/?$'.substr($regex, $pos + 2); | ||
229 | $hasTrailingSlash = true; | ||
230 | } | ||
231 | $conditions[] = sprintf("preg_match(%s, \$pathinfo, \$matches)", var_export($regex, true)); | ||
232 | |||
233 | $matches = true; | ||
234 | } | ||
235 | |||
236 | if ($compiledRoute->getHostVariables()) { | ||
237 | $hostMatches = true; | ||
238 | } | ||
239 | |||
240 | $conditions = implode(' && ', $conditions); | ||
241 | |||
242 | $code .= <<<EOF | ||
243 | // $name | ||
244 | if ($conditions) { | ||
245 | |||
246 | EOF; | ||
247 | |||
248 | if ($methods) { | ||
249 | $gotoname = 'not_'.preg_replace('/[^A-Za-z0-9_]/', '', $name); | ||
250 | |||
251 | if (1 === count($methods)) { | ||
252 | $code .= <<<EOF | ||
253 | if (\$this->context->getMethod() != '$methods[0]') { | ||
254 | \$allow[] = '$methods[0]'; | ||
255 | goto $gotoname; | ||
256 | } | ||
257 | |||
258 | |||
259 | EOF; | ||
260 | } else { | ||
261 | $methods = implode("', '", $methods); | ||
262 | $code .= <<<EOF | ||
263 | if (!in_array(\$this->context->getMethod(), array('$methods'))) { | ||
264 | \$allow = array_merge(\$allow, array('$methods')); | ||
265 | goto $gotoname; | ||
266 | } | ||
267 | |||
268 | |||
269 | EOF; | ||
270 | } | ||
271 | } | ||
272 | |||
273 | if ($hasTrailingSlash) { | ||
274 | $code .= <<<EOF | ||
275 | if (substr(\$pathinfo, -1) !== '/') { | ||
276 | return \$this->redirect(\$pathinfo.'/', '$name'); | ||
277 | } | ||
278 | |||
279 | |||
280 | EOF; | ||
281 | } | ||
282 | |||
283 | if ($scheme = $route->getRequirement('_scheme')) { | ||
284 | if (!$supportsRedirections) { | ||
285 | throw new \LogicException('The "_scheme" requirement is only supported for URL matchers that implement RedirectableUrlMatcherInterface.'); | ||
286 | } | ||
287 | |||
288 | $code .= <<<EOF | ||
289 | if (\$this->context->getScheme() !== '$scheme') { | ||
290 | return \$this->redirect(\$pathinfo, '$name', '$scheme'); | ||
291 | } | ||
292 | |||
293 | |||
294 | EOF; | ||
295 | } | ||
296 | |||
297 | // optimize parameters array | ||
298 | if ($matches || $hostMatches) { | ||
299 | $vars = array(); | ||
300 | if ($hostMatches) { | ||
301 | $vars[] = '$hostMatches'; | ||
302 | } | ||
303 | if ($matches) { | ||
304 | $vars[] = '$matches'; | ||
305 | } | ||
306 | $vars[] = "array('_route' => '$name')"; | ||
307 | |||
308 | $code .= sprintf(" return \$this->mergeDefaults(array_replace(%s), %s);\n" | ||
309 | , implode(', ', $vars), str_replace("\n", '', var_export($route->getDefaults(), true))); | ||
310 | |||
311 | } elseif ($route->getDefaults()) { | ||
312 | $code .= sprintf(" return %s;\n", str_replace("\n", '', var_export(array_replace($route->getDefaults(), array('_route' => $name)), true))); | ||
313 | } else { | ||
314 | $code .= sprintf(" return array('_route' => '%s');\n", $name); | ||
315 | } | ||
316 | $code .= " }\n"; | ||
317 | |||
318 | if ($methods) { | ||
319 | $code .= " $gotoname:\n"; | ||
320 | } | ||
321 | |||
322 | return $code; | ||
323 | } | ||
324 | |||
325 | /** | ||
326 | * Groups consecutive routes having the same host regex. | ||
327 | * | ||
328 | * The result is a collection of collections of routes having the same host regex. | ||
329 | * | ||
330 | * @param RouteCollection $routes A flat RouteCollection | ||
331 | * | ||
332 | * @return DumperCollection A collection with routes grouped by host regex in sub-collections | ||
333 | */ | ||
334 | private function groupRoutesByHostRegex(RouteCollection $routes) | ||
335 | { | ||
336 | $groups = new DumperCollection(); | ||
337 | |||
338 | $currentGroup = new DumperCollection(); | ||
339 | $currentGroup->setAttribute('host_regex', null); | ||
340 | $groups->add($currentGroup); | ||
341 | |||
342 | foreach ($routes as $name => $route) { | ||
343 | $hostRegex = $route->compile()->getHostRegex(); | ||
344 | if ($currentGroup->getAttribute('host_regex') !== $hostRegex) { | ||
345 | $currentGroup = new DumperCollection(); | ||
346 | $currentGroup->setAttribute('host_regex', $hostRegex); | ||
347 | $groups->add($currentGroup); | ||
348 | } | ||
349 | $currentGroup->add(new DumperRoute($name, $route)); | ||
350 | } | ||
351 | |||
352 | return $groups; | ||
353 | } | ||
354 | |||
355 | /** | ||
356 | * Organizes the routes into a prefix tree. | ||
357 | * | ||
358 | * Routes order is preserved such that traversing the tree will traverse the | ||
359 | * routes in the origin order. | ||
360 | * | ||
361 | * @param DumperCollection $collection A collection of routes | ||
362 | * | ||
363 | * @return DumperPrefixCollection | ||
364 | */ | ||
365 | private function buildPrefixTree(DumperCollection $collection) | ||
366 | { | ||
367 | $tree = new DumperPrefixCollection(); | ||
368 | $current = $tree; | ||
369 | |||
370 | foreach ($collection as $route) { | ||
371 | $current = $current->addPrefixRoute($route); | ||
372 | } | ||
373 | |||
374 | $tree->mergeSlashNodes(); | ||
375 | |||
376 | return $tree; | ||
377 | } | ||
378 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Matcher/RedirectableUrlMatcher.php b/vendor/symfony/routing/Symfony/Component/Routing/Matcher/RedirectableUrlMatcher.php new file mode 100644 index 00000000..51e80057 --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Matcher/RedirectableUrlMatcher.php | |||
@@ -0,0 +1,61 @@ | |||
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\Matcher; | ||
13 | |||
14 | use Symfony\Component\Routing\Exception\ResourceNotFoundException; | ||
15 | use Symfony\Component\Routing\Route; | ||
16 | |||
17 | /** | ||
18 | * @author Fabien Potencier <fabien@symfony.com> | ||
19 | * | ||
20 | * @api | ||
21 | */ | ||
22 | abstract class RedirectableUrlMatcher extends UrlMatcher implements RedirectableUrlMatcherInterface | ||
23 | { | ||
24 | /** | ||
25 | * {@inheritdoc} | ||
26 | */ | ||
27 | public function match($pathinfo) | ||
28 | { | ||
29 | try { | ||
30 | $parameters = parent::match($pathinfo); | ||
31 | } catch (ResourceNotFoundException $e) { | ||
32 | if ('/' === substr($pathinfo, -1) || !in_array($this->context->getMethod(), array('HEAD', 'GET'))) { | ||
33 | throw $e; | ||
34 | } | ||
35 | |||
36 | try { | ||
37 | parent::match($pathinfo.'/'); | ||
38 | |||
39 | return $this->redirect($pathinfo.'/', null); | ||
40 | } catch (ResourceNotFoundException $e2) { | ||
41 | throw $e; | ||
42 | } | ||
43 | } | ||
44 | |||
45 | return $parameters; | ||
46 | } | ||
47 | |||
48 | /** | ||
49 | * {@inheritDoc} | ||
50 | */ | ||
51 | protected function handleRouteRequirements($pathinfo, $name, Route $route) | ||
52 | { | ||
53 | // check HTTP scheme requirement | ||
54 | $scheme = $route->getRequirement('_scheme'); | ||
55 | if ($scheme && $this->context->getScheme() !== $scheme) { | ||
56 | return array(self::ROUTE_MATCH, $this->redirect($pathinfo, $name, $scheme)); | ||
57 | } | ||
58 | |||
59 | return array(self::REQUIREMENT_MATCH, null); | ||
60 | } | ||
61 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Matcher/RedirectableUrlMatcherInterface.php b/vendor/symfony/routing/Symfony/Component/Routing/Matcher/RedirectableUrlMatcherInterface.php new file mode 100644 index 00000000..ea91e075 --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Matcher/RedirectableUrlMatcherInterface.php | |||
@@ -0,0 +1,35 @@ | |||
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\Matcher; | ||
13 | |||
14 | /** | ||
15 | * RedirectableUrlMatcherInterface knows how to redirect the user. | ||
16 | * | ||
17 | * @author Fabien Potencier <fabien@symfony.com> | ||
18 | * | ||
19 | * @api | ||
20 | */ | ||
21 | interface RedirectableUrlMatcherInterface | ||
22 | { | ||
23 | /** | ||
24 | * Redirects the user to another URL. | ||
25 | * | ||
26 | * @param string $path The path info to redirect to. | ||
27 | * @param string $route The route name that matched | ||
28 | * @param string|null $scheme The URL scheme (null to keep the current one) | ||
29 | * | ||
30 | * @return array An array of parameters | ||
31 | * | ||
32 | * @api | ||
33 | */ | ||
34 | public function redirect($path, $route, $scheme = null); | ||
35 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Matcher/RequestMatcherInterface.php b/vendor/symfony/routing/Symfony/Component/Routing/Matcher/RequestMatcherInterface.php new file mode 100644 index 00000000..b5def3d4 --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Matcher/RequestMatcherInterface.php | |||
@@ -0,0 +1,39 @@ | |||
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\Matcher; | ||
13 | |||
14 | use Symfony\Component\HttpFoundation\Request; | ||
15 | use Symfony\Component\Routing\Exception\ResourceNotFoundException; | ||
16 | use Symfony\Component\Routing\Exception\MethodNotAllowedException; | ||
17 | |||
18 | /** | ||
19 | * RequestMatcherInterface is the interface that all request matcher classes must implement. | ||
20 | * | ||
21 | * @author Fabien Potencier <fabien@symfony.com> | ||
22 | */ | ||
23 | interface RequestMatcherInterface | ||
24 | { | ||
25 | /** | ||
26 | * Tries to match a request with a set of routes. | ||
27 | * | ||
28 | * If the matcher can not find information, it must throw one of the exceptions documented | ||
29 | * below. | ||
30 | * | ||
31 | * @param Request $request The request to match | ||
32 | * | ||
33 | * @return array An array of parameters | ||
34 | * | ||
35 | * @throws ResourceNotFoundException If no matching resource could be found | ||
36 | * @throws MethodNotAllowedException If a matching resource was found but the request method is not allowed | ||
37 | */ | ||
38 | public function matchRequest(Request $request); | ||
39 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Matcher/TraceableUrlMatcher.php b/vendor/symfony/routing/Symfony/Component/Routing/Matcher/TraceableUrlMatcher.php new file mode 100644 index 00000000..c09f83e8 --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Matcher/TraceableUrlMatcher.php | |||
@@ -0,0 +1,121 @@ | |||
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\Matcher; | ||
13 | |||
14 | use Symfony\Component\Routing\Exception\ExceptionInterface; | ||
15 | use Symfony\Component\Routing\Route; | ||
16 | use Symfony\Component\Routing\RouteCollection; | ||
17 | use Symfony\Component\Routing\Matcher\UrlMatcher; | ||
18 | |||
19 | /** | ||
20 | * TraceableUrlMatcher helps debug path info matching by tracing the match. | ||
21 | * | ||
22 | * @author Fabien Potencier <fabien@symfony.com> | ||
23 | */ | ||
24 | class TraceableUrlMatcher extends UrlMatcher | ||
25 | { | ||
26 | const ROUTE_DOES_NOT_MATCH = 0; | ||
27 | const ROUTE_ALMOST_MATCHES = 1; | ||
28 | const ROUTE_MATCHES = 2; | ||
29 | |||
30 | protected $traces; | ||
31 | |||
32 | public function getTraces($pathinfo) | ||
33 | { | ||
34 | $this->traces = array(); | ||
35 | |||
36 | try { | ||
37 | $this->match($pathinfo); | ||
38 | } catch (ExceptionInterface $e) { | ||
39 | } | ||
40 | |||
41 | return $this->traces; | ||
42 | } | ||
43 | |||
44 | protected function matchCollection($pathinfo, RouteCollection $routes) | ||
45 | { | ||
46 | foreach ($routes as $name => $route) { | ||
47 | $compiledRoute = $route->compile(); | ||
48 | |||
49 | if (!preg_match($compiledRoute->getRegex(), $pathinfo, $matches)) { | ||
50 | // does it match without any requirements? | ||
51 | $r = new Route($route->getPath(), $route->getDefaults(), array(), $route->getOptions()); | ||
52 | $cr = $r->compile(); | ||
53 | if (!preg_match($cr->getRegex(), $pathinfo)) { | ||
54 | $this->addTrace(sprintf('Path "%s" does not match', $route->getPath()), self::ROUTE_DOES_NOT_MATCH, $name, $route); | ||
55 | |||
56 | continue; | ||
57 | } | ||
58 | |||
59 | foreach ($route->getRequirements() as $n => $regex) { | ||
60 | $r = new Route($route->getPath(), $route->getDefaults(), array($n => $regex), $route->getOptions()); | ||
61 | $cr = $r->compile(); | ||
62 | |||
63 | if (in_array($n, $cr->getVariables()) && !preg_match($cr->getRegex(), $pathinfo)) { | ||
64 | $this->addTrace(sprintf('Requirement for "%s" does not match (%s)', $n, $regex), self::ROUTE_ALMOST_MATCHES, $name, $route); | ||
65 | |||
66 | continue 2; | ||
67 | } | ||
68 | } | ||
69 | |||
70 | continue; | ||
71 | } | ||
72 | |||
73 | // check host requirement | ||
74 | $hostMatches = array(); | ||
75 | if ($compiledRoute->getHostRegex() && !preg_match($compiledRoute->getHostRegex(), $this->context->getHost(), $hostMatches)) { | ||
76 | $this->addTrace(sprintf('Host "%s" does not match the requirement ("%s")', $this->context->getHost(), $route->getHost()), self::ROUTE_ALMOST_MATCHES, $name, $route); | ||
77 | |||
78 | return true; | ||
79 | } | ||
80 | |||
81 | // check HTTP method requirement | ||
82 | if ($req = $route->getRequirement('_method')) { | ||
83 | // HEAD and GET are equivalent as per RFC | ||
84 | if ('HEAD' === $method = $this->context->getMethod()) { | ||
85 | $method = 'GET'; | ||
86 | } | ||
87 | |||
88 | if (!in_array($method, $req = explode('|', strtoupper($req)))) { | ||
89 | $this->allow = array_merge($this->allow, $req); | ||
90 | |||
91 | $this->addTrace(sprintf('Method "%s" does not match the requirement ("%s")', $this->context->getMethod(), implode(', ', $req)), self::ROUTE_ALMOST_MATCHES, $name, $route); | ||
92 | |||
93 | continue; | ||
94 | } | ||
95 | } | ||
96 | |||
97 | // check HTTP scheme requirement | ||
98 | if ($scheme = $route->getRequirement('_scheme')) { | ||
99 | if ($this->context->getScheme() !== $scheme) { | ||
100 | $this->addTrace(sprintf('Scheme "%s" does not match the requirement ("%s"); the user will be redirected', $this->context->getScheme(), $scheme), self::ROUTE_ALMOST_MATCHES, $name, $route); | ||
101 | |||
102 | return true; | ||
103 | } | ||
104 | } | ||
105 | |||
106 | $this->addTrace('Route matches!', self::ROUTE_MATCHES, $name, $route); | ||
107 | |||
108 | return true; | ||
109 | } | ||
110 | } | ||
111 | |||
112 | private function addTrace($log, $level = self::ROUTE_DOES_NOT_MATCH, $name = null, $route = null) | ||
113 | { | ||
114 | $this->traces[] = array( | ||
115 | 'log' => $log, | ||
116 | 'name' => $name, | ||
117 | 'level' => $level, | ||
118 | 'path' => null !== $route ? $route->getPath() : null, | ||
119 | ); | ||
120 | } | ||
121 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Matcher/UrlMatcher.php b/vendor/symfony/routing/Symfony/Component/Routing/Matcher/UrlMatcher.php new file mode 100644 index 00000000..db18ec4e --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Matcher/UrlMatcher.php | |||
@@ -0,0 +1,208 @@ | |||
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\Matcher; | ||
13 | |||
14 | use Symfony\Component\Routing\Exception\MethodNotAllowedException; | ||
15 | use Symfony\Component\Routing\Exception\ResourceNotFoundException; | ||
16 | use Symfony\Component\Routing\RouteCollection; | ||
17 | use Symfony\Component\Routing\RequestContext; | ||
18 | use Symfony\Component\Routing\Route; | ||
19 | |||
20 | /** | ||
21 | * UrlMatcher matches URL based on a set of routes. | ||
22 | * | ||
23 | * @author Fabien Potencier <fabien@symfony.com> | ||
24 | * | ||
25 | * @api | ||
26 | */ | ||
27 | class UrlMatcher implements UrlMatcherInterface | ||
28 | { | ||
29 | const REQUIREMENT_MATCH = 0; | ||
30 | const REQUIREMENT_MISMATCH = 1; | ||
31 | const ROUTE_MATCH = 2; | ||
32 | |||
33 | /** | ||
34 | * @var RequestContext | ||
35 | */ | ||
36 | protected $context; | ||
37 | |||
38 | /** | ||
39 | * @var array | ||
40 | */ | ||
41 | protected $allow = array(); | ||
42 | |||
43 | /** | ||
44 | * @var RouteCollection | ||
45 | */ | ||
46 | protected $routes; | ||
47 | |||
48 | /** | ||
49 | * Constructor. | ||
50 | * | ||
51 | * @param RouteCollection $routes A RouteCollection instance | ||
52 | * @param RequestContext $context The context | ||
53 | * | ||
54 | * @api | ||
55 | */ | ||
56 | public function __construct(RouteCollection $routes, RequestContext $context) | ||
57 | { | ||
58 | $this->routes = $routes; | ||
59 | $this->context = $context; | ||
60 | } | ||
61 | |||
62 | /** | ||
63 | * {@inheritdoc} | ||
64 | */ | ||
65 | public function setContext(RequestContext $context) | ||
66 | { | ||
67 | $this->context = $context; | ||
68 | } | ||
69 | |||
70 | /** | ||
71 | * {@inheritdoc} | ||
72 | */ | ||
73 | public function getContext() | ||
74 | { | ||
75 | return $this->context; | ||
76 | } | ||
77 | |||
78 | /** | ||
79 | * {@inheritdoc} | ||
80 | */ | ||
81 | public function match($pathinfo) | ||
82 | { | ||
83 | $this->allow = array(); | ||
84 | |||
85 | if ($ret = $this->matchCollection(rawurldecode($pathinfo), $this->routes)) { | ||
86 | return $ret; | ||
87 | } | ||
88 | |||
89 | throw 0 < count($this->allow) | ||
90 | ? new MethodNotAllowedException(array_unique(array_map('strtoupper', $this->allow))) | ||
91 | : new ResourceNotFoundException(); | ||
92 | } | ||
93 | |||
94 | /** | ||
95 | * Tries to match a URL with a set of routes. | ||
96 | * | ||
97 | * @param string $pathinfo The path info to be parsed | ||
98 | * @param RouteCollection $routes The set of routes | ||
99 | * | ||
100 | * @return array An array of parameters | ||
101 | * | ||
102 | * @throws ResourceNotFoundException If the resource could not be found | ||
103 | * @throws MethodNotAllowedException If the resource was found but the request method is not allowed | ||
104 | */ | ||
105 | protected function matchCollection($pathinfo, RouteCollection $routes) | ||
106 | { | ||
107 | foreach ($routes as $name => $route) { | ||
108 | $compiledRoute = $route->compile(); | ||
109 | |||
110 | // check the static prefix of the URL first. Only use the more expensive preg_match when it matches | ||
111 | if ('' !== $compiledRoute->getStaticPrefix() && 0 !== strpos($pathinfo, $compiledRoute->getStaticPrefix())) { | ||
112 | continue; | ||
113 | } | ||
114 | |||
115 | if (!preg_match($compiledRoute->getRegex(), $pathinfo, $matches)) { | ||
116 | continue; | ||
117 | } | ||
118 | |||
119 | $hostMatches = array(); | ||
120 | if ($compiledRoute->getHostRegex() && !preg_match($compiledRoute->getHostRegex(), $this->context->getHost(), $hostMatches)) { | ||
121 | continue; | ||
122 | } | ||
123 | |||
124 | // check HTTP method requirement | ||
125 | if ($req = $route->getRequirement('_method')) { | ||
126 | // HEAD and GET are equivalent as per RFC | ||
127 | if ('HEAD' === $method = $this->context->getMethod()) { | ||
128 | $method = 'GET'; | ||
129 | } | ||
130 | |||
131 | if (!in_array($method, $req = explode('|', strtoupper($req)))) { | ||
132 | $this->allow = array_merge($this->allow, $req); | ||
133 | |||
134 | continue; | ||
135 | } | ||
136 | } | ||
137 | |||
138 | $status = $this->handleRouteRequirements($pathinfo, $name, $route); | ||
139 | |||
140 | if (self::ROUTE_MATCH === $status[0]) { | ||
141 | return $status[1]; | ||
142 | } | ||
143 | |||
144 | if (self::REQUIREMENT_MISMATCH === $status[0]) { | ||
145 | continue; | ||
146 | } | ||
147 | |||
148 | return $this->getAttributes($route, $name, array_replace($matches, $hostMatches)); | ||
149 | } | ||
150 | } | ||
151 | |||
152 | /** | ||
153 | * Returns an array of values to use as request attributes. | ||
154 | * | ||
155 | * As this method requires the Route object, it is not available | ||
156 | * in matchers that do not have access to the matched Route instance | ||
157 | * (like the PHP and Apache matcher dumpers). | ||
158 | * | ||
159 | * @param Route $route The route we are matching against | ||
160 | * @param string $name The name of the route | ||
161 | * @param array $attributes An array of attributes from the matcher | ||
162 | * | ||
163 | * @return array An array of parameters | ||
164 | */ | ||
165 | protected function getAttributes(Route $route, $name, array $attributes) | ||
166 | { | ||
167 | $attributes['_route'] = $name; | ||
168 | |||
169 | return $this->mergeDefaults($attributes, $route->getDefaults()); | ||
170 | } | ||
171 | |||
172 | /** | ||
173 | * Handles specific route requirements. | ||
174 | * | ||
175 | * @param string $pathinfo The path | ||
176 | * @param string $name The route name | ||
177 | * @param Route $route The route | ||
178 | * | ||
179 | * @return array The first element represents the status, the second contains additional information | ||
180 | */ | ||
181 | protected function handleRouteRequirements($pathinfo, $name, Route $route) | ||
182 | { | ||
183 | // check HTTP scheme requirement | ||
184 | $scheme = $route->getRequirement('_scheme'); | ||
185 | $status = $scheme && $scheme !== $this->context->getScheme() ? self::REQUIREMENT_MISMATCH : self::REQUIREMENT_MATCH; | ||
186 | |||
187 | return array($status, null); | ||
188 | } | ||
189 | |||
190 | /** | ||
191 | * Get merged default parameters. | ||
192 | * | ||
193 | * @param array $params The parameters | ||
194 | * @param array $defaults The defaults | ||
195 | * | ||
196 | * @return array Merged default parameters | ||
197 | */ | ||
198 | protected function mergeDefaults($params, $defaults) | ||
199 | { | ||
200 | foreach ($params as $key => $value) { | ||
201 | if (!is_int($key)) { | ||
202 | $defaults[$key] = $value; | ||
203 | } | ||
204 | } | ||
205 | |||
206 | return $defaults; | ||
207 | } | ||
208 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Matcher/UrlMatcherInterface.php b/vendor/symfony/routing/Symfony/Component/Routing/Matcher/UrlMatcherInterface.php new file mode 100644 index 00000000..dd718b15 --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Matcher/UrlMatcherInterface.php | |||
@@ -0,0 +1,43 @@ | |||
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\Matcher; | ||
13 | |||
14 | use Symfony\Component\Routing\RequestContextAwareInterface; | ||
15 | use Symfony\Component\Routing\Exception\ResourceNotFoundException; | ||
16 | use Symfony\Component\Routing\Exception\MethodNotAllowedException; | ||
17 | |||
18 | /** | ||
19 | * UrlMatcherInterface is the interface that all URL matcher classes must implement. | ||
20 | * | ||
21 | * @author Fabien Potencier <fabien@symfony.com> | ||
22 | * | ||
23 | * @api | ||
24 | */ | ||
25 | interface UrlMatcherInterface extends RequestContextAwareInterface | ||
26 | { | ||
27 | /** | ||
28 | * Tries to match a URL path with a set of routes. | ||
29 | * | ||
30 | * If the matcher can not find information, it must throw one of the exceptions documented | ||
31 | * below. | ||
32 | * | ||
33 | * @param string $pathinfo The path info to be parsed (raw format, i.e. not urldecoded) | ||
34 | * | ||
35 | * @return array An array of parameters | ||
36 | * | ||
37 | * @throws ResourceNotFoundException If the resource could not be found | ||
38 | * @throws MethodNotAllowedException If the resource was found but the request method is not allowed | ||
39 | * | ||
40 | * @api | ||
41 | */ | ||
42 | public function match($pathinfo); | ||
43 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/README.md b/vendor/symfony/routing/Symfony/Component/Routing/README.md new file mode 100644 index 00000000..663844a6 --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/README.md | |||
@@ -0,0 +1,34 @@ | |||
1 | Routing Component | ||
2 | ================= | ||
3 | |||
4 | Routing associates a request with the code that will convert it to a response. | ||
5 | |||
6 | The example below demonstrates how you can set up a fully working routing | ||
7 | system: | ||
8 | |||
9 | use Symfony\Component\HttpFoundation\Request; | ||
10 | use Symfony\Component\Routing\Matcher\UrlMatcher; | ||
11 | use Symfony\Component\Routing\RequestContext; | ||
12 | use Symfony\Component\Routing\RouteCollection; | ||
13 | use Symfony\Component\Routing\Route; | ||
14 | |||
15 | $routes = new RouteCollection(); | ||
16 | $routes->add('hello', new Route('/hello', array('controller' => 'foo'))); | ||
17 | |||
18 | $context = new RequestContext(); | ||
19 | |||
20 | // this is optional and can be done without a Request instance | ||
21 | $context->fromRequest(Request::createFromGlobals()); | ||
22 | |||
23 | $matcher = new UrlMatcher($routes, $context); | ||
24 | |||
25 | $parameters = $matcher->match('/hello'); | ||
26 | |||
27 | Resources | ||
28 | --------- | ||
29 | |||
30 | You can run the unit tests with the following command: | ||
31 | |||
32 | $ cd path/to/Symfony/Component/Routing/ | ||
33 | $ composer.phar install --dev | ||
34 | $ phpunit | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/RequestContext.php b/vendor/symfony/routing/Symfony/Component/Routing/RequestContext.php new file mode 100644 index 00000000..cb536968 --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/RequestContext.php | |||
@@ -0,0 +1,315 @@ | |||
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\HttpFoundation\Request; | ||
15 | |||
16 | /** | ||
17 | * Holds information about the current request. | ||
18 | * | ||
19 | * @author Fabien Potencier <fabien@symfony.com> | ||
20 | * | ||
21 | * @api | ||
22 | */ | ||
23 | class RequestContext | ||
24 | { | ||
25 | private $baseUrl; | ||
26 | private $pathInfo; | ||
27 | private $method; | ||
28 | private $host; | ||
29 | private $scheme; | ||
30 | private $httpPort; | ||
31 | private $httpsPort; | ||
32 | private $queryString; | ||
33 | |||
34 | /** | ||
35 | * @var array | ||
36 | */ | ||
37 | private $parameters = array(); | ||
38 | |||
39 | /** | ||
40 | * Constructor. | ||
41 | * | ||
42 | * @param string $baseUrl The base URL | ||
43 | * @param string $method The HTTP method | ||
44 | * @param string $host The HTTP host name | ||
45 | * @param string $scheme The HTTP scheme | ||
46 | * @param integer $httpPort The HTTP port | ||
47 | * @param integer $httpsPort The HTTPS port | ||
48 | * @param string $path The path | ||
49 | * @param string $queryString The query string | ||
50 | * | ||
51 | * @api | ||
52 | */ | ||
53 | public function __construct($baseUrl = '', $method = 'GET', $host = 'localhost', $scheme = 'http', $httpPort = 80, $httpsPort = 443, $path = '/', $queryString = '') | ||
54 | { | ||
55 | $this->baseUrl = $baseUrl; | ||
56 | $this->method = strtoupper($method); | ||
57 | $this->host = $host; | ||
58 | $this->scheme = strtolower($scheme); | ||
59 | $this->httpPort = $httpPort; | ||
60 | $this->httpsPort = $httpsPort; | ||
61 | $this->pathInfo = $path; | ||
62 | $this->queryString = $queryString; | ||
63 | } | ||
64 | |||
65 | public function fromRequest(Request $request) | ||
66 | { | ||
67 | $this->setBaseUrl($request->getBaseUrl()); | ||
68 | $this->setPathInfo($request->getPathInfo()); | ||
69 | $this->setMethod($request->getMethod()); | ||
70 | $this->setHost($request->getHost()); | ||
71 | $this->setScheme($request->getScheme()); | ||
72 | $this->setHttpPort($request->isSecure() ? $this->httpPort : $request->getPort()); | ||
73 | $this->setHttpsPort($request->isSecure() ? $request->getPort() : $this->httpsPort); | ||
74 | $this->setQueryString($request->server->get('QUERY_STRING')); | ||
75 | } | ||
76 | |||
77 | /** | ||
78 | * Gets the base URL. | ||
79 | * | ||
80 | * @return string The base URL | ||
81 | */ | ||
82 | public function getBaseUrl() | ||
83 | { | ||
84 | return $this->baseUrl; | ||
85 | } | ||
86 | |||
87 | /** | ||
88 | * Sets the base URL. | ||
89 | * | ||
90 | * @param string $baseUrl The base URL | ||
91 | * | ||
92 | * @api | ||
93 | */ | ||
94 | public function setBaseUrl($baseUrl) | ||
95 | { | ||
96 | $this->baseUrl = $baseUrl; | ||
97 | } | ||
98 | |||
99 | /** | ||
100 | * Gets the path info. | ||
101 | * | ||
102 | * @return string The path info | ||
103 | */ | ||
104 | public function getPathInfo() | ||
105 | { | ||
106 | return $this->pathInfo; | ||
107 | } | ||
108 | |||
109 | /** | ||
110 | * Sets the path info. | ||
111 | * | ||
112 | * @param string $pathInfo The path info | ||
113 | */ | ||
114 | public function setPathInfo($pathInfo) | ||
115 | { | ||
116 | $this->pathInfo = $pathInfo; | ||
117 | } | ||
118 | |||
119 | /** | ||
120 | * Gets the HTTP method. | ||
121 | * | ||
122 | * The method is always an uppercased string. | ||
123 | * | ||
124 | * @return string The HTTP method | ||
125 | */ | ||
126 | public function getMethod() | ||
127 | { | ||
128 | return $this->method; | ||
129 | } | ||
130 | |||
131 | /** | ||
132 | * Sets the HTTP method. | ||
133 | * | ||
134 | * @param string $method The HTTP method | ||
135 | * | ||
136 | * @api | ||
137 | */ | ||
138 | public function setMethod($method) | ||
139 | { | ||
140 | $this->method = strtoupper($method); | ||
141 | } | ||
142 | |||
143 | /** | ||
144 | * Gets the HTTP host. | ||
145 | * | ||
146 | * @return string The HTTP host | ||
147 | */ | ||
148 | public function getHost() | ||
149 | { | ||
150 | return $this->host; | ||
151 | } | ||
152 | |||
153 | /** | ||
154 | * Sets the HTTP host. | ||
155 | * | ||
156 | * @param string $host The HTTP host | ||
157 | * | ||
158 | * @api | ||
159 | */ | ||
160 | public function setHost($host) | ||
161 | { | ||
162 | $this->host = $host; | ||
163 | } | ||
164 | |||
165 | /** | ||
166 | * Gets the HTTP scheme. | ||
167 | * | ||
168 | * @return string The HTTP scheme | ||
169 | */ | ||
170 | public function getScheme() | ||
171 | { | ||
172 | return $this->scheme; | ||
173 | } | ||
174 | |||
175 | /** | ||
176 | * Sets the HTTP scheme. | ||
177 | * | ||
178 | * @param string $scheme The HTTP scheme | ||
179 | * | ||
180 | * @api | ||
181 | */ | ||
182 | public function setScheme($scheme) | ||
183 | { | ||
184 | $this->scheme = strtolower($scheme); | ||
185 | } | ||
186 | |||
187 | /** | ||
188 | * Gets the HTTP port. | ||
189 | * | ||
190 | * @return string The HTTP port | ||
191 | */ | ||
192 | public function getHttpPort() | ||
193 | { | ||
194 | return $this->httpPort; | ||
195 | } | ||
196 | |||
197 | /** | ||
198 | * Sets the HTTP port. | ||
199 | * | ||
200 | * @param string $httpPort The HTTP port | ||
201 | * | ||
202 | * @api | ||
203 | */ | ||
204 | public function setHttpPort($httpPort) | ||
205 | { | ||
206 | $this->httpPort = $httpPort; | ||
207 | } | ||
208 | |||
209 | /** | ||
210 | * Gets the HTTPS port. | ||
211 | * | ||
212 | * @return string The HTTPS port | ||
213 | */ | ||
214 | public function getHttpsPort() | ||
215 | { | ||
216 | return $this->httpsPort; | ||
217 | } | ||
218 | |||
219 | /** | ||
220 | * Sets the HTTPS port. | ||
221 | * | ||
222 | * @param string $httpsPort The HTTPS port | ||
223 | * | ||
224 | * @api | ||
225 | */ | ||
226 | public function setHttpsPort($httpsPort) | ||
227 | { | ||
228 | $this->httpsPort = $httpsPort; | ||
229 | } | ||
230 | |||
231 | /** | ||
232 | * Gets the query string. | ||
233 | * | ||
234 | * @return string The query string | ||
235 | */ | ||
236 | public function getQueryString() | ||
237 | { | ||
238 | return $this->queryString; | ||
239 | } | ||
240 | |||
241 | /** | ||
242 | * Sets the query string. | ||
243 | * | ||
244 | * @param string $queryString The query string | ||
245 | * | ||
246 | * @api | ||
247 | */ | ||
248 | public function setQueryString($queryString) | ||
249 | { | ||
250 | $this->queryString = $queryString; | ||
251 | } | ||
252 | |||
253 | /** | ||
254 | * Returns the parameters. | ||
255 | * | ||
256 | * @return array The parameters | ||
257 | */ | ||
258 | public function getParameters() | ||
259 | { | ||
260 | return $this->parameters; | ||
261 | } | ||
262 | |||
263 | /** | ||
264 | * Sets the parameters. | ||
265 | * | ||
266 | * This method implements a fluent interface. | ||
267 | * | ||
268 | * @param array $parameters The parameters | ||
269 | * | ||
270 | * @return Route The current Route instance | ||
271 | */ | ||
272 | public function setParameters(array $parameters) | ||
273 | { | ||
274 | $this->parameters = $parameters; | ||
275 | |||
276 | return $this; | ||
277 | } | ||
278 | |||
279 | /** | ||
280 | * Gets a parameter value. | ||
281 | * | ||
282 | * @param string $name A parameter name | ||
283 | * | ||
284 | * @return mixed The parameter value | ||
285 | */ | ||
286 | public function getParameter($name) | ||
287 | { | ||
288 | return isset($this->parameters[$name]) ? $this->parameters[$name] : null; | ||
289 | } | ||
290 | |||
291 | /** | ||
292 | * Checks if a parameter value is set for the given parameter. | ||
293 | * | ||
294 | * @param string $name A parameter name | ||
295 | * | ||
296 | * @return Boolean true if the parameter value is set, false otherwise | ||
297 | */ | ||
298 | public function hasParameter($name) | ||
299 | { | ||
300 | return array_key_exists($name, $this->parameters); | ||
301 | } | ||
302 | |||
303 | /** | ||
304 | * Sets a parameter value. | ||
305 | * | ||
306 | * @param string $name A parameter name | ||
307 | * @param mixed $parameter The parameter value | ||
308 | * | ||
309 | * @api | ||
310 | */ | ||
311 | public function setParameter($name, $parameter) | ||
312 | { | ||
313 | $this->parameters[$name] = $parameter; | ||
314 | } | ||
315 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/RequestContextAwareInterface.php b/vendor/symfony/routing/Symfony/Component/Routing/RequestContextAwareInterface.php new file mode 100644 index 00000000..daf52549 --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/RequestContextAwareInterface.php | |||
@@ -0,0 +1,36 @@ | |||
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 | * @api | ||
16 | */ | ||
17 | interface RequestContextAwareInterface | ||
18 | { | ||
19 | /** | ||
20 | * Sets the request context. | ||
21 | * | ||
22 | * @param RequestContext $context The context | ||
23 | * | ||
24 | * @api | ||
25 | */ | ||
26 | public function setContext(RequestContext $context); | ||
27 | |||
28 | /** | ||
29 | * Gets the request context. | ||
30 | * | ||
31 | * @return RequestContext The context | ||
32 | * | ||
33 | * @api | ||
34 | */ | ||
35 | public function getContext(); | ||
36 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Route.php b/vendor/symfony/routing/Symfony/Component/Routing/Route.php new file mode 100644 index 00000000..060e9781 --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Route.php | |||
@@ -0,0 +1,594 @@ | |||
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 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/RouteCollection.php b/vendor/symfony/routing/Symfony/Component/Routing/RouteCollection.php new file mode 100644 index 00000000..499fe0f0 --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/RouteCollection.php | |||
@@ -0,0 +1,271 @@ | |||
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\Resource\ResourceInterface; | ||
15 | |||
16 | /** | ||
17 | * A RouteCollection represents a set of Route instances. | ||
18 | * | ||
19 | * When adding a route at the end of the collection, an existing route | ||
20 | * with the same name is removed first. So there can only be one route | ||
21 | * with a given name. | ||
22 | * | ||
23 | * @author Fabien Potencier <fabien@symfony.com> | ||
24 | * @author Tobias Schultze <http://tobion.de> | ||
25 | * | ||
26 | * @api | ||
27 | */ | ||
28 | class RouteCollection implements \IteratorAggregate, \Countable | ||
29 | { | ||
30 | /** | ||
31 | * @var Route[] | ||
32 | */ | ||
33 | private $routes = array(); | ||
34 | |||
35 | /** | ||
36 | * @var array | ||
37 | */ | ||
38 | private $resources = array(); | ||
39 | |||
40 | public function __clone() | ||
41 | { | ||
42 | foreach ($this->routes as $name => $route) { | ||
43 | $this->routes[$name] = clone $route; | ||
44 | } | ||
45 | } | ||
46 | |||
47 | /** | ||
48 | * Gets the current RouteCollection as an Iterator that includes all routes. | ||
49 | * | ||
50 | * It implements \IteratorAggregate. | ||
51 | * | ||
52 | * @see all() | ||
53 | * | ||
54 | * @return \ArrayIterator An \ArrayIterator object for iterating over routes | ||
55 | */ | ||
56 | public function getIterator() | ||
57 | { | ||
58 | return new \ArrayIterator($this->routes); | ||
59 | } | ||
60 | |||
61 | /** | ||
62 | * Gets the number of Routes in this collection. | ||
63 | * | ||
64 | * @return int The number of routes | ||
65 | */ | ||
66 | public function count() | ||
67 | { | ||
68 | return count($this->routes); | ||
69 | } | ||
70 | |||
71 | /** | ||
72 | * Adds a route. | ||
73 | * | ||
74 | * @param string $name The route name | ||
75 | * @param Route $route A Route instance | ||
76 | * | ||
77 | * @api | ||
78 | */ | ||
79 | public function add($name, Route $route) | ||
80 | { | ||
81 | unset($this->routes[$name]); | ||
82 | |||
83 | $this->routes[$name] = $route; | ||
84 | } | ||
85 | |||
86 | /** | ||
87 | * Returns all routes in this collection. | ||
88 | * | ||
89 | * @return Route[] An array of routes | ||
90 | */ | ||
91 | public function all() | ||
92 | { | ||
93 | return $this->routes; | ||
94 | } | ||
95 | |||
96 | /** | ||
97 | * Gets a route by name. | ||
98 | * | ||
99 | * @param string $name The route name | ||
100 | * | ||
101 | * @return Route|null A Route instance or null when not found | ||
102 | */ | ||
103 | public function get($name) | ||
104 | { | ||
105 | return isset($this->routes[$name]) ? $this->routes[$name] : null; | ||
106 | } | ||
107 | |||
108 | /** | ||
109 | * Removes a route or an array of routes by name from the collection | ||
110 | * | ||
111 | * @param string|array $name The route name or an array of route names | ||
112 | */ | ||
113 | public function remove($name) | ||
114 | { | ||
115 | foreach ((array) $name as $n) { | ||
116 | unset($this->routes[$n]); | ||
117 | } | ||
118 | } | ||
119 | |||
120 | /** | ||
121 | * Adds a route collection at the end of the current set by appending all | ||
122 | * routes of the added collection. | ||
123 | * | ||
124 | * @param RouteCollection $collection A RouteCollection instance | ||
125 | * | ||
126 | * @api | ||
127 | */ | ||
128 | public function addCollection(RouteCollection $collection) | ||
129 | { | ||
130 | // we need to remove all routes with the same names first because just replacing them | ||
131 | // would not place the new route at the end of the merged array | ||
132 | foreach ($collection->all() as $name => $route) { | ||
133 | unset($this->routes[$name]); | ||
134 | $this->routes[$name] = $route; | ||
135 | } | ||
136 | |||
137 | $this->resources = array_merge($this->resources, $collection->getResources()); | ||
138 | } | ||
139 | |||
140 | /** | ||
141 | * Adds a prefix to the path of all child routes. | ||
142 | * | ||
143 | * @param string $prefix An optional prefix to add before each pattern of the route collection | ||
144 | * @param array $defaults An array of default values | ||
145 | * @param array $requirements An array of requirements | ||
146 | * | ||
147 | * @api | ||
148 | */ | ||
149 | public function addPrefix($prefix, array $defaults = array(), array $requirements = array()) | ||
150 | { | ||
151 | $prefix = trim(trim($prefix), '/'); | ||
152 | |||
153 | if ('' === $prefix) { | ||
154 | return; | ||
155 | } | ||
156 | |||
157 | foreach ($this->routes as $route) { | ||
158 | $route->setPath('/'.$prefix.$route->getPath()); | ||
159 | $route->addDefaults($defaults); | ||
160 | $route->addRequirements($requirements); | ||
161 | } | ||
162 | } | ||
163 | |||
164 | /** | ||
165 | * Sets the host pattern on all routes. | ||
166 | * | ||
167 | * @param string $pattern The pattern | ||
168 | * @param array $defaults An array of default values | ||
169 | * @param array $requirements An array of requirements | ||
170 | */ | ||
171 | public function setHost($pattern, array $defaults = array(), array $requirements = array()) | ||
172 | { | ||
173 | foreach ($this->routes as $route) { | ||
174 | $route->setHost($pattern); | ||
175 | $route->addDefaults($defaults); | ||
176 | $route->addRequirements($requirements); | ||
177 | } | ||
178 | } | ||
179 | |||
180 | /** | ||
181 | * Adds defaults to all routes. | ||
182 | * | ||
183 | * An existing default value under the same name in a route will be overridden. | ||
184 | * | ||
185 | * @param array $defaults An array of default values | ||
186 | */ | ||
187 | public function addDefaults(array $defaults) | ||
188 | { | ||
189 | if ($defaults) { | ||
190 | foreach ($this->routes as $route) { | ||
191 | $route->addDefaults($defaults); | ||
192 | } | ||
193 | } | ||
194 | } | ||
195 | |||
196 | /** | ||
197 | * Adds requirements to all routes. | ||
198 | * | ||
199 | * An existing requirement under the same name in a route will be overridden. | ||
200 | * | ||
201 | * @param array $requirements An array of requirements | ||
202 | */ | ||
203 | public function addRequirements(array $requirements) | ||
204 | { | ||
205 | if ($requirements) { | ||
206 | foreach ($this->routes as $route) { | ||
207 | $route->addRequirements($requirements); | ||
208 | } | ||
209 | } | ||
210 | } | ||
211 | |||
212 | /** | ||
213 | * Adds options to all routes. | ||
214 | * | ||
215 | * An existing option value under the same name in a route will be overridden. | ||
216 | * | ||
217 | * @param array $options An array of options | ||
218 | */ | ||
219 | public function addOptions(array $options) | ||
220 | { | ||
221 | if ($options) { | ||
222 | foreach ($this->routes as $route) { | ||
223 | $route->addOptions($options); | ||
224 | } | ||
225 | } | ||
226 | } | ||
227 | |||
228 | /** | ||
229 | * Sets the schemes (e.g. 'https') all child routes are restricted to. | ||
230 | * | ||
231 | * @param string|array $schemes The scheme or an array of schemes | ||
232 | */ | ||
233 | public function setSchemes($schemes) | ||
234 | { | ||
235 | foreach ($this->routes as $route) { | ||
236 | $route->setSchemes($schemes); | ||
237 | } | ||
238 | } | ||
239 | |||
240 | /** | ||
241 | * Sets the HTTP methods (e.g. 'POST') all child routes are restricted to. | ||
242 | * | ||
243 | * @param string|array $methods The method or an array of methods | ||
244 | */ | ||
245 | public function setMethods($methods) | ||
246 | { | ||
247 | foreach ($this->routes as $route) { | ||
248 | $route->setMethods($methods); | ||
249 | } | ||
250 | } | ||
251 | |||
252 | /** | ||
253 | * Returns an array of resources loaded to build this collection. | ||
254 | * | ||
255 | * @return ResourceInterface[] An array of resources | ||
256 | */ | ||
257 | public function getResources() | ||
258 | { | ||
259 | return array_unique($this->resources); | ||
260 | } | ||
261 | |||
262 | /** | ||
263 | * Adds a resource for this collection. | ||
264 | * | ||
265 | * @param ResourceInterface $resource A resource instance | ||
266 | */ | ||
267 | public function addResource(ResourceInterface $resource) | ||
268 | { | ||
269 | $this->resources[] = $resource; | ||
270 | } | ||
271 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/RouteCompiler.php b/vendor/symfony/routing/Symfony/Component/Routing/RouteCompiler.php new file mode 100644 index 00000000..7ced4b3a --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/RouteCompiler.php | |||
@@ -0,0 +1,233 @@ | |||
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 | * RouteCompiler compiles Route instances to CompiledRoute instances. | ||
16 | * | ||
17 | * @author Fabien Potencier <fabien@symfony.com> | ||
18 | * @author Tobias Schultze <http://tobion.de> | ||
19 | */ | ||
20 | class RouteCompiler implements RouteCompilerInterface | ||
21 | { | ||
22 | const REGEX_DELIMITER = '#'; | ||
23 | |||
24 | /** | ||
25 | * This string defines the characters that are automatically considered separators in front of | ||
26 | * optional placeholders (with default and no static text following). Such a single separator | ||
27 | * can be left out together with the optional placeholder from matching and generating URLs. | ||
28 | */ | ||
29 | const SEPARATORS = '/,;.:-_~+*=@|'; | ||
30 | |||
31 | /** | ||
32 | * {@inheritDoc} | ||
33 | * | ||
34 | * @throws \LogicException If a variable is referenced more than once | ||
35 | * @throws \DomainException If a variable name is numeric because PHP raises an error for such | ||
36 | * subpatterns in PCRE and thus would break matching, e.g. "(?P<123>.+)". | ||
37 | */ | ||
38 | public static function compile(Route $route) | ||
39 | { | ||
40 | $staticPrefix = null; | ||
41 | $hostVariables = array(); | ||
42 | $pathVariables = array(); | ||
43 | $variables = array(); | ||
44 | $tokens = array(); | ||
45 | $regex = null; | ||
46 | $hostRegex = null; | ||
47 | $hostTokens = array(); | ||
48 | |||
49 | if ('' !== $host = $route->getHost()) { | ||
50 | $result = self::compilePattern($route, $host, true); | ||
51 | |||
52 | $hostVariables = $result['variables']; | ||
53 | $variables = array_merge($variables, $hostVariables); | ||
54 | |||
55 | $hostTokens = $result['tokens']; | ||
56 | $hostRegex = $result['regex']; | ||
57 | } | ||
58 | |||
59 | $path = $route->getPath(); | ||
60 | |||
61 | $result = self::compilePattern($route, $path, false); | ||
62 | |||
63 | $staticPrefix = $result['staticPrefix']; | ||
64 | |||
65 | $pathVariables = $result['variables']; | ||
66 | $variables = array_merge($variables, $pathVariables); | ||
67 | |||
68 | $tokens = $result['tokens']; | ||
69 | $regex = $result['regex']; | ||
70 | |||
71 | return new CompiledRoute( | ||
72 | $staticPrefix, | ||
73 | $regex, | ||
74 | $tokens, | ||
75 | $pathVariables, | ||
76 | $hostRegex, | ||
77 | $hostTokens, | ||
78 | $hostVariables, | ||
79 | array_unique($variables) | ||
80 | ); | ||
81 | } | ||
82 | |||
83 | private static function compilePattern(Route $route, $pattern, $isHost) | ||
84 | { | ||
85 | $tokens = array(); | ||
86 | $variables = array(); | ||
87 | $matches = array(); | ||
88 | $pos = 0; | ||
89 | $defaultSeparator = $isHost ? '.' : '/'; | ||
90 | |||
91 | // Match all variables enclosed in "{}" and iterate over them. But we only want to match the innermost variable | ||
92 | // in case of nested "{}", e.g. {foo{bar}}. This in ensured because \w does not match "{" or "}" itself. | ||
93 | preg_match_all('#\{\w+\}#', $pattern, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER); | ||
94 | foreach ($matches as $match) { | ||
95 | $varName = substr($match[0][0], 1, -1); | ||
96 | // get all static text preceding the current variable | ||
97 | $precedingText = substr($pattern, $pos, $match[0][1] - $pos); | ||
98 | $pos = $match[0][1] + strlen($match[0][0]); | ||
99 | $precedingChar = strlen($precedingText) > 0 ? substr($precedingText, -1) : ''; | ||
100 | $isSeparator = '' !== $precedingChar && false !== strpos(static::SEPARATORS, $precedingChar); | ||
101 | |||
102 | if (is_numeric($varName)) { | ||
103 | throw new \DomainException(sprintf('Variable name "%s" cannot be numeric in route pattern "%s". Please use a different name.', $varName, $pattern)); | ||
104 | } | ||
105 | if (in_array($varName, $variables)) { | ||
106 | throw new \LogicException(sprintf('Route pattern "%s" cannot reference variable name "%s" more than once.', $pattern, $varName)); | ||
107 | } | ||
108 | |||
109 | if ($isSeparator && strlen($precedingText) > 1) { | ||
110 | $tokens[] = array('text', substr($precedingText, 0, -1)); | ||
111 | } elseif (!$isSeparator && strlen($precedingText) > 0) { | ||
112 | $tokens[] = array('text', $precedingText); | ||
113 | } | ||
114 | |||
115 | $regexp = $route->getRequirement($varName); | ||
116 | if (null === $regexp) { | ||
117 | $followingPattern = (string) substr($pattern, $pos); | ||
118 | // Find the next static character after the variable that functions as a separator. By default, this separator and '/' | ||
119 | // are disallowed for the variable. This default requirement makes sure that optional variables can be matched at all | ||
120 | // and that the generating-matching-combination of URLs unambiguous, i.e. the params used for generating the URL are | ||
121 | // the same that will be matched. Example: new Route('/{page}.{_format}', array('_format' => 'html')) | ||
122 | // If {page} would also match the separating dot, {_format} would never match as {page} will eagerly consume everything. | ||
123 | // Also even if {_format} was not optional the requirement prevents that {page} matches something that was originally | ||
124 | // part of {_format} when generating the URL, e.g. _format = 'mobile.html'. | ||
125 | $nextSeparator = self::findNextSeparator($followingPattern); | ||
126 | $regexp = sprintf( | ||
127 | '[^%s%s]+', | ||
128 | preg_quote($defaultSeparator, self::REGEX_DELIMITER), | ||
129 | $defaultSeparator !== $nextSeparator && '' !== $nextSeparator ? preg_quote($nextSeparator, self::REGEX_DELIMITER) : '' | ||
130 | ); | ||
131 | if (('' !== $nextSeparator && !preg_match('#^\{\w+\}#', $followingPattern)) || '' === $followingPattern) { | ||
132 | // When we have a separator, which is disallowed for the variable, we can optimize the regex with a possessive | ||
133 | // quantifier. This prevents useless backtracking of PCRE and improves performance by 20% for matching those patterns. | ||
134 | // Given the above example, there is no point in backtracking into {page} (that forbids the dot) when a dot must follow | ||
135 | // after it. This optimization cannot be applied when the next char is no real separator or when the next variable is | ||
136 | // directly adjacent, e.g. '/{x}{y}'. | ||
137 | $regexp .= '+'; | ||
138 | } | ||
139 | } | ||
140 | |||
141 | $tokens[] = array('variable', $isSeparator ? $precedingChar : '', $regexp, $varName); | ||
142 | $variables[] = $varName; | ||
143 | } | ||
144 | |||
145 | if ($pos < strlen($pattern)) { | ||
146 | $tokens[] = array('text', substr($pattern, $pos)); | ||
147 | } | ||
148 | |||
149 | // find the first optional token | ||
150 | $firstOptional = PHP_INT_MAX; | ||
151 | if (!$isHost) { | ||
152 | for ($i = count($tokens) - 1; $i >= 0; $i--) { | ||
153 | $token = $tokens[$i]; | ||
154 | if ('variable' === $token[0] && $route->hasDefault($token[3])) { | ||
155 | $firstOptional = $i; | ||
156 | } else { | ||
157 | break; | ||
158 | } | ||
159 | } | ||
160 | } | ||
161 | |||
162 | // compute the matching regexp | ||
163 | $regexp = ''; | ||
164 | for ($i = 0, $nbToken = count($tokens); $i < $nbToken; $i++) { | ||
165 | $regexp .= self::computeRegexp($tokens, $i, $firstOptional); | ||
166 | } | ||
167 | |||
168 | return array( | ||
169 | 'staticPrefix' => 'text' === $tokens[0][0] ? $tokens[0][1] : '', | ||
170 | 'regex' => self::REGEX_DELIMITER.'^'.$regexp.'$'.self::REGEX_DELIMITER.'s', | ||
171 | 'tokens' => array_reverse($tokens), | ||
172 | 'variables' => $variables, | ||
173 | ); | ||
174 | } | ||
175 | |||
176 | /** | ||
177 | * Returns the next static character in the Route pattern that will serve as a separator. | ||
178 | * | ||
179 | * @param string $pattern The route pattern | ||
180 | * | ||
181 | * @return string The next static character that functions as separator (or empty string when none available) | ||
182 | */ | ||
183 | private static function findNextSeparator($pattern) | ||
184 | { | ||
185 | if ('' == $pattern) { | ||
186 | // return empty string if pattern is empty or false (false which can be returned by substr) | ||
187 | return ''; | ||
188 | } | ||
189 | // first remove all placeholders from the pattern so we can find the next real static character | ||
190 | $pattern = preg_replace('#\{\w+\}#', '', $pattern); | ||
191 | |||
192 | return isset($pattern[0]) && false !== strpos(static::SEPARATORS, $pattern[0]) ? $pattern[0] : ''; | ||
193 | } | ||
194 | |||
195 | /** | ||
196 | * Computes the regexp used to match a specific token. It can be static text or a subpattern. | ||
197 | * | ||
198 | * @param array $tokens The route tokens | ||
199 | * @param integer $index The index of the current token | ||
200 | * @param integer $firstOptional The index of the first optional token | ||
201 | * | ||
202 | * @return string The regexp pattern for a single token | ||
203 | */ | ||
204 | private static function computeRegexp(array $tokens, $index, $firstOptional) | ||
205 | { | ||
206 | $token = $tokens[$index]; | ||
207 | if ('text' === $token[0]) { | ||
208 | // Text tokens | ||
209 | return preg_quote($token[1], self::REGEX_DELIMITER); | ||
210 | } else { | ||
211 | // Variable tokens | ||
212 | if (0 === $index && 0 === $firstOptional) { | ||
213 | // When the only token is an optional variable token, the separator is required | ||
214 | return sprintf('%s(?P<%s>%s)?', preg_quote($token[1], self::REGEX_DELIMITER), $token[3], $token[2]); | ||
215 | } else { | ||
216 | $regexp = sprintf('%s(?P<%s>%s)', preg_quote($token[1], self::REGEX_DELIMITER), $token[3], $token[2]); | ||
217 | if ($index >= $firstOptional) { | ||
218 | // Enclose each optional token in a subpattern to make it optional. | ||
219 | // "?:" means it is non-capturing, i.e. the portion of the subject string that | ||
220 | // matched the optional subpattern is not passed back. | ||
221 | $regexp = "(?:$regexp"; | ||
222 | $nbTokens = count($tokens); | ||
223 | if ($nbTokens - 1 == $index) { | ||
224 | // Close the optional subpatterns | ||
225 | $regexp .= str_repeat(")?", $nbTokens - $firstOptional - (0 === $firstOptional ? 1 : 0)); | ||
226 | } | ||
227 | } | ||
228 | |||
229 | return $regexp; | ||
230 | } | ||
231 | } | ||
232 | } | ||
233 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/RouteCompilerInterface.php b/vendor/symfony/routing/Symfony/Component/Routing/RouteCompilerInterface.php new file mode 100644 index 00000000..e6f8ee6d --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/RouteCompilerInterface.php | |||
@@ -0,0 +1,32 @@ | |||
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 | * RouteCompilerInterface is the interface that all RouteCompiler classes must implement. | ||
16 | * | ||
17 | * @author Fabien Potencier <fabien@symfony.com> | ||
18 | */ | ||
19 | interface RouteCompilerInterface | ||
20 | { | ||
21 | /** | ||
22 | * Compiles the current route instance. | ||
23 | * | ||
24 | * @param Route $route A Route instance | ||
25 | * | ||
26 | * @return CompiledRoute A CompiledRoute instance | ||
27 | * | ||
28 | * @throws \LogicException If the Route cannot be compiled because the | ||
29 | * path or host pattern is invalid | ||
30 | */ | ||
31 | public static function compile(Route $route); | ||
32 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Router.php b/vendor/symfony/routing/Symfony/Component/Routing/Router.php new file mode 100644 index 00000000..d1e28979 --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Router.php | |||
@@ -0,0 +1,289 @@ | |||
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\Loader\LoaderInterface; | ||
15 | use Symfony\Component\Config\ConfigCache; | ||
16 | use Psr\Log\LoggerInterface; | ||
17 | use Symfony\Component\Routing\Generator\ConfigurableRequirementsInterface; | ||
18 | use Symfony\Component\Routing\Generator\UrlGeneratorInterface; | ||
19 | use Symfony\Component\Routing\Matcher\UrlMatcherInterface; | ||
20 | |||
21 | /** | ||
22 | * The Router class is an example of the integration of all pieces of the | ||
23 | * routing system for easier use. | ||
24 | * | ||
25 | * @author Fabien Potencier <fabien@symfony.com> | ||
26 | */ | ||
27 | class Router implements RouterInterface | ||
28 | { | ||
29 | /** | ||
30 | * @var UrlMatcherInterface|null | ||
31 | */ | ||
32 | protected $matcher; | ||
33 | |||
34 | /** | ||
35 | * @var UrlGeneratorInterface|null | ||
36 | */ | ||
37 | protected $generator; | ||
38 | |||
39 | /** | ||
40 | * @var RequestContext | ||
41 | */ | ||
42 | protected $context; | ||
43 | |||
44 | /** | ||
45 | * @var LoaderInterface | ||
46 | */ | ||
47 | protected $loader; | ||
48 | |||
49 | /** | ||
50 | * @var RouteCollection|null | ||
51 | */ | ||
52 | protected $collection; | ||
53 | |||
54 | /** | ||
55 | * @var mixed | ||
56 | */ | ||
57 | protected $resource; | ||
58 | |||
59 | /** | ||
60 | * @var array | ||
61 | */ | ||
62 | protected $options = array(); | ||
63 | |||
64 | /** | ||
65 | * @var LoggerInterface|null | ||
66 | */ | ||
67 | protected $logger; | ||
68 | |||
69 | /** | ||
70 | * Constructor. | ||
71 | * | ||
72 | * @param LoaderInterface $loader A LoaderInterface instance | ||
73 | * @param mixed $resource The main resource to load | ||
74 | * @param array $options An array of options | ||
75 | * @param RequestContext $context The context | ||
76 | * @param LoggerInterface $logger A logger instance | ||
77 | */ | ||
78 | public function __construct(LoaderInterface $loader, $resource, array $options = array(), RequestContext $context = null, LoggerInterface $logger = null) | ||
79 | { | ||
80 | $this->loader = $loader; | ||
81 | $this->resource = $resource; | ||
82 | $this->logger = $logger; | ||
83 | $this->context = null === $context ? new RequestContext() : $context; | ||
84 | $this->setOptions($options); | ||
85 | } | ||
86 | |||
87 | /** | ||
88 | * Sets options. | ||
89 | * | ||
90 | * Available options: | ||
91 | * | ||
92 | * * cache_dir: The cache directory (or null to disable caching) | ||
93 | * * debug: Whether to enable debugging or not (false by default) | ||
94 | * * resource_type: Type hint for the main resource (optional) | ||
95 | * | ||
96 | * @param array $options An array of options | ||
97 | * | ||
98 | * @throws \InvalidArgumentException When unsupported option is provided | ||
99 | */ | ||
100 | public function setOptions(array $options) | ||
101 | { | ||
102 | $this->options = array( | ||
103 | 'cache_dir' => null, | ||
104 | 'debug' => false, | ||
105 | 'generator_class' => 'Symfony\\Component\\Routing\\Generator\\UrlGenerator', | ||
106 | 'generator_base_class' => 'Symfony\\Component\\Routing\\Generator\\UrlGenerator', | ||
107 | 'generator_dumper_class' => 'Symfony\\Component\\Routing\\Generator\\Dumper\\PhpGeneratorDumper', | ||
108 | 'generator_cache_class' => 'ProjectUrlGenerator', | ||
109 | 'matcher_class' => 'Symfony\\Component\\Routing\\Matcher\\UrlMatcher', | ||
110 | 'matcher_base_class' => 'Symfony\\Component\\Routing\\Matcher\\UrlMatcher', | ||
111 | 'matcher_dumper_class' => 'Symfony\\Component\\Routing\\Matcher\\Dumper\\PhpMatcherDumper', | ||
112 | 'matcher_cache_class' => 'ProjectUrlMatcher', | ||
113 | 'resource_type' => null, | ||
114 | 'strict_requirements' => true, | ||
115 | ); | ||
116 | |||
117 | // check option names and live merge, if errors are encountered Exception will be thrown | ||
118 | $invalid = array(); | ||
119 | foreach ($options as $key => $value) { | ||
120 | if (array_key_exists($key, $this->options)) { | ||
121 | $this->options[$key] = $value; | ||
122 | } else { | ||
123 | $invalid[] = $key; | ||
124 | } | ||
125 | } | ||
126 | |||
127 | if ($invalid) { | ||
128 | throw new \InvalidArgumentException(sprintf('The Router does not support the following options: "%s".', implode('", "', $invalid))); | ||
129 | } | ||
130 | } | ||
131 | |||
132 | /** | ||
133 | * Sets an option. | ||
134 | * | ||
135 | * @param string $key The key | ||
136 | * @param mixed $value The value | ||
137 | * | ||
138 | * @throws \InvalidArgumentException | ||
139 | */ | ||
140 | public function setOption($key, $value) | ||
141 | { | ||
142 | if (!array_key_exists($key, $this->options)) { | ||
143 | throw new \InvalidArgumentException(sprintf('The Router does not support the "%s" option.', $key)); | ||
144 | } | ||
145 | |||
146 | $this->options[$key] = $value; | ||
147 | } | ||
148 | |||
149 | /** | ||
150 | * Gets an option value. | ||
151 | * | ||
152 | * @param string $key The key | ||
153 | * | ||
154 | * @return mixed The value | ||
155 | * | ||
156 | * @throws \InvalidArgumentException | ||
157 | */ | ||
158 | public function getOption($key) | ||
159 | { | ||
160 | if (!array_key_exists($key, $this->options)) { | ||
161 | throw new \InvalidArgumentException(sprintf('The Router does not support the "%s" option.', $key)); | ||
162 | } | ||
163 | |||
164 | return $this->options[$key]; | ||
165 | } | ||
166 | |||
167 | /** | ||
168 | * {@inheritdoc} | ||
169 | */ | ||
170 | public function getRouteCollection() | ||
171 | { | ||
172 | if (null === $this->collection) { | ||
173 | $this->collection = $this->loader->load($this->resource, $this->options['resource_type']); | ||
174 | } | ||
175 | |||
176 | return $this->collection; | ||
177 | } | ||
178 | |||
179 | /** | ||
180 | * {@inheritdoc} | ||
181 | */ | ||
182 | public function setContext(RequestContext $context) | ||
183 | { | ||
184 | $this->context = $context; | ||
185 | |||
186 | if (null !== $this->matcher) { | ||
187 | $this->getMatcher()->setContext($context); | ||
188 | } | ||
189 | if (null !== $this->generator) { | ||
190 | $this->getGenerator()->setContext($context); | ||
191 | } | ||
192 | } | ||
193 | |||
194 | /** | ||
195 | * {@inheritdoc} | ||
196 | */ | ||
197 | public function getContext() | ||
198 | { | ||
199 | return $this->context; | ||
200 | } | ||
201 | |||
202 | /** | ||
203 | * {@inheritdoc} | ||
204 | */ | ||
205 | public function generate($name, $parameters = array(), $referenceType = self::ABSOLUTE_PATH) | ||
206 | { | ||
207 | return $this->getGenerator()->generate($name, $parameters, $referenceType); | ||
208 | } | ||
209 | |||
210 | /** | ||
211 | * {@inheritdoc} | ||
212 | */ | ||
213 | public function match($pathinfo) | ||
214 | { | ||
215 | return $this->getMatcher()->match($pathinfo); | ||
216 | } | ||
217 | |||
218 | /** | ||
219 | * Gets the UrlMatcher instance associated with this Router. | ||
220 | * | ||
221 | * @return UrlMatcherInterface A UrlMatcherInterface instance | ||
222 | */ | ||
223 | public function getMatcher() | ||
224 | { | ||
225 | if (null !== $this->matcher) { | ||
226 | return $this->matcher; | ||
227 | } | ||
228 | |||
229 | if (null === $this->options['cache_dir'] || null === $this->options['matcher_cache_class']) { | ||
230 | return $this->matcher = new $this->options['matcher_class']($this->getRouteCollection(), $this->context); | ||
231 | } | ||
232 | |||
233 | $class = $this->options['matcher_cache_class']; | ||
234 | $cache = new ConfigCache($this->options['cache_dir'].'/'.$class.'.php', $this->options['debug']); | ||
235 | if (!$cache->isFresh($class)) { | ||
236 | $dumper = new $this->options['matcher_dumper_class']($this->getRouteCollection()); | ||
237 | |||
238 | $options = array( | ||
239 | 'class' => $class, | ||
240 | 'base_class' => $this->options['matcher_base_class'], | ||
241 | ); | ||
242 | |||
243 | $cache->write($dumper->dump($options), $this->getRouteCollection()->getResources()); | ||
244 | } | ||
245 | |||
246 | require_once $cache; | ||
247 | |||
248 | return $this->matcher = new $class($this->context); | ||
249 | } | ||
250 | |||
251 | /** | ||
252 | * Gets the UrlGenerator instance associated with this Router. | ||
253 | * | ||
254 | * @return UrlGeneratorInterface A UrlGeneratorInterface instance | ||
255 | */ | ||
256 | public function getGenerator() | ||
257 | { | ||
258 | if (null !== $this->generator) { | ||
259 | return $this->generator; | ||
260 | } | ||
261 | |||
262 | if (null === $this->options['cache_dir'] || null === $this->options['generator_cache_class']) { | ||
263 | $this->generator = new $this->options['generator_class']($this->getRouteCollection(), $this->context, $this->logger); | ||
264 | } else { | ||
265 | $class = $this->options['generator_cache_class']; | ||
266 | $cache = new ConfigCache($this->options['cache_dir'].'/'.$class.'.php', $this->options['debug']); | ||
267 | if (!$cache->isFresh($class)) { | ||
268 | $dumper = new $this->options['generator_dumper_class']($this->getRouteCollection()); | ||
269 | |||
270 | $options = array( | ||
271 | 'class' => $class, | ||
272 | 'base_class' => $this->options['generator_base_class'], | ||
273 | ); | ||
274 | |||
275 | $cache->write($dumper->dump($options), $this->getRouteCollection()->getResources()); | ||
276 | } | ||
277 | |||
278 | require_once $cache; | ||
279 | |||
280 | $this->generator = new $class($this->context, $this->logger); | ||
281 | } | ||
282 | |||
283 | if ($this->generator instanceof ConfigurableRequirementsInterface) { | ||
284 | $this->generator->setStrictRequirements($this->options['strict_requirements']); | ||
285 | } | ||
286 | |||
287 | return $this->generator; | ||
288 | } | ||
289 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/RouterInterface.php b/vendor/symfony/routing/Symfony/Component/Routing/RouterInterface.php new file mode 100644 index 00000000..a10ae34e --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/RouterInterface.php | |||
@@ -0,0 +1,32 @@ | |||
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\Routing\Generator\UrlGeneratorInterface; | ||
15 | use Symfony\Component\Routing\Matcher\UrlMatcherInterface; | ||
16 | |||
17 | /** | ||
18 | * RouterInterface is the interface that all Router classes must implement. | ||
19 | * | ||
20 | * This interface is the concatenation of UrlMatcherInterface and UrlGeneratorInterface. | ||
21 | * | ||
22 | * @author Fabien Potencier <fabien@symfony.com> | ||
23 | */ | ||
24 | interface RouterInterface extends UrlMatcherInterface, UrlGeneratorInterface | ||
25 | { | ||
26 | /** | ||
27 | * Gets the RouteCollection instance associated with this Router. | ||
28 | * | ||
29 | * @return RouteCollection A RouteCollection instance | ||
30 | */ | ||
31 | public function getRouteCollection(); | ||
32 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Tests/Annotation/RouteTest.php b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Annotation/RouteTest.php new file mode 100644 index 00000000..b58869f7 --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Annotation/RouteTest.php | |||
@@ -0,0 +1,49 @@ | |||
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\Tests\Annotation; | ||
13 | |||
14 | use Symfony\Component\Routing\Annotation\Route; | ||
15 | |||
16 | class RouteTest extends \PHPUnit_Framework_TestCase | ||
17 | { | ||
18 | /** | ||
19 | * @expectedException \BadMethodCallException | ||
20 | */ | ||
21 | public function testInvalidRouteParameter() | ||
22 | { | ||
23 | $route = new Route(array('foo' => 'bar')); | ||
24 | } | ||
25 | |||
26 | /** | ||
27 | * @dataProvider getValidParameters | ||
28 | */ | ||
29 | public function testRouteParameters($parameter, $value, $getter) | ||
30 | { | ||
31 | $route = new Route(array($parameter => $value)); | ||
32 | $this->assertEquals($route->$getter(), $value); | ||
33 | } | ||
34 | |||
35 | public function getValidParameters() | ||
36 | { | ||
37 | return array( | ||
38 | array('value', '/Blog', 'getPattern'), | ||
39 | array('value', '/Blog', 'getPath'), | ||
40 | array('requirements', array('_method' => 'GET'), 'getRequirements'), | ||
41 | array('options', array('compiler_class' => 'RouteCompiler'), 'getOptions'), | ||
42 | array('name', 'blog_index', 'getName'), | ||
43 | array('defaults', array('_controller' => 'MyBlogBundle:Blog:index'), 'getDefaults'), | ||
44 | array('schemes', array('https'), 'getSchemes'), | ||
45 | array('methods', array('GET', 'POST'), 'getMethods'), | ||
46 | array('host', array('{locale}.example.com'), 'getHost') | ||
47 | ); | ||
48 | } | ||
49 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Tests/CompiledRouteTest.php b/vendor/symfony/routing/Symfony/Component/Routing/Tests/CompiledRouteTest.php new file mode 100644 index 00000000..215ebb70 --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Tests/CompiledRouteTest.php | |||
@@ -0,0 +1,26 @@ | |||
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\Tests; | ||
13 | |||
14 | use Symfony\Component\Routing\CompiledRoute; | ||
15 | |||
16 | class CompiledRouteTest extends \PHPUnit_Framework_TestCase | ||
17 | { | ||
18 | public function testAccessors() | ||
19 | { | ||
20 | $compiled = new CompiledRoute('prefix', 'regex', array('tokens'), array(), array(), array(), array(), array('variables')); | ||
21 | $this->assertEquals('prefix', $compiled->getStaticPrefix(), '__construct() takes a static prefix as its second argument'); | ||
22 | $this->assertEquals('regex', $compiled->getRegex(), '__construct() takes a regexp as its third argument'); | ||
23 | $this->assertEquals(array('tokens'), $compiled->getTokens(), '__construct() takes an array of tokens as its fourth argument'); | ||
24 | $this->assertEquals(array('variables'), $compiled->getVariables(), '__construct() takes an array of variables as its ninth argument'); | ||
25 | } | ||
26 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/AnnotatedClasses/AbstractClass.php b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/AnnotatedClasses/AbstractClass.php new file mode 100644 index 00000000..56bcab2a --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/AnnotatedClasses/AbstractClass.php | |||
@@ -0,0 +1,16 @@ | |||
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\Tests\Fixtures\AnnotatedClasses; | ||
13 | |||
14 | abstract class AbstractClass | ||
15 | { | ||
16 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/AnnotatedClasses/BarClass.php b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/AnnotatedClasses/BarClass.php new file mode 100644 index 00000000..a3882773 --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/AnnotatedClasses/BarClass.php | |||
@@ -0,0 +1,19 @@ | |||
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\Tests\Fixtures\AnnotatedClasses; | ||
13 | |||
14 | class BarClass | ||
15 | { | ||
16 | public function routeAction($arg1, $arg2 = 'defaultValue2', $arg3 = 'defaultValue3') | ||
17 | { | ||
18 | } | ||
19 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/AnnotatedClasses/FooClass.php b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/AnnotatedClasses/FooClass.php new file mode 100644 index 00000000..320dc350 --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/AnnotatedClasses/FooClass.php | |||
@@ -0,0 +1,16 @@ | |||
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\Tests\Fixtures\AnnotatedClasses; | ||
13 | |||
14 | class FooClass | ||
15 | { | ||
16 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/CustomXmlFileLoader.php b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/CustomXmlFileLoader.php new file mode 100644 index 00000000..12a5bedb --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/CustomXmlFileLoader.php | |||
@@ -0,0 +1,26 @@ | |||
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\Tests\Fixtures; | ||
13 | |||
14 | use Symfony\Component\Routing\Loader\XmlFileLoader; | ||
15 | use Symfony\Component\Config\Util\XmlUtils; | ||
16 | |||
17 | /** | ||
18 | * XmlFileLoader with schema validation turned off | ||
19 | */ | ||
20 | class CustomXmlFileLoader extends XmlFileLoader | ||
21 | { | ||
22 | protected function loadFile($file) | ||
23 | { | ||
24 | return XmlUtils::loadFile($file, function() { return true; }); | ||
25 | } | ||
26 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/RedirectableUrlMatcher.php b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/RedirectableUrlMatcher.php new file mode 100644 index 00000000..e95c1f26 --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/RedirectableUrlMatcher.php | |||
@@ -0,0 +1,30 @@ | |||
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\Tests\Fixtures; | ||
13 | |||
14 | use Symfony\Component\Routing\Matcher\UrlMatcher; | ||
15 | use Symfony\Component\Routing\Matcher\RedirectableUrlMatcherInterface; | ||
16 | |||
17 | /** | ||
18 | * @author Fabien Potencier <fabien@symfony.com> | ||
19 | */ | ||
20 | class RedirectableUrlMatcher extends UrlMatcher implements RedirectableUrlMatcherInterface | ||
21 | { | ||
22 | public function redirect($path, $route, $scheme = null) | ||
23 | { | ||
24 | return array( | ||
25 | '_controller' => 'Some controller reference...', | ||
26 | 'path' => $path, | ||
27 | 'scheme' => $scheme, | ||
28 | ); | ||
29 | } | ||
30 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/annotated.php b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/annotated.php new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/annotated.php | |||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher1.apache b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher1.apache new file mode 100644 index 00000000..26a561cc --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher1.apache | |||
@@ -0,0 +1,163 @@ | |||
1 | # skip "real" requests | ||
2 | RewriteCond %{REQUEST_FILENAME} -f | ||
3 | RewriteRule .* - [QSA,L] | ||
4 | |||
5 | # foo | ||
6 | RewriteCond %{REQUEST_URI} ^/foo/(baz|symfony)$ | ||
7 | RewriteRule .* app.php [QSA,L,E=_ROUTING_route:foo,E=_ROUTING_param_bar:%1,E=_ROUTING_default_def:test] | ||
8 | |||
9 | # foobar | ||
10 | RewriteCond %{REQUEST_URI} ^/foo(?:/([^/]++))?$ | ||
11 | RewriteRule .* app.php [QSA,L,E=_ROUTING_route:foobar,E=_ROUTING_param_bar:%1,E=_ROUTING_default_bar:toto] | ||
12 | |||
13 | # bar | ||
14 | RewriteCond %{REQUEST_URI} ^/bar/([^/]++)$ | ||
15 | RewriteCond %{REQUEST_METHOD} !^(GET|HEAD)$ [NC] | ||
16 | RewriteRule .* - [S=1,E=_ROUTING_allow_GET:1,E=_ROUTING_allow_HEAD:1] | ||
17 | RewriteCond %{REQUEST_URI} ^/bar/([^/]++)$ | ||
18 | RewriteRule .* app.php [QSA,L,E=_ROUTING_route:bar,E=_ROUTING_param_foo:%1] | ||
19 | |||
20 | # baragain | ||
21 | RewriteCond %{REQUEST_URI} ^/baragain/([^/]++)$ | ||
22 | RewriteCond %{REQUEST_METHOD} !^(GET|POST|HEAD)$ [NC] | ||
23 | RewriteRule .* - [S=1,E=_ROUTING_allow_GET:1,E=_ROUTING_allow_POST:1,E=_ROUTING_allow_HEAD:1] | ||
24 | RewriteCond %{REQUEST_URI} ^/baragain/([^/]++)$ | ||
25 | RewriteRule .* app.php [QSA,L,E=_ROUTING_route:baragain,E=_ROUTING_param_foo:%1] | ||
26 | |||
27 | # baz | ||
28 | RewriteCond %{REQUEST_URI} ^/test/baz$ | ||
29 | RewriteRule .* app.php [QSA,L,E=_ROUTING_route:baz] | ||
30 | |||
31 | # baz2 | ||
32 | RewriteCond %{REQUEST_URI} ^/test/baz\.html$ | ||
33 | RewriteRule .* app.php [QSA,L,E=_ROUTING_route:baz2] | ||
34 | |||
35 | # baz3 | ||
36 | RewriteCond %{REQUEST_URI} ^/test/baz3$ | ||
37 | RewriteRule .* $0/ [QSA,L,R=301] | ||
38 | RewriteCond %{REQUEST_URI} ^/test/baz3/$ | ||
39 | RewriteRule .* app.php [QSA,L,E=_ROUTING_route:baz3] | ||
40 | |||
41 | # baz4 | ||
42 | RewriteCond %{REQUEST_URI} ^/test/([^/]++)$ | ||
43 | RewriteRule .* $0/ [QSA,L,R=301] | ||
44 | RewriteCond %{REQUEST_URI} ^/test/([^/]++)/$ | ||
45 | RewriteRule .* app.php [QSA,L,E=_ROUTING_route:baz4,E=_ROUTING_param_foo:%1] | ||
46 | |||
47 | # baz5 | ||
48 | RewriteCond %{REQUEST_URI} ^/test/([^/]++)/$ | ||
49 | RewriteCond %{REQUEST_METHOD} !^(GET|HEAD)$ [NC] | ||
50 | RewriteRule .* - [S=2,E=_ROUTING_allow_GET:1,E=_ROUTING_allow_HEAD:1] | ||
51 | RewriteCond %{REQUEST_URI} ^/test/([^/]++)$ | ||
52 | RewriteRule .* $0/ [QSA,L,R=301] | ||
53 | RewriteCond %{REQUEST_URI} ^/test/([^/]++)/$ | ||
54 | RewriteRule .* app.php [QSA,L,E=_ROUTING_route:baz5,E=_ROUTING_param_foo:%1] | ||
55 | |||
56 | # baz5unsafe | ||
57 | RewriteCond %{REQUEST_URI} ^/testunsafe/([^/]++)/$ | ||
58 | RewriteCond %{REQUEST_METHOD} !^(POST)$ [NC] | ||
59 | RewriteRule .* - [S=1,E=_ROUTING_allow_POST:1] | ||
60 | RewriteCond %{REQUEST_URI} ^/testunsafe/([^/]++)/$ | ||
61 | RewriteRule .* app.php [QSA,L,E=_ROUTING_route:baz5unsafe,E=_ROUTING_param_foo:%1] | ||
62 | |||
63 | # baz6 | ||
64 | RewriteCond %{REQUEST_URI} ^/test/baz$ | ||
65 | RewriteRule .* app.php [QSA,L,E=_ROUTING_route:baz6,E=_ROUTING_default_foo:bar\ baz] | ||
66 | |||
67 | # baz7 | ||
68 | RewriteCond %{REQUEST_URI} ^/te\ st/baz$ | ||
69 | RewriteRule .* app.php [QSA,L,E=_ROUTING_route:baz7] | ||
70 | |||
71 | # baz8 | ||
72 | RewriteCond %{REQUEST_URI} ^/te\\\ st/baz$ | ||
73 | RewriteRule .* app.php [QSA,L,E=_ROUTING_route:baz8] | ||
74 | |||
75 | # baz9 | ||
76 | RewriteCond %{REQUEST_URI} ^/test/(te\\\ st)$ | ||
77 | RewriteRule .* app.php [QSA,L,E=_ROUTING_route:baz9,E=_ROUTING_param_baz:%1] | ||
78 | |||
79 | RewriteCond %{HTTP:Host} ^a\.example\.com$ | ||
80 | RewriteRule .? - [E=__ROUTING_host_1:1] | ||
81 | |||
82 | # route1 | ||
83 | RewriteCond %{ENV:__ROUTING_host_1} =1 | ||
84 | RewriteCond %{REQUEST_URI} ^/route1$ | ||
85 | RewriteRule .* app.php [QSA,L,E=_ROUTING_route:route1] | ||
86 | |||
87 | # route2 | ||
88 | RewriteCond %{ENV:__ROUTING_host_1} =1 | ||
89 | RewriteCond %{REQUEST_URI} ^/c2/route2$ | ||
90 | RewriteRule .* app.php [QSA,L,E=_ROUTING_route:route2] | ||
91 | |||
92 | RewriteCond %{HTTP:Host} ^b\.example\.com$ | ||
93 | RewriteRule .? - [E=__ROUTING_host_2:1] | ||
94 | |||
95 | # route3 | ||
96 | RewriteCond %{ENV:__ROUTING_host_2} =1 | ||
97 | RewriteCond %{REQUEST_URI} ^/c2/route3$ | ||
98 | RewriteRule .* app.php [QSA,L,E=_ROUTING_route:route3] | ||
99 | |||
100 | RewriteCond %{HTTP:Host} ^a\.example\.com$ | ||
101 | RewriteRule .? - [E=__ROUTING_host_3:1] | ||
102 | |||
103 | # route4 | ||
104 | RewriteCond %{ENV:__ROUTING_host_3} =1 | ||
105 | RewriteCond %{REQUEST_URI} ^/route4$ | ||
106 | RewriteRule .* app.php [QSA,L,E=_ROUTING_route:route4] | ||
107 | |||
108 | RewriteCond %{HTTP:Host} ^c\.example\.com$ | ||
109 | RewriteRule .? - [E=__ROUTING_host_4:1] | ||
110 | |||
111 | # route5 | ||
112 | RewriteCond %{ENV:__ROUTING_host_4} =1 | ||
113 | RewriteCond %{REQUEST_URI} ^/route5$ | ||
114 | RewriteRule .* app.php [QSA,L,E=_ROUTING_route:route5] | ||
115 | |||
116 | # route6 | ||
117 | RewriteCond %{REQUEST_URI} ^/route6$ | ||
118 | RewriteRule .* app.php [QSA,L,E=_ROUTING_route:route6] | ||
119 | |||
120 | RewriteCond %{HTTP:Host} ^([^\.]++)\.example\.com$ | ||
121 | RewriteRule .? - [E=__ROUTING_host_5:1,E=__ROUTING_host_5_var1:%1] | ||
122 | |||
123 | # route11 | ||
124 | RewriteCond %{ENV:__ROUTING_host_5} =1 | ||
125 | RewriteCond %{REQUEST_URI} ^/route11$ | ||
126 | RewriteRule .* app.php [QSA,L,E=_ROUTING_route:route11,E=_ROUTING_param_var1:%{ENV:__ROUTING_host_5_var1}] | ||
127 | |||
128 | # route12 | ||
129 | RewriteCond %{ENV:__ROUTING_host_5} =1 | ||
130 | RewriteCond %{REQUEST_URI} ^/route12$ | ||
131 | RewriteRule .* app.php [QSA,L,E=_ROUTING_route:route12,E=_ROUTING_param_var1:%{ENV:__ROUTING_host_5_var1},E=_ROUTING_default_var1:val] | ||
132 | |||
133 | # route13 | ||
134 | RewriteCond %{ENV:__ROUTING_host_5} =1 | ||
135 | RewriteCond %{REQUEST_URI} ^/route13/([^/]++)$ | ||
136 | RewriteRule .* app.php [QSA,L,E=_ROUTING_route:route13,E=_ROUTING_param_var1:%{ENV:__ROUTING_host_5_var1},E=_ROUTING_param_name:%1] | ||
137 | |||
138 | # route14 | ||
139 | RewriteCond %{ENV:__ROUTING_host_5} =1 | ||
140 | RewriteCond %{REQUEST_URI} ^/route14/([^/]++)$ | ||
141 | RewriteRule .* app.php [QSA,L,E=_ROUTING_route:route14,E=_ROUTING_param_var1:%{ENV:__ROUTING_host_5_var1},E=_ROUTING_param_name:%1,E=_ROUTING_default_var1:val] | ||
142 | |||
143 | RewriteCond %{HTTP:Host} ^c\.example\.com$ | ||
144 | RewriteRule .? - [E=__ROUTING_host_6:1] | ||
145 | |||
146 | # route15 | ||
147 | RewriteCond %{ENV:__ROUTING_host_6} =1 | ||
148 | RewriteCond %{REQUEST_URI} ^/route15/([^/]++)$ | ||
149 | RewriteRule .* app.php [QSA,L,E=_ROUTING_route:route15,E=_ROUTING_param_name:%1] | ||
150 | |||
151 | # route16 | ||
152 | RewriteCond %{REQUEST_URI} ^/route16/([^/]++)$ | ||
153 | RewriteRule .* app.php [QSA,L,E=_ROUTING_route:route16,E=_ROUTING_param_name:%1,E=_ROUTING_default_var1:val] | ||
154 | |||
155 | # route17 | ||
156 | RewriteCond %{REQUEST_URI} ^/route17$ | ||
157 | RewriteRule .* app.php [QSA,L,E=_ROUTING_route:route17] | ||
158 | |||
159 | # 405 Method Not Allowed | ||
160 | RewriteCond %{ENV:_ROUTING__allow_GET} =1 [OR] | ||
161 | RewriteCond %{ENV:_ROUTING__allow_HEAD} =1 [OR] | ||
162 | RewriteCond %{ENV:_ROUTING__allow_POST} =1 | ||
163 | RewriteRule .* app.php [QSA,L] | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher1.php b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher1.php new file mode 100644 index 00000000..e5f7665c --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher1.php | |||
@@ -0,0 +1,310 @@ | |||
1 | <?php | ||
2 | |||
3 | use Symfony\Component\Routing\Exception\MethodNotAllowedException; | ||
4 | use Symfony\Component\Routing\Exception\ResourceNotFoundException; | ||
5 | use Symfony\Component\Routing\RequestContext; | ||
6 | |||
7 | /** | ||
8 | * ProjectUrlMatcher | ||
9 | * | ||
10 | * This class has been auto-generated | ||
11 | * by the Symfony Routing Component. | ||
12 | */ | ||
13 | class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher | ||
14 | { | ||
15 | /** | ||
16 | * Constructor. | ||
17 | */ | ||
18 | public function __construct(RequestContext $context) | ||
19 | { | ||
20 | $this->context = $context; | ||
21 | } | ||
22 | |||
23 | public function match($pathinfo) | ||
24 | { | ||
25 | $allow = array(); | ||
26 | $pathinfo = rawurldecode($pathinfo); | ||
27 | |||
28 | // foo | ||
29 | if (0 === strpos($pathinfo, '/foo') && preg_match('#^/foo/(?P<bar>baz|symfony)$#s', $pathinfo, $matches)) { | ||
30 | return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo')), array ( 'def' => 'test',)); | ||
31 | } | ||
32 | |||
33 | if (0 === strpos($pathinfo, '/bar')) { | ||
34 | // bar | ||
35 | if (preg_match('#^/bar/(?P<foo>[^/]++)$#s', $pathinfo, $matches)) { | ||
36 | if (!in_array($this->context->getMethod(), array('GET', 'HEAD'))) { | ||
37 | $allow = array_merge($allow, array('GET', 'HEAD')); | ||
38 | goto not_bar; | ||
39 | } | ||
40 | |||
41 | return $this->mergeDefaults(array_replace($matches, array('_route' => 'bar')), array ()); | ||
42 | } | ||
43 | not_bar: | ||
44 | |||
45 | // barhead | ||
46 | if (0 === strpos($pathinfo, '/barhead') && preg_match('#^/barhead/(?P<foo>[^/]++)$#s', $pathinfo, $matches)) { | ||
47 | if (!in_array($this->context->getMethod(), array('GET', 'HEAD'))) { | ||
48 | $allow = array_merge($allow, array('GET', 'HEAD')); | ||
49 | goto not_barhead; | ||
50 | } | ||
51 | |||
52 | return $this->mergeDefaults(array_replace($matches, array('_route' => 'barhead')), array ()); | ||
53 | } | ||
54 | not_barhead: | ||
55 | |||
56 | } | ||
57 | |||
58 | if (0 === strpos($pathinfo, '/test')) { | ||
59 | if (0 === strpos($pathinfo, '/test/baz')) { | ||
60 | // baz | ||
61 | if ($pathinfo === '/test/baz') { | ||
62 | return array('_route' => 'baz'); | ||
63 | } | ||
64 | |||
65 | // baz2 | ||
66 | if ($pathinfo === '/test/baz.html') { | ||
67 | return array('_route' => 'baz2'); | ||
68 | } | ||
69 | |||
70 | // baz3 | ||
71 | if ($pathinfo === '/test/baz3/') { | ||
72 | return array('_route' => 'baz3'); | ||
73 | } | ||
74 | |||
75 | } | ||
76 | |||
77 | // baz4 | ||
78 | if (preg_match('#^/test/(?P<foo>[^/]++)/$#s', $pathinfo, $matches)) { | ||
79 | return $this->mergeDefaults(array_replace($matches, array('_route' => 'baz4')), array ()); | ||
80 | } | ||
81 | |||
82 | // baz5 | ||
83 | if (preg_match('#^/test/(?P<foo>[^/]++)/$#s', $pathinfo, $matches)) { | ||
84 | if ($this->context->getMethod() != 'POST') { | ||
85 | $allow[] = 'POST'; | ||
86 | goto not_baz5; | ||
87 | } | ||
88 | |||
89 | return $this->mergeDefaults(array_replace($matches, array('_route' => 'baz5')), array ()); | ||
90 | } | ||
91 | not_baz5: | ||
92 | |||
93 | // baz.baz6 | ||
94 | if (preg_match('#^/test/(?P<foo>[^/]++)/$#s', $pathinfo, $matches)) { | ||
95 | if ($this->context->getMethod() != 'PUT') { | ||
96 | $allow[] = 'PUT'; | ||
97 | goto not_bazbaz6; | ||
98 | } | ||
99 | |||
100 | return $this->mergeDefaults(array_replace($matches, array('_route' => 'baz.baz6')), array ()); | ||
101 | } | ||
102 | not_bazbaz6: | ||
103 | |||
104 | } | ||
105 | |||
106 | // foofoo | ||
107 | if ($pathinfo === '/foofoo') { | ||
108 | return array ( 'def' => 'test', '_route' => 'foofoo',); | ||
109 | } | ||
110 | |||
111 | // quoter | ||
112 | if (preg_match('#^/(?P<quoter>[\']+)$#s', $pathinfo, $matches)) { | ||
113 | return $this->mergeDefaults(array_replace($matches, array('_route' => 'quoter')), array ()); | ||
114 | } | ||
115 | |||
116 | // space | ||
117 | if ($pathinfo === '/spa ce') { | ||
118 | return array('_route' => 'space'); | ||
119 | } | ||
120 | |||
121 | if (0 === strpos($pathinfo, '/a')) { | ||
122 | if (0 === strpos($pathinfo, '/a/b\'b')) { | ||
123 | // foo1 | ||
124 | if (preg_match('#^/a/b\'b/(?P<foo>[^/]++)$#s', $pathinfo, $matches)) { | ||
125 | return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo1')), array ()); | ||
126 | } | ||
127 | |||
128 | // bar1 | ||
129 | if (preg_match('#^/a/b\'b/(?P<bar>[^/]++)$#s', $pathinfo, $matches)) { | ||
130 | return $this->mergeDefaults(array_replace($matches, array('_route' => 'bar1')), array ()); | ||
131 | } | ||
132 | |||
133 | } | ||
134 | |||
135 | // overridden | ||
136 | if (preg_match('#^/a/(?P<var>.*)$#s', $pathinfo, $matches)) { | ||
137 | return $this->mergeDefaults(array_replace($matches, array('_route' => 'overridden')), array ()); | ||
138 | } | ||
139 | |||
140 | if (0 === strpos($pathinfo, '/a/b\'b')) { | ||
141 | // foo2 | ||
142 | if (preg_match('#^/a/b\'b/(?P<foo1>[^/]++)$#s', $pathinfo, $matches)) { | ||
143 | return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo2')), array ()); | ||
144 | } | ||
145 | |||
146 | // bar2 | ||
147 | if (preg_match('#^/a/b\'b/(?P<bar1>[^/]++)$#s', $pathinfo, $matches)) { | ||
148 | return $this->mergeDefaults(array_replace($matches, array('_route' => 'bar2')), array ()); | ||
149 | } | ||
150 | |||
151 | } | ||
152 | |||
153 | } | ||
154 | |||
155 | if (0 === strpos($pathinfo, '/multi')) { | ||
156 | // helloWorld | ||
157 | if (0 === strpos($pathinfo, '/multi/hello') && preg_match('#^/multi/hello(?:/(?P<who>[^/]++))?$#s', $pathinfo, $matches)) { | ||
158 | return $this->mergeDefaults(array_replace($matches, array('_route' => 'helloWorld')), array ( 'who' => 'World!',)); | ||
159 | } | ||
160 | |||
161 | // overridden2 | ||
162 | if ($pathinfo === '/multi/new') { | ||
163 | return array('_route' => 'overridden2'); | ||
164 | } | ||
165 | |||
166 | // hey | ||
167 | if ($pathinfo === '/multi/hey/') { | ||
168 | return array('_route' => 'hey'); | ||
169 | } | ||
170 | |||
171 | } | ||
172 | |||
173 | // foo3 | ||
174 | if (preg_match('#^/(?P<_locale>[^/]++)/b/(?P<foo>[^/]++)$#s', $pathinfo, $matches)) { | ||
175 | return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo3')), array ()); | ||
176 | } | ||
177 | |||
178 | // bar3 | ||
179 | if (preg_match('#^/(?P<_locale>[^/]++)/b/(?P<bar>[^/]++)$#s', $pathinfo, $matches)) { | ||
180 | return $this->mergeDefaults(array_replace($matches, array('_route' => 'bar3')), array ()); | ||
181 | } | ||
182 | |||
183 | if (0 === strpos($pathinfo, '/aba')) { | ||
184 | // ababa | ||
185 | if ($pathinfo === '/ababa') { | ||
186 | return array('_route' => 'ababa'); | ||
187 | } | ||
188 | |||
189 | // foo4 | ||
190 | if (preg_match('#^/aba/(?P<foo>[^/]++)$#s', $pathinfo, $matches)) { | ||
191 | return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo4')), array ()); | ||
192 | } | ||
193 | |||
194 | } | ||
195 | |||
196 | $host = $this->context->getHost(); | ||
197 | |||
198 | if (preg_match('#^a\\.example\\.com$#s', $host, $hostMatches)) { | ||
199 | // route1 | ||
200 | if ($pathinfo === '/route1') { | ||
201 | return array('_route' => 'route1'); | ||
202 | } | ||
203 | |||
204 | // route2 | ||
205 | if ($pathinfo === '/c2/route2') { | ||
206 | return array('_route' => 'route2'); | ||
207 | } | ||
208 | |||
209 | } | ||
210 | |||
211 | if (preg_match('#^b\\.example\\.com$#s', $host, $hostMatches)) { | ||
212 | // route3 | ||
213 | if ($pathinfo === '/c2/route3') { | ||
214 | return array('_route' => 'route3'); | ||
215 | } | ||
216 | |||
217 | } | ||
218 | |||
219 | if (preg_match('#^a\\.example\\.com$#s', $host, $hostMatches)) { | ||
220 | // route4 | ||
221 | if ($pathinfo === '/route4') { | ||
222 | return array('_route' => 'route4'); | ||
223 | } | ||
224 | |||
225 | } | ||
226 | |||
227 | if (preg_match('#^c\\.example\\.com$#s', $host, $hostMatches)) { | ||
228 | // route5 | ||
229 | if ($pathinfo === '/route5') { | ||
230 | return array('_route' => 'route5'); | ||
231 | } | ||
232 | |||
233 | } | ||
234 | |||
235 | // route6 | ||
236 | if ($pathinfo === '/route6') { | ||
237 | return array('_route' => 'route6'); | ||
238 | } | ||
239 | |||
240 | if (preg_match('#^(?P<var1>[^\\.]++)\\.example\\.com$#s', $host, $hostMatches)) { | ||
241 | if (0 === strpos($pathinfo, '/route1')) { | ||
242 | // route11 | ||
243 | if ($pathinfo === '/route11') { | ||
244 | return $this->mergeDefaults(array_replace($hostMatches, array('_route' => 'route11')), array ()); | ||
245 | } | ||
246 | |||
247 | // route12 | ||
248 | if ($pathinfo === '/route12') { | ||
249 | return $this->mergeDefaults(array_replace($hostMatches, array('_route' => 'route12')), array ( 'var1' => 'val',)); | ||
250 | } | ||
251 | |||
252 | // route13 | ||
253 | if (0 === strpos($pathinfo, '/route13') && preg_match('#^/route13/(?P<name>[^/]++)$#s', $pathinfo, $matches)) { | ||
254 | return $this->mergeDefaults(array_replace($hostMatches, $matches, array('_route' => 'route13')), array ()); | ||
255 | } | ||
256 | |||
257 | // route14 | ||
258 | if (0 === strpos($pathinfo, '/route14') && preg_match('#^/route14/(?P<name>[^/]++)$#s', $pathinfo, $matches)) { | ||
259 | return $this->mergeDefaults(array_replace($hostMatches, $matches, array('_route' => 'route14')), array ( 'var1' => 'val',)); | ||
260 | } | ||
261 | |||
262 | } | ||
263 | |||
264 | } | ||
265 | |||
266 | if (preg_match('#^c\\.example\\.com$#s', $host, $hostMatches)) { | ||
267 | // route15 | ||
268 | if (0 === strpos($pathinfo, '/route15') && preg_match('#^/route15/(?P<name>[^/]++)$#s', $pathinfo, $matches)) { | ||
269 | return $this->mergeDefaults(array_replace($matches, array('_route' => 'route15')), array ()); | ||
270 | } | ||
271 | |||
272 | } | ||
273 | |||
274 | if (0 === strpos($pathinfo, '/route1')) { | ||
275 | // route16 | ||
276 | if (0 === strpos($pathinfo, '/route16') && preg_match('#^/route16/(?P<name>[^/]++)$#s', $pathinfo, $matches)) { | ||
277 | return $this->mergeDefaults(array_replace($matches, array('_route' => 'route16')), array ( 'var1' => 'val',)); | ||
278 | } | ||
279 | |||
280 | // route17 | ||
281 | if ($pathinfo === '/route17') { | ||
282 | return array('_route' => 'route17'); | ||
283 | } | ||
284 | |||
285 | } | ||
286 | |||
287 | if (0 === strpos($pathinfo, '/a')) { | ||
288 | // a | ||
289 | if ($pathinfo === '/a/a...') { | ||
290 | return array('_route' => 'a'); | ||
291 | } | ||
292 | |||
293 | if (0 === strpos($pathinfo, '/a/b')) { | ||
294 | // b | ||
295 | if (preg_match('#^/a/b/(?P<var>[^/]++)$#s', $pathinfo, $matches)) { | ||
296 | return $this->mergeDefaults(array_replace($matches, array('_route' => 'b')), array ()); | ||
297 | } | ||
298 | |||
299 | // c | ||
300 | if (0 === strpos($pathinfo, '/a/b/c') && preg_match('#^/a/b/c/(?P<var>[^/]++)$#s', $pathinfo, $matches)) { | ||
301 | return $this->mergeDefaults(array_replace($matches, array('_route' => 'c')), array ()); | ||
302 | } | ||
303 | |||
304 | } | ||
305 | |||
306 | } | ||
307 | |||
308 | throw 0 < count($allow) ? new MethodNotAllowedException(array_unique($allow)) : new ResourceNotFoundException(); | ||
309 | } | ||
310 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.apache b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.apache new file mode 100644 index 00000000..309f2ff0 --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.apache | |||
@@ -0,0 +1,7 @@ | |||
1 | # skip "real" requests | ||
2 | RewriteCond %{REQUEST_FILENAME} -f | ||
3 | RewriteRule .* - [QSA,L] | ||
4 | |||
5 | # foo | ||
6 | RewriteCond %{REQUEST_URI} ^/foo$ | ||
7 | RewriteRule .* ap\ p_d\ ev.php [QSA,L,E=_ROUTING_route:foo] | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.php b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.php new file mode 100644 index 00000000..ad157909 --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.php | |||
@@ -0,0 +1,340 @@ | |||
1 | <?php | ||
2 | |||
3 | use Symfony\Component\Routing\Exception\MethodNotAllowedException; | ||
4 | use Symfony\Component\Routing\Exception\ResourceNotFoundException; | ||
5 | use Symfony\Component\Routing\RequestContext; | ||
6 | |||
7 | /** | ||
8 | * ProjectUrlMatcher | ||
9 | * | ||
10 | * This class has been auto-generated | ||
11 | * by the Symfony Routing Component. | ||
12 | */ | ||
13 | class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\RedirectableUrlMatcher | ||
14 | { | ||
15 | /** | ||
16 | * Constructor. | ||
17 | */ | ||
18 | public function __construct(RequestContext $context) | ||
19 | { | ||
20 | $this->context = $context; | ||
21 | } | ||
22 | |||
23 | public function match($pathinfo) | ||
24 | { | ||
25 | $allow = array(); | ||
26 | $pathinfo = rawurldecode($pathinfo); | ||
27 | |||
28 | // foo | ||
29 | if (0 === strpos($pathinfo, '/foo') && preg_match('#^/foo/(?P<bar>baz|symfony)$#s', $pathinfo, $matches)) { | ||
30 | return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo')), array ( 'def' => 'test',)); | ||
31 | } | ||
32 | |||
33 | if (0 === strpos($pathinfo, '/bar')) { | ||
34 | // bar | ||
35 | if (preg_match('#^/bar/(?P<foo>[^/]++)$#s', $pathinfo, $matches)) { | ||
36 | if (!in_array($this->context->getMethod(), array('GET', 'HEAD'))) { | ||
37 | $allow = array_merge($allow, array('GET', 'HEAD')); | ||
38 | goto not_bar; | ||
39 | } | ||
40 | |||
41 | return $this->mergeDefaults(array_replace($matches, array('_route' => 'bar')), array ()); | ||
42 | } | ||
43 | not_bar: | ||
44 | |||
45 | // barhead | ||
46 | if (0 === strpos($pathinfo, '/barhead') && preg_match('#^/barhead/(?P<foo>[^/]++)$#s', $pathinfo, $matches)) { | ||
47 | if (!in_array($this->context->getMethod(), array('GET', 'HEAD'))) { | ||
48 | $allow = array_merge($allow, array('GET', 'HEAD')); | ||
49 | goto not_barhead; | ||
50 | } | ||
51 | |||
52 | return $this->mergeDefaults(array_replace($matches, array('_route' => 'barhead')), array ()); | ||
53 | } | ||
54 | not_barhead: | ||
55 | |||
56 | } | ||
57 | |||
58 | if (0 === strpos($pathinfo, '/test')) { | ||
59 | if (0 === strpos($pathinfo, '/test/baz')) { | ||
60 | // baz | ||
61 | if ($pathinfo === '/test/baz') { | ||
62 | return array('_route' => 'baz'); | ||
63 | } | ||
64 | |||
65 | // baz2 | ||
66 | if ($pathinfo === '/test/baz.html') { | ||
67 | return array('_route' => 'baz2'); | ||
68 | } | ||
69 | |||
70 | // baz3 | ||
71 | if (rtrim($pathinfo, '/') === '/test/baz3') { | ||
72 | if (substr($pathinfo, -1) !== '/') { | ||
73 | return $this->redirect($pathinfo.'/', 'baz3'); | ||
74 | } | ||
75 | |||
76 | return array('_route' => 'baz3'); | ||
77 | } | ||
78 | |||
79 | } | ||
80 | |||
81 | // baz4 | ||
82 | if (preg_match('#^/test/(?P<foo>[^/]++)/?$#s', $pathinfo, $matches)) { | ||
83 | if (substr($pathinfo, -1) !== '/') { | ||
84 | return $this->redirect($pathinfo.'/', 'baz4'); | ||
85 | } | ||
86 | |||
87 | return $this->mergeDefaults(array_replace($matches, array('_route' => 'baz4')), array ()); | ||
88 | } | ||
89 | |||
90 | // baz5 | ||
91 | if (preg_match('#^/test/(?P<foo>[^/]++)/$#s', $pathinfo, $matches)) { | ||
92 | if ($this->context->getMethod() != 'POST') { | ||
93 | $allow[] = 'POST'; | ||
94 | goto not_baz5; | ||
95 | } | ||
96 | |||
97 | return $this->mergeDefaults(array_replace($matches, array('_route' => 'baz5')), array ()); | ||
98 | } | ||
99 | not_baz5: | ||
100 | |||
101 | // baz.baz6 | ||
102 | if (preg_match('#^/test/(?P<foo>[^/]++)/$#s', $pathinfo, $matches)) { | ||
103 | if ($this->context->getMethod() != 'PUT') { | ||
104 | $allow[] = 'PUT'; | ||
105 | goto not_bazbaz6; | ||
106 | } | ||
107 | |||
108 | return $this->mergeDefaults(array_replace($matches, array('_route' => 'baz.baz6')), array ()); | ||
109 | } | ||
110 | not_bazbaz6: | ||
111 | |||
112 | } | ||
113 | |||
114 | // foofoo | ||
115 | if ($pathinfo === '/foofoo') { | ||
116 | return array ( 'def' => 'test', '_route' => 'foofoo',); | ||
117 | } | ||
118 | |||
119 | // quoter | ||
120 | if (preg_match('#^/(?P<quoter>[\']+)$#s', $pathinfo, $matches)) { | ||
121 | return $this->mergeDefaults(array_replace($matches, array('_route' => 'quoter')), array ()); | ||
122 | } | ||
123 | |||
124 | // space | ||
125 | if ($pathinfo === '/spa ce') { | ||
126 | return array('_route' => 'space'); | ||
127 | } | ||
128 | |||
129 | if (0 === strpos($pathinfo, '/a')) { | ||
130 | if (0 === strpos($pathinfo, '/a/b\'b')) { | ||
131 | // foo1 | ||
132 | if (preg_match('#^/a/b\'b/(?P<foo>[^/]++)$#s', $pathinfo, $matches)) { | ||
133 | return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo1')), array ()); | ||
134 | } | ||
135 | |||
136 | // bar1 | ||
137 | if (preg_match('#^/a/b\'b/(?P<bar>[^/]++)$#s', $pathinfo, $matches)) { | ||
138 | return $this->mergeDefaults(array_replace($matches, array('_route' => 'bar1')), array ()); | ||
139 | } | ||
140 | |||
141 | } | ||
142 | |||
143 | // overridden | ||
144 | if (preg_match('#^/a/(?P<var>.*)$#s', $pathinfo, $matches)) { | ||
145 | return $this->mergeDefaults(array_replace($matches, array('_route' => 'overridden')), array ()); | ||
146 | } | ||
147 | |||
148 | if (0 === strpos($pathinfo, '/a/b\'b')) { | ||
149 | // foo2 | ||
150 | if (preg_match('#^/a/b\'b/(?P<foo1>[^/]++)$#s', $pathinfo, $matches)) { | ||
151 | return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo2')), array ()); | ||
152 | } | ||
153 | |||
154 | // bar2 | ||
155 | if (preg_match('#^/a/b\'b/(?P<bar1>[^/]++)$#s', $pathinfo, $matches)) { | ||
156 | return $this->mergeDefaults(array_replace($matches, array('_route' => 'bar2')), array ()); | ||
157 | } | ||
158 | |||
159 | } | ||
160 | |||
161 | } | ||
162 | |||
163 | if (0 === strpos($pathinfo, '/multi')) { | ||
164 | // helloWorld | ||
165 | if (0 === strpos($pathinfo, '/multi/hello') && preg_match('#^/multi/hello(?:/(?P<who>[^/]++))?$#s', $pathinfo, $matches)) { | ||
166 | return $this->mergeDefaults(array_replace($matches, array('_route' => 'helloWorld')), array ( 'who' => 'World!',)); | ||
167 | } | ||
168 | |||
169 | // overridden2 | ||
170 | if ($pathinfo === '/multi/new') { | ||
171 | return array('_route' => 'overridden2'); | ||
172 | } | ||
173 | |||
174 | // hey | ||
175 | if (rtrim($pathinfo, '/') === '/multi/hey') { | ||
176 | if (substr($pathinfo, -1) !== '/') { | ||
177 | return $this->redirect($pathinfo.'/', 'hey'); | ||
178 | } | ||
179 | |||
180 | return array('_route' => 'hey'); | ||
181 | } | ||
182 | |||
183 | } | ||
184 | |||
185 | // foo3 | ||
186 | if (preg_match('#^/(?P<_locale>[^/]++)/b/(?P<foo>[^/]++)$#s', $pathinfo, $matches)) { | ||
187 | return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo3')), array ()); | ||
188 | } | ||
189 | |||
190 | // bar3 | ||
191 | if (preg_match('#^/(?P<_locale>[^/]++)/b/(?P<bar>[^/]++)$#s', $pathinfo, $matches)) { | ||
192 | return $this->mergeDefaults(array_replace($matches, array('_route' => 'bar3')), array ()); | ||
193 | } | ||
194 | |||
195 | if (0 === strpos($pathinfo, '/aba')) { | ||
196 | // ababa | ||
197 | if ($pathinfo === '/ababa') { | ||
198 | return array('_route' => 'ababa'); | ||
199 | } | ||
200 | |||
201 | // foo4 | ||
202 | if (preg_match('#^/aba/(?P<foo>[^/]++)$#s', $pathinfo, $matches)) { | ||
203 | return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo4')), array ()); | ||
204 | } | ||
205 | |||
206 | } | ||
207 | |||
208 | $host = $this->context->getHost(); | ||
209 | |||
210 | if (preg_match('#^a\\.example\\.com$#s', $host, $hostMatches)) { | ||
211 | // route1 | ||
212 | if ($pathinfo === '/route1') { | ||
213 | return array('_route' => 'route1'); | ||
214 | } | ||
215 | |||
216 | // route2 | ||
217 | if ($pathinfo === '/c2/route2') { | ||
218 | return array('_route' => 'route2'); | ||
219 | } | ||
220 | |||
221 | } | ||
222 | |||
223 | if (preg_match('#^b\\.example\\.com$#s', $host, $hostMatches)) { | ||
224 | // route3 | ||
225 | if ($pathinfo === '/c2/route3') { | ||
226 | return array('_route' => 'route3'); | ||
227 | } | ||
228 | |||
229 | } | ||
230 | |||
231 | if (preg_match('#^a\\.example\\.com$#s', $host, $hostMatches)) { | ||
232 | // route4 | ||
233 | if ($pathinfo === '/route4') { | ||
234 | return array('_route' => 'route4'); | ||
235 | } | ||
236 | |||
237 | } | ||
238 | |||
239 | if (preg_match('#^c\\.example\\.com$#s', $host, $hostMatches)) { | ||
240 | // route5 | ||
241 | if ($pathinfo === '/route5') { | ||
242 | return array('_route' => 'route5'); | ||
243 | } | ||
244 | |||
245 | } | ||
246 | |||
247 | // route6 | ||
248 | if ($pathinfo === '/route6') { | ||
249 | return array('_route' => 'route6'); | ||
250 | } | ||
251 | |||
252 | if (preg_match('#^(?P<var1>[^\\.]++)\\.example\\.com$#s', $host, $hostMatches)) { | ||
253 | if (0 === strpos($pathinfo, '/route1')) { | ||
254 | // route11 | ||
255 | if ($pathinfo === '/route11') { | ||
256 | return $this->mergeDefaults(array_replace($hostMatches, array('_route' => 'route11')), array ()); | ||
257 | } | ||
258 | |||
259 | // route12 | ||
260 | if ($pathinfo === '/route12') { | ||
261 | return $this->mergeDefaults(array_replace($hostMatches, array('_route' => 'route12')), array ( 'var1' => 'val',)); | ||
262 | } | ||
263 | |||
264 | // route13 | ||
265 | if (0 === strpos($pathinfo, '/route13') && preg_match('#^/route13/(?P<name>[^/]++)$#s', $pathinfo, $matches)) { | ||
266 | return $this->mergeDefaults(array_replace($hostMatches, $matches, array('_route' => 'route13')), array ()); | ||
267 | } | ||
268 | |||
269 | // route14 | ||
270 | if (0 === strpos($pathinfo, '/route14') && preg_match('#^/route14/(?P<name>[^/]++)$#s', $pathinfo, $matches)) { | ||
271 | return $this->mergeDefaults(array_replace($hostMatches, $matches, array('_route' => 'route14')), array ( 'var1' => 'val',)); | ||
272 | } | ||
273 | |||
274 | } | ||
275 | |||
276 | } | ||
277 | |||
278 | if (preg_match('#^c\\.example\\.com$#s', $host, $hostMatches)) { | ||
279 | // route15 | ||
280 | if (0 === strpos($pathinfo, '/route15') && preg_match('#^/route15/(?P<name>[^/]++)$#s', $pathinfo, $matches)) { | ||
281 | return $this->mergeDefaults(array_replace($matches, array('_route' => 'route15')), array ()); | ||
282 | } | ||
283 | |||
284 | } | ||
285 | |||
286 | if (0 === strpos($pathinfo, '/route1')) { | ||
287 | // route16 | ||
288 | if (0 === strpos($pathinfo, '/route16') && preg_match('#^/route16/(?P<name>[^/]++)$#s', $pathinfo, $matches)) { | ||
289 | return $this->mergeDefaults(array_replace($matches, array('_route' => 'route16')), array ( 'var1' => 'val',)); | ||
290 | } | ||
291 | |||
292 | // route17 | ||
293 | if ($pathinfo === '/route17') { | ||
294 | return array('_route' => 'route17'); | ||
295 | } | ||
296 | |||
297 | } | ||
298 | |||
299 | if (0 === strpos($pathinfo, '/a')) { | ||
300 | // a | ||
301 | if ($pathinfo === '/a/a...') { | ||
302 | return array('_route' => 'a'); | ||
303 | } | ||
304 | |||
305 | if (0 === strpos($pathinfo, '/a/b')) { | ||
306 | // b | ||
307 | if (preg_match('#^/a/b/(?P<var>[^/]++)$#s', $pathinfo, $matches)) { | ||
308 | return $this->mergeDefaults(array_replace($matches, array('_route' => 'b')), array ()); | ||
309 | } | ||
310 | |||
311 | // c | ||
312 | if (0 === strpos($pathinfo, '/a/b/c') && preg_match('#^/a/b/c/(?P<var>[^/]++)$#s', $pathinfo, $matches)) { | ||
313 | return $this->mergeDefaults(array_replace($matches, array('_route' => 'c')), array ()); | ||
314 | } | ||
315 | |||
316 | } | ||
317 | |||
318 | } | ||
319 | |||
320 | // secure | ||
321 | if ($pathinfo === '/secure') { | ||
322 | if ($this->context->getScheme() !== 'https') { | ||
323 | return $this->redirect($pathinfo, 'secure', 'https'); | ||
324 | } | ||
325 | |||
326 | return array('_route' => 'secure'); | ||
327 | } | ||
328 | |||
329 | // nonsecure | ||
330 | if ($pathinfo === '/nonsecure') { | ||
331 | if ($this->context->getScheme() !== 'http') { | ||
332 | return $this->redirect($pathinfo, 'nonsecure', 'http'); | ||
333 | } | ||
334 | |||
335 | return array('_route' => 'nonsecure'); | ||
336 | } | ||
337 | |||
338 | throw 0 < count($allow) ? new MethodNotAllowedException(array_unique($allow)) : new ResourceNotFoundException(); | ||
339 | } | ||
340 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher3.php b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher3.php new file mode 100644 index 00000000..f2f642eb --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher3.php | |||
@@ -0,0 +1,43 @@ | |||
1 | <?php | ||
2 | |||
3 | use Symfony\Component\Routing\Exception\MethodNotAllowedException; | ||
4 | use Symfony\Component\Routing\Exception\ResourceNotFoundException; | ||
5 | use Symfony\Component\Routing\RequestContext; | ||
6 | |||
7 | /** | ||
8 | * ProjectUrlMatcher | ||
9 | * | ||
10 | * This class has been auto-generated | ||
11 | * by the Symfony Routing Component. | ||
12 | */ | ||
13 | class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher | ||
14 | { | ||
15 | /** | ||
16 | * Constructor. | ||
17 | */ | ||
18 | public function __construct(RequestContext $context) | ||
19 | { | ||
20 | $this->context = $context; | ||
21 | } | ||
22 | |||
23 | public function match($pathinfo) | ||
24 | { | ||
25 | $allow = array(); | ||
26 | $pathinfo = rawurldecode($pathinfo); | ||
27 | |||
28 | if (0 === strpos($pathinfo, '/rootprefix')) { | ||
29 | // static | ||
30 | if ($pathinfo === '/rootprefix/test') { | ||
31 | return array('_route' => 'static'); | ||
32 | } | ||
33 | |||
34 | // dynamic | ||
35 | if (preg_match('#^/rootprefix/(?P<var>[^/]++)$#s', $pathinfo, $matches)) { | ||
36 | return $this->mergeDefaults(array_replace($matches, array('_route' => 'dynamic')), array ()); | ||
37 | } | ||
38 | |||
39 | } | ||
40 | |||
41 | throw 0 < count($allow) ? new MethodNotAllowedException(array_unique($allow)) : new ResourceNotFoundException(); | ||
42 | } | ||
43 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/empty.yml b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/empty.yml new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/empty.yml | |||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/foo.xml b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/foo.xml new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/foo.xml | |||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/foo1.xml b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/foo1.xml new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/foo1.xml | |||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/incomplete.yml b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/incomplete.yml new file mode 100644 index 00000000..df64d324 --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/incomplete.yml | |||
@@ -0,0 +1,2 @@ | |||
1 | blog_show: | ||
2 | defaults: { _controller: MyBlogBundle:Blog:show } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/missing_id.xml b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/missing_id.xml new file mode 100644 index 00000000..4ea4115f --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/missing_id.xml | |||
@@ -0,0 +1,8 @@ | |||
1 | <?xml version="1.0" encoding="UTF-8" ?> | ||
2 | |||
3 | <routes xmlns="http://symfony.com/schema/routing" | ||
4 | xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
5 | xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd"> | ||
6 | |||
7 | <route path="/test"></route> | ||
8 | </routes> | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/missing_path.xml b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/missing_path.xml new file mode 100644 index 00000000..ef5bc088 --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/missing_path.xml | |||
@@ -0,0 +1,8 @@ | |||
1 | <?xml version="1.0" encoding="UTF-8" ?> | ||
2 | |||
3 | <routes xmlns="http://symfony.com/schema/routing" | ||
4 | xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
5 | xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd"> | ||
6 | |||
7 | <route id="myroute"></route> | ||
8 | </routes> | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/namespaceprefix.xml b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/namespaceprefix.xml new file mode 100644 index 00000000..bdd6a473 --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/namespaceprefix.xml | |||
@@ -0,0 +1,13 @@ | |||
1 | <?xml version="1.0" encoding="UTF-8" ?> | ||
2 | |||
3 | <r:routes xmlns:r="http://symfony.com/schema/routing" | ||
4 | xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
5 | xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd"> | ||
6 | |||
7 | <r:route id="blog_show" path="/blog/{slug}" host="{_locale}.example.com"> | ||
8 | <r:default key="_controller">MyBundle:Blog:show</r:default> | ||
9 | <requirement xmlns="http://symfony.com/schema/routing" key="slug">\w+</requirement> | ||
10 | <r2:requirement xmlns:r2="http://symfony.com/schema/routing" key="_locale">en|fr|de</r2:requirement> | ||
11 | <r:option key="compiler_class">RouteCompiler</r:option> | ||
12 | </r:route> | ||
13 | </r:routes> | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/nonesense_resource_plus_path.yml b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/nonesense_resource_plus_path.yml new file mode 100644 index 00000000..a3e94737 --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/nonesense_resource_plus_path.yml | |||
@@ -0,0 +1,3 @@ | |||
1 | blog_show: | ||
2 | resource: validpattern.yml | ||
3 | path: /test | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/nonesense_type_without_resource.yml b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/nonesense_type_without_resource.yml new file mode 100644 index 00000000..547cda3b --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/nonesense_type_without_resource.yml | |||
@@ -0,0 +1,3 @@ | |||
1 | blog_show: | ||
2 | path: /blog/{slug} | ||
3 | type: custom | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/nonvalid.xml b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/nonvalid.xml new file mode 100644 index 00000000..755e4430 --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/nonvalid.xml | |||
@@ -0,0 +1,11 @@ | |||
1 | <?xml version="1.0" encoding="UTF-8" ?> | ||
2 | |||
3 | <routes xmlns="http://symfony.com/schema/routing" | ||
4 | xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
5 | xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd"> | ||
6 | |||
7 | <route id="blog_show" path="/blog/{slug}"> | ||
8 | <default key="_controller">MyBundle:Blog:show</default> | ||
9 | <requirement key="_method">GET</requirement> | ||
10 | <!-- </route> --> | ||
11 | </routes> | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/nonvalid.yml b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/nonvalid.yml new file mode 100644 index 00000000..257cc564 --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/nonvalid.yml | |||
@@ -0,0 +1 @@ | |||
foo | |||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/nonvalid2.yml b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/nonvalid2.yml new file mode 100644 index 00000000..cfa9992b --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/nonvalid2.yml | |||
@@ -0,0 +1 @@ | |||
route: string | |||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/nonvalidkeys.yml b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/nonvalidkeys.yml new file mode 100644 index 00000000..015e270f --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/nonvalidkeys.yml | |||
@@ -0,0 +1,3 @@ | |||
1 | someroute: | ||
2 | resource: path/to/some.yml | ||
3 | name_prefix: test_ | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/nonvalidnode.xml b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/nonvalidnode.xml new file mode 100644 index 00000000..863ef03b --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/nonvalidnode.xml | |||
@@ -0,0 +1,8 @@ | |||
1 | <?xml version="1.0" encoding="UTF-8" ?> | ||
2 | |||
3 | <routes xmlns="http://symfony.com/schema/routing" | ||
4 | xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
5 | xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd"> | ||
6 | |||
7 | <foo>bar</foo> | ||
8 | </routes> | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/nonvalidroute.xml b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/nonvalidroute.xml new file mode 100644 index 00000000..a46961ee --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/nonvalidroute.xml | |||
@@ -0,0 +1,13 @@ | |||
1 | <?xml version="1.0" encoding="UTF-8" ?> | ||
2 | |||
3 | <routes xmlns="http://symfony.com/schema/routing" | ||
4 | xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
5 | xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd"> | ||
6 | |||
7 | <route id="blog_show" path="/blog/{slug}"> | ||
8 | <default key="_controller">MyBundle:Blog:show</default> | ||
9 | <requirement key="_method">GET</requirement> | ||
10 | <option key="compiler_class">RouteCompiler</option> | ||
11 | <foo key="bar">baz</foo> | ||
12 | </route> | ||
13 | </routes> | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/special_route_name.yml b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/special_route_name.yml new file mode 100644 index 00000000..78be239a --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/special_route_name.yml | |||
@@ -0,0 +1,2 @@ | |||
1 | "#$péß^a|": | ||
2 | path: "true" | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/validpattern.php b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/validpattern.php new file mode 100644 index 00000000..b8bbbb5f --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/validpattern.php | |||
@@ -0,0 +1,23 @@ | |||
1 | <?php | ||
2 | use Symfony\Component\Routing\RouteCollection; | ||
3 | use Symfony\Component\Routing\Route; | ||
4 | |||
5 | $collection = new RouteCollection(); | ||
6 | $collection->add('blog_show', new Route( | ||
7 | '/blog/{slug}', | ||
8 | array('_controller' => 'MyBlogBundle:Blog:show'), | ||
9 | array('locale' => '\w+'), | ||
10 | array('compiler_class' => 'RouteCompiler'), | ||
11 | '{locale}.example.com', | ||
12 | array('https'), | ||
13 | array('GET','POST','put','OpTiOnS') | ||
14 | )); | ||
15 | $collection->add('blog_show_legacy', new Route( | ||
16 | '/blog/{slug}', | ||
17 | array('_controller' => 'MyBlogBundle:Blog:show'), | ||
18 | array('_method' => 'GET|POST|put|OpTiOnS', '_scheme' => 'https', 'locale' => '\w+',), | ||
19 | array('compiler_class' => 'RouteCompiler'), | ||
20 | '{locale}.example.com' | ||
21 | )); | ||
22 | |||
23 | return $collection; | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/validpattern.xml b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/validpattern.xml new file mode 100644 index 00000000..b9f22347 --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/validpattern.xml | |||
@@ -0,0 +1,21 @@ | |||
1 | <?xml version="1.0" encoding="UTF-8" ?> | ||
2 | |||
3 | <routes xmlns="http://symfony.com/schema/routing" | ||
4 | xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
5 | xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd"> | ||
6 | |||
7 | <route id="blog_show" path="/blog/{slug}" host="{locale}.example.com" methods="GET|POST put,OpTiOnS" schemes="hTTps"> | ||
8 | <default key="_controller">MyBundle:Blog:show</default> | ||
9 | <requirement key="locale">\w+</requirement> | ||
10 | <option key="compiler_class">RouteCompiler</option> | ||
11 | </route> | ||
12 | |||
13 | <route id="blog_show_legacy" pattern="/blog/{slug}" host="{locale}.example.com"> | ||
14 | <default key="_controller">MyBundle:Blog:show</default> | ||
15 | <default key="slug" xsi:nil="true" /> | ||
16 | <requirement key="_method">GET|POST|put|OpTiOnS</requirement> | ||
17 | <requirement key="_scheme">hTTps</requirement> | ||
18 | <requirement key="locale">\w+</requirement> | ||
19 | <option key="compiler_class">RouteCompiler</option> | ||
20 | </route> | ||
21 | </routes> | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/validpattern.yml b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/validpattern.yml new file mode 100644 index 00000000..4ada8832 --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/validpattern.yml | |||
@@ -0,0 +1,17 @@ | |||
1 | blog_show: | ||
2 | path: /blog/{slug} | ||
3 | defaults: { _controller: "MyBundle:Blog:show" } | ||
4 | host: "{locale}.example.com" | ||
5 | requirements: { 'locale': '\w+' } | ||
6 | methods: ['GET','POST','put','OpTiOnS'] | ||
7 | schemes: ['https'] | ||
8 | options: | ||
9 | compiler_class: RouteCompiler | ||
10 | |||
11 | blog_show_legacy: | ||
12 | pattern: /blog/{slug} | ||
13 | defaults: { _controller: "MyBundle:Blog:show" } | ||
14 | host: "{locale}.example.com" | ||
15 | requirements: { '_method': 'GET|POST|put|OpTiOnS', _scheme: https, 'locale': '\w+' } | ||
16 | options: | ||
17 | compiler_class: RouteCompiler | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/validresource.xml b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/validresource.xml new file mode 100644 index 00000000..295c3cc4 --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/validresource.xml | |||
@@ -0,0 +1,12 @@ | |||
1 | <?xml version="1.0" encoding="UTF-8" ?> | ||
2 | |||
3 | <routes xmlns="http://symfony.com/schema/routing" | ||
4 | xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
5 | xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd"> | ||
6 | |||
7 | <import resource="validpattern.xml" prefix="/{foo}" host=""> | ||
8 | <default key="foo">123</default> | ||
9 | <requirement key="foo">\d+</requirement> | ||
10 | <option key="foo">bar</option> | ||
11 | </import> | ||
12 | </routes> | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/validresource.yml b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/validresource.yml new file mode 100644 index 00000000..495ed854 --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/validresource.yml | |||
@@ -0,0 +1,7 @@ | |||
1 | _blog: | ||
2 | resource: validpattern.yml | ||
3 | prefix: /{foo} | ||
4 | defaults: { 'foo': '123' } | ||
5 | requirements: { 'foo': '\d+' } | ||
6 | options: { 'foo': 'bar' } | ||
7 | host: "" | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/withdoctype.xml b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/withdoctype.xml new file mode 100644 index 00000000..f217d5bc --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Fixtures/withdoctype.xml | |||
@@ -0,0 +1,3 @@ | |||
1 | <?xml version="1.0"?> | ||
2 | <!DOCTYPE foo> | ||
3 | <foo></foo> | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Tests/Generator/Dumper/PhpGeneratorDumperTest.php b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Generator/Dumper/PhpGeneratorDumperTest.php new file mode 100644 index 00000000..ab5f4cda --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Generator/Dumper/PhpGeneratorDumperTest.php | |||
@@ -0,0 +1,117 @@ | |||
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\Tests\Generator\Dumper; | ||
13 | |||
14 | use Symfony\Component\Routing\RouteCollection; | ||
15 | use Symfony\Component\Routing\Route; | ||
16 | use Symfony\Component\Routing\Generator\Dumper\PhpGeneratorDumper; | ||
17 | use Symfony\Component\Routing\RequestContext; | ||
18 | |||
19 | class PhpGeneratorDumperTest extends \PHPUnit_Framework_TestCase | ||
20 | { | ||
21 | /** | ||
22 | * @var RouteCollection | ||
23 | */ | ||
24 | private $routeCollection; | ||
25 | |||
26 | /** | ||
27 | * @var PhpGeneratorDumper | ||
28 | */ | ||
29 | private $generatorDumper; | ||
30 | |||
31 | /** | ||
32 | * @var string | ||
33 | */ | ||
34 | private $testTmpFilepath; | ||
35 | |||
36 | protected function setUp() | ||
37 | { | ||
38 | parent::setUp(); | ||
39 | |||
40 | $this->routeCollection = new RouteCollection(); | ||
41 | $this->generatorDumper = new PhpGeneratorDumper($this->routeCollection); | ||
42 | $this->testTmpFilepath = sys_get_temp_dir().DIRECTORY_SEPARATOR.'php_generator.php'; | ||
43 | @unlink($this->testTmpFilepath); | ||
44 | } | ||
45 | |||
46 | protected function tearDown() | ||
47 | { | ||
48 | parent::tearDown(); | ||
49 | |||
50 | @unlink($this->testTmpFilepath); | ||
51 | |||
52 | $this->routeCollection = null; | ||
53 | $this->generatorDumper = null; | ||
54 | $this->testTmpFilepath = null; | ||
55 | } | ||
56 | |||
57 | public function testDumpWithRoutes() | ||
58 | { | ||
59 | $this->routeCollection->add('Test', new Route('/testing/{foo}')); | ||
60 | $this->routeCollection->add('Test2', new Route('/testing2')); | ||
61 | |||
62 | file_put_contents($this->testTmpFilepath, $this->generatorDumper->dump()); | ||
63 | include ($this->testTmpFilepath); | ||
64 | |||
65 | $projectUrlGenerator = new \ProjectUrlGenerator(new RequestContext('/app.php')); | ||
66 | |||
67 | $absoluteUrlWithParameter = $projectUrlGenerator->generate('Test', array('foo' => 'bar'), true); | ||
68 | $absoluteUrlWithoutParameter = $projectUrlGenerator->generate('Test2', array(), true); | ||
69 | $relativeUrlWithParameter = $projectUrlGenerator->generate('Test', array('foo' => 'bar'), false); | ||
70 | $relativeUrlWithoutParameter = $projectUrlGenerator->generate('Test2', array(), false); | ||
71 | |||
72 | $this->assertEquals($absoluteUrlWithParameter, 'http://localhost/app.php/testing/bar'); | ||
73 | $this->assertEquals($absoluteUrlWithoutParameter, 'http://localhost/app.php/testing2'); | ||
74 | $this->assertEquals($relativeUrlWithParameter, '/app.php/testing/bar'); | ||
75 | $this->assertEquals($relativeUrlWithoutParameter, '/app.php/testing2'); | ||
76 | } | ||
77 | |||
78 | /** | ||
79 | * @expectedException \InvalidArgumentException | ||
80 | */ | ||
81 | public function testDumpWithoutRoutes() | ||
82 | { | ||
83 | file_put_contents($this->testTmpFilepath, $this->generatorDumper->dump(array('class' => 'WithoutRoutesUrlGenerator'))); | ||
84 | include ($this->testTmpFilepath); | ||
85 | |||
86 | $projectUrlGenerator = new \WithoutRoutesUrlGenerator(new RequestContext('/app.php')); | ||
87 | |||
88 | $projectUrlGenerator->generate('Test', array()); | ||
89 | } | ||
90 | |||
91 | /** | ||
92 | * @expectedException \Symfony\Component\Routing\Exception\RouteNotFoundException | ||
93 | */ | ||
94 | public function testGenerateNonExistingRoute() | ||
95 | { | ||
96 | $this->routeCollection->add('Test', new Route('/test')); | ||
97 | |||
98 | file_put_contents($this->testTmpFilepath, $this->generatorDumper->dump(array('class' => 'NonExistingRoutesUrlGenerator'))); | ||
99 | include ($this->testTmpFilepath); | ||
100 | |||
101 | $projectUrlGenerator = new \NonExistingRoutesUrlGenerator(new RequestContext()); | ||
102 | $url = $projectUrlGenerator->generate('NonExisting', array()); | ||
103 | } | ||
104 | |||
105 | public function testDumpForRouteWithDefaults() | ||
106 | { | ||
107 | $this->routeCollection->add('Test', new Route('/testing/{foo}', array('foo' => 'bar'))); | ||
108 | |||
109 | file_put_contents($this->testTmpFilepath, $this->generatorDumper->dump(array('class' => 'DefaultRoutesUrlGenerator'))); | ||
110 | include ($this->testTmpFilepath); | ||
111 | |||
112 | $projectUrlGenerator = new \DefaultRoutesUrlGenerator(new RequestContext()); | ||
113 | $url = $projectUrlGenerator->generate('Test', array()); | ||
114 | |||
115 | $this->assertEquals($url, '/testing'); | ||
116 | } | ||
117 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Tests/Generator/UrlGeneratorTest.php b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Generator/UrlGeneratorTest.php new file mode 100644 index 00000000..5f8ef491 --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Generator/UrlGeneratorTest.php | |||
@@ -0,0 +1,635 @@ | |||
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\Tests\Generator; | ||
13 | |||
14 | use Symfony\Component\Routing\RouteCollection; | ||
15 | use Symfony\Component\Routing\Route; | ||
16 | use Symfony\Component\Routing\Generator\UrlGenerator; | ||
17 | use Symfony\Component\Routing\Generator\UrlGeneratorInterface; | ||
18 | use Symfony\Component\Routing\RequestContext; | ||
19 | |||
20 | class UrlGeneratorTest extends \PHPUnit_Framework_TestCase | ||
21 | { | ||
22 | public function testAbsoluteUrlWithPort80() | ||
23 | { | ||
24 | $routes = $this->getRoutes('test', new Route('/testing')); | ||
25 | $url = $this->getGenerator($routes)->generate('test', array(), true); | ||
26 | |||
27 | $this->assertEquals('http://localhost/app.php/testing', $url); | ||
28 | } | ||
29 | |||
30 | public function testAbsoluteSecureUrlWithPort443() | ||
31 | { | ||
32 | $routes = $this->getRoutes('test', new Route('/testing')); | ||
33 | $url = $this->getGenerator($routes, array('scheme' => 'https'))->generate('test', array(), true); | ||
34 | |||
35 | $this->assertEquals('https://localhost/app.php/testing', $url); | ||
36 | } | ||
37 | |||
38 | public function testAbsoluteUrlWithNonStandardPort() | ||
39 | { | ||
40 | $routes = $this->getRoutes('test', new Route('/testing')); | ||
41 | $url = $this->getGenerator($routes, array('httpPort' => 8080))->generate('test', array(), true); | ||
42 | |||
43 | $this->assertEquals('http://localhost:8080/app.php/testing', $url); | ||
44 | } | ||
45 | |||
46 | public function testAbsoluteSecureUrlWithNonStandardPort() | ||
47 | { | ||
48 | $routes = $this->getRoutes('test', new Route('/testing')); | ||
49 | $url = $this->getGenerator($routes, array('httpsPort' => 8080, 'scheme' => 'https'))->generate('test', array(), true); | ||
50 | |||
51 | $this->assertEquals('https://localhost:8080/app.php/testing', $url); | ||
52 | } | ||
53 | |||
54 | public function testRelativeUrlWithoutParameters() | ||
55 | { | ||
56 | $routes = $this->getRoutes('test', new Route('/testing')); | ||
57 | $url = $this->getGenerator($routes)->generate('test', array(), false); | ||
58 | |||
59 | $this->assertEquals('/app.php/testing', $url); | ||
60 | } | ||
61 | |||
62 | public function testRelativeUrlWithParameter() | ||
63 | { | ||
64 | $routes = $this->getRoutes('test', new Route('/testing/{foo}')); | ||
65 | $url = $this->getGenerator($routes)->generate('test', array('foo' => 'bar'), false); | ||
66 | |||
67 | $this->assertEquals('/app.php/testing/bar', $url); | ||
68 | } | ||
69 | |||
70 | public function testRelativeUrlWithNullParameter() | ||
71 | { | ||
72 | $routes = $this->getRoutes('test', new Route('/testing.{format}', array('format' => null))); | ||
73 | $url = $this->getGenerator($routes)->generate('test', array(), false); | ||
74 | |||
75 | $this->assertEquals('/app.php/testing', $url); | ||
76 | } | ||
77 | |||
78 | /** | ||
79 | * @expectedException \Symfony\Component\Routing\Exception\InvalidParameterException | ||
80 | */ | ||
81 | public function testRelativeUrlWithNullParameterButNotOptional() | ||
82 | { | ||
83 | $routes = $this->getRoutes('test', new Route('/testing/{foo}/bar', array('foo' => null))); | ||
84 | // This must raise an exception because the default requirement for "foo" is "[^/]+" which is not met with these params. | ||
85 | // Generating path "/testing//bar" would be wrong as matching this route would fail. | ||
86 | $this->getGenerator($routes)->generate('test', array(), false); | ||
87 | } | ||
88 | |||
89 | public function testRelativeUrlWithOptionalZeroParameter() | ||
90 | { | ||
91 | $routes = $this->getRoutes('test', new Route('/testing/{page}')); | ||
92 | $url = $this->getGenerator($routes)->generate('test', array('page' => 0), false); | ||
93 | |||
94 | $this->assertEquals('/app.php/testing/0', $url); | ||
95 | } | ||
96 | |||
97 | public function testNotPassedOptionalParameterInBetween() | ||
98 | { | ||
99 | $routes = $this->getRoutes('test', new Route('/{slug}/{page}', array('slug' => 'index', 'page' => 0))); | ||
100 | $this->assertSame('/app.php/index/1', $this->getGenerator($routes)->generate('test', array('page' => 1))); | ||
101 | $this->assertSame('/app.php/', $this->getGenerator($routes)->generate('test')); | ||
102 | } | ||
103 | |||
104 | public function testRelativeUrlWithExtraParameters() | ||
105 | { | ||
106 | $routes = $this->getRoutes('test', new Route('/testing')); | ||
107 | $url = $this->getGenerator($routes)->generate('test', array('foo' => 'bar'), false); | ||
108 | |||
109 | $this->assertEquals('/app.php/testing?foo=bar', $url); | ||
110 | } | ||
111 | |||
112 | public function testAbsoluteUrlWithExtraParameters() | ||
113 | { | ||
114 | $routes = $this->getRoutes('test', new Route('/testing')); | ||
115 | $url = $this->getGenerator($routes)->generate('test', array('foo' => 'bar'), true); | ||
116 | |||
117 | $this->assertEquals('http://localhost/app.php/testing?foo=bar', $url); | ||
118 | } | ||
119 | |||
120 | public function testUrlWithNullExtraParameters() | ||
121 | { | ||
122 | $routes = $this->getRoutes('test', new Route('/testing')); | ||
123 | $url = $this->getGenerator($routes)->generate('test', array('foo' => null), true); | ||
124 | |||
125 | $this->assertEquals('http://localhost/app.php/testing', $url); | ||
126 | } | ||
127 | |||
128 | public function testUrlWithExtraParametersFromGlobals() | ||
129 | { | ||
130 | $routes = $this->getRoutes('test', new Route('/testing')); | ||
131 | $generator = $this->getGenerator($routes); | ||
132 | $context = new RequestContext('/app.php'); | ||
133 | $context->setParameter('bar', 'bar'); | ||
134 | $generator->setContext($context); | ||
135 | $url = $generator->generate('test', array('foo' => 'bar')); | ||
136 | |||
137 | $this->assertEquals('/app.php/testing?foo=bar', $url); | ||
138 | } | ||
139 | |||
140 | public function testUrlWithGlobalParameter() | ||
141 | { | ||
142 | $routes = $this->getRoutes('test', new Route('/testing/{foo}')); | ||
143 | $generator = $this->getGenerator($routes); | ||
144 | $context = new RequestContext('/app.php'); | ||
145 | $context->setParameter('foo', 'bar'); | ||
146 | $generator->setContext($context); | ||
147 | $url = $generator->generate('test', array()); | ||
148 | |||
149 | $this->assertEquals('/app.php/testing/bar', $url); | ||
150 | } | ||
151 | |||
152 | public function testGlobalParameterHasHigherPriorityThanDefault() | ||
153 | { | ||
154 | $routes = $this->getRoutes('test', new Route('/{_locale}', array('_locale' => 'en'))); | ||
155 | $generator = $this->getGenerator($routes); | ||
156 | $context = new RequestContext('/app.php'); | ||
157 | $context->setParameter('_locale', 'de'); | ||
158 | $generator->setContext($context); | ||
159 | $url = $generator->generate('test', array()); | ||
160 | |||
161 | $this->assertSame('/app.php/de', $url); | ||
162 | } | ||
163 | |||
164 | /** | ||
165 | * @expectedException \Symfony\Component\Routing\Exception\RouteNotFoundException | ||
166 | */ | ||
167 | public function testGenerateWithoutRoutes() | ||
168 | { | ||
169 | $routes = $this->getRoutes('foo', new Route('/testing/{foo}')); | ||
170 | $this->getGenerator($routes)->generate('test', array(), true); | ||
171 | } | ||
172 | |||
173 | /** | ||
174 | * @expectedException \Symfony\Component\Routing\Exception\MissingMandatoryParametersException | ||
175 | */ | ||
176 | public function testGenerateForRouteWithoutMandatoryParameter() | ||
177 | { | ||
178 | $routes = $this->getRoutes('test', new Route('/testing/{foo}')); | ||
179 | $this->getGenerator($routes)->generate('test', array(), true); | ||
180 | } | ||
181 | |||
182 | /** | ||
183 | * @expectedException \Symfony\Component\Routing\Exception\InvalidParameterException | ||
184 | */ | ||
185 | public function testGenerateForRouteWithInvalidOptionalParameter() | ||
186 | { | ||
187 | $routes = $this->getRoutes('test', new Route('/testing/{foo}', array('foo' => '1'), array('foo' => 'd+'))); | ||
188 | $this->getGenerator($routes)->generate('test', array('foo' => 'bar'), true); | ||
189 | } | ||
190 | |||
191 | /** | ||
192 | * @expectedException \Symfony\Component\Routing\Exception\InvalidParameterException | ||
193 | */ | ||
194 | public function testGenerateForRouteWithInvalidParameter() | ||
195 | { | ||
196 | $routes = $this->getRoutes('test', new Route('/testing/{foo}', array(), array('foo' => '1|2'))); | ||
197 | $this->getGenerator($routes)->generate('test', array('foo' => '0'), true); | ||
198 | } | ||
199 | |||
200 | public function testGenerateForRouteWithInvalidOptionalParameterNonStrict() | ||
201 | { | ||
202 | $routes = $this->getRoutes('test', new Route('/testing/{foo}', array('foo' => '1'), array('foo' => 'd+'))); | ||
203 | $generator = $this->getGenerator($routes); | ||
204 | $generator->setStrictRequirements(false); | ||
205 | $this->assertNull($generator->generate('test', array('foo' => 'bar'), true)); | ||
206 | } | ||
207 | |||
208 | public function testGenerateForRouteWithInvalidOptionalParameterNonStrictWithLogger() | ||
209 | { | ||
210 | if (!interface_exists('Psr\Log\LoggerInterface')) { | ||
211 | $this->markTestSkipped('The "psr/log" package is not available'); | ||
212 | } | ||
213 | |||
214 | $routes = $this->getRoutes('test', new Route('/testing/{foo}', array('foo' => '1'), array('foo' => 'd+'))); | ||
215 | $logger = $this->getMock('Psr\Log\LoggerInterface'); | ||
216 | $logger->expects($this->once()) | ||
217 | ->method('error'); | ||
218 | $generator = $this->getGenerator($routes, array(), $logger); | ||
219 | $generator->setStrictRequirements(false); | ||
220 | $this->assertNull($generator->generate('test', array('foo' => 'bar'), true)); | ||
221 | } | ||
222 | |||
223 | public function testGenerateForRouteWithInvalidParameterButDisabledRequirementsCheck() | ||
224 | { | ||
225 | $routes = $this->getRoutes('test', new Route('/testing/{foo}', array('foo' => '1'), array('foo' => 'd+'))); | ||
226 | $generator = $this->getGenerator($routes); | ||
227 | $generator->setStrictRequirements(null); | ||
228 | $this->assertSame('/app.php/testing/bar', $generator->generate('test', array('foo' => 'bar'))); | ||
229 | } | ||
230 | |||
231 | /** | ||
232 | * @expectedException \Symfony\Component\Routing\Exception\InvalidParameterException | ||
233 | */ | ||
234 | public function testGenerateForRouteWithInvalidMandatoryParameter() | ||
235 | { | ||
236 | $routes = $this->getRoutes('test', new Route('/testing/{foo}', array(), array('foo' => 'd+'))); | ||
237 | $this->getGenerator($routes)->generate('test', array('foo' => 'bar'), true); | ||
238 | } | ||
239 | |||
240 | /** | ||
241 | * @expectedException \Symfony\Component\Routing\Exception\InvalidParameterException | ||
242 | */ | ||
243 | public function testRequiredParamAndEmptyPassed() | ||
244 | { | ||
245 | $routes = $this->getRoutes('test', new Route('/{slug}', array(), array('slug' => '.+'))); | ||
246 | $this->getGenerator($routes)->generate('test', array('slug' => '')); | ||
247 | } | ||
248 | |||
249 | public function testSchemeRequirementDoesNothingIfSameCurrentScheme() | ||
250 | { | ||
251 | $routes = $this->getRoutes('test', new Route('/', array(), array('_scheme' => 'http'))); | ||
252 | $this->assertEquals('/app.php/', $this->getGenerator($routes)->generate('test')); | ||
253 | |||
254 | $routes = $this->getRoutes('test', new Route('/', array(), array('_scheme' => 'https'))); | ||
255 | $this->assertEquals('/app.php/', $this->getGenerator($routes, array('scheme' => 'https'))->generate('test')); | ||
256 | } | ||
257 | |||
258 | public function testSchemeRequirementForcesAbsoluteUrl() | ||
259 | { | ||
260 | $routes = $this->getRoutes('test', new Route('/', array(), array('_scheme' => 'https'))); | ||
261 | $this->assertEquals('https://localhost/app.php/', $this->getGenerator($routes)->generate('test')); | ||
262 | |||
263 | $routes = $this->getRoutes('test', new Route('/', array(), array('_scheme' => 'http'))); | ||
264 | $this->assertEquals('http://localhost/app.php/', $this->getGenerator($routes, array('scheme' => 'https'))->generate('test')); | ||
265 | } | ||
266 | |||
267 | public function testPathWithTwoStartingSlashes() | ||
268 | { | ||
269 | $routes = $this->getRoutes('test', new Route('//path-and-not-domain')); | ||
270 | |||
271 | // this must not generate '//path-and-not-domain' because that would be a network path | ||
272 | $this->assertSame('/path-and-not-domain', $this->getGenerator($routes, array('BaseUrl' => ''))->generate('test')); | ||
273 | } | ||
274 | |||
275 | public function testNoTrailingSlashForMultipleOptionalParameters() | ||
276 | { | ||
277 | $routes = $this->getRoutes('test', new Route('/category/{slug1}/{slug2}/{slug3}', array('slug2' => null, 'slug3' => null))); | ||
278 | |||
279 | $this->assertEquals('/app.php/category/foo', $this->getGenerator($routes)->generate('test', array('slug1' => 'foo'))); | ||
280 | } | ||
281 | |||
282 | public function testWithAnIntegerAsADefaultValue() | ||
283 | { | ||
284 | $routes = $this->getRoutes('test', new Route('/{default}', array('default' => 0))); | ||
285 | |||
286 | $this->assertEquals('/app.php/foo', $this->getGenerator($routes)->generate('test', array('default' => 'foo'))); | ||
287 | } | ||
288 | |||
289 | public function testNullForOptionalParameterIsIgnored() | ||
290 | { | ||
291 | $routes = $this->getRoutes('test', new Route('/test/{default}', array('default' => 0))); | ||
292 | |||
293 | $this->assertEquals('/app.php/test', $this->getGenerator($routes)->generate('test', array('default' => null))); | ||
294 | } | ||
295 | |||
296 | public function testQueryParamSameAsDefault() | ||
297 | { | ||
298 | $routes = $this->getRoutes('test', new Route('/test', array('default' => 'value'))); | ||
299 | |||
300 | $this->assertSame('/app.php/test', $this->getGenerator($routes)->generate('test', array('default' => 'foo'))); | ||
301 | $this->assertSame('/app.php/test', $this->getGenerator($routes)->generate('test', array('default' => 'value'))); | ||
302 | $this->assertSame('/app.php/test', $this->getGenerator($routes)->generate('test')); | ||
303 | } | ||
304 | |||
305 | public function testGenerateWithSpecialRouteName() | ||
306 | { | ||
307 | $routes = $this->getRoutes('$péß^a|', new Route('/bar')); | ||
308 | |||
309 | $this->assertSame('/app.php/bar', $this->getGenerator($routes)->generate('$péß^a|')); | ||
310 | } | ||
311 | |||
312 | public function testUrlEncoding() | ||
313 | { | ||
314 | // This tests the encoding of reserved characters that are used for delimiting of URI components (defined in RFC 3986) | ||
315 | // and other special ASCII chars. These chars are tested as static text path, variable path and query param. | ||
316 | $chars = '@:[]/()*\'" +,;-._~&$<>|{}%\\^`!?foo=bar#id'; | ||
317 | $routes = $this->getRoutes('test', new Route("/$chars/{varpath}", array(), array('varpath' => '.+'))); | ||
318 | $this->assertSame('/app.php/@:%5B%5D/%28%29*%27%22%20+,;-._~%26%24%3C%3E|%7B%7D%25%5C%5E%60!%3Ffoo=bar%23id' | ||
319 | .'/@:%5B%5D/%28%29*%27%22%20+,;-._~%26%24%3C%3E|%7B%7D%25%5C%5E%60!%3Ffoo=bar%23id' | ||
320 | .'?query=%40%3A%5B%5D%2F%28%29%2A%27%22+%2B%2C%3B-._%7E%26%24%3C%3E%7C%7B%7D%25%5C%5E%60%21%3Ffoo%3Dbar%23id', | ||
321 | $this->getGenerator($routes)->generate('test', array( | ||
322 | 'varpath' => $chars, | ||
323 | 'query' => $chars | ||
324 | )) | ||
325 | ); | ||
326 | } | ||
327 | |||
328 | public function testEncodingOfRelativePathSegments() | ||
329 | { | ||
330 | $routes = $this->getRoutes('test', new Route('/dir/../dir/..')); | ||
331 | $this->assertSame('/app.php/dir/%2E%2E/dir/%2E%2E', $this->getGenerator($routes)->generate('test')); | ||
332 | $routes = $this->getRoutes('test', new Route('/dir/./dir/.')); | ||
333 | $this->assertSame('/app.php/dir/%2E/dir/%2E', $this->getGenerator($routes)->generate('test')); | ||
334 | $routes = $this->getRoutes('test', new Route('/a./.a/a../..a/...')); | ||
335 | $this->assertSame('/app.php/a./.a/a../..a/...', $this->getGenerator($routes)->generate('test')); | ||
336 | } | ||
337 | |||
338 | public function testAdjacentVariables() | ||
339 | { | ||
340 | $routes = $this->getRoutes('test', new Route('/{x}{y}{z}.{_format}', array('z' => 'default-z', '_format' => 'html'), array('y' => '\d+'))); | ||
341 | $generator = $this->getGenerator($routes); | ||
342 | $this->assertSame('/app.php/foo123', $generator->generate('test', array('x' => 'foo', 'y' => '123'))); | ||
343 | $this->assertSame('/app.php/foo123bar.xml', $generator->generate('test', array('x' => 'foo', 'y' => '123', 'z' => 'bar', '_format' => 'xml'))); | ||
344 | |||
345 | // The default requirement for 'x' should not allow the separator '.' in this case because it would otherwise match everything | ||
346 | // and following optional variables like _format could never match. | ||
347 | $this->setExpectedException('Symfony\Component\Routing\Exception\InvalidParameterException'); | ||
348 | $generator->generate('test', array('x' => 'do.t', 'y' => '123', 'z' => 'bar', '_format' => 'xml')); | ||
349 | } | ||
350 | |||
351 | public function testOptionalVariableWithNoRealSeparator() | ||
352 | { | ||
353 | $routes = $this->getRoutes('test', new Route('/get{what}', array('what' => 'All'))); | ||
354 | $generator = $this->getGenerator($routes); | ||
355 | |||
356 | $this->assertSame('/app.php/get', $generator->generate('test')); | ||
357 | $this->assertSame('/app.php/getSites', $generator->generate('test', array('what' => 'Sites'))); | ||
358 | } | ||
359 | |||
360 | public function testRequiredVariableWithNoRealSeparator() | ||
361 | { | ||
362 | $routes = $this->getRoutes('test', new Route('/get{what}Suffix')); | ||
363 | $generator = $this->getGenerator($routes); | ||
364 | |||
365 | $this->assertSame('/app.php/getSitesSuffix', $generator->generate('test', array('what' => 'Sites'))); | ||
366 | } | ||
367 | |||
368 | public function testDefaultRequirementOfVariable() | ||
369 | { | ||
370 | $routes = $this->getRoutes('test', new Route('/{page}.{_format}')); | ||
371 | $generator = $this->getGenerator($routes); | ||
372 | |||
373 | $this->assertSame('/app.php/index.mobile.html', $generator->generate('test', array('page' => 'index', '_format' => 'mobile.html'))); | ||
374 | } | ||
375 | |||
376 | /** | ||
377 | * @expectedException \Symfony\Component\Routing\Exception\InvalidParameterException | ||
378 | */ | ||
379 | public function testDefaultRequirementOfVariableDisallowsSlash() | ||
380 | { | ||
381 | $routes = $this->getRoutes('test', new Route('/{page}.{_format}')); | ||
382 | $this->getGenerator($routes)->generate('test', array('page' => 'index', '_format' => 'sl/ash')); | ||
383 | } | ||
384 | |||
385 | /** | ||
386 | * @expectedException \Symfony\Component\Routing\Exception\InvalidParameterException | ||
387 | */ | ||
388 | public function testDefaultRequirementOfVariableDisallowsNextSeparator() | ||
389 | { | ||
390 | $routes = $this->getRoutes('test', new Route('/{page}.{_format}')); | ||
391 | $this->getGenerator($routes)->generate('test', array('page' => 'do.t', '_format' => 'html')); | ||
392 | } | ||
393 | |||
394 | public function testWithHostDifferentFromContext() | ||
395 | { | ||
396 | $routes = $this->getRoutes('test', new Route('/{name}', array(), array(), array(), '{locale}.example.com')); | ||
397 | |||
398 | $this->assertEquals('//fr.example.com/app.php/Fabien', $this->getGenerator($routes)->generate('test', array('name' =>'Fabien', 'locale' => 'fr'))); | ||
399 | } | ||
400 | |||
401 | public function testWithHostSameAsContext() | ||
402 | { | ||
403 | $routes = $this->getRoutes('test', new Route('/{name}', array(), array(), array(), '{locale}.example.com')); | ||
404 | |||
405 | $this->assertEquals('/app.php/Fabien', $this->getGenerator($routes, array('host' => 'fr.example.com'))->generate('test', array('name' =>'Fabien', 'locale' => 'fr'))); | ||
406 | } | ||
407 | |||
408 | public function testWithHostSameAsContextAndAbsolute() | ||
409 | { | ||
410 | $routes = $this->getRoutes('test', new Route('/{name}', array(), array(), array(), '{locale}.example.com')); | ||
411 | |||
412 | $this->assertEquals('http://fr.example.com/app.php/Fabien', $this->getGenerator($routes, array('host' => 'fr.example.com'))->generate('test', array('name' =>'Fabien', 'locale' => 'fr'), true)); | ||
413 | } | ||
414 | |||
415 | /** | ||
416 | * @expectedException \Symfony\Component\Routing\Exception\InvalidParameterException | ||
417 | */ | ||
418 | public function testUrlWithInvalidParameterInHost() | ||
419 | { | ||
420 | $routes = $this->getRoutes('test', new Route('/', array(), array('foo' => 'bar'), array(), '{foo}.example.com')); | ||
421 | $this->getGenerator($routes)->generate('test', array('foo' => 'baz'), false); | ||
422 | } | ||
423 | |||
424 | /** | ||
425 | * @expectedException \Symfony\Component\Routing\Exception\InvalidParameterException | ||
426 | */ | ||
427 | public function testUrlWithInvalidParameterInHostWhenParamHasADefaultValue() | ||
428 | { | ||
429 | $routes = $this->getRoutes('test', new Route('/', array('foo' => 'bar'), array('foo' => 'bar'), array(), '{foo}.example.com')); | ||
430 | $this->getGenerator($routes)->generate('test', array('foo' => 'baz'), false); | ||
431 | } | ||
432 | |||
433 | /** | ||
434 | * @expectedException \Symfony\Component\Routing\Exception\InvalidParameterException | ||
435 | */ | ||
436 | public function testUrlWithInvalidParameterEqualsDefaultValueInHost() | ||
437 | { | ||
438 | $routes = $this->getRoutes('test', new Route('/', array('foo' => 'baz'), array('foo' => 'bar'), array(), '{foo}.example.com')); | ||
439 | $this->getGenerator($routes)->generate('test', array('foo' => 'baz'), false); | ||
440 | } | ||
441 | |||
442 | public function testUrlWithInvalidParameterInHostInNonStrictMode() | ||
443 | { | ||
444 | $routes = $this->getRoutes('test', new Route('/', array(), array('foo' => 'bar'), array(), '{foo}.example.com')); | ||
445 | $generator = $this->getGenerator($routes); | ||
446 | $generator->setStrictRequirements(false); | ||
447 | $this->assertNull($generator->generate('test', array('foo' => 'baz'), false)); | ||
448 | } | ||
449 | |||
450 | public function testGenerateNetworkPath() | ||
451 | { | ||
452 | $routes = $this->getRoutes('test', new Route('/{name}', array(), array('_scheme' => 'http'), array(), '{locale}.example.com')); | ||
453 | |||
454 | $this->assertSame('//fr.example.com/app.php/Fabien', $this->getGenerator($routes)->generate('test', | ||
455 | array('name' =>'Fabien', 'locale' => 'fr'), UrlGeneratorInterface::NETWORK_PATH), 'network path with different host' | ||
456 | ); | ||
457 | $this->assertSame('//fr.example.com/app.php/Fabien?query=string', $this->getGenerator($routes, array('host' => 'fr.example.com'))->generate('test', | ||
458 | array('name' =>'Fabien', 'locale' => 'fr', 'query' => 'string'), UrlGeneratorInterface::NETWORK_PATH), 'network path although host same as context' | ||
459 | ); | ||
460 | $this->assertSame('http://fr.example.com/app.php/Fabien', $this->getGenerator($routes, array('scheme' => 'https'))->generate('test', | ||
461 | array('name' =>'Fabien', 'locale' => 'fr'), UrlGeneratorInterface::NETWORK_PATH), 'absolute URL because scheme requirement does not match context' | ||
462 | ); | ||
463 | $this->assertSame('http://fr.example.com/app.php/Fabien', $this->getGenerator($routes)->generate('test', | ||
464 | array('name' =>'Fabien', 'locale' => 'fr'), UrlGeneratorInterface::ABSOLUTE_URL), 'absolute URL with same scheme because it is requested' | ||
465 | ); | ||
466 | } | ||
467 | |||
468 | public function testGenerateRelativePath() | ||
469 | { | ||
470 | $routes = new RouteCollection(); | ||
471 | $routes->add('article', new Route('/{author}/{article}/')); | ||
472 | $routes->add('comments', new Route('/{author}/{article}/comments')); | ||
473 | $routes->add('host', new Route('/{article}', array(), array(), array(), '{author}.example.com')); | ||
474 | $routes->add('scheme', new Route('/{author}', array(), array('_scheme' => 'https'))); | ||
475 | $routes->add('unrelated', new Route('/about')); | ||
476 | |||
477 | $generator = $this->getGenerator($routes, array('host' => 'example.com', 'pathInfo' => '/fabien/symfony-is-great/')); | ||
478 | |||
479 | $this->assertSame('comments', $generator->generate('comments', | ||
480 | array('author' =>'fabien', 'article' => 'symfony-is-great'), UrlGeneratorInterface::RELATIVE_PATH) | ||
481 | ); | ||
482 | $this->assertSame('comments?page=2', $generator->generate('comments', | ||
483 | array('author' =>'fabien', 'article' => 'symfony-is-great', 'page' => 2), UrlGeneratorInterface::RELATIVE_PATH) | ||
484 | ); | ||
485 | $this->assertSame('../twig-is-great/', $generator->generate('article', | ||
486 | array('author' =>'fabien', 'article' => 'twig-is-great'), UrlGeneratorInterface::RELATIVE_PATH) | ||
487 | ); | ||
488 | $this->assertSame('../../bernhard/forms-are-great/', $generator->generate('article', | ||
489 | array('author' =>'bernhard', 'article' => 'forms-are-great'), UrlGeneratorInterface::RELATIVE_PATH) | ||
490 | ); | ||
491 | $this->assertSame('//bernhard.example.com/app.php/forms-are-great', $generator->generate('host', | ||
492 | array('author' =>'bernhard', 'article' => 'forms-are-great'), UrlGeneratorInterface::RELATIVE_PATH) | ||
493 | ); | ||
494 | $this->assertSame('https://example.com/app.php/bernhard', $generator->generate('scheme', | ||
495 | array('author' =>'bernhard'), UrlGeneratorInterface::RELATIVE_PATH) | ||
496 | ); | ||
497 | $this->assertSame('../../about', $generator->generate('unrelated', | ||
498 | array(), UrlGeneratorInterface::RELATIVE_PATH) | ||
499 | ); | ||
500 | } | ||
501 | |||
502 | /** | ||
503 | * @dataProvider provideRelativePaths | ||
504 | */ | ||
505 | public function testGetRelativePath($sourcePath, $targetPath, $expectedPath) | ||
506 | { | ||
507 | $this->assertSame($expectedPath, UrlGenerator::getRelativePath($sourcePath, $targetPath)); | ||
508 | } | ||
509 | |||
510 | public function provideRelativePaths() | ||
511 | { | ||
512 | return array( | ||
513 | array( | ||
514 | '/same/dir/', | ||
515 | '/same/dir/', | ||
516 | '' | ||
517 | ), | ||
518 | array( | ||
519 | '/same/file', | ||
520 | '/same/file', | ||
521 | '' | ||
522 | ), | ||
523 | array( | ||
524 | '/', | ||
525 | '/file', | ||
526 | 'file' | ||
527 | ), | ||
528 | array( | ||
529 | '/', | ||
530 | '/dir/file', | ||
531 | 'dir/file' | ||
532 | ), | ||
533 | array( | ||
534 | '/dir/file.html', | ||
535 | '/dir/different-file.html', | ||
536 | 'different-file.html' | ||
537 | ), | ||
538 | array( | ||
539 | '/same/dir/extra-file', | ||
540 | '/same/dir/', | ||
541 | './' | ||
542 | ), | ||
543 | array( | ||
544 | '/parent/dir/', | ||
545 | '/parent/', | ||
546 | '../' | ||
547 | ), | ||
548 | array( | ||
549 | '/parent/dir/extra-file', | ||
550 | '/parent/', | ||
551 | '../' | ||
552 | ), | ||
553 | array( | ||
554 | '/a/b/', | ||
555 | '/x/y/z/', | ||
556 | '../../x/y/z/' | ||
557 | ), | ||
558 | array( | ||
559 | '/a/b/c/d/e', | ||
560 | '/a/c/d', | ||
561 | '../../../c/d' | ||
562 | ), | ||
563 | array( | ||
564 | '/a/b/c//', | ||
565 | '/a/b/c/', | ||
566 | '../' | ||
567 | ), | ||
568 | array( | ||
569 | '/a/b/c/', | ||
570 | '/a/b/c//', | ||
571 | './/' | ||
572 | ), | ||
573 | array( | ||
574 | '/root/a/b/c/', | ||
575 | '/root/x/b/c/', | ||
576 | '../../../x/b/c/' | ||
577 | ), | ||
578 | array( | ||
579 | '/a/b/c/d/', | ||
580 | '/a', | ||
581 | '../../../../a' | ||
582 | ), | ||
583 | array( | ||
584 | '/special-chars/sp%20ce/1€/mäh/e=mc²', | ||
585 | '/special-chars/sp%20ce/1€/<µ>/e=mc²', | ||
586 | '../<µ>/e=mc²' | ||
587 | ), | ||
588 | array( | ||
589 | 'not-rooted', | ||
590 | 'dir/file', | ||
591 | 'dir/file' | ||
592 | ), | ||
593 | array( | ||
594 | '//dir/', | ||
595 | '', | ||
596 | '../../' | ||
597 | ), | ||
598 | array( | ||
599 | '/dir/', | ||
600 | '/dir/file:with-colon', | ||
601 | './file:with-colon' | ||
602 | ), | ||
603 | array( | ||
604 | '/dir/', | ||
605 | '/dir/subdir/file:with-colon', | ||
606 | 'subdir/file:with-colon' | ||
607 | ), | ||
608 | array( | ||
609 | '/dir/', | ||
610 | '/dir/:subdir/', | ||
611 | './:subdir/' | ||
612 | ), | ||
613 | ); | ||
614 | } | ||
615 | |||
616 | protected function getGenerator(RouteCollection $routes, array $parameters = array(), $logger = null) | ||
617 | { | ||
618 | $context = new RequestContext('/app.php'); | ||
619 | foreach ($parameters as $key => $value) { | ||
620 | $method = 'set'.$key; | ||
621 | $context->$method($value); | ||
622 | } | ||
623 | $generator = new UrlGenerator($routes, $context, $logger); | ||
624 | |||
625 | return $generator; | ||
626 | } | ||
627 | |||
628 | protected function getRoutes($name, Route $route) | ||
629 | { | ||
630 | $routes = new RouteCollection(); | ||
631 | $routes->add($name, $route); | ||
632 | |||
633 | return $routes; | ||
634 | } | ||
635 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Tests/Loader/AbstractAnnotationLoaderTest.php b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Loader/AbstractAnnotationLoaderTest.php new file mode 100644 index 00000000..c927ae4a --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Loader/AbstractAnnotationLoaderTest.php | |||
@@ -0,0 +1,38 @@ | |||
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\Tests\Loader; | ||
13 | |||
14 | abstract class AbstractAnnotationLoaderTest extends \PHPUnit_Framework_TestCase | ||
15 | { | ||
16 | protected function setUp() | ||
17 | { | ||
18 | if (!class_exists('Doctrine\\Common\\Version')) { | ||
19 | $this->markTestSkipped('Doctrine is not available.'); | ||
20 | } | ||
21 | } | ||
22 | |||
23 | public function getReader() | ||
24 | { | ||
25 | return $this->getMockBuilder('Doctrine\Common\Annotations\Reader') | ||
26 | ->disableOriginalConstructor() | ||
27 | ->getMock() | ||
28 | ; | ||
29 | } | ||
30 | |||
31 | public function getClassLoader($reader) | ||
32 | { | ||
33 | return $this->getMockBuilder('Symfony\Component\Routing\Loader\AnnotationClassLoader') | ||
34 | ->setConstructorArgs(array($reader)) | ||
35 | ->getMockForAbstractClass() | ||
36 | ; | ||
37 | } | ||
38 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Tests/Loader/AnnotationClassLoaderTest.php b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Loader/AnnotationClassLoaderTest.php new file mode 100644 index 00000000..31c43f58 --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Loader/AnnotationClassLoaderTest.php | |||
@@ -0,0 +1,119 @@ | |||
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\Tests\Loader; | ||
13 | |||
14 | class AnnotationClassLoaderTest extends AbstractAnnotationLoaderTest | ||
15 | { | ||
16 | protected $loader; | ||
17 | |||
18 | protected function setUp() | ||
19 | { | ||
20 | parent::setUp(); | ||
21 | |||
22 | $this->reader = $this->getReader(); | ||
23 | $this->loader = $this->getClassLoader($this->reader); | ||
24 | } | ||
25 | |||
26 | /** | ||
27 | * @expectedException \InvalidArgumentException | ||
28 | */ | ||
29 | public function testLoadMissingClass() | ||
30 | { | ||
31 | $this->loader->load('MissingClass'); | ||
32 | } | ||
33 | |||
34 | /** | ||
35 | * @expectedException \InvalidArgumentException | ||
36 | */ | ||
37 | public function testLoadAbstractClass() | ||
38 | { | ||
39 | $this->loader->load('Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses\AbstractClass'); | ||
40 | } | ||
41 | |||
42 | /** | ||
43 | * @dataProvider provideTestSupportsChecksResource | ||
44 | */ | ||
45 | public function testSupportsChecksResource($resource, $expectedSupports) | ||
46 | { | ||
47 | $this->assertSame($expectedSupports, $this->loader->supports($resource), '->supports() returns true if the resource is loadable'); | ||
48 | } | ||
49 | |||
50 | public function provideTestSupportsChecksResource() | ||
51 | { | ||
52 | return array( | ||
53 | array('class', true), | ||
54 | array('\fully\qualified\class\name', true), | ||
55 | array('namespaced\class\without\leading\slash', true), | ||
56 | array('ÿClassWithLegalSpecialCharacters', true), | ||
57 | array('5', false), | ||
58 | array('foo.foo', false), | ||
59 | array(null, false), | ||
60 | ); | ||
61 | } | ||
62 | |||
63 | public function testSupportsChecksTypeIfSpecified() | ||
64 | { | ||
65 | $this->assertTrue($this->loader->supports('class', 'annotation'), '->supports() checks the resource type if specified'); | ||
66 | $this->assertFalse($this->loader->supports('class', 'foo'), '->supports() checks the resource type if specified'); | ||
67 | } | ||
68 | |||
69 | public function getLoadTests() | ||
70 | { | ||
71 | return array( | ||
72 | array( | ||
73 | 'Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses\BarClass', | ||
74 | array('name'=>'route1'), | ||
75 | array('arg2' => 'defaultValue2', 'arg3' =>'defaultValue3') | ||
76 | ), | ||
77 | array( | ||
78 | 'Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses\BarClass', | ||
79 | array('name'=>'route1', 'defaults' => array('arg2' => 'foo')), | ||
80 | array('arg2' => 'defaultValue2', 'arg3' =>'defaultValue3') | ||
81 | ), | ||
82 | ); | ||
83 | } | ||
84 | |||
85 | /** | ||
86 | * @dataProvider getLoadTests | ||
87 | */ | ||
88 | public function testLoad($className, $routeDatas = array(), $methodArgs = array()) | ||
89 | { | ||
90 | $routeDatas = array_replace(array( | ||
91 | 'name' => 'route', | ||
92 | 'path' => '/', | ||
93 | 'requirements' => array(), | ||
94 | 'options' => array(), | ||
95 | 'defaults' => array(), | ||
96 | 'schemes' => array(), | ||
97 | 'methods' => array(), | ||
98 | ), $routeDatas); | ||
99 | |||
100 | $this->reader | ||
101 | ->expects($this->once()) | ||
102 | ->method('getMethodAnnotations') | ||
103 | ->will($this->returnValue(array($this->getAnnotatedRoute($routeDatas)))) | ||
104 | ; | ||
105 | $routeCollection = $this->loader->load($className); | ||
106 | $route = $routeCollection->get($routeDatas['name']); | ||
107 | |||
108 | $this->assertSame($routeDatas['path'], $route->getPath(), '->load preserves path annotation'); | ||
109 | $this->assertSame($routeDatas['requirements'],$route->getRequirements(), '->load preserves requirements annotation'); | ||
110 | $this->assertCount(0, array_intersect($route->getOptions(), $routeDatas['options']), '->load preserves options annotation'); | ||
111 | $this->assertSame(array_replace($routeDatas['defaults'], $methodArgs), $route->getDefaults(), '->load preserves defaults annotation'); | ||
112 | } | ||
113 | |||
114 | private function getAnnotatedRoute($datas) | ||
115 | { | ||
116 | return new \Symfony\Component\Routing\Annotation\Route($datas); | ||
117 | } | ||
118 | |||
119 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Tests/Loader/AnnotationDirectoryLoaderTest.php b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Loader/AnnotationDirectoryLoaderTest.php new file mode 100644 index 00000000..29126ba4 --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Loader/AnnotationDirectoryLoaderTest.php | |||
@@ -0,0 +1,53 @@ | |||
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\Tests\Loader; | ||
13 | |||
14 | use Symfony\Component\Routing\Loader\AnnotationDirectoryLoader; | ||
15 | use Symfony\Component\Config\FileLocator; | ||
16 | |||
17 | class AnnotationDirectoryLoaderTest extends AbstractAnnotationLoaderTest | ||
18 | { | ||
19 | protected $loader; | ||
20 | protected $reader; | ||
21 | |||
22 | protected function setUp() | ||
23 | { | ||
24 | parent::setUp(); | ||
25 | |||
26 | $this->reader = $this->getReader(); | ||
27 | $this->loader = new AnnotationDirectoryLoader(new FileLocator(), $this->getClassLoader($this->reader)); | ||
28 | } | ||
29 | |||
30 | public function testLoad() | ||
31 | { | ||
32 | $this->reader->expects($this->exactly(2))->method('getClassAnnotation'); | ||
33 | |||
34 | $this->reader | ||
35 | ->expects($this->any()) | ||
36 | ->method('getMethodAnnotations') | ||
37 | ->will($this->returnValue(array())) | ||
38 | ; | ||
39 | |||
40 | $this->loader->load(__DIR__.'/../Fixtures/AnnotatedClasses'); | ||
41 | } | ||
42 | |||
43 | public function testSupports() | ||
44 | { | ||
45 | $fixturesDir = __DIR__.'/../Fixtures'; | ||
46 | |||
47 | $this->assertTrue($this->loader->supports($fixturesDir), '->supports() returns true if the resource is loadable'); | ||
48 | $this->assertFalse($this->loader->supports('foo.foo'), '->supports() returns true if the resource is loadable'); | ||
49 | |||
50 | $this->assertTrue($this->loader->supports($fixturesDir, 'annotation'), '->supports() checks the resource type if specified'); | ||
51 | $this->assertFalse($this->loader->supports($fixturesDir, 'foo'), '->supports() checks the resource type if specified'); | ||
52 | } | ||
53 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Tests/Loader/AnnotationFileLoaderTest.php b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Loader/AnnotationFileLoaderTest.php new file mode 100644 index 00000000..f0a8a0e3 --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Loader/AnnotationFileLoaderTest.php | |||
@@ -0,0 +1,47 @@ | |||
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\Tests\Loader; | ||
13 | |||
14 | use Symfony\Component\Routing\Loader\AnnotationFileLoader; | ||
15 | use Symfony\Component\Config\FileLocator; | ||
16 | |||
17 | class AnnotationFileLoaderTest extends AbstractAnnotationLoaderTest | ||
18 | { | ||
19 | protected $loader; | ||
20 | protected $reader; | ||
21 | |||
22 | protected function setUp() | ||
23 | { | ||
24 | parent::setUp(); | ||
25 | |||
26 | $this->reader = $this->getReader(); | ||
27 | $this->loader = new AnnotationFileLoader(new FileLocator(), $this->getClassLoader($this->reader)); | ||
28 | } | ||
29 | |||
30 | public function testLoad() | ||
31 | { | ||
32 | $this->reader->expects($this->once())->method('getClassAnnotation'); | ||
33 | |||
34 | $this->loader->load(__DIR__.'/../Fixtures/AnnotatedClasses/FooClass.php'); | ||
35 | } | ||
36 | |||
37 | public function testSupports() | ||
38 | { | ||
39 | $fixture = __DIR__.'/../Fixtures/annotated.php'; | ||
40 | |||
41 | $this->assertTrue($this->loader->supports($fixture), '->supports() returns true if the resource is loadable'); | ||
42 | $this->assertFalse($this->loader->supports('foo.foo'), '->supports() returns true if the resource is loadable'); | ||
43 | |||
44 | $this->assertTrue($this->loader->supports($fixture, 'annotation'), '->supports() checks the resource type if specified'); | ||
45 | $this->assertFalse($this->loader->supports($fixture, 'foo'), '->supports() checks the resource type if specified'); | ||
46 | } | ||
47 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Tests/Loader/ClosureLoaderTest.php b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Loader/ClosureLoaderTest.php new file mode 100644 index 00000000..64d1b086 --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Loader/ClosureLoaderTest.php | |||
@@ -0,0 +1,55 @@ | |||
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\Tests\Loader; | ||
13 | |||
14 | use Symfony\Component\Routing\Loader\ClosureLoader; | ||
15 | use Symfony\Component\Routing\Route; | ||
16 | use Symfony\Component\Routing\RouteCollection; | ||
17 | |||
18 | class ClosureLoaderTest extends \PHPUnit_Framework_TestCase | ||
19 | { | ||
20 | protected function setUp() | ||
21 | { | ||
22 | if (!class_exists('Symfony\Component\Config\FileLocator')) { | ||
23 | $this->markTestSkipped('The "Config" component is not available'); | ||
24 | } | ||
25 | } | ||
26 | |||
27 | public function testSupports() | ||
28 | { | ||
29 | $loader = new ClosureLoader(); | ||
30 | |||
31 | $closure = function () {}; | ||
32 | |||
33 | $this->assertTrue($loader->supports($closure), '->supports() returns true if the resource is loadable'); | ||
34 | $this->assertFalse($loader->supports('foo.foo'), '->supports() returns true if the resource is loadable'); | ||
35 | |||
36 | $this->assertTrue($loader->supports($closure, 'closure'), '->supports() checks the resource type if specified'); | ||
37 | $this->assertFalse($loader->supports($closure, 'foo'), '->supports() checks the resource type if specified'); | ||
38 | } | ||
39 | |||
40 | public function testLoad() | ||
41 | { | ||
42 | $loader = new ClosureLoader(); | ||
43 | |||
44 | $route = new Route('/'); | ||
45 | $routes = $loader->load(function () use ($route) { | ||
46 | $routes = new RouteCollection(); | ||
47 | |||
48 | $routes->add('foo', $route); | ||
49 | |||
50 | return $routes; | ||
51 | }); | ||
52 | |||
53 | $this->assertEquals($route, $routes->get('foo'), '->load() loads a \Closure resource'); | ||
54 | } | ||
55 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Tests/Loader/PhpFileLoaderTest.php b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Loader/PhpFileLoaderTest.php new file mode 100644 index 00000000..18b166fc --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Loader/PhpFileLoaderTest.php | |||
@@ -0,0 +1,55 @@ | |||
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\Tests\Loader; | ||
13 | |||
14 | use Symfony\Component\Config\FileLocator; | ||
15 | use Symfony\Component\Routing\Loader\PhpFileLoader; | ||
16 | |||
17 | class PhpFileLoaderTest extends \PHPUnit_Framework_TestCase | ||
18 | { | ||
19 | protected function setUp() | ||
20 | { | ||
21 | if (!class_exists('Symfony\Component\Config\FileLocator')) { | ||
22 | $this->markTestSkipped('The "Config" component is not available'); | ||
23 | } | ||
24 | } | ||
25 | |||
26 | public function testSupports() | ||
27 | { | ||
28 | $loader = new PhpFileLoader($this->getMock('Symfony\Component\Config\FileLocator')); | ||
29 | |||
30 | $this->assertTrue($loader->supports('foo.php'), '->supports() returns true if the resource is loadable'); | ||
31 | $this->assertFalse($loader->supports('foo.foo'), '->supports() returns true if the resource is loadable'); | ||
32 | |||
33 | $this->assertTrue($loader->supports('foo.php', 'php'), '->supports() checks the resource type if specified'); | ||
34 | $this->assertFalse($loader->supports('foo.php', 'foo'), '->supports() checks the resource type if specified'); | ||
35 | } | ||
36 | |||
37 | public function testLoadWithRoute() | ||
38 | { | ||
39 | $loader = new PhpFileLoader(new FileLocator(array(__DIR__.'/../Fixtures'))); | ||
40 | $routeCollection = $loader->load('validpattern.php'); | ||
41 | $routes = $routeCollection->all(); | ||
42 | |||
43 | $this->assertCount(2, $routes, 'Two routes are loaded'); | ||
44 | $this->assertContainsOnly('Symfony\Component\Routing\Route', $routes); | ||
45 | |||
46 | foreach ($routes as $route) { | ||
47 | $this->assertSame('/blog/{slug}', $route->getPath()); | ||
48 | $this->assertSame('MyBlogBundle:Blog:show', $route->getDefault('_controller')); | ||
49 | $this->assertSame('{locale}.example.com', $route->getHost()); | ||
50 | $this->assertSame('RouteCompiler', $route->getOption('compiler_class')); | ||
51 | $this->assertEquals(array('GET', 'POST', 'PUT', 'OPTIONS'), $route->getMethods()); | ||
52 | $this->assertEquals(array('https'), $route->getSchemes()); | ||
53 | } | ||
54 | } | ||
55 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Tests/Loader/XmlFileLoaderTest.php b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Loader/XmlFileLoaderTest.php new file mode 100644 index 00000000..9f038c16 --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Loader/XmlFileLoaderTest.php | |||
@@ -0,0 +1,127 @@ | |||
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\Tests\Loader; | ||
13 | |||
14 | use Symfony\Component\Config\FileLocator; | ||
15 | use Symfony\Component\Routing\Loader\XmlFileLoader; | ||
16 | use Symfony\Component\Routing\Tests\Fixtures\CustomXmlFileLoader; | ||
17 | |||
18 | class XmlFileLoaderTest extends \PHPUnit_Framework_TestCase | ||
19 | { | ||
20 | protected function setUp() | ||
21 | { | ||
22 | if (!class_exists('Symfony\Component\Config\FileLocator')) { | ||
23 | $this->markTestSkipped('The "Config" component is not available'); | ||
24 | } | ||
25 | } | ||
26 | |||
27 | public function testSupports() | ||
28 | { | ||
29 | $loader = new XmlFileLoader($this->getMock('Symfony\Component\Config\FileLocator')); | ||
30 | |||
31 | $this->assertTrue($loader->supports('foo.xml'), '->supports() returns true if the resource is loadable'); | ||
32 | $this->assertFalse($loader->supports('foo.foo'), '->supports() returns true if the resource is loadable'); | ||
33 | |||
34 | $this->assertTrue($loader->supports('foo.xml', 'xml'), '->supports() checks the resource type if specified'); | ||
35 | $this->assertFalse($loader->supports('foo.xml', 'foo'), '->supports() checks the resource type if specified'); | ||
36 | } | ||
37 | |||
38 | public function testLoadWithRoute() | ||
39 | { | ||
40 | $loader = new XmlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures'))); | ||
41 | $routeCollection = $loader->load('validpattern.xml'); | ||
42 | $routes = $routeCollection->all(); | ||
43 | |||
44 | $this->assertCount(2, $routes, 'Two routes are loaded'); | ||
45 | $this->assertContainsOnly('Symfony\Component\Routing\Route', $routes); | ||
46 | |||
47 | foreach ($routes as $route) { | ||
48 | $this->assertSame('/blog/{slug}', $route->getPath()); | ||
49 | $this->assertSame('{locale}.example.com', $route->getHost()); | ||
50 | $this->assertSame('MyBundle:Blog:show', $route->getDefault('_controller')); | ||
51 | $this->assertSame('\w+', $route->getRequirement('locale')); | ||
52 | $this->assertSame('RouteCompiler', $route->getOption('compiler_class')); | ||
53 | $this->assertEquals(array('GET', 'POST', 'PUT', 'OPTIONS'), $route->getMethods()); | ||
54 | $this->assertEquals(array('https'), $route->getSchemes()); | ||
55 | } | ||
56 | } | ||
57 | |||
58 | public function testLoadWithNamespacePrefix() | ||
59 | { | ||
60 | $loader = new XmlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures'))); | ||
61 | $routeCollection = $loader->load('namespaceprefix.xml'); | ||
62 | |||
63 | $this->assertCount(1, $routeCollection->all(), 'One route is loaded'); | ||
64 | |||
65 | $route = $routeCollection->get('blog_show'); | ||
66 | $this->assertSame('/blog/{slug}', $route->getPath()); | ||
67 | $this->assertSame('{_locale}.example.com', $route->getHost()); | ||
68 | $this->assertSame('MyBundle:Blog:show', $route->getDefault('_controller')); | ||
69 | $this->assertSame('\w+', $route->getRequirement('slug')); | ||
70 | $this->assertSame('en|fr|de', $route->getRequirement('_locale')); | ||
71 | $this->assertSame(null, $route->getDefault('slug')); | ||
72 | $this->assertSame('RouteCompiler', $route->getOption('compiler_class')); | ||
73 | } | ||
74 | |||
75 | public function testLoadWithImport() | ||
76 | { | ||
77 | $loader = new XmlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures'))); | ||
78 | $routeCollection = $loader->load('validresource.xml'); | ||
79 | $routes = $routeCollection->all(); | ||
80 | |||
81 | $this->assertCount(2, $routes, 'Two routes are loaded'); | ||
82 | $this->assertContainsOnly('Symfony\Component\Routing\Route', $routes); | ||
83 | |||
84 | foreach ($routes as $route) { | ||
85 | $this->assertSame('/{foo}/blog/{slug}', $route->getPath()); | ||
86 | $this->assertSame('123', $route->getDefault('foo')); | ||
87 | $this->assertSame('\d+', $route->getRequirement('foo')); | ||
88 | $this->assertSame('bar', $route->getOption('foo')); | ||
89 | $this->assertSame('', $route->getHost()); | ||
90 | } | ||
91 | } | ||
92 | |||
93 | /** | ||
94 | * @expectedException \InvalidArgumentException | ||
95 | * @dataProvider getPathsToInvalidFiles | ||
96 | */ | ||
97 | public function testLoadThrowsExceptionWithInvalidFile($filePath) | ||
98 | { | ||
99 | $loader = new XmlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures'))); | ||
100 | $loader->load($filePath); | ||
101 | } | ||
102 | |||
103 | /** | ||
104 | * @expectedException \InvalidArgumentException | ||
105 | * @dataProvider getPathsToInvalidFiles | ||
106 | */ | ||
107 | public function testLoadThrowsExceptionWithInvalidFileEvenWithoutSchemaValidation($filePath) | ||
108 | { | ||
109 | $loader = new CustomXmlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures'))); | ||
110 | $loader->load($filePath); | ||
111 | } | ||
112 | |||
113 | public function getPathsToInvalidFiles() | ||
114 | { | ||
115 | return array(array('nonvalidnode.xml'), array('nonvalidroute.xml'), array('nonvalid.xml'), array('missing_id.xml'), array('missing_path.xml')); | ||
116 | } | ||
117 | |||
118 | /** | ||
119 | * @expectedException \InvalidArgumentException | ||
120 | * @expectedExceptionMessage Document types are not allowed. | ||
121 | */ | ||
122 | public function testDocTypeIsNotAllowed() | ||
123 | { | ||
124 | $loader = new XmlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures'))); | ||
125 | $loader->load('withdoctype.xml'); | ||
126 | } | ||
127 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Tests/Loader/YamlFileLoaderTest.php b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Loader/YamlFileLoaderTest.php new file mode 100644 index 00000000..a3e934ce --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Loader/YamlFileLoaderTest.php | |||
@@ -0,0 +1,113 @@ | |||
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\Tests\Loader; | ||
13 | |||
14 | use Symfony\Component\Config\FileLocator; | ||
15 | use Symfony\Component\Routing\Loader\YamlFileLoader; | ||
16 | use Symfony\Component\Config\Resource\FileResource; | ||
17 | |||
18 | class YamlFileLoaderTest extends \PHPUnit_Framework_TestCase | ||
19 | { | ||
20 | protected function setUp() | ||
21 | { | ||
22 | if (!class_exists('Symfony\Component\Config\FileLocator')) { | ||
23 | $this->markTestSkipped('The "Config" component is not available'); | ||
24 | } | ||
25 | |||
26 | if (!class_exists('Symfony\Component\Yaml\Yaml')) { | ||
27 | $this->markTestSkipped('The "Yaml" component is not available'); | ||
28 | } | ||
29 | } | ||
30 | |||
31 | public function testSupports() | ||
32 | { | ||
33 | $loader = new YamlFileLoader($this->getMock('Symfony\Component\Config\FileLocator')); | ||
34 | |||
35 | $this->assertTrue($loader->supports('foo.yml'), '->supports() returns true if the resource is loadable'); | ||
36 | $this->assertFalse($loader->supports('foo.foo'), '->supports() returns true if the resource is loadable'); | ||
37 | |||
38 | $this->assertTrue($loader->supports('foo.yml', 'yaml'), '->supports() checks the resource type if specified'); | ||
39 | $this->assertFalse($loader->supports('foo.yml', 'foo'), '->supports() checks the resource type if specified'); | ||
40 | } | ||
41 | |||
42 | public function testLoadDoesNothingIfEmpty() | ||
43 | { | ||
44 | $loader = new YamlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures'))); | ||
45 | $collection = $loader->load('empty.yml'); | ||
46 | |||
47 | $this->assertEquals(array(), $collection->all()); | ||
48 | $this->assertEquals(array(new FileResource(realpath(__DIR__.'/../Fixtures/empty.yml'))), $collection->getResources()); | ||
49 | } | ||
50 | |||
51 | /** | ||
52 | * @expectedException \InvalidArgumentException | ||
53 | * @dataProvider getPathsToInvalidFiles | ||
54 | */ | ||
55 | public function testLoadThrowsExceptionWithInvalidFile($filePath) | ||
56 | { | ||
57 | $loader = new YamlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures'))); | ||
58 | $loader->load($filePath); | ||
59 | } | ||
60 | |||
61 | public function getPathsToInvalidFiles() | ||
62 | { | ||
63 | return array(array('nonvalid.yml'), array('nonvalid2.yml'), array('incomplete.yml'), array('nonvalidkeys.yml'), array('nonesense_resource_plus_path.yml'), array('nonesense_type_without_resource.yml')); | ||
64 | } | ||
65 | |||
66 | public function testLoadSpecialRouteName() | ||
67 | { | ||
68 | $loader = new YamlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures'))); | ||
69 | $routeCollection = $loader->load('special_route_name.yml'); | ||
70 | $route = $routeCollection->get('#$péß^a|'); | ||
71 | |||
72 | $this->assertInstanceOf('Symfony\Component\Routing\Route', $route); | ||
73 | $this->assertSame('/true', $route->getPath()); | ||
74 | } | ||
75 | |||
76 | public function testLoadWithRoute() | ||
77 | { | ||
78 | $loader = new YamlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures'))); | ||
79 | $routeCollection = $loader->load('validpattern.yml'); | ||
80 | $routes = $routeCollection->all(); | ||
81 | |||
82 | $this->assertCount(2, $routes, 'Two routes are loaded'); | ||
83 | $this->assertContainsOnly('Symfony\Component\Routing\Route', $routes); | ||
84 | |||
85 | foreach ($routes as $route) { | ||
86 | $this->assertSame('/blog/{slug}', $route->getPath()); | ||
87 | $this->assertSame('{locale}.example.com', $route->getHost()); | ||
88 | $this->assertSame('MyBundle:Blog:show', $route->getDefault('_controller')); | ||
89 | $this->assertSame('\w+', $route->getRequirement('locale')); | ||
90 | $this->assertSame('RouteCompiler', $route->getOption('compiler_class')); | ||
91 | $this->assertEquals(array('GET', 'POST', 'PUT', 'OPTIONS'), $route->getMethods()); | ||
92 | $this->assertEquals(array('https'), $route->getSchemes()); | ||
93 | } | ||
94 | } | ||
95 | |||
96 | public function testLoadWithResource() | ||
97 | { | ||
98 | $loader = new YamlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures'))); | ||
99 | $routeCollection = $loader->load('validresource.yml'); | ||
100 | $routes = $routeCollection->all(); | ||
101 | |||
102 | $this->assertCount(2, $routes, 'Two routes are loaded'); | ||
103 | $this->assertContainsOnly('Symfony\Component\Routing\Route', $routes); | ||
104 | |||
105 | foreach ($routes as $route) { | ||
106 | $this->assertSame('/{foo}/blog/{slug}', $route->getPath()); | ||
107 | $this->assertSame('123', $route->getDefault('foo')); | ||
108 | $this->assertSame('\d+', $route->getRequirement('foo')); | ||
109 | $this->assertSame('bar', $route->getOption('foo')); | ||
110 | $this->assertSame('', $route->getHost()); | ||
111 | } | ||
112 | } | ||
113 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Tests/Matcher/ApacheUrlMatcherTest.php b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Matcher/ApacheUrlMatcherTest.php new file mode 100644 index 00000000..6550911e --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Matcher/ApacheUrlMatcherTest.php | |||
@@ -0,0 +1,137 @@ | |||
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\Tests\Matcher; | ||
13 | |||
14 | use Symfony\Component\Routing\RouteCollection; | ||
15 | use Symfony\Component\Routing\RequestContext; | ||
16 | use Symfony\Component\Routing\Matcher\ApacheUrlMatcher; | ||
17 | |||
18 | class ApacheUrlMatcherTest extends \PHPUnit_Framework_TestCase | ||
19 | { | ||
20 | protected $server; | ||
21 | |||
22 | protected function setUp() | ||
23 | { | ||
24 | $this->server = $_SERVER; | ||
25 | } | ||
26 | |||
27 | protected function tearDown() | ||
28 | { | ||
29 | $_SERVER = $this->server; | ||
30 | } | ||
31 | |||
32 | /** | ||
33 | * @dataProvider getMatchData | ||
34 | */ | ||
35 | public function testMatch($name, $pathinfo, $server, $expect) | ||
36 | { | ||
37 | $collection = new RouteCollection(); | ||
38 | $context = new RequestContext(); | ||
39 | $matcher = new ApacheUrlMatcher($collection, $context); | ||
40 | |||
41 | $_SERVER = $server; | ||
42 | |||
43 | $result = $matcher->match($pathinfo, $server); | ||
44 | $this->assertSame(var_export($expect, true), var_export($result, true)); | ||
45 | } | ||
46 | |||
47 | public function getMatchData() | ||
48 | { | ||
49 | return array( | ||
50 | array( | ||
51 | 'Simple route', | ||
52 | '/hello/world', | ||
53 | array( | ||
54 | '_ROUTING_route' => 'hello', | ||
55 | '_ROUTING_param__controller' => 'AcmeBundle:Default:index', | ||
56 | '_ROUTING_param_name' => 'world', | ||
57 | ), | ||
58 | array( | ||
59 | '_controller' => 'AcmeBundle:Default:index', | ||
60 | 'name' => 'world', | ||
61 | '_route' => 'hello', | ||
62 | ), | ||
63 | ), | ||
64 | array( | ||
65 | 'Route with params and defaults', | ||
66 | '/hello/hugo', | ||
67 | array( | ||
68 | '_ROUTING_route' => 'hello', | ||
69 | '_ROUTING_param__controller' => 'AcmeBundle:Default:index', | ||
70 | '_ROUTING_param_name' => 'hugo', | ||
71 | '_ROUTING_default_name' => 'world', | ||
72 | ), | ||
73 | array( | ||
74 | 'name' => 'hugo', | ||
75 | '_controller' => 'AcmeBundle:Default:index', | ||
76 | '_route' => 'hello', | ||
77 | ), | ||
78 | ), | ||
79 | array( | ||
80 | 'Route with defaults only', | ||
81 | '/hello', | ||
82 | array( | ||
83 | '_ROUTING_route' => 'hello', | ||
84 | '_ROUTING_param__controller' => 'AcmeBundle:Default:index', | ||
85 | '_ROUTING_default_name' => 'world', | ||
86 | ), | ||
87 | array( | ||
88 | 'name' => 'world', | ||
89 | '_controller' => 'AcmeBundle:Default:index', | ||
90 | '_route' => 'hello', | ||
91 | ), | ||
92 | ), | ||
93 | array( | ||
94 | 'REDIRECT_ envs', | ||
95 | '/hello/world', | ||
96 | array( | ||
97 | 'REDIRECT__ROUTING_route' => 'hello', | ||
98 | 'REDIRECT__ROUTING_param__controller' => 'AcmeBundle:Default:index', | ||
99 | 'REDIRECT__ROUTING_param_name' => 'world', | ||
100 | ), | ||
101 | array( | ||
102 | '_controller' => 'AcmeBundle:Default:index', | ||
103 | 'name' => 'world', | ||
104 | '_route' => 'hello', | ||
105 | ), | ||
106 | ), | ||
107 | array( | ||
108 | 'REDIRECT_REDIRECT_ envs', | ||
109 | '/hello/world', | ||
110 | array( | ||
111 | 'REDIRECT_REDIRECT__ROUTING_route' => 'hello', | ||
112 | 'REDIRECT_REDIRECT__ROUTING_param__controller' => 'AcmeBundle:Default:index', | ||
113 | 'REDIRECT_REDIRECT__ROUTING_param_name' => 'world', | ||
114 | ), | ||
115 | array( | ||
116 | '_controller' => 'AcmeBundle:Default:index', | ||
117 | 'name' => 'world', | ||
118 | '_route' => 'hello', | ||
119 | ), | ||
120 | ), | ||
121 | array( | ||
122 | 'REDIRECT_REDIRECT_ envs', | ||
123 | '/hello/world', | ||
124 | array( | ||
125 | 'REDIRECT_REDIRECT__ROUTING_route' => 'hello', | ||
126 | 'REDIRECT_REDIRECT__ROUTING_param__controller' => 'AcmeBundle:Default:index', | ||
127 | 'REDIRECT_REDIRECT__ROUTING_param_name' => 'world', | ||
128 | ), | ||
129 | array( | ||
130 | '_controller' => 'AcmeBundle:Default:index', | ||
131 | 'name' => 'world', | ||
132 | '_route' => 'hello', | ||
133 | ), | ||
134 | ), | ||
135 | ); | ||
136 | } | ||
137 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Tests/Matcher/Dumper/ApacheMatcherDumperTest.php b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Matcher/Dumper/ApacheMatcherDumperTest.php new file mode 100644 index 00000000..72bee710 --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Matcher/Dumper/ApacheMatcherDumperTest.php | |||
@@ -0,0 +1,196 @@ | |||
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\Tests\Matcher\Dumper; | ||
13 | |||
14 | use Symfony\Component\Routing\Route; | ||
15 | use Symfony\Component\Routing\RouteCollection; | ||
16 | use Symfony\Component\Routing\Matcher\Dumper\ApacheMatcherDumper; | ||
17 | |||
18 | class ApacheMatcherDumperTest extends \PHPUnit_Framework_TestCase | ||
19 | { | ||
20 | protected static $fixturesPath; | ||
21 | |||
22 | public static function setUpBeforeClass() | ||
23 | { | ||
24 | self::$fixturesPath = realpath(__DIR__.'/../../Fixtures/'); | ||
25 | } | ||
26 | |||
27 | public function testDump() | ||
28 | { | ||
29 | $dumper = new ApacheMatcherDumper($this->getRouteCollection()); | ||
30 | |||
31 | $this->assertStringEqualsFile(self::$fixturesPath.'/dumper/url_matcher1.apache', $dumper->dump(), '->dump() dumps basic routes to the correct apache format.'); | ||
32 | } | ||
33 | |||
34 | /** | ||
35 | * @dataProvider provideEscapeFixtures | ||
36 | */ | ||
37 | public function testEscapePattern($src, $dest, $char, $with, $message) | ||
38 | { | ||
39 | $r = new \ReflectionMethod(new ApacheMatcherDumper($this->getRouteCollection()), 'escape'); | ||
40 | $r->setAccessible(true); | ||
41 | $this->assertEquals($dest, $r->invoke(null, $src, $char, $with), $message); | ||
42 | } | ||
43 | |||
44 | public function provideEscapeFixtures() | ||
45 | { | ||
46 | return array( | ||
47 | array('foo', 'foo', ' ', '-', 'Preserve string that should not be escaped'), | ||
48 | array('fo-o', 'fo-o', ' ', '-', 'Preserve string that should not be escaped'), | ||
49 | array('fo o', 'fo- o', ' ', '-', 'Escape special characters'), | ||
50 | array('fo-- o', 'fo--- o', ' ', '-', 'Escape special characters'), | ||
51 | array('fo- o', 'fo- o', ' ', '-', 'Do not escape already escaped string'), | ||
52 | ); | ||
53 | } | ||
54 | |||
55 | public function testEscapeScriptName() | ||
56 | { | ||
57 | $collection = new RouteCollection(); | ||
58 | $collection->add('foo', new Route('/foo')); | ||
59 | $dumper = new ApacheMatcherDumper($collection); | ||
60 | $this->assertStringEqualsFile(self::$fixturesPath.'/dumper/url_matcher2.apache', $dumper->dump(array('script_name' => 'ap p_d\ ev.php'))); | ||
61 | } | ||
62 | |||
63 | private function getRouteCollection() | ||
64 | { | ||
65 | $collection = new RouteCollection(); | ||
66 | |||
67 | // defaults and requirements | ||
68 | $collection->add('foo', new Route( | ||
69 | '/foo/{bar}', | ||
70 | array('def' => 'test'), | ||
71 | array('bar' => 'baz|symfony') | ||
72 | )); | ||
73 | // defaults parameters in pattern | ||
74 | $collection->add('foobar', new Route( | ||
75 | '/foo/{bar}', | ||
76 | array('bar' => 'toto') | ||
77 | )); | ||
78 | // method requirement | ||
79 | $collection->add('bar', new Route( | ||
80 | '/bar/{foo}', | ||
81 | array(), | ||
82 | array('_method' => 'GET|head') | ||
83 | )); | ||
84 | // method requirement (again) | ||
85 | $collection->add('baragain', new Route( | ||
86 | '/baragain/{foo}', | ||
87 | array(), | ||
88 | array('_method' => 'get|post') | ||
89 | )); | ||
90 | // simple | ||
91 | $collection->add('baz', new Route( | ||
92 | '/test/baz' | ||
93 | )); | ||
94 | // simple with extension | ||
95 | $collection->add('baz2', new Route( | ||
96 | '/test/baz.html' | ||
97 | )); | ||
98 | // trailing slash | ||
99 | $collection->add('baz3', new Route( | ||
100 | '/test/baz3/' | ||
101 | )); | ||
102 | // trailing slash with variable | ||
103 | $collection->add('baz4', new Route( | ||
104 | '/test/{foo}/' | ||
105 | )); | ||
106 | // trailing slash and safe method | ||
107 | $collection->add('baz5', new Route( | ||
108 | '/test/{foo}/', | ||
109 | array(), | ||
110 | array('_method' => 'get') | ||
111 | )); | ||
112 | // trailing slash and unsafe method | ||
113 | $collection->add('baz5unsafe', new Route( | ||
114 | '/testunsafe/{foo}/', | ||
115 | array(), | ||
116 | array('_method' => 'post') | ||
117 | )); | ||
118 | // complex | ||
119 | $collection->add('baz6', new Route( | ||
120 | '/test/baz', | ||
121 | array('foo' => 'bar baz') | ||
122 | )); | ||
123 | // space in path | ||
124 | $collection->add('baz7', new Route( | ||
125 | '/te st/baz' | ||
126 | )); | ||
127 | // space preceded with \ in path | ||
128 | $collection->add('baz8', new Route( | ||
129 | '/te\\ st/baz' | ||
130 | )); | ||
131 | // space preceded with \ in requirement | ||
132 | $collection->add('baz9', new Route( | ||
133 | '/test/{baz}', | ||
134 | array(), | ||
135 | array( | ||
136 | 'baz' => 'te\\\\ st', | ||
137 | ) | ||
138 | )); | ||
139 | |||
140 | $collection1 = new RouteCollection(); | ||
141 | |||
142 | $route1 = new Route('/route1', array(), array(), array(), 'a.example.com'); | ||
143 | $collection1->add('route1', $route1); | ||
144 | |||
145 | $collection2 = new RouteCollection(); | ||
146 | |||
147 | $route2 = new Route('/route2', array(), array(), array(), 'a.example.com'); | ||
148 | $collection2->add('route2', $route2); | ||
149 | |||
150 | $route3 = new Route('/route3', array(), array(), array(), 'b.example.com'); | ||
151 | $collection2->add('route3', $route3); | ||
152 | |||
153 | $collection2->addPrefix('/c2'); | ||
154 | $collection1->addCollection($collection2); | ||
155 | |||
156 | $route4 = new Route('/route4', array(), array(), array(), 'a.example.com'); | ||
157 | $collection1->add('route4', $route4); | ||
158 | |||
159 | $route5 = new Route('/route5', array(), array(), array(), 'c.example.com'); | ||
160 | $collection1->add('route5', $route5); | ||
161 | |||
162 | $route6 = new Route('/route6', array(), array(), array(), null); | ||
163 | $collection1->add('route6', $route6); | ||
164 | |||
165 | $collection->addCollection($collection1); | ||
166 | |||
167 | // host and variables | ||
168 | |||
169 | $collection1 = new RouteCollection(); | ||
170 | |||
171 | $route11 = new Route('/route11', array(), array(), array(), '{var1}.example.com'); | ||
172 | $collection1->add('route11', $route11); | ||
173 | |||
174 | $route12 = new Route('/route12', array('var1' => 'val'), array(), array(), '{var1}.example.com'); | ||
175 | $collection1->add('route12', $route12); | ||
176 | |||
177 | $route13 = new Route('/route13/{name}', array(), array(), array(), '{var1}.example.com'); | ||
178 | $collection1->add('route13', $route13); | ||
179 | |||
180 | $route14 = new Route('/route14/{name}', array('var1' => 'val'), array(), array(), '{var1}.example.com'); | ||
181 | $collection1->add('route14', $route14); | ||
182 | |||
183 | $route15 = new Route('/route15/{name}', array(), array(), array(), 'c.example.com'); | ||
184 | $collection1->add('route15', $route15); | ||
185 | |||
186 | $route16 = new Route('/route16/{name}', array('var1' => 'val'), array(), array(), null); | ||
187 | $collection1->add('route16', $route16); | ||
188 | |||
189 | $route17 = new Route('/route17', array(), array(), array(), null); | ||
190 | $collection1->add('route17', $route17); | ||
191 | |||
192 | $collection->addCollection($collection1); | ||
193 | |||
194 | return $collection; | ||
195 | } | ||
196 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Tests/Matcher/Dumper/DumperCollectionTest.php b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Matcher/Dumper/DumperCollectionTest.php new file mode 100644 index 00000000..54b37727 --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Matcher/Dumper/DumperCollectionTest.php | |||
@@ -0,0 +1,33 @@ | |||
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\Test\Matcher\Dumper; | ||
13 | |||
14 | use Symfony\Component\Routing\Matcher\Dumper\DumperCollection; | ||
15 | |||
16 | class DumperCollectionTest extends \PHPUnit_Framework_TestCase | ||
17 | { | ||
18 | public function testGetRoot() | ||
19 | { | ||
20 | $a = new DumperCollection(); | ||
21 | |||
22 | $b = new DumperCollection(); | ||
23 | $a->add($b); | ||
24 | |||
25 | $c = new DumperCollection(); | ||
26 | $b->add($c); | ||
27 | |||
28 | $d = new DumperCollection(); | ||
29 | $c->add($d); | ||
30 | |||
31 | $this->assertSame($a, $c->getRoot()); | ||
32 | } | ||
33 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Tests/Matcher/Dumper/DumperPrefixCollectionTest.php b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Matcher/Dumper/DumperPrefixCollectionTest.php new file mode 100644 index 00000000..7b4565c4 --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Matcher/Dumper/DumperPrefixCollectionTest.php | |||
@@ -0,0 +1,123 @@ | |||
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\Tests\Matcher\Dumper; | ||
13 | |||
14 | use Symfony\Component\Routing\Route; | ||
15 | use Symfony\Component\Routing\Matcher\Dumper\DumperPrefixCollection; | ||
16 | use Symfony\Component\Routing\Matcher\Dumper\DumperRoute; | ||
17 | use Symfony\Component\Routing\Matcher\Dumper\DumperCollection; | ||
18 | |||
19 | class DumperPrefixCollectionTest extends \PHPUnit_Framework_TestCase | ||
20 | { | ||
21 | public function testAddPrefixRoute() | ||
22 | { | ||
23 | $coll = new DumperPrefixCollection; | ||
24 | $coll->setPrefix(''); | ||
25 | |||
26 | $route = new DumperRoute('bar', new Route('/foo/bar')); | ||
27 | $coll = $coll->addPrefixRoute($route); | ||
28 | |||
29 | $route = new DumperRoute('bar2', new Route('/foo/bar')); | ||
30 | $coll = $coll->addPrefixRoute($route); | ||
31 | |||
32 | $route = new DumperRoute('qux', new Route('/foo/qux')); | ||
33 | $coll = $coll->addPrefixRoute($route); | ||
34 | |||
35 | $route = new DumperRoute('bar3', new Route('/foo/bar')); | ||
36 | $coll = $coll->addPrefixRoute($route); | ||
37 | |||
38 | $route = new DumperRoute('bar4', new Route('')); | ||
39 | $result = $coll->addPrefixRoute($route); | ||
40 | |||
41 | $expect = <<<'EOF' | ||
42 | |-coll / | ||
43 | | |-coll /f | ||
44 | | | |-coll /fo | ||
45 | | | | |-coll /foo | ||
46 | | | | | |-coll /foo/ | ||
47 | | | | | | |-coll /foo/b | ||
48 | | | | | | | |-coll /foo/ba | ||
49 | | | | | | | | |-coll /foo/bar | ||
50 | | | | | | | | | |-route bar /foo/bar | ||
51 | | | | | | | | | |-route bar2 /foo/bar | ||
52 | | | | | | |-coll /foo/q | ||
53 | | | | | | | |-coll /foo/qu | ||
54 | | | | | | | | |-coll /foo/qux | ||
55 | | | | | | | | | |-route qux /foo/qux | ||
56 | | | | | | |-coll /foo/b | ||
57 | | | | | | | |-coll /foo/ba | ||
58 | | | | | | | | |-coll /foo/bar | ||
59 | | | | | | | | | |-route bar3 /foo/bar | ||
60 | | |-route bar4 / | ||
61 | |||
62 | EOF; | ||
63 | |||
64 | $this->assertSame($expect, $this->collectionToString($result->getRoot(), ' ')); | ||
65 | } | ||
66 | |||
67 | public function testMergeSlashNodes() | ||
68 | { | ||
69 | $coll = new DumperPrefixCollection; | ||
70 | $coll->setPrefix(''); | ||
71 | |||
72 | $route = new DumperRoute('bar', new Route('/foo/bar')); | ||
73 | $coll = $coll->addPrefixRoute($route); | ||
74 | |||
75 | $route = new DumperRoute('bar2', new Route('/foo/bar')); | ||
76 | $coll = $coll->addPrefixRoute($route); | ||
77 | |||
78 | $route = new DumperRoute('qux', new Route('/foo/qux')); | ||
79 | $coll = $coll->addPrefixRoute($route); | ||
80 | |||
81 | $route = new DumperRoute('bar3', new Route('/foo/bar')); | ||
82 | $result = $coll->addPrefixRoute($route); | ||
83 | |||
84 | $result->getRoot()->mergeSlashNodes(); | ||
85 | |||
86 | $expect = <<<'EOF' | ||
87 | |-coll /f | ||
88 | | |-coll /fo | ||
89 | | | |-coll /foo | ||
90 | | | | |-coll /foo/b | ||
91 | | | | | |-coll /foo/ba | ||
92 | | | | | | |-coll /foo/bar | ||
93 | | | | | | | |-route bar /foo/bar | ||
94 | | | | | | | |-route bar2 /foo/bar | ||
95 | | | | |-coll /foo/q | ||
96 | | | | | |-coll /foo/qu | ||
97 | | | | | | |-coll /foo/qux | ||
98 | | | | | | | |-route qux /foo/qux | ||
99 | | | | |-coll /foo/b | ||
100 | | | | | |-coll /foo/ba | ||
101 | | | | | | |-coll /foo/bar | ||
102 | | | | | | | |-route bar3 /foo/bar | ||
103 | |||
104 | EOF; | ||
105 | |||
106 | $this->assertSame($expect, $this->collectionToString($result->getRoot(), ' ')); | ||
107 | } | ||
108 | |||
109 | private function collectionToString(DumperCollection $collection, $prefix) | ||
110 | { | ||
111 | $string = ''; | ||
112 | foreach ($collection as $route) { | ||
113 | if ($route instanceof DumperCollection) { | ||
114 | $string .= sprintf("%s|-coll %s\n", $prefix, $route->getPrefix()); | ||
115 | $string .= $this->collectionToString($route, $prefix.'| '); | ||
116 | } else { | ||
117 | $string .= sprintf("%s|-route %s %s\n", $prefix, $route->getName(), $route->getRoute()->getPath()); | ||
118 | } | ||
119 | } | ||
120 | |||
121 | return $string; | ||
122 | } | ||
123 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Tests/Matcher/Dumper/PhpMatcherDumperTest.php b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Matcher/Dumper/PhpMatcherDumperTest.php new file mode 100644 index 00000000..542ede85 --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Matcher/Dumper/PhpMatcherDumperTest.php | |||
@@ -0,0 +1,261 @@ | |||
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\Tests\Matcher\Dumper; | ||
13 | |||
14 | use Symfony\Component\Routing\Matcher\Dumper\PhpMatcherDumper; | ||
15 | use Symfony\Component\Routing\Route; | ||
16 | use Symfony\Component\Routing\RouteCollection; | ||
17 | |||
18 | class PhpMatcherDumperTest extends \PHPUnit_Framework_TestCase | ||
19 | { | ||
20 | /** | ||
21 | * @expectedException \LogicException | ||
22 | */ | ||
23 | public function testDumpWhenSchemeIsUsedWithoutAProperDumper() | ||
24 | { | ||
25 | $collection = new RouteCollection(); | ||
26 | $collection->add('secure', new Route( | ||
27 | '/secure', | ||
28 | array(), | ||
29 | array('_scheme' => 'https') | ||
30 | )); | ||
31 | $dumper = new PhpMatcherDumper($collection); | ||
32 | $dumper->dump(); | ||
33 | } | ||
34 | |||
35 | /** | ||
36 | * @dataProvider getRouteCollections | ||
37 | */ | ||
38 | public function testDump(RouteCollection $collection, $fixture, $options = array()) | ||
39 | { | ||
40 | $basePath = __DIR__.'/../../Fixtures/dumper/'; | ||
41 | |||
42 | $dumper = new PhpMatcherDumper($collection); | ||
43 | $this->assertStringEqualsFile($basePath.$fixture, $dumper->dump($options), '->dump() correctly dumps routes as optimized PHP code.'); | ||
44 | } | ||
45 | |||
46 | public function getRouteCollections() | ||
47 | { | ||
48 | /* test case 1 */ | ||
49 | |||
50 | $collection = new RouteCollection(); | ||
51 | |||
52 | $collection->add('overridden', new Route('/overridden')); | ||
53 | |||
54 | // defaults and requirements | ||
55 | $collection->add('foo', new Route( | ||
56 | '/foo/{bar}', | ||
57 | array('def' => 'test'), | ||
58 | array('bar' => 'baz|symfony') | ||
59 | )); | ||
60 | // method requirement | ||
61 | $collection->add('bar', new Route( | ||
62 | '/bar/{foo}', | ||
63 | array(), | ||
64 | array('_method' => 'GET|head') | ||
65 | )); | ||
66 | // GET method requirement automatically adds HEAD as valid | ||
67 | $collection->add('barhead', new Route( | ||
68 | '/barhead/{foo}', | ||
69 | array(), | ||
70 | array('_method' => 'GET') | ||
71 | )); | ||
72 | // simple | ||
73 | $collection->add('baz', new Route( | ||
74 | '/test/baz' | ||
75 | )); | ||
76 | // simple with extension | ||
77 | $collection->add('baz2', new Route( | ||
78 | '/test/baz.html' | ||
79 | )); | ||
80 | // trailing slash | ||
81 | $collection->add('baz3', new Route( | ||
82 | '/test/baz3/' | ||
83 | )); | ||
84 | // trailing slash with variable | ||
85 | $collection->add('baz4', new Route( | ||
86 | '/test/{foo}/' | ||
87 | )); | ||
88 | // trailing slash and method | ||
89 | $collection->add('baz5', new Route( | ||
90 | '/test/{foo}/', | ||
91 | array(), | ||
92 | array('_method' => 'post') | ||
93 | )); | ||
94 | // complex name | ||
95 | $collection->add('baz.baz6', new Route( | ||
96 | '/test/{foo}/', | ||
97 | array(), | ||
98 | array('_method' => 'put') | ||
99 | )); | ||
100 | // defaults without variable | ||
101 | $collection->add('foofoo', new Route( | ||
102 | '/foofoo', | ||
103 | array('def' => 'test') | ||
104 | )); | ||
105 | // pattern with quotes | ||
106 | $collection->add('quoter', new Route( | ||
107 | '/{quoter}', | ||
108 | array(), | ||
109 | array('quoter' => '[\']+') | ||
110 | )); | ||
111 | // space in pattern | ||
112 | $collection->add('space', new Route( | ||
113 | '/spa ce' | ||
114 | )); | ||
115 | |||
116 | // prefixes | ||
117 | $collection1 = new RouteCollection(); | ||
118 | $collection1->add('overridden', new Route('/overridden1')); | ||
119 | $collection1->add('foo1', new Route('/{foo}')); | ||
120 | $collection1->add('bar1', new Route('/{bar}')); | ||
121 | $collection1->addPrefix('/b\'b'); | ||
122 | $collection2 = new RouteCollection(); | ||
123 | $collection2->addCollection($collection1); | ||
124 | $collection2->add('overridden', new Route('/{var}', array(), array('var' => '.*'))); | ||
125 | $collection1 = new RouteCollection(); | ||
126 | $collection1->add('foo2', new Route('/{foo1}')); | ||
127 | $collection1->add('bar2', new Route('/{bar1}')); | ||
128 | $collection1->addPrefix('/b\'b'); | ||
129 | $collection2->addCollection($collection1); | ||
130 | $collection2->addPrefix('/a'); | ||
131 | $collection->addCollection($collection2); | ||
132 | |||
133 | // overridden through addCollection() and multiple sub-collections with no own prefix | ||
134 | $collection1 = new RouteCollection(); | ||
135 | $collection1->add('overridden2', new Route('/old')); | ||
136 | $collection1->add('helloWorld', new Route('/hello/{who}', array('who' => 'World!'))); | ||
137 | $collection2 = new RouteCollection(); | ||
138 | $collection3 = new RouteCollection(); | ||
139 | $collection3->add('overridden2', new Route('/new')); | ||
140 | $collection3->add('hey', new Route('/hey/')); | ||
141 | $collection2->addCollection($collection3); | ||
142 | $collection1->addCollection($collection2); | ||
143 | $collection1->addPrefix('/multi'); | ||
144 | $collection->addCollection($collection1); | ||
145 | |||
146 | // "dynamic" prefix | ||
147 | $collection1 = new RouteCollection(); | ||
148 | $collection1->add('foo3', new Route('/{foo}')); | ||
149 | $collection1->add('bar3', new Route('/{bar}')); | ||
150 | $collection1->addPrefix('/b'); | ||
151 | $collection1->addPrefix('{_locale}'); | ||
152 | $collection->addCollection($collection1); | ||
153 | |||
154 | // route between collections | ||
155 | $collection->add('ababa', new Route('/ababa')); | ||
156 | |||
157 | // collection with static prefix but only one route | ||
158 | $collection1 = new RouteCollection(); | ||
159 | $collection1->add('foo4', new Route('/{foo}')); | ||
160 | $collection1->addPrefix('/aba'); | ||
161 | $collection->addCollection($collection1); | ||
162 | |||
163 | // prefix and host | ||
164 | |||
165 | $collection1 = new RouteCollection(); | ||
166 | |||
167 | $route1 = new Route('/route1', array(), array(), array(), 'a.example.com'); | ||
168 | $collection1->add('route1', $route1); | ||
169 | |||
170 | $collection2 = new RouteCollection(); | ||
171 | |||
172 | $route2 = new Route('/c2/route2', array(), array(), array(), 'a.example.com'); | ||
173 | $collection1->add('route2', $route2); | ||
174 | |||
175 | $route3 = new Route('/c2/route3', array(), array(), array(), 'b.example.com'); | ||
176 | $collection1->add('route3', $route3); | ||
177 | |||
178 | $route4 = new Route('/route4', array(), array(), array(), 'a.example.com'); | ||
179 | $collection1->add('route4', $route4); | ||
180 | |||
181 | $route5 = new Route('/route5', array(), array(), array(), 'c.example.com'); | ||
182 | $collection1->add('route5', $route5); | ||
183 | |||
184 | $route6 = new Route('/route6', array(), array(), array(), null); | ||
185 | $collection1->add('route6', $route6); | ||
186 | |||
187 | $collection->addCollection($collection1); | ||
188 | |||
189 | // host and variables | ||
190 | |||
191 | $collection1 = new RouteCollection(); | ||
192 | |||
193 | $route11 = new Route('/route11', array(), array(), array(), '{var1}.example.com'); | ||
194 | $collection1->add('route11', $route11); | ||
195 | |||
196 | $route12 = new Route('/route12', array('var1' => 'val'), array(), array(), '{var1}.example.com'); | ||
197 | $collection1->add('route12', $route12); | ||
198 | |||
199 | $route13 = new Route('/route13/{name}', array(), array(), array(), '{var1}.example.com'); | ||
200 | $collection1->add('route13', $route13); | ||
201 | |||
202 | $route14 = new Route('/route14/{name}', array('var1' => 'val'), array(), array(), '{var1}.example.com'); | ||
203 | $collection1->add('route14', $route14); | ||
204 | |||
205 | $route15 = new Route('/route15/{name}', array(), array(), array(), 'c.example.com'); | ||
206 | $collection1->add('route15', $route15); | ||
207 | |||
208 | $route16 = new Route('/route16/{name}', array('var1' => 'val'), array(), array(), null); | ||
209 | $collection1->add('route16', $route16); | ||
210 | |||
211 | $route17 = new Route('/route17', array(), array(), array(), null); | ||
212 | $collection1->add('route17', $route17); | ||
213 | |||
214 | $collection->addCollection($collection1); | ||
215 | |||
216 | // multiple sub-collections with a single route and a prefix each | ||
217 | $collection1 = new RouteCollection(); | ||
218 | $collection1->add('a', new Route('/a...')); | ||
219 | $collection2 = new RouteCollection(); | ||
220 | $collection2->add('b', new Route('/{var}')); | ||
221 | $collection3 = new RouteCollection(); | ||
222 | $collection3->add('c', new Route('/{var}')); | ||
223 | $collection3->addPrefix('/c'); | ||
224 | $collection2->addCollection($collection3); | ||
225 | $collection2->addPrefix('/b'); | ||
226 | $collection1->addCollection($collection2); | ||
227 | $collection1->addPrefix('/a'); | ||
228 | $collection->addCollection($collection1); | ||
229 | |||
230 | /* test case 2 */ | ||
231 | |||
232 | $redirectCollection = clone $collection; | ||
233 | |||
234 | // force HTTPS redirection | ||
235 | $redirectCollection->add('secure', new Route( | ||
236 | '/secure', | ||
237 | array(), | ||
238 | array('_scheme' => 'https') | ||
239 | )); | ||
240 | |||
241 | // force HTTP redirection | ||
242 | $redirectCollection->add('nonsecure', new Route( | ||
243 | '/nonsecure', | ||
244 | array(), | ||
245 | array('_scheme' => 'http') | ||
246 | )); | ||
247 | |||
248 | /* test case 3 */ | ||
249 | |||
250 | $rootprefixCollection = new RouteCollection(); | ||
251 | $rootprefixCollection->add('static', new Route('/test')); | ||
252 | $rootprefixCollection->add('dynamic', new Route('/{var}')); | ||
253 | $rootprefixCollection->addPrefix('rootprefix'); | ||
254 | |||
255 | return array( | ||
256 | array($collection, 'url_matcher1.php', array()), | ||
257 | array($redirectCollection, 'url_matcher2.php', array('base_class' => 'Symfony\Component\Routing\Tests\Fixtures\RedirectableUrlMatcher')), | ||
258 | array($rootprefixCollection, 'url_matcher3.php', array()) | ||
259 | ); | ||
260 | } | ||
261 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Tests/Matcher/RedirectableUrlMatcherTest.php b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Matcher/RedirectableUrlMatcherTest.php new file mode 100644 index 00000000..2ad4fc87 --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Matcher/RedirectableUrlMatcherTest.php | |||
@@ -0,0 +1,58 @@ | |||
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\Tests\Matcher; | ||
13 | |||
14 | use Symfony\Component\Routing\Route; | ||
15 | use Symfony\Component\Routing\RouteCollection; | ||
16 | use Symfony\Component\Routing\RequestContext; | ||
17 | |||
18 | class RedirectableUrlMatcherTest extends \PHPUnit_Framework_TestCase | ||
19 | { | ||
20 | public function testRedirectWhenNoSlash() | ||
21 | { | ||
22 | $coll = new RouteCollection(); | ||
23 | $coll->add('foo', new Route('/foo/')); | ||
24 | |||
25 | $matcher = $this->getMockForAbstractClass('Symfony\Component\Routing\Matcher\RedirectableUrlMatcher', array($coll, new RequestContext())); | ||
26 | $matcher->expects($this->once())->method('redirect'); | ||
27 | $matcher->match('/foo'); | ||
28 | } | ||
29 | |||
30 | /** | ||
31 | * @expectedException \Symfony\Component\Routing\Exception\ResourceNotFoundException | ||
32 | */ | ||
33 | public function testRedirectWhenNoSlashForNonSafeMethod() | ||
34 | { | ||
35 | $coll = new RouteCollection(); | ||
36 | $coll->add('foo', new Route('/foo/')); | ||
37 | |||
38 | $context = new RequestContext(); | ||
39 | $context->setMethod('POST'); | ||
40 | $matcher = $this->getMockForAbstractClass('Symfony\Component\Routing\Matcher\RedirectableUrlMatcher', array($coll, $context)); | ||
41 | $matcher->match('/foo'); | ||
42 | } | ||
43 | |||
44 | public function testSchemeRedirect() | ||
45 | { | ||
46 | $coll = new RouteCollection(); | ||
47 | $coll->add('foo', new Route('/foo', array(), array('_scheme' => 'https'))); | ||
48 | |||
49 | $matcher = $this->getMockForAbstractClass('Symfony\Component\Routing\Matcher\RedirectableUrlMatcher', array($coll, new RequestContext())); | ||
50 | $matcher | ||
51 | ->expects($this->once()) | ||
52 | ->method('redirect') | ||
53 | ->with('/foo', 'foo', 'https') | ||
54 | ->will($this->returnValue(array('_route' => 'foo'))) | ||
55 | ; | ||
56 | $matcher->match('/foo'); | ||
57 | } | ||
58 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Tests/Matcher/TraceableUrlMatcherTest.php b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Matcher/TraceableUrlMatcherTest.php new file mode 100644 index 00000000..86d8d954 --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Matcher/TraceableUrlMatcherTest.php | |||
@@ -0,0 +1,66 @@ | |||
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\Tests\Matcher; | ||
13 | |||
14 | use Symfony\Component\Routing\Route; | ||
15 | use Symfony\Component\Routing\RouteCollection; | ||
16 | use Symfony\Component\Routing\RequestContext; | ||
17 | use Symfony\Component\Routing\Matcher\TraceableUrlMatcher; | ||
18 | |||
19 | class TraceableUrlMatcherTest extends \PHPUnit_Framework_TestCase | ||
20 | { | ||
21 | public function test() | ||
22 | { | ||
23 | $coll = new RouteCollection(); | ||
24 | $coll->add('foo', new Route('/foo', array(), array('_method' => 'POST'))); | ||
25 | $coll->add('bar', new Route('/bar/{id}', array(), array('id' => '\d+'))); | ||
26 | $coll->add('bar1', new Route('/bar/{name}', array(), array('id' => '\w+', '_method' => 'POST'))); | ||
27 | $coll->add('bar2', new Route('/foo', array(), array(), array(), 'baz')); | ||
28 | $coll->add('bar3', new Route('/foo1', array(), array(), array(), 'baz')); | ||
29 | |||
30 | $context = new RequestContext(); | ||
31 | $context->setHost('baz'); | ||
32 | |||
33 | $matcher = new TraceableUrlMatcher($coll, $context); | ||
34 | $traces = $matcher->getTraces('/babar'); | ||
35 | $this->assertEquals(array(0, 0, 0, 0, 0), $this->getLevels($traces)); | ||
36 | |||
37 | $traces = $matcher->getTraces('/foo'); | ||
38 | $this->assertEquals(array(1, 0, 0, 2), $this->getLevels($traces)); | ||
39 | |||
40 | $traces = $matcher->getTraces('/bar/12'); | ||
41 | $this->assertEquals(array(0, 2), $this->getLevels($traces)); | ||
42 | |||
43 | $traces = $matcher->getTraces('/bar/dd'); | ||
44 | $this->assertEquals(array(0, 1, 1, 0, 0), $this->getLevels($traces)); | ||
45 | |||
46 | $traces = $matcher->getTraces('/foo1'); | ||
47 | $this->assertEquals(array(0, 0, 0, 0, 2), $this->getLevels($traces)); | ||
48 | |||
49 | $context->setMethod('POST'); | ||
50 | $traces = $matcher->getTraces('/foo'); | ||
51 | $this->assertEquals(array(2), $this->getLevels($traces)); | ||
52 | |||
53 | $traces = $matcher->getTraces('/bar/dd'); | ||
54 | $this->assertEquals(array(0, 1, 2), $this->getLevels($traces)); | ||
55 | } | ||
56 | |||
57 | public function getLevels($traces) | ||
58 | { | ||
59 | $levels = array(); | ||
60 | foreach ($traces as $trace) { | ||
61 | $levels[] = $trace['level']; | ||
62 | } | ||
63 | |||
64 | return $levels; | ||
65 | } | ||
66 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Tests/Matcher/UrlMatcherTest.php b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Matcher/UrlMatcherTest.php new file mode 100644 index 00000000..8a1428f1 --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Tests/Matcher/UrlMatcherTest.php | |||
@@ -0,0 +1,383 @@ | |||
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\Tests\Matcher; | ||
13 | |||
14 | use Symfony\Component\Routing\Exception\MethodNotAllowedException; | ||
15 | use Symfony\Component\Routing\Exception\ResourceNotFoundException; | ||
16 | use Symfony\Component\Routing\Matcher\UrlMatcher; | ||
17 | use Symfony\Component\Routing\Route; | ||
18 | use Symfony\Component\Routing\RouteCollection; | ||
19 | use Symfony\Component\Routing\RequestContext; | ||
20 | |||
21 | class UrlMatcherTest extends \PHPUnit_Framework_TestCase | ||
22 | { | ||
23 | public function testNoMethodSoAllowed() | ||
24 | { | ||
25 | $coll = new RouteCollection(); | ||
26 | $coll->add('foo', new Route('/foo')); | ||
27 | |||
28 | $matcher = new UrlMatcher($coll, new RequestContext()); | ||
29 | $matcher->match('/foo'); | ||
30 | } | ||
31 | |||
32 | public function testMethodNotAllowed() | ||
33 | { | ||
34 | $coll = new RouteCollection(); | ||
35 | $coll->add('foo', new Route('/foo', array(), array('_method' => 'post'))); | ||
36 | |||
37 | $matcher = new UrlMatcher($coll, new RequestContext()); | ||
38 | |||
39 | try { | ||
40 | $matcher->match('/foo'); | ||
41 | $this->fail(); | ||
42 | } catch (MethodNotAllowedException $e) { | ||
43 | $this->assertEquals(array('POST'), $e->getAllowedMethods()); | ||
44 | } | ||
45 | } | ||
46 | |||
47 | public function testHeadAllowedWhenRequirementContainsGet() | ||
48 | { | ||
49 | $coll = new RouteCollection(); | ||
50 | $coll->add('foo', new Route('/foo', array(), array('_method' => 'get'))); | ||
51 | |||
52 | $matcher = new UrlMatcher($coll, new RequestContext('', 'head')); | ||
53 | $matcher->match('/foo'); | ||
54 | } | ||
55 | |||
56 | public function testMethodNotAllowedAggregatesAllowedMethods() | ||
57 | { | ||
58 | $coll = new RouteCollection(); | ||
59 | $coll->add('foo1', new Route('/foo', array(), array('_method' => 'post'))); | ||
60 | $coll->add('foo2', new Route('/foo', array(), array('_method' => 'put|delete'))); | ||
61 | |||
62 | $matcher = new UrlMatcher($coll, new RequestContext()); | ||
63 | |||
64 | try { | ||
65 | $matcher->match('/foo'); | ||
66 | $this->fail(); | ||
67 | } catch (MethodNotAllowedException $e) { | ||
68 | $this->assertEquals(array('POST', 'PUT', 'DELETE'), $e->getAllowedMethods()); | ||
69 | } | ||
70 | } | ||
71 | |||
72 | public function testMatch() | ||
73 | { | ||
74 | // test the patterns are matched and parameters are returned | ||
75 | $collection = new RouteCollection(); | ||
76 | $collection->add('foo', new Route('/foo/{bar}')); | ||
77 | $matcher = new UrlMatcher($collection, new RequestContext()); | ||
78 | try { | ||
79 | $matcher->match('/no-match'); | ||
80 | $this->fail(); | ||
81 | } catch (ResourceNotFoundException $e) {} | ||
82 | $this->assertEquals(array('_route' => 'foo', 'bar' => 'baz'), $matcher->match('/foo/baz')); | ||
83 | |||
84 | // test that defaults are merged | ||
85 | $collection = new RouteCollection(); | ||
86 | $collection->add('foo', new Route('/foo/{bar}', array('def' => 'test'))); | ||
87 | $matcher = new UrlMatcher($collection, new RequestContext()); | ||
88 | $this->assertEquals(array('_route' => 'foo', 'bar' => 'baz', 'def' => 'test'), $matcher->match('/foo/baz')); | ||
89 | |||
90 | // test that route "method" is ignored if no method is given in the context | ||
91 | $collection = new RouteCollection(); | ||
92 | $collection->add('foo', new Route('/foo', array(), array('_method' => 'GET|head'))); | ||
93 | $matcher = new UrlMatcher($collection, new RequestContext()); | ||
94 | $this->assertInternalType('array', $matcher->match('/foo')); | ||
95 | |||
96 | // route does not match with POST method context | ||
97 | $matcher = new UrlMatcher($collection, new RequestContext('', 'post')); | ||
98 | try { | ||
99 | $matcher->match('/foo'); | ||
100 | $this->fail(); | ||
101 | } catch (MethodNotAllowedException $e) {} | ||
102 | |||
103 | // route does match with GET or HEAD method context | ||
104 | $matcher = new UrlMatcher($collection, new RequestContext()); | ||
105 | $this->assertInternalType('array', $matcher->match('/foo')); | ||
106 | $matcher = new UrlMatcher($collection, new RequestContext('', 'head')); | ||
107 | $this->assertInternalType('array', $matcher->match('/foo')); | ||
108 | |||
109 | // route with an optional variable as the first segment | ||
110 | $collection = new RouteCollection(); | ||
111 | $collection->add('bar', new Route('/{bar}/foo', array('bar' => 'bar'), array('bar' => 'foo|bar'))); | ||
112 | $matcher = new UrlMatcher($collection, new RequestContext()); | ||
113 | $this->assertEquals(array('_route' => 'bar', 'bar' => 'bar'), $matcher->match('/bar/foo')); | ||
114 | $this->assertEquals(array('_route' => 'bar', 'bar' => 'foo'), $matcher->match('/foo/foo')); | ||
115 | |||
116 | $collection = new RouteCollection(); | ||
117 | $collection->add('bar', new Route('/{bar}', array('bar' => 'bar'), array('bar' => 'foo|bar'))); | ||
118 | $matcher = new UrlMatcher($collection, new RequestContext()); | ||
119 | $this->assertEquals(array('_route' => 'bar', 'bar' => 'foo'), $matcher->match('/foo')); | ||
120 | $this->assertEquals(array('_route' => 'bar', 'bar' => 'bar'), $matcher->match('/')); | ||
121 | |||
122 | // route with only optional variables | ||
123 | $collection = new RouteCollection(); | ||
124 | $collection->add('bar', new Route('/{foo}/{bar}', array('foo' => 'foo', 'bar' => 'bar'), array())); | ||
125 | $matcher = new UrlMatcher($collection, new RequestContext()); | ||
126 | $this->assertEquals(array('_route' => 'bar', 'foo' => 'foo', 'bar' => 'bar'), $matcher->match('/')); | ||
127 | $this->assertEquals(array('_route' => 'bar', 'foo' => 'a', 'bar' => 'bar'), $matcher->match('/a')); | ||
128 | $this->assertEquals(array('_route' => 'bar', 'foo' => 'a', 'bar' => 'b'), $matcher->match('/a/b')); | ||
129 | } | ||
130 | |||
131 | public function testMatchWithPrefixes() | ||
132 | { | ||
133 | $collection = new RouteCollection(); | ||
134 | $collection->add('foo', new Route('/{foo}')); | ||
135 | $collection->addPrefix('/b'); | ||
136 | $collection->addPrefix('/a'); | ||
137 | |||
138 | $matcher = new UrlMatcher($collection, new RequestContext()); | ||
139 | $this->assertEquals(array('_route' => 'foo', 'foo' => 'foo'), $matcher->match('/a/b/foo')); | ||
140 | } | ||
141 | |||
142 | public function testMatchWithDynamicPrefix() | ||
143 | { | ||
144 | $collection = new RouteCollection(); | ||
145 | $collection->add('foo', new Route('/{foo}')); | ||
146 | $collection->addPrefix('/b'); | ||
147 | $collection->addPrefix('/{_locale}'); | ||
148 | |||
149 | $matcher = new UrlMatcher($collection, new RequestContext()); | ||
150 | $this->assertEquals(array('_locale' => 'fr', '_route' => 'foo', 'foo' => 'foo'), $matcher->match('/fr/b/foo')); | ||
151 | } | ||
152 | |||
153 | public function testMatchSpecialRouteName() | ||
154 | { | ||
155 | $collection = new RouteCollection(); | ||
156 | $collection->add('$péß^a|', new Route('/bar')); | ||
157 | |||
158 | $matcher = new UrlMatcher($collection, new RequestContext()); | ||
159 | $this->assertEquals(array('_route' => '$péß^a|'), $matcher->match('/bar')); | ||
160 | } | ||
161 | |||
162 | public function testMatchNonAlpha() | ||
163 | { | ||
164 | $collection = new RouteCollection(); | ||
165 | $chars = '!"$%éà &\'()*+,./:;<=>@ABCDEFGHIJKLMNOPQRSTUVWXYZ\\[]^_`abcdefghijklmnopqrstuvwxyz{|}~-'; | ||
166 | $collection->add('foo', new Route('/{foo}/bar', array(), array('foo' => '['.preg_quote($chars).']+'))); | ||
167 | |||
168 | $matcher = new UrlMatcher($collection, new RequestContext()); | ||
169 | $this->assertEquals(array('_route' => 'foo', 'foo' => $chars), $matcher->match('/'.rawurlencode($chars).'/bar')); | ||
170 | $this->assertEquals(array('_route' => 'foo', 'foo' => $chars), $matcher->match('/'.strtr($chars, array('%' => '%25')).'/bar')); | ||
171 | } | ||
172 | |||
173 | public function testMatchWithDotMetacharacterInRequirements() | ||
174 | { | ||
175 | $collection = new RouteCollection(); | ||
176 | $collection->add('foo', new Route('/{foo}/bar', array(), array('foo' => '.+'))); | ||
177 | |||
178 | $matcher = new UrlMatcher($collection, new RequestContext()); | ||
179 | $this->assertEquals(array('_route' => 'foo', 'foo' => "\n"), $matcher->match('/'.urlencode("\n").'/bar'), 'linefeed character is matched'); | ||
180 | } | ||
181 | |||
182 | public function testMatchOverriddenRoute() | ||
183 | { | ||
184 | $collection = new RouteCollection(); | ||
185 | $collection->add('foo', new Route('/foo')); | ||
186 | |||
187 | $collection1 = new RouteCollection(); | ||
188 | $collection1->add('foo', new Route('/foo1')); | ||
189 | |||
190 | $collection->addCollection($collection1); | ||
191 | |||
192 | $matcher = new UrlMatcher($collection, new RequestContext()); | ||
193 | |||
194 | $this->assertEquals(array('_route' => 'foo'), $matcher->match('/foo1')); | ||
195 | $this->setExpectedException('Symfony\Component\Routing\Exception\ResourceNotFoundException'); | ||
196 | $this->assertEquals(array(), $matcher->match('/foo')); | ||
197 | } | ||
198 | |||
199 | public function testMatchRegression() | ||
200 | { | ||
201 | $coll = new RouteCollection(); | ||
202 | $coll->add('foo', new Route('/foo/{foo}')); | ||
203 | $coll->add('bar', new Route('/foo/bar/{foo}')); | ||
204 | |||
205 | $matcher = new UrlMatcher($coll, new RequestContext()); | ||
206 | $this->assertEquals(array('foo' => 'bar', '_route' => 'bar'), $matcher->match('/foo/bar/bar')); | ||
207 | |||
208 | $collection = new RouteCollection(); | ||
209 | $collection->add('foo', new Route('/{bar}')); | ||
210 | $matcher = new UrlMatcher($collection, new RequestContext()); | ||
211 | try { | ||
212 | $matcher->match('/'); | ||
213 | $this->fail(); | ||
214 | } catch (ResourceNotFoundException $e) { | ||
215 | } | ||
216 | } | ||
217 | |||
218 | public function testDefaultRequirementForOptionalVariables() | ||
219 | { | ||
220 | $coll = new RouteCollection(); | ||
221 | $coll->add('test', new Route('/{page}.{_format}', array('page' => 'index', '_format' => 'html'))); | ||
222 | |||
223 | $matcher = new UrlMatcher($coll, new RequestContext()); | ||
224 | $this->assertEquals(array('page' => 'my-page', '_format' => 'xml', '_route' => 'test'), $matcher->match('/my-page.xml')); | ||
225 | } | ||
226 | |||
227 | public function testMatchingIsEager() | ||
228 | { | ||
229 | $coll = new RouteCollection(); | ||
230 | $coll->add('test', new Route('/{foo}-{bar}-', array(), array('foo' => '.+', 'bar' => '.+'))); | ||
231 | |||
232 | $matcher = new UrlMatcher($coll, new RequestContext()); | ||
233 | $this->assertEquals(array('foo' => 'text1-text2-text3', 'bar' => 'text4', '_route' => 'test'), $matcher->match('/text1-text2-text3-text4-')); | ||
234 | } | ||
235 | |||
236 | public function testAdjacentVariables() | ||
237 | { | ||
238 | $coll = new RouteCollection(); | ||
239 | $coll->add('test', new Route('/{w}{x}{y}{z}.{_format}', array('z' => 'default-z', '_format' => 'html'), array('y' => 'y|Y'))); | ||
240 | |||
241 | $matcher = new UrlMatcher($coll, new RequestContext()); | ||
242 | // 'w' eagerly matches as much as possible and the other variables match the remaining chars. | ||
243 | // This also shows that the variables w-z must all exclude the separating char (the dot '.' in this case) by default requirement. | ||
244 | // Otherwise they would also consume '.xml' and _format would never match as it's an optional variable. | ||
245 | $this->assertEquals(array('w' => 'wwwww', 'x' => 'x', 'y' => 'Y', 'z' => 'Z','_format' => 'xml', '_route' => 'test'), $matcher->match('/wwwwwxYZ.xml')); | ||
246 | // As 'y' has custom requirement and can only be of value 'y|Y', it will leave 'ZZZ' to variable z. | ||
247 | // So with carefully chosen requirements adjacent variables, can be useful. | ||
248 | $this->assertEquals(array('w' => 'wwwww', 'x' => 'x', 'y' => 'y', 'z' => 'ZZZ','_format' => 'html', '_route' => 'test'), $matcher->match('/wwwwwxyZZZ')); | ||
249 | // z and _format are optional. | ||
250 | $this->assertEquals(array('w' => 'wwwww', 'x' => 'x', 'y' => 'y', 'z' => 'default-z','_format' => 'html', '_route' => 'test'), $matcher->match('/wwwwwxy')); | ||
251 | |||
252 | $this->setExpectedException('Symfony\Component\Routing\Exception\ResourceNotFoundException'); | ||
253 | $matcher->match('/wxy.html'); | ||
254 | } | ||
255 | |||
256 | public function testOptionalVariableWithNoRealSeparator() | ||
257 | { | ||
258 | $coll = new RouteCollection(); | ||
259 | $coll->add('test', new Route('/get{what}', array('what' => 'All'))); | ||
260 | $matcher = new UrlMatcher($coll, new RequestContext()); | ||
261 | |||
262 | $this->assertEquals(array('what' => 'All', '_route' => 'test'), $matcher->match('/get')); | ||
263 | $this->assertEquals(array('what' => 'Sites', '_route' => 'test'), $matcher->match('/getSites')); | ||
264 | |||
265 | // Usually the character in front of an optional parameter can be left out, e.g. with pattern '/get/{what}' just '/get' would match. | ||
266 | // But here the 't' in 'get' is not a separating character, so it makes no sense to match without it. | ||
267 | $this->setExpectedException('Symfony\Component\Routing\Exception\ResourceNotFoundException'); | ||
268 | $matcher->match('/ge'); | ||
269 | } | ||
270 | |||
271 | public function testRequiredVariableWithNoRealSeparator() | ||
272 | { | ||
273 | $coll = new RouteCollection(); | ||
274 | $coll->add('test', new Route('/get{what}Suffix')); | ||
275 | $matcher = new UrlMatcher($coll, new RequestContext()); | ||
276 | |||
277 | $this->assertEquals(array('what' => 'Sites', '_route' => 'test'), $matcher->match('/getSitesSuffix')); | ||
278 | } | ||
279 | |||
280 | public function testDefaultRequirementOfVariable() | ||
281 | { | ||
282 | $coll = new RouteCollection(); | ||
283 | $coll->add('test', new Route('/{page}.{_format}')); | ||
284 | $matcher = new UrlMatcher($coll, new RequestContext()); | ||
285 | |||
286 | $this->assertEquals(array('page' => 'index', '_format' => 'mobile.html', '_route' => 'test'), $matcher->match('/index.mobile.html')); | ||
287 | } | ||
288 | |||
289 | /** | ||
290 | * @expectedException \Symfony\Component\Routing\Exception\ResourceNotFoundException | ||
291 | */ | ||
292 | public function testDefaultRequirementOfVariableDisallowsSlash() | ||
293 | { | ||
294 | $coll = new RouteCollection(); | ||
295 | $coll->add('test', new Route('/{page}.{_format}')); | ||
296 | $matcher = new UrlMatcher($coll, new RequestContext()); | ||
297 | |||
298 | $matcher->match('/index.sl/ash'); | ||
299 | } | ||
300 | |||
301 | /** | ||
302 | * @expectedException \Symfony\Component\Routing\Exception\ResourceNotFoundException | ||
303 | */ | ||
304 | public function testDefaultRequirementOfVariableDisallowsNextSeparator() | ||
305 | { | ||
306 | $coll = new RouteCollection(); | ||
307 | $coll->add('test', new Route('/{page}.{_format}', array(), array('_format' => 'html|xml'))); | ||
308 | $matcher = new UrlMatcher($coll, new RequestContext()); | ||
309 | |||
310 | $matcher->match('/do.t.html'); | ||
311 | } | ||
312 | |||
313 | /** | ||
314 | * @expectedException \Symfony\Component\Routing\Exception\ResourceNotFoundException | ||
315 | */ | ||
316 | public function testSchemeRequirement() | ||
317 | { | ||
318 | $coll = new RouteCollection(); | ||
319 | $coll->add('foo', new Route('/foo', array(), array('_scheme' => 'https'))); | ||
320 | $matcher = new UrlMatcher($coll, new RequestContext()); | ||
321 | $matcher->match('/foo'); | ||
322 | } | ||
323 | |||
324 | public function testDecodeOnce() | ||
325 | { | ||
326 | $coll = new RouteCollection(); | ||
327 | $coll->add('foo', new Route('/foo/{foo}')); | ||
328 | |||
329 | $matcher = new UrlMatcher($coll, new RequestContext()); | ||
330 | $this->assertEquals(array('foo' => 'bar%23', '_route' => 'foo'), $matcher->match('/foo/bar%2523')); | ||
331 | } | ||
332 | |||
333 | public function testCannotRelyOnPrefix() | ||
334 | { | ||
335 | $coll = new RouteCollection(); | ||
336 | |||
337 | $subColl = new RouteCollection(); | ||
338 | $subColl->add('bar', new Route('/bar')); | ||
339 | $subColl->addPrefix('/prefix'); | ||
340 | // overwrite the pattern, so the prefix is not valid anymore for this route in the collection | ||
341 | $subColl->get('bar')->setPattern('/new'); | ||
342 | |||
343 | $coll->addCollection($subColl); | ||
344 | |||
345 | $matcher = new UrlMatcher($coll, new RequestContext()); | ||
346 | $this->assertEquals(array('_route' => 'bar'), $matcher->match('/new')); | ||
347 | } | ||
348 | |||
349 | public function testWithHost() | ||
350 | { | ||
351 | $coll = new RouteCollection(); | ||
352 | $coll->add('foo', new Route('/foo/{foo}', array(), array(), array(), '{locale}.example.com')); | ||
353 | |||
354 | $matcher = new UrlMatcher($coll, new RequestContext('', 'GET', 'en.example.com')); | ||
355 | $this->assertEquals(array('foo' => 'bar', '_route' => 'foo', 'locale' => 'en'), $matcher->match('/foo/bar')); | ||
356 | } | ||
357 | |||
358 | public function testWithHostOnRouteCollection() | ||
359 | { | ||
360 | $coll = new RouteCollection(); | ||
361 | $coll->add('foo', new Route('/foo/{foo}')); | ||
362 | $coll->add('bar', new Route('/bar/{foo}', array(), array(), array(), '{locale}.example.net')); | ||
363 | $coll->setHost('{locale}.example.com'); | ||
364 | |||
365 | $matcher = new UrlMatcher($coll, new RequestContext('', 'GET', 'en.example.com')); | ||
366 | $this->assertEquals(array('foo' => 'bar', '_route' => 'foo', 'locale' => 'en'), $matcher->match('/foo/bar')); | ||
367 | |||
368 | $matcher = new UrlMatcher($coll, new RequestContext('', 'GET', 'en.example.com')); | ||
369 | $this->assertEquals(array('foo' => 'bar', '_route' => 'bar', 'locale' => 'en'), $matcher->match('/bar/bar')); | ||
370 | } | ||
371 | |||
372 | /** | ||
373 | * @expectedException \Symfony\Component\Routing\Exception\ResourceNotFoundException | ||
374 | */ | ||
375 | public function testWithOutHostHostDoesNotMatch() | ||
376 | { | ||
377 | $coll = new RouteCollection(); | ||
378 | $coll->add('foo', new Route('/foo/{foo}', array(), array(), array(), '{locale}.example.com')); | ||
379 | |||
380 | $matcher = new UrlMatcher($coll, new RequestContext('', 'GET', 'example.com')); | ||
381 | $matcher->match('/foo/bar'); | ||
382 | } | ||
383 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Tests/RouteCollectionTest.php b/vendor/symfony/routing/Symfony/Component/Routing/Tests/RouteCollectionTest.php new file mode 100644 index 00000000..3d78adf9 --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Tests/RouteCollectionTest.php | |||
@@ -0,0 +1,255 @@ | |||
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\Tests; | ||
13 | |||
14 | use Symfony\Component\Routing\RouteCollection; | ||
15 | use Symfony\Component\Routing\Route; | ||
16 | use Symfony\Component\Config\Resource\FileResource; | ||
17 | |||
18 | class RouteCollectionTest extends \PHPUnit_Framework_TestCase | ||
19 | { | ||
20 | public function testRoute() | ||
21 | { | ||
22 | $collection = new RouteCollection(); | ||
23 | $route = new Route('/foo'); | ||
24 | $collection->add('foo', $route); | ||
25 | $this->assertEquals(array('foo' => $route), $collection->all(), '->add() adds a route'); | ||
26 | $this->assertEquals($route, $collection->get('foo'), '->get() returns a route by name'); | ||
27 | $this->assertNull($collection->get('bar'), '->get() returns null if a route does not exist'); | ||
28 | } | ||
29 | |||
30 | public function testOverriddenRoute() | ||
31 | { | ||
32 | $collection = new RouteCollection(); | ||
33 | $collection->add('foo', new Route('/foo')); | ||
34 | $collection->add('foo', new Route('/foo1')); | ||
35 | |||
36 | $this->assertEquals('/foo1', $collection->get('foo')->getPath()); | ||
37 | } | ||
38 | |||
39 | public function testDeepOverriddenRoute() | ||
40 | { | ||
41 | $collection = new RouteCollection(); | ||
42 | $collection->add('foo', new Route('/foo')); | ||
43 | |||
44 | $collection1 = new RouteCollection(); | ||
45 | $collection1->add('foo', new Route('/foo1')); | ||
46 | |||
47 | $collection2 = new RouteCollection(); | ||
48 | $collection2->add('foo', new Route('/foo2')); | ||
49 | |||
50 | $collection1->addCollection($collection2); | ||
51 | $collection->addCollection($collection1); | ||
52 | |||
53 | $this->assertEquals('/foo2', $collection1->get('foo')->getPath()); | ||
54 | $this->assertEquals('/foo2', $collection->get('foo')->getPath()); | ||
55 | } | ||
56 | |||
57 | public function testIterator() | ||
58 | { | ||
59 | $collection = new RouteCollection(); | ||
60 | $collection->add('foo', new Route('/foo')); | ||
61 | |||
62 | $collection1 = new RouteCollection(); | ||
63 | $collection1->add('bar', $bar = new Route('/bar')); | ||
64 | $collection1->add('foo', $foo = new Route('/foo-new')); | ||
65 | $collection->addCollection($collection1); | ||
66 | $collection->add('last', $last = new Route('/last')); | ||
67 | |||
68 | $this->assertInstanceOf('\ArrayIterator', $collection->getIterator()); | ||
69 | $this->assertSame(array('bar' => $bar, 'foo' => $foo, 'last' => $last), $collection->getIterator()->getArrayCopy()); | ||
70 | } | ||
71 | |||
72 | public function testCount() | ||
73 | { | ||
74 | $collection = new RouteCollection(); | ||
75 | $collection->add('foo', new Route('/foo')); | ||
76 | |||
77 | $collection1 = new RouteCollection(); | ||
78 | $collection1->add('bar', new Route('/bar')); | ||
79 | $collection->addCollection($collection1); | ||
80 | |||
81 | $this->assertCount(2, $collection); | ||
82 | } | ||
83 | |||
84 | public function testAddCollection() | ||
85 | { | ||
86 | $collection = new RouteCollection(); | ||
87 | $collection->add('foo', new Route('/foo')); | ||
88 | |||
89 | $collection1 = new RouteCollection(); | ||
90 | $collection1->add('bar', $bar = new Route('/bar')); | ||
91 | $collection1->add('foo', $foo = new Route('/foo-new')); | ||
92 | |||
93 | $collection2 = new RouteCollection(); | ||
94 | $collection2->add('grandchild', $grandchild = new Route('/grandchild')); | ||
95 | |||
96 | $collection1->addCollection($collection2); | ||
97 | $collection->addCollection($collection1); | ||
98 | $collection->add('last', $last = new Route('/last')); | ||
99 | |||
100 | $this->assertSame(array('bar' => $bar, 'foo' => $foo, 'grandchild' => $grandchild, 'last' => $last), $collection->all(), | ||
101 | '->addCollection() imports routes of another collection, overrides if necessary and adds them at the end'); | ||
102 | } | ||
103 | |||
104 | public function testAddCollectionWithResources() | ||
105 | { | ||
106 | if (!class_exists('Symfony\Component\Config\Resource\FileResource')) { | ||
107 | $this->markTestSkipped('The "Config" component is not available'); | ||
108 | } | ||
109 | |||
110 | $collection = new RouteCollection(); | ||
111 | $collection->addResource($foo = new FileResource(__DIR__.'/Fixtures/foo.xml')); | ||
112 | $collection1 = new RouteCollection(); | ||
113 | $collection1->addResource($foo1 = new FileResource(__DIR__.'/Fixtures/foo1.xml')); | ||
114 | $collection->addCollection($collection1); | ||
115 | $this->assertEquals(array($foo, $foo1), $collection->getResources(), '->addCollection() merges resources'); | ||
116 | } | ||
117 | |||
118 | public function testAddDefaultsAndRequirementsAndOptions() | ||
119 | { | ||
120 | $collection = new RouteCollection(); | ||
121 | $collection->add('foo', new Route('/{placeholder}')); | ||
122 | $collection1 = new RouteCollection(); | ||
123 | $collection1->add('bar', new Route('/{placeholder}', | ||
124 | array('_controller' => 'fixed', 'placeholder' => 'default'), array('placeholder' => '.+'), array('option' => 'value')) | ||
125 | ); | ||
126 | $collection->addCollection($collection1); | ||
127 | |||
128 | $collection->addDefaults(array('placeholder' => 'new-default')); | ||
129 | $this->assertEquals(array('placeholder' => 'new-default'), $collection->get('foo')->getDefaults(), '->addDefaults() adds defaults to all routes'); | ||
130 | $this->assertEquals(array('_controller' => 'fixed', 'placeholder' => 'new-default'), $collection->get('bar')->getDefaults(), | ||
131 | '->addDefaults() adds defaults to all routes and overwrites existing ones'); | ||
132 | |||
133 | $collection->addRequirements(array('placeholder' => '\d+')); | ||
134 | $this->assertEquals(array('placeholder' => '\d+'), $collection->get('foo')->getRequirements(), '->addRequirements() adds requirements to all routes'); | ||
135 | $this->assertEquals(array('placeholder' => '\d+'), $collection->get('bar')->getRequirements(), | ||
136 | '->addRequirements() adds requirements to all routes and overwrites existing ones'); | ||
137 | |||
138 | $collection->addOptions(array('option' => 'new-value')); | ||
139 | $this->assertEquals( | ||
140 | array('option' => 'new-value', 'compiler_class' => 'Symfony\\Component\\Routing\\RouteCompiler'), | ||
141 | $collection->get('bar')->getOptions(), '->addOptions() adds options to all routes and overwrites existing ones' | ||
142 | ); | ||
143 | } | ||
144 | |||
145 | public function testAddPrefix() | ||
146 | { | ||
147 | $collection = new RouteCollection(); | ||
148 | $collection->add('foo', $foo = new Route('/foo')); | ||
149 | $collection2 = new RouteCollection(); | ||
150 | $collection2->add('bar', $bar = new Route('/bar')); | ||
151 | $collection->addCollection($collection2); | ||
152 | $collection->addPrefix(' / '); | ||
153 | $this->assertSame('/foo', $collection->get('foo')->getPattern(), '->addPrefix() trims the prefix and a single slash has no effect'); | ||
154 | $collection->addPrefix('/{admin}', array('admin' => 'admin'), array('admin' => '\d+')); | ||
155 | $this->assertEquals('/{admin}/foo', $collection->get('foo')->getPath(), '->addPrefix() adds a prefix to all routes'); | ||
156 | $this->assertEquals('/{admin}/bar', $collection->get('bar')->getPath(), '->addPrefix() adds a prefix to all routes'); | ||
157 | $this->assertEquals(array('admin' => 'admin'), $collection->get('foo')->getDefaults(), '->addPrefix() adds defaults to all routes'); | ||
158 | $this->assertEquals(array('admin' => 'admin'), $collection->get('bar')->getDefaults(), '->addPrefix() adds defaults to all routes'); | ||
159 | $this->assertEquals(array('admin' => '\d+'), $collection->get('foo')->getRequirements(), '->addPrefix() adds requirements to all routes'); | ||
160 | $this->assertEquals(array('admin' => '\d+'), $collection->get('bar')->getRequirements(), '->addPrefix() adds requirements to all routes'); | ||
161 | $collection->addPrefix('0'); | ||
162 | $this->assertEquals('/0/{admin}/foo', $collection->get('foo')->getPattern(), '->addPrefix() ensures a prefix must start with a slash and must not end with a slash'); | ||
163 | $collection->addPrefix('/ /'); | ||
164 | $this->assertSame('/ /0/{admin}/foo', $collection->get('foo')->getPath(), '->addPrefix() can handle spaces if desired'); | ||
165 | $this->assertSame('/ /0/{admin}/bar', $collection->get('bar')->getPath(), 'the route pattern of an added collection is in synch with the added prefix'); | ||
166 | } | ||
167 | |||
168 | public function testAddPrefixOverridesDefaultsAndRequirements() | ||
169 | { | ||
170 | $collection = new RouteCollection(); | ||
171 | $collection->add('foo', $foo = new Route('/foo')); | ||
172 | $collection->add('bar', $bar = new Route('/bar', array(), array('_scheme' => 'http'))); | ||
173 | $collection->addPrefix('/admin', array(), array('_scheme' => 'https')); | ||
174 | |||
175 | $this->assertEquals('https', $collection->get('foo')->getRequirement('_scheme'), '->addPrefix() overrides existing requirements'); | ||
176 | $this->assertEquals('https', $collection->get('bar')->getRequirement('_scheme'), '->addPrefix() overrides existing requirements'); | ||
177 | } | ||
178 | |||
179 | public function testResource() | ||
180 | { | ||
181 | if (!class_exists('Symfony\Component\Config\Resource\FileResource')) { | ||
182 | $this->markTestSkipped('The "Config" component is not available'); | ||
183 | } | ||
184 | |||
185 | $collection = new RouteCollection(); | ||
186 | $collection->addResource($foo = new FileResource(__DIR__.'/Fixtures/foo.xml')); | ||
187 | $collection->addResource($bar = new FileResource(__DIR__.'/Fixtures/bar.xml')); | ||
188 | $collection->addResource(new FileResource(__DIR__.'/Fixtures/foo.xml')); | ||
189 | |||
190 | $this->assertEquals(array($foo, $bar), $collection->getResources(), | ||
191 | '->addResource() adds a resource and getResources() only returns unique ones by comparing the string representation'); | ||
192 | } | ||
193 | |||
194 | public function testUniqueRouteWithGivenName() | ||
195 | { | ||
196 | $collection1 = new RouteCollection(); | ||
197 | $collection1->add('foo', new Route('/old')); | ||
198 | $collection2 = new RouteCollection(); | ||
199 | $collection3 = new RouteCollection(); | ||
200 | $collection3->add('foo', $new = new Route('/new')); | ||
201 | |||
202 | $collection2->addCollection($collection3); | ||
203 | $collection1->addCollection($collection2); | ||
204 | |||
205 | $this->assertSame($new, $collection1->get('foo'), '->get() returns new route that overrode previous one'); | ||
206 | // size of 1 because collection1 contains /new but not /old anymore | ||
207 | $this->assertCount(1, $collection1->getIterator(), '->addCollection() removes previous routes when adding new routes with the same name'); | ||
208 | } | ||
209 | |||
210 | public function testGet() | ||
211 | { | ||
212 | $collection1 = new RouteCollection(); | ||
213 | $collection1->add('a', $a = new Route('/a')); | ||
214 | $collection2 = new RouteCollection(); | ||
215 | $collection2->add('b', $b = new Route('/b')); | ||
216 | $collection1->addCollection($collection2); | ||
217 | $collection1->add('$péß^a|', $c = new Route('/special')); | ||
218 | |||
219 | $this->assertSame($b, $collection1->get('b'), '->get() returns correct route in child collection'); | ||
220 | $this->assertSame($c, $collection1->get('$péß^a|'), '->get() can handle special characters'); | ||
221 | $this->assertNull($collection2->get('a'), '->get() does not return the route defined in parent collection'); | ||
222 | $this->assertNull($collection1->get('non-existent'), '->get() returns null when route does not exist'); | ||
223 | $this->assertNull($collection1->get(0), '->get() does not disclose internal child RouteCollection'); | ||
224 | } | ||
225 | |||
226 | public function testRemove() | ||
227 | { | ||
228 | $collection = new RouteCollection(); | ||
229 | $collection->add('foo', $foo = new Route('/foo')); | ||
230 | |||
231 | $collection1 = new RouteCollection(); | ||
232 | $collection1->add('bar', $bar = new Route('/bar')); | ||
233 | $collection->addCollection($collection1); | ||
234 | $collection->add('last', $last = new Route('/last')); | ||
235 | |||
236 | $collection->remove('foo'); | ||
237 | $this->assertSame(array('bar' => $bar, 'last' => $last), $collection->all(), '->remove() can remove a single route'); | ||
238 | $collection->remove(array('bar', 'last')); | ||
239 | $this->assertSame(array(), $collection->all(), '->remove() accepts an array and can remove multiple routes at once'); | ||
240 | } | ||
241 | |||
242 | public function testSetHost() | ||
243 | { | ||
244 | $collection = new RouteCollection(); | ||
245 | $routea = new Route('/a'); | ||
246 | $routeb = new Route('/b', array(), array(), array(), '{locale}.example.net'); | ||
247 | $collection->add('a', $routea); | ||
248 | $collection->add('b', $routeb); | ||
249 | |||
250 | $collection->setHost('{locale}.example.com'); | ||
251 | |||
252 | $this->assertEquals('{locale}.example.com', $routea->getHost()); | ||
253 | $this->assertEquals('{locale}.example.com', $routeb->getHost()); | ||
254 | } | ||
255 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Tests/RouteCompilerTest.php b/vendor/symfony/routing/Symfony/Component/Routing/Tests/RouteCompilerTest.php new file mode 100644 index 00000000..d663ae96 --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Tests/RouteCompilerTest.php | |||
@@ -0,0 +1,253 @@ | |||
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\Tests; | ||
13 | |||
14 | use Symfony\Component\Routing\Route; | ||
15 | |||
16 | class RouteCompilerTest extends \PHPUnit_Framework_TestCase | ||
17 | { | ||
18 | /** | ||
19 | * @dataProvider provideCompileData | ||
20 | */ | ||
21 | public function testCompile($name, $arguments, $prefix, $regex, $variables, $tokens) | ||
22 | { | ||
23 | $r = new \ReflectionClass('Symfony\\Component\\Routing\\Route'); | ||
24 | $route = $r->newInstanceArgs($arguments); | ||
25 | |||
26 | $compiled = $route->compile(); | ||
27 | $this->assertEquals($prefix, $compiled->getStaticPrefix(), $name.' (static prefix)'); | ||
28 | $this->assertEquals($regex, $compiled->getRegex(), $name.' (regex)'); | ||
29 | $this->assertEquals($variables, $compiled->getVariables(), $name.' (variables)'); | ||
30 | $this->assertEquals($tokens, $compiled->getTokens(), $name.' (tokens)'); | ||
31 | } | ||
32 | |||
33 | public function provideCompileData() | ||
34 | { | ||
35 | return array( | ||
36 | array( | ||
37 | 'Static route', | ||
38 | array('/foo'), | ||
39 | '/foo', '#^/foo$#s', array(), array( | ||
40 | array('text', '/foo'), | ||
41 | )), | ||
42 | |||
43 | array( | ||
44 | 'Route with a variable', | ||
45 | array('/foo/{bar}'), | ||
46 | '/foo', '#^/foo/(?P<bar>[^/]++)$#s', array('bar'), array( | ||
47 | array('variable', '/', '[^/]++', 'bar'), | ||
48 | array('text', '/foo'), | ||
49 | )), | ||
50 | |||
51 | array( | ||
52 | 'Route with a variable that has a default value', | ||
53 | array('/foo/{bar}', array('bar' => 'bar')), | ||
54 | '/foo', '#^/foo(?:/(?P<bar>[^/]++))?$#s', array('bar'), array( | ||
55 | array('variable', '/', '[^/]++', 'bar'), | ||
56 | array('text', '/foo'), | ||
57 | )), | ||
58 | |||
59 | array( | ||
60 | 'Route with several variables', | ||
61 | array('/foo/{bar}/{foobar}'), | ||
62 | '/foo', '#^/foo/(?P<bar>[^/]++)/(?P<foobar>[^/]++)$#s', array('bar', 'foobar'), array( | ||
63 | array('variable', '/', '[^/]++', 'foobar'), | ||
64 | array('variable', '/', '[^/]++', 'bar'), | ||
65 | array('text', '/foo'), | ||
66 | )), | ||
67 | |||
68 | array( | ||
69 | 'Route with several variables that have default values', | ||
70 | array('/foo/{bar}/{foobar}', array('bar' => 'bar', 'foobar' => '')), | ||
71 | '/foo', '#^/foo(?:/(?P<bar>[^/]++)(?:/(?P<foobar>[^/]++))?)?$#s', array('bar', 'foobar'), array( | ||
72 | array('variable', '/', '[^/]++', 'foobar'), | ||
73 | array('variable', '/', '[^/]++', 'bar'), | ||
74 | array('text', '/foo'), | ||
75 | )), | ||
76 | |||
77 | array( | ||
78 | 'Route with several variables but some of them have no default values', | ||
79 | array('/foo/{bar}/{foobar}', array('bar' => 'bar')), | ||
80 | '/foo', '#^/foo/(?P<bar>[^/]++)/(?P<foobar>[^/]++)$#s', array('bar', 'foobar'), array( | ||
81 | array('variable', '/', '[^/]++', 'foobar'), | ||
82 | array('variable', '/', '[^/]++', 'bar'), | ||
83 | array('text', '/foo'), | ||
84 | )), | ||
85 | |||
86 | array( | ||
87 | 'Route with an optional variable as the first segment', | ||
88 | array('/{bar}', array('bar' => 'bar')), | ||
89 | '', '#^/(?P<bar>[^/]++)?$#s', array('bar'), array( | ||
90 | array('variable', '/', '[^/]++', 'bar'), | ||
91 | )), | ||
92 | |||
93 | array( | ||
94 | 'Route with a requirement of 0', | ||
95 | array('/{bar}', array('bar' => null), array('bar' => '0')), | ||
96 | '', '#^/(?P<bar>0)?$#s', array('bar'), array( | ||
97 | array('variable', '/', '0', 'bar'), | ||
98 | )), | ||
99 | |||
100 | array( | ||
101 | 'Route with an optional variable as the first segment with requirements', | ||
102 | array('/{bar}', array('bar' => 'bar'), array('bar' => '(foo|bar)')), | ||
103 | '', '#^/(?P<bar>(foo|bar))?$#s', array('bar'), array( | ||
104 | array('variable', '/', '(foo|bar)', 'bar'), | ||
105 | )), | ||
106 | |||
107 | array( | ||
108 | 'Route with only optional variables', | ||
109 | array('/{foo}/{bar}', array('foo' => 'foo', 'bar' => 'bar')), | ||
110 | '', '#^/(?P<foo>[^/]++)?(?:/(?P<bar>[^/]++))?$#s', array('foo', 'bar'), array( | ||
111 | array('variable', '/', '[^/]++', 'bar'), | ||
112 | array('variable', '/', '[^/]++', 'foo'), | ||
113 | )), | ||
114 | |||
115 | array( | ||
116 | 'Route with a variable in last position', | ||
117 | array('/foo-{bar}'), | ||
118 | '/foo', '#^/foo\-(?P<bar>[^/]++)$#s', array('bar'), array( | ||
119 | array('variable', '-', '[^/]++', 'bar'), | ||
120 | array('text', '/foo'), | ||
121 | )), | ||
122 | |||
123 | array( | ||
124 | 'Route with nested placeholders', | ||
125 | array('/{static{var}static}'), | ||
126 | '/{static', '#^/\{static(?P<var>[^/]+)static\}$#s', array('var'), array( | ||
127 | array('text', 'static}'), | ||
128 | array('variable', '', '[^/]+', 'var'), | ||
129 | array('text', '/{static'), | ||
130 | )), | ||
131 | |||
132 | array( | ||
133 | 'Route without separator between variables', | ||
134 | array('/{w}{x}{y}{z}.{_format}', array('z' => 'default-z', '_format' => 'html'), array('y' => '(y|Y)')), | ||
135 | '', '#^/(?P<w>[^/\.]+)(?P<x>[^/\.]+)(?P<y>(y|Y))(?:(?P<z>[^/\.]++)(?:\.(?P<_format>[^/]++))?)?$#s', array('w', 'x', 'y', 'z', '_format'), array( | ||
136 | array('variable', '.', '[^/]++', '_format'), | ||
137 | array('variable', '', '[^/\.]++', 'z'), | ||
138 | array('variable', '', '(y|Y)', 'y'), | ||
139 | array('variable', '', '[^/\.]+', 'x'), | ||
140 | array('variable', '/', '[^/\.]+', 'w'), | ||
141 | )), | ||
142 | |||
143 | array( | ||
144 | 'Route with a format', | ||
145 | array('/foo/{bar}.{_format}'), | ||
146 | '/foo', '#^/foo/(?P<bar>[^/\.]++)\.(?P<_format>[^/]++)$#s', array('bar', '_format'), array( | ||
147 | array('variable', '.', '[^/]++', '_format'), | ||
148 | array('variable', '/', '[^/\.]++', 'bar'), | ||
149 | array('text', '/foo'), | ||
150 | )), | ||
151 | ); | ||
152 | } | ||
153 | |||
154 | /** | ||
155 | * @expectedException \LogicException | ||
156 | */ | ||
157 | public function testRouteWithSameVariableTwice() | ||
158 | { | ||
159 | $route = new Route('/{name}/{name}'); | ||
160 | |||
161 | $compiled = $route->compile(); | ||
162 | } | ||
163 | |||
164 | /** | ||
165 | * @dataProvider getNumericVariableNames | ||
166 | * @expectedException \DomainException | ||
167 | */ | ||
168 | public function testRouteWithNumericVariableName($name) | ||
169 | { | ||
170 | $route = new Route('/{'. $name.'}'); | ||
171 | $route->compile(); | ||
172 | } | ||
173 | |||
174 | public function getNumericVariableNames() | ||
175 | { | ||
176 | return array( | ||
177 | array('09'), | ||
178 | array('123'), | ||
179 | array('1e2') | ||
180 | ); | ||
181 | } | ||
182 | |||
183 | /** | ||
184 | * @dataProvider provideCompileWithHostData | ||
185 | */ | ||
186 | public function testCompileWithHost($name, $arguments, $prefix, $regex, $variables, $pathVariables, $tokens, $hostRegex, $hostVariables, $hostTokens) | ||
187 | { | ||
188 | $r = new \ReflectionClass('Symfony\\Component\\Routing\\Route'); | ||
189 | $route = $r->newInstanceArgs($arguments); | ||
190 | |||
191 | $compiled = $route->compile(); | ||
192 | $this->assertEquals($prefix, $compiled->getStaticPrefix(), $name.' (static prefix)'); | ||
193 | $this->assertEquals($regex, str_replace(array("\n", ' '), '', $compiled->getRegex()), $name.' (regex)'); | ||
194 | $this->assertEquals($variables, $compiled->getVariables(), $name.' (variables)'); | ||
195 | $this->assertEquals($pathVariables, $compiled->getPathVariables(), $name.' (path variables)'); | ||
196 | $this->assertEquals($tokens, $compiled->getTokens(), $name.' (tokens)'); | ||
197 | $this->assertEquals($hostRegex, str_replace(array("\n", ' '), '', $compiled->getHostRegex()), $name.' (host regex)'); | ||
198 | $this->assertEquals($hostVariables, $compiled->getHostVariables(), $name.' (host variables)'); | ||
199 | $this->assertEquals($hostTokens, $compiled->getHostTokens(), $name.' (host tokens)'); | ||
200 | } | ||
201 | |||
202 | public function provideCompileWithHostData() | ||
203 | { | ||
204 | return array( | ||
205 | array( | ||
206 | 'Route with host pattern', | ||
207 | array('/hello', array(), array(), array(), 'www.example.com'), | ||
208 | '/hello', '#^/hello$#s', array(), array(), array( | ||
209 | array('text', '/hello'), | ||
210 | ), | ||
211 | '#^www\.example\.com$#s', array(), array( | ||
212 | array('text', 'www.example.com'), | ||
213 | ), | ||
214 | ), | ||
215 | array( | ||
216 | 'Route with host pattern and some variables', | ||
217 | array('/hello/{name}', array(), array(), array(), 'www.example.{tld}'), | ||
218 | '/hello', '#^/hello/(?P<name>[^/]++)$#s', array('tld', 'name'), array('name'), array( | ||
219 | array('variable', '/', '[^/]++', 'name'), | ||
220 | array('text', '/hello'), | ||
221 | ), | ||
222 | '#^www\.example\.(?P<tld>[^\.]++)$#s', array('tld'), array( | ||
223 | array('variable', '.', '[^\.]++', 'tld'), | ||
224 | array('text', 'www.example'), | ||
225 | ), | ||
226 | ), | ||
227 | array( | ||
228 | 'Route with variable at beginning of host', | ||
229 | array('/hello', array(), array(), array(), '{locale}.example.{tld}'), | ||
230 | '/hello', '#^/hello$#s', array('locale', 'tld'), array(), array( | ||
231 | array('text', '/hello'), | ||
232 | ), | ||
233 | '#^(?P<locale>[^\.]++)\.example\.(?P<tld>[^\.]++)$#s', array('locale', 'tld'), array( | ||
234 | array('variable', '.', '[^\.]++', 'tld'), | ||
235 | array('text', '.example'), | ||
236 | array('variable', '', '[^\.]++', 'locale'), | ||
237 | ), | ||
238 | ), | ||
239 | array( | ||
240 | 'Route with host variables that has a default value', | ||
241 | array('/hello', array('locale' => 'a', 'tld' => 'b'), array(), array(), '{locale}.example.{tld}'), | ||
242 | '/hello', '#^/hello$#s', array('locale', 'tld'), array(), array( | ||
243 | array('text', '/hello'), | ||
244 | ), | ||
245 | '#^(?P<locale>[^\.]++)\.example\.(?P<tld>[^\.]++)$#s', array('locale', 'tld'), array( | ||
246 | array('variable', '.', '[^\.]++', 'tld'), | ||
247 | array('text', '.example'), | ||
248 | array('variable', '', '[^\.]++', 'locale'), | ||
249 | ), | ||
250 | ), | ||
251 | ); | ||
252 | } | ||
253 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Tests/RouteTest.php b/vendor/symfony/routing/Symfony/Component/Routing/Tests/RouteTest.php new file mode 100644 index 00000000..31f1066f --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Tests/RouteTest.php | |||
@@ -0,0 +1,192 @@ | |||
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\Tests; | ||
13 | |||
14 | use Symfony\Component\Routing\Route; | ||
15 | |||
16 | class RouteTest extends \PHPUnit_Framework_TestCase | ||
17 | { | ||
18 | public function testConstructor() | ||
19 | { | ||
20 | $route = new Route('/{foo}', array('foo' => 'bar'), array('foo' => '\d+'), array('foo' => 'bar'), '{locale}.example.com'); | ||
21 | $this->assertEquals('/{foo}', $route->getPath(), '__construct() takes a path as its first argument'); | ||
22 | $this->assertEquals(array('foo' => 'bar'), $route->getDefaults(), '__construct() takes defaults as its second argument'); | ||
23 | $this->assertEquals(array('foo' => '\d+'), $route->getRequirements(), '__construct() takes requirements as its third argument'); | ||
24 | $this->assertEquals('bar', $route->getOption('foo'), '__construct() takes options as its fourth argument'); | ||
25 | $this->assertEquals('{locale}.example.com', $route->getHost(), '__construct() takes a host pattern as its fifth argument'); | ||
26 | |||
27 | $route = new Route('/', array(), array(), array(), '', array('Https'), array('POST', 'put')); | ||
28 | $this->assertEquals(array('https'), $route->getSchemes(), '__construct() takes schemes as its sixth argument and lowercases it'); | ||
29 | $this->assertEquals(array('POST', 'PUT'), $route->getMethods(), '__construct() takes methods as its seventh argument and uppercases it'); | ||
30 | |||
31 | $route = new Route('/', array(), array(), array(), '', 'Https', 'Post'); | ||
32 | $this->assertEquals(array('https'), $route->getSchemes(), '__construct() takes a single scheme as its sixth argument'); | ||
33 | $this->assertEquals(array('POST'), $route->getMethods(), '__construct() takes a single method as its seventh argument'); | ||
34 | } | ||
35 | |||
36 | public function testPath() | ||
37 | { | ||
38 | $route = new Route('/{foo}'); | ||
39 | $route->setPath('/{bar}'); | ||
40 | $this->assertEquals('/{bar}', $route->getPath(), '->setPath() sets the path'); | ||
41 | $route->setPath(''); | ||
42 | $this->assertEquals('/', $route->getPath(), '->setPath() adds a / at the beginning of the path if needed'); | ||
43 | $route->setPath('bar'); | ||
44 | $this->assertEquals('/bar', $route->getPath(), '->setPath() adds a / at the beginning of the path if needed'); | ||
45 | $this->assertEquals($route, $route->setPath(''), '->setPath() implements a fluent interface'); | ||
46 | $route->setPath('//path'); | ||
47 | $this->assertEquals('/path', $route->getPath(), '->setPath() does not allow two slahes "//" at the beginning of the path as it would be confused with a network path when generating the path from the route'); | ||
48 | } | ||
49 | |||
50 | public function testOptions() | ||
51 | { | ||
52 | $route = new Route('/{foo}'); | ||
53 | $route->setOptions(array('foo' => 'bar')); | ||
54 | $this->assertEquals(array_merge(array( | ||
55 | 'compiler_class' => 'Symfony\\Component\\Routing\\RouteCompiler', | ||
56 | ), array('foo' => 'bar')), $route->getOptions(), '->setOptions() sets the options'); | ||
57 | $this->assertEquals($route, $route->setOptions(array()), '->setOptions() implements a fluent interface'); | ||
58 | |||
59 | $route->setOptions(array('foo' => 'foo')); | ||
60 | $route->addOptions(array('bar' => 'bar')); | ||
61 | $this->assertEquals($route, $route->addOptions(array()), '->addOptions() implements a fluent interface'); | ||
62 | $this->assertEquals(array('foo' => 'foo', 'bar' => 'bar', 'compiler_class' => 'Symfony\\Component\\Routing\\RouteCompiler'), $route->getOptions(), '->addDefaults() keep previous defaults'); | ||
63 | } | ||
64 | |||
65 | public function testDefaults() | ||
66 | { | ||
67 | $route = new Route('/{foo}'); | ||
68 | $route->setDefaults(array('foo' => 'bar')); | ||
69 | $this->assertEquals(array('foo' => 'bar'), $route->getDefaults(), '->setDefaults() sets the defaults'); | ||
70 | $this->assertEquals($route, $route->setDefaults(array()), '->setDefaults() implements a fluent interface'); | ||
71 | |||
72 | $route->setDefault('foo', 'bar'); | ||
73 | $this->assertEquals('bar', $route->getDefault('foo'), '->setDefault() sets a default value'); | ||
74 | |||
75 | $route->setDefault('foo2', 'bar2'); | ||
76 | $this->assertEquals('bar2', $route->getDefault('foo2'), '->getDefault() return the default value'); | ||
77 | $this->assertNull($route->getDefault('not_defined'), '->getDefault() return null if default value is not setted'); | ||
78 | |||
79 | $route->setDefault('_controller', $closure = function () { return 'Hello'; }); | ||
80 | $this->assertEquals($closure, $route->getDefault('_controller'), '->setDefault() sets a default value'); | ||
81 | |||
82 | $route->setDefaults(array('foo' => 'foo')); | ||
83 | $route->addDefaults(array('bar' => 'bar')); | ||
84 | $this->assertEquals($route, $route->addDefaults(array()), '->addDefaults() implements a fluent interface'); | ||
85 | $this->assertEquals(array('foo' => 'foo', 'bar' => 'bar'), $route->getDefaults(), '->addDefaults() keep previous defaults'); | ||
86 | } | ||
87 | |||
88 | public function testRequirements() | ||
89 | { | ||
90 | $route = new Route('/{foo}'); | ||
91 | $route->setRequirements(array('foo' => '\d+')); | ||
92 | $this->assertEquals(array('foo' => '\d+'), $route->getRequirements(), '->setRequirements() sets the requirements'); | ||
93 | $this->assertEquals('\d+', $route->getRequirement('foo'), '->getRequirement() returns a requirement'); | ||
94 | $this->assertNull($route->getRequirement('bar'), '->getRequirement() returns null if a requirement is not defined'); | ||
95 | $route->setRequirements(array('foo' => '^\d+$')); | ||
96 | $this->assertEquals('\d+', $route->getRequirement('foo'), '->getRequirement() removes ^ and $ from the path'); | ||
97 | $this->assertEquals($route, $route->setRequirements(array()), '->setRequirements() implements a fluent interface'); | ||
98 | |||
99 | $route->setRequirements(array('foo' => '\d+')); | ||
100 | $route->addRequirements(array('bar' => '\d+')); | ||
101 | $this->assertEquals($route, $route->addRequirements(array()), '->addRequirements() implements a fluent interface'); | ||
102 | $this->assertEquals(array('foo' => '\d+', 'bar' => '\d+'), $route->getRequirements(), '->addRequirement() keep previous requirements'); | ||
103 | } | ||
104 | |||
105 | public function testRequirement() | ||
106 | { | ||
107 | $route = new Route('/{foo}'); | ||
108 | $route->setRequirement('foo', '^\d+$'); | ||
109 | $this->assertEquals('\d+', $route->getRequirement('foo'), '->setRequirement() removes ^ and $ from the path'); | ||
110 | } | ||
111 | |||
112 | /** | ||
113 | * @dataProvider getInvalidRequirements | ||
114 | * @expectedException \InvalidArgumentException | ||
115 | */ | ||
116 | public function testSetInvalidRequirement($req) | ||
117 | { | ||
118 | $route = new Route('/{foo}'); | ||
119 | $route->setRequirement('foo', $req); | ||
120 | } | ||
121 | |||
122 | public function getInvalidRequirements() | ||
123 | { | ||
124 | return array( | ||
125 | array(''), | ||
126 | array(array()), | ||
127 | array('^$'), | ||
128 | array('^'), | ||
129 | array('$') | ||
130 | ); | ||
131 | } | ||
132 | |||
133 | public function testHost() | ||
134 | { | ||
135 | $route = new Route('/'); | ||
136 | $route->setHost('{locale}.example.net'); | ||
137 | $this->assertEquals('{locale}.example.net', $route->getHost(), '->setHost() sets the host pattern'); | ||
138 | } | ||
139 | |||
140 | public function testScheme() | ||
141 | { | ||
142 | $route = new Route('/'); | ||
143 | $this->assertEquals(array(), $route->getSchemes(), 'schemes is initialized with array()'); | ||
144 | $route->setSchemes('hTTp'); | ||
145 | $this->assertEquals(array('http'), $route->getSchemes(), '->setSchemes() accepts a single scheme string and lowercases it'); | ||
146 | $route->setSchemes(array('HttpS', 'hTTp')); | ||
147 | $this->assertEquals(array('https', 'http'), $route->getSchemes(), '->setSchemes() accepts an array of schemes and lowercases them'); | ||
148 | } | ||
149 | |||
150 | public function testSchemeIsBC() | ||
151 | { | ||
152 | $route = new Route('/'); | ||
153 | $route->setRequirement('_scheme', 'http|https'); | ||
154 | $this->assertEquals('http|https', $route->getRequirement('_scheme')); | ||
155 | $this->assertEquals(array('http', 'https'), $route->getSchemes()); | ||
156 | $route->setSchemes(array('hTTp')); | ||
157 | $this->assertEquals('http', $route->getRequirement('_scheme')); | ||
158 | $route->setSchemes(array()); | ||
159 | $this->assertNull($route->getRequirement('_scheme')); | ||
160 | } | ||
161 | |||
162 | public function testMethod() | ||
163 | { | ||
164 | $route = new Route('/'); | ||
165 | $this->assertEquals(array(), $route->getMethods(), 'methods is initialized with array()'); | ||
166 | $route->setMethods('gEt'); | ||
167 | $this->assertEquals(array('GET'), $route->getMethods(), '->setMethods() accepts a single method string and uppercases it'); | ||
168 | $route->setMethods(array('gEt', 'PosT')); | ||
169 | $this->assertEquals(array('GET', 'POST'), $route->getMethods(), '->setMethods() accepts an array of methods and uppercases them'); | ||
170 | } | ||
171 | |||
172 | public function testMethodIsBC() | ||
173 | { | ||
174 | $route = new Route('/'); | ||
175 | $route->setRequirement('_method', 'GET|POST'); | ||
176 | $this->assertEquals('GET|POST', $route->getRequirement('_method')); | ||
177 | $this->assertEquals(array('GET', 'POST'), $route->getMethods()); | ||
178 | $route->setMethods(array('gEt')); | ||
179 | $this->assertEquals('GET', $route->getRequirement('_method')); | ||
180 | $route->setMethods(array()); | ||
181 | $this->assertNull($route->getRequirement('_method')); | ||
182 | } | ||
183 | |||
184 | public function testCompile() | ||
185 | { | ||
186 | $route = new Route('/{foo}'); | ||
187 | $this->assertInstanceOf('Symfony\Component\Routing\CompiledRoute', $compiled = $route->compile(), '->compile() returns a compiled route'); | ||
188 | $this->assertSame($compiled, $route->compile(), '->compile() only compiled the route once if unchanged'); | ||
189 | $route->setRequirement('foo', '.*'); | ||
190 | $this->assertNotSame($compiled, $route->compile(), '->compile() recompiles if the route was modified'); | ||
191 | } | ||
192 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/Tests/RouterTest.php b/vendor/symfony/routing/Symfony/Component/Routing/Tests/RouterTest.php new file mode 100644 index 00000000..a3c336e5 --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/Tests/RouterTest.php | |||
@@ -0,0 +1,138 @@ | |||
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\Tests; | ||
13 | |||
14 | use Symfony\Component\Routing\Router; | ||
15 | |||
16 | class RouterTest extends \PHPUnit_Framework_TestCase | ||
17 | { | ||
18 | private $router = null; | ||
19 | |||
20 | private $loader = null; | ||
21 | |||
22 | protected function setUp() | ||
23 | { | ||
24 | $this->loader = $this->getMock('Symfony\Component\Config\Loader\LoaderInterface'); | ||
25 | $this->router = new Router($this->loader, 'routing.yml'); | ||
26 | } | ||
27 | |||
28 | public function testSetOptionsWithSupportedOptions() | ||
29 | { | ||
30 | $this->router->setOptions(array( | ||
31 | 'cache_dir' => './cache', | ||
32 | 'debug' => true, | ||
33 | 'resource_type' => 'ResourceType' | ||
34 | )); | ||
35 | |||
36 | $this->assertSame('./cache', $this->router->getOption('cache_dir')); | ||
37 | $this->assertTrue($this->router->getOption('debug')); | ||
38 | $this->assertSame('ResourceType', $this->router->getOption('resource_type')); | ||
39 | } | ||
40 | |||
41 | /** | ||
42 | * @expectedException \InvalidArgumentException | ||
43 | * @expectedExceptionMessage The Router does not support the following options: "option_foo", "option_bar" | ||
44 | */ | ||
45 | public function testSetOptionsWithUnsupportedOptions() | ||
46 | { | ||
47 | $this->router->setOptions(array( | ||
48 | 'cache_dir' => './cache', | ||
49 | 'option_foo' => true, | ||
50 | 'option_bar' => 'baz', | ||
51 | 'resource_type' => 'ResourceType' | ||
52 | )); | ||
53 | } | ||
54 | |||
55 | public function testSetOptionWithSupportedOption() | ||
56 | { | ||
57 | $this->router->setOption('cache_dir', './cache'); | ||
58 | |||
59 | $this->assertSame('./cache', $this->router->getOption('cache_dir')); | ||
60 | } | ||
61 | |||
62 | /** | ||
63 | * @expectedException \InvalidArgumentException | ||
64 | * @expectedExceptionMessage The Router does not support the "option_foo" option | ||
65 | */ | ||
66 | public function testSetOptionWithUnsupportedOption() | ||
67 | { | ||
68 | $this->router->setOption('option_foo', true); | ||
69 | } | ||
70 | |||
71 | /** | ||
72 | * @expectedException \InvalidArgumentException | ||
73 | * @expectedExceptionMessage The Router does not support the "option_foo" option | ||
74 | */ | ||
75 | public function testGetOptionWithUnsupportedOption() | ||
76 | { | ||
77 | $this->router->getOption('option_foo', true); | ||
78 | } | ||
79 | |||
80 | public function testThatRouteCollectionIsLoaded() | ||
81 | { | ||
82 | $this->router->setOption('resource_type', 'ResourceType'); | ||
83 | |||
84 | $routeCollection = $this->getMock('Symfony\Component\Routing\RouteCollection'); | ||
85 | |||
86 | $this->loader->expects($this->once()) | ||
87 | ->method('load')->with('routing.yml', 'ResourceType') | ||
88 | ->will($this->returnValue($routeCollection)); | ||
89 | |||
90 | $this->assertSame($routeCollection, $this->router->getRouteCollection()); | ||
91 | } | ||
92 | |||
93 | /** | ||
94 | * @dataProvider provideMatcherOptionsPreventingCaching | ||
95 | */ | ||
96 | public function testMatcherIsCreatedIfCacheIsNotConfigured($option) | ||
97 | { | ||
98 | $this->router->setOption($option, null); | ||
99 | |||
100 | $this->loader->expects($this->once()) | ||
101 | ->method('load')->with('routing.yml', null) | ||
102 | ->will($this->returnValue($this->getMock('Symfony\Component\Routing\RouteCollection'))); | ||
103 | |||
104 | $this->assertInstanceOf('Symfony\\Component\\Routing\\Matcher\\UrlMatcher', $this->router->getMatcher()); | ||
105 | |||
106 | } | ||
107 | |||
108 | public function provideMatcherOptionsPreventingCaching() | ||
109 | { | ||
110 | return array( | ||
111 | array('cache_dir'), | ||
112 | array('matcher_cache_class') | ||
113 | ); | ||
114 | } | ||
115 | |||
116 | /** | ||
117 | * @dataProvider provideGeneratorOptionsPreventingCaching | ||
118 | */ | ||
119 | public function testGeneratorIsCreatedIfCacheIsNotConfigured($option) | ||
120 | { | ||
121 | $this->router->setOption($option, null); | ||
122 | |||
123 | $this->loader->expects($this->once()) | ||
124 | ->method('load')->with('routing.yml', null) | ||
125 | ->will($this->returnValue($this->getMock('Symfony\Component\Routing\RouteCollection'))); | ||
126 | |||
127 | $this->assertInstanceOf('Symfony\\Component\\Routing\\Generator\\UrlGenerator', $this->router->getGenerator()); | ||
128 | |||
129 | } | ||
130 | |||
131 | public function provideGeneratorOptionsPreventingCaching() | ||
132 | { | ||
133 | return array( | ||
134 | array('cache_dir'), | ||
135 | array('generator_cache_class') | ||
136 | ); | ||
137 | } | ||
138 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/composer.json b/vendor/symfony/routing/Symfony/Component/Routing/composer.json new file mode 100644 index 00000000..9a737c6b --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/composer.json | |||
@@ -0,0 +1,42 @@ | |||
1 | { | ||
2 | "name": "symfony/routing", | ||
3 | "type": "library", | ||
4 | "description": "Symfony Routing Component", | ||
5 | "keywords": [], | ||
6 | "homepage": "http://symfony.com", | ||
7 | "license": "MIT", | ||
8 | "authors": [ | ||
9 | { | ||
10 | "name": "Fabien Potencier", | ||
11 | "email": "fabien@symfony.com" | ||
12 | }, | ||
13 | { | ||
14 | "name": "Symfony Community", | ||
15 | "homepage": "http://symfony.com/contributors" | ||
16 | } | ||
17 | ], | ||
18 | "require": { | ||
19 | "php": ">=5.3.3" | ||
20 | }, | ||
21 | "require-dev": { | ||
22 | "symfony/config": "~2.2", | ||
23 | "symfony/yaml": "~2.0", | ||
24 | "doctrine/common": "~2.2", | ||
25 | "psr/log": "~1.0" | ||
26 | }, | ||
27 | "suggest": { | ||
28 | "symfony/config": "", | ||
29 | "symfony/yaml": "", | ||
30 | "doctrine/common": "" | ||
31 | }, | ||
32 | "autoload": { | ||
33 | "psr-0": { "Symfony\\Component\\Routing\\": "" } | ||
34 | }, | ||
35 | "target-dir": "Symfony/Component/Routing", | ||
36 | "minimum-stability": "dev", | ||
37 | "extra": { | ||
38 | "branch-alias": { | ||
39 | "dev-master": "2.3-dev" | ||
40 | } | ||
41 | } | ||
42 | } | ||
diff --git a/vendor/symfony/routing/Symfony/Component/Routing/phpunit.xml.dist b/vendor/symfony/routing/Symfony/Component/Routing/phpunit.xml.dist new file mode 100644 index 00000000..830066aa --- /dev/null +++ b/vendor/symfony/routing/Symfony/Component/Routing/phpunit.xml.dist | |||
@@ -0,0 +1,29 @@ | |||
1 | <?xml version="1.0" encoding="UTF-8"?> | ||
2 | |||
3 | <phpunit backupGlobals="false" | ||
4 | backupStaticAttributes="false" | ||
5 | colors="true" | ||
6 | convertErrorsToExceptions="true" | ||
7 | convertNoticesToExceptions="true" | ||
8 | convertWarningsToExceptions="true" | ||
9 | processIsolation="false" | ||
10 | stopOnFailure="false" | ||
11 | syntaxCheck="false" | ||
12 | bootstrap="vendor/autoload.php" | ||
13 | > | ||
14 | <testsuites> | ||
15 | <testsuite name="Symfony Routing Component Test Suite"> | ||
16 | <directory>./Tests/</directory> | ||
17 | </testsuite> | ||
18 | </testsuites> | ||
19 | |||
20 | <filter> | ||
21 | <whitelist> | ||
22 | <directory>./</directory> | ||
23 | <exclude> | ||
24 | <directory>./vendor</directory> | ||
25 | <directory>./Tests</directory> | ||
26 | </exclude> | ||
27 | </whitelist> | ||
28 | </filter> | ||
29 | </phpunit> | ||