Verzeichnisstruktur phpBB-3.3.16


Veröffentlicht
27.04.2026

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: 01.05.2026, 11:27 - 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