8000 feature #12979 [Router] added appending of new optional document frag… · symfony/symfony@61e5ddc · GitHub
[go: up one dir, main page]

Skip to content

Commit 61e5ddc

Browse files
committed
feature #12979 [Router] added appending of new optional document fragment (rodnaph)
This PR was merged into the 3.2-dev branch. Discussion ---------- [Router] added appending of new optional document fragment added a new optional parameter to the generate method for the document fragment. when specified this is appended to generated urls. | Q | A | ------------- | --- | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | none | License | MIT | Doc PR | none Commits ------- 6d79a56 [Routing] adds _fragment special option to url generation for document fragment
2 parents 4742962 + 6d79a56 commit 61e5ddc

File tree

5 files changed

+53
-3
lines changed

5 files changed

+53
-3
lines changed

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,13 @@ protected function doGenerate($variables, $defaults, $requirements, $tokens, $pa
257257
$url = $schemeAuthority.$this->context->getBaseUrl().$url;
258258
}
259259

260+
// extract unused parameters
261+
$extra = array_diff_key($parameters, $variables, $defaults);
262+
263+
// extract fragment
264+
$fragment = isset($extra['_fragment']) ? $extra['_fragment'] : '';
265+
unset($extra['_fragment']);
266+
260267
// add a query string if needed
261268
$extra = array_udiff_assoc(array_diff_key($parameters, $variables), $defaults, function ($a, $b) {
262269
return $a == $b ? 0 : 1;
@@ -268,6 +275,10 @@ protected function doGenerate($variables, $defaults, $requirements, $tokens, $pa
268275
$url .= '?'.strtr($query, array('%2F' => '/'));
269276
}
270277

278+
if ('' !== $fragment) {
279+
$url .= '#'.strtr(rawurlencode($fragment), array('%2F' => '/', '%3F' => '?'));
280+
}
281+
271282
return $url;
272283
}
273284

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ interface UrlGeneratorInterface extends RequestContextAwareInterface
6969
*
7070
* If there is no route with the given name, the generator must throw the RouteNotFoundException.
7171
*
72+
* The special parameter _fragment will be used as the document fragment suffixed to the final URL.
73+
*
7274
* @param string $name The name of the route
7375
* @param mixed $parameters An array of parameters
7476
* @param int $referenceType The type of reference to be generated (one of the constants)

src/Symfony/Component/Routing/RouteCompiler.php

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,10 @@ class RouteCompiler implements RouteCompilerInterface
3131
/**
3232
* {@inheritdoc}
3333
*
34-
* @throws \LogicException If a variable is referenced more than once
35-
* @throws \DomainException If a variable name is numeric because PHP raises an error for such
36-
* subpatterns in PCRE and thus would break matching, e.g. "(?P<123>.+)".
34+
* @throws \InvalidArgumentException If a path variable is named _fragment
35+
* @throws \LogicException If a variable is referenced more than once
36+
* @throws \DomainException If a variable name is numeric because PHP raises an error for such
37+
* subpatterns in PCRE and thus would break matching, e.g. "(?P<123>.+)".
3738
*/
3839
public static function compile(Route $route)
3940
{
@@ -59,6 +60,13 @@ public static function compile(Route $route)
5960
$staticPrefix = $result['staticPrefix'];
6061

6162
$pathVariables = $result['variables'];
63+
64+
foreach ($pathVariables as $pathParam) {
65+
if ('_fragment' === $pathParam) {
66+
throw new \InvalidArgumentException(sprintf('Route pattern "%s" cannot contain "_fragment" as a path parameter.', $route->getPath()));
67+
}
68+
}
69+
6270
$variables = array_merge($variables, $pathVariables);
6371

6472
$tokens = $result['tokens'];

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

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -634,6 +634,25 @@ public function provideRelativePaths()
634634
);
635635
}
636636

637+
public function testFragmentsCanBeAppendedToUrls()
638+
{
639+
$routes = $this->getRoutes('test', new Route('/testing'));
640+
641+
$url = $this->getGenerator($routes)->generate('test', array('_fragment' => 'frag ment'), true);
642+
$this->assertEquals('/app.php/testing#frag%20ment', $url);
643+
644+
$url = $this->getGenerator($routes)->generate('test', array('_fragment' => '0'), true);
645+
$this->assertEquals('/app.php/testing#0', $url);
646+
}
647+
648+
public function testFragmentsDoNotEscapeValidCharacters()
649+
{
650+
$routes = $this->getRoutes('test', new Route('/testing'));
651+
$url = $this->getGenerator($routes)->generate('test', array('_fragment' => '?/'), true);
652+
653+
$this->assertEquals('/app.php/testing#?/', $url);
654+
}
655+
637656
protected function getGenerator(RouteCollection $routes, array $parameters = array(), $logger = null)
638657
{
639658
$context = new RequestContext('/app.php');

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,16 @@ public function testRouteWithSameVariableTwice()
175175
$compiled = $route->compile();
176176
}
177177

178+
/**
179+
* @expectedException \InvalidArgumentException
180+
*/
181+
public function testRouteWithFragmentAsPathParameter()
182+
{
183+
$route = new Route('/{_fragment}');
184+
185+
$compiled = $route->compile();
186+
}
187+
178188
/**
179189
* @dataProvider getNumericVariableNames
180190
* @expectedException \DomainException

0 commit comments

Comments
 (0)
0