Parcourir la source

[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.
Ryan Weaver il y a 14 ans
Parent
commit
739ebf92f5

+ 3 - 2
src/Symfony/Component/Routing/Matcher/Dumper/ApacheMatcherDumper.php

@@ -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" : '';

+ 1 - 3
src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php

@@ -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()) {

+ 2 - 1
src/Symfony/Component/Routing/Matcher/UrlMatcher.php

@@ -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;
             }
 

+ 10 - 8
src/Symfony/Component/Routing/Route.php

@@ -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 ('$' == substr($regex, -1)) {
-                    $regex = substr($regex, 0, -1);
-                }
+            if (is_array($regex)) {
+                throw new \InvalidArgumentException(sprintf('Routing requirements must be a string, array given for "%s"', $key));
+            }
+
+            if ('^' == $regex[0]) {
+                $regex = substr($regex, 1);
+            }
+
+            if ('$' == substr($regex, -1)) {
+                $regex = substr($regex, 0, -1);
             }
 
             $this->requirements[$key] = $regex;

+ 1 - 2
tests/Symfony/Tests/Component/Routing/Fixtures/dumper/url_matcher1.apache

@@ -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]

+ 1 - 1
tests/Symfony/Tests/Component/Routing/Fixtures/dumper/url_matcher1.php

@@ -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'));
         }
 

+ 3 - 3
tests/Symfony/Tests/Component/Routing/Matcher/Dumper/ApacheMatcherDumperTest.php

@@ -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);

+ 3 - 3
tests/Symfony/Tests/Component/Routing/Matcher/Dumper/PhpMatcherDumperTest.php

@@ -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.');

+ 3 - 3
tests/Symfony/Tests/Component/Routing/Matcher/UrlMatcherTest.php

@@ -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());

+ 4 - 0
tests/Symfony/Tests/Component/Routing/RouteTest.php

@@ -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()