annotate vendor/symfony-cmf/routing/NestedMatcher/NestedMatcher.php @ 19:fa3358dc1485 tip

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