Skip to content

Commit 3786999

Browse files
committed
:octocat: move QueryUtil::parseUrl() to UriUtil::parseUrl()
1 parent f83afbf commit 3786999

File tree

5 files changed

+66
-65
lines changed

5 files changed

+66
-65
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,6 @@ The following classes contain static methods for use with PSR-7 http message obj
6363
| `build(array $params, int $encoding = null, string $delimiter = null, string $enclosure = null)` | `string` | Builds a query string from an array of key value pairs, similar to [`http_build_query`](https://www.php.net/manual/en/function.http-build-query). Valid values for `$encoding` are `PHP_QUERY_RFC3986` (default) and `PHP_QUERY_RFC1738`, any other integer value will be interpreted as "no encoding" (`Query::NO_ENCODING`). |
6464
| `merge(string $uri, array $query)` | `string` | Merges additional query parameters into an existing query string. |
6565
| `parse(string $querystring, int $urlEncoding = null)` | `array` | Parses a query string into an associative array, similar to [`parse_str`](https://www.php.net/manual/en/function.parse-str) (without the inconvenient usage of a by-reference result variable). |
66-
| `parseUrl(string $url)` | `?array` | UTF-8 aware `\parse_url()` replacement. |
6766
| `recursiveRawurlencode(mixed $data)` | `array\|string` | Recursive [`rawurlencode`](https://www.php.net/manual/en/function.rawurlencode) |
6867

6968
### `MessageUtil`
@@ -87,6 +86,7 @@ The following classes contain static methods for use with PSR-7 http message obj
8786
| `isRelativePathReference(UriInterface $uri)` | `bool` | Checks whether the URI is a relative-path reference. |
8887
| `withoutQueryValue(UriInterface $uri, string $key)` | `UriInterface` | Removes a specific query string value. Any existing query string values that exactly match the provided `$key` are removed. |
8988
| `withQueryValue(UriInterface $uri, string $key, string $value = null)` | `UriInterface` | Adds a specific query string value. Any existing query string values that exactly match the provided `$key` are removed and replaced with the given `$key`-`$value` pair. A value of null will set the query string key without a value, e.g. "key" instead of "key=value". |
89+
| `parseUrl(string $url)` | `?array` | UTF-8 aware `\parse_url()` replacement. |
9090

9191
### `MimeTypeUtil`
9292
| method | return | info |

src/QueryUtil.php

Lines changed: 3 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212

1313
use InvalidArgumentException;
1414
use function array_map, array_merge, call_user_func_array, explode, implode, is_array, is_bool,
15-
is_iterable, is_numeric, is_scalar, is_string, parse_url, preg_match, preg_replace_callback,
16-
rawurldecode, rawurlencode, sort, str_replace, trim, uksort, urlencode;
15+
is_iterable, is_numeric, is_scalar, is_string, rawurldecode, rawurlencode, sort, str_replace,
16+
trim, uksort;
1717
use const PHP_QUERY_RFC1738, PHP_QUERY_RFC3986, SORT_STRING;
1818

1919
/**
@@ -162,7 +162,7 @@ public static function build(array $params, int $encoding = null, string $delimi
162162
* Merges additional query parameters into an existing query string
163163
*/
164164
public static function merge(string $uri, array $query):string{
165-
$querypart = (self::parseUrl($uri)['query'] ?? '');
165+
$querypart = (UriUtil::parseUrl($uri)['query'] ?? '');
166166
$params = array_merge(self::parse($querypart), $query);
167167
$requestURI = explode('?', $uri)[0];
168168

@@ -221,41 +221,6 @@ public static function parse(string $querystring, int $urlEncoding = null):array
221221
return $result;
222222
}
223223

224-
/**
225-
* UTF-8 aware \parse_url() replacement.
226-
*
227-
* The internal function produces broken output for non ASCII domain names
228-
* (IDN) when used with locales other than "C".
229-
*
230-
* On the other hand, cURL understands IDN correctly only when UTF-8 locale
231-
* is configured ("C.UTF-8", "en_US.UTF-8", etc.).
232-
*
233-
* @see https://bugs.php.net/bug.php?id=52923
234-
* @see https://www.php.net/manual/en/function.parse-url.php#114817
235-
* @see https://curl.haxx.se/libcurl/c/CURLOPT_URL.html#ENCODING
236-
*
237-
* @link https://github.com/guzzle/psr7/blob/c0dcda9f54d145bd4d062a6d15f54931a67732f9/src/Uri.php#L89-L130
238-
*/
239-
public static function parseUrl(string $url):?array{
240-
// If IPv6
241-
$prefix = '';
242-
/** @noinspection RegExpRedundantEscape */
243-
if(preg_match('%^(.*://\[[0-9:a-f]+\])(.*?)$%', $url, $matches)){
244-
/** @var array{0:string, 1:string, 2:string} $matches */
245-
$prefix = $matches[1];
246-
$url = $matches[2];
247-
}
248-
249-
$encodedUrl = preg_replace_callback('%[^:/@?&=#]+%usD', fn($matches) => urlencode($matches[0]), $url);
250-
$result = parse_url($prefix.$encodedUrl);
251-
252-
if($result === false){
253-
return null;
254-
}
255-
256-
return array_map('urldecode', $result);
257-
}
258-
259224
/**
260225
* Recursive rawurlencode
261226
*

src/UriUtil.php

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
namespace chillerlan\HTTP\Utils;
1212

1313
use Psr\Http\Message\UriInterface;
14-
use function array_filter, explode, implode, rawurldecode;
14+
use function array_filter, array_map, explode, implode, parse_url, preg_match, preg_replace_callback, rawurldecode, urlencode;
1515

1616
/**
1717
*
@@ -139,4 +139,39 @@ public static function withQueryValue(UriInterface $uri, string $key, string $va
139139
return $uri->withQuery(implode('&', $result));
140140
}
141141

142+
/**
143+
* UTF-8 aware \parse_url() replacement.
144+
*
145+
* The internal function produces broken output for non ASCII domain names
146+
* (IDN) when used with locales other than "C".
147+
*
148+
* On the other hand, cURL understands IDN correctly only when UTF-8 locale
149+
* is configured ("C.UTF-8", "en_US.UTF-8", etc.).
150+
*
151+
* @see https://bugs.php.net/bug.php?id=52923
152+
* @see https://www.php.net/manual/en/function.parse-url.php#114817
153+
* @see https://curl.haxx.se/libcurl/c/CURLOPT_URL.html#ENCODING
154+
*
155+
* @link https://github.com/guzzle/psr7/blob/c0dcda9f54d145bd4d062a6d15f54931a67732f9/src/Uri.php#L89-L130
156+
*/
157+
public static function parseUrl(string $url):?array{
158+
// If IPv6
159+
$prefix = '';
160+
/** @noinspection RegExpRedundantEscape */
161+
if(preg_match('%^(.*://\[[0-9:a-f]+\])(.*?)$%', $url, $matches)){
162+
/** @var array{0:string, 1:string, 2:string} $matches */
163+
$prefix = $matches[1];
164+
$url = $matches[2];
165+
}
166+
167+
$encodedUrl = preg_replace_callback('%[^:/@?&=#]+%usD', fn($matches) => urlencode($matches[0]), $url);
168+
$result = parse_url($prefix.$encodedUrl);
169+
170+
if($result === false){
171+
return null;
172+
}
173+
174+
return array_map('urldecode', $result);
175+
}
176+
142177
}

tests/QueryUtilTest.php

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -168,31 +168,6 @@ public function testParseDoesTrimQuestionMark():void{
168168
$this::assertSame(QueryUtil::parse('?q=a'), ['q' => 'a']);
169169
}
170170

171-
public static function parseUrlProvider():array{
172-
return [
173-
['http://', null],
174-
[
175-
'https://яндекAс.рф', [
176-
'scheme' => 'https',
177-
'host' => 'яндекAс.рф',
178-
],
179-
],
180-
[
181-
'http://[2a00:f48:1008::212:183:10]:56?foo=bar', [
182-
'scheme' => 'http',
183-
'host' => '[2a00:f48:1008::212:183:10]',
184-
'port' => '56',
185-
'query' => 'foo=bar',
186-
],
187-
],
188-
];
189-
}
190-
191-
#[DataProvider('parseUrlProvider')]
192-
public function testParseUrl($url, $expected):void{
193-
$this::assertSame($expected, QueryUtil::parseUrl($url));
194-
}
195-
196171
public static function rawurlencodeDataProvider():array{
197172
return [
198173
'null' => [null, ''],

tests/UriUtilTest.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
namespace chillerlan\HTTPTest\Utils;
1212

1313
use chillerlan\HTTP\Utils\UriUtil;
14+
use PHPUnit\Framework\Attributes\DataProvider;
1415
use PHPUnit\Framework\TestCase;
1516

1617
/**
@@ -127,4 +128,29 @@ public function testUriIsDefaultPort():void{
127128

128129
}
129130

131+
public static function parseUrlProvider():array{
132+
return [
133+
['http://', null],
134+
[
135+
'https://яндекAс.рф', [
136+
'scheme' => 'https',
137+
'host' => 'яндекAс.рф',
138+
],
139+
],
140+
[
141+
'http://[2a00:f48:1008::212:183:10]:56?foo=bar', [
142+
'scheme' => 'http',
143+
'host' => '[2a00:f48:1008::212:183:10]',
144+
'port' => '56',
145+
'query' => 'foo=bar',
146+
],
147+
],
148+
];
149+
}
150+
151+
#[DataProvider('parseUrlProvider')]
152+
public function testParseUrl($url, $expected):void{
153+
$this::assertSame($expected, UriUtil::parseUrl($url));
154+
}
155+
130156
}

0 commit comments

Comments
 (0)