vendor/symfony-cmf/routing/src/NestedMatcher/NestedMatcher.php line 141

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of the Symfony CMF package.
  4.  *
  5.  * (c) 2011-2017 Symfony CMF
  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\Cmf\Component\Routing\NestedMatcher;
  11. use Symfony\Cmf\Component\Routing\RouteProviderInterface;
  12. use Symfony\Component\HttpFoundation\Request;
  13. use Symfony\Component\Routing\Exception\ResourceNotFoundException;
  14. use Symfony\Component\Routing\Matcher\RequestMatcherInterface;
  15. /**
  16.  * A more flexible approach to matching. The route collection to match against
  17.  * can be dynamically determined based on the request and users can inject
  18.  * their own filters or use a custom final matching strategy.
  19.  *
  20.  * The nested matcher splits matching into three configurable steps:
  21.  *
  22.  * 1) Get potential matches from a RouteProviderInterface
  23.  * 2) Apply any RouteFilterInterface to reduce the route collection
  24.  * 3) Have FinalMatcherInterface select the best match of the remaining routes
  25.  *
  26.  * @author Larry Garfield
  27.  * @author David Buchmann
  28.  */
  29. class NestedMatcher implements RequestMatcherInterface
  30. {
  31.     /**
  32.      * The route provider responsible for the first-pass match.
  33.      *
  34.      * @var RouteProviderInterface
  35.      */
  36.     protected $routeProvider;
  37.     /**
  38.      * The final matcher.
  39.      *
  40.      * @var FinalMatcherInterface
  41.      */
  42.     protected $finalMatcher;
  43.     /**
  44.      * An array of RouteFilterInterface objects.
  45.      *
  46.      * @var RouteFilterInterface[]
  47.      */
  48.     protected $filters = [];
  49.     /**
  50.      * Array of RouteFilterInterface objects, sorted.
  51.      *
  52.      * @var RouteFilterInterface[]
  53.      */
  54.     protected $sortedFilters = [];
  55.     /**
  56.      * Constructs a new NestedMatcher.
  57.      *
  58.      * @param RouteProviderInterface $provider The route provider this matcher
  59.      *                                         should use
  60.      * @param FinalMatcherInterface  $final    The Final Matcher to match the
  61.      *                                         routes
  62.      */
  63.     public function __construct(
  64.         RouteProviderInterface $provider null,
  65.         FinalMatcherInterface $final null
  66.     ) {
  67.         if (null !== $provider) {
  68.             $this->setRouteProvider($provider);
  69.         }
  70.         if (null !== $final) {
  71.             $this->setFinalMatcher($final);
  72.         }
  73.     }
  74.     /**
  75.      * Sets the route provider for the matching plan.
  76.      *
  77.      * @param RouteProviderInterface $provider A source of routes
  78.      *
  79.      * @return NestedMatcher this object to have a fluent interface
  80.      */
  81.     public function setRouteProvider(RouteProviderInterface $provider)
  82.     {
  83.         $this->routeProvider $provider;
  84.         return $this;
  85.     }
  86.     /**
  87.      * Adds a partial matcher to the matching plan.
  88.      *
  89.      * Partial matchers will be run in the order in which they are added.
  90.      *
  91.      * @param RouteFilterInterface $filter
  92.      * @param int                  $priority (optional) The priority of the
  93.      *                                       filter. Higher number filters will
  94.      *                                       be used first. Defaults to 0
  95.      *
  96.      * @return NestedMatcher this object to have a fluent interface
  97.      */
  98.     public function addRouteFilter(RouteFilterInterface $filter$priority 0)
  99.     {
  100.         if (empty($this->filters[$priority])) {
  101.             $this->filters[$priority] = [];
  102.         }
  103.         $this->filters[$priority][] = $filter;
  104.         $this->sortedFilters = [];
  105.         return $this;
  106.     }
  107.     /**
  108.      * Sets the final matcher for the matching plan.
  109.      *
  110.      * @param FinalMatcherInterface $final The final matcher that will have to
  111.      *                                     pick the route that will be used
  112.      *
  113.      * @return NestedMatcher this object to have a fluent interface
  114.      */
  115.     public function setFinalMatcher(FinalMatcherInterface $final)
  116.     {
  117.         $this->finalMatcher $final;
  118.         return $this;
  119.     }
  120.     /**
  121.      * {@inheritdoc}
  122.      */
  123.     public function matchRequest(Request $request)
  124.     {
  125.         $collection $this->routeProvider->getRouteCollectionForRequest($request);
  126.         if (!count($collection)) {
  127.             throw new ResourceNotFoundException();
  128.         }
  129.         // Route filters are expected to throw an exception themselves if they
  130.         // end up filtering the list down to 0.
  131.         foreach ($this->getRouteFilters() as $filter) {
  132.             $collection $filter->filter($collection$request);
  133.         }
  134.         return $this->finalMatcher->finalMatch($collection$request);
  135.     }
  136.     /**
  137.      * Sorts the filters and flattens them.
  138.      *
  139.      * @return RouteFilterInterface[] the filters ordered by priority
  140.      */
  141.     public function getRouteFilters()
  142.     {
  143.         if (=== count($this->sortedFilters)) {
  144.             $this->sortedFilters $this->sortFilters();
  145.         }
  146.         return $this->sortedFilters;
  147.     }
  148.     /**
  149.      * Sort filters by priority.
  150.      *
  151.      * The highest priority number is the highest priority (reverse sorting).
  152.      *
  153.      * @return RouteFilterInterface[] the sorted filters
  154.      */
  155.     protected function sortFilters()
  156.     {
  157.         if (=== count($this->filters)) {
  158.             return [];
  159.         }
  160.         krsort($this->filters);
  161.         return call_user_func_array('array_merge'$this->filters);
  162.     }
  163. }