[Routing] Changing the _method route requirement to be a regular expression so that it's consistent with all other requirements.

Unlike all other requirements, the _method regex requirement is case-insensitive.
This commit is contained in:
Ryan Weaver 2010-11-25 08:49:33 -06:00 committed by Fabien Potencier
parent acb977aa88
commit 739ebf92f5
10 changed files with 30 additions and 25 deletions

View File

@ -61,8 +61,9 @@ class ApacheMatcherDumper extends MatcherDumper
$variables = implode(',', $variables);
$conditions = array();
foreach ((array) $route->getRequirement('_method') as $method) {
$conditions[] = sprintf('RewriteCond %%{REQUEST_METHOD} =%s', strtoupper($method));
if ($req = $route->getRequirement('_method'))
{
$conditions[] = sprintf('RewriteCond %%{REQUEST_METHOD} ^(%s) [NC]', $req);
}
$conditions = count($conditions) ? implode(" [OR]\n", $conditions)."\n" : '';

View File

@ -57,9 +57,7 @@ class PhpMatcherDumper extends MatcherDumper
$conditions = array();
if ($req = $route->getRequirement('_method')) {
$req = array_map('strtolower', (array) $req);
$conditions[] = sprintf("isset(\$this->context['method']) && in_array(strtolower(\$this->context['method']), %s)", str_replace("\n", '', var_export($req, true)));
$conditions[] = sprintf("isset(\$this->context['method']) && preg_match('#^(%s)$#xi', \$this->context['method'])", $req);
}
if ($compiledRoute->getStaticPrefix()) {

View File

@ -56,7 +56,8 @@ class UrlMatcher implements UrlMatcherInterface
$compiledRoute = $route->compile();
// check HTTP method requirement
if (isset($this->context['method']) && (($req = $route->getRequirement('_method')) && !in_array(strtolower($this->context['method']), array_map('strtolower', (array) $req)))) {
if (isset($this->context['method']) && (($req = $route->getRequirement('_method')) && !preg_match(sprintf('#^(%s)$#xi', $req), $this->context['method']))) {
continue;
}

View File

@ -193,14 +193,16 @@ class Route
{
$this->requirements = array();
foreach ($requirements as $key => $regex) {
if (!is_array($regex)) {
if ('^' == $regex[0]) {
$regex = substr($regex, 1);
}
if (is_array($regex)) {
throw new \InvalidArgumentException(sprintf('Routing requirements must be a string, array given for "%s"', $key));
}
if ('$' == substr($regex, -1)) {
$regex = substr($regex, 0, -1);
}
if ('^' == $regex[0]) {
$regex = substr($regex, 1);
}
if ('$' == substr($regex, -1)) {
$regex = substr($regex, 0, -1);
}
$this->requirements[$key] = $regex;

View File

@ -1,7 +1,6 @@
RewriteCond %{PATH_INFO} ^/foo/(baz|symfony)$
RewriteRule .* app.php [QSA,L,E=_ROUTING__route:foo,E=_ROUTING_bar:%1,E=_ROUTING_def:test]
RewriteCond %{REQUEST_METHOD} =GET [OR]
RewriteCond %{REQUEST_METHOD} =HEAD
RewriteCond %{REQUEST_METHOD} ^(GET|head) [NC]
RewriteCond %{PATH_INFO} ^/bar/([^/\.]+?)$
RewriteRule .* app.php [QSA,L,E=_ROUTING__route:bar,E=_ROUTING_foo:%1]

View File

@ -25,7 +25,7 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
return array_merge($this->mergeDefaults($matches, array ( 'def' => 'test',)), array('_route' => 'foo'));
}
if (isset($this->context['method']) && in_array(strtolower($this->context['method']), array ( 0 => 'get', 1 => 'head',)) && 0 === strpos($url, '/bar') && preg_match('#^/bar/(?P<foo>[^/\.]+?)$#x', $url, $matches)) {
if (isset($this->context['method']) && preg_match('#^(GET|head)$#xi', $this->context['method']) && 0 === strpos($url, '/bar') && preg_match('#^/bar/(?P<foo>[^/\.]+?)$#x', $url, $matches)) {
return array_merge($this->mergeDefaults($matches, array ()), array('_route' => 'bar'));
}

View File

@ -28,15 +28,15 @@ class ApacheMatcherDumperTest extends \PHPUnit_Framework_TestCase
{
$collection = new RouteCollection();
$collection->addRoute('foo', new Route(
$collection->add('foo', new Route(
'/foo/:bar',
array('def' => 'test'),
array('bar' => 'baz|symfony')
));
$collection->addRoute('bar', new Route(
$collection->add('bar', new Route(
'/bar/:foo',
array(),
array('_method' => array('GET', 'HEAD'))
array('_method' => 'GET|head')
));
$dumper = new ApacheMatcherDumper($collection);

View File

@ -28,15 +28,15 @@ class PhpMatcherDumperTest extends \PHPUnit_Framework_TestCase
{
$collection = new RouteCollection();
$collection->addRoute('foo', new Route(
$collection->add('foo', new Route(
'/foo/:bar',
array('def' => 'test'),
array('bar' => 'baz|symfony')
));
$collection->addRoute('bar', new Route(
$collection->add('bar', new Route(
'/bar/:foo',
array(),
array('_method' => array('GET', 'HEAD'))
array('_method' => 'GET|head')
));
$dumper = new PhpMatcherDumper($collection);
$this->assertStringEqualsFile(self::$fixturesPath.'/dumper/url_matcher1.php', $dumper->dump(), '->dump() dumps basic routes to the correct PHP file.');

View File

@ -34,20 +34,20 @@ class UrlMatcherTest extends \PHPUnit_Framework_TestCase
{
// test the patterns are matched are parameters are returned
$collection = new RouteCollection();
$collection->addRoute('foo', new Route('/foo/:bar'));
$collection->add('foo', new Route('/foo/:bar'));
$matcher = new UrlMatcher($collection, array(), array());
$this->assertEquals(false, $matcher->match('/no-match'));
$this->assertEquals(array('_route' => 'foo', 'bar' => 'baz'), $matcher->match('/foo/baz'));
// test that defaults are merged
$collection = new RouteCollection();
$collection->addRoute('foo', new Route('/foo/:bar', array('def' => 'test')));
$collection->add('foo', new Route('/foo/:bar', array('def' => 'test')));
$matcher = new UrlMatcher($collection, array(), array());
$this->assertEquals(array('_route' => 'foo', 'bar' => 'baz', 'def' => 'test'), $matcher->match('/foo/baz'));
// test that route "metod" is ignore if no method is given in the context
$collection = new RouteCollection();
$collection->addRoute('foo', new Route('/foo', array(), array('_method' => array('GET', 'HEAD'))));
$collection->add('foo', new Route('/foo', array(), array('_method' => 'GET|head')));
// route matches with no context
$matcher = new UrlMatcher($collection, array(), array());

View File

@ -79,6 +79,10 @@ class RouteTest extends \PHPUnit_Framework_TestCase
$route->setRequirements(array('foo' => '^\d+$'));
$this->assertEquals('\d+', $route->getRequirement('foo'), '->getRequirement() removes ^ and $ from the pattern');
$this->assertEquals($route, $route->setRequirements(array()), '->setRequirements() implements a fluent interface');
// test that an array requirement throws an exception
$this->setExpectedException('InvalidArgumentException');
$route->setRequirements(array('foo' => array('bar', 'baz')));
}
public function testCompile()