Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 779435a

Browse filesBrowse files
sleepyboynicolas-grekas
authored andcommitted
[HttpClient] simplify merging logic of query string
1 parent ecfb468 commit 779435a
Copy full SHA for 779435a

File tree

Expand file treeCollapse file tree

2 files changed

+19
-85
lines changed
Filter options
Expand file treeCollapse file tree

2 files changed

+19
-85
lines changed

‎src/Symfony/Component/HttpClient/HttpClientTrait.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/HttpClient/HttpClientTrait.php
+17-83Lines changed: 17 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@
1111

1212
namespace Symfony\Component\HttpClient;
1313

14-
use RecursiveArrayIterator;
15-
use RecursiveIteratorIterator;
1614
use Symfony\Component\HttpClient\Exception\InvalidArgumentException;
1715

1816
/**
@@ -473,97 +471,33 @@ private static function mergeQueryString(?string $queryString, array $queryArray
473471
}
474472

475473
$query = [];
476-
if (null !== $queryString && '' !== $queryString) {
477-
$query = self::parseQueryString($queryString);
478-
}
479-
480-
if (!empty($queryArray)) {
481-
$query = self::mergeQueryParams($query, $queryArray, $replace);
482-
}
483474

484-
$finalQueryString = '';
485-
if (!empty($query)) {
486-
$iterator = new RecursiveIteratorIterator(new RecursiveArrayIterator($query));
487-
$iterator->rewind();
488-
foreach ($iterator as $v) {
489-
$finalQueryString .= ($finalQueryString ? '&' : '').$v;
475+
if (null !== $queryString) {
476+
foreach (explode('&', $queryString) as $v) {
477+
if ('' !== $v) {
478+
$k = urldecode(explode('=', $v, 2)[0]);
479+
$query[$k] = (isset($query[$k]) ? $query[$k].'&' : '').$v;
480+
}
490481
}
491482
}
492483

493-
return $finalQueryString;
494-
}
495-
496-
/**
497-
* Custom query string parser.
498-
* We cannot use parse_str() here as it replaces some characters and breaks legit query strings.
499-
*
500-
* @param string $queryString
501-
*
502-
* @return array
503-
*/
504-
private static function parseQueryString($queryString)
505-
{
506-
$query = [];
507-
foreach (explode('&', $queryString) as $v) {
508-
if ('' == $v) {
509-
continue;
510-
}
511-
512-
if (false === $n = strpos($v, '=')) {
513-
$k = $v;
514-
} else {
515-
$k = substr($v, 0, $n);
516-
}
517-
518-
if (preg_match('/^(?P<key>[^\[]*)(?P<keys>\[.*\])$/', $k, $matches)) {
519-
$firstKey = $matches['key'];
520-
preg_match_all('/(?<=\[).+?(?=\])/', $matches['keys'], $matches);
521-
$keys = array_reverse($matches[0]);
522-
$query[urldecode($firstKey)] = array_reduce($keys, function ($array, $item) {
523-
return [$item => $array];
524-
}, $v);
525-
} else {
526-
$query[urldecode($k)] = (isset($query[$k]) ? $query[$k].'&' : '').$v;
484+
if ($replace) {
485+
foreach ($queryArray as $k => $v) {
486+
if (null === $v) {
487+
unset($query[$k]);
488+
}
527489
}
528490
}
529491

530-
return $query;
531-
}
532-
533-
/**
534-
* @param array $query
535-
* @param array $queryArray
536-
* @param bool $replace
537-
* @param string $parentPath
538-
*
539-
* @return array
540-
*/
541-
private static function mergeQueryParams(array $query, array $queryArray, bool $replace, string $parentPath = ''): array
542-
{
543-
foreach ($queryArray as $k => $v) {
544-
if (!$replace && isset($query[$k]) && (!\is_array($v) || is_scalar($query[$k]))) {
545-
continue;
546-
}
547-
548-
$path = $parentPath.($parentPath ? '[' : '').$k.($parentPath ? ']' : '');
549-
550-
if ($replace || !isset($query[$k])) {
551-
if (\is_array($v) && (!isset($query[$k]) || !\is_array($query[$k]))) {
552-
$query[$k] = [];
553-
}
492+
$queryString = http_build_query($queryArray, '', '&', PHP_QUERY_RFC3986);
493+
$queryArray = [];
554494

555-
if (null === $v) {
556-
unset($query[$k]);
557-
} elseif (is_scalar($v)) {
558-
$query[$k] = rawurlencode($path).'='.rawurlencode($v);
559-
} elseif (\is_array($v)) {
560-
$query[$k] = self::mergeQueryParams($query[$k], $v, $replace, $path);
561-
} else {
562-
throw new InvalidArgumentException(sprintf('Unsupported value for query parameter "%s": scalar or null expected, %s given.', $path, \gettype($v)));
563-
}
495+
if ($queryString) {
496+
foreach (explode('&', $queryString) as $v) {
497+
$queryArray[rawurldecode(explode('=', $v, 2)[0])] = $v;
564498
}
565499
}
566500

567-
return $query;
501+
return implode('&', $replace ? array_replace($query, $queryArray) : ($query + $queryArray));
568502
}
569503
}

‎src/Symfony/Component/HttpClient/Tests/HttpClientTraitTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/HttpClient/Tests/HttpClientTraitTest.php
+2-2Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,8 +143,8 @@ public function provideParseUrl()
143143
yield [[null, null, 'bar', '?a=b%2B%20c', null], 'bar?a=b+c', ['a' => 'b+ c']];
144144
yield [[null, null, 'bar', '?a%5Bb%5D=c', null], 'bar', ['a' => ['b' => 'c']]];
145145
yield [[null, null, 'bar', '?a%5Bb%5Bc%5D=d', null], 'bar?a[b[c]=d', []];
146-
yield [[null, null, 'bar', '?a%5Bb%5D%5Bc%5D=dd', null], 'bar?a[b][c]=d&e[f]=g', ['a' => ['b' => ['c' => 'dd']], 'e' => null]];
147-
yield [[null, null, 'bar', '?a%5Bb%20c%5D=d&e%3Df=%E2%9C%93', null], 'bar?a=b', ['a' => ['b c' => 'd'], 'e=f' => '']];
146+
yield [[null, null, 'bar', '?a%5Bb%5D%5Bc%5D=dd', null], 'bar?a[b][c]=d&e[f]=g', ['a' => ['b' => ['c' => 'dd']], 'e[f]' => null]];
147+
yield [[null, null, 'bar', '?a=b&a%5Bb%20c%5D=d&e%3Df=%E2%9C%93', null], 'bar?a=b', ['a' => ['b c' => 'd'], 'e=f' => '']];
148148
}
149149

150150
/**

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.