diff --git a/src/Symfony/Component/Routing/Annotation/Route.php b/src/Symfony/Component/Routing/Annotation/Route.php index 90521c0be8e0d..91cabb4e7faf3 100644 --- a/src/Symfony/Component/Routing/Annotation/Route.php +++ b/src/Symfony/Component/Routing/Annotation/Route.php @@ -120,6 +120,11 @@ public function getOptions() return $this->options; } + public function getOption($name) + { + return isset($this->options[$name]) ? $this->options[$name] : null; + } + public function setDefaults($defaults) { $this->defaults = $defaults; diff --git a/src/Symfony/Component/Routing/Loader/AnnotationClassLoader.php b/src/Symfony/Component/Routing/Loader/AnnotationClassLoader.php index f6d44252157a1..8cb23305b13eb 100644 --- a/src/Symfony/Component/Routing/Loader/AnnotationClassLoader.php +++ b/src/Symfony/Component/Routing/Loader/AnnotationClassLoader.php @@ -72,6 +72,11 @@ abstract class AnnotationClassLoader implements LoaderInterface */ protected $defaultRouteIndex = 0; + /** + * @var array + */ + protected $routesWithPriority = array(); + /** * Constructor. * @@ -122,11 +127,33 @@ public function load($class, $type = null) $this->defaultRouteIndex = 0; foreach ($this->reader->getMethodAnnotations($method) as $annot) { if ($annot instanceof $this->routeAnnotationClass) { - $this->addRoute($collection, $annot, $globals, $class, $method); + $priority = (int) $annot->getOption('priority'); + $this->routesWithPriority[$priority][] = array($annot, $globals, $class, $method); } } } + $collection = $this->addPriorityRoutes($collection); + + return $collection; + } + + /** + * Add the prioritised routes to the collection + * + * @param $collection + * @return RouteCollection + */ + public function addPriorityRoutes($collection) + { + krsort($this->routesWithPriority); + + foreach ($this->routesWithPriority as $priorityGroup) { + foreach ($priorityGroup as $route) { + $this->addRoute($collection, $route[0], $route[1], $route[2], $route[3]); + } + } + return $collection; } diff --git a/src/Symfony/Component/Routing/Loader/AnnotationDirectoryLoader.php b/src/Symfony/Component/Routing/Loader/AnnotationDirectoryLoader.php index abd68ed6c4fab..4044b1a8bc8e9 100644 --- a/src/Symfony/Component/Routing/Loader/AnnotationDirectoryLoader.php +++ b/src/Symfony/Component/Routing/Loader/AnnotationDirectoryLoader.php @@ -58,6 +58,8 @@ public function load($path, $type = null) } } + $collection = $this->loader->addPriorityRoutes($collection); + return $collection; } diff --git a/src/Symfony/Component/Routing/Loader/AnnotationFileLoader.php b/src/Symfony/Component/Routing/Loader/AnnotationFileLoader.php index e54a0181c7861..5da11bab22960 100644 --- a/src/Symfony/Component/Routing/Loader/AnnotationFileLoader.php +++ b/src/Symfony/Component/Routing/Loader/AnnotationFileLoader.php @@ -65,6 +65,8 @@ public function load($file, $type = null) $collection->addCollection($this->loader->load($class, $type)); } + $collection = $this->loader->addPriorityRoutes($collection); + return $collection; } diff --git a/src/Symfony/Component/Routing/Tests/Loader/AnnotationClassLoaderTest.php b/src/Symfony/Component/Routing/Tests/Loader/AnnotationClassLoaderTest.php index 3b39a666edc26..95b101c98f3f3 100644 --- a/src/Symfony/Component/Routing/Tests/Loader/AnnotationClassLoaderTest.php +++ b/src/Symfony/Component/Routing/Tests/Loader/AnnotationClassLoaderTest.php @@ -91,6 +91,11 @@ public function getLoadTests() array('name' => 'route1', 'defaults' => array('arg2' => 'foo'), 'condition' => 'context.getMethod() == "GET"'), array('arg2' => 'defaultValue2', 'arg3' =>'defaultValue3') ), + array( + 'Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses\BarClass', + array('name' => 'route1', 'options' => array('priority' => 10)), + array('arg2' => 'defaultValue2', 'arg3' => 'defaultValue3'), + ), ); } @@ -120,7 +125,7 @@ public function testLoad($className, $routeDatas = array(), $methodArgs = array( $this->assertSame($routeDatas['path'], $route->getPath(), '->load preserves path annotation'); $this->assertSame($routeDatas['requirements'],$route->getRequirements(), '->load preserves requirements annotation'); - $this->assertCount(0, array_intersect($route->getOptions(), $routeDatas['options']), '->load preserves options annotation'); + $this->assertSame(count($routeDatas['options']), count(array_intersect($route->getOptions(), $routeDatas['options'])), '->load preserves options annotation'); $this->assertSame(array_replace($methodArgs, $routeDatas['defaults']), $route->getDefaults(), '->load preserves defaults annotation'); $this->assertEquals($routeDatas['condition'], $route->getCondition(), '->load preserves condition annotation'); } diff --git a/src/Symfony/Component/Routing/Tests/Loader/AnnotationDirectoryLoaderTest.php b/src/Symfony/Component/Routing/Tests/Loader/AnnotationDirectoryLoaderTest.php index 29126ba4f2091..5be8a25c394bb 100644 --- a/src/Symfony/Component/Routing/Tests/Loader/AnnotationDirectoryLoaderTest.php +++ b/src/Symfony/Component/Routing/Tests/Loader/AnnotationDirectoryLoaderTest.php @@ -13,6 +13,7 @@ use Symfony\Component\Routing\Loader\AnnotationDirectoryLoader; use Symfony\Component\Config\FileLocator; +use Symfony\Component\Routing\Annotation\Route; class AnnotationDirectoryLoaderTest extends AbstractAnnotationLoaderTest { @@ -50,4 +51,27 @@ public function testSupports() $this->assertTrue($this->loader->supports($fixturesDir, 'annotation'), '->supports() checks the resource type if specified'); $this->assertFalse($this->loader->supports($fixturesDir, 'foo'), '->supports() checks the resource type if specified'); } + + public function testRoutesWithPriority() + { + $routeDatas = array( + 'foo' => new Route(array('name' => 'foo', 'path' => '/foo')), + 'unimportant' => new Route(array('name' => 'unimportant', 'path' => '/unimportant', 'options' => array('priority' => -10))), + 'bar' => new Route(array('name' => 'bar', 'path' => '/bar')), + 'static_id' => new Route(array('name' => 'static_id', 'path' => '/static/{id}', 'options' => array('priority' => 1))), + 'home' => new Route(array('name' => 'home', 'path' => '/home')), + 'static_contact' => new Route(array('name' => 'static_contact', 'path' => '/static/contact', 'options' => array('priority' => 5))), + 'login' => new Route(array('name' => 'login', 'path' => '/login')), + 'static_location' => new Route(array('name' => 'static_location', 'path' => '/static/location', 'options' => array('priority' => 5))), + ); + + $this->reader + ->expects($this->once()) + ->method('getMethodAnnotations') + ->will($this->returnValue($routeDatas)); + + $routeCollection = $this->loader->load(__DIR__.'/../Fixtures/AnnotatedClasses'); + $expectedOrder = array( 'static_contact', 'static_location', 'static_id', 'foo', 'bar', 'home', 'login', 'unimportant'); + $this->assertEquals($expectedOrder, array_keys($routeCollection->all())); + } } diff --git a/src/Symfony/Component/Routing/Tests/Loader/AnnotationFileLoaderTest.php b/src/Symfony/Component/Routing/Tests/Loader/AnnotationFileLoaderTest.php index f0a8a0e329539..034d19bf2116d 100644 --- a/src/Symfony/Component/Routing/Tests/Loader/AnnotationFileLoaderTest.php +++ b/src/Symfony/Component/Routing/Tests/Loader/AnnotationFileLoaderTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Routing\Tests\Loader; +use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Routing\Loader\AnnotationFileLoader; use Symfony\Component\Config\FileLocator; @@ -44,4 +45,26 @@ public function testSupports() $this->assertTrue($this->loader->supports($fixture, 'annotation'), '->supports() checks the resource type if specified'); $this->assertFalse($this->loader->supports($fixture, 'foo'), '->supports() checks the resource type if specified'); } + + public function testRoutesWithPriority() + { + $routeDatas = array( + 'foo' => new Route(array('name' => 'foo', 'path' => '/foo')), + 'bar' => new Route(array('name' => 'bar', 'path' => '/bar')), + 'static_id' => new Route(array('name' => 'static_id', 'path' => '/static/{id}', 'options' => array('priority' => 1))), + 'home' => new Route(array('name' => 'home', 'path' => '/home')), + 'static_contact' => new Route(array('name' => 'static_contact', 'path' => '/static/contact', 'options' => array('priority' => 5))), + 'login' => new Route(array('name' => 'login', 'path' => '/login')), + 'static_location' => new Route(array('name' => 'static_location', 'path' => '/static/location', 'options' => array('priority' => 5))), + ); + + $this->reader + ->expects($this->once()) + ->method('getMethodAnnotations') + ->will($this->returnValue($routeDatas)); + + $routeCollection = $this->loader->load(__DIR__.'/../Fixtures/AnnotatedClasses/BarClass.php'); + $expectedOrder = array( 'static_contact', 'static_location', 'static_id', 'foo', 'bar', 'home', 'login'); + $this->assertEquals($expectedOrder, array_keys($routeCollection->all())); + } }