diff --git a/CHANGELOG-2.1.md b/CHANGELOG-2.1.md index 048a42938a13..03506f01da5b 100644 --- a/CHANGELOG-2.1.md +++ b/CHANGELOG-2.1.md @@ -348,7 +348,7 @@ To get the diff between two versions, go to https://github.com/symfony/symfony/c * the UrlMatcher does not throw a \LogicException any more when the required scheme is not the current one * added a TraceableUrlMatcher - * added the possibility to define default values and requirements for placeholders in prefix, including imported routes + * added the possibility to define options, default values and requirements for placeholders in prefix, including imported routes * added RouterInterface::getRouteCollection ### Security diff --git a/src/Symfony/Component/Routing/Loader/XmlFileLoader.php b/src/Symfony/Component/Routing/Loader/XmlFileLoader.php index 913deab43b94..8f27b03c300e 100644 --- a/src/Symfony/Component/Routing/Loader/XmlFileLoader.php +++ b/src/Symfony/Component/Routing/Loader/XmlFileLoader.php @@ -79,6 +79,7 @@ protected function parseNode(RouteCollection $collection, \DOMElement $node, $pa $defaults = array(); $requirements = array(); + $options = array(); foreach ($node->childNodes as $n) { if (!$n instanceof \DOMElement) { @@ -92,13 +93,16 @@ protected function parseNode(RouteCollection $collection, \DOMElement $node, $pa case 'requirement': $requirements[(string) $n->getAttribute('key')] = trim((string) $n->nodeValue); break; + case 'option': + $options[(string) $n->getAttribute('key')] = trim((string) $n->nodeValue); + break; default: throw new \InvalidArgumentException(sprintf('Unable to parse tag "%s"', $n->tagName)); } } $this->setCurrentDir(dirname($path)); - $collection->addCollection($this->import($resource, ('' !== $type ? $type : null), false, $file), $prefix, $defaults, $requirements); + $collection->addCollection($this->import($resource, ('' !== $type ? $type : null), false, $file), $prefix, $defaults, $requirements, $options); break; default: throw new \InvalidArgumentException(sprintf('Unable to parse tag "%s"', $node->tagName)); diff --git a/src/Symfony/Component/Routing/Loader/YamlFileLoader.php b/src/Symfony/Component/Routing/Loader/YamlFileLoader.php index 5d8f02a26828..1f9d711f8145 100644 --- a/src/Symfony/Component/Routing/Loader/YamlFileLoader.php +++ b/src/Symfony/Component/Routing/Loader/YamlFileLoader.php @@ -69,9 +69,10 @@ public function load($file, $type = null) $prefix = isset($config['prefix']) ? $config['prefix'] : null; $defaults = isset($config['defaults']) ? $config['defaults'] : array(); $requirements = isset($config['requirements']) ? $config['requirements'] : array(); + $options = isset($config['options']) ? $config['options'] : array(); $this->setCurrentDir(dirname($path)); - $collection->addCollection($this->import($config['resource'], $type, false, $file), $prefix, $defaults, $requirements); + $collection->addCollection($this->import($config['resource'], $type, false, $file), $prefix, $defaults, $requirements, $options); } else { $this->parseRoute($collection, $name, $config, $path); } diff --git a/src/Symfony/Component/Routing/Loader/schema/routing/routing-1.0.xsd b/src/Symfony/Component/Routing/Loader/schema/routing/routing-1.0.xsd index 3b8fa3db9a4b..b8571e661d07 100644 --- a/src/Symfony/Component/Routing/Loader/schema/routing/routing-1.0.xsd +++ b/src/Symfony/Component/Routing/Loader/schema/routing/routing-1.0.xsd @@ -29,6 +29,7 @@ + diff --git a/src/Symfony/Component/Routing/Route.php b/src/Symfony/Component/Routing/Route.php index 02131f430942..933dbced472f 100644 --- a/src/Symfony/Component/Routing/Route.php +++ b/src/Symfony/Component/Routing/Route.php @@ -107,9 +107,27 @@ public function getOptions() */ public function setOptions(array $options) { - $this->options = array_merge(array( + $this->options = array( 'compiler_class' => 'Symfony\\Component\\Routing\\RouteCompiler', - ), $options); + ); + + return $this->addOptions($options); + } + + /** + * Adds options. + * + * This method implements a fluent interface. + * + * @param array $options The options + * + * @return Route The current Route instance + */ + public function addOptions(array $options) + { + foreach ($options as $name => $option) { + $this->options[(string) $name] = $option; + } return $this; } diff --git a/src/Symfony/Component/Routing/RouteCollection.php b/src/Symfony/Component/Routing/RouteCollection.php index 400cfb89780d..beebd1253c1f 100644 --- a/src/Symfony/Component/Routing/RouteCollection.php +++ b/src/Symfony/Component/Routing/RouteCollection.php @@ -179,13 +179,14 @@ public function remove($name) * @param string $prefix An optional prefix to add before each pattern of the route collection * @param array $defaults An array of default values * @param array $requirements An array of requirements + * @param array $options An array of options * * @api */ - public function addCollection(RouteCollection $collection, $prefix = '', $defaults = array(), $requirements = array()) + public function addCollection(RouteCollection $collection, $prefix = '', $defaults = array(), $requirements = array(), $options = array()) { $collection->setParent($this); - $collection->addPrefix($prefix, $defaults, $requirements); + $collection->addPrefix($prefix, $defaults, $requirements, $options); // remove all routes with the same name in all existing collections foreach (array_keys($collection->all()) as $name) { @@ -201,10 +202,11 @@ public function addCollection(RouteCollection $collection, $prefix = '', $defaul * @param string $prefix An optional prefix to add before each pattern of the route collection * @param array $defaults An array of default values * @param array $requirements An array of requirements + * @param array $options An array of options * * @api */ - public function addPrefix($prefix, $defaults = array(), $requirements = array()) + public function addPrefix($prefix, $defaults = array(), $requirements = array(), $options = array()) { // a prefix must not end with a slash $prefix = rtrim($prefix, '/'); @@ -218,11 +220,12 @@ public function addPrefix($prefix, $defaults = array(), $requirements = array()) foreach ($this->routes as $name => $route) { if ($route instanceof RouteCollection) { - $route->addPrefix($prefix, $defaults, $requirements); + $route->addPrefix($prefix, $defaults, $requirements, $options); } else { $route->setPattern($prefix.$route->getPattern()); $route->addDefaults($defaults); $route->addRequirements($requirements); + $route->addOptions($options); } } } diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/validresource.xml b/src/Symfony/Component/Routing/Tests/Fixtures/validresource.xml index 72856b81618c..14ac0fc331bb 100644 --- a/src/Symfony/Component/Routing/Tests/Fixtures/validresource.xml +++ b/src/Symfony/Component/Routing/Tests/Fixtures/validresource.xml @@ -7,5 +7,6 @@ foo \d+ + diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/validresource.yml b/src/Symfony/Component/Routing/Tests/Fixtures/validresource.yml index c36dea5c4f81..e66f37613b7f 100644 --- a/src/Symfony/Component/Routing/Tests/Fixtures/validresource.yml +++ b/src/Symfony/Component/Routing/Tests/Fixtures/validresource.yml @@ -3,3 +3,4 @@ blog_show: prefix: /{foo} defaults: { 'foo': 'foo' } requirements: { 'foo': '\d+' } + options: { 'foo': 'bar' } diff --git a/src/Symfony/Component/Routing/Tests/Loader/XmlFileLoaderTest.php b/src/Symfony/Component/Routing/Tests/Loader/XmlFileLoaderTest.php index e47d1b3ec84f..554ee1a88ba3 100644 --- a/src/Symfony/Component/Routing/Tests/Loader/XmlFileLoaderTest.php +++ b/src/Symfony/Component/Routing/Tests/Loader/XmlFileLoaderTest.php @@ -61,6 +61,7 @@ public function testLoadWithImport() $this->assertContainsOnly('Symfony\Component\Routing\Route', $routes); $this->assertEquals('foo', $routes['blog_show']->getDefault('foo')); $this->assertEquals('\d+', $routes['blog_show']->getRequirement('foo')); + $this->assertEquals('bar', $routes['blog_show']->getOption('foo')); } /** diff --git a/src/Symfony/Component/Routing/Tests/Loader/YamlFileLoaderTest.php b/src/Symfony/Component/Routing/Tests/Loader/YamlFileLoaderTest.php index 79668e27bc38..0c870e667a6a 100644 --- a/src/Symfony/Component/Routing/Tests/Loader/YamlFileLoaderTest.php +++ b/src/Symfony/Component/Routing/Tests/Loader/YamlFileLoaderTest.php @@ -101,6 +101,7 @@ public function testLoadWithResource() $this->assertContainsOnly('Symfony\Component\Routing\Route', $routes); $this->assertEquals('foo', $routes['blog_show']->getDefault('foo')); $this->assertEquals('\d+', $routes['blog_show']->getRequirement('foo')); + $this->assertEquals('bar', $routes['blog_show']->getOption('foo')); } /** diff --git a/src/Symfony/Component/Routing/Tests/RouteCollectionTest.php b/src/Symfony/Component/Routing/Tests/RouteCollectionTest.php index 917d666d1aa9..3e73065d0b7c 100644 --- a/src/Symfony/Component/Routing/Tests/RouteCollectionTest.php +++ b/src/Symfony/Component/Routing/Tests/RouteCollectionTest.php @@ -107,10 +107,14 @@ public function testAddCollection() $collection->add('foo', $foo = new Route('/foo')); $collection1 = new RouteCollection(); $collection1->add('foo', $foo1 = new Route('/foo1')); - $collection->addCollection($collection1, '/{foo}', array('foo' => 'foo'), array('foo' => '\d+')); + $collection->addCollection($collection1, '/{foo}', array('foo' => 'foo'), array('foo' => '\d+'), array('foo' => 'bar')); $this->assertEquals('/{foo}/foo1', $collection->get('foo')->getPattern(), '->addCollection() can add a prefix to all merged routes'); $this->assertEquals(array('foo' => 'foo'), $collection->get('foo')->getDefaults(), '->addCollection() can add a prefix to all merged routes'); $this->assertEquals(array('foo' => '\d+'), $collection->get('foo')->getRequirements(), '->addCollection() can add a prefix to all merged routes'); + $this->assertEquals( + array('foo' => 'bar', 'compiler_class' => 'Symfony\\Component\\Routing\\RouteCompiler'), + $collection->get('foo')->getOptions(), '->addCollection() can add an option to all merged routes' + ); $collection = new RouteCollection(); $collection->addResource($foo = new FileResource(__DIR__.'/Fixtures/foo.xml')); @@ -125,13 +129,21 @@ public function testAddPrefix() $collection = new RouteCollection(); $collection->add('foo', $foo = new Route('/foo')); $collection->add('bar', $bar = new Route('/bar')); - $collection->addPrefix('/{admin}', array('admin' => 'admin'), array('admin' => '\d+')); + $collection->addPrefix('/{admin}', array('admin' => 'admin'), array('admin' => '\d+'), array('foo' => 'bar')); $this->assertEquals('/{admin}/foo', $collection->get('foo')->getPattern(), '->addPrefix() adds a prefix to all routes'); $this->assertEquals('/{admin}/bar', $collection->get('bar')->getPattern(), '->addPrefix() adds a prefix to all routes'); $this->assertEquals(array('admin' => 'admin'), $collection->get('foo')->getDefaults(), '->addPrefix() adds a prefix to all routes'); $this->assertEquals(array('admin' => 'admin'), $collection->get('bar')->getDefaults(), '->addPrefix() adds a prefix to all routes'); $this->assertEquals(array('admin' => '\d+'), $collection->get('foo')->getRequirements(), '->addPrefix() adds a prefix to all routes'); $this->assertEquals(array('admin' => '\d+'), $collection->get('bar')->getRequirements(), '->addPrefix() adds a prefix to all routes'); + $this->assertEquals( + array('foo' => 'bar', 'compiler_class' => 'Symfony\\Component\\Routing\\RouteCompiler'), + $collection->get('foo')->getOptions(), '->addPrefix() adds an option to all routes' + ); + $this->assertEquals( + array('foo' => 'bar', 'compiler_class' => 'Symfony\\Component\\Routing\\RouteCompiler'), + $collection->get('bar')->getOptions(), '->addPrefix() adds an option to all routes' + ); } public function testAddPrefixOverridesDefaultsAndRequirements() diff --git a/src/Symfony/Component/Routing/Tests/RouteTest.php b/src/Symfony/Component/Routing/Tests/RouteTest.php index 5acb64eb07da..1295bc43c0b8 100644 --- a/src/Symfony/Component/Routing/Tests/RouteTest.php +++ b/src/Symfony/Component/Routing/Tests/RouteTest.php @@ -44,14 +44,13 @@ public function testOptions() 'compiler_class' => 'Symfony\\Component\\Routing\\RouteCompiler', ), array('foo' => 'bar')), $route->getOptions(), '->setOptions() sets the options'); $this->assertEquals($route, $route->setOptions(array()), '->setOptions() implements a fluent interface'); + + $route->setOptions(array('foo' => 'foo')); + $route->addOptions(array('bar' => 'bar')); + $this->assertEquals($route, $route->addOptions(array()), '->addOptions() implements a fluent interface'); + $this->assertEquals(array('foo' => 'foo', 'bar' => 'bar', 'compiler_class' => 'Symfony\\Component\\Routing\\RouteCompiler'), $route->getOptions(), '->addDefaults() keep previous defaults'); } - /** - * @covers Symfony\Component\Routing\Route::setDefaults - * @covers Symfony\Component\Routing\Route::getDefaults - * @covers Symfony\Component\Routing\Route::setDefault - * @covers Symfony\Component\Routing\Route::getDefault - */ public function testDefaults() { $route = new Route('/{foo}');