Skip to content
Permalink
Browse files

bug #27601 [Routing] fix URL generation with look-around requirements…

… (nasimnabavi)

This PR was merged into the 3.4 branch.

Discussion
----------

[Routing] fix URL generation with look-around requirements

| Q             | A
| ------------- | ---
| Branch?       | 2.8 up to 4.1 for bug fixes
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #10548
| License       | MIT
| Doc PR        |

If you have a non-catchable pattern in requirements like f.e. a positive lookahead (.+(?=/foo/)), the generator will not accept the parameter as the parameter itself cannot fulfil the requirement, but only matches in the context of the entire path.
This fix looks for lookAround in the path and ignores checking the requirements if any lookAround exists.

Commits
-------

c474451 [Routing] fix URL generation with look-around requirements
  • Loading branch information...
fabpot committed Feb 21, 2019
2 parents 4b56617 + c474451 commit 5ac4c2abf552518875a7a10f57322bfae2b93f52
@@ -140,8 +140,8 @@ protected function doGenerate($variables, $defaults, $requirements, $tokens, $pa
foreach ($tokens as $token) {
if ('variable' === $token[0]) {
if (!$optional || !array_key_exists($token[3], $defaults) || null !== $mergedParams[$token[3]] && (string) $mergedParams[$token[3]] !== (string) $defaults[$token[3]]) {
// check requirement
if (null !== $this->strictRequirements && !preg_match('#^'.$token[2].'$#'.(empty($token[4]) ? '' : 'u'), $mergedParams[$token[3]])) {
// check requirement (while ignoring look-around patterns)
if (null !== $this->strictRequirements && !preg_match('#^'.preg_replace('/\(\?(?:=|<=|!|<!)((?:[^()\\\\]+|\\\\.|\((?1)\))*)\)/', '', $token[2]).'$#'.(empty($token[4]) ? '' : 'u'), $mergedParams[$token[3]])) {
if ($this->strictRequirements) {
throw new InvalidParameterException(strtr($message, ['{parameter}' => $token[3], '{route}' => $name, '{expected}' => $token[2], '{given}' => $mergedParams[$token[3]]]));
}
@@ -195,7 +195,8 @@ protected function doGenerate($variables, $defaults, $requirements, $tokens, $pa
$routeHost = '';
foreach ($hostTokens as $token) {
if ('variable' === $token[0]) {
if (null !== $this->strictRequirements && !preg_match('#^'.$token[2].'$#i'.(empty($token[4]) ? '' : 'u'), $mergedParams[$token[3]])) {
// check requirement (while ignoring look-around patterns)
if (null !== $this->strictRequirements && !preg_match('#^'.preg_replace('/\(\?(?:=|<=|!|<!)((?:[^()\\\\]+|\\\\.|\((?1)\))*)\)/', '', $token[2]).'$#i'.(empty($token[4]) ? '' : 'u'), $mergedParams[$token[3]])) {
if ($this->strictRequirements) {
throw new InvalidParameterException(strtr($message, ['{parameter}' => $token[3], '{route}' => $name, '{expected}' => $token[2], '{given}' => $mergedParams[$token[3]]]));
}
@@ -703,6 +703,23 @@ public function testFragmentsCanBeDefinedAsDefaults()
$this->assertEquals('/app.php/testing#fragment', $url);
}
/**
* @dataProvider provideLookAroundRequirementsInPath
*/
public function testLookRoundRequirementsInPath($expected, $path, $requirement)
{
$routes = $this->getRoutes('test', new Route($path, array(), array('foo' => $requirement, 'baz' => '.+?')));
$this->assertSame($expected, $this->getGenerator($routes)->generate('test', array('foo' => 'a/b', 'baz' => 'c/d/e')));
}
public function provideLookAroundRequirementsInPath()
{
yield array('/app.php/a/b/b%28ar/c/d/e', '/{foo}/b(ar/{baz}', '.+(?=/b\\(ar/)');
yield array('/app.php/a/b/bar/c/d/e', '/{foo}/bar/{baz}', '.+(?!$)');
yield array('/app.php/bar/a/b/bam/c/d/e', '/bar/{foo}/bam/{baz}', '(?<=/bar/).+');
yield array('/app.php/bar/a/b/bam/c/d/e', '/bar/{foo}/bam/{baz}', '(?<!^).+');
}
protected function getGenerator(RouteCollection $routes, array $parameters = [], $logger = null)
{
$context = new RequestContext('/app.php');

0 comments on commit 5ac4c2a

Please sign in to comment.
You can’t perform that action at this time.