vendor/friendsofsymfony/rest-bundle/Routing/Loader/RestXmlCollectionLoader.php line 14

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of the FOSRestBundle package.
  4.  *
  5.  * (c) FriendsOfSymfony <http://friendsofsymfony.github.com/>
  6.  *
  7.  * For the full copyright and license information, please view the LICENSE
  8.  * file that was distributed with this source code.
  9.  */
  10. namespace FOS\RestBundle\Routing\Loader;
  11. @trigger_error(sprintf('The %s\RestXmlCollectionLoader class is deprecated since FOSRestBundle 2.8.'__NAMESPACE__), E_USER_DEPRECATED);
  12. use FOS\RestBundle\Routing\RestRouteCollection;
  13. use Symfony\Component\Config\FileLocatorInterface;
  14. use Symfony\Component\Config\Util\XmlUtils;
  15. use Symfony\Component\Routing\Loader\XmlFileLoader;
  16. use Symfony\Component\Routing\RouteCollection;
  17. /**
  18.  * RestXmlCollectionLoader XML file collections loader.
  19.  *
  20.  * @author Donald Tyler <[email protected]>
  21.  *
  22.  * @deprecated since 2.8
  23.  */
  24. class RestXmlCollectionLoader extends XmlFileLoader
  25. {
  26.     protected $collectionParents = [];
  27.     private $processor;
  28.     private $includeFormat;
  29.     private $formats;
  30.     private $defaultFormat;
  31.     /**
  32.      * @param string[] $formats
  33.      */
  34.     public function __construct(
  35.         FileLocatorInterface $locator,
  36.         RestRouteProcessor $processor,
  37.         bool $includeFormat true,
  38.         array $formats = [],
  39.         string $defaultFormat null
  40.     ) {
  41.         parent::__construct($locator);
  42.         $this->processor $processor;
  43.         $this->includeFormat $includeFormat;
  44.         $this->formats $formats;
  45.         $this->defaultFormat $defaultFormat;
  46.     }
  47.     /**
  48.      * {@inheritdoc}
  49.      */
  50.     protected function parseNode(RouteCollection $collection, \DOMElement $node$path$file)
  51.     {
  52.         switch ($node->tagName) {
  53.             case 'route':
  54.                 $this->parseRoute($collection$node$path);
  55.                 break;
  56.             case 'import':
  57.                 $name = (string) $node->getAttribute('id');
  58.                 $resource = (string) $node->getAttribute('resource');
  59.                 $prefix = (string) $node->getAttribute('prefix');
  60.                 $namePrefix = (string) $node->getAttribute('name-prefix');
  61.                 $parent = (string) $node->getAttribute('parent');
  62.                 $type = (string) $node->getAttribute('type');
  63.                 $host = isset($config['host']) ? $config['host'] : null;
  64.                 $currentDir dirname($path);
  65.                 $parents = [];
  66.                 if (!empty($parent)) {
  67.                     if (!isset($this->collectionParents[$parent])) {
  68.                         throw new \InvalidArgumentException(sprintf('Cannot find parent resource with name %s'$parent));
  69.                     }
  70.                     $parents $this->collectionParents[$parent];
  71.                 }
  72.                 $imported $this->processor->importResource($this$resource$parents$prefix$namePrefix$type$currentDir);
  73.                 if (!empty($name) && $imported instanceof RestRouteCollection) {
  74.                     $parents[] = (!empty($prefix) ? $prefix.'/' '').$imported->getSingularName();
  75.                     $prefix null;
  76.                     $this->collectionParents[$name] = $parents;
  77.                 }
  78.                 if (!empty($host)) {
  79.                     $imported->setHost($host);
  80.                 }
  81.                 $imported->addPrefix((string) $prefix);
  82.                 $collection->addCollection($imported);
  83.                 break;
  84.             default:
  85.                 throw new \InvalidArgumentException(sprintf('Unable to parse tag "%s"'$node->tagName));
  86.         }
  87.     }
  88.     /**
  89.      * {@inheritdoc}
  90.      */
  91.     protected function parseRoute(RouteCollection $collection, \DOMElement $node$path)
  92.     {
  93.         if ($this->includeFormat) {
  94.             $path $node->getAttribute('path');
  95.             // append format placeholder if not present
  96.             if (false === strpos($path'{_format}')) {
  97.                 $node->setAttribute('path'$path.'.{_format}');
  98.             }
  99.             // set format requirement if configured globally
  100.             $requirements $node->getElementsByTagNameNS(self::NAMESPACE_URI'requirement');
  101.             $format null;
  102.             for ($i 0$i $requirements->length; ++$i) {
  103.                 $item $requirements->item($i);
  104.                 if ($item instanceof \DOMElement && $item->hasAttribute('_format')) {
  105.                     $format $item->getAttribute('_format');
  106.                     break;
  107.                 }
  108.             }
  109.             if (null === $format && !empty($this->formats)) {
  110.                 $requirement $node->ownerDocument->createElementNs(
  111.                     self::NAMESPACE_URI,
  112.                     'requirement',
  113.                     implode('|'array_keys($this->formats))
  114.                 );
  115.                 $requirement->setAttribute('key''_format');
  116.                 $node->appendChild($requirement);
  117.             }
  118.         }
  119.         // set the default format if configured
  120.         if (null !== $this->defaultFormat) {
  121.             $defaultFormatNode $node->ownerDocument->createElementNS(
  122.                 self::NAMESPACE_URI,
  123.                 'default',
  124.                 $this->defaultFormat
  125.             );
  126.             $defaultFormatNode->setAttribute('key''_format');
  127.             $node->appendChild($defaultFormatNode);
  128.         }
  129.         $options $this->getOptions($node);
  130.         foreach ($options as $option) {
  131.             $node->appendChild($option);
  132.         }
  133.         $length $node->childNodes->length;
  134.         for ($i 0$i $length; ++$i) {
  135.             $loopNode $node->childNodes->item($i);
  136.             if (XML_TEXT_NODE === $loopNode->nodeType) {
  137.                 continue;
  138.             }
  139.             $newNode $node->ownerDocument->createElementNS(
  140.                 self::NAMESPACE_URI,
  141.                 $loopNode->nodeName,
  142.                 $loopNode->nodeValue
  143.             );
  144.             foreach ($loopNode->attributes as $value) {
  145.                 $newNode->setAttribute($value->name$value->value);
  146.             }
  147.             $node->appendChild($newNode);
  148.         }
  149.         parent::parseRoute($collection$node$path);
  150.     }
  151.     private function getOptions(\DOMElement $node)
  152.     {
  153.         $options = [];
  154.         foreach ($node->childNodes as $child) {
  155.             if ($child instanceof \DOMElement && 'option' === $child->tagName) {
  156.                 $option $node->ownerDocument->createElementNs(
  157.                     self::NAMESPACE_URI,
  158.                     'option',
  159.                     $child->nodeValue
  160.                 );
  161.                 $option->setAttribute('key'$child->getAttribute('key'));
  162.                 $options[] = $option;
  163.             }
  164.         }
  165.         return $options;
  166.     }
  167.     /**
  168.      * {@inheritdoc}
  169.      */
  170.     public function supports($resource$type null)
  171.     {
  172.         return is_string($resource) &&
  173.             'xml' === pathinfo($resourcePATHINFO_EXTENSION) &&
  174.             'rest' === $type;
  175.     }
  176.     protected function validate(\DOMDocument $dom)
  177.     {
  178.         $restRoutinglocation realpath(__DIR__.'/../../Resources/config/schema/routing/rest_routing-1.0.xsd');
  179.         $restRoutinglocation rawurlencode(str_replace('\\''/'$restRoutinglocation));
  180.         $routinglocation realpath(__DIR__.'/../../Resources/config/schema/routing-1.0.xsd');
  181.         $routinglocation rawurlencode(str_replace('\\''/'$routinglocation));
  182.         $source = <<<EOF
  183. <?xml version="1.0" encoding="utf-8" ?>
  184. <xsd:schema xmlns="http://symfony.com/schema"
  185.     xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  186.     targetNamespace="http://symfony.com/schema"
  187.     elementFormDefault="qualified">
  188.     <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
  189.     <xsd:import namespace="http://friendsofsymfony.github.com/schema/rest" schemaLocation="$restRoutinglocation" />
  190.     <xsd:import namespace="http://symfony.com/schema/routing" schemaLocation="$routinglocation" />
  191. </xsd:schema>
  192. EOF;
  193.         $current libxml_use_internal_errors(true);
  194.         libxml_clear_errors();
  195.         if (!$dom->schemaValidateSource($source)) {
  196.             throw new \InvalidArgumentException(implode("\n"$this->getXmlErrors_($current)));
  197.         }
  198.         libxml_use_internal_errors($current);
  199.     }
  200.     /**
  201.      * {@inheritdoc}
  202.      *
  203.      * @internal
  204.      */
  205.     protected function loadFile($file)
  206.     {
  207.         if (class_exists(XmlUtils::class)) {
  208.             $dom XmlUtils::loadFile($file);
  209.             $this->validate($dom);
  210.             return $dom;
  211.         }
  212.         return parent::loadFile($file);
  213.     }
  214.     /**
  215.      * Retrieves libxml errors and clears them.
  216.      *
  217.      * Note: The underscore postfix on the method name is to ensure compatibility with versions
  218.      *       before 2.0.16 while working around a bug in PHP https://bugs.php.net/bug.php?id=62956
  219.      */
  220.     private function getXmlErrors_(bool $internalErrors): array
  221.     {
  222.         $errors = [];
  223.         foreach (libxml_get_errors() as $error) {
  224.             $errors[] = sprintf(
  225.                 '[%s %s] %s (in %s - line %d, column %d)',
  226.                 LIBXML_ERR_WARNING === $error->level 'WARNING' 'ERROR',
  227.                 $error->code,
  228.                 trim($error->message),
  229.                 $error->file $error->file 'n/a',
  230.                 $error->line,
  231.                 $error->column
  232.             );
  233.         }
  234.         libxml_clear_errors();
  235.         libxml_use_internal_errors($internalErrors);
  236.         return $errors;
  237.     }
  238. }