Passed
Branch dev (140aec)
by Alex
02:37
created
src/Collector.php 1 patch
Indentation   +333 added lines, -333 removed lines patch added patch discarded remove patch
@@ -33,338 +33,338 @@
 block discarded – undo
33 33
 class Collector
34 34
 {
35 35
 
36
-    use Collectors\ControllerCollectorTrait;
37
-    use Collectors\ResourceCollectorTrait;
38
-
39
-    /**
40
-     * These regex define the structure of a dynamic segment in a pattern.
41
-     *
42
-     * @var string
43
-     */
44
-
45
-    const DYNAMIC_REGEX = "{\s*(\w*)\s*(?::\s*([^{}]*(?:{(?-1)}*)*))?\s*}";
46
-
47
-
48
-    /**
49
-     * All the supported http methods separated by spaces.
50
-     *
51
-     * @var string
52
-     */
53
-
54
-    const HTTP_METHODS = "get post put patch delete";
55
-
56
-    /**
57
-     * The static routes are simple stored in a multidimensional array, the first
58
-     * dimension is indexed by an http method and hold an array indexed with the patterns
59
-     * and holding the route. ex. [METHOD => [PATTERN => ROUTE]]
60
-     *
61
-     * @var array
62
-     */
63
-
64
-    protected $statics  = [];
65
-
66
-    /**
67
-     * The dynamic routes have parameters and are stored in a hashtable that every cell have
68
-     * an array with route patterns as indexes and routes as values. ex. [INDEX => [PATTERN => ROUTE]]
69
-     *
70
-     * @var array
71
-     */
72
-
73
-    protected $dynamics = [];
74
-
75
-    /**
76
-     * Some regex wildcards for easily definition of dynamic routes. ps. all keys and values must start with :
77
-     *
78
-     * @var array
79
-     */
80
-
81
-    protected $wildcards = [
82
-        ":uid"     => ":uid-[a-zA-Z0-9]",
83
-        ":slug"    => ":[a-z0-9-]",
84
-        ":string"  => ":\w",
85
-        ":int"     => ":\d",
86
-        ":integer" => ":\d",
87
-        ":float"   => ":[-+]?\d*?[.]?\d",
88
-        ":double"  => ":[-+]?\d*?[.]?\d",
89
-        ":hex"     => ":0[xX][0-9a-fA-F]",
90
-        ":octal"   => ":0[1-7][0-7]",
91
-        ":bool"    => ":1|0|true|false|yes|no",
92
-        ":boolean" => ":1|0|true|false|yes|no",
93
-    ];
94
-
95
-    /**
96
-     * @param string $method
97
-     * @param string $pattern
98
-     * @param string|array|\Closure $action
99
-     *
100
-     * @throws BadRouteException 
101
-     * @throws MethodNotSupportedException
102
-     *
103
-     * @return Group
104
-     */
105
-
106
-    public function set($method, $pattern, $action)
107
-    {
108
-        $method   = $this->parseMethod($method);
109
-        $patterns = $this->parsePattern($pattern);
110
-        $group    = new Group;
111
-
112
-        foreach ($patterns as $pattern)
113
-        {
114
-            $route = new Route($this, $method, $pattern, $action);
115
-            $group->setRoute($route);
116
-
117
-            if (strpos($pattern, "{") !== false) {
118
-                   $index = $this->getDynamicIndex($method, $pattern);
119
-                   $this->dynamics[$index][$pattern] = $route;
120
-            } else $this->statics[$method][$pattern] = $route;
121
-        }
122
-
123
-        return $group;
124
-    }
125
-
126
-    public function get   ($pattern, $action) { return $this->set("get"   , $pattern, $action); }
127
-    public function post  ($pattern, $action) { return $this->set("post"  , $pattern, $action); }
128
-    public function put   ($pattern, $action) { return $this->set("put"   , $pattern, $action); }
129
-    public function patch ($pattern, $action) { return $this->set("patch" , $pattern, $action); }
130
-    public function delete($pattern, $action) { return $this->set("delete", $pattern, $action); }
131
-
132
-    /**
133
-     * Insert a route into several http methods.
134
-     *
135
-     * @param string[] $methods
136
-     * @param string $pattern
137
-     * @param string|array|\Closure $action
138
-     *
139
-     * @return Group
140
-     */
141
-
142
-    public function match(array $methods, $pattern, $action)
143
-    {
144
-        $group = new Group;
145
-        foreach ($methods as $method)
146
-            $group->set($this->set($method, $pattern, $action));
147
-        return $group;
148
-    }
149
-
150
-    /**
151
-     * Insert a route into every http method supported.
152
-     *
153
-     * @param string $pattern
154
-     * @param string|array|\Closure $action
155
-     *
156
-     * @return Group
157
-     */
158
-
159
-    public function any($pattern, $action)
160
-    {
161
-        return $this->match(explode(" ", self::HTTP_METHODS), $pattern, $action);
162
-    }
163
-
164
-    /**
165
-     * Insert a route into every http method supported but the given ones.
166
-     *
167
-     * @param string[] $methods
168
-     * @param string $pattern
169
-     * @param string|array|\Closure $action
170
-     *
171
-     * @return Group
172
-     */
173
-
174
-    public function except(array $methods, $pattern, $action)
175
-    {
176
-        return $this->match(array_diff(explode(" ", self::HTTP_METHODS), $methods), $pattern, $action);
177
-    }
178
-
179
-    /**
180
-     * Group all given routes.
181
-     *
182
-     * @param Route[] $routes
183
-     * @return Group
184
-     */
185
-
186
-    public function group(array $routes)
187
-    {
188
-        $group = new Group;
189
-        foreach ($routes as $route)
190
-            $group->set($route);
191
-        return $group;
192
-    }
193
-
194
-    /**
195
-     * Remove a route from collector.
196
-     *
197
-     * @param string $method
198
-     * @param string $pattern
199
-     */
200
-
201
-    public function forget($method, $pattern)
202
-    {
203
-        if (strpos($pattern, "{") === false) {
204
-               unset($this->statics[$method][$pattern]);
205
-        } else unset($this->dynamics[$this->getDynamicIndex($method, $pattern)][$pattern]);
206
-    }
207
-
208
-    /**
209
-     * Determine if the http method is valid.
210
-     *
211
-     * @param string $method
212
-     * @throws MethodNotSupportedException
213
-     * @return string
214
-     */
215
-
216
-    protected function parseMethod($method)
217
-    {
218
-        $method = strtolower($method);
219
-
220
-        if (strpos(self::HTTP_METHODS, $method) === false) {
221
-            throw new MethodNotSupportedException($method);
222
-        }
223
-
224
-        return $method;
225
-    }
226
-
227
-    /**
228
-     * Separate routes pattern with optional parts into n new patterns.
229
-     *
230
-     * @param  string $pattern
231
-     * @return array
232
-     */
233
-
234
-    protected function parsePattern($pattern)
235
-    {
236
-        $withoutClosing = rtrim($pattern, "]");
237
-        $closingNumber  = strlen($pattern) - strlen($withoutClosing);
238
-
239
-        $segments = preg_split("~" . self::DYNAMIC_REGEX . "(*SKIP)(*F)|\[~x", $withoutClosing);
240
-        $this->parseSegments($segments, $closingNumber, $withoutClosing);
241
-
242
-        return $this->buildSegments($segments);
243
-    }
244
-
245
-    /**
246
-     * Parse all the possible patterns seeking for an incorrect or incompatible pattern.
247
-     *
248
-     * @param string[] $segments       Segments are all the possible patterns made on top of a pattern with optional segments.
249
-     * @param int      $closingNumber  The count of optional segments.
250
-     * @param string   $withoutClosing The pattern without the closing token of an optional segment. aka: ]
251
-     *
252
-     * @throws BadRouteException
253
-     */
254
-
255
-    protected function parseSegments(array $segments, $closingNumber, $withoutClosing)
256
-    {
257
-        if ($closingNumber !== count($segments) - 1) {
258
-            if (preg_match("~" . self::DYNAMIC_REGEX . "(*SKIP)(*F)|\]~x", $withoutClosing)) {
259
-                   throw new BadRouteException(BadRouteException::OPTIONAL_SEGMENTS_ON_MIDDLE);
260
-            } else throw new BadRouteException(BadRouteException::UNCLOSED_OPTIONAL_SEGMENTS);
261
-        }
262
-    }
263
-
264
-    /**
265
-     * @param string[] $segments
266
-     *
267
-     * @throws BadRouteException
268
-     * @return array
269
-     */
270
-
271
-    protected function buildSegments(array $segments)
272
-    {
273
-        $pattern  = "";
274
-        $patterns = [];
275
-        $wildcardTokens = array_keys($this->wildcards);
276
-        $wildcardRegex  = $this->wildcards;
277
-
278
-        foreach ($segments as $n => $segment) {
279
-            if ($segment === "" && $n !== 0) {
280
-                throw new BadRouteException(BadRouteException::EMPTY_OPTIONAL_PARTS);
281
-            }
282
-
283
-            $patterns[] = $pattern .= str_replace($wildcardTokens, $wildcardRegex, $segment);
284
-        }
285
-
286
-        return $patterns;
287
-    }
288
-
289
-    /**
290
-     * @param string $method
291
-     * @param string $pattern
292
-     *
293
-     * @return Route|false
294
-     */
295
-
296
-    public function findStaticRoute($method, $pattern)
297
-    {
298
-        $method = strtolower($method);
299
-        if (isset($this->statics[$method]) && isset($this->statics[$method][$pattern]))
300
-            return $this->statics[$method][$pattern];
301
-        return false;
302
-    }
303
-
304
-    /**
305
-     * @param string $method
306
-     * @param string $pattern
307
-     *
308
-     * @return array|false
309
-     */
310
-
311
-    public function findDynamicRoutes($method, $pattern)
312
-    {
313
-        $index = $this->getDynamicIndex($method, $pattern);
314
-        return isset($this->dynamics[$index]) ? $this->dynamics[$index] : false;
315
-    }
316
-
317
-    /**
318
-     * @param string $method
319
-     * @param string $pattern
320
-     *
321
-     * @return int
322
-     */
323
-
324
-    protected function getDynamicIndex($method, $pattern)
325
-    {
326
-        return crc32(strtolower($method)) + substr_count($pattern, "/");
327
-    }
328
-
329
-    /**
330
-     * @return string[]
331
-     */
332
-
333
-    public function getWildcards()
334
-    {
335
-        $wildcards = [];
336
-        foreach ($this->wildcards as $token => $regex)
337
-            $wildcards[substr($token, 1)] = substr($regex, 1);
338
-        return $wildcards;
339
-    }
340
-
341
-    /**
342
-     * @return string[]
343
-     */
344
-
345
-    public function getWildcardTokens()
346
-    {
347
-        return $this->wildcards;
348
-    }
349
-
350
-    /**
351
-     * @param string $wildcard
352
-     * @return string|null
353
-     */
354
-
355
-    public function getWildcard($wildcard)
356
-    {
357
-        return isset($this->wildcards[":$wildcard"]) ? substr($this->wildcards[":$wildcard"], 1) : null;
358
-    }
359
-
360
-    /**
361
-     * @param string $wildcard
362
-     * @param string $pattern
363
-     */
364
-
365
-    public function setWildcard($wildcard, $pattern)
366
-    {
367
-        $this->wildcards[":$wildcard"] = ":$pattern";
368
-    }
36
+	use Collectors\ControllerCollectorTrait;
37
+	use Collectors\ResourceCollectorTrait;
38
+
39
+	/**
40
+	 * These regex define the structure of a dynamic segment in a pattern.
41
+	 *
42
+	 * @var string
43
+	 */
44
+
45
+	const DYNAMIC_REGEX = "{\s*(\w*)\s*(?::\s*([^{}]*(?:{(?-1)}*)*))?\s*}";
46
+
47
+
48
+	/**
49
+	 * All the supported http methods separated by spaces.
50
+	 *
51
+	 * @var string
52
+	 */
53
+
54
+	const HTTP_METHODS = "get post put patch delete";
55
+
56
+	/**
57
+	 * The static routes are simple stored in a multidimensional array, the first
58
+	 * dimension is indexed by an http method and hold an array indexed with the patterns
59
+	 * and holding the route. ex. [METHOD => [PATTERN => ROUTE]]
60
+	 *
61
+	 * @var array
62
+	 */
63
+
64
+	protected $statics  = [];
65
+
66
+	/**
67
+	 * The dynamic routes have parameters and are stored in a hashtable that every cell have
68
+	 * an array with route patterns as indexes and routes as values. ex. [INDEX => [PATTERN => ROUTE]]
69
+	 *
70
+	 * @var array
71
+	 */
72
+
73
+	protected $dynamics = [];
74
+
75
+	/**
76
+	 * Some regex wildcards for easily definition of dynamic routes. ps. all keys and values must start with :
77
+	 *
78
+	 * @var array
79
+	 */
80
+
81
+	protected $wildcards = [
82
+		":uid"     => ":uid-[a-zA-Z0-9]",
83
+		":slug"    => ":[a-z0-9-]",
84
+		":string"  => ":\w",
85
+		":int"     => ":\d",
86
+		":integer" => ":\d",
87
+		":float"   => ":[-+]?\d*?[.]?\d",
88
+		":double"  => ":[-+]?\d*?[.]?\d",
89
+		":hex"     => ":0[xX][0-9a-fA-F]",
90
+		":octal"   => ":0[1-7][0-7]",
91
+		":bool"    => ":1|0|true|false|yes|no",
92
+		":boolean" => ":1|0|true|false|yes|no",
93
+	];
94
+
95
+	/**
96
+	 * @param string $method
97
+	 * @param string $pattern
98
+	 * @param string|array|\Closure $action
99
+	 *
100
+	 * @throws BadRouteException 
101
+	 * @throws MethodNotSupportedException
102
+	 *
103
+	 * @return Group
104
+	 */
105
+
106
+	public function set($method, $pattern, $action)
107
+	{
108
+		$method   = $this->parseMethod($method);
109
+		$patterns = $this->parsePattern($pattern);
110
+		$group    = new Group;
111
+
112
+		foreach ($patterns as $pattern)
113
+		{
114
+			$route = new Route($this, $method, $pattern, $action);
115
+			$group->setRoute($route);
116
+
117
+			if (strpos($pattern, "{") !== false) {
118
+				   $index = $this->getDynamicIndex($method, $pattern);
119
+				   $this->dynamics[$index][$pattern] = $route;
120
+			} else $this->statics[$method][$pattern] = $route;
121
+		}
122
+
123
+		return $group;
124
+	}
125
+
126
+	public function get   ($pattern, $action) { return $this->set("get"   , $pattern, $action); }
127
+	public function post  ($pattern, $action) { return $this->set("post"  , $pattern, $action); }
128
+	public function put   ($pattern, $action) { return $this->set("put"   , $pattern, $action); }
129
+	public function patch ($pattern, $action) { return $this->set("patch" , $pattern, $action); }
130
+	public function delete($pattern, $action) { return $this->set("delete", $pattern, $action); }
131
+
132
+	/**
133
+	 * Insert a route into several http methods.
134
+	 *
135
+	 * @param string[] $methods
136
+	 * @param string $pattern
137
+	 * @param string|array|\Closure $action
138
+	 *
139
+	 * @return Group
140
+	 */
141
+
142
+	public function match(array $methods, $pattern, $action)
143
+	{
144
+		$group = new Group;
145
+		foreach ($methods as $method)
146
+			$group->set($this->set($method, $pattern, $action));
147
+		return $group;
148
+	}
149
+
150
+	/**
151
+	 * Insert a route into every http method supported.
152
+	 *
153
+	 * @param string $pattern
154
+	 * @param string|array|\Closure $action
155
+	 *
156
+	 * @return Group
157
+	 */
158
+
159
+	public function any($pattern, $action)
160
+	{
161
+		return $this->match(explode(" ", self::HTTP_METHODS), $pattern, $action);
162
+	}
163
+
164
+	/**
165
+	 * Insert a route into every http method supported but the given ones.
166
+	 *
167
+	 * @param string[] $methods
168
+	 * @param string $pattern
169
+	 * @param string|array|\Closure $action
170
+	 *
171
+	 * @return Group
172
+	 */
173
+
174
+	public function except(array $methods, $pattern, $action)
175
+	{
176
+		return $this->match(array_diff(explode(" ", self::HTTP_METHODS), $methods), $pattern, $action);
177
+	}
178
+
179
+	/**
180
+	 * Group all given routes.
181
+	 *
182
+	 * @param Route[] $routes
183
+	 * @return Group
184
+	 */
185
+
186
+	public function group(array $routes)
187
+	{
188
+		$group = new Group;
189
+		foreach ($routes as $route)
190
+			$group->set($route);
191
+		return $group;
192
+	}
193
+
194
+	/**
195
+	 * Remove a route from collector.
196
+	 *
197
+	 * @param string $method
198
+	 * @param string $pattern
199
+	 */
200
+
201
+	public function forget($method, $pattern)
202
+	{
203
+		if (strpos($pattern, "{") === false) {
204
+			   unset($this->statics[$method][$pattern]);
205
+		} else unset($this->dynamics[$this->getDynamicIndex($method, $pattern)][$pattern]);
206
+	}
207
+
208
+	/**
209
+	 * Determine if the http method is valid.
210
+	 *
211
+	 * @param string $method
212
+	 * @throws MethodNotSupportedException
213
+	 * @return string
214
+	 */
215
+
216
+	protected function parseMethod($method)
217
+	{
218
+		$method = strtolower($method);
219
+
220
+		if (strpos(self::HTTP_METHODS, $method) === false) {
221
+			throw new MethodNotSupportedException($method);
222
+		}
223
+
224
+		return $method;
225
+	}
226
+
227
+	/**
228
+	 * Separate routes pattern with optional parts into n new patterns.
229
+	 *
230
+	 * @param  string $pattern
231
+	 * @return array
232
+	 */
233
+
234
+	protected function parsePattern($pattern)
235
+	{
236
+		$withoutClosing = rtrim($pattern, "]");
237
+		$closingNumber  = strlen($pattern) - strlen($withoutClosing);
238
+
239
+		$segments = preg_split("~" . self::DYNAMIC_REGEX . "(*SKIP)(*F)|\[~x", $withoutClosing);
240
+		$this->parseSegments($segments, $closingNumber, $withoutClosing);
241
+
242
+		return $this->buildSegments($segments);
243
+	}
244
+
245
+	/**
246
+	 * Parse all the possible patterns seeking for an incorrect or incompatible pattern.
247
+	 *
248
+	 * @param string[] $segments       Segments are all the possible patterns made on top of a pattern with optional segments.
249
+	 * @param int      $closingNumber  The count of optional segments.
250
+	 * @param string   $withoutClosing The pattern without the closing token of an optional segment. aka: ]
251
+	 *
252
+	 * @throws BadRouteException
253
+	 */
254
+
255
+	protected function parseSegments(array $segments, $closingNumber, $withoutClosing)
256
+	{
257
+		if ($closingNumber !== count($segments) - 1) {
258
+			if (preg_match("~" . self::DYNAMIC_REGEX . "(*SKIP)(*F)|\]~x", $withoutClosing)) {
259
+				   throw new BadRouteException(BadRouteException::OPTIONAL_SEGMENTS_ON_MIDDLE);
260
+			} else throw new BadRouteException(BadRouteException::UNCLOSED_OPTIONAL_SEGMENTS);
261
+		}
262
+	}
263
+
264
+	/**
265
+	 * @param string[] $segments
266
+	 *
267
+	 * @throws BadRouteException
268
+	 * @return array
269
+	 */
270
+
271
+	protected function buildSegments(array $segments)
272
+	{
273
+		$pattern  = "";
274
+		$patterns = [];
275
+		$wildcardTokens = array_keys($this->wildcards);
276
+		$wildcardRegex  = $this->wildcards;
277
+
278
+		foreach ($segments as $n => $segment) {
279
+			if ($segment === "" && $n !== 0) {
280
+				throw new BadRouteException(BadRouteException::EMPTY_OPTIONAL_PARTS);
281
+			}
282
+
283
+			$patterns[] = $pattern .= str_replace($wildcardTokens, $wildcardRegex, $segment);
284
+		}
285
+
286
+		return $patterns;
287
+	}
288
+
289
+	/**
290
+	 * @param string $method
291
+	 * @param string $pattern
292
+	 *
293
+	 * @return Route|false
294
+	 */
295
+
296
+	public function findStaticRoute($method, $pattern)
297
+	{
298
+		$method = strtolower($method);
299
+		if (isset($this->statics[$method]) && isset($this->statics[$method][$pattern]))
300
+			return $this->statics[$method][$pattern];
301
+		return false;
302
+	}
303
+
304
+	/**
305
+	 * @param string $method
306
+	 * @param string $pattern
307
+	 *
308
+	 * @return array|false
309
+	 */
310
+
311
+	public function findDynamicRoutes($method, $pattern)
312
+	{
313
+		$index = $this->getDynamicIndex($method, $pattern);
314
+		return isset($this->dynamics[$index]) ? $this->dynamics[$index] : false;
315
+	}
316
+
317
+	/**
318
+	 * @param string $method
319
+	 * @param string $pattern
320
+	 *
321
+	 * @return int
322
+	 */
323
+
324
+	protected function getDynamicIndex($method, $pattern)
325
+	{
326
+		return crc32(strtolower($method)) + substr_count($pattern, "/");
327
+	}
328
+
329
+	/**
330
+	 * @return string[]
331
+	 */
332
+
333
+	public function getWildcards()
334
+	{
335
+		$wildcards = [];
336
+		foreach ($this->wildcards as $token => $regex)
337
+			$wildcards[substr($token, 1)] = substr($regex, 1);
338
+		return $wildcards;
339
+	}
340
+
341
+	/**
342
+	 * @return string[]
343
+	 */
344
+
345
+	public function getWildcardTokens()
346
+	{
347
+		return $this->wildcards;
348
+	}
349
+
350
+	/**
351
+	 * @param string $wildcard
352
+	 * @return string|null
353
+	 */
354
+
355
+	public function getWildcard($wildcard)
356
+	{
357
+		return isset($this->wildcards[":$wildcard"]) ? substr($this->wildcards[":$wildcard"], 1) : null;
358
+	}
359
+
360
+	/**
361
+	 * @param string $wildcard
362
+	 * @param string $pattern
363
+	 */
364
+
365
+	public function setWildcard($wildcard, $pattern)
366
+	{
367
+		$this->wildcards[":$wildcard"] = ":$pattern";
368
+	}
369 369
     
370 370
 }
Please login to merge, or discard this patch.