Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 578eb1b

Browse files
nasimnabavinicolas-grekas
authored andcommitted
[Routing] fix URL generation with look-around requirements
1 parent 7f310b4 commit 578eb1b

File tree

4 files changed

+34
-9
lines changed

4 files changed

+34
-9
lines changed

src/Symfony/Component/Routing/Generator/UrlGenerator.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -140,8 +140,8 @@ protected function doGenerate($variables, $defaults, $requirements, $tokens, $pa
140140
foreach ($tokens as $token) {
141141
if ('variable' === $token[0]) {
142142
if (!$optional || !array_key_exists($token[3], $defaults) || null !== $mergedParams[$token[3]] && (string) $mergedParams[$token[3]] !== (string) $defaults[$token[3]]) {
143-
// check requirement
144-
if (null !== $this->strictRequirements && !preg_match('#^'.$token[2].'$#'.(empty($token[4]) ? '' : 'u'), $mergedParams[$token[3]])) {
143+
// check requirement (while ignoring look-around patterns)
144+
if (null !== $this->strictRequirements && !preg_match('#^'.preg_replace('/\(\?(?:=|<=|!|<!)((?:[^()\\\\]+|\\\\.|\((?1)\))*)\)/', '', $token[2]).'$#'.($token[4] ?? ''), $mergedParams[$token[3]])) {
145145
if ($this->strictRequirements) {
146146
throw new InvalidParameterException(strtr($message, array('{parameter}' => $token[3], '{route}' => $name, '{expected}' => $token[2], '{given}' => $mergedParams[$token[3]])));
147147
}
@@ -195,7 +195,8 @@ protected function doGenerate($variables, $defaults, $requirements, $tokens, $pa
195195
$routeHost = '';
196196
foreach ($hostTokens as $token) {
197197
if ('variable' === $token[0]) {
198-
if (null !== $this->strictRequirements && !preg_match('#^'.$token[2].'$#i'.(empty($token[4]) ? '' : 'u'), $mergedParams[$token[3]])) {
198+
// check requirement (while ignoring look-around patterns)
199+
if (null !== $this->strictRequirements && !preg_match('#^'.preg_replace('/\(\?(?:=|<=|!|<!)((?:[^()\\\\]+|\\\\.|\((?1)\))*)\)/', '', $token[2]).'$#i'.($token[4] ?? ''), $mergedParams[$token[3]])) {
199200
if ($this->strictRequirements) {
200201
throw new InvalidParameterException(strtr($message, array('{parameter}' => $token[3], '{route}' => $name, '{expected}' => $token[2], '{given}' => $mergedParams[$token[3]])));
201202
}

src/Symfony/Component/Routing/RouteCompiler.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ private static function compilePattern(Route $route, $pattern, $isHost)
217217
$regexp .= 'u';
218218
for ($i = 0, $nbToken = \count($tokens); $i < $nbToken; ++$i) {
219219
if ('variable' === $tokens[$i][0]) {
220-
$tokens[$i][] = true;
220+
$tokens[$i][] = 'u';
221221
}
222222
}
223223
}

src/Symfony/Component/Routing/Tests/Generator/UrlGeneratorTest.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -703,6 +703,30 @@ public function testFragmentsCanBeDefinedAsDefaults()
703703
$this->assertEquals('/app.php/testing#fragment', $url);
704704
}
705705

706+
public function testLookAheadPositiveInRequirements()
707+
{
708+
$routes = $this->getRoutes('test', new Route('/{foo}/b(ar/{baz}', array(), array('foo' => '.+(?=/b\\(ar/)', 'baz' => '.+?')));
709+
$this->assertSame('/app.php/a/b/b%28ar/c/d/e', $this->getGenerator($routes)->generate('test', array('foo' => 'a/b', 'baz' => 'c/d/e')));
710+
}
711+
712+
public function testLookAheadNegativeInRequirementss()
713+
{
714+
$routes = $this->getRoutes('test', new Route('/{foo}/bar/{baz}', array(), array('foo' => '.+(?!$)', 'baz' => '.+?')));
715+
$this->assertSame('/app.php/a/b/bar/c/d/e', $this->getGenerator($routes)->generate('test', array('foo' => 'a/b', 'baz' => 'c/d/e')));
716+
}
717+
718+
public function testLookBehindPositiveInRequirements()
719+
{
720+
$routes = $this->getRoutes('test', new Route('/bar/{foo}/bam/{baz}', array(), array('foo' => '(?<=/bar/).+', 'baz' => '.+?')));
721+
$this->assertSame('/app.php/bar/a/b/bam/c/d/e', $this->getGenerator($routes)->generate('test', array('foo' => 'a/b', 'baz' => 'c/d/e')));
722+
}
723+
724+
public function testLookBehindNegativeInRequirements()
725+
{
726+
$routes = $this->getRoutes('test', new Route('/bar/{foo}/bam/{baz}', array(), array('foo' => '(?<!^).+', 'baz' => '.+?')));
727+
$this->assertSame('/app.php/bar/a/b/bam/c/d/e', $this->getGenerator($routes)->generate('test', array('foo' => 'a/b', 'baz' => 'c/d/e')));
728+
}
729+
706730
protected function getGenerator(RouteCollection $routes, array $parameters = array(), $logger = null)
707731
{
708732
$context = new RequestContext('/app.php');

src/Symfony/Component/Routing/Tests/RouteCompilerTest.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ public function provideCompileData()
177177
'Route with an explicit UTF-8 requirement',
178178
array('/{bar}', array('bar' => null), array('bar' => '.'), array('utf8' => true)),
179179
'', '#^/(?P<bar>.)?$#sDu', array('bar'), array(
180-
array('variable', '/', '.', 'bar', true),
180+
array('variable', '/', '.', 'bar', 'u'),
181181
),
182182
),
183183
);
@@ -216,7 +216,7 @@ public function provideCompileImplicitUtf8Data()
216216
'Route with an implicit UTF-8 requirement',
217217
array('/{bar}', array('bar' => null), array('bar' => 'é')),
218218
'', '#^/(?P<bar>é)?$#sDu', array('bar'), array(
219-
array('variable', '/', 'é', 'bar', true),
219+
array('variable', '/', 'é', 'bar', 'u'),
220220
),
221221
'requirements',
222222
),
@@ -225,7 +225,7 @@ public function provideCompileImplicitUtf8Data()
225225
'Route with a UTF-8 class requirement',
226226
array('/{bar}', array('bar' => null), array('bar' => '\pM')),
227227
'', '#^/(?P<bar>\pM)?$#sDu', array('bar'), array(
228-
array('variable', '/', '\pM', 'bar', true),
228+
array('variable', '/', '\pM', 'bar', 'u'),
229229
),
230230
'requirements',
231231
),
@@ -234,8 +234,8 @@ public function provideCompileImplicitUtf8Data()
234234
'Route with a UTF-8 separator',
235235
array('/foo/{bar}§{_format}', array(), array(), array('compiler_class' => Utf8RouteCompiler::class)),
236236
'/foo', '#^/foo/(?P<bar>[^/§]++)§(?P<_format>[^/]++)$#sDu', array('bar', '_format'), array(
237-
array('variable', '§', '[^/]++', '_format', true),
238-
array('variable', '/', '[^/§]++', 'bar', true),
237+
array('variable', '§', '[^/]++', '_format', 'u'),
238+
array('variable', '/', '[^/§]++', 'bar', 'u'),
239239
array('text', '/foo'),
240240
),
241241
'patterns',

0 commit comments

Comments
 (0)