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