1
|
|
|
<?php |
2
|
|
|
namespace DevOp\Core\Http; |
3
|
|
|
|
4
|
|
|
use Psr\Http\Message\UriInterface; |
5
|
|
|
|
6
|
|
|
class Uri implements UriInterface |
7
|
|
|
{ |
8
|
|
|
|
9
|
|
|
/** |
10
|
|
|
* @var array |
11
|
|
|
*/ |
12
|
|
|
private static $schemes = array( |
13
|
|
|
'http' => 80, |
14
|
|
|
'https' => 443 |
15
|
|
|
); |
16
|
|
|
|
17
|
|
|
/** |
18
|
|
|
* @var string|null |
19
|
|
|
*/ |
20
|
|
|
private $scheme; |
21
|
|
|
|
22
|
|
|
/** |
23
|
|
|
* @var string|null |
24
|
|
|
*/ |
25
|
|
|
private $userInfo; |
26
|
|
|
|
27
|
|
|
/** |
28
|
|
|
* @var string|null |
29
|
|
|
*/ |
30
|
|
|
private $host; |
31
|
|
|
|
32
|
|
|
/** |
33
|
|
|
* @var int|null |
34
|
|
|
*/ |
35
|
|
|
private $port; |
36
|
|
|
|
37
|
|
|
/** |
38
|
|
|
* @var string |
39
|
|
|
*/ |
40
|
|
|
private $path = ''; |
41
|
|
|
|
42
|
|
|
/** |
43
|
|
|
* @var string|null |
44
|
|
|
*/ |
45
|
|
|
private $query; |
46
|
|
|
|
47
|
|
|
/** |
48
|
|
|
* @var string|null |
49
|
|
|
*/ |
50
|
|
|
private $fragment; |
51
|
|
|
|
52
|
|
|
/** |
53
|
|
|
* @param UriInterface|string $uri |
54
|
|
|
* @return UriInterface |
55
|
|
|
*/ |
56
|
100 |
|
public function __construct($uri = '') |
57
|
|
|
{ |
58
|
|
|
|
59
|
100 |
|
if ($uri instanceof UriInterface) { |
60
|
|
|
return $uri; |
61
|
|
|
} |
62
|
|
|
|
63
|
100 |
|
$parseUrl = parse_url($uri); |
64
|
100 |
|
if (!$parseUrl) { |
|
|
|
|
65
|
2 |
|
throw new \InvalidArgumentException; |
66
|
|
|
} |
67
|
|
|
|
68
|
98 |
|
$components = array_merge(array( |
69
|
98 |
|
'scheme' => '', |
70
|
|
|
'host' => '', |
71
|
|
|
'port' => null, |
72
|
|
|
'user' => null, |
73
|
|
|
'pass' => null, |
74
|
|
|
'path' => '', |
75
|
|
|
'query' => null, |
76
|
|
|
'fragment' => null |
77
|
98 |
|
), $parseUrl); |
78
|
|
|
|
79
|
98 |
|
$this->scheme = $components['scheme']; |
80
|
98 |
|
$this->host = $components['host']; |
81
|
98 |
|
$this->port = $this->isStandartPort($components['port']); |
82
|
98 |
|
$this->path = $components['path']; |
83
|
98 |
|
$this->query = $components['query']; |
84
|
98 |
|
$this->fragment = $components['fragment']; |
85
|
98 |
|
$this->userInfo = implode(':', array_filter([$components['user'], $components['pass']])); |
86
|
98 |
|
} |
87
|
|
|
|
88
|
|
|
/** |
89
|
|
|
* @param int $port |
90
|
|
|
* @return int|null |
91
|
|
|
*/ |
92
|
98 |
|
public function isStandartPort($port) |
93
|
|
|
{ |
94
|
98 |
|
if (!in_array($port, [self::$schemes['http'], self::$schemes['https']])) { |
95
|
98 |
|
return $port; |
96
|
|
|
} |
97
|
|
|
return null; |
98
|
|
|
} |
99
|
|
|
|
100
|
|
|
/** |
101
|
|
|
* @return string |
102
|
|
|
*/ |
103
|
52 |
|
public function __toString() |
104
|
|
|
{ |
105
|
52 |
|
$uri = $this->scheme; |
106
|
|
|
|
107
|
52 |
|
if ($this->userInfo !== null) { |
108
|
52 |
|
$uri .= "://{$this->userInfo}"; |
109
|
|
|
} |
110
|
|
|
|
111
|
52 |
|
$uri .= $this->host; |
112
|
|
|
|
113
|
52 |
|
if ($this->port !== null && !in_array($this->port, [self::$schemes['http'], self::$schemes['https']])) { |
114
|
|
|
$uri .= ":{$this->host}{$this->port}"; |
115
|
|
|
} |
116
|
|
|
|
117
|
52 |
|
$uri .= $this->path; |
118
|
|
|
|
119
|
52 |
|
if ($this->query !== null) { |
120
|
36 |
|
$uri .= "?{$this->query}"; |
121
|
|
|
} |
122
|
|
|
|
123
|
52 |
|
if ($this->fragment !== null) { |
124
|
|
|
$uri .= "#{$this->fragment}"; |
125
|
|
|
} |
126
|
|
|
|
127
|
52 |
|
return $uri; |
128
|
|
|
} |
129
|
|
|
|
130
|
|
|
/** |
131
|
|
|
* @return string |
132
|
|
|
*/ |
133
|
|
|
public function getAuthority() |
134
|
|
|
{ |
135
|
|
|
return ($this->userInfo ?: $this->userInfo) . $this->host . ($this->port ?: ":{$this->port}"); |
136
|
|
|
} |
137
|
|
|
|
138
|
|
|
/** |
139
|
|
|
* @return string |
140
|
|
|
*/ |
141
|
2 |
|
public function getFragment() |
142
|
|
|
{ |
143
|
2 |
|
return $this->fragment; |
144
|
|
|
} |
145
|
|
|
|
146
|
|
|
/** |
147
|
|
|
* @return string |
148
|
|
|
*/ |
149
|
86 |
|
public function getHost() |
150
|
|
|
{ |
151
|
86 |
|
return $this->host; |
152
|
|
|
} |
153
|
|
|
|
154
|
|
|
/** |
155
|
|
|
* @return string |
156
|
|
|
*/ |
157
|
4 |
|
public function getPath() |
158
|
|
|
{ |
159
|
4 |
|
return $this->path; |
160
|
|
|
} |
161
|
|
|
|
162
|
|
|
/** |
163
|
|
|
* @return null|int |
164
|
|
|
*/ |
165
|
4 |
|
public function getPort() |
166
|
|
|
{ |
167
|
4 |
|
return $this->port; |
168
|
|
|
} |
169
|
|
|
|
170
|
|
|
/** |
171
|
|
|
* @return string |
172
|
|
|
*/ |
173
|
4 |
|
public function getQuery() |
174
|
|
|
{ |
175
|
4 |
|
return $this->query; |
176
|
|
|
} |
177
|
|
|
|
178
|
|
|
/** |
179
|
|
|
* @return string |
180
|
|
|
*/ |
181
|
4 |
|
public function getScheme() |
182
|
|
|
{ |
183
|
4 |
|
return $this->scheme; |
184
|
|
|
} |
185
|
|
|
|
186
|
|
|
/** |
187
|
|
|
* @return string |
188
|
|
|
*/ |
189
|
4 |
|
public function getUserInfo() |
190
|
|
|
{ |
191
|
4 |
|
return $this->userInfo; |
192
|
|
|
} |
193
|
|
|
|
194
|
|
|
/** |
195
|
|
|
* @param string $fragment |
196
|
|
|
* @return self |
197
|
|
|
*/ |
198
|
|
|
public function withFragment($fragment) |
199
|
|
|
{ |
200
|
|
|
if ($fragment === $this->fragment) { |
201
|
|
|
return $this; |
202
|
|
|
} |
203
|
|
|
|
204
|
|
|
$clone = clone $this; |
205
|
|
|
$clone->fragment = $fragment; |
206
|
|
|
|
207
|
|
|
return $clone; |
208
|
|
|
} |
209
|
|
|
|
210
|
|
|
/** |
211
|
|
|
* @param string $host |
212
|
|
|
* @return self |
213
|
|
|
*/ |
214
|
16 |
|
public function withHost($host) |
215
|
|
|
{ |
216
|
16 |
|
if ($host === $this->host) { |
217
|
|
|
return $this; |
218
|
|
|
} |
219
|
|
|
|
220
|
16 |
|
$clone = clone $this; |
221
|
16 |
|
$clone->host = $host; |
222
|
|
|
|
223
|
16 |
|
return $clone; |
224
|
|
|
} |
225
|
|
|
|
226
|
|
|
/** |
227
|
|
|
* @param string $path |
228
|
|
|
* @return self |
229
|
|
|
*/ |
230
|
16 |
|
public function withPath($path) |
231
|
|
|
{ |
232
|
16 |
|
if ($path === $this->path) { |
233
|
|
|
return $this; |
234
|
|
|
} |
235
|
|
|
|
236
|
16 |
|
$clone = clone $this; |
237
|
16 |
|
$clone->path = $path; |
238
|
|
|
|
239
|
16 |
|
return $clone; |
240
|
|
|
} |
241
|
|
|
|
242
|
|
|
/** |
243
|
|
|
* @param int $port |
244
|
|
|
* @return self |
245
|
|
|
*/ |
246
|
2 |
|
public function withPort($port) |
247
|
|
|
{ |
248
|
2 |
|
if ($port === $this->port) { |
249
|
|
|
return $this; |
250
|
|
|
} |
251
|
|
|
|
252
|
2 |
|
$clone = clone $this; |
253
|
2 |
|
$clone->port = (int) $port; |
254
|
|
|
|
255
|
2 |
|
return $clone; |
256
|
|
|
} |
257
|
|
|
|
258
|
|
|
/** |
259
|
|
|
* @param string $query |
260
|
|
|
* @return self |
261
|
|
|
*/ |
262
|
16 |
|
public function withQuery($query) |
263
|
|
|
{ |
264
|
16 |
|
if ($query === $this->query) { |
265
|
|
|
return $this; |
266
|
|
|
} |
267
|
|
|
|
268
|
16 |
|
$clone = clone $this; |
269
|
16 |
|
$clone->query = $query; |
270
|
|
|
|
271
|
16 |
|
return $clone; |
272
|
|
|
} |
273
|
|
|
|
274
|
|
|
/** |
275
|
|
|
* @param string $scheme |
276
|
|
|
* @return self |
277
|
|
|
*/ |
278
|
16 |
|
public function withScheme($scheme) |
279
|
|
|
{ |
280
|
16 |
|
if ($scheme === $this->scheme) { |
281
|
|
|
return $this; |
282
|
|
|
} |
283
|
|
|
|
284
|
16 |
|
$clone = clone $this; |
285
|
16 |
|
$clone->scheme = $scheme; |
286
|
|
|
|
287
|
16 |
|
return $clone; |
288
|
|
|
} |
289
|
|
|
|
290
|
|
|
/** |
291
|
|
|
* @param string $user |
292
|
|
|
* @param string|null $password |
293
|
|
|
* @return self |
294
|
|
|
*/ |
295
|
2 |
|
public function withUserInfo($user, $password = null) |
296
|
|
|
{ |
297
|
2 |
|
$userInfo = $user; |
298
|
2 |
|
if (null !== $password) { |
299
|
|
|
$userInfo .= ":{$password}"; |
300
|
|
|
} |
301
|
|
|
|
302
|
2 |
|
if ($userInfo === $this->userInfo) { |
303
|
|
|
return $this; |
304
|
|
|
} |
305
|
|
|
|
306
|
2 |
|
$clone = clone $this; |
307
|
2 |
|
$clone->userInfo = $userInfo; |
308
|
|
|
|
309
|
2 |
|
return $clone; |
310
|
|
|
} |
311
|
|
|
} |
312
|
|
|
|
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.