1919 * because the routes will not be used until the collector is used.
2020 */
2121
22+ if (!class_exists (Parser::class, false )) {
23+ include __DIR__ . "/Parser.php " ;
24+ }
25+
2226include __DIR__ . "/Route.php " ;
2327include __DIR__ . "/Group.php " ;
2428include __DIR__ . "/Collectors/ControllerCollectorTrait.php " ;
@@ -36,14 +40,6 @@ class Collector
3640 use Collectors \ControllerCollectorTrait;
3741 use Collectors \ResourceCollectorTrait;
3842
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-
4743
4844 /**
4945 * All the supported http methods separated by spaces.
@@ -73,24 +69,23 @@ class Collector
7369 protected $ dynamics = [];
7470
7571 /**
76- * Some regex wildcards for easily definition of dynamic routes. ps. all keys and values must start with :
72+ * The pattern parser instance.
7773 *
78- * @var array
74+ * @var Parser
7975 */
8076
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- ];
77+ protected $ parser ;
78+
79+ /**
80+ * Collector constructor.
81+ *
82+ * @param Parser|null $parser
83+ */
84+
85+ public function __construct (Parser $ parser = null )
86+ {
87+ $ this ->parser = $ parser ?: new Parser ;
88+ }
9489
9590 /**
9691 * @param string $method
@@ -105,8 +100,8 @@ class Collector
105100
106101 public function set ($ method , $ pattern , $ action )
107102 {
108- $ method = $ this ->parseMethod ($ method );
109- $ patterns = $ this ->parsePattern ($ pattern );
103+ $ method = $ this ->getValidMethod ($ method );
104+ $ patterns = $ this ->parser -> parsePattern ($ pattern );
110105 $ group = new Group ;
111106
112107 foreach ($ patterns as $ pattern )
@@ -205,87 +200,6 @@ public function forget($method, $pattern)
205200 } else unset($ this ->dynamics [$ this ->getDynamicIndex ($ method , $ pattern )][$ pattern ]);
206201 }
207202
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-
289203 /**
290204 * @param string $method
291205 * @param string $pattern
@@ -326,16 +240,33 @@ protected function getDynamicIndex($method, $pattern)
326240 return crc32 (strtolower ($ method )) + substr_count ($ pattern , "/ " );
327241 }
328242
243+ /**
244+ * Determine if the http method is valid.
245+ *
246+ * @param string $method
247+ *
248+ * @throws MethodNotSupportedException
249+ * @return string
250+ */
251+
252+ protected function getValidMethod ($ method )
253+ {
254+ $ method = strtolower ($ method );
255+
256+ if (strpos (self ::HTTP_METHODS , $ method ) === false ) {
257+ throw new MethodNotSupportedException ($ method );
258+ }
259+
260+ return $ method ;
261+ }
262+
329263 /**
330264 * @return string[]
331265 */
332266
333267 public function getWildcards ()
334268 {
335- $ wildcards = [];
336- foreach ($ this ->wildcards as $ token => $ regex )
337- $ wildcards [substr ($ token , 1 )] = substr ($ regex , 1 );
338- return $ wildcards ;
269+ return $ this ->parser ->getWildcards ();
339270 }
340271
341272 /**
@@ -344,7 +275,7 @@ public function getWildcards()
344275
345276 public function getWildcardTokens ()
346277 {
347- return $ this ->wildcards ;
278+ return $ this ->parser -> getWildcardTokens () ;
348279 }
349280
350281 /**
@@ -354,7 +285,7 @@ public function getWildcardTokens()
354285
355286 public function getWildcard ($ wildcard )
356287 {
357- return isset ( $ this ->wildcards [ " : $ wildcard " ]) ? substr ( $ this -> wildcards [ " : $ wildcard" ], 1 ) : null ;
288+ return $ this ->parser -> getWildcard ( $ wildcard) ;
358289 }
359290
360291 /**
@@ -366,7 +297,33 @@ public function getWildcard($wildcard)
366297
367298 public function setWildcard ($ wildcard , $ pattern )
368299 {
369- $ this ->wildcards [": $ wildcard " ] = ": $ pattern " ;
300+ $ this ->parser ->setWildcard ($ wildcard , $ pattern );
301+ return $ this ;
302+ }
303+
304+ /**
305+ * @return Parser
306+ */
307+
308+ public function getParser ()
309+ {
310+ return $ this ->parser ;
311+ }
312+
313+ /**
314+ * @param Parser $parser
315+ *
316+ * @throws \LogicException
317+ * @return self
318+ */
319+
320+ public function setParser (Parser $ parser )
321+ {
322+ if (!empty ($ this ->statics ) || !empty ($ this ->dynamics )) {
323+ throw new \LogicException ("You can't define a route parser after registering a route. " );
324+ }
325+
326+ $ this ->parser = $ parser ;
370327 return $ this ;
371328 }
372329
0 commit comments