From 177dfbc17098b089a26d49400ce09049861e5424 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 18 Apr 2019 15:09:11 +0200 Subject: [PATCH] [Routing] fix matching trailing vars with defaults --- .../Routing/Matcher/Dumper/PhpMatcherTrait.php | 2 +- src/Symfony/Component/Routing/Matcher/UrlMatcher.php | 2 +- .../Tests/Matcher/RedirectableUrlMatcherTest.php | 11 +++++++++++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherTrait.php b/src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherTrait.php index b77c530854..95e0d8d3a9 100644 --- a/src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherTrait.php +++ b/src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherTrait.php @@ -132,7 +132,7 @@ trait PhpMatcherTrait $hasTrailingVar = $trimmedPathinfo !== $pathinfo && $hasTrailingVar; - if ($hasTrailingVar && ($hasTrailingSlash || '/' !== substr($matches[\count($vars)], -1)) && preg_match($regex, $this->matchHost ? $host.'.'.$trimmedPathinfo : $trimmedPathinfo, $n) && $m === (int) $n['MARK']) { + if ($hasTrailingVar && ($hasTrailingSlash || !($n = $matches[\count($vars)] ?? '') || '/' !== substr($n, -1)) && preg_match($regex, $this->matchHost ? $host.'.'.$trimmedPathinfo : $trimmedPathinfo, $n) && $m === (int) $n['MARK']) { if ($hasTrailingSlash) { $matches = $n; } else { diff --git a/src/Symfony/Component/Routing/Matcher/UrlMatcher.php b/src/Symfony/Component/Routing/Matcher/UrlMatcher.php index 5b6c0440da..dda9edb7e2 100644 --- a/src/Symfony/Component/Routing/Matcher/UrlMatcher.php +++ b/src/Symfony/Component/Routing/Matcher/UrlMatcher.php @@ -158,7 +158,7 @@ class UrlMatcher implements UrlMatcherInterface, RequestMatcherInterface $hasTrailingVar = $trimmedPathinfo !== $pathinfo && preg_match('#\{\w+\}/?$#', $route->getPath()); - if ($hasTrailingVar && ($hasTrailingSlash || '/' !== substr($matches[(\count($matches) - 1) >> 1], -1)) && preg_match($regex, $trimmedPathinfo, $m)) { + if ($hasTrailingVar && ($hasTrailingSlash || !($m = $matches[\count($compiledRoute->getPathVariables())] ?? '') || '/' !== substr($m, -1)) && preg_match($regex, $trimmedPathinfo, $m)) { if ($hasTrailingSlash) { $matches = $m; } else { diff --git a/src/Symfony/Component/Routing/Tests/Matcher/RedirectableUrlMatcherTest.php b/src/Symfony/Component/Routing/Tests/Matcher/RedirectableUrlMatcherTest.php index 42acb04857..5e8114ea28 100644 --- a/src/Symfony/Component/Routing/Tests/Matcher/RedirectableUrlMatcherTest.php +++ b/src/Symfony/Component/Routing/Tests/Matcher/RedirectableUrlMatcherTest.php @@ -198,6 +198,17 @@ class RedirectableUrlMatcherTest extends UrlMatcherTest $this->assertEquals(['_route' => 'a', 'a' => '123'], $matcher->match('/123/')); } + public function testTrailingRequirementWithDefault() + { + $coll = new RouteCollection(); + $coll->add('a', new Route('/foo/{a}', ['a' => 'bar'], ['a' => '.+'])); + + $matcher = $this->getUrlMatcher($coll); + $matcher->expects($this->once())->method('redirect')->with('/foo')->willReturn([]); + + $this->assertEquals(['_route' => 'a', 'a' => 'bar'], $matcher->match('/foo/')); + } + protected function getUrlMatcher(RouteCollection $routes, RequestContext $context = null) { return $this->getMockForAbstractClass('Symfony\Component\Routing\Matcher\RedirectableUrlMatcher', [$routes, $context ?: new RequestContext()]);