From fe694de7464ed18d9eb2947d7bc817bddde7965b Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Sat, 5 Feb 2011 19:06:40 +0100 Subject: [PATCH] [Routing] Make trailing slashes in urls optional --- .../Controller/RedirectController.php | 31 +++++++++++++++++++ .../Matcher/Dumper/PhpMatcherDumper.php | 31 +++++++++++++++++-- 2 files changed, 59 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Controller/RedirectController.php b/src/Symfony/Bundle/FrameworkBundle/Controller/RedirectController.php index 0f95d187a1..d4dab53e2f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Controller/RedirectController.php +++ b/src/Symfony/Bundle/FrameworkBundle/Controller/RedirectController.php @@ -54,4 +54,35 @@ class RedirectController extends ContainerAware return $response; } + + /** + * Redirects to a URL. + * + * It expects a url path parameter. + * By default, the response status code is 301. + * + * If the url is empty, the status code will be 410. + * If the permanent path parameter is set, the status code will be 302. + * + * @param string $url The url to redirect to + * @param Boolean $permanent Whether the redirect is permanent or not + * + * @return Response A Response instance + */ + public function urlRedirectAction($url, $permanent = false) + { + if (!$url) { + $response = $this->container->get('response'); + $response->setStatusCode(410); + + return $response; + } + + $code = $permanent ? 301 : 302; + + $response = $this->container->get('response'); + $response->setRedirect($url, $code); + + return $response; + } } diff --git a/src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php b/src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php index f2fa5a9332..902c4dc326 100644 --- a/src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php +++ b/src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php @@ -60,8 +60,14 @@ class PhpMatcherDumper extends MatcherDumper $conditions[] = sprintf("isset(\$this->context['method']) && preg_match('#^(%s)$#xi', \$this->context['method'])", $req); } + $hasTrailingSlash = false; if (!count($compiledRoute->getVariables()) && false !== preg_match('#^(.)\^(?P.*?)\$\1#', $compiledRoute->getRegex(), $m)) { - $conditions[] = sprintf("\$url === '%s'", str_replace('\\', '', $m['url'])); + if (substr($m['url'], -1) === '/' && $m['url'] !== '/') { + $conditions[] = sprintf("rtrim(\$url, '/') === '%s'", rtrim(str_replace('\\', '', $m['url']), '/')); + $hasTrailingSlash = true; + } else { + $conditions[] = sprintf("\$url === '%s'", str_replace('\\', '', $m['url'])); + } $matches = 'array()'; } else { @@ -69,15 +75,34 @@ class PhpMatcherDumper extends MatcherDumper $conditions[] = sprintf("0 === strpos(\$url, '%s')", $compiledRoute->getStaticPrefix()); } - $conditions[] = sprintf("preg_match('%s', \$url, \$matches)", $compiledRoute->getRegex()); + $regex = $compiledRoute->getRegex(); + if ($pos = strpos($regex, '/$')) { + $regex = substr($regex, 0, $pos) . '/?$' . substr($regex, $pos+2); + $conditions[] = sprintf("preg_match('%s', \$url, \$matches)", $regex); + $hasTrailingSlash = true; + } else { + $conditions[] = sprintf("preg_match('%s', \$url, \$matches)", $regex); + } $matches = '$matches'; } $conditions = implode(' && ', $conditions); - $code[] = sprintf(<< 'Symfony\\Bundle\\FrameworkBundle\\Controller\\RedirectController::urlRedirectAction', 'url' => \$this->context['base_url'].\$url.'/', 'permanent' => true, '_route' => '%s'); + } +EOF + , $name); + } + + $code[] = sprintf(<<mergeDefaults($matches, %s), array('_route' => '%s')); }