This commit is contained in:
Arnaud Le Blanc 2012-11-05 20:53:57 +01:00
parent 8366b8ab27
commit 6cd34570d7
22 changed files with 94 additions and 77 deletions

View File

@ -93,7 +93,7 @@ EOF
? implode(', ', $requirements['_method']) : $requirements['_method'] ? implode(', ', $requirements['_method']) : $requirements['_method']
) )
: 'ANY'; : 'ANY';
$hostname = null !== $route->getHostnamePattern() $hostname = '' !== $route->getHostnamePattern()
? $route->getHostnamePattern() : 'ANY'; ? $route->getHostnamePattern() : 'ANY';
$maxName = max($maxName, strlen($name)); $maxName = max($maxName, strlen($name));

View File

@ -30,14 +30,14 @@ class CompiledRoute
/** /**
* Constructor. * Constructor.
* *
* @param string $staticPrefix The static prefix of the compiled route * @param string $staticPrefix The static prefix of the compiled route
* @param string $regex The regular expression to use to match this route * @param string $regex The regular expression to use to match this route
* @param array $tokens An array of tokens to use to generate URL for this route * @param array $tokens An array of tokens to use to generate URL for this route
* @param array $pathVariables An array of path variables * @param array $pathVariables An array of path variables
* @param array $hostnameRegex Hostname regex * @param array $hostnameRegex|null Hostname regex
* @param array $hostnameTokens Hostname tokens * @param array $hostnameTokens Hostname tokens
* @param array $hostnameVariables An array of hostname variables * @param array $hostnameVariables An array of hostname variables
* @param array $variables An array of variables (variables defined in the path and in the hostname patterns) * @param array $variables An array of variables (variables defined in the path and in the hostname patterns)
*/ */
public function __construct($staticPrefix, $regex, array $tokens, array $pathVariables, $hostnameRegex = null, array $hostnameTokens = array(), array $hostnameVariables = array(), array $variables = array()) public function __construct($staticPrefix, $regex, array $tokens, array $pathVariables, $hostnameRegex = null, array $hostnameTokens = array(), array $hostnameVariables = array(), array $variables = array())
{ {
@ -74,7 +74,7 @@ class CompiledRoute
/** /**
* Returns the hostname regex * Returns the hostname regex
* *
* @return string The hostname regex * @return string|null The hostname regex or null
*/ */
public function getHostnameRegex() public function getHostnameRegex()
{ {

View File

@ -101,7 +101,7 @@ abstract class AnnotationClassLoader implements LoaderInterface
'requirements' => array(), 'requirements' => array(),
'options' => array(), 'options' => array(),
'defaults' => array(), 'defaults' => array(),
'hostname_pattern' => null, 'hostname_pattern' => '',
); );
$class = new \ReflectionClass($class); $class = new \ReflectionClass($class);

View File

@ -70,7 +70,7 @@ class YamlFileLoader extends FileLoader
$defaults = isset($config['defaults']) ? $config['defaults'] : array(); $defaults = isset($config['defaults']) ? $config['defaults'] : array();
$requirements = isset($config['requirements']) ? $config['requirements'] : array(); $requirements = isset($config['requirements']) ? $config['requirements'] : array();
$options = isset($config['options']) ? $config['options'] : array(); $options = isset($config['options']) ? $config['options'] : array();
$hostnamePattern = isset($config['hostname_pattern']) ? $config['hostname_pattern'] : null; $hostnamePattern = isset($config['hostname_pattern']) ? $config['hostname_pattern'] : '';
$this->setCurrentDir(dirname($path)); $this->setCurrentDir(dirname($path));
$collection->addCollection($this->import($config['resource'], $type, false, $file), $prefix, $defaults, $requirements, $options, $hostnamePattern); $collection->addCollection($this->import($config['resource'], $type, false, $file), $prefix, $defaults, $requirements, $options, $hostnamePattern);

View File

@ -111,6 +111,7 @@ class ApacheMatcherDumper extends MatcherDumper
* @param Route $route The route * @param Route $route The route
* @param array $options Options * @param array $options Options
* @param bool $hostnameRegexUnique Unique identifier for the hostname regex * @param bool $hostnameRegexUnique Unique identifier for the hostname regex
*
* @return string The compiled route * @return string The compiled route
*/ */
private function dumpRoute($name, $route, array $options, $hostnameRegexUnique) private function dumpRoute($name, $route, array $options, $hostnameRegexUnique)

View File

@ -102,7 +102,7 @@ class DumperCollection implements \IteratorAggregate
/** /**
* Returns true if the attribute is defined. * Returns true if the attribute is defined.
* *
* @param string $name The attribute name * @param string $name The attribute name
* *
* @return Boolean true if the attribute is defined, false otherwise * @return Boolean true if the attribute is defined, false otherwise
*/ */
@ -117,7 +117,7 @@ class DumperCollection implements \IteratorAggregate
* @param string $name The attribute name * @param string $name The attribute name
* @param mixed $default Default value is the attribute doesn't exist * @param mixed $default Default value is the attribute doesn't exist
* *
* @return mixed The attribute value * @return mixed The attribute value
*/ */
public function getAttribute($name, $default = null) public function getAttribute($name, $default = null)
{ {
@ -138,7 +138,7 @@ class DumperCollection implements \IteratorAggregate
/** /**
* Sets multiple attributes. * Sets multiple attributes.
* *
* @param array $attributes The attributes * @param array $attributes The attributes
*/ */
public function setAttributes($attributes) public function setAttributes($attributes)
{ {

View File

@ -144,9 +144,9 @@ EOF;
/** /**
* Generates PHP code recursively to match a tree of routes * Generates PHP code recursively to match a tree of routes
* *
* @param DumperPrefixCollection $routes A DumperPrefixCollection instance * @param DumperPrefixCollection $routes A DumperPrefixCollection instance
* @param Boolean $supportsRedirections Whether redirections are supported by the base class * @param Boolean $supportsRedirections Whether redirections are supported by the base class
* @parma string $prefix Prefix of the parent collection * @parma string $prefix Prefix of the parent collection
* *
* @return string PHP code * @return string PHP code
*/ */
@ -302,7 +302,11 @@ EOF;
if ($hostnameMatches) { if ($hostnameMatches) {
$vars[] = '$hostnameMatches'; $vars[] = '$hostnameMatches';
} }
$matchesExpr = implode(' + ', $vars); if (count($vars) > 1) {
$matchesExpr = 'array_merge(' . implode(', ', array_reverse($vars)) . ')';
} else {
$matchesExpr = current($vars);
}
$code .= sprintf(" return array_merge(\$this->mergeDefaults(%s, %s), array('_route' => '%s'));\n" $code .= sprintf(" return array_merge(\$this->mergeDefaults(%s, %s), array('_route' => '%s'));\n"
, $matchesExpr, str_replace("\n", '', var_export($route->getDefaults(), true)), $name); , $matchesExpr, str_replace("\n", '', var_export($route->getDefaults(), true)), $name);
@ -313,7 +317,7 @@ EOF;
$code .= " \$matches = \$hostnameMatches;\n"; $code .= " \$matches = \$hostnameMatches;\n";
} else { } else {
if ($hostnameMatches) { if ($hostnameMatches) {
$code .= " \$matches = \$matches + \$hostnameMatches;\n"; $code .= " \$matches = array_merge(\$hostnameMatches, \$matches);\n";
} }
} }
@ -336,8 +340,8 @@ EOF;
/** /**
* Flattens a tree of routes to a single collection. * Flattens a tree of routes to a single collection.
* *
* @param RouteCollection $routes Collection of routes * @param RouteCollection $routes Collection of routes
* @param DumperCollection $to A DumperCollection to add routes to * @param DumperCollection $to A DumperCollection to add routes to
* *
* @return DumperCollection * @return DumperCollection
*/ */
@ -394,7 +398,7 @@ EOF;
* Routes order is preserved such that traversing the tree will traverse the * Routes order is preserved such that traversing the tree will traverse the
* routes in the origin order * routes in the origin order
* *
* @param DumperCollection $collection A collection of routes * @param DumperCollection $collection A collection of routes
* *
* @return DumperPrefixCollection * @return DumperPrefixCollection
*/ */

View File

@ -147,7 +147,7 @@ class UrlMatcher implements UrlMatcherInterface
continue; continue;
} }
return array_merge($this->mergeDefaults($hostnameMatches + $matches, $route->getDefaults()), array('_route' => $name)); return array_merge($this->mergeDefaults(array_merge($matches, $hostnameMatches), $route->getDefaults()), array('_route' => $name));
} }
} }

View File

@ -44,7 +44,7 @@ class Route implements \Serializable
* *
* @api * @api
*/ */
public function __construct($pattern, array $defaults = array(), array $requirements = array(), array $options = array(), $hostnamePattern = null) public function __construct($pattern, array $defaults = array(), array $requirements = array(), array $options = array(), $hostnamePattern = '')
{ {
$this->setPattern($pattern); $this->setPattern($pattern);
$this->setDefaults($defaults); $this->setDefaults($defaults);
@ -106,14 +106,24 @@ class Route implements \Serializable
return $this; return $this;
} }
/**
* Returns the hostname pattern.
*
* @return string The pattern
*/
public function getHostnamePattern() public function getHostnamePattern()
{ {
return $this->hostnamePattern; return $this->hostnamePattern;
} }
/**
* Sets the hostname pattern.
*
* @param string $pattern The pattern
*/
public function setHostnamePattern($pattern) public function setHostnamePattern($pattern)
{ {
$this->hostnamePattern = $pattern; $this->hostnamePattern = (string) $pattern;
return $this; return $this;
} }

View File

@ -42,7 +42,7 @@ class RouteCollection implements \IteratorAggregate, \Countable
$this->routes = array(); $this->routes = array();
$this->resources = array(); $this->resources = array();
$this->prefix = ''; $this->prefix = '';
$this->hostnamePattern = null; $this->hostnamePattern = '';
} }
public function __clone() public function __clone()
@ -185,18 +185,18 @@ class RouteCollection implements \IteratorAggregate, \Countable
/** /**
* Adds a route collection to the current set of routes (at the end of the current set). * Adds a route collection to the current set of routes (at the end of the current set).
* *
* @param RouteCollection $collection A RouteCollection instance * @param RouteCollection $collection A RouteCollection instance
* @param string $prefix An optional prefix to add before each pattern of the route collection * @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 $defaults An array of default values
* @param array $requirements An array of requirements * @param array $requirements An array of requirements
* @param array $options An array of options * @param array $options An array of options
* @param string $hostnamePattern Hostname pattern * @param string $hostnamePattern Hostname pattern
* *
* @throws \InvalidArgumentException When the RouteCollection already exists in the tree * @throws \InvalidArgumentException When the RouteCollection already exists in the tree
* *
* @api * @api
*/ */
public function addCollection(RouteCollection $collection, $prefix = '', $defaults = array(), $requirements = array(), $options = array(), $hostnamePattern = null) public function addCollection(RouteCollection $collection, $prefix = '', $defaults = array(), $requirements = array(), $options = array(), $hostnamePattern = '')
{ {
// prevent infinite loops by recursive referencing // prevent infinite loops by recursive referencing
$root = $this->getRoot(); $root = $this->getRoot();
@ -212,10 +212,7 @@ class RouteCollection implements \IteratorAggregate, \Countable
// necessarily already have it applied (depending on the order RouteCollections are added to each other) // necessarily already have it applied (depending on the order RouteCollections are added to each other)
$collection->addPrefix($this->getPrefix() . $prefix, $defaults, $requirements, $options); $collection->addPrefix($this->getPrefix() . $prefix, $defaults, $requirements, $options);
// Allow child collection to have a different pattern $collection->setHostnamePattern($hostnamePattern);
if (!$collection->getHostnamePattern()) {
$collection->setHostnamePattern($hostnamePattern);
}
$this->routes[] = $collection; $this->routes[] = $collection;
} }
@ -268,6 +265,34 @@ class RouteCollection implements \IteratorAggregate, \Countable
return $this->prefix; return $this->prefix;
} }
/**
* Returns the hostname pattern.
*
* @return string The pattern
*/
public function getHostnamePattern()
{
return $this->hostnamePattern;
}
/**
* Sets the hostname pattern on this collection and all children.
*
* @param string $pattern The pattern
*/
public function setHostnamePattern($pattern)
{
$this->hostnamePattern = $pattern;
if ('' === $pattern) {
return;
}
foreach ($this->routes as $name => $route) {
$route->setHostnamePattern($pattern);
}
}
/** /**
* Returns an array of resources loaded to build this collection. * Returns an array of resources loaded to build this collection.
* *
@ -350,21 +375,4 @@ class RouteCollection implements \IteratorAggregate, \Countable
return false; return false;
} }
public function getHostnamePattern()
{
return $this->hostnamePattern;
}
public function setHostnamePattern($pattern)
{
$this->hostnamePattern = $pattern;
foreach ($this->routes as $name => $route) {
// Allow individual routes to have a different pattern
if (!$route->getHostnamePattern()) {
$route->setHostnamePattern($pattern);
}
}
}
} }

View File

@ -46,7 +46,7 @@ class RouteCompiler implements RouteCompilerInterface
$hostnameRegex = null; $hostnameRegex = null;
$hostnameTokens = array(); $hostnameTokens = array();
if (null !== $hostnamePattern = $route->getHostnamePattern()) { if ('' !== $hostnamePattern = $route->getHostnamePattern()) {
$result = $this->compilePattern($route, $hostnamePattern, true); $result = $this->compilePattern($route, $hostnamePattern, true);
$hostnameVariables = $result['variables']; $hostnameVariables = $result['variables'];

View File

@ -282,7 +282,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
// route13 // route13
if (0 === strpos($pathinfo, '/route13') && preg_match('#^/route13/(?<name>[^/]++)$#s', $pathinfo, $matches)) { if (0 === strpos($pathinfo, '/route13') && preg_match('#^/route13/(?<name>[^/]++)$#s', $pathinfo, $matches)) {
$matches = $matches + $hostnameMatches; $matches = array_merge($hostnameMatches, $matches);
$matches['_route'] = 'route13'; $matches['_route'] = 'route13';
return $matches; return $matches;
@ -290,7 +290,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
// route14 // route14
if (0 === strpos($pathinfo, '/route14') && preg_match('#^/route14/(?<name>[^/]++)$#s', $pathinfo, $matches)) { if (0 === strpos($pathinfo, '/route14') && preg_match('#^/route14/(?<name>[^/]++)$#s', $pathinfo, $matches)) {
return array_merge($this->mergeDefaults($matches + $hostnameMatches, array ( 'var1' => 'val',)), array('_route' => 'route14')); return array_merge($this->mergeDefaults(array_merge($hostnameMatches, $matches), array ( 'var1' => 'val',)), array('_route' => 'route14'));
} }
} }

View File

@ -294,7 +294,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\Redirec
// route13 // route13
if (0 === strpos($pathinfo, '/route13') && preg_match('#^/route13/(?<name>[^/]++)$#s', $pathinfo, $matches)) { if (0 === strpos($pathinfo, '/route13') && preg_match('#^/route13/(?<name>[^/]++)$#s', $pathinfo, $matches)) {
$matches = $matches + $hostnameMatches; $matches = array_merge($hostnameMatches, $matches);
$matches['_route'] = 'route13'; $matches['_route'] = 'route13';
return $matches; return $matches;
@ -302,7 +302,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\Redirec
// route14 // route14
if (0 === strpos($pathinfo, '/route14') && preg_match('#^/route14/(?<name>[^/]++)$#s', $pathinfo, $matches)) { if (0 === strpos($pathinfo, '/route14') && preg_match('#^/route14/(?<name>[^/]++)$#s', $pathinfo, $matches)) {
return array_merge($this->mergeDefaults($matches + $hostnameMatches, array ( 'var1' => 'val',)), array('_route' => 'route14')); return array_merge($this->mergeDefaults(array_merge($hostnameMatches, $matches), array ( 'var1' => 'val',)), array('_route' => 'route14'));
} }
} }

View File

@ -2,6 +2,6 @@ blog_show:
pattern: /blog/{slug} pattern: /blog/{slug}
defaults: { _controller: MyBlogBundle:Blog:show } defaults: { _controller: MyBlogBundle:Blog:show }
hostname_pattern: "{locale}.example.com" hostname_pattern: "{locale}.example.com"
requirements: { 'foo': '\d+' } requirements: { 'locale': '\d+' }
options: options:
compiler_class: RouteCompiler compiler_class: RouteCompiler

View File

@ -235,7 +235,7 @@ class UrlGeneratorTest extends \PHPUnit_Framework_TestCase
$routes = $this->getRoutes('test', new Route('/testing/{foo}', array(), array('foo' => 'd+'))); $routes = $this->getRoutes('test', new Route('/testing/{foo}', array(), array('foo' => 'd+')));
$this->getGenerator($routes)->generate('test', array('foo' => 'bar'), true); $this->getGenerator($routes)->generate('test', array('foo' => 'bar'), true);
} }
/** /**
* @expectedException Symfony\Component\Routing\Exception\InvalidParameterException * @expectedException Symfony\Component\Routing\Exception\InvalidParameterException
*/ */
@ -262,7 +262,7 @@ class UrlGeneratorTest extends \PHPUnit_Framework_TestCase
$routes = $this->getRoutes('test', new Route('/', array(), array('_scheme' => 'http'))); $routes = $this->getRoutes('test', new Route('/', array(), array('_scheme' => 'http')));
$this->assertEquals('http://localhost/app.php/', $this->getGenerator($routes, array('scheme' => 'https'))->generate('test')); $this->assertEquals('http://localhost/app.php/', $this->getGenerator($routes, array('scheme' => 'https'))->generate('test'));
} }
public function testPathWithTwoStartingSlashes() public function testPathWithTwoStartingSlashes()
{ {
$routes = $this->getRoutes('test', new Route('//path-and-not-domain')); $routes = $this->getRoutes('test', new Route('//path-and-not-domain'));

View File

@ -90,7 +90,7 @@ class YamlFileLoaderTest extends \PHPUnit_Framework_TestCase
$route = $routes['blog_show']; $route = $routes['blog_show'];
$this->assertEquals('/blog/{slug}', $route->getPattern()); $this->assertEquals('/blog/{slug}', $route->getPattern());
$this->assertEquals('MyBlogBundle:Blog:show', $route->getDefault('_controller')); $this->assertEquals('MyBlogBundle:Blog:show', $route->getDefault('_controller'));
$this->assertEquals('\d+', $route->getRequirement('foo')); $this->assertEquals('\d+', $route->getRequirement('locale'));
$this->assertEquals('{locale}.example.com', $route->getHostnamePattern()); $this->assertEquals('{locale}.example.com', $route->getHostnamePattern());
$this->assertEquals('RouteCompiler', $route->getOption('compiler_class')); $this->assertEquals('RouteCompiler', $route->getOption('compiler_class'));
} }

View File

@ -22,4 +22,3 @@ class DumperCollectionTest extends \PHPUnit_Framework_TestCase
$this->assertSame($a, $c->getRoot()); $this->assertSame($a, $c->getRoot());
} }
} }

View File

@ -112,4 +112,3 @@ EOF;
return $string; return $string;
} }
} }

View File

@ -14,7 +14,6 @@ namespace Symfony\Component\Routing\Tests\Matcher\Dumper;
use Symfony\Component\Routing\Matcher\Dumper\PhpMatcherDumper; use Symfony\Component\Routing\Matcher\Dumper\PhpMatcherDumper;
use Symfony\Component\Routing\Route; use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Routing\Matcher\Dumper\DumperCollection;
class PhpMatcherDumperTest extends \PHPUnit_Framework_TestCase class PhpMatcherDumperTest extends \PHPUnit_Framework_TestCase
{ {
@ -165,13 +164,11 @@ class PhpMatcherDumperTest extends \PHPUnit_Framework_TestCase
$collection2 = new RouteCollection(); $collection2 = new RouteCollection();
$route2 = new Route('/route2', array(), array(), array(), 'a.example.com'); $route2 = new Route('/c2/route2', array(), array(), array(), 'a.example.com');
$collection2->add('route2', $route2); $collection1->add('route2', $route2);
$route3 = new Route('/route3', array(), array(), array(), 'b.example.com'); $route3 = new Route('/c2/route3', array(), array(), array(), 'b.example.com');
$collection2->add('route3', $route3); $collection1->add('route3', $route3);
$collection1->addCollection($collection2, '/c2');
$route4 = new Route('/route4', array(), array(), array(), 'a.example.com'); $route4 = new Route('/route4', array(), array(), array(), 'a.example.com');
$collection1->add('route4', $route4); $collection1->add('route4', $route4);

View File

@ -348,7 +348,7 @@ class UrlMatcherTest extends \PHPUnit_Framework_TestCase
$matcher = new UrlMatcher($coll, new RequestContext('', 'GET', 'en.example.com')); $matcher = new UrlMatcher($coll, new RequestContext('', 'GET', 'en.example.com'));
$this->assertEquals(array('foo' => 'bar', '_route' => 'foo', 'locale' => 'en'), $matcher->match('/foo/bar')); $this->assertEquals(array('foo' => 'bar', '_route' => 'foo', 'locale' => 'en'), $matcher->match('/foo/bar'));
$matcher = new UrlMatcher($coll, new RequestContext('', 'GET', 'en.example.net')); $matcher = new UrlMatcher($coll, new RequestContext('', 'GET', 'en.example.com'));
$this->assertEquals(array('foo' => 'bar', '_route' => 'bar', 'locale' => 'en'), $matcher->match('/bar/bar')); $this->assertEquals(array('foo' => 'bar', '_route' => 'bar', 'locale' => 'en'), $matcher->match('/bar/bar'));
} }

View File

@ -309,6 +309,6 @@ class RouteCollectionTest extends \PHPUnit_Framework_TestCase
$collection->setHostnamePattern('{locale}.example.com'); $collection->setHostnamePattern('{locale}.example.com');
$this->assertEquals('{locale}.example.com', $routea->getHostnamePattern()); $this->assertEquals('{locale}.example.com', $routea->getHostnamePattern());
$this->assertEquals('{locale}.example.net', $routeb->getHostnamePattern()); $this->assertEquals('{locale}.example.com', $routeb->getHostnamePattern());
} }
} }

View File

@ -197,7 +197,7 @@ class RouteCompilerTest extends \PHPUnit_Framework_TestCase
$this->assertEquals($hostnameRegex, str_replace(array("\n", ' '), '', $compiled->getHostnameRegex()), $name.' (hostname regex)'); $this->assertEquals($hostnameRegex, str_replace(array("\n", ' '), '', $compiled->getHostnameRegex()), $name.' (hostname regex)');
$this->assertEquals($hostnameVariables, $compiled->getHostnameVariables(), $name.' (hostname variables)'); $this->assertEquals($hostnameVariables, $compiled->getHostnameVariables(), $name.' (hostname variables)');
$this->assertEquals($hostnameTokens, $compiled->getHostnameTokens(), $name.' (hostname tokens)'); $this->assertEquals($hostnameTokens, $compiled->getHostnameTokens(), $name.' (hostname tokens)');
} }
public function provideCompileWithHostnameData() public function provideCompileWithHostnameData()
{ {
@ -247,8 +247,7 @@ class RouteCompilerTest extends \PHPUnit_Framework_TestCase
array('text', '.example'), array('text', '.example'),
array('variable', '', '[^\.]++', 'locale'), array('variable', '', '[^\.]++', 'locale'),
), ),
), ),
); );
} }
} }