diff options
Diffstat (limited to 'vendor/symfony/routing/Symfony/Component/Routing/Loader')
8 files changed, 1073 insertions, 0 deletions
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> | ||