From f0b7433fac76ed14320819d2326dac421e8d2fad Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 29 Jan 2018 18:46:50 +0100 Subject: [PATCH] [Routing] check static routes first in a switch --- .../Generator/Dumper/PhpGeneratorDumper.php | 4 +- .../Matcher/Dumper/PhpMatcherDumper.php | 132 ++++++- .../Tests/Fixtures/dumper/url_matcher1.php | 245 +++++++------ .../Tests/Fixtures/dumper/url_matcher2.php | 325 +++++++++--------- .../Tests/Fixtures/dumper/url_matcher3.php | 26 +- .../Tests/Fixtures/dumper/url_matcher4.php | 94 +++-- .../Tests/Fixtures/dumper/url_matcher5.php | 149 ++++---- .../Tests/Fixtures/dumper/url_matcher6.php | 127 ++++--- .../Tests/Fixtures/dumper/url_matcher7.php | 147 ++++---- 9 files changed, 643 insertions(+), 606 deletions(-) diff --git a/src/Symfony/Component/Routing/Generator/Dumper/PhpGeneratorDumper.php b/src/Symfony/Component/Routing/Generator/Dumper/PhpGeneratorDumper.php index 60bdf1da3522c..0cb87f1163f3b 100644 --- a/src/Symfony/Component/Routing/Generator/Dumper/PhpGeneratorDumper.php +++ b/src/Symfony/Component/Routing/Generator/Dumper/PhpGeneratorDumper.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Routing\Generator\Dumper; +use Symfony\Component\Routing\Matcher\Dumper\PhpMatcherDumper; + /** * PhpGeneratorDumper creates a PHP class able to generate URLs for a given set of routes. * @@ -88,7 +90,7 @@ private function generateDeclaredRoutes() $properties[] = $compiledRoute->getHostTokens(); $properties[] = $route->getSchemes(); - $routes .= sprintf(" '%s' => %s,\n", $name, str_replace("\n", '', var_export($properties, true))); + $routes .= sprintf(" '%s' => %s,\n", $name, PhpMatcherDumper::export($properties)); } $routes .= ' )'; diff --git a/src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php b/src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php index b74ff8a9d79cf..098f549783dfe 100644 --- a/src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php +++ b/src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php @@ -140,8 +140,9 @@ private function compileRoutes(RouteCollection $routes, $supportsRedirections) $code .= sprintf(" if (preg_match(%s, \$host, \$hostMatches)) {\n", var_export($regex, true)); } + $groupCode = $this->compileStaticRoutes($collection, $supportsRedirections); $tree = $this->buildStaticPrefixCollection($collection); - $groupCode = $this->compileStaticPrefixRoutes($tree, $supportsRedirections); + $groupCode .= $this->compileStaticPrefixRoutes($tree, $supportsRedirections); if (null !== $regex) { // apply extra indention at each line (except empty ones) @@ -176,6 +177,66 @@ private function buildStaticPrefixCollection(DumperCollection $collection) return $prefixCollection; } + /** + * Generates PHP code to match the static routes in a collection. + */ + private function compileStaticRoutes(DumperCollection $collection, bool $supportsRedirections): string + { + $code = ''; + $dynamicRegex = array(); + $dynamicRoutes = array(); + $staticRoutes = array(); + + foreach ($collection->all() as $route) { + $compiledRoute = $route->getRoute()->compile(); + $regex = $compiledRoute->getRegex(); + $methods = $route->getRoute()->getMethods(); + if ($hasTrailingSlash = $supportsRedirections && $pos = strpos($regex, '/$')) { + $regex = substr($regex, 0, $pos).'/?$'.substr($regex, $pos + 2); + } + if (!$compiledRoute->getPathVariables()) { + $url = $route->getRoute()->getPath(); + if ($hasTrailingSlash) { + $url = rtrim($url, '/'); + } + foreach ($dynamicRegex as $rx) { + if (preg_match($rx, $url)) { + $dynamicRegex[] = $regex; + $dynamicRoutes[] = $route; + continue 2; + } + } + + $staticRoutes[$url][] = array($hasTrailingSlash, $route); + } else { + $dynamicRegex[] = $regex; + $dynamicRoutes[] = $route; + } + } + + $collection->setAll($dynamicRoutes); + + if ($staticRoutes) { + foreach ($staticRoutes as $url => $routes) { + $code .= sprintf(" case %s:\n", var_export($url, true)); + foreach ($routes as list($hasTrailingSlash, $route)) { + $methods = $route->getRoute()->getMethods(); + $supportsTrailingSlash = $supportsRedirections && (!$methods || in_array('HEAD', $methods) || in_array('GET', $methods)); + $routeCode = $this->compileRoute($route->getRoute(), $route->getName(), $supportsRedirections, null, $hasTrailingSlash); + if ($route->getRoute()->getCondition() || ($hasTrailingSlash && !$supportsTrailingSlash)) { + $routeCode = preg_replace('/^.{2,}$/m', ' $0', $routeCode); + } + $code .= $routeCode; + } + $code .= " break;\n"; + } + $code = preg_replace('/^.{2,}$/m', ' $0', $code); + $code = sprintf(" switch (%s) {\n{$code} }\n\n", $supportsRedirections ? '$trimmedPathinfo' : '$pathinfo'); + } + + return $code; + } + /** * Generates PHP code to match a tree of routes. * @@ -222,17 +283,17 @@ private function compileStaticPrefixRoutes(StaticPrefixCollection $collection, $ * @param string $name The name of the Route * @param bool $supportsRedirections Whether redirections are supported by the base class * @param string|null $parentPrefix The prefix of the parent collection used to optimize the code + * @param bool|null $hasTrailingSlash Whether the path has a trailing slash when compiling a static route * * @return string PHP code * * @throws \LogicException */ - private function compileRoute(Route $route, $name, $supportsRedirections, $parentPrefix = null) + private function compileRoute(Route $route, $name, $supportsRedirections, $parentPrefix = null, bool $hasTrailingSlash = null) { $code = ''; $compiledRoute = $route->compile(); $conditions = array(); - $hasTrailingSlash = false; $matches = false; $hostMatches = false; $methods = $route->getMethods(); @@ -240,10 +301,11 @@ private function compileRoute(Route $route, $name, $supportsRedirections, $paren $supportsTrailingSlash = $supportsRedirections && (!$methods || in_array('HEAD', $methods) || in_array('GET', $methods)); $regex = $compiledRoute->getRegex(); - if (!count($compiledRoute->getPathVariables()) && false !== preg_match('#^(.)\^(?P.*?)\$\1#'.('u' === substr($regex, -1) ? 'u' : ''), $regex, $m)) { - if ($supportsTrailingSlash && '/' === substr($m['url'], -1)) { + if (null !== $hasTrailingSlash && (!$hasTrailingSlash || $supportsTrailingSlash)) { + // no-op + } elseif (!$compiledRoute->getPathVariables() && preg_match('#^(.)\^(?P.*?)\$\1#'.('u' === $regex[-1] ? 'u' : ''), $regex, $m)) { + if ($hasTrailingSlash = $supportsTrailingSlash && '/' === $m['url'][-1]) { $conditions[] = sprintf('%s === $trimmedPathinfo', var_export(rtrim(str_replace('\\', '', $m['url']), '/'), true)); - $hasTrailingSlash = true; } else { $conditions[] = sprintf('%s === $pathinfo', var_export(str_replace('\\', '', $m['url']), true)); } @@ -252,9 +314,8 @@ private function compileRoute(Route $route, $name, $supportsRedirections, $paren $conditions[] = sprintf('0 === strpos($pathinfo, %s)', var_export($compiledRoute->getStaticPrefix(), true)); } - if ($supportsTrailingSlash && $pos = strpos($regex, '/$')) { + if ($hasTrailingSlash = $supportsTrailingSlash && $pos = strpos($regex, '/$')) { $regex = substr($regex, 0, $pos).'/?$'.substr($regex, $pos + 2); - $hasTrailingSlash = true; } $conditions[] = sprintf('preg_match(%s, $pathinfo, $matches)', var_export($regex, true)); @@ -271,11 +332,15 @@ private function compileRoute(Route $route, $name, $supportsRedirections, $paren $conditions = implode(' && ', $conditions); - $code .= <<mergeDefaults(array_replace(%s), %s);\n", implode(', ', $vars), - str_replace("\n", '', var_export($route->getDefaults(), true)) + self::export($route->getDefaults()) ); } elseif ($route->getDefaults()) { - $code .= sprintf(" \$ret = %s;\n", str_replace("\n", '', var_export(array_replace($route->getDefaults(), array('_route' => $name)), true))); + $code .= sprintf(" \$ret = %s;\n", self::export(array_replace($route->getDefaults(), array('_route' => $name)))); } else { $code .= sprintf(" \$ret = array('_route' => '%s');\n", $name); } if ($hasTrailingSlash) { $code .= <<getScheme()])) { @@ -391,7 +456,11 @@ private function compileRoute(Route $route, $name, $supportsRedirections, $paren } else { $code = substr_replace($code, 'return', $retOffset, 6); } - $code .= " }\n"; + if ($conditions) { + $code .= " }\n"; + } elseif ($methods || $hasTrailingSlash) { + $code .= ' '; + } if ($methods || $hasTrailingSlash) { $code .= " $gotoname:\n"; @@ -440,4 +509,39 @@ private function getExpressionLanguage() return $this->expressionLanguage; } + + /** + * @internal + */ + public static function export($value): string + { + if (null === $value) { + return 'null'; + } + if (!\is_array($value)) { + return var_export($value, true); + } + if (!$value) { + return 'array()'; + } + + $i = 0; + $export = 'array('; + + foreach ($value as $k => $v) { + if ($i === $k) { + ++$i; + } else { + $export .= var_export($k, true).' => '; + + if (\is_int($k) && $i < $k) { + $i = 1 + $k; + } + } + + $export .= self::export($v).', '; + } + + return substr_replace($export, ')', -2); + } } diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher1.php b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher1.php index 9506f0cbfc944..33e701ac9e8ff 100644 --- a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher1.php +++ b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher1.php @@ -28,20 +28,47 @@ public function match($rawPathinfo) $canonicalMethod = 'GET'; } - if (0 === strpos($pathinfo, '/foo')) { - // foo - if (preg_match('#^/foo/(?Pbaz|symfony)$#sD', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo')), array ( 'def' => 'test',)); - } - - // foofoo - if ('/foofoo' === $pathinfo) { - return array ( 'def' => 'test', '_route' => 'foofoo',); - } + switch ($pathinfo) { + case '/test/baz': + // baz + return array('_route' => 'baz'); + break; + case '/test/baz.html': + // baz2 + return array('_route' => 'baz2'); + break; + case '/test/baz3/': + // baz3 + return array('_route' => 'baz3'); + break; + case '/foofoo': + // foofoo + return array('def' => 'test', '_route' => 'foofoo'); + break; + case '/spa ce': + // space + return array('_route' => 'space'); + break; + case '/multi/new': + // overridden2 + return array('_route' => 'overridden2'); + break; + case '/multi/hey/': + // hey + return array('_route' => 'hey'); + break; + case '/ababa': + // ababa + return array('_route' => 'ababa'); + break; + } + // foo + if (0 === strpos($pathinfo, '/foo') && preg_match('#^/foo/(?Pbaz|symfony)$#sD', $pathinfo, $matches)) { + return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo')), array('def' => 'test')); } - elseif (0 === strpos($pathinfo, '/bar')) { + if (0 === strpos($pathinfo, '/bar')) { // bar if (preg_match('#^/bar/(?P[^/]++)$#sD', $pathinfo, $matches)) { if ('GET' !== $canonicalMethod) { @@ -49,7 +76,7 @@ public function match($rawPathinfo) goto not_bar; } - return $this->mergeDefaults(array_replace($matches, array('_route' => 'bar')), array ()); + return $this->mergeDefaults(array_replace($matches, array('_route' => 'bar')), array()); } not_bar: @@ -60,34 +87,16 @@ public function match($rawPathinfo) goto not_barhead; } - return $this->mergeDefaults(array_replace($matches, array('_route' => 'barhead')), array ()); + return $this->mergeDefaults(array_replace($matches, array('_route' => 'barhead')), array()); } not_barhead: } elseif (0 === strpos($pathinfo, '/test')) { - if (0 === strpos($pathinfo, '/test/baz')) { - // baz - if ('/test/baz' === $pathinfo) { - return array('_route' => 'baz'); - } - - // baz2 - if ('/test/baz.html' === $pathinfo) { - return array('_route' => 'baz2'); - } - - // baz3 - if ('/test/baz3/' === $pathinfo) { - return array('_route' => 'baz3'); - } - - } - // baz4 if (preg_match('#^/test/(?P[^/]++)/$#sD', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'baz4')), array ()); + return $this->mergeDefaults(array_replace($matches, array('_route' => 'baz4')), array()); } // baz5 @@ -97,7 +106,7 @@ public function match($rawPathinfo) goto not_baz5; } - return $this->mergeDefaults(array_replace($matches, array('_route' => 'baz5')), array ()); + return $this->mergeDefaults(array_replace($matches, array('_route' => 'baz5')), array()); } not_baz5: @@ -108,7 +117,7 @@ public function match($rawPathinfo) goto not_bazbaz6; } - return $this->mergeDefaults(array_replace($matches, array('_route' => 'baz.baz6')), array ()); + return $this->mergeDefaults(array_replace($matches, array('_route' => 'baz.baz6')), array()); } not_bazbaz6: @@ -116,155 +125,136 @@ public function match($rawPathinfo) // quoter if (preg_match('#^/(?P[\']+)$#sD', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'quoter')), array ()); - } - - // space - if ('/spa ce' === $pathinfo) { - return array('_route' => 'space'); + return $this->mergeDefaults(array_replace($matches, array('_route' => 'quoter')), array()); } if (0 === strpos($pathinfo, '/a')) { if (0 === strpos($pathinfo, '/a/b\'b')) { // foo1 if (preg_match('#^/a/b\'b/(?P[^/]++)$#sD', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo1')), array ()); + return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo1')), array()); } // bar1 if (preg_match('#^/a/b\'b/(?P[^/]++)$#sD', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'bar1')), array ()); + return $this->mergeDefaults(array_replace($matches, array('_route' => 'bar1')), array()); } } // overridden if (preg_match('#^/a/(?P.*)$#sD', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'overridden')), array ()); + return $this->mergeDefaults(array_replace($matches, array('_route' => 'overridden')), array()); } if (0 === strpos($pathinfo, '/a/b\'b')) { // foo2 if (preg_match('#^/a/b\'b/(?P[^/]++)$#sD', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo2')), array ()); + return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo2')), array()); } // bar2 if (preg_match('#^/a/b\'b/(?P[^/]++)$#sD', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'bar2')), array ()); + return $this->mergeDefaults(array_replace($matches, array('_route' => 'bar2')), array()); } } } - elseif (0 === strpos($pathinfo, '/multi')) { - // helloWorld - if (0 === strpos($pathinfo, '/multi/hello') && preg_match('#^/multi/hello(?:/(?P[^/]++))?$#sD', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'helloWorld')), array ( 'who' => 'World!',)); - } - - // hey - if ('/multi/hey/' === $pathinfo) { - return array('_route' => 'hey'); - } - - // overridden2 - if ('/multi/new' === $pathinfo) { - return array('_route' => 'overridden2'); - } - + // helloWorld + if (0 === strpos($pathinfo, '/multi/hello') && preg_match('#^/multi/hello(?:/(?P[^/]++))?$#sD', $pathinfo, $matches)) { + return $this->mergeDefaults(array_replace($matches, array('_route' => 'helloWorld')), array('who' => 'World!')); } // foo3 if (preg_match('#^/(?P<_locale>[^/]++)/b/(?P[^/]++)$#sD', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo3')), array ()); + return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo3')), array()); } // bar3 if (preg_match('#^/(?P<_locale>[^/]++)/b/(?P[^/]++)$#sD', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'bar3')), array ()); + return $this->mergeDefaults(array_replace($matches, array('_route' => 'bar3')), array()); } - if (0 === strpos($pathinfo, '/aba')) { - // ababa - if ('/ababa' === $pathinfo) { - return array('_route' => 'ababa'); - } - - // foo4 - if (preg_match('#^/aba/(?P[^/]++)$#sD', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo4')), array ()); - } - + // foo4 + if (0 === strpos($pathinfo, '/aba') && preg_match('#^/aba/(?P[^/]++)$#sD', $pathinfo, $matches)) { + return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo4')), array()); } $host = $context->getHost(); if (preg_match('#^a\\.example\\.com$#sDi', $host, $hostMatches)) { - // route1 - if ('/route1' === $pathinfo) { - return array('_route' => 'route1'); - } - - // route2 - if ('/c2/route2' === $pathinfo) { - return array('_route' => 'route2'); + switch ($pathinfo) { + case '/route1': + // route1 + return array('_route' => 'route1'); + break; + case '/c2/route2': + // route2 + return array('_route' => 'route2'); + break; } } if (preg_match('#^b\\.example\\.com$#sDi', $host, $hostMatches)) { - // route3 - if ('/c2/route3' === $pathinfo) { - return array('_route' => 'route3'); + switch ($pathinfo) { + case '/c2/route3': + // route3 + return array('_route' => 'route3'); + break; } } if (preg_match('#^a\\.example\\.com$#sDi', $host, $hostMatches)) { - // route4 - if ('/route4' === $pathinfo) { - return array('_route' => 'route4'); + switch ($pathinfo) { + case '/route4': + // route4 + return array('_route' => 'route4'); + break; } } if (preg_match('#^c\\.example\\.com$#sDi', $host, $hostMatches)) { - // route5 - if ('/route5' === $pathinfo) { - return array('_route' => 'route5'); + switch ($pathinfo) { + case '/route5': + // route5 + return array('_route' => 'route5'); + break; } } - // route6 - if ('/route6' === $pathinfo) { - return array('_route' => 'route6'); + switch ($pathinfo) { + case '/route6': + // route6 + return array('_route' => 'route6'); + break; } if (preg_match('#^(?P[^\\.]++)\\.example\\.com$#sDi', $host, $hostMatches)) { - if (0 === strpos($pathinfo, '/route1')) { - // route11 - if ('/route11' === $pathinfo) { - return $this->mergeDefaults(array_replace($hostMatches, array('_route' => 'route11')), array ()); - } - - // route12 - if ('/route12' === $pathinfo) { - return $this->mergeDefaults(array_replace($hostMatches, array('_route' => 'route12')), array ( 'var1' => 'val',)); - } - - // route13 - if (0 === strpos($pathinfo, '/route13') && preg_match('#^/route13/(?P[^/]++)$#sD', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($hostMatches, $matches, array('_route' => 'route13')), array ()); - } + switch ($pathinfo) { + case '/route11': + // route11 + return $this->mergeDefaults(array_replace($hostMatches, array('_route' => 'route11')), array()); + break; + case '/route12': + // route12 + return $this->mergeDefaults(array_replace($hostMatches, array('_route' => 'route12')), array('var1' => 'val')); + break; + } - // route14 - if (0 === strpos($pathinfo, '/route14') && preg_match('#^/route14/(?P[^/]++)$#sD', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($hostMatches, $matches, array('_route' => 'route14')), array ( 'var1' => 'val',)); - } + // route13 + if (0 === strpos($pathinfo, '/route13') && preg_match('#^/route13/(?P[^/]++)$#sD', $pathinfo, $matches)) { + return $this->mergeDefaults(array_replace($hostMatches, $matches, array('_route' => 'route13')), array()); + } + // route14 + if (0 === strpos($pathinfo, '/route14') && preg_match('#^/route14/(?P[^/]++)$#sD', $pathinfo, $matches)) { + return $this->mergeDefaults(array_replace($hostMatches, $matches, array('_route' => 'route14')), array('var1' => 'val')); } } @@ -272,35 +262,36 @@ public function match($rawPathinfo) if (preg_match('#^c\\.example\\.com$#sDi', $host, $hostMatches)) { // route15 if (0 === strpos($pathinfo, '/route15') && preg_match('#^/route15/(?P[^/]++)$#sD', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'route15')), array ()); + return $this->mergeDefaults(array_replace($matches, array('_route' => 'route15')), array()); } } - // route16 - if (0 === strpos($pathinfo, '/route16') && preg_match('#^/route16/(?P[^/]++)$#sD', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'route16')), array ( 'var1' => 'val',)); - } - - // route17 - if ('/route17' === $pathinfo) { - return array('_route' => 'route17'); + switch ($pathinfo) { + case '/route17': + // route17 + return array('_route' => 'route17'); + break; + case '/a/a...': + // a + return array('_route' => 'a'); + break; } - // a - if ('/a/a...' === $pathinfo) { - return array('_route' => 'a'); + // route16 + if (0 === strpos($pathinfo, '/route16') && preg_match('#^/route16/(?P[^/]++)$#sD', $pathinfo, $matches)) { + return $this->mergeDefaults(array_replace($matches, array('_route' => 'route16')), array('var1' => 'val')); } if (0 === strpos($pathinfo, '/a/b')) { // b if (preg_match('#^/a/b/(?P[^/]++)$#sD', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'b')), array ()); + return $this->mergeDefaults(array_replace($matches, array('_route' => 'b')), array()); } // c if (0 === strpos($pathinfo, '/a/b/c') && preg_match('#^/a/b/c/(?P[^/]++)$#sD', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'c')), array ()); + return $this->mergeDefaults(array_replace($matches, array('_route' => 'c')), array()); } } diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.php b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.php index 69e8420e8d50a..ac71c4295d87b 100644 --- a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.php +++ b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.php @@ -28,20 +28,67 @@ public function match($rawPathinfo) $canonicalMethod = 'GET'; } - if (0 === strpos($pathinfo, '/foo')) { - // foo - if (preg_match('#^/foo/(?Pbaz|symfony)$#sD', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo')), array ( 'def' => 'test',)); - } + switch ($trimmedPathinfo) { + case '/test/baz': + // baz + return array('_route' => 'baz'); + break; + case '/test/baz.html': + // baz2 + return array('_route' => 'baz2'); + break; + case '/test/baz3': + // baz3 + $ret = array('_route' => 'baz3'); + if ('/' === $pathinfo[-1]) { + // no-op + } elseif ('GET' !== $canonicalMethod) { + goto not_baz3; + } else { + return array_replace($ret, $this->redirect($rawPathinfo.'/', 'baz3')); + } - // foofoo - if ('/foofoo' === $pathinfo) { - return array ( 'def' => 'test', '_route' => 'foofoo',); - } + return $ret; + not_baz3: + break; + case '/foofoo': + // foofoo + return array('def' => 'test', '_route' => 'foofoo'); + break; + case '/spa ce': + // space + return array('_route' => 'space'); + break; + case '/multi/new': + // overridden2 + return array('_route' => 'overridden2'); + break; + case '/multi/hey': + // hey + $ret = array('_route' => 'hey'); + if ('/' === $pathinfo[-1]) { + // no-op + } elseif ('GET' !== $canonicalMethod) { + goto not_hey; + } else { + return array_replace($ret, $this->redirect($rawPathinfo.'/', 'hey')); + } + return $ret; + not_hey: + break; + case '/ababa': + // ababa + return array('_route' => 'ababa'); + break; } - elseif (0 === strpos($pathinfo, '/bar')) { + // foo + if (0 === strpos($pathinfo, '/foo') && preg_match('#^/foo/(?Pbaz|symfony)$#sD', $pathinfo, $matches)) { + return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo')), array('def' => 'test')); + } + + if (0 === strpos($pathinfo, '/bar')) { // bar if (preg_match('#^/bar/(?P[^/]++)$#sD', $pathinfo, $matches)) { if ('GET' !== $canonicalMethod) { @@ -49,7 +96,7 @@ public function match($rawPathinfo) goto not_bar; } - return $this->mergeDefaults(array_replace($matches, array('_route' => 'bar')), array ()); + return $this->mergeDefaults(array_replace($matches, array('_route' => 'bar')), array()); } not_bar: @@ -60,45 +107,17 @@ public function match($rawPathinfo) goto not_barhead; } - return $this->mergeDefaults(array_replace($matches, array('_route' => 'barhead')), array ()); + return $this->mergeDefaults(array_replace($matches, array('_route' => 'barhead')), array()); } not_barhead: } elseif (0 === strpos($pathinfo, '/test')) { - if (0 === strpos($pathinfo, '/test/baz')) { - // baz - if ('/test/baz' === $pathinfo) { - return array('_route' => 'baz'); - } - - // baz2 - if ('/test/baz.html' === $pathinfo) { - return array('_route' => 'baz2'); - } - - // baz3 - if ('/test/baz3' === $trimmedPathinfo) { - $ret = array('_route' => 'baz3'); - if ('/' === substr($pathinfo, -1)) { - // no-op - } elseif ('GET' !== $canonicalMethod) { - goto not_baz3; - } else { - return array_replace($ret, $this->redirect($rawPathinfo.'/', 'baz3')); - } - - return $ret; - } - not_baz3: - - } - // baz4 if (preg_match('#^/test/(?P[^/]++)/?$#sD', $pathinfo, $matches)) { - $ret = $this->mergeDefaults(array_replace($matches, array('_route' => 'baz4')), array ()); - if ('/' === substr($pathinfo, -1)) { + $ret = $this->mergeDefaults(array_replace($matches, array('_route' => 'baz4')), array()); + if ('/' === $pathinfo[-1]) { // no-op } elseif ('GET' !== $canonicalMethod) { goto not_baz4; @@ -117,7 +136,7 @@ public function match($rawPathinfo) goto not_baz5; } - return $this->mergeDefaults(array_replace($matches, array('_route' => 'baz5')), array ()); + return $this->mergeDefaults(array_replace($matches, array('_route' => 'baz5')), array()); } not_baz5: @@ -128,7 +147,7 @@ public function match($rawPathinfo) goto not_bazbaz6; } - return $this->mergeDefaults(array_replace($matches, array('_route' => 'baz.baz6')), array ()); + return $this->mergeDefaults(array_replace($matches, array('_route' => 'baz.baz6')), array()); } not_bazbaz6: @@ -136,165 +155,136 @@ public function match($rawPathinfo) // quoter if (preg_match('#^/(?P[\']+)$#sD', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'quoter')), array ()); - } - - // space - if ('/spa ce' === $pathinfo) { - return array('_route' => 'space'); + return $this->mergeDefaults(array_replace($matches, array('_route' => 'quoter')), array()); } if (0 === strpos($pathinfo, '/a')) { if (0 === strpos($pathinfo, '/a/b\'b')) { // foo1 if (preg_match('#^/a/b\'b/(?P[^/]++)$#sD', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo1')), array ()); + return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo1')), array()); } // bar1 if (preg_match('#^/a/b\'b/(?P[^/]++)$#sD', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'bar1')), array ()); + return $this->mergeDefaults(array_replace($matches, array('_route' => 'bar1')), array()); } } // overridden if (preg_match('#^/a/(?P.*)$#sD', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'overridden')), array ()); + return $this->mergeDefaults(array_replace($matches, array('_route' => 'overridden')), array()); } if (0 === strpos($pathinfo, '/a/b\'b')) { // foo2 if (preg_match('#^/a/b\'b/(?P[^/]++)$#sD', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo2')), array ()); + return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo2')), array()); } // bar2 if (preg_match('#^/a/b\'b/(?P[^/]++)$#sD', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'bar2')), array ()); + return $this->mergeDefaults(array_replace($matches, array('_route' => 'bar2')), array()); } } } - elseif (0 === strpos($pathinfo, '/multi')) { - // helloWorld - if (0 === strpos($pathinfo, '/multi/hello') && preg_match('#^/multi/hello(?:/(?P[^/]++))?$#sD', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'helloWorld')), array ( 'who' => 'World!',)); - } - - // hey - if ('/multi/hey' === $trimmedPathinfo) { - $ret = array('_route' => 'hey'); - if ('/' === substr($pathinfo, -1)) { - // no-op - } elseif ('GET' !== $canonicalMethod) { - goto not_hey; - } else { - return array_replace($ret, $this->redirect($rawPathinfo.'/', 'hey')); - } - - return $ret; - } - not_hey: - - // overridden2 - if ('/multi/new' === $pathinfo) { - return array('_route' => 'overridden2'); - } - + // helloWorld + if (0 === strpos($pathinfo, '/multi/hello') && preg_match('#^/multi/hello(?:/(?P[^/]++))?$#sD', $pathinfo, $matches)) { + return $this->mergeDefaults(array_replace($matches, array('_route' => 'helloWorld')), array('who' => 'World!')); } // foo3 if (preg_match('#^/(?P<_locale>[^/]++)/b/(?P[^/]++)$#sD', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo3')), array ()); + return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo3')), array()); } // bar3 if (preg_match('#^/(?P<_locale>[^/]++)/b/(?P[^/]++)$#sD', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'bar3')), array ()); + return $this->mergeDefaults(array_replace($matches, array('_route' => 'bar3')), array()); } - if (0 === strpos($pathinfo, '/aba')) { - // ababa - if ('/ababa' === $pathinfo) { - return array('_route' => 'ababa'); - } - - // foo4 - if (preg_match('#^/aba/(?P[^/]++)$#sD', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo4')), array ()); - } - + // foo4 + if (0 === strpos($pathinfo, '/aba') && preg_match('#^/aba/(?P[^/]++)$#sD', $pathinfo, $matches)) { + return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo4')), array()); } $host = $context->getHost(); if (preg_match('#^a\\.example\\.com$#sDi', $host, $hostMatches)) { - // route1 - if ('/route1' === $pathinfo) { - return array('_route' => 'route1'); - } - - // route2 - if ('/c2/route2' === $pathinfo) { - return array('_route' => 'route2'); + switch ($trimmedPathinfo) { + case '/route1': + // route1 + return array('_route' => 'route1'); + break; + case '/c2/route2': + // route2 + return array('_route' => 'route2'); + break; } } if (preg_match('#^b\\.example\\.com$#sDi', $host, $hostMatches)) { - // route3 - if ('/c2/route3' === $pathinfo) { - return array('_route' => 'route3'); + switch ($trimmedPathinfo) { + case '/c2/route3': + // route3 + return array('_route' => 'route3'); + break; } } if (preg_match('#^a\\.example\\.com$#sDi', $host, $hostMatches)) { - // route4 - if ('/route4' === $pathinfo) { - return array('_route' => 'route4'); + switch ($trimmedPathinfo) { + case '/route4': + // route4 + return array('_route' => 'route4'); + break; } } if (preg_match('#^c\\.example\\.com$#sDi', $host, $hostMatches)) { - // route5 - if ('/route5' === $pathinfo) { - return array('_route' => 'route5'); + switch ($trimmedPathinfo) { + case '/route5': + // route5 + return array('_route' => 'route5'); + break; } } - // route6 - if ('/route6' === $pathinfo) { - return array('_route' => 'route6'); + switch ($trimmedPathinfo) { + case '/route6': + // route6 + return array('_route' => 'route6'); + break; } if (preg_match('#^(?P[^\\.]++)\\.example\\.com$#sDi', $host, $hostMatches)) { - if (0 === strpos($pathinfo, '/route1')) { - // route11 - if ('/route11' === $pathinfo) { - return $this->mergeDefaults(array_replace($hostMatches, array('_route' => 'route11')), array ()); - } - - // route12 - if ('/route12' === $pathinfo) { - return $this->mergeDefaults(array_replace($hostMatches, array('_route' => 'route12')), array ( 'var1' => 'val',)); - } - - // route13 - if (0 === strpos($pathinfo, '/route13') && preg_match('#^/route13/(?P[^/]++)$#sD', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($hostMatches, $matches, array('_route' => 'route13')), array ()); - } + switch ($trimmedPathinfo) { + case '/route11': + // route11 + return $this->mergeDefaults(array_replace($hostMatches, array('_route' => 'route11')), array()); + break; + case '/route12': + // route12 + return $this->mergeDefaults(array_replace($hostMatches, array('_route' => 'route12')), array('var1' => 'val')); + break; + } - // route14 - if (0 === strpos($pathinfo, '/route14') && preg_match('#^/route14/(?P[^/]++)$#sD', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($hostMatches, $matches, array('_route' => 'route14')), array ( 'var1' => 'val',)); - } + // route13 + if (0 === strpos($pathinfo, '/route13') && preg_match('#^/route13/(?P[^/]++)$#sD', $pathinfo, $matches)) { + return $this->mergeDefaults(array_replace($hostMatches, $matches, array('_route' => 'route13')), array()); + } + // route14 + if (0 === strpos($pathinfo, '/route14') && preg_match('#^/route14/(?P[^/]++)$#sD', $pathinfo, $matches)) { + return $this->mergeDefaults(array_replace($hostMatches, $matches, array('_route' => 'route14')), array('var1' => 'val')); } } @@ -302,59 +292,58 @@ public function match($rawPathinfo) if (preg_match('#^c\\.example\\.com$#sDi', $host, $hostMatches)) { // route15 if (0 === strpos($pathinfo, '/route15') && preg_match('#^/route15/(?P[^/]++)$#sD', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'route15')), array ()); + return $this->mergeDefaults(array_replace($matches, array('_route' => 'route15')), array()); } } - // route16 - if (0 === strpos($pathinfo, '/route16') && preg_match('#^/route16/(?P[^/]++)$#sD', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'route16')), array ( 'var1' => 'val',)); - } + switch ($trimmedPathinfo) { + case '/route17': + // route17 + return array('_route' => 'route17'); + break; + case '/a/a...': + // a + return array('_route' => 'a'); + break; + case '/secure': + // secure + $ret = array('_route' => 'secure'); + $requiredSchemes = array('https' => 0); + if (!isset($requiredSchemes[$context->getScheme()])) { + return array_replace($ret, $this->redirect($rawPathinfo, 'secure', key($requiredSchemes))); + } - // route17 - if ('/route17' === $pathinfo) { - return array('_route' => 'route17'); + return $ret; + break; + case '/nonsecure': + // nonsecure + $ret = array('_route' => 'nonsecure'); + $requiredSchemes = array('http' => 0); + if (!isset($requiredSchemes[$context->getScheme()])) { + return array_replace($ret, $this->redirect($rawPathinfo, 'nonsecure', key($requiredSchemes))); + } + + return $ret; + break; } - // a - if ('/a/a...' === $pathinfo) { - return array('_route' => 'a'); + // route16 + if (0 === strpos($pathinfo, '/route16') && preg_match('#^/route16/(?P[^/]++)$#sD', $pathinfo, $matches)) { + return $this->mergeDefaults(array_replace($matches, array('_route' => 'route16')), array('var1' => 'val')); } if (0 === strpos($pathinfo, '/a/b')) { // b if (preg_match('#^/a/b/(?P[^/]++)$#sD', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'b')), array ()); + return $this->mergeDefaults(array_replace($matches, array('_route' => 'b')), array()); } // c if (0 === strpos($pathinfo, '/a/b/c') && preg_match('#^/a/b/c/(?P[^/]++)$#sD', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'c')), array ()); - } - - } - - // secure - if ('/secure' === $pathinfo) { - $ret = array('_route' => 'secure'); - $requiredSchemes = array ( 'https' => 0,); - if (!isset($requiredSchemes[$context->getScheme()])) { - return array_replace($ret, $this->redirect($rawPathinfo, 'secure', key($requiredSchemes))); - } - - return $ret; - } - - // nonsecure - if ('/nonsecure' === $pathinfo) { - $ret = array('_route' => 'nonsecure'); - $requiredSchemes = array ( 'http' => 0,); - if (!isset($requiredSchemes[$context->getScheme()])) { - return array_replace($ret, $this->redirect($rawPathinfo, 'nonsecure', key($requiredSchemes))); + return $this->mergeDefaults(array_replace($matches, array('_route' => 'c')), array()); } - return $ret; } throw 0 < count($allow) ? new MethodNotAllowedException(array_unique($allow)) : new ResourceNotFoundException(); diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher3.php b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher3.php index cfa6d131a057a..8ddff39a460e4 100644 --- a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher3.php +++ b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher3.php @@ -28,22 +28,22 @@ public function match($rawPathinfo) $canonicalMethod = 'GET'; } - if (0 === strpos($pathinfo, '/rootprefix')) { - // static - if ('/rootprefix/test' === $pathinfo) { + switch ($pathinfo) { + case '/rootprefix/test': + // static return array('_route' => 'static'); - } - - // dynamic - if (preg_match('#^/rootprefix/(?P[^/]++)$#sD', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'dynamic')), array ()); - } - + break; + case '/with-condition': + // with-condition + if (($context->getMethod() == "GET")) { + return array('_route' => 'with-condition'); + } + break; } - // with-condition - if ('/with-condition' === $pathinfo && ($context->getMethod() == "GET")) { - return array('_route' => 'with-condition'); + // dynamic + if (0 === strpos($pathinfo, '/rootprefix') && preg_match('#^/rootprefix/(?P[^/]++)$#sD', $pathinfo, $matches)) { + return $this->mergeDefaults(array_replace($matches, array('_route' => 'dynamic')), array()); } throw 0 < count($allow) ? new MethodNotAllowedException(array_unique($allow)) : new ResourceNotFoundException(); diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher4.php b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher4.php index 89f2b10e22783..8c10d9ac6fa40 100644 --- a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher4.php +++ b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher4.php @@ -28,73 +28,65 @@ public function match($rawPathinfo) $canonicalMethod = 'GET'; } - // just_head - if ('/just_head' === $pathinfo) { - if ('HEAD' !== $requestMethod) { - $allow[] = 'HEAD'; - goto not_just_head; - } - - return array('_route' => 'just_head'); - } - not_just_head: - - // head_and_get - if ('/head_and_get' === $pathinfo) { - if ('GET' !== $canonicalMethod) { - $allow[] = 'GET'; - goto not_head_and_get; - } - - return array('_route' => 'head_and_get'); - } - not_head_and_get: - - // get_and_head - if ('/get_and_head' === $pathinfo) { - if ('GET' !== $canonicalMethod) { - $allow[] = 'GET'; - goto not_get_and_head; - } + switch ($pathinfo) { + case '/just_head': + // just_head + if ('HEAD' !== $requestMethod) { + $allow[] = 'HEAD'; + goto not_just_head; + } - return array('_route' => 'get_and_head'); - } - not_get_and_head: + return array('_route' => 'just_head'); + not_just_head: + break; + case '/head_and_get': + // head_and_get + if ('GET' !== $canonicalMethod) { + $allow[] = 'GET'; + goto not_head_and_get; + } - // post_and_head - if ('/post_and_get' === $pathinfo) { - if (!in_array($requestMethod, array('POST', 'HEAD'))) { - $allow = array_merge($allow, array('POST', 'HEAD')); - goto not_post_and_head; - } + return array('_route' => 'head_and_get'); + not_head_and_get: + break; + case '/get_and_head': + // get_and_head + if ('GET' !== $canonicalMethod) { + $allow[] = 'GET'; + goto not_get_and_head; + } - return array('_route' => 'post_and_head'); - } - not_post_and_head: + return array('_route' => 'get_and_head'); + not_get_and_head: + break; + case '/post_and_get': + // post_and_head + if (!in_array($requestMethod, array('POST', 'HEAD'))) { + $allow = array_merge($allow, array('POST', 'HEAD')); + goto not_post_and_head; + } - if (0 === strpos($pathinfo, '/put_and_post')) { - // put_and_post - if ('/put_and_post' === $pathinfo) { + return array('_route' => 'post_and_head'); + not_post_and_head: + break; + case '/put_and_post': + // put_and_post if (!in_array($requestMethod, array('PUT', 'POST'))) { $allow = array_merge($allow, array('PUT', 'POST')); goto not_put_and_post; } return array('_route' => 'put_and_post'); - } - not_put_and_post: - - // put_and_get_and_head - if ('/put_and_post' === $pathinfo) { + not_put_and_post: + // put_and_get_and_head if (!in_array($canonicalMethod, array('PUT', 'GET'))) { $allow = array_merge($allow, array('PUT', 'GET')); goto not_put_and_get_and_head; } return array('_route' => 'put_and_get_and_head'); - } - not_put_and_get_and_head: - + not_put_and_get_and_head: + break; } throw 0 < count($allow) ? new MethodNotAllowedException(array_unique($allow)) : new ResourceNotFoundException(); diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher5.php b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher5.php index ab4d6da7bdaff..57dbdf42b418c 100644 --- a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher5.php +++ b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher5.php @@ -28,34 +28,23 @@ public function match($rawPathinfo) $canonicalMethod = 'GET'; } - if (0 === strpos($pathinfo, '/a')) { - // a_first - if ('/a/11' === $pathinfo) { + switch ($trimmedPathinfo) { + case '/a/11': + // a_first return array('_route' => 'a_first'); - } - - // a_second - if ('/a/22' === $pathinfo) { + break; + case '/a/22': + // a_second return array('_route' => 'a_second'); - } - - // a_third - if ('/a/333' === $pathinfo) { + break; + case '/a/333': + // a_third return array('_route' => 'a_third'); - } - - } - - // a_wildcard - if (preg_match('#^/(?P[^/]++)$#sD', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'a_wildcard')), array ()); - } - - if (0 === strpos($pathinfo, '/a')) { - // a_fourth - if ('/a/44' === $trimmedPathinfo) { + break; + case '/a/44': + // a_fourth $ret = array('_route' => 'a_fourth'); - if ('/' === substr($pathinfo, -1)) { + if ('/' === $pathinfo[-1]) { // no-op } elseif ('GET' !== $canonicalMethod) { goto not_a_fourth; @@ -64,13 +53,12 @@ public function match($rawPathinfo) } return $ret; - } - not_a_fourth: - - // a_fifth - if ('/a/55' === $trimmedPathinfo) { + not_a_fourth: + break; + case '/a/55': + // a_fifth $ret = array('_route' => 'a_fifth'); - if ('/' === substr($pathinfo, -1)) { + if ('/' === $pathinfo[-1]) { // no-op } elseif ('GET' !== $canonicalMethod) { goto not_a_fifth; @@ -79,13 +67,12 @@ public function match($rawPathinfo) } return $ret; - } - not_a_fifth: - - // a_sixth - if ('/a/66' === $trimmedPathinfo) { + not_a_fifth: + break; + case '/a/66': + // a_sixth $ret = array('_route' => 'a_sixth'); - if ('/' === substr($pathinfo, -1)) { + if ('/' === $pathinfo[-1]) { // no-op } elseif ('GET' !== $canonicalMethod) { goto not_a_sixth; @@ -94,21 +81,12 @@ public function match($rawPathinfo) } return $ret; - } - not_a_sixth: - - } - - // nested_wildcard - if (0 === strpos($pathinfo, '/nested') && preg_match('#^/nested/(?P[^/]++)$#sD', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'nested_wildcard')), array ()); - } - - if (0 === strpos($pathinfo, '/nested/group')) { - // nested_a - if ('/nested/group/a' === $trimmedPathinfo) { + not_a_sixth: + break; + case '/nested/group/a': + // nested_a $ret = array('_route' => 'nested_a'); - if ('/' === substr($pathinfo, -1)) { + if ('/' === $pathinfo[-1]) { // no-op } elseif ('GET' !== $canonicalMethod) { goto not_nested_a; @@ -117,13 +95,12 @@ public function match($rawPathinfo) } return $ret; - } - not_nested_a: - - // nested_b - if ('/nested/group/b' === $trimmedPathinfo) { + not_nested_a: + break; + case '/nested/group/b': + // nested_b $ret = array('_route' => 'nested_b'); - if ('/' === substr($pathinfo, -1)) { + if ('/' === $pathinfo[-1]) { // no-op } elseif ('GET' !== $canonicalMethod) { goto not_nested_b; @@ -132,13 +109,12 @@ public function match($rawPathinfo) } return $ret; - } - not_nested_b: - - // nested_c - if ('/nested/group/c' === $trimmedPathinfo) { + not_nested_b: + break; + case '/nested/group/c': + // nested_c $ret = array('_route' => 'nested_c'); - if ('/' === substr($pathinfo, -1)) { + if ('/' === $pathinfo[-1]) { // no-op } elseif ('GET' !== $canonicalMethod) { goto not_nested_c; @@ -147,16 +123,12 @@ public function match($rawPathinfo) } return $ret; - } - not_nested_c: - - } - - elseif (0 === strpos($pathinfo, '/slashed/group')) { - // slashed_a - if ('/slashed/group' === $trimmedPathinfo) { + not_nested_c: + break; + case '/slashed/group': + // slashed_a $ret = array('_route' => 'slashed_a'); - if ('/' === substr($pathinfo, -1)) { + if ('/' === $pathinfo[-1]) { // no-op } elseif ('GET' !== $canonicalMethod) { goto not_slashed_a; @@ -165,13 +137,12 @@ public function match($rawPathinfo) } return $ret; - } - not_slashed_a: - - // slashed_b - if ('/slashed/group/b' === $trimmedPathinfo) { + not_slashed_a: + break; + case '/slashed/group/b': + // slashed_b $ret = array('_route' => 'slashed_b'); - if ('/' === substr($pathinfo, -1)) { + if ('/' === $pathinfo[-1]) { // no-op } elseif ('GET' !== $canonicalMethod) { goto not_slashed_b; @@ -180,13 +151,12 @@ public function match($rawPathinfo) } return $ret; - } - not_slashed_b: - - // slashed_c - if ('/slashed/group/c' === $trimmedPathinfo) { + not_slashed_b: + break; + case '/slashed/group/c': + // slashed_c $ret = array('_route' => 'slashed_c'); - if ('/' === substr($pathinfo, -1)) { + if ('/' === $pathinfo[-1]) { // no-op } elseif ('GET' !== $canonicalMethod) { goto not_slashed_c; @@ -195,9 +165,18 @@ public function match($rawPathinfo) } return $ret; - } - not_slashed_c: + not_slashed_c: + break; + } + + // a_wildcard + if (preg_match('#^/(?P[^/]++)$#sD', $pathinfo, $matches)) { + return $this->mergeDefaults(array_replace($matches, array('_route' => 'a_wildcard')), array()); + } + // nested_wildcard + if (0 === strpos($pathinfo, '/nested') && preg_match('#^/nested/(?P[^/]++)$#sD', $pathinfo, $matches)) { + return $this->mergeDefaults(array_replace($matches, array('_route' => 'nested_wildcard')), array()); } throw 0 < count($allow) ? new MethodNotAllowedException(array_unique($allow)) : new ResourceNotFoundException(); diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher6.php b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher6.php index 90ea628a146b5..b7c8bbb981287 100644 --- a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher6.php +++ b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher6.php @@ -28,51 +28,81 @@ public function match($rawPathinfo) $canonicalMethod = 'GET'; } - if (0 === strpos($pathinfo, '/trailing/simple')) { - // simple_trailing_slash_no_methods - if ('/trailing/simple/no-methods/' === $pathinfo) { + switch ($pathinfo) { + case '/trailing/simple/no-methods/': + // simple_trailing_slash_no_methods return array('_route' => 'simple_trailing_slash_no_methods'); - } - - // simple_trailing_slash_GET_method - if ('/trailing/simple/get-method/' === $pathinfo) { + break; + case '/trailing/simple/get-method/': + // simple_trailing_slash_GET_method if ('GET' !== $canonicalMethod) { $allow[] = 'GET'; goto not_simple_trailing_slash_GET_method; } return array('_route' => 'simple_trailing_slash_GET_method'); - } - not_simple_trailing_slash_GET_method: - - // simple_trailing_slash_HEAD_method - if ('/trailing/simple/head-method/' === $pathinfo) { + not_simple_trailing_slash_GET_method: + break; + case '/trailing/simple/head-method/': + // simple_trailing_slash_HEAD_method if ('HEAD' !== $requestMethod) { $allow[] = 'HEAD'; goto not_simple_trailing_slash_HEAD_method; } return array('_route' => 'simple_trailing_slash_HEAD_method'); - } - not_simple_trailing_slash_HEAD_method: - - // simple_trailing_slash_POST_method - if ('/trailing/simple/post-method/' === $pathinfo) { + not_simple_trailing_slash_HEAD_method: + break; + case '/trailing/simple/post-method/': + // simple_trailing_slash_POST_method if ('POST' !== $canonicalMethod) { $allow[] = 'POST'; goto not_simple_trailing_slash_POST_method; } return array('_route' => 'simple_trailing_slash_POST_method'); - } - not_simple_trailing_slash_POST_method: + not_simple_trailing_slash_POST_method: + break; + case '/not-trailing/simple/no-methods': + // simple_not_trailing_slash_no_methods + return array('_route' => 'simple_not_trailing_slash_no_methods'); + break; + case '/not-trailing/simple/get-method': + // simple_not_trailing_slash_GET_method + if ('GET' !== $canonicalMethod) { + $allow[] = 'GET'; + goto not_simple_not_trailing_slash_GET_method; + } + return array('_route' => 'simple_not_trailing_slash_GET_method'); + not_simple_not_trailing_slash_GET_method: + break; + case '/not-trailing/simple/head-method': + // simple_not_trailing_slash_HEAD_method + if ('HEAD' !== $requestMethod) { + $allow[] = 'HEAD'; + goto not_simple_not_trailing_slash_HEAD_method; + } + + return array('_route' => 'simple_not_trailing_slash_HEAD_method'); + not_simple_not_trailing_slash_HEAD_method: + break; + case '/not-trailing/simple/post-method': + // simple_not_trailing_slash_POST_method + if ('POST' !== $canonicalMethod) { + $allow[] = 'POST'; + goto not_simple_not_trailing_slash_POST_method; + } + + return array('_route' => 'simple_not_trailing_slash_POST_method'); + not_simple_not_trailing_slash_POST_method: + break; } - elseif (0 === strpos($pathinfo, '/trailing/regex')) { + if (0 === strpos($pathinfo, '/trailing/regex')) { // regex_trailing_slash_no_methods if (0 === strpos($pathinfo, '/trailing/regex/no-methods') && preg_match('#^/trailing/regex/no\\-methods/(?P[^/]++)/$#sD', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_trailing_slash_no_methods')), array ()); + return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_trailing_slash_no_methods')), array()); } // regex_trailing_slash_GET_method @@ -82,7 +112,7 @@ public function match($rawPathinfo) goto not_regex_trailing_slash_GET_method; } - return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_trailing_slash_GET_method')), array ()); + return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_trailing_slash_GET_method')), array()); } not_regex_trailing_slash_GET_method: @@ -93,7 +123,7 @@ public function match($rawPathinfo) goto not_regex_trailing_slash_HEAD_method; } - return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_trailing_slash_HEAD_method')), array ()); + return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_trailing_slash_HEAD_method')), array()); } not_regex_trailing_slash_HEAD_method: @@ -104,57 +134,16 @@ public function match($rawPathinfo) goto not_regex_trailing_slash_POST_method; } - return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_trailing_slash_POST_method')), array ()); + return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_trailing_slash_POST_method')), array()); } not_regex_trailing_slash_POST_method: } - elseif (0 === strpos($pathinfo, '/not-trailing/simple')) { - // simple_not_trailing_slash_no_methods - if ('/not-trailing/simple/no-methods' === $pathinfo) { - return array('_route' => 'simple_not_trailing_slash_no_methods'); - } - - // simple_not_trailing_slash_GET_method - if ('/not-trailing/simple/get-method' === $pathinfo) { - if ('GET' !== $canonicalMethod) { - $allow[] = 'GET'; - goto not_simple_not_trailing_slash_GET_method; - } - - return array('_route' => 'simple_not_trailing_slash_GET_method'); - } - not_simple_not_trailing_slash_GET_method: - - // simple_not_trailing_slash_HEAD_method - if ('/not-trailing/simple/head-method' === $pathinfo) { - if ('HEAD' !== $requestMethod) { - $allow[] = 'HEAD'; - goto not_simple_not_trailing_slash_HEAD_method; - } - - return array('_route' => 'simple_not_trailing_slash_HEAD_method'); - } - not_simple_not_trailing_slash_HEAD_method: - - // simple_not_trailing_slash_POST_method - if ('/not-trailing/simple/post-method' === $pathinfo) { - if ('POST' !== $canonicalMethod) { - $allow[] = 'POST'; - goto not_simple_not_trailing_slash_POST_method; - } - - return array('_route' => 'simple_not_trailing_slash_POST_method'); - } - not_simple_not_trailing_slash_POST_method: - - } - elseif (0 === strpos($pathinfo, '/not-trailing/regex')) { // regex_not_trailing_slash_no_methods if (0 === strpos($pathinfo, '/not-trailing/regex/no-methods') && preg_match('#^/not\\-trailing/regex/no\\-methods/(?P[^/]++)$#sD', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_not_trailing_slash_no_methods')), array ()); + return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_not_trailing_slash_no_methods')), array()); } // regex_not_trailing_slash_GET_method @@ -164,7 +153,7 @@ public function match($rawPathinfo) goto not_regex_not_trailing_slash_GET_method; } - return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_not_trailing_slash_GET_method')), array ()); + return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_not_trailing_slash_GET_method')), array()); } not_regex_not_trailing_slash_GET_method: @@ -175,7 +164,7 @@ public function match($rawPathinfo) goto not_regex_not_trailing_slash_HEAD_method; } - return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_not_trailing_slash_HEAD_method')), array ()); + return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_not_trailing_slash_HEAD_method')), array()); } not_regex_not_trailing_slash_HEAD_method: @@ -186,7 +175,7 @@ public function match($rawPathinfo) goto not_regex_not_trailing_slash_POST_method; } - return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_not_trailing_slash_POST_method')), array ()); + return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_not_trailing_slash_POST_method')), array()); } not_regex_not_trailing_slash_POST_method: diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher7.php b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher7.php index de486eea9b843..41c6c84dd5690 100644 --- a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher7.php +++ b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher7.php @@ -28,11 +28,11 @@ public function match($rawPathinfo) $canonicalMethod = 'GET'; } - if (0 === strpos($pathinfo, '/trailing/simple')) { - // simple_trailing_slash_no_methods - if ('/trailing/simple/no-methods' === $trimmedPathinfo) { + switch ($trimmedPathinfo) { + case '/trailing/simple/no-methods': + // simple_trailing_slash_no_methods $ret = array('_route' => 'simple_trailing_slash_no_methods'); - if ('/' === substr($pathinfo, -1)) { + if ('/' === $pathinfo[-1]) { // no-op } elseif ('GET' !== $canonicalMethod) { goto not_simple_trailing_slash_no_methods; @@ -41,18 +41,17 @@ public function match($rawPathinfo) } return $ret; - } - not_simple_trailing_slash_no_methods: - - // simple_trailing_slash_GET_method - if ('/trailing/simple/get-method' === $trimmedPathinfo) { + not_simple_trailing_slash_no_methods: + break; + case '/trailing/simple/get-method': + // simple_trailing_slash_GET_method if ('GET' !== $canonicalMethod) { $allow[] = 'GET'; goto not_simple_trailing_slash_GET_method; } $ret = array('_route' => 'simple_trailing_slash_GET_method'); - if ('/' === substr($pathinfo, -1)) { + if ('/' === $pathinfo[-1]) { // no-op } elseif ('GET' !== $canonicalMethod) { goto not_simple_trailing_slash_GET_method; @@ -61,18 +60,17 @@ public function match($rawPathinfo) } return $ret; - } - not_simple_trailing_slash_GET_method: - - // simple_trailing_slash_HEAD_method - if ('/trailing/simple/head-method' === $trimmedPathinfo) { + not_simple_trailing_slash_GET_method: + break; + case '/trailing/simple/head-method': + // simple_trailing_slash_HEAD_method if ('HEAD' !== $requestMethod) { $allow[] = 'HEAD'; goto not_simple_trailing_slash_HEAD_method; } $ret = array('_route' => 'simple_trailing_slash_HEAD_method'); - if ('/' === substr($pathinfo, -1)) { + if ('/' === $pathinfo[-1]) { // no-op } elseif ('GET' !== $canonicalMethod) { goto not_simple_trailing_slash_HEAD_method; @@ -81,27 +79,61 @@ public function match($rawPathinfo) } return $ret; - } - not_simple_trailing_slash_HEAD_method: + not_simple_trailing_slash_HEAD_method: + break; + case '/trailing/simple/post-method': + // simple_trailing_slash_POST_method + if ('/trailing/simple/post-method/' === $pathinfo) { + if ('POST' !== $canonicalMethod) { + $allow[] = 'POST'; + goto not_simple_trailing_slash_POST_method; + } + + return array('_route' => 'simple_trailing_slash_POST_method'); + } + not_simple_trailing_slash_POST_method: + break; + case '/not-trailing/simple/no-methods': + // simple_not_trailing_slash_no_methods + return array('_route' => 'simple_not_trailing_slash_no_methods'); + break; + case '/not-trailing/simple/get-method': + // simple_not_trailing_slash_GET_method + if ('GET' !== $canonicalMethod) { + $allow[] = 'GET'; + goto not_simple_not_trailing_slash_GET_method; + } - // simple_trailing_slash_POST_method - if ('/trailing/simple/post-method/' === $pathinfo) { + return array('_route' => 'simple_not_trailing_slash_GET_method'); + not_simple_not_trailing_slash_GET_method: + break; + case '/not-trailing/simple/head-method': + // simple_not_trailing_slash_HEAD_method + if ('HEAD' !== $requestMethod) { + $allow[] = 'HEAD'; + goto not_simple_not_trailing_slash_HEAD_method; + } + + return array('_route' => 'simple_not_trailing_slash_HEAD_method'); + not_simple_not_trailing_slash_HEAD_method: + break; + case '/not-trailing/simple/post-method': + // simple_not_trailing_slash_POST_method if ('POST' !== $canonicalMethod) { $allow[] = 'POST'; - goto not_simple_trailing_slash_POST_method; + goto not_simple_not_trailing_slash_POST_method; } - return array('_route' => 'simple_trailing_slash_POST_method'); - } - not_simple_trailing_slash_POST_method: - + return array('_route' => 'simple_not_trailing_slash_POST_method'); + not_simple_not_trailing_slash_POST_method: + break; } - elseif (0 === strpos($pathinfo, '/trailing/regex')) { + if (0 === strpos($pathinfo, '/trailing/regex')) { // regex_trailing_slash_no_methods if (0 === strpos($pathinfo, '/trailing/regex/no-methods') && preg_match('#^/trailing/regex/no\\-methods/(?P[^/]++)/?$#sD', $pathinfo, $matches)) { - $ret = $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_trailing_slash_no_methods')), array ()); - if ('/' === substr($pathinfo, -1)) { + $ret = $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_trailing_slash_no_methods')), array()); + if ('/' === $pathinfo[-1]) { // no-op } elseif ('GET' !== $canonicalMethod) { goto not_regex_trailing_slash_no_methods; @@ -120,8 +152,8 @@ public function match($rawPathinfo) goto not_regex_trailing_slash_GET_method; } - $ret = $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_trailing_slash_GET_method')), array ()); - if ('/' === substr($pathinfo, -1)) { + $ret = $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_trailing_slash_GET_method')), array()); + if ('/' === $pathinfo[-1]) { // no-op } elseif ('GET' !== $canonicalMethod) { goto not_regex_trailing_slash_GET_method; @@ -140,8 +172,8 @@ public function match($rawPathinfo) goto not_regex_trailing_slash_HEAD_method; } - $ret = $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_trailing_slash_HEAD_method')), array ()); - if ('/' === substr($pathinfo, -1)) { + $ret = $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_trailing_slash_HEAD_method')), array()); + if ('/' === $pathinfo[-1]) { // no-op } elseif ('GET' !== $canonicalMethod) { goto not_regex_trailing_slash_HEAD_method; @@ -160,57 +192,16 @@ public function match($rawPathinfo) goto not_regex_trailing_slash_POST_method; } - return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_trailing_slash_POST_method')), array ()); + return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_trailing_slash_POST_method')), array()); } not_regex_trailing_slash_POST_method: } - elseif (0 === strpos($pathinfo, '/not-trailing/simple')) { - // simple_not_trailing_slash_no_methods - if ('/not-trailing/simple/no-methods' === $pathinfo) { - return array('_route' => 'simple_not_trailing_slash_no_methods'); - } - - // simple_not_trailing_slash_GET_method - if ('/not-trailing/simple/get-method' === $pathinfo) { - if ('GET' !== $canonicalMethod) { - $allow[] = 'GET'; - goto not_simple_not_trailing_slash_GET_method; - } - - return array('_route' => 'simple_not_trailing_slash_GET_method'); - } - not_simple_not_trailing_slash_GET_method: - - // simple_not_trailing_slash_HEAD_method - if ('/not-trailing/simple/head-method' === $pathinfo) { - if ('HEAD' !== $requestMethod) { - $allow[] = 'HEAD'; - goto not_simple_not_trailing_slash_HEAD_method; - } - - return array('_route' => 'simple_not_trailing_slash_HEAD_method'); - } - not_simple_not_trailing_slash_HEAD_method: - - // simple_not_trailing_slash_POST_method - if ('/not-trailing/simple/post-method' === $pathinfo) { - if ('POST' !== $canonicalMethod) { - $allow[] = 'POST'; - goto not_simple_not_trailing_slash_POST_method; - } - - return array('_route' => 'simple_not_trailing_slash_POST_method'); - } - not_simple_not_trailing_slash_POST_method: - - } - elseif (0 === strpos($pathinfo, '/not-trailing/regex')) { // regex_not_trailing_slash_no_methods if (0 === strpos($pathinfo, '/not-trailing/regex/no-methods') && preg_match('#^/not\\-trailing/regex/no\\-methods/(?P[^/]++)$#sD', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_not_trailing_slash_no_methods')), array ()); + return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_not_trailing_slash_no_methods')), array()); } // regex_not_trailing_slash_GET_method @@ -220,7 +211,7 @@ public function match($rawPathinfo) goto not_regex_not_trailing_slash_GET_method; } - return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_not_trailing_slash_GET_method')), array ()); + return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_not_trailing_slash_GET_method')), array()); } not_regex_not_trailing_slash_GET_method: @@ -231,7 +222,7 @@ public function match($rawPathinfo) goto not_regex_not_trailing_slash_HEAD_method; } - return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_not_trailing_slash_HEAD_method')), array ()); + return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_not_trailing_slash_HEAD_method')), array()); } not_regex_not_trailing_slash_HEAD_method: @@ -242,7 +233,7 @@ public function match($rawPathinfo) goto not_regex_not_trailing_slash_POST_method; } - return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_not_trailing_slash_POST_method')), array ()); + return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_not_trailing_slash_POST_method')), array()); } not_regex_not_trailing_slash_POST_method: