comparison vendor/symfony-cmf/routing/NestedMatcher/NestedMatcher.php @ 0:4c8ae668cc8c

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