3333 */
3434class RouteCollector
3535{
36- private const ROUTE_SEARCH_ANY = 'any ' ;
37- private const ROUTE_SEARCH_METHODS = 'methods ' ;
38-
3936 /**
4037 * @var RouterInterface
4138 */
@@ -49,32 +46,16 @@ class RouteCollector
4946 private $ routes = [];
5047
5148 /**
52- * List of all routes indexed by name
53- *
54- * @var Route[]
55- */
56- private $ routeNames = [];
57-
58- /**
59- * Search structure for duplicate path-method detection
60- * Indexed by path + method. Leaves are instances of Route
61- * [
62- * '/path/foo' => [
63- * 'methods' => [
64- * 'GET' => $route1,
65- * 'POST' => $route2,
66- * ],
67- * ],
68- * '/path/bar' => [ 'any' => $route3 ],
69- * ]
49+ * Checks for duplicate routes
7050 *
71- * @var array
51+ * @var DuplicateRouteDetector
7252 */
73- private $ routePaths = [] ;
53+ private $ duplicateChecker ;
7454
7555 public function __construct (RouterInterface $ router )
7656 {
7757 $ this ->router = $ router ;
58+ $ this ->duplicateChecker = new DuplicateRouteDetector ();
7859 }
7960
8061 /**
@@ -95,27 +76,13 @@ public function route(
9576
9677 $ methods = $ methods ?? Route::HTTP_METHOD_ANY ;
9778 $ route = new Route ($ path , $ middleware , $ methods , $ name );
98- $ this ->checkForDuplicateRoute ($ route );
99- $ this ->fillRouteSearchStructure ($ route );
79+ $ this ->duplicateChecker ->detectDuplicate ($ route );
10080 $ this ->routes [] = $ route ;
10181 $ this ->router ->addRoute ($ route );
10282
10383 return $ route ;
10484 }
10585
106- private function fillRouteSearchStructure (Route $ route ): void
107- {
108- $ this ->routeNames [$ route ->getName ()] = $ route ;
109- if ($ route ->allowsAnyMethod ()) {
110- $ this ->routePaths [$ route ->getPath ()][self ::ROUTE_SEARCH_ANY ] = $ route ;
111- }
112-
113- $ allowedMethods = $ route ->getAllowedMethods () ?? [];
114- foreach ($ allowedMethods as $ allowedMethod ) {
115- $ this ->routePaths [$ route ->getPath ()][self ::ROUTE_SEARCH_METHODS ][ $ allowedMethod ] = $ route ;
116- }
117- }
118-
11986 /**
12087 * @param null|string $name The name of the route.
12188 */
@@ -173,53 +140,4 @@ public function getRoutes() : array
173140 {
174141 return $ this ->routes ;
175142 }
176-
177- /**
178- * Determine if the route is duplicated in the current list.
179- *
180- * Checks if a route with the same name or path exists already in the list;
181- * if so, and it responds to any of the $methods indicated, raises
182- * a DuplicateRouteException indicating a duplicate route.
183- *
184- * @throws Exception\DuplicateRouteException on duplicate route detection.
185- */
186- private function checkForDuplicateRoute (Route $ route ) : void
187- {
188- if (isset ($ this ->routeNames [$ route ->getName ()])) {
189- $ this ->duplicateRouteDetected ($ route );
190- }
191-
192- if (! isset ($ this ->routePaths [$ route ->getPath ()])) {
193- return ;
194- }
195-
196- if (isset ($ this ->routePaths [$ route ->getPath ()][self ::ROUTE_SEARCH_ANY ])) {
197- $ this ->duplicateRouteDetected ($ route );
198- }
199-
200- if ($ route ->allowsAnyMethod () && isset ($ this ->routePaths [$ route ->getPath ()][self ::ROUTE_SEARCH_METHODS ])) {
201- $ this ->duplicateRouteDetected ($ route );
202- }
203-
204- $ allowedMethods = $ route ->getAllowedMethods () ?? [];
205- foreach ($ allowedMethods as $ method ) {
206- if (isset ($ this ->routePaths [$ route ->getPath ()][self ::ROUTE_SEARCH_METHODS ][ $ method ])) {
207- $ this ->duplicateRouteDetected ($ route );
208- }
209- }
210- }
211-
212- private function duplicateRouteDetected (Route $ duplicate ):void
213- {
214- $ allowedMethods = $ duplicate ->getAllowedMethods () ?: ['(any) ' ];
215- $ name = $ duplicate ->getName ();
216- throw new Exception \DuplicateRouteException (
217- sprintf (
218- 'Duplicate route detected; path "%s" answering to methods [%s]%s ' ,
219- $ duplicate ->getPath (),
220- implode (', ' , $ allowedMethods ),
221- $ name ? sprintf (', with name "%s" ' , $ name ) : ''
222- )
223- );
224- }
225143}
0 commit comments