Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 12 additions & 7 deletions src/Symfony/Component/HttpFoundation/Request.php
Original file line number Diff line number Diff line change
Expand Up @@ -616,14 +616,15 @@ public static function getTrustedHosts()
/**
* Normalizes a query string.
*
* It builds a normalized query string, where keys/value pairs are alphabetized,
* It builds a normalized query string, where keys/value pairs are alphabetized (by default),
* have consistent escaping and unneeded delimiters are removed.
*
* @param string $qs Query string
* @param string $qs Query string
* @param bool $preserveOrder Flag to preserve the querystring from being alphabetically ordered
*
* @return string A normalized query string for the Request
*/
public static function normalizeQueryString($qs)
public static function normalizeQueryString($qs, bool $preserveOrder = false)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding a new argument is a BC break, isn't it?
This needs a BC layer.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Totally right, I'll work on this sorry.

{
if ('' == $qs) {
return '';
Expand Down Expand Up @@ -651,7 +652,9 @@ public static function normalizeQueryString($qs)
$order[] = urldecode($keyValuePair[0]);
}

array_multisort($order, SORT_ASC, $parts);
if (true !== $preserveOrder) {
array_multisort($order, SORT_ASC, $parts);
}

return implode('&', $parts);
}
Expand Down Expand Up @@ -1103,13 +1106,15 @@ public function getRelativeUriForPath($path)
* Generates the normalized query string for the Request.
*
* It builds a normalized query string, where keys/value pairs are alphabetized
* and have consistent escaping.
* (by default) and have consistent escaping.
*
* @param bool $preserveOrder Flag to preserve the querystring from being alphabetically ordered
*
* @return string|null A normalized query string for the Request
*/
public function getQueryString()
public function getQueryString(bool $preserveOrder = false)
{
$qs = static::normalizeQueryString($this->server->get('QUERY_STRING'));
$qs = static::normalizeQueryString($this->server->get('QUERY_STRING'), $preserveOrder);

return '' === $qs ? null : $qs;
}
Expand Down
30 changes: 28 additions & 2 deletions src/Symfony/Component/HttpFoundation/Tests/RequestTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -672,17 +672,43 @@ public function testGetQueryString($query, $expectedQuery, $msg)
$this->assertSame($expectedQuery, $request->getQueryString(), $msg);
}

public function testGetQueryStringSortAlphabeticalyByDefaut()
{
$request = new Request();

$request->server->set('QUERY_STRING', 'foo=bar&bar=');
$this->assertSame('bar=&foo=bar', $request->getQueryString(), 'sorts keys alphabetically');
}

/**
* @dataProvider getQueryStringNormalizationData
*/
public function testGetQueryStringWithoutOrderingDoesNotAffectAnythingElseThanOrder($query, $expectedQuery, $msg)
{
$request = new Request();

$request->server->set('QUERY_STRING', $query);
$this->assertSame($expectedQuery, $request->getQueryString(true), $msg);
}

public function testGetQueryStringPreservesOrder()
{
$request = new Request();

$request->server->set('QUERY_STRING', 'foo=bar&bar=');
$this->assertSame('foo=bar&bar=', $request->getQueryString(true), 'preserves keys order');
}

public function getQueryStringNormalizationData()
{
return array(
array('foo', 'foo', 'works with valueless parameters'),
array('foo=', 'foo=', 'includes a dangling equal sign'),
array('bar=&foo=bar', 'bar=&foo=bar', '->works with empty parameters'),
array('foo=bar&bar=', 'bar=&foo=bar', 'sorts keys alphabetically'),

// GET parameters, that are submitted from a HTML form, encode spaces as "+" by default (as defined in enctype application/x-www-form-urlencoded).
// PHP also converts "+" to spaces when filling the global _GET or when using the function parse_str.
array('him=John%20Doe&her=Jane+Doe', 'her=Jane%20Doe&him=John%20Doe', 'normalizes spaces in both encodings "%20" and "+"'),
array('her=Jane+Doe&him=John%20Doe', 'her=Jane%20Doe&him=John%20Doe', 'normalizes spaces in both encodings "%20" and "+"'),

array('foo[]=1&foo[]=2', 'foo%5B%5D=1&foo%5B%5D=2', 'allows array notation'),
array('foo=1&foo=2', 'foo=1&foo=2', 'allows repeated parameters'),
Expand Down