bug #37271 [FrameworkBundle] preserve dots in query-string when redirecting (nicolas-grekas)
This PR was merged into the 4.4 branch.
Discussion
----------
[FrameworkBundle] preserve dots in query-string when redirecting
| Q | A
| ------------- | ---
| Branch? | 4.4
| Bug fix? | yes
| New feature? | no
| Deprecations? | no
| Tickets | Fix #29664
| License | MIT
| Doc PR | -
Requires #37270 to pass.
Commits
-------
3d0d59de20
[FrameworkBundle] preserve dots in query-string when redirecting
This commit is contained in:
commit
8ec9770b68
@ -62,7 +62,17 @@ class RedirectController
|
|||||||
$attributes = [];
|
$attributes = [];
|
||||||
if (false === $ignoreAttributes || \is_array($ignoreAttributes)) {
|
if (false === $ignoreAttributes || \is_array($ignoreAttributes)) {
|
||||||
$attributes = $request->attributes->get('_route_params');
|
$attributes = $request->attributes->get('_route_params');
|
||||||
$attributes = $keepQueryParams ? array_merge($request->query->all(), $attributes) : $attributes;
|
|
||||||
|
if ($keepQueryParams) {
|
||||||
|
if ($query = $request->server->get('QUERY_STRING')) {
|
||||||
|
$query = self::parseQuery($query);
|
||||||
|
} else {
|
||||||
|
$query = $request->query->all();
|
||||||
|
}
|
||||||
|
|
||||||
|
$attributes = array_merge($query, $attributes);
|
||||||
|
}
|
||||||
|
|
||||||
unset($attributes['route'], $attributes['permanent'], $attributes['ignoreAttributes'], $attributes['keepRequestMethod'], $attributes['keepQueryParams']);
|
unset($attributes['route'], $attributes['permanent'], $attributes['ignoreAttributes'], $attributes['keepRequestMethod'], $attributes['keepQueryParams']);
|
||||||
if ($ignoreAttributes) {
|
if ($ignoreAttributes) {
|
||||||
$attributes = array_diff_key($attributes, array_flip($ignoreAttributes));
|
$attributes = array_diff_key($attributes, array_flip($ignoreAttributes));
|
||||||
@ -175,4 +185,49 @@ class RedirectController
|
|||||||
|
|
||||||
throw new \RuntimeException(sprintf('The parameter "path" or "route" is required to configure the redirect action in "%s" routing configuration.', $request->attributes->get('_route')));
|
throw new \RuntimeException(sprintf('The parameter "path" or "route" is required to configure the redirect action in "%s" routing configuration.', $request->attributes->get('_route')));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static function parseQuery(string $query)
|
||||||
|
{
|
||||||
|
$q = [];
|
||||||
|
|
||||||
|
foreach (explode('&', $query) as $v) {
|
||||||
|
if (false !== $i = strpos($v, "\0")) {
|
||||||
|
$v = substr($v, 0, $i);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (false === $i = strpos($v, '=')) {
|
||||||
|
$k = urldecode($v);
|
||||||
|
$v = '';
|
||||||
|
} else {
|
||||||
|
$k = urldecode(substr($v, 0, $i));
|
||||||
|
$v = substr($v, $i);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (false !== $i = strpos($k, "\0")) {
|
||||||
|
$k = substr($k, 0, $i);
|
||||||
|
}
|
||||||
|
|
||||||
|
$k = ltrim($k, ' ');
|
||||||
|
|
||||||
|
if (false === $i = strpos($k, '[')) {
|
||||||
|
$q[] = bin2hex($k).$v;
|
||||||
|
} else {
|
||||||
|
$q[] = substr_replace($k, bin2hex(substr($k, 0, $i)), 0, $i).$v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
parse_str(implode('&', $q), $q);
|
||||||
|
|
||||||
|
$query = [];
|
||||||
|
|
||||||
|
foreach ($q as $k => $v) {
|
||||||
|
if (false !== $i = strpos($k, '_')) {
|
||||||
|
$query[substr_replace($k, hex2bin(substr($k, 0, $i)).'[', 0, 1 + $i)] = $v;
|
||||||
|
} else {
|
||||||
|
$query[hex2bin($k)] = $v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $query;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -302,17 +302,16 @@ class RedirectControllerTest extends TestCase
|
|||||||
$baseUrl = '/base';
|
$baseUrl = '/base';
|
||||||
$port = 80;
|
$port = 80;
|
||||||
|
|
||||||
$request = $this->createRequestObject($scheme, $host, $port, $baseUrl, 'base=zaza');
|
$request = $this->createRequestObject($scheme, $host, $port, $baseUrl, 'b.se=zaza');
|
||||||
$request->query = new ParameterBag(['base' => 'zaza']);
|
|
||||||
$request->attributes = new ParameterBag(['_route_params' => ['base2' => 'zaza']]);
|
$request->attributes = new ParameterBag(['_route_params' => ['base2' => 'zaza']]);
|
||||||
$urlGenerator = $this->getMockBuilder(UrlGeneratorInterface::class)->getMock();
|
$urlGenerator = $this->getMockBuilder(UrlGeneratorInterface::class)->getMock();
|
||||||
$urlGenerator->expects($this->exactly(2))->method('generate')->willReturn('/test?base=zaza&base2=zaza')->with('/test', ['base' => 'zaza', 'base2' => 'zaza'], UrlGeneratorInterface::ABSOLUTE_URL);
|
$urlGenerator->expects($this->exactly(2))->method('generate')->willReturn('/test?b.se=zaza&base2=zaza')->with('/test', ['b.se' => 'zaza', 'base2' => 'zaza'], UrlGeneratorInterface::ABSOLUTE_URL);
|
||||||
|
|
||||||
$controller = new RedirectController($urlGenerator);
|
$controller = new RedirectController($urlGenerator);
|
||||||
$this->assertRedirectUrl($controller->redirectAction($request, '/test', false, false, false, true), '/test?base=zaza&base2=zaza');
|
$this->assertRedirectUrl($controller->redirectAction($request, '/test', false, false, false, true), '/test?b.se=zaza&base2=zaza');
|
||||||
|
|
||||||
$request->attributes->set('_route_params', ['base2' => 'zaza', 'route' => '/test', 'ignoreAttributes' => false, 'keepRequestMethod' => false, 'keepQueryParams' => true]);
|
$request->attributes->set('_route_params', ['base2' => 'zaza', 'route' => '/test', 'ignoreAttributes' => false, 'keepRequestMethod' => false, 'keepQueryParams' => true]);
|
||||||
$this->assertRedirectUrl($controller($request), '/test?base=zaza&base2=zaza');
|
$this->assertRedirectUrl($controller($request), '/test?b.se=zaza&base2=zaza');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testRedirectWithQueryWithRouteParamsOveriding()
|
public function testRedirectWithQueryWithRouteParamsOveriding()
|
||||||
@ -322,17 +321,16 @@ class RedirectControllerTest extends TestCase
|
|||||||
$baseUrl = '/base';
|
$baseUrl = '/base';
|
||||||
$port = 80;
|
$port = 80;
|
||||||
|
|
||||||
$request = $this->createRequestObject($scheme, $host, $port, $baseUrl, 'base=zaza');
|
$request = $this->createRequestObject($scheme, $host, $port, $baseUrl, 'b.se=zaza');
|
||||||
$request->query = new ParameterBag(['base' => 'zaza']);
|
$request->attributes = new ParameterBag(['_route_params' => ['b.se' => 'zouzou']]);
|
||||||
$request->attributes = new ParameterBag(['_route_params' => ['base' => 'zouzou']]);
|
|
||||||
$urlGenerator = $this->getMockBuilder(UrlGeneratorInterface::class)->getMock();
|
$urlGenerator = $this->getMockBuilder(UrlGeneratorInterface::class)->getMock();
|
||||||
$urlGenerator->expects($this->exactly(2))->method('generate')->willReturn('/test?base=zouzou')->with('/test', ['base' => 'zouzou'], UrlGeneratorInterface::ABSOLUTE_URL);
|
$urlGenerator->expects($this->exactly(2))->method('generate')->willReturn('/test?b.se=zouzou')->with('/test', ['b.se' => 'zouzou'], UrlGeneratorInterface::ABSOLUTE_URL);
|
||||||
|
|
||||||
$controller = new RedirectController($urlGenerator);
|
$controller = new RedirectController($urlGenerator);
|
||||||
$this->assertRedirectUrl($controller->redirectAction($request, '/test', false, false, false, true), '/test?base=zouzou');
|
$this->assertRedirectUrl($controller->redirectAction($request, '/test', false, false, false, true), '/test?b.se=zouzou');
|
||||||
|
|
||||||
$request->attributes->set('_route_params', ['base' => 'zouzou', 'route' => '/test', 'ignoreAttributes' => false, 'keepRequestMethod' => false, 'keepQueryParams' => true]);
|
$request->attributes->set('_route_params', ['b.se' => 'zouzou', 'route' => '/test', 'ignoreAttributes' => false, 'keepRequestMethod' => false, 'keepQueryParams' => true]);
|
||||||
$this->assertRedirectUrl($controller($request), '/test?base=zouzou');
|
$this->assertRedirectUrl($controller($request), '/test?b.se=zouzou');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testMissingPathOrRouteParameter()
|
public function testMissingPathOrRouteParameter()
|
||||||
|
Reference in New Issue
Block a user