[ Index ]

PHP Cross Reference of phpBB-3.3.3-deutsch

title

Body

[close]

/vendor/symfony/routing/Loader/ -> XmlFileLoader.php (source)

   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\Config\Loader\FileLoader;
  15  use Symfony\Component\Config\Resource\FileResource;
  16  use Symfony\Component\Config\Util\XmlUtils;
  17  use Symfony\Component\Routing\Route;
  18  use Symfony\Component\Routing\RouteCollection;
  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('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  }


Generated: Sun Feb 14 20:08:31 2021 Cross-referenced by PHPXref 0.7.1