Skip to content

Commit eff4046

Browse files
committed
:octocat: extract URI related functions into class UriUtil
1 parent c1995d5 commit eff4046

File tree

4 files changed

+283
-253
lines changed

4 files changed

+283
-253
lines changed

src/UriUtil.php

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
<?php
2+
/**
3+
* Class UriUtils
4+
*
5+
* @created 22.10.2022
6+
* @author smiley <smiley@chillerlan.net>
7+
* @copyright 2022 smiley
8+
* @license MIT
9+
*/
10+
11+
namespace chillerlan\HTTP\Utils;
12+
13+
use Psr\Http\Message\UriInterface;
14+
use function array_filter, explode, implode, rawurldecode;
15+
16+
/**
17+
*
18+
*/
19+
final class UriUtil{
20+
21+
public const URI_DEFAULT_PORTS = [
22+
'http' => 80,
23+
'https' => 443,
24+
'ftp' => 21,
25+
'gopher' => 70,
26+
'nntp' => 119,
27+
'news' => 119,
28+
'telnet' => 23,
29+
'tn3270' => 23,
30+
'imap' => 143,
31+
'pop' => 110,
32+
'ldap' => 389,
33+
];
34+
35+
/**
36+
* Checks whether the UriInterface has a port set and if that port is one of the default ports for the given scheme
37+
*/
38+
public static function isDefaultPort(UriInterface $uri):bool{
39+
$port = $uri->getPort();
40+
$scheme = $uri->getScheme();
41+
42+
return $port === null || (isset(self::URI_DEFAULT_PORTS[$scheme]) && $port === self::URI_DEFAULT_PORTS[$scheme]);
43+
}
44+
45+
/**
46+
* Checks Whether the URI is absolute, i.e. it has a scheme.
47+
*
48+
* An instance of UriInterface can either be an absolute URI or a relative reference. This method returns true
49+
* if it is the former. An absolute URI has a scheme. A relative reference is used to express a URI relative
50+
* to another URI, the base URI. Relative references can be divided into several forms:
51+
* - network-path references, e.g. '//example.com/path'
52+
* - absolute-path references, e.g. '/path'
53+
* - relative-path references, e.g. 'subpath'
54+
*
55+
* @see Uri::isNetworkPathReference
56+
* @see Uri::isAbsolutePathReference
57+
* @see Uri::isRelativePathReference
58+
* @link https://tools.ietf.org/html/rfc3986#section-4
59+
*/
60+
public static function isAbsolute(UriInterface $uri):bool{
61+
return $uri->getScheme() !== '';
62+
}
63+
64+
/**
65+
* Checks Whether the URI is a network-path reference.
66+
*
67+
* A relative reference that begins with two slash characters is termed an network-path reference.
68+
*
69+
* @link https://tools.ietf.org/html/rfc3986#section-4.2
70+
*/
71+
public static function isNetworkPathReference(UriInterface $uri):bool{
72+
return $uri->getScheme() === '' && $uri->getAuthority() !== '';
73+
}
74+
75+
/**
76+
* Checks Whether the URI is a absolute-path reference.
77+
*
78+
* A relative reference that begins with a single slash character is termed an absolute-path reference.
79+
*
80+
* @link https://tools.ietf.org/html/rfc3986#section-4.2
81+
*/
82+
public static function isAbsolutePathReference(UriInterface $uri):bool{
83+
return $uri->getScheme() === '' && $uri->getAuthority() === '' && isset($uri->getPath()[0]) && $uri->getPath()[0] === '/';
84+
}
85+
86+
/**
87+
* Checks Whether the URI is a relative-path reference.
88+
*
89+
* A relative reference that does not begin with a slash character is termed a relative-path reference.
90+
*
91+
* @link https://tools.ietf.org/html/rfc3986#section-4.2
92+
*/
93+
public static function isRelativePathReference(UriInterface $uri):bool{
94+
return $uri->getScheme() === '' && $uri->getAuthority() === '' && (!isset($uri->getPath()[0]) || $uri->getPath()[0] !== '/');
95+
}
96+
97+
/**
98+
* Removes a specific query string value.
99+
*
100+
* Any existing query string values that exactly match the provided $key are removed.
101+
*/
102+
public static function withoutQueryValue(UriInterface $uri, string $key):UriInterface{
103+
$current = $uri->getQuery();
104+
105+
if($current === ''){
106+
return $uri;
107+
}
108+
109+
$decodedKey = rawurldecode($key);
110+
111+
$result = array_filter(explode('&', $current), function($part) use ($decodedKey){
112+
return rawurldecode(explode('=', $part)[0]) !== $decodedKey;
113+
});
114+
115+
return $uri->withQuery(implode('&', $result));
116+
}
117+
118+
/**
119+
* Adds a specific query string value.
120+
*
121+
* Any existing query string values that exactly match the provided $key are
122+
* removed and replaced with the given $key $value pair.
123+
*
124+
* A value of null will set the query string key without a value, e.g. "key" instead of "key=value".
125+
*/
126+
public static function withQueryValue(UriInterface $uri, string $key, string $value = null):UriInterface{
127+
$current = $uri->getQuery();
128+
129+
if($current === ''){
130+
$result = [];
131+
}
132+
else{
133+
$decodedKey = rawurldecode($key);
134+
$result = array_filter(explode('&', $current), function($part) use ($decodedKey){
135+
return rawurldecode(explode('=', $part)[0]) !== $decodedKey;
136+
});
137+
}
138+
139+
// Query string separators ("=", "&") within the key or value need to be encoded
140+
// (while preventing double-encoding) before setting the query string. All other
141+
// chars that need percent-encoding will be encoded by withQuery().
142+
$replaceQuery = ['=' => '%3D', '&' => '%26'];
143+
$key = strtr($key, $replaceQuery);
144+
145+
$result[] = $value !== null
146+
? $key.'='.strtr($value, $replaceQuery)
147+
: $key;
148+
149+
return $uri->withQuery(implode('&', $result));
150+
}
151+
152+
}

src/message_helpers.php

Lines changed: 1 addition & 135 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,7 @@
99
namespace chillerlan\HTTP\Utils;
1010

1111
use TypeError;
12-
use Psr\Http\Message\UriInterface;
13-
14-
use function array_filter, array_map, explode, implode, is_array, is_scalar, pathinfo, rawurldecode, rawurlencode, strtolower;
15-
12+
use function array_map, is_array, is_scalar, pathinfo, rawurlencode, strtolower;
1613
use const PATHINFO_EXTENSION;
1714

1815
const CHILLERLAN_PSR7_UTIL_INCLUDES = true;
@@ -157,134 +154,3 @@ function r_rawurlencode($data){
157154

158155
return rawurlencode((string)$data);
159156
}
160-
161-
const URI_DEFAULT_PORTS = [
162-
'http' => 80,
163-
'https' => 443,
164-
'ftp' => 21,
165-
'gopher' => 70,
166-
'nntp' => 119,
167-
'news' => 119,
168-
'telnet' => 23,
169-
'tn3270' => 23,
170-
'imap' => 143,
171-
'pop' => 110,
172-
'ldap' => 389,
173-
];
174-
175-
/**
176-
* Checks whether the UriInterface has a port set and if that port is one of the default ports for the given scheme
177-
*/
178-
function uriIsDefaultPort(UriInterface $uri):bool{
179-
$port = $uri->getPort();
180-
$scheme = $uri->getScheme();
181-
182-
return $port === null || (isset(URI_DEFAULT_PORTS[$scheme]) && $port === URI_DEFAULT_PORTS[$scheme]);
183-
}
184-
185-
/**
186-
* Checks Whether the URI is absolute, i.e. it has a scheme.
187-
*
188-
* An instance of UriInterface can either be an absolute URI or a relative reference. This method returns true
189-
* if it is the former. An absolute URI has a scheme. A relative reference is used to express a URI relative
190-
* to another URI, the base URI. Relative references can be divided into several forms:
191-
* - network-path references, e.g. '//example.com/path'
192-
* - absolute-path references, e.g. '/path'
193-
* - relative-path references, e.g. 'subpath'
194-
*
195-
* @see Uri::isNetworkPathReference
196-
* @see Uri::isAbsolutePathReference
197-
* @see Uri::isRelativePathReference
198-
* @link https://tools.ietf.org/html/rfc3986#section-4
199-
*/
200-
function uriIsAbsolute(UriInterface $uri):bool{
201-
return $uri->getScheme() !== '';
202-
}
203-
204-
/**
205-
* Checks Whether the URI is a network-path reference.
206-
*
207-
* A relative reference that begins with two slash characters is termed an network-path reference.
208-
*
209-
* @link https://tools.ietf.org/html/rfc3986#section-4.2
210-
*/
211-
function uriIsNetworkPathReference(UriInterface $uri):bool{
212-
return $uri->getScheme() === '' && $uri->getAuthority() !== '';
213-
}
214-
215-
/**
216-
* Checks Whether the URI is a absolute-path reference.
217-
*
218-
* A relative reference that begins with a single slash character is termed an absolute-path reference.
219-
*
220-
* @link https://tools.ietf.org/html/rfc3986#section-4.2
221-
*/
222-
function uriIsAbsolutePathReference(UriInterface $uri):bool{
223-
return $uri->getScheme() === '' && $uri->getAuthority() === '' && isset($uri->getPath()[0]) && $uri->getPath()[0] === '/';
224-
}
225-
226-
/**
227-
* Checks Whether the URI is a relative-path reference.
228-
*
229-
* A relative reference that does not begin with a slash character is termed a relative-path reference.
230-
*
231-
* @link https://tools.ietf.org/html/rfc3986#section-4.2
232-
*/
233-
function uriIsRelativePathReference(UriInterface $uri):bool{
234-
return $uri->getScheme() === '' && $uri->getAuthority() === '' && (!isset($uri->getPath()[0]) || $uri->getPath()[0] !== '/');
235-
}
236-
237-
/**
238-
* Removes a specific query string value.
239-
*
240-
* Any existing query string values that exactly match the provided $key are removed.
241-
*/
242-
function uriWithoutQueryValue(UriInterface $uri, string $key):UriInterface{
243-
$current = $uri->getQuery();
244-
245-
if($current === ''){
246-
return $uri;
247-
}
248-
249-
$decodedKey = rawurldecode($key);
250-
251-
$result = array_filter(explode('&', $current), function($part) use ($decodedKey){
252-
return rawurldecode(explode('=', $part)[0]) !== $decodedKey;
253-
});
254-
255-
return $uri->withQuery(implode('&', $result));
256-
}
257-
258-
/**
259-
* Adds a specific query string value.
260-
*
261-
* Any existing query string values that exactly match the provided $key are
262-
* removed and replaced with the given $key $value pair.
263-
*
264-
* A value of null will set the query string key without a value, e.g. "key" instead of "key=value".
265-
*/
266-
function uriWithQueryValue(UriInterface $uri, string $key, string $value = null):UriInterface{
267-
$current = $uri->getQuery();
268-
269-
if($current === ''){
270-
$result = [];
271-
}
272-
else{
273-
$decodedKey = rawurldecode($key);
274-
$result = array_filter(explode('&', $current), function($part) use ($decodedKey){
275-
return rawurldecode(explode('=', $part)[0]) !== $decodedKey;
276-
});
277-
}
278-
279-
// Query string separators ("=", "&") within the key or value need to be encoded
280-
// (while preventing double-encoding) before setting the query string. All other
281-
// chars that need percent-encoding will be encoded by withQuery().
282-
$replaceQuery = ['=' => '%3D', '&' => '%26'];
283-
$key = strtr($key, $replaceQuery);
284-
285-
$result[] = $value !== null
286-
? $key.'='.strtr($value, $replaceQuery)
287-
: $key;
288-
289-
return $uri->withQuery(implode('&', $result));
290-
}

0 commit comments

Comments
 (0)