Skip to content

Commit

Permalink
Replace own query string to array with package
Browse files Browse the repository at this point in the history
As there is the new query string package, replace the last usage of the
`Helpers::queryStringToArray()` method with the `Query` class from the
package, to not have duplicate logic. Also, the package already contains
some fixes.
  • Loading branch information
otsch committed Jan 30, 2023
1 parent 3fcce93 commit 7cdcb0c
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 42 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [2.0.3] - 2023-01-30
### Fixed
- As there is the new query string package, replace the last usage of the `Helpers::queryStringToArray()` method with the `Query` class from the package, to not have duplicate logic. Also, the package already contains some fixes.

## [2.0.2] - 2023-01-14
### Changed
- Updated lists of schemes, suffixes and default ports.
Expand Down
46 changes: 5 additions & 41 deletions src/Helpers.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

namespace Crwlr\Url;

use Crwlr\QueryString\Query;
use Exception;

/**
* Class Helpers
*
Expand Down Expand Up @@ -143,16 +146,11 @@ public static function buildUserInfoFromComponents(array $components): string
* Converts a URL query string to array.
*
* @return string[]
* @throws Exception
*/
public static function queryStringToArray(string $query = ''): array
{
parse_str($query, $array);

if (preg_match('/(?:^|&)([^\[=&]*\.)/', $query)) { // Matches keys in the query that contain a dot
return self::replaceKeysContainingDots($query, $array);
}

return $array;
return Query::fromString($query)->toArray();
}

/**
Expand Down Expand Up @@ -295,38 +293,4 @@ public static function idn_to_utf8(string $string): string

return $converted !== false ? $converted : $string;
}

/**
* Helper method for queryStringToArray
*
* When keys within a URL query string contain dots, PHP's parse_str() method converts them to underscores. This
* method works around this issue so the requested query array returns the proper keys with dots.
*
* @param string[] $array
* @return string[]
*/
private static function replaceKeysContainingDots(string $query, array $array): array
{
// Regex to find keys in query string.
preg_match_all('/(?:^|&)([^=&\[]+)(?:[=&\[]|$)/', $query, $matches);
$brokenKeys = $fixedArray = [];

// Create mapping of broken keys to original proper keys.
foreach ($matches[1] as $value) {
if (str_contains($value, '.')) {
$brokenKeys[str_replace('.', '_', $value)] = $value;
}
}

// Recreate the array with the proper keys.
foreach ($array as $key => $value) {
if (isset($brokenKeys[$key])) {
$fixedArray[$brokenKeys[$key]] = $value;
} else {
$fixedArray[$key] = $value;
}
}

return $fixedArray;
}
}
9 changes: 8 additions & 1 deletion src/Url.php
Original file line number Diff line number Diff line change
Expand Up @@ -426,17 +426,24 @@ public function queryArray(?array $query = null): array|Url
{
if ($query === null) {
if ($this->query instanceof Query) {
return $this->query->toArray();
} elseif ($this->query) {
$this->query = Query::fromString($this->query);

return $this->query->toArray();
}

return $this->query ? Helpers::queryStringToArray($this->query) : [];
return [];
} else {
$this->query = $this->validateComponentValue('query', http_build_query($query));
}

return $this->updateFullUrlAndReturnInstance();
}

/**
* @throws Exception
*/
public function queryString(): Query
{
if (!$this->query instanceof Query) {
Expand Down
22 changes: 22 additions & 0 deletions tests/UrlTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,28 @@
$this->assertEquals('https://www.example.com#foo', $url->toString());
});

it('parses a query string with percent encoded brackets and keys containing dots', function () {
$url = Url::parse('https://www.example.com/path?foo.bar%5B0%5D=v1&foo.bar_extra%5B0%5D=v2&foo.bar.extra%5B0%5D=v3');

expect($url->queryArray())->toBe([
'foo.bar' => ['v1'],
'foo.bar_extra' => ['v2'],
'foo.bar.extra' => ['v3'],
]);
});

it('correctly parses a query where keys contain dots', function () {
$url = Url::parse('https://www.example.com/path?foo.bar[0]=v1&foo.bar_extra[0]=v2&foo.bar.extra[0]=v3');

expect($url->query())->toBe('foo.bar%5B0%5D=v1&foo.bar_extra%5B0%5D=v2&foo.bar.extra%5B0%5D=v3');

expect($url->queryArray())->toBe([
'foo.bar' => ['v1'],
'foo.bar_extra' => ['v2'],
'foo.bar.extra' => ['v3'],
]);
});

test('ReplaceQueryString', function () {
$url = createDefaultUrlObject();
$this->assertEquals('some=query', $url->query());
Expand Down

0 comments on commit 7cdcb0c

Please sign in to comment.