Verzeichnisstruktur phpBB-3.3.15
- Veröffentlicht
- 28.08.2024
So funktioniert es
|
Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück |
Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis. |
|
(Beispiel Datei-Icons)
|
Auf das Icon klicken um den Quellcode anzuzeigen |
XmlFileLoader.php
001 <?php
002
003 /*
004 * This file is part of the Symfony package.
005 *
006 * (c) Fabien Potencier <fabien@symfony.com>
007 *
008 * For the full copyright and license information, please view the LICENSE
009 * file that was distributed with this source code.
010 */
011
012 namespace Symfony\Component\Routing\Loader;
013
014 use Symfony\Component\Config\Loader\FileLoader;
015 use Symfony\Component\Config\Resource\FileResource;
016 use Symfony\Component\Config\Util\XmlUtils;
017 use Symfony\Component\Routing\Route;
018 use Symfony\Component\Routing\RouteCollection;
019
020 /**
021 * XmlFileLoader loads XML routing files.
022 *
023 * @author Fabien Potencier <fabien@symfony.com>
024 * @author Tobias Schultze <http://tobion.de>
025 */
026 class XmlFileLoader extends FileLoader
027 {
028 const NAMESPACE_URI = 'http://symfony.com/schema/routing';
029 const SCHEME_PATH = '/schema/routing/routing-1.0.xsd';
030
031 /**
032 * Loads an XML file.
033 *
034 * @param string $file An XML file path
035 * @param string|null $type The resource type
036 *
037 * @return RouteCollection A RouteCollection instance
038 *
039 * @throws \InvalidArgumentException when the file cannot be loaded or when the XML cannot be
040 * parsed because it does not validate against the scheme
041 */
042 public function load($file, $type = null)
043 {
044 $path = $this->locator->locate($file);
045
046 $xml = $this->loadFile($path);
047
048 $collection = new RouteCollection();
049 $collection->addResource(new FileResource($path));
050
051 // process routes and imports
052 foreach ($xml->documentElement->childNodes as $node) {
053 if (!$node instanceof \DOMElement) {
054 continue;
055 }
056
057 $this->parseNode($collection, $node, $path, $file);
058 }
059
060 return $collection;
061 }
062
063 /**
064 * Parses a node from a loaded XML file.
065 *
066 * @param RouteCollection $collection Collection to associate with the node
067 * @param \DOMElement $node Element to parse
068 * @param string $path Full path of the XML file being processed
069 * @param string $file Loaded file name
070 *
071 * @throws \InvalidArgumentException When the XML is invalid
072 */
073 protected function parseNode(RouteCollection $collection, \DOMElement $node, $path, $file)
074 {
075 if (self::NAMESPACE_URI !== $node->namespaceURI) {
076 return;
077 }
078
079 switch ($node->localName) {
080 case 'route':
081 $this->parseRoute($collection, $node, $path);
082 break;
083 case 'import':
084 $this->parseImport($collection, $node, $path, $file);
085 break;
086 default:
087 throw new \InvalidArgumentException(sprintf('Unknown tag "%s" used in file "%s". Expected "route" or "import".', $node->localName, $path));
088 }
089 }
090
091 /**
092 * {@inheritdoc}
093 */
094 public function supports($resource, $type = null)
095 {
096 return \is_string($resource) && 'xml' === pathinfo($resource, \PATHINFO_EXTENSION) && (!$type || 'xml' === $type);
097 }
098
099 /**
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('path')) {
111 throw new \InvalidArgumentException(sprintf('The <route> element in file "%s" must have an "id" and a "path" attribute.', $path));
112 }
113
114 $schemes = preg_split('/[\s,\|]++/', $node->getAttribute('schemes'), -1, \PREG_SPLIT_NO_EMPTY);
115 $methods = preg_split('/[\s,\|]++/', $node->getAttribute('methods'), -1, \PREG_SPLIT_NO_EMPTY);
116
117 list($defaults, $requirements, $options, $condition) = $this->parseConfigs($node, $path);
118
119 $route = new Route($node->getAttribute('path'), $defaults, $requirements, $options, $node->getAttribute('host'), $schemes, $methods, $condition);
120 $collection->add($id, $route);
121 }
122
123 /**
124 * Parses an import and adds the routes in the resource to the RouteCollection.
125 *
126 * @param RouteCollection $collection RouteCollection instance
127 * @param \DOMElement $node Element to parse that represents a Route
128 * @param string $path Full path of the XML file being processed
129 * @param string $file Loaded file name
130 *
131 * @throws \InvalidArgumentException When the XML is invalid
132 */
133 protected function parseImport(RouteCollection $collection, \DOMElement $node, $path, $file)
134 {
135 if ('' === $resource = $node->getAttribute('resource')) {
136 throw new \InvalidArgumentException(sprintf('The <import> element in file "%s" must have a "resource" attribute.', $path));
137 }
138
139 $type = $node->getAttribute('type');
140 $prefix = $node->getAttribute('prefix');
141 $host = $node->hasAttribute('host') ? $node->getAttribute('host') : null;
142 $schemes = $node->hasAttribute('schemes') ? preg_split('/[\s,\|]++/', $node->getAttribute('schemes'), -1, \PREG_SPLIT_NO_EMPTY) : null;
143 $methods = $node->hasAttribute('methods') ? preg_split('/[\s,\|]++/', $node->getAttribute('methods'), -1, \PREG_SPLIT_NO_EMPTY) : null;
144
145 list($defaults, $requirements, $options, $condition) = $this->parseConfigs($node, $path);
146
147 $this->setCurrentDir(\dirname($path));
148
149 /** @var RouteCollection[] $imported */
150 $imported = $this->import($resource, ('' !== $type ? $type : null), false, $file) ?: [];
151
152 if (!\is_array($imported)) {
153 $imported = [$imported];
154 }
155
156 foreach ($imported as $subCollection) {
157 /* @var $subCollection RouteCollection */
158 $subCollection->addPrefix($prefix);
159 if (null !== $host) {
160 $subCollection->setHost($host);
161 }
162 if (null !== $condition) {
163 $subCollection->setCondition($condition);
164 }
165 if (null !== $schemes) {
166 $subCollection->setSchemes($schemes);
167 }
168 if (null !== $methods) {
169 $subCollection->setMethods($methods);
170 }
171 $subCollection->addDefaults($defaults);
172 $subCollection->addRequirements($requirements);
173 $subCollection->addOptions($options);
174
175 $collection->addCollection($subCollection);
176 }
177 }
178
179 /**
180 * Loads an XML file.
181 *
182 * @param string $file An XML file path
183 *
184 * @return \DOMDocument
185 *
186 * @throws \InvalidArgumentException When loading of XML file fails because of syntax errors
187 * or when the XML structure is not as expected by the scheme -
188 * see validate()
189 */
190 protected function loadFile($file)
191 {
192 return XmlUtils::loadFile($file, __DIR__.static::SCHEME_PATH);
193 }
194
195 /**
196 * Parses the config elements (default, requirement, option).
197 *
198 * @param \DOMElement $node Element to parse that contains the configs
199 * @param string $path Full path of the XML file being processed
200 *
201 * @return array An array with the defaults as first item, requirements as second and options as third
202 *
203 * @throws \InvalidArgumentException When the XML is invalid
204 */
205 private function parseConfigs(\DOMElement $node, $path)
206 {
207 $defaults = [];
208 $requirements = [];
209 $options = [];
210 $condition = null;
211
212 /** @var \DOMElement $n */
213 foreach ($node->getElementsByTagNameNS(self::NAMESPACE_URI, '*') as $n) {
214 if ($node !== $n->parentNode) {
215 continue;
216 }
217
218 switch ($n->localName) {
219 case 'default':
220 if ($this->isElementValueNull($n)) {
221 $defaults[$n->getAttribute('key')] = null;
222 } else {
223 $defaults[$n->getAttribute('key')] = $this->parseDefaultsConfig($n, $path);
224 }
225
226 break;
227 case 'requirement':
228 $requirements[$n->getAttribute('key')] = trim($n->textContent);
229 break;
230 case 'option':
231 $options[$n->getAttribute('key')] = XmlUtils::phpize(trim($n->textContent));
232 break;
233 case 'condition':
234 $condition = trim($n->textContent);
235 break;
236 default:
237 throw new \InvalidArgumentException(sprintf('Unknown tag "%s" used in file "%s". Expected "default", "requirement", "option" or "condition".', $n->localName, $path));
238 }
239 }
240
241 if ($controller = $node->getAttribute('controller')) {
242 if (isset($defaults['_controller'])) {
243 $name = $node->hasAttribute('id') ? sprintf('"%s".', $node->getAttribute('id')) : sprintf('the "%s" tag.', $node->tagName);
244
245 throw new \InvalidArgumentException(sprintf('The routing file "%s" must not specify both the "controller" attribute and the defaults key "_controller" for ', $path).$name);
246 }
247
248 $defaults['_controller'] = $controller;
249 }
250
251 return [$defaults, $requirements, $options, $condition];
252 }
253
254 /**
255 * Parses the "default" elements.
256 *
257 * @param \DOMElement $element The "default" element to parse
258 * @param string $path Full path of the XML file being processed
259 *
260 * @return array|bool|float|int|string|null The parsed value of the "default" element
261 */
262 private function parseDefaultsConfig(\DOMElement $element, $path)
263 {
264 if ($this->isElementValueNull($element)) {
265 return null;
266 }
267
268 // Check for existing element nodes in the default element. There can
269 // only be a single element inside a default element. So this element
270 // (if one was found) can safely be returned.
271 foreach ($element->childNodes as $child) {
272 if (!$child instanceof \DOMElement) {
273 continue;
274 }
275
276 if (self::NAMESPACE_URI !== $child->namespaceURI) {
277 continue;
278 }
279
280 return $this->parseDefaultNode($child, $path);
281 }
282
283 // If the default element doesn't contain a nested "bool", "int", "float",
284 // "string", "list", or "map" element, the element contents will be treated
285 // as the string value of the associated default option.
286 return trim($element->textContent);
287 }
288
289 /**
290 * Recursively parses the value of a "default" element.
291 *
292 * @param \DOMElement $node The node value
293 * @param string $path Full path of the XML file being processed
294 *
295 * @return array|bool|float|int|string The parsed value
296 *
297 * @throws \InvalidArgumentException when the XML is invalid
298 */
299 private function parseDefaultNode(\DOMElement $node, $path)
300 {
301 if ($this->isElementValueNull($node)) {
302 return null;
303 }
304
305 switch ($node->localName) {
306 case 'bool':
307 return 'true' === trim($node->nodeValue) || '1' === trim($node->nodeValue);
308 case 'int':
309 return (int) trim($node->nodeValue);
310 case 'float':
311 return (float) trim($node->nodeValue);
312 case 'string':
313 return trim($node->nodeValue);
314 case 'list':
315 $list = [];
316
317 foreach ($node->childNodes as $element) {
318 if (!$element instanceof \DOMElement) {
319 continue;
320 }
321
322 if (self::NAMESPACE_URI !== $element->namespaceURI) {
323 continue;
324 }
325
326 $list[] = $this->parseDefaultNode($element, $path);
327 }
328
329 return $list;
330 case 'map':
331 $map = [];
332
333 foreach ($node->childNodes as $element) {
334 if (!$element instanceof \DOMElement) {
335 continue;
336 }
337
338 if (self::NAMESPACE_URI !== $element->namespaceURI) {
339 continue;
340 }
341
342 $map[$element->getAttribute('key')] = $this->parseDefaultNode($element, $path);
343 }
344
345 return $map;
346 default:
347 throw new \InvalidArgumentException(sprintf('Unknown tag "%s" used in file "%s". Expected "bool", "int", "float", "string", "list", or "map".', $node->localName, $path));
348 }
349 }
350
351 private function isElementValueNull(\DOMElement $element)
352 {
353 $namespaceUri = 'http://www.w3.org/2001/XMLSchema-instance';
354
355 if (!$element->hasAttributeNS($namespaceUri, 'nil')) {
356 return false;
357 }
358
359 return 'true' === $element->getAttributeNS($namespaceUri, 'nil') || '1' === $element->getAttributeNS($namespaceUri, 'nil');
360 }
361 }
362