[Routing] fix trailing slash matching with empty-matching trailing vars
This commit is contained in:
parent
243b257ca7
commit
d6da21ac19
@ -132,7 +132,7 @@ trait PhpMatcherTrait
|
|||||||
|
|
||||||
$hasTrailingVar = $trimmedPathinfo !== $pathinfo && $hasTrailingVar;
|
$hasTrailingVar = $trimmedPathinfo !== $pathinfo && $hasTrailingVar;
|
||||||
|
|
||||||
if ($hasTrailingVar && ($hasTrailingSlash || !($n = $matches[\count($vars)] ?? '') || '/' !== substr($n, -1)) && preg_match($regex, $this->matchHost ? $host.'.'.$trimmedPathinfo : $trimmedPathinfo, $n) && $m === (int) $n['MARK']) {
|
if ($hasTrailingVar && ($hasTrailingSlash || (null === $n = $matches[\count($vars)] ?? null) || '/' !== ($n[-1] ?? '/')) && preg_match($regex, $this->matchHost ? $host.'.'.$trimmedPathinfo : $trimmedPathinfo, $n) && $m === (int) $n['MARK']) {
|
||||||
if ($hasTrailingSlash) {
|
if ($hasTrailingSlash) {
|
||||||
$matches = $n;
|
$matches = $n;
|
||||||
} else {
|
} else {
|
||||||
|
@ -158,7 +158,7 @@ class UrlMatcher implements UrlMatcherInterface, RequestMatcherInterface
|
|||||||
|
|
||||||
$hasTrailingVar = $trimmedPathinfo !== $pathinfo && preg_match('#\{\w+\}/?$#', $route->getPath());
|
$hasTrailingVar = $trimmedPathinfo !== $pathinfo && preg_match('#\{\w+\}/?$#', $route->getPath());
|
||||||
|
|
||||||
if ($hasTrailingVar && ($hasTrailingSlash || !($m = $matches[\count($compiledRoute->getPathVariables())] ?? '') || '/' !== substr($m, -1)) && preg_match($regex, $trimmedPathinfo, $m)) {
|
if ($hasTrailingVar && ($hasTrailingSlash || (null === $m = $matches[\count($compiledRoute->getPathVariables())] ?? null) || '/' !== ($m[-1] ?? '/')) && preg_match($regex, $trimmedPathinfo, $m)) {
|
||||||
if ($hasTrailingSlash) {
|
if ($hasTrailingSlash) {
|
||||||
$matches = $m;
|
$matches = $m;
|
||||||
} else {
|
} else {
|
||||||
|
@ -198,15 +198,15 @@ class RedirectableUrlMatcherTest extends UrlMatcherTest
|
|||||||
$this->assertEquals(['_route' => 'a', 'a' => '123'], $matcher->match('/123/'));
|
$this->assertEquals(['_route' => 'a', 'a' => '123'], $matcher->match('/123/'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testTrailingRequirementWithDefault()
|
public function testTrailingRequirementWithDefault_A()
|
||||||
{
|
{
|
||||||
$coll = new RouteCollection();
|
$coll = new RouteCollection();
|
||||||
$coll->add('a', new Route('/foo/{a}', ['a' => 'bar'], ['a' => '.+']));
|
$coll->add('a', new Route('/fr-fr/{a}', ['a' => 'aaa'], ['a' => '.+']));
|
||||||
|
|
||||||
$matcher = $this->getUrlMatcher($coll);
|
$matcher = $this->getUrlMatcher($coll);
|
||||||
$matcher->expects($this->once())->method('redirect')->with('/foo')->willReturn([]);
|
$matcher->expects($this->once())->method('redirect')->with('/fr-fr')->willReturn([]);
|
||||||
|
|
||||||
$this->assertEquals(['_route' => 'a', 'a' => 'bar'], $matcher->match('/foo/'));
|
$this->assertEquals(['_route' => 'a', 'a' => 'aaa'], $matcher->match('/fr-fr/'));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getUrlMatcher(RouteCollection $routes, RequestContext $context = null)
|
protected function getUrlMatcher(RouteCollection $routes, RequestContext $context = null)
|
||||||
|
@ -757,6 +757,41 @@ class UrlMatcherTest extends TestCase
|
|||||||
$this->assertEquals(['_route' => 'a', 'a' => 'foo/'], $matcher->match('/foo/'));
|
$this->assertEquals(['_route' => 'a', 'a' => 'foo/'], $matcher->match('/foo/'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testTrailingRequirementWithDefault()
|
||||||
|
{
|
||||||
|
$coll = new RouteCollection();
|
||||||
|
$coll->add('a', new Route('/fr-fr/{a}', ['a' => 'aaa'], ['a' => '.+']));
|
||||||
|
$coll->add('b', new Route('/en-en/{b}', ['b' => 'bbb'], ['b' => '.*']));
|
||||||
|
|
||||||
|
$matcher = $this->getUrlMatcher($coll);
|
||||||
|
|
||||||
|
$this->assertEquals(['_route' => 'a', 'a' => 'aaa'], $matcher->match('/fr-fr'));
|
||||||
|
$this->assertEquals(['_route' => 'a', 'a' => 'AAA'], $matcher->match('/fr-fr/AAA'));
|
||||||
|
$this->assertEquals(['_route' => 'b', 'b' => 'bbb'], $matcher->match('/en-en'));
|
||||||
|
$this->assertEquals(['_route' => 'b', 'b' => 'BBB'], $matcher->match('/en-en/BBB'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testTrailingRequirementWithDefault_A()
|
||||||
|
{
|
||||||
|
$coll = new RouteCollection();
|
||||||
|
$coll->add('a', new Route('/fr-fr/{a}', ['a' => 'aaa'], ['a' => '.+']));
|
||||||
|
|
||||||
|
$matcher = $this->getUrlMatcher($coll);
|
||||||
|
|
||||||
|
$this->expectException(ResourceNotFoundException::class);
|
||||||
|
$matcher->match('/fr-fr/');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testTrailingRequirementWithDefault_B()
|
||||||
|
{
|
||||||
|
$coll = new RouteCollection();
|
||||||
|
$coll->add('b', new Route('/en-en/{b}', ['b' => 'bbb'], ['b' => '.*']));
|
||||||
|
|
||||||
|
$matcher = $this->getUrlMatcher($coll);
|
||||||
|
|
||||||
|
$this->assertEquals(['_route' => 'b', 'b' => ''], $matcher->match('/en-en/'));
|
||||||
|
}
|
||||||
|
|
||||||
protected function getUrlMatcher(RouteCollection $routes, RequestContext $context = null)
|
protected function getUrlMatcher(RouteCollection $routes, RequestContext $context = null)
|
||||||
{
|
{
|
||||||
return new UrlMatcher($routes, $context ?: new RequestContext());
|
return new UrlMatcher($routes, $context ?: new RequestContext());
|
||||||
|
Reference in New Issue
Block a user