Passed
Branch dev (e7fa0b)
by Alex
02:32
created
src/Matcher.php 1 patch
Indentation   +266 added lines, -266 removed lines patch added patch discarded remove patch
@@ -23,272 +23,272 @@
 block discarded – undo
23 23
 class Matcher
24 24
 {
25 25
 
26
-    /**
27
-     * @var Collector
28
-     */
29
-
30
-    protected $collector;
31
-
32
-    /**
33
-     * Define a basepath to all routes.
34
-     *
35
-     * @var string
36
-     */
37
-
38
-    protected $basepath = "";
39
-
40
-    /**
41
-     * Construct the route dispatcher.
42
-     *
43
-     * @param Collector $collector
44
-     * @param string $basepath Define a Path prefix that must be excluded on matches.
45
-     */
46
-
47
-    public function __construct(Collector $collector, $basepath = "")
48
-    {
49
-        $this->collector = $collector;
50
-        $this->basepath  = $basepath;
51
-    }
52
-
53
-    /**
54
-     * Find a route that matches the given arguments.
55
-     * 
56
-     * @param string $httpMethod
57
-     * @param string $path
58
-     *
59
-     * @throws NotFoundException
60
-     * @throws MethodNotAllowedException
61
-     *
62
-     * @return Route
63
-     */
64
-
65
-    public function match($httpMethod, $path)
66
-    {
67
-        $path = $this->parsePath($path);
68
-
69
-        if ($route = $this->collector->findStaticRoute($httpMethod, $path)) {
70
-            return $route;
71
-        }
72
-
73
-        if ($route = $this->matchDynamicRoute($httpMethod, $path)) {
74
-            return $route;
75
-        }
76
-
77
-        $this->matchSimilarRoute($httpMethod, $path);
78
-    }
79
-
80
-    /**
81
-     * Find and return the request dynamic route based on the compiled data and Path.
82
-     *
83
-     * @param string $httpMethod
84
-     * @param string $path
85
-     *
86
-     * @return Route|false If the request match an array with the action and parameters will
87
-     *                     be returned otherwise a false will.
88
-     */
89
-
90
-    protected function matchDynamicRoute($httpMethod, $path)
91
-    {
92
-        if ($routes = $this->collector->findDynamicRoutes($httpMethod, $path)) {
93
-            // chunk routes for smaller regex groups using the Sturges' Formula
94
-            foreach (array_chunk($routes, round(1 + 3.3 * log(count($routes))), true) as $chunk) {
95
-                array_map([$this, "buildRoute"], $chunk);
96
-                list($pattern, $map) = $this->buildGroup($chunk);
97
-
98
-                if (!preg_match($pattern, $path, $matches)) {
99
-                    continue;
100
-                }
101
-
102
-                /** @var Route $route */
103
-                $route = $map[count($matches)];
104
-                unset($matches[0]);
105
-
106
-                $route->setParams(array_combine($route->getParams(), array_filter($matches)));
107
-                $route->setMatcher($this);
108
-
109
-                return $route;
110
-            }
111
-        }
112
-
113
-        return false;
114
-    }
115
-
116
-    /**
117
-     * Parse the dynamic segments of the pattern and replace then for
118
-     * corresponding regex.
119
-     *
120
-     * @param Route $route
121
-     * @return Route
122
-     */
123
-
124
-    protected function buildRoute(Route $route)
125
-    {
126
-        if ($route->getBlock()) {
127
-            return $route;
128
-        }
129
-
130
-        list($pattern, $params) = $this->parsePlaceholders($route->getPattern());
131
-        return $route->setPatternWithoutReset($pattern)->setParams($params)->setBlock(true);
132
-    }
133
-
134
-    /**
135
-     * Group several dynamic routes patterns into one big regex and maps
136
-     * the routes to the pattern positions in the big regex.
137
-     *
138
-     * @param array $routes
139
-     * @return array
140
-     */
141
-
142
-    protected function buildGroup(array $routes)
143
-    {
144
-        $groupCount = (int) $map = $regex = [];
145
-
146
-        /** @var Route $route */
147
-        foreach ($routes as $route) {
148
-            $params           = $route->getParams();
149
-            $paramsCount      = count($params);
150
-            $groupCount       = max($groupCount, $paramsCount) + 1;
151
-            $regex[]          = $route->getPattern() . str_repeat("()", $groupCount - $paramsCount - 1);
152
-            $map[$groupCount] = $route;
153
-        }
154
-
155
-        return ["~^(?|" . implode("|", $regex) . ")$~", $map];
156
-    }
157
-
158
-    /**
159
-     * Parse an route pattern seeking for parameters and build the route regex.
160
-     *
161
-     * @param string $pattern
162
-     * @return array 0 => new route regex, 1 => map of parameter names
163
-     */
164
-
165
-    protected function parsePlaceholders($pattern)
166
-    {
167
-        $params = [];
168
-        preg_match_all("~" . Collector::DYNAMIC_REGEX . "~x", $pattern, $matches, PREG_SET_ORDER);
169
-
170
-        foreach ((array) $matches as $key => $match) {
171
-            $pattern = str_replace($match[0], isset($match[2]) ? "({$match[2]})" : "([^/]+)", $pattern);
172
-            $params[$key] = $match[1];
173
-        }
174
-
175
-        return [$pattern, $params];
176
-    }
177
-
178
-    /**
179
-     * Get only the path of a given url.
180
-     *
181
-     * @param string $path The given URL
182
-     *
183
-     * @throws Exception
184
-     * @return string
185
-     */
186
-
187
-    protected function parsePath($path)
188
-    {
189
-        $path = parse_url(substr(strstr(";" . $path, ";" . $this->basepath), strlen(";" . $this->basepath)), PHP_URL_PATH);
190
-
191
-        if ($path === false) {
192
-            throw new Exception("Seriously malformed URL passed to route matcher.");
193
-        }
194
-
195
-        return $path;
196
-    }
197
-
198
-    /**
199
-     * Generate an HTTP error request with method not allowed or not found.
200
-     *
201
-     * @param string $httpMethod
202
-     * @param string $path
203
-     *
204
-     * @throws NotFoundException
205
-     * @throws MethodNotAllowedException
206
-     */
207
-
208
-    protected function matchSimilarRoute($httpMethod, $path)
209
-    {
210
-        $dm = [];
211
-
212
-        if (($sm = $this->checkStaticRouteInOtherMethods($httpMethod, $path))
213
-                || ($dm = $this->checkDynamicRouteInOtherMethods($httpMethod, $path))) {
214
-            throw new MethodNotAllowedException($httpMethod, $path, array_merge((array) $sm, (array) $dm));
215
-        }
216
-
217
-        throw new NotFoundException($httpMethod, $path);
218
-    }
219
-
220
-    /**
221
-     * Verify if a static route match in another method than the requested.
222
-     *
223
-     * @param string $targetHttpMethod The HTTP method that must not be checked
224
-     * @param string $path              The Path that must be matched.
225
-     *
226
-     * @return array
227
-     */
228
-
229
-    protected function checkStaticRouteInOtherMethods($targetHttpMethod, $path)
230
-    {
231
-        return array_filter($this->getHttpMethodsBut($targetHttpMethod), function ($httpMethod) use ($path) {
232
-            return (bool) $this->collector->findStaticRoute($httpMethod, $path);
233
-        });
234
-    }
235
-
236
-    /**
237
-     * Verify if a dynamic route match in another method than the requested.
238
-     *
239
-     * @param string $targetHttpMethod The HTTP method that must not be checked
240
-     * @param string $path             The Path that must be matched.
241
-     *
242
-     * @return array
243
-     */
244
-
245
-    protected function checkDynamicRouteInOtherMethods($targetHttpMethod, $path)
246
-    {
247
-        return array_filter($this->getHttpMethodsBut($targetHttpMethod), function ($httpMethod) use ($path) {
248
-            return (bool) $this->matchDynamicRoute($httpMethod, $path);
249
-        });
250
-    }
251
-
252
-    /**
253
-     * Strip the given http methods and return all the others.
254
-     *
255
-     * @param  array|string
256
-     * @return array
257
-     */
258
-
259
-    protected function getHttpMethodsBut($targetHttpMethod)
260
-    {
261
-        return array_diff(explode(" ", Collector::HTTP_METHODS), (array) $targetHttpMethod);
262
-    }
263
-
264
-    /**
265
-     * @return Collector
266
-     */
267
-
268
-    public function getCollector()
269
-    {
270
-        return $this->collector;
271
-    }
272
-
273
-    /**
274
-     * @return string
275
-     */
276
-
277
-    public function getBasePath()
278
-    {
279
-        return $this->basepath;
280
-    }
281
-
282
-    /**
283
-     * Set a new basepath, this will be a prefix that must be excluded in
284
-     * every requested Path.
285
-     *
286
-     * @param string $basepath The new basepath
287
-     */
26
+	/**
27
+	 * @var Collector
28
+	 */
29
+
30
+	protected $collector;
31
+
32
+	/**
33
+	 * Define a basepath to all routes.
34
+	 *
35
+	 * @var string
36
+	 */
37
+
38
+	protected $basepath = "";
39
+
40
+	/**
41
+	 * Construct the route dispatcher.
42
+	 *
43
+	 * @param Collector $collector
44
+	 * @param string $basepath Define a Path prefix that must be excluded on matches.
45
+	 */
46
+
47
+	public function __construct(Collector $collector, $basepath = "")
48
+	{
49
+		$this->collector = $collector;
50
+		$this->basepath  = $basepath;
51
+	}
52
+
53
+	/**
54
+	 * Find a route that matches the given arguments.
55
+	 * 
56
+	 * @param string $httpMethod
57
+	 * @param string $path
58
+	 *
59
+	 * @throws NotFoundException
60
+	 * @throws MethodNotAllowedException
61
+	 *
62
+	 * @return Route
63
+	 */
64
+
65
+	public function match($httpMethod, $path)
66
+	{
67
+		$path = $this->parsePath($path);
68
+
69
+		if ($route = $this->collector->findStaticRoute($httpMethod, $path)) {
70
+			return $route;
71
+		}
72
+
73
+		if ($route = $this->matchDynamicRoute($httpMethod, $path)) {
74
+			return $route;
75
+		}
76
+
77
+		$this->matchSimilarRoute($httpMethod, $path);
78
+	}
79
+
80
+	/**
81
+	 * Find and return the request dynamic route based on the compiled data and Path.
82
+	 *
83
+	 * @param string $httpMethod
84
+	 * @param string $path
85
+	 *
86
+	 * @return Route|false If the request match an array with the action and parameters will
87
+	 *                     be returned otherwise a false will.
88
+	 */
89
+
90
+	protected function matchDynamicRoute($httpMethod, $path)
91
+	{
92
+		if ($routes = $this->collector->findDynamicRoutes($httpMethod, $path)) {
93
+			// chunk routes for smaller regex groups using the Sturges' Formula
94
+			foreach (array_chunk($routes, round(1 + 3.3 * log(count($routes))), true) as $chunk) {
95
+				array_map([$this, "buildRoute"], $chunk);
96
+				list($pattern, $map) = $this->buildGroup($chunk);
97
+
98
+				if (!preg_match($pattern, $path, $matches)) {
99
+					continue;
100
+				}
101
+
102
+				/** @var Route $route */
103
+				$route = $map[count($matches)];
104
+				unset($matches[0]);
105
+
106
+				$route->setParams(array_combine($route->getParams(), array_filter($matches)));
107
+				$route->setMatcher($this);
108
+
109
+				return $route;
110
+			}
111
+		}
112
+
113
+		return false;
114
+	}
115
+
116
+	/**
117
+	 * Parse the dynamic segments of the pattern and replace then for
118
+	 * corresponding regex.
119
+	 *
120
+	 * @param Route $route
121
+	 * @return Route
122
+	 */
123
+
124
+	protected function buildRoute(Route $route)
125
+	{
126
+		if ($route->getBlock()) {
127
+			return $route;
128
+		}
129
+
130
+		list($pattern, $params) = $this->parsePlaceholders($route->getPattern());
131
+		return $route->setPatternWithoutReset($pattern)->setParams($params)->setBlock(true);
132
+	}
133
+
134
+	/**
135
+	 * Group several dynamic routes patterns into one big regex and maps
136
+	 * the routes to the pattern positions in the big regex.
137
+	 *
138
+	 * @param array $routes
139
+	 * @return array
140
+	 */
141
+
142
+	protected function buildGroup(array $routes)
143
+	{
144
+		$groupCount = (int) $map = $regex = [];
145
+
146
+		/** @var Route $route */
147
+		foreach ($routes as $route) {
148
+			$params           = $route->getParams();
149
+			$paramsCount      = count($params);
150
+			$groupCount       = max($groupCount, $paramsCount) + 1;
151
+			$regex[]          = $route->getPattern() . str_repeat("()", $groupCount - $paramsCount - 1);
152
+			$map[$groupCount] = $route;
153
+		}
154
+
155
+		return ["~^(?|" . implode("|", $regex) . ")$~", $map];
156
+	}
157
+
158
+	/**
159
+	 * Parse an route pattern seeking for parameters and build the route regex.
160
+	 *
161
+	 * @param string $pattern
162
+	 * @return array 0 => new route regex, 1 => map of parameter names
163
+	 */
164
+
165
+	protected function parsePlaceholders($pattern)
166
+	{
167
+		$params = [];
168
+		preg_match_all("~" . Collector::DYNAMIC_REGEX . "~x", $pattern, $matches, PREG_SET_ORDER);
169
+
170
+		foreach ((array) $matches as $key => $match) {
171
+			$pattern = str_replace($match[0], isset($match[2]) ? "({$match[2]})" : "([^/]+)", $pattern);
172
+			$params[$key] = $match[1];
173
+		}
174
+
175
+		return [$pattern, $params];
176
+	}
177
+
178
+	/**
179
+	 * Get only the path of a given url.
180
+	 *
181
+	 * @param string $path The given URL
182
+	 *
183
+	 * @throws Exception
184
+	 * @return string
185
+	 */
186
+
187
+	protected function parsePath($path)
188
+	{
189
+		$path = parse_url(substr(strstr(";" . $path, ";" . $this->basepath), strlen(";" . $this->basepath)), PHP_URL_PATH);
190
+
191
+		if ($path === false) {
192
+			throw new Exception("Seriously malformed URL passed to route matcher.");
193
+		}
194
+
195
+		return $path;
196
+	}
197
+
198
+	/**
199
+	 * Generate an HTTP error request with method not allowed or not found.
200
+	 *
201
+	 * @param string $httpMethod
202
+	 * @param string $path
203
+	 *
204
+	 * @throws NotFoundException
205
+	 * @throws MethodNotAllowedException
206
+	 */
207
+
208
+	protected function matchSimilarRoute($httpMethod, $path)
209
+	{
210
+		$dm = [];
211
+
212
+		if (($sm = $this->checkStaticRouteInOtherMethods($httpMethod, $path))
213
+				|| ($dm = $this->checkDynamicRouteInOtherMethods($httpMethod, $path))) {
214
+			throw new MethodNotAllowedException($httpMethod, $path, array_merge((array) $sm, (array) $dm));
215
+		}
216
+
217
+		throw new NotFoundException($httpMethod, $path);
218
+	}
219
+
220
+	/**
221
+	 * Verify if a static route match in another method than the requested.
222
+	 *
223
+	 * @param string $targetHttpMethod The HTTP method that must not be checked
224
+	 * @param string $path              The Path that must be matched.
225
+	 *
226
+	 * @return array
227
+	 */
228
+
229
+	protected function checkStaticRouteInOtherMethods($targetHttpMethod, $path)
230
+	{
231
+		return array_filter($this->getHttpMethodsBut($targetHttpMethod), function ($httpMethod) use ($path) {
232
+			return (bool) $this->collector->findStaticRoute($httpMethod, $path);
233
+		});
234
+	}
235
+
236
+	/**
237
+	 * Verify if a dynamic route match in another method than the requested.
238
+	 *
239
+	 * @param string $targetHttpMethod The HTTP method that must not be checked
240
+	 * @param string $path             The Path that must be matched.
241
+	 *
242
+	 * @return array
243
+	 */
244
+
245
+	protected function checkDynamicRouteInOtherMethods($targetHttpMethod, $path)
246
+	{
247
+		return array_filter($this->getHttpMethodsBut($targetHttpMethod), function ($httpMethod) use ($path) {
248
+			return (bool) $this->matchDynamicRoute($httpMethod, $path);
249
+		});
250
+	}
251
+
252
+	/**
253
+	 * Strip the given http methods and return all the others.
254
+	 *
255
+	 * @param  array|string
256
+	 * @return array
257
+	 */
258
+
259
+	protected function getHttpMethodsBut($targetHttpMethod)
260
+	{
261
+		return array_diff(explode(" ", Collector::HTTP_METHODS), (array) $targetHttpMethod);
262
+	}
263
+
264
+	/**
265
+	 * @return Collector
266
+	 */
267
+
268
+	public function getCollector()
269
+	{
270
+		return $this->collector;
271
+	}
272
+
273
+	/**
274
+	 * @return string
275
+	 */
276
+
277
+	public function getBasePath()
278
+	{
279
+		return $this->basepath;
280
+	}
281
+
282
+	/**
283
+	 * Set a new basepath, this will be a prefix that must be excluded in
284
+	 * every requested Path.
285
+	 *
286
+	 * @param string $basepath The new basepath
287
+	 */
288 288
     
289
-    public function setBasePath($basepath)
290
-    {
291
-        $this->basepath = $basepath;
292
-    }
289
+	public function setBasePath($basepath)
290
+	{
291
+		$this->basepath = $basepath;
292
+	}
293 293
 
294 294
 }
Please login to merge, or discard this patch.