Fix bug in style changes for the Use cases on the live site.
[yaffs-website] / vendor / symfony / 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 class XmlFileLoader extends FileLoader
27 {
28     const NAMESPACE_URI = 'http://symfony.com/schema/routing';
29     const SCHEME_PATH = '/schema/routing/routing-1.0.xsd';
30
31     /**
32      * Loads an XML file.
33      *
34      * @param string      $file An XML file path
35      * @param string|null $type The resource type
36      *
37      * @return RouteCollection A RouteCollection instance
38      *
39      * @throws \InvalidArgumentException When the file cannot be loaded or when the XML cannot be
40      *                                   parsed because it does not validate against the scheme.
41      */
42     public function load($file, $type = null)
43     {
44         $path = $this->locator->locate($file);
45
46         $xml = $this->loadFile($path);
47
48         $collection = new RouteCollection();
49         $collection->addResource(new FileResource($path));
50
51         // process routes and imports
52         foreach ($xml->documentElement->childNodes as $node) {
53             if (!$node instanceof \DOMElement) {
54                 continue;
55             }
56
57             $this->parseNode($collection, $node, $path, $file);
58         }
59
60         return $collection;
61     }
62
63     /**
64      * Parses a node from a loaded XML file.
65      *
66      * @param RouteCollection $collection Collection to associate with the node
67      * @param \DOMElement     $node       Element to parse
68      * @param string          $path       Full path of the XML file being processed
69      * @param string          $file       Loaded file name
70      *
71      * @throws \InvalidArgumentException When the XML is invalid
72      */
73     protected function parseNode(RouteCollection $collection, \DOMElement $node, $path, $file)
74     {
75         if (self::NAMESPACE_URI !== $node->namespaceURI) {
76             return;
77         }
78
79         switch ($node->localName) {
80             case 'route':
81                 $this->parseRoute($collection, $node, $path);
82                 break;
83             case 'import':
84                 $this->parseImport($collection, $node, $path, $file);
85                 break;
86             default:
87                 throw new \InvalidArgumentException(sprintf('Unknown tag "%s" used in file "%s". Expected "route" or "import".', $node->localName, $path));
88         }
89     }
90
91     /**
92      * {@inheritdoc}
93      */
94     public function supports($resource, $type = null)
95     {
96         return is_string($resource) && 'xml' === pathinfo($resource, PATHINFO_EXTENSION) && (!$type || 'xml' === $type);
97     }
98
99     /**
100      * Parses a route and adds it to the RouteCollection.
101      *
102      * @param RouteCollection $collection RouteCollection instance
103      * @param \DOMElement     $node       Element to parse that represents a Route
104      * @param string          $path       Full path of the XML file being processed
105      *
106      * @throws \InvalidArgumentException When the XML is invalid
107      */
108     protected function parseRoute(RouteCollection $collection, \DOMElement $node, $path)
109     {
110         if ('' === ($id = $node->getAttribute('id')) || (!$node->hasAttribute('pattern') && !$node->hasAttribute('path'))) {
111             throw new \InvalidArgumentException(sprintf('The <route> element in file "%s" must have an "id" and a "path" attribute.', $path));
112         }
113
114         if ($node->hasAttribute('pattern')) {
115             if ($node->hasAttribute('path')) {
116                 throw new \InvalidArgumentException(sprintf('The <route> element in file "%s" cannot define both a "path" and a "pattern" attribute. Use only "path".', $path));
117             }
118
119             @trigger_error(sprintf('The "pattern" option in file "%s" is deprecated since version 2.2 and will be removed in 3.0. Use the "path" option in the route definition instead.', $path), E_USER_DEPRECATED);
120
121             $node->setAttribute('path', $node->getAttribute('pattern'));
122             $node->removeAttribute('pattern');
123         }
124
125         $schemes = preg_split('/[\s,\|]++/', $node->getAttribute('schemes'), -1, PREG_SPLIT_NO_EMPTY);
126         $methods = preg_split('/[\s,\|]++/', $node->getAttribute('methods'), -1, PREG_SPLIT_NO_EMPTY);
127
128         list($defaults, $requirements, $options, $condition) = $this->parseConfigs($node, $path);
129
130         if (isset($requirements['_method'])) {
131             if (0 === count($methods)) {
132                 $methods = explode('|', $requirements['_method']);
133             }
134
135             unset($requirements['_method']);
136             @trigger_error(sprintf('The "_method" requirement of route "%s" in file "%s" is deprecated since version 2.2 and will be removed in 3.0. Use the "methods" attribute instead.', $id, $path), E_USER_DEPRECATED);
137         }
138
139         if (isset($requirements['_scheme'])) {
140             if (0 === count($schemes)) {
141                 $schemes = explode('|', $requirements['_scheme']);
142             }
143
144             unset($requirements['_scheme']);
145             @trigger_error(sprintf('The "_scheme" requirement of route "%s" in file "%s" is deprecated since version 2.2 and will be removed in 3.0. Use the "schemes" attribute instead.', $id, $path), E_USER_DEPRECATED);
146         }
147
148         $route = new Route($node->getAttribute('path'), $defaults, $requirements, $options, $node->getAttribute('host'), $schemes, $methods, $condition);
149         $collection->add($id, $route);
150     }
151
152     /**
153      * Parses an import and adds the routes in the resource to the RouteCollection.
154      *
155      * @param RouteCollection $collection RouteCollection instance
156      * @param \DOMElement     $node       Element to parse that represents a Route
157      * @param string          $path       Full path of the XML file being processed
158      * @param string          $file       Loaded file name
159      *
160      * @throws \InvalidArgumentException When the XML is invalid
161      */
162     protected function parseImport(RouteCollection $collection, \DOMElement $node, $path, $file)
163     {
164         if ('' === $resource = $node->getAttribute('resource')) {
165             throw new \InvalidArgumentException(sprintf('The <import> element in file "%s" must have a "resource" attribute.', $path));
166         }
167
168         $type = $node->getAttribute('type');
169         $prefix = $node->getAttribute('prefix');
170         $host = $node->hasAttribute('host') ? $node->getAttribute('host') : null;
171         $schemes = $node->hasAttribute('schemes') ? preg_split('/[\s,\|]++/', $node->getAttribute('schemes'), -1, PREG_SPLIT_NO_EMPTY) : null;
172         $methods = $node->hasAttribute('methods') ? preg_split('/[\s,\|]++/', $node->getAttribute('methods'), -1, PREG_SPLIT_NO_EMPTY) : null;
173
174         list($defaults, $requirements, $options, $condition) = $this->parseConfigs($node, $path);
175
176         $this->setCurrentDir(dirname($path));
177
178         $subCollection = $this->import($resource, ('' !== $type ? $type : null), false, $file);
179         /* @var $subCollection RouteCollection */
180         $subCollection->addPrefix($prefix);
181         if (null !== $host) {
182             $subCollection->setHost($host);
183         }
184         if (null !== $condition) {
185             $subCollection->setCondition($condition);
186         }
187         if (null !== $schemes) {
188             $subCollection->setSchemes($schemes);
189         }
190         if (null !== $methods) {
191             $subCollection->setMethods($methods);
192         }
193         $subCollection->addDefaults($defaults);
194         $subCollection->addRequirements($requirements);
195         $subCollection->addOptions($options);
196
197         $collection->addCollection($subCollection);
198     }
199
200     /**
201      * Loads an XML file.
202      *
203      * @param string $file An XML file path
204      *
205      * @return \DOMDocument
206      *
207      * @throws \InvalidArgumentException When loading of XML file fails because of syntax errors
208      *                                   or when the XML structure is not as expected by the scheme -
209      *                                   see validate()
210      */
211     protected function loadFile($file)
212     {
213         return XmlUtils::loadFile($file, __DIR__.static::SCHEME_PATH);
214     }
215
216     /**
217      * Parses the config elements (default, requirement, option).
218      *
219      * @param \DOMElement $node Element to parse that contains the configs
220      * @param string      $path Full path of the XML file being processed
221      *
222      * @return array An array with the defaults as first item, requirements as second and options as third
223      *
224      * @throws \InvalidArgumentException When the XML is invalid
225      */
226     private function parseConfigs(\DOMElement $node, $path)
227     {
228         $defaults = array();
229         $requirements = array();
230         $options = array();
231         $condition = null;
232
233         foreach ($node->getElementsByTagNameNS(self::NAMESPACE_URI, '*') as $n) {
234             switch ($n->localName) {
235                 case 'default':
236                     if ($this->isElementValueNull($n)) {
237                         $defaults[$n->getAttribute('key')] = null;
238                     } else {
239                         $defaults[$n->getAttribute('key')] = trim($n->textContent);
240                     }
241
242                     break;
243                 case 'requirement':
244                     $requirements[$n->getAttribute('key')] = trim($n->textContent);
245                     break;
246                 case 'option':
247                     $options[$n->getAttribute('key')] = trim($n->textContent);
248                     break;
249                 case 'condition':
250                     $condition = trim($n->textContent);
251                     break;
252                 default:
253                     throw new \InvalidArgumentException(sprintf('Unknown tag "%s" used in file "%s". Expected "default", "requirement" or "option".', $n->localName, $path));
254             }
255         }
256
257         return array($defaults, $requirements, $options, $condition);
258     }
259
260     private function isElementValueNull(\DOMElement $element)
261     {
262         $namespaceUri = 'http://www.w3.org/2001/XMLSchema-instance';
263
264         if (!$element->hasAttributeNS($namespaceUri, 'nil')) {
265             return false;
266         }
267
268         return 'true' === $element->getAttributeNS($namespaceUri, 'nil') || '1' === $element->getAttributeNS($namespaceUri, 'nil');
269     }
270 }