Skip to content

Commit ff3966e

Browse files
Merge branch '4.4' into 5.0
* 4.4: [VarDumper] fix typo Fix support for PHP8 union types [FrameworkBundle] preserve dots in query-string when redirecting [3.4] Fix support for PHP8 union types [PhpUnitBridge] Streamline ansi/no-ansi of composer according to phpunit --colors option [3.4] Small update in our internal terminology [Cache] fix compat with DBAL v3 [HttpClient] Convert CurlHttpClient::handlePush() to instance method [VarDumper] Fix CliDumper coloration [DI] tighten detection of local dirs to prevent false positives [FrameworkBundle] preserve dots in query-string when redirecting Fix precendence in 4.4 bumped Symfony version to 3.4.43 updated VERSION for 3.4.42 update CONTRIBUTORS for 3.4.42 updated CHANGELOG for 3.4.42
2 parents a4779a0 + f7094b7 commit ff3966e

File tree

2 files changed

+84
-41
lines changed

2 files changed

+84
-41
lines changed

Controller/RedirectController.php

Lines changed: 57 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,17 @@ public function redirectAction(Request $request, string $route, bool $permanent
6262
$attributes = [];
6363
if (false === $ignoreAttributes || \is_array($ignoreAttributes)) {
6464
$attributes = $request->attributes->get('_route_params');
65-
$attributes = $keepQueryParams ? array_merge($request->query->all(), $attributes) : $attributes;
65+
66+
if ($keepQueryParams) {
67+
if ($query = $request->server->get('QUERY_STRING')) {
68+
$query = self::parseQuery($query);
69+
} else {
70+
$query = $request->query->all();
71+
}
72+
73+
$attributes = array_merge($query, $attributes);
74+
}
75+
6676
unset($attributes['route'], $attributes['permanent'], $attributes['ignoreAttributes'], $attributes['keepRequestMethod'], $attributes['keepQueryParams']);
6777
if ($ignoreAttributes) {
6878
$attributes = array_diff_key($attributes, array_flip($ignoreAttributes));
@@ -117,8 +127,7 @@ public function urlRedirectAction(Request $request, string $path, bool $permanen
117127
$scheme = $request->getScheme();
118128
}
119129

120-
$qs = $request->getQueryString();
121-
if ($qs) {
130+
if ($qs = $request->server->get('QUERY_STRING') ?: $request->getQueryString()) {
122131
if (false === strpos($path, '?')) {
123132
$qs = '?'.$qs;
124133
} else {
@@ -176,4 +185,49 @@ public function __invoke(Request $request): Response
176185

177186
throw new \RuntimeException(sprintf('The parameter "path" or "route" is required to configure the redirect action in "%s" routing configuration.', $request->attributes->get('_route')));
178187
}
188+
189+
private static function parseQuery(string $query)
190+
{
191+
$q = [];
192+
193+
foreach (explode('&', $query) as $v) {
194+
if (false !== $i = strpos($v, "\0")) {
195+
$v = substr($v, 0, $i);
196+
}
197+
198+
if (false === $i = strpos($v, '=')) {
199+
$k = urldecode($v);
200+
$v = '';
201+
} else {
202+
$k = urldecode(substr($v, 0, $i));
203+
$v = substr($v, $i);
204+
}
205+
206+
if (false !== $i = strpos($k, "\0")) {
207+
$k = substr($k, 0, $i);
208+
}
209+
210+
$k = ltrim($k, ' ');
211+
212+
if (false === $i = strpos($k, '[')) {
213+
$q[] = bin2hex($k).$v;
214+
} else {
215+
$q[] = substr_replace($k, bin2hex(substr($k, 0, $i)), 0, $i).$v;
216+
}
217+
}
218+
219+
parse_str(implode('&', $q), $q);
220+
221+
$query = [];
222+
223+
foreach ($q as $k => $v) {
224+
if (false !== $i = strpos($k, '_')) {
225+
$query[substr_replace($k, hex2bin(substr($k, 0, $i)).'[', 0, 1 + $i)] = $v;
226+
} else {
227+
$query[hex2bin($k)] = $v;
228+
}
229+
}
230+
231+
return $query;
232+
}
179233
}

Tests/Controller/RedirectControllerTest.php

Lines changed: 27 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -267,9 +267,9 @@ public function pathQueryParamsProvider()
267267
return [
268268
['http://www.example.com/base/redirect-path', '/redirect-path', ''],
269269
['http://www.example.com/base/redirect-path?foo=bar', '/redirect-path?foo=bar', ''],
270-
['http://www.example.com/base/redirect-path?foo=bar', '/redirect-path', 'foo=bar'],
271-
['http://www.example.com/base/redirect-path?foo=bar&abc=example', '/redirect-path?foo=bar', 'abc=example'],
272-
['http://www.example.com/base/redirect-path?foo=bar&abc=example&baz=def', '/redirect-path?foo=bar', 'abc=example&baz=def'],
270+
['http://www.example.com/base/redirect-path?f.o=bar', '/redirect-path', 'f.o=bar'],
271+
['http://www.example.com/base/redirect-path?f.o=bar&a.c=example', '/redirect-path?f.o=bar', 'a.c=example'],
272+
['http://www.example.com/base/redirect-path?f.o=bar&a.c=example&b.z=def', '/redirect-path?f.o=bar', 'a.c=example&b.z=def'],
273273
];
274274
}
275275

@@ -302,17 +302,16 @@ public function testRedirectWithQuery()
302302
$baseUrl = '/base';
303303
$port = 80;
304304

305-
$request = $this->createRequestObject($scheme, $host, $port, $baseUrl, 'base=zaza');
306-
$request->query = new ParameterBag(['base' => 'zaza']);
305+
$request = $this->createRequestObject($scheme, $host, $port, $baseUrl, 'b.se=zaza');
307306
$request->attributes = new ParameterBag(['_route_params' => ['base2' => 'zaza']]);
308307
$urlGenerator = $this->getMockBuilder(UrlGeneratorInterface::class)->getMock();
309-
$urlGenerator->expects($this->exactly(2))->method('generate')->willReturn('/test?base=zaza&base2=zaza')->with('/test', ['base' => 'zaza', 'base2' => 'zaza'], UrlGeneratorInterface::ABSOLUTE_URL);
308+
$urlGenerator->expects($this->exactly(2))->method('generate')->willReturn('/test?b.se=zaza&base2=zaza')->with('/test', ['b.se' => 'zaza', 'base2' => 'zaza'], UrlGeneratorInterface::ABSOLUTE_URL);
310309

311310
$controller = new RedirectController($urlGenerator);
312-
$this->assertRedirectUrl($controller->redirectAction($request, '/test', false, false, false, true), '/test?base=zaza&base2=zaza');
311+
$this->assertRedirectUrl($controller->redirectAction($request, '/test', false, false, false, true), '/test?b.se=zaza&base2=zaza');
313312

314313
$request->attributes->set('_route_params', ['base2' => 'zaza', 'route' => '/test', 'ignoreAttributes' => false, 'keepRequestMethod' => false, 'keepQueryParams' => true]);
315-
$this->assertRedirectUrl($controller($request), '/test?base=zaza&base2=zaza');
314+
$this->assertRedirectUrl($controller($request), '/test?b.se=zaza&base2=zaza');
316315
}
317316

318317
public function testRedirectWithQueryWithRouteParamsOveriding()
@@ -322,17 +321,16 @@ public function testRedirectWithQueryWithRouteParamsOveriding()
322321
$baseUrl = '/base';
323322
$port = 80;
324323

325-
$request = $this->createRequestObject($scheme, $host, $port, $baseUrl, 'base=zaza');
326-
$request->query = new ParameterBag(['base' => 'zaza']);
327-
$request->attributes = new ParameterBag(['_route_params' => ['base' => 'zouzou']]);
324+
$request = $this->createRequestObject($scheme, $host, $port, $baseUrl, 'b.se=zaza');
325+
$request->attributes = new ParameterBag(['_route_params' => ['b.se' => 'zouzou']]);
328326
$urlGenerator = $this->getMockBuilder(UrlGeneratorInterface::class)->getMock();
329-
$urlGenerator->expects($this->exactly(2))->method('generate')->willReturn('/test?base=zouzou')->with('/test', ['base' => 'zouzou'], UrlGeneratorInterface::ABSOLUTE_URL);
327+
$urlGenerator->expects($this->exactly(2))->method('generate')->willReturn('/test?b.se=zouzou')->with('/test', ['b.se' => 'zouzou'], UrlGeneratorInterface::ABSOLUTE_URL);
330328

331329
$controller = new RedirectController($urlGenerator);
332-
$this->assertRedirectUrl($controller->redirectAction($request, '/test', false, false, false, true), '/test?base=zouzou');
330+
$this->assertRedirectUrl($controller->redirectAction($request, '/test', false, false, false, true), '/test?b.se=zouzou');
333331

334-
$request->attributes->set('_route_params', ['base' => 'zouzou', 'route' => '/test', 'ignoreAttributes' => false, 'keepRequestMethod' => false, 'keepQueryParams' => true]);
335-
$this->assertRedirectUrl($controller($request), '/test?base=zouzou');
332+
$request->attributes->set('_route_params', ['b.se' => 'zouzou', 'route' => '/test', 'ignoreAttributes' => false, 'keepRequestMethod' => false, 'keepQueryParams' => true]);
333+
$this->assertRedirectUrl($controller($request), '/test?b.se=zouzou');
336334
}
337335

338336
public function testMissingPathOrRouteParameter()
@@ -353,29 +351,20 @@ public function testAmbiguousPathAndRouteParameter()
353351

354352
private function createRequestObject($scheme, $host, $port, $baseUrl, $queryString = '')
355353
{
356-
$request = $this->getMockBuilder('Symfony\Component\HttpFoundation\Request')->getMock();
357-
$request
358-
->expects($this->any())
359-
->method('getScheme')
360-
->willReturn($scheme);
361-
$request
362-
->expects($this->any())
363-
->method('getHost')
364-
->willReturn($host);
365-
$request
366-
->expects($this->any())
367-
->method('getPort')
368-
->willReturn($port);
369-
$request
370-
->expects($this->any())
371-
->method('getBaseUrl')
372-
->willReturn($baseUrl);
373-
$request
374-
->expects($this->any())
375-
->method('getQueryString')
376-
->willReturn($queryString);
377-
378-
return $request;
354+
if ('' !== $queryString) {
355+
parse_str($queryString, $query);
356+
} else {
357+
$query = [];
358+
}
359+
360+
return new Request($query, [], [], [], [], [
361+
'HTTPS' => 'https' === $scheme,
362+
'HTTP_HOST' => $host.($port ? ':'.$port : ''),
363+
'SERVER_PORT' => $port,
364+
'SCRIPT_FILENAME' => $baseUrl,
365+
'REQUEST_URI' => $baseUrl,
366+
'QUERY_STRING' => $queryString,
367+
]);
379368
}
380369

381370
private function createRedirectController($httpPort = null, $httpsPort = null)

0 commit comments

Comments
 (0)