From 091240ea03255bd2b5585651f9f172054d0bdd2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rados=C5=82aw=20Kowalewski?= Date: Tue, 3 Feb 2015 22:38:32 +0100 Subject: [PATCH] Use shared RouteCollection among nested routes and apply prefix to route path before generating unique route name Fixes #1106 --- src/Silex/ControllerCollection.php | 28 ++++++++++++--- .../Silex/Tests/ControllerCollectionTest.php | 35 +++++++++++++++++++ 2 files changed, 58 insertions(+), 5 deletions(-) diff --git a/src/Silex/ControllerCollection.php b/src/Silex/ControllerCollection.php index 7e27708bd..4ec61134a 100644 --- a/src/Silex/ControllerCollection.php +++ b/src/Silex/ControllerCollection.php @@ -42,6 +42,7 @@ class ControllerCollection protected $defaultRoute; protected $defaultController; protected $prefix; + protected $routes; public function __construct(Route $defaultRoute) { @@ -51,6 +52,16 @@ public function __construct(Route $defaultRoute) }; } + /** + * Use existing route collection to resolve conflicting autogenerated route names among mounted routes + * + * @param RouteCollection $routes + */ + public function shareRoutes(RouteCollection $routes) + { + $this->routes = $routes; + } + /** * Mounts controllers under the given route prefix. * @@ -59,6 +70,10 @@ public function __construct(Route $defaultRoute) */ public function mount($prefix, ControllerCollection $controllers) { + if (!($this->routes instanceof RouteCollection)) { + $this->routes = new RouteCollection(); + } + $controllers->shareRoutes($this->routes); $controllers->prefix = $prefix; $this->controllers[] = $controllers; @@ -188,12 +203,17 @@ public function __call($method, $arguments) */ public function flush($prefix = '') { - $routes = new RouteCollection(); + if ($prefix !== '') { + $prefix = '/'.trim(trim($prefix), '/'); + } + + $routes = $this->routes ?: new RouteCollection(); foreach ($this->controllers as $controller) { if ($controller instanceof Controller) { + $controller->getRoute()->setPath($prefix.$controller->getRoute()->getPath()); if (!$name = $controller->getRouteName()) { - $name = $controller->generateRouteName($prefix); + $name = $controller->generateRouteName(''); while ($routes->get($name)) { $name .= '_'; } @@ -202,12 +222,10 @@ public function flush($prefix = '') $routes->add($name, $controller->getRoute()); $controller->freeze(); } else { - $routes->addCollection($controller->flush($controller->prefix)); + $routes->addCollection($controller->flush($prefix.$controller->prefix)); } } - $routes->addPrefix($prefix); - $this->controllers = array(); return $routes; diff --git a/tests/Silex/Tests/ControllerCollectionTest.php b/tests/Silex/Tests/ControllerCollectionTest.php index 5420798a9..9d3a7a081 100644 --- a/tests/Silex/Tests/ControllerCollectionTest.php +++ b/tests/Silex/Tests/ControllerCollectionTest.php @@ -89,6 +89,41 @@ public function testUniqueGeneratedRouteNames() $this->assertEquals(array('_a_a', '_a_a_'), array_keys($routes->all())); } + public function testUniqueGeneratedRouteNamesAmongMounts() + { + $controllers = new ControllerCollection(new Route()); + + $controllers->mount('/root-a', $rootA = new ControllerCollection(new Route())); + $controllers->mount('/root_a', $rootB = new ControllerCollection(new Route())); + + $rootA->match('/leaf', function () {}); + $rootB->match('/leaf', function () {}); + + $routes = $controllers->flush(); + + $this->assertCount(2, $routes->all()); + $this->assertEquals(array('_root_a_leaf', '_root_a_leaf_'), array_keys($routes->all())); + } + + public function testUniqueGeneratedRouteNamesAmongNestedMounts() + { + $controllers = new ControllerCollection(new Route()); + + $controllers->mount('/root-a', $rootA = new ControllerCollection(new Route())); + $controllers->mount('/root_a', $rootB = new ControllerCollection(new Route())); + + $rootA->mount('/tree', $treeA = new ControllerCollection(new Route())); + $rootB->mount('/tree', $treeB = new ControllerCollection(new Route())); + + $treeA->match('/leaf', function () {}); + $treeB->match('/leaf', function () {}); + + $routes = $controllers->flush(); + + $this->assertCount(2, $routes->all()); + $this->assertEquals(array('_root_a_tree_leaf', '_root_a_tree_leaf_'), array_keys($routes->all())); + } + public function testAssert() { $controllers = new ControllerCollection(new Route());