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.
Auf den Verzeichnisnamen klicken, dies zeigt nur das Verzeichnis mit Inhalt an

(Beispiel Datei-Icons)

Auf das Icon klicken um den Quellcode anzuzeigen

XmlFileLoader.php

Zuletzt modifiziert: 02.04.2025, 15:03 - Dateigröße: 13.11 KiB


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