Skip to content

Commit

Permalink
Query helper
Browse files Browse the repository at this point in the history
  • Loading branch information
sirn-se committed Mar 2, 2024
1 parent 21af2b2 commit 9b17fc5
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 13 deletions.
29 changes: 16 additions & 13 deletions src/Uri.php
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,12 @@ public function getQueryItem(string $name, int $flags = 0): array|string|null
public function withQueryItems(array $items, int $flags = 0): UriInterface
{
$clone = $this->clone($flags);
$clone->setQuery(http_build_query($this->merge($this->getQueryItems($flags), $items)), $flags);
$clone->setQuery(http_build_query(
$this->queryMerge($this->getQueryItems($flags), $items),
'',
null,
PHP_QUERY_RFC3986
), $flags);
return $clone;
}

Expand Down Expand Up @@ -557,7 +562,7 @@ private function parse(string $uri_string = ''): void
if (empty($auth) && $main['authority'] !== '') {
throw new InvalidArgumentException("Invalid 'authority'.");
}
if ($this->isEmpty($auth['host']) && !$this->isEmpty($auth['user'])) {
if ($auth['host'] === '' && $auth['user'] !== '') {
throw new InvalidArgumentException("Invalid 'authority'.");
}
$this->setUser(isset($auth['user']) ? $auth['user'] : '');
Expand Down Expand Up @@ -589,14 +594,10 @@ private function uriEncode(string $source, int $flags = 0, string $keep = ''): s
}, $source);
}

private function formatComponent(mixed $value, string $before = '', string $after = ''): string
private function formatComponent(string|int|null $value, string $before = '', string $after = ''): string
{
return $this->isEmpty($value) ? '' : "{$before}{$value}{$after}";
}

private function isEmpty(mixed $value): bool
{
return is_null($value) || $value === '';
$string = strval($value);
return $string === '' ? '' : "{$before}{$string}{$after}";
}

private function normalizePath(string $path): string
Expand Down Expand Up @@ -645,15 +646,17 @@ private function idnDecode(string $value): string
return idn_to_utf8($value, IDNA_NONTRANSITIONAL_TO_UNICODE, INTL_IDNA_VARIANT_UTS46);
}

private function merge(array $a, array $b): array
private function queryMerge(array $a, array $b): array
{
foreach ($b as $key => $value) {
if (is_int($key)) {
$a[] = $value;
} elseif (array_key_exists($key, $a) && is_array($a[$key]) && is_array($b[$key])) {
$a[$key] = $this->merge($a[$key], $b[$key]);
} elseif (is_array($value)) {
$a[$key] = $this->queryMerge($a[$key] ?? [], $b[$key] ?? []);
} elseif (is_scalar($value)) {
$a[$key] = rawurldecode($b[$key]);
} else {
$a[$key] = $b[$key];
unset($a[$key]);
}
}
return $a;
Expand Down
13 changes: 13 additions & 0 deletions tests/UriExtensionsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,19 @@ public function testComponents(): void
$this->assertEquals(parse_url($uri_str), $uri->getComponents());
}

public function testQueryHelpers2(): void
{
$uri = new Uri('http://domain.tld:80/path?aaa=ö +-:;%C3%B6');
$this->assertEquals('aaa=%C3%B6%20+-:;%C3%B6', $uri->getQuery());
$this->assertEquals(['aaa' => 'ö -:;ö'], $uri->getQueryItems());
$this->assertEquals('ö -:;ö', $uri->getQueryItem('aaa'));

$uri = $uri->withQueryItem('aaa', 'å -+:;%C3%A5');
$this->assertEquals('aaa=%C3%A5%20-%2B%3A%3B%C3%A5', $uri->getQuery());
$this->assertEquals(['aaa' => 'å -+:;å'], $uri->getQueryItems());
$this->assertEquals('å -+:;å', $uri->getQueryItem('aaa'));
}

public function testQueryHelpers(): void
{
$uri = new Uri('http://domain.tld:80/path?arr%5B0%5D=arr1&arr%5B1%5D=arr2#fragment');
Expand Down

0 comments on commit 9b17fc5

Please sign in to comment.