vendor/symfony/routing/RouteCollection.php line 26

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of the Symfony package.
  4.  *
  5.  * (c) Fabien Potencier <[email protected]>
  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 Symfony\Component\Routing;
  11. use Symfony\Component\Config\Resource\ResourceInterface;
  12. /**
  13.  * A RouteCollection represents a set of Route instances.
  14.  *
  15.  * When adding a route at the end of the collection, an existing route
  16.  * with the same name is removed first. So there can only be one route
  17.  * with a given name.
  18.  *
  19.  * @author Fabien Potencier <[email protected]>
  20.  * @author Tobias Schultze <http://tobion.de>
  21.  */
  22. class RouteCollection implements \IteratorAggregate, \Countable
  23. {
  24.     /**
  25.      * @var Route[]
  26.      */
  27.     private $routes = [];
  28.     /**
  29.      * @var array
  30.      */
  31.     private $resources = [];
  32.     /**
  33.      * @var int[]
  34.      */
  35.     private $priorities = [];
  36.     public function __clone()
  37.     {
  38.         foreach ($this->routes as $name => $route) {
  39.             $this->routes[$name] = clone $route;
  40.         }
  41.     }
  42.     /**
  43.      * Gets the current RouteCollection as an Iterator that includes all routes.
  44.      *
  45.      * It implements \IteratorAggregate.
  46.      *
  47.      * @see all()
  48.      *
  49.      * @return \ArrayIterator|Route[] An \ArrayIterator object for iterating over routes
  50.      */
  51.     public function getIterator()
  52.     {
  53.         return new \ArrayIterator($this->all());
  54.     }
  55.     /**
  56.      * Gets the number of Routes in this collection.
  57.      *
  58.      * @return int The number of routes
  59.      */
  60.     public function count()
  61.     {
  62.         return \count($this->routes);
  63.     }
  64.     /**
  65.      * @param int $priority
  66.      */
  67.     public function add(string $nameRoute $route/*, int $priority = 0*/)
  68.     {
  69.         if (\func_num_args() < && __CLASS__ !== static::class && __CLASS__ !== (new \ReflectionMethod($this__FUNCTION__))->getDeclaringClass()->getName() && !$this instanceof \PHPUnit\Framework\MockObject\MockObject && !$this instanceof \Prophecy\Prophecy\ProphecySubjectInterface) {
  70.             trigger_deprecation('symfony/routing''5.1''The "%s()" method will have a new "int $priority = 0" argument in version 6.0, not defining it is deprecated.'__METHOD__);
  71.         }
  72.         unset($this->routes[$name], $this->priorities[$name]);
  73.         $this->routes[$name] = $route;
  74.         if ($priority <= \func_num_args() ? func_get_arg(2) : 0) {
  75.             $this->priorities[$name] = $priority;
  76.         }
  77.     }
  78.     /**
  79.      * Returns all routes in this collection.
  80.      *
  81.      * @return Route[] An array of routes
  82.      */
  83.     public function all()
  84.     {
  85.         if ($this->priorities) {
  86.             $priorities $this->priorities;
  87.             $keysOrder array_flip(array_keys($this->routes));
  88.             uksort($this->routes, static function ($n1$n2) use ($priorities$keysOrder) {
  89.                 return (($priorities[$n2] ?? 0) <=> ($priorities[$n1] ?? 0)) ?: ($keysOrder[$n1] <=> $keysOrder[$n2]);
  90.             });
  91.         }
  92.         return $this->routes;
  93.     }
  94.     /**
  95.      * Gets a route by name.
  96.      *
  97.      * @return Route|null A Route instance or null when not found
  98.      */
  99.     public function get(string $name)
  100.     {
  101.         return isset($this->routes[$name]) ? $this->routes[$name] : null;
  102.     }
  103.     /**
  104.      * Removes a route or an array of routes by name from the collection.
  105.      *
  106.      * @param string|string[] $name The route name or an array of route names
  107.      */
  108.     public function remove($name)
  109.     {
  110.         foreach ((array) $name as $n) {
  111.             unset($this->routes[$n], $this->priorities[$n]);
  112.         }
  113.     }
  114.     /**
  115.      * Adds a route collection at the end of the current set by appending all
  116.      * routes of the added collection.
  117.      */
  118.     public function addCollection(self $collection)
  119.     {
  120.         // we need to remove all routes with the same names first because just replacing them
  121.         // would not place the new route at the end of the merged array
  122.         foreach ($collection->all() as $name => $route) {
  123.             unset($this->routes[$name], $this->priorities[$name]);
  124.             $this->routes[$name] = $route;
  125.             if (isset($collection->priorities[$name])) {
  126.                 $this->priorities[$name] = $collection->priorities[$name];
  127.             }
  128.         }
  129.         foreach ($collection->getResources() as $resource) {
  130.             $this->addResource($resource);
  131.         }
  132.     }
  133.     /**
  134.      * Adds a prefix to the path of all child routes.
  135.      */
  136.     public function addPrefix(string $prefix, array $defaults = [], array $requirements = [])
  137.     {
  138.         $prefix trim(trim($prefix), '/');
  139.         if ('' === $prefix) {
  140.             return;
  141.         }
  142.         foreach ($this->routes as $route) {
  143.             $route->setPath('/'.$prefix.$route->getPath());
  144.             $route->addDefaults($defaults);
  145.             $route->addRequirements($requirements);
  146.         }
  147.     }
  148.     /**
  149.      * Adds a prefix to the name of all the routes within in the collection.
  150.      */
  151.     public function addNamePrefix(string $prefix)
  152.     {
  153.         $prefixedRoutes = [];
  154.         $prefixedPriorities = [];
  155.         foreach ($this->routes as $name => $route) {
  156.             $prefixedRoutes[$prefix.$name] = $route;
  157.             if (null !== $canonicalName $route->getDefault('_canonical_route')) {
  158.                 $route->setDefault('_canonical_route'$prefix.$canonicalName);
  159.             }
  160.             if (isset($this->priorities[$name])) {
  161.                 $prefixedPriorities[$prefix.$name] = $this->priorities[$name];
  162.             }
  163.         }
  164.         $this->routes $prefixedRoutes;
  165.         $this->priorities $prefixedPriorities;
  166.     }
  167.     /**
  168.      * Sets the host pattern on all routes.
  169.      */
  170.     public function setHost(?string $pattern, array $defaults = [], array $requirements = [])
  171.     {
  172.         foreach ($this->routes as $route) {
  173.             $route->setHost($pattern);
  174.             $route->addDefaults($defaults);
  175.             $route->addRequirements($requirements);
  176.         }
  177.     }
  178.     /**
  179.      * Sets a condition on all routes.
  180.      *
  181.      * Existing conditions will be overridden.
  182.      */
  183.     public function setCondition(?string $condition)
  184.     {
  185.         foreach ($this->routes as $route) {
  186.             $route->setCondition($condition);
  187.         }
  188.     }
  189.     /**
  190.      * Adds defaults to all routes.
  191.      *
  192.      * An existing default value under the same name in a route will be overridden.
  193.      */
  194.     public function addDefaults(array $defaults)
  195.     {
  196.         if ($defaults) {
  197.             foreach ($this->routes as $route) {
  198.                 $route->addDefaults($defaults);
  199.             }
  200.         }
  201.     }
  202.     /**
  203.      * Adds requirements to all routes.
  204.      *
  205.      * An existing requirement under the same name in a route will be overridden.
  206.      */
  207.     public function addRequirements(array $requirements)
  208.     {
  209.         if ($requirements) {
  210.             foreach ($this->routes as $route) {
  211.                 $route->addRequirements($requirements);
  212.             }
  213.         }
  214.     }
  215.     /**
  216.      * Adds options to all routes.
  217.      *
  218.      * An existing option value under the same name in a route will be overridden.
  219.      */
  220.     public function addOptions(array $options)
  221.     {
  222.         if ($options) {
  223.             foreach ($this->routes as $route) {
  224.                 $route->addOptions($options);
  225.             }
  226.         }
  227.     }
  228.     /**
  229.      * Sets the schemes (e.g. 'https') all child routes are restricted to.
  230.      *
  231.      * @param string|string[] $schemes The scheme or an array of schemes
  232.      */
  233.     public function setSchemes($schemes)
  234.     {
  235.         foreach ($this->routes as $route) {
  236.             $route->setSchemes($schemes);
  237.         }
  238.     }
  239.     /**
  240.      * Sets the HTTP methods (e.g. 'POST') all child routes are restricted to.
  241.      *
  242.      * @param string|string[] $methods The method or an array of methods
  243.      */
  244.     public function setMethods($methods)
  245.     {
  246.         foreach ($this->routes as $route) {
  247.             $route->setMethods($methods);
  248.         }
  249.     }
  250.     /**
  251.      * Returns an array of resources loaded to build this collection.
  252.      *
  253.      * @return ResourceInterface[] An array of resources
  254.      */
  255.     public function getResources()
  256.     {
  257.         return array_values($this->resources);
  258.     }
  259.     /**
  260.      * Adds a resource for this collection. If the resource already exists
  261.      * it is not added.
  262.      */
  263.     public function addResource(ResourceInterface $resource)
  264.     {
  265.         $key = (string) $resource;
  266.         if (!isset($this->resources[$key])) {
  267.             $this->resources[$key] = $resource;
  268.         }
  269.     }
  270. }