]> git.immae.eu Git - github/wallabag/wallabag.git/blob - vendor/symfony/routing/Symfony/Component/Routing/Loader/XmlFileLoader.php
twig implementation
[github/wallabag/wallabag.git] / vendor / symfony / routing / Symfony / Component / Routing / Loader / XmlFileLoader.php
1 <?php
2
3 /*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12 namespace Symfony\Component\Routing\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 }