1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace vakata\http; |
4
|
|
|
|
5
|
|
|
use Zend\Diactoros\Uri as ZendUri; |
6
|
|
|
use Zend\Diactoros\Stream; |
7
|
|
|
use Zend\Diactoros\UploadedFile; |
8
|
|
|
use Zend\Diactoros\ServerRequest; |
9
|
|
|
use Zend\Diactoros\ServerRequestFactory; |
10
|
|
|
|
11
|
|
|
class Request extends ServerRequest |
12
|
|
|
{ |
13
|
|
|
/** |
14
|
|
|
* Create an instance from globals |
15
|
|
|
* |
16
|
|
|
* @param array $server |
17
|
|
|
* @param array $query |
18
|
|
|
* @param array $body |
19
|
|
|
* @param array $cookies |
20
|
|
|
* @param array $files |
21
|
|
|
* @return Request |
22
|
|
|
*/ |
23
|
|
|
public static function fromGlobals( |
24
|
|
|
array $server = null, |
25
|
|
|
array $query = null, |
26
|
|
|
array $body = null, |
27
|
|
|
array $cookies = null, |
28
|
|
|
array $files = null |
29
|
|
|
) { |
30
|
|
|
$server = \Zend\Diactoros\normalizeServer($server ?: $_SERVER); |
31
|
|
|
$files = \Zend\Diactoros\normalizeUploadedFiles($files ?: $_FILES); |
32
|
|
|
$headers = \Zend\Diactoros\marshalHeadersFromSapi($server); |
33
|
|
|
|
34
|
|
|
if (null === $cookies && array_key_exists('cookie', $headers)) { |
35
|
|
|
$cookies = self::parseCookieHeader($headers['cookie']); |
36
|
|
|
} |
37
|
|
|
$uri = \Zend\Diactoros\marshalUriFromSapi($server, $headers); |
38
|
|
|
|
39
|
|
|
if ($body === null) { |
40
|
|
|
$body = []; |
41
|
|
|
if (isset($headers['content-type']) && strpos($headers['content-type'], 'json') !== false) { |
42
|
|
|
$body = json_decode($body, true); |
43
|
|
|
if ($body === null) { |
44
|
|
|
$body = []; |
45
|
|
|
} |
46
|
|
|
} else { |
47
|
|
|
$body = static::fixedQueryParams(file_get_contents('php://input')); |
48
|
|
|
} |
49
|
|
|
} |
50
|
|
|
|
51
|
|
|
return new static( |
52
|
|
|
$server, |
53
|
|
|
$files, |
54
|
|
|
$uri, |
55
|
|
|
ServerRequestFactory::get('REQUEST_METHOD', $server, 'GET'), |
|
|
|
|
56
|
|
|
'php://input', |
57
|
|
|
$headers, |
58
|
|
|
$cookies ?: $_COOKIE, |
59
|
|
|
$query ?: static::fixedQueryParams($uri->getQuery()), |
60
|
|
|
$body ?: (count($_POST) ? $_POST : json_decode(file_get_contents('php://input'), true)), |
61
|
|
|
\Zend\Diactoros\marshalProtocolVersionFromSapi($server) |
62
|
|
|
); |
63
|
|
|
} |
64
|
1 |
|
public static function fromString(string $str) : Request |
65
|
|
|
{ |
66
|
1 |
|
$method = 'GET'; |
67
|
1 |
|
$version = '1.1'; |
68
|
1 |
|
$uri = '/'; |
69
|
1 |
|
$headers = []; |
70
|
1 |
|
$files = []; |
71
|
1 |
|
$body = ''; |
72
|
|
|
|
73
|
1 |
|
$break = strpos($str, "\r\n\r\n") === false ? "\n" : "\r\n"; // just in case someone breaks RFC 2616 |
74
|
|
|
|
75
|
1 |
|
list($headers, $message) = array_pad(explode($break . $break, $str, 2), 2, ''); |
76
|
1 |
|
$headers = explode($break, preg_replace("(" . $break . "\s+)", " ", $headers)); |
77
|
1 |
|
if (isset($headers[0]) && strlen($headers[0])) { |
78
|
1 |
|
$temp = explode(' ', $headers[0]); |
79
|
1 |
|
if (in_array($temp[0], ['GET', 'POST', 'HEAD', 'PATCH', 'PUT', 'OPTIONS', 'TRACE', 'DELETE'])) { |
80
|
1 |
|
$method = $temp[0]; |
81
|
1 |
|
$uri = $temp[1]; |
82
|
1 |
|
if (isset($temp[2])) { |
83
|
1 |
|
$version = substr($temp[2], 5); |
84
|
|
|
} |
85
|
1 |
|
unset($headers[0]); |
86
|
1 |
|
$headers = array_values($headers); |
87
|
|
|
} |
88
|
|
|
} |
89
|
1 |
|
$temp = array_filter($headers); |
90
|
1 |
|
$headers = []; |
91
|
1 |
|
foreach ($temp as $v) { |
92
|
1 |
|
$v = explode(':', $v, 2); |
93
|
1 |
|
$name = trim($v[0]); |
94
|
1 |
|
$name = str_replace('_', ' ', strtolower($name)); |
95
|
1 |
|
$name = str_replace('-', ' ', strtolower($name)); |
96
|
1 |
|
$name = str_replace(' ', '-', ucwords($name)); |
97
|
1 |
|
$headers[$name] = trim($v[1]); |
98
|
|
|
} |
99
|
1 |
|
if (isset($headers['Host'])) { |
100
|
|
|
$uri = $headers['Host'] . $uri; |
101
|
|
|
} else { |
102
|
1 |
|
$uri = 'localhost' . $uri; |
103
|
|
|
} |
104
|
1 |
|
if (isset($headers['Content-Type']) && strpos($headers['Content-Type'], 'multipart') !== false) { |
105
|
|
|
$bndr = trim(explode(' boundary=', $headers['Content-Type'])[1], '"'); |
106
|
|
|
$parts = explode($break . '--' . $bndr, $break . $message); |
107
|
|
|
if (count($parts) == 1) { |
108
|
|
|
$body = $message; |
109
|
|
|
} else { |
110
|
|
|
array_pop($parts); |
111
|
|
|
array_shift($parts); |
112
|
|
|
$post = []; |
113
|
|
|
$fres = []; |
114
|
|
|
foreach ($parts as $k => $item) { |
115
|
|
|
list($head, $pbody) = explode($break . $break, $item, 2); |
116
|
|
|
$head = explode($break, preg_replace("(" . $break . "\s+)", " ", $head)); |
117
|
|
|
foreach ($head as $h) { |
118
|
|
|
if (strpos(strtolower($h), 'content-disposition') === 0) { |
119
|
|
|
$cd = explode(';', $h); |
120
|
|
|
$name = ''; |
121
|
|
|
$file = ''; |
122
|
|
|
foreach ($cd as $p) { |
123
|
|
|
if (strpos(trim($p), 'name=') === 0) { |
124
|
|
|
$name = trim(explode('name=', $p)[1], ' "'); |
125
|
|
|
} |
126
|
|
|
if (strpos(trim($p), 'filename=') === 0) { |
127
|
|
|
$file = trim(explode('filename=', $p)[1], ' "'); |
128
|
|
|
} |
129
|
|
|
} |
130
|
|
|
if ($file) { |
131
|
|
|
// create resource manually |
132
|
|
|
$fres[$k] = fopen('php://temp', 'wb+'); |
133
|
|
|
fwrite($fres[$k], $pbody); |
134
|
|
|
rewind($fres[$k]); |
135
|
|
|
$files[$name] = new UploadedFile( |
136
|
|
|
$fres[$k], |
137
|
|
|
strlen($pbody), |
138
|
|
|
UPLOAD_ERR_OK, |
139
|
|
|
$file |
140
|
|
|
); |
141
|
|
|
} else { |
142
|
|
|
$post[$name] = $pbody; |
143
|
|
|
} |
144
|
|
|
} |
145
|
|
|
} |
146
|
|
|
} |
147
|
|
|
$body = http_build_query($post); |
148
|
|
|
} |
149
|
1 |
|
} elseif (strlen($message)) { |
150
|
|
|
$body = $message; |
151
|
|
|
} |
152
|
1 |
|
if (strpos($uri, '://') === false) { |
153
|
1 |
|
$uri = 'http://' . $uri; |
154
|
|
|
} |
155
|
|
|
|
156
|
1 |
|
if (isset($headers['Content-Type']) && strpos($headers['Content-Type'], 'json') !== false) { |
157
|
|
|
$params = json_decode($body, true); |
158
|
|
|
} else { |
159
|
1 |
|
$params = static::fixedQueryParams($body); |
160
|
|
|
} |
161
|
1 |
|
$temp = (new Stream('php://temp', 'wb+')); |
162
|
1 |
|
$temp->write($body); |
163
|
1 |
|
$uri = new ZendUri($uri); |
164
|
1 |
|
return new static( |
165
|
1 |
|
[], |
166
|
1 |
|
\Zend\Diactoros\normalizeUploadedFiles($files), |
167
|
1 |
|
$uri, |
168
|
1 |
|
$method, |
169
|
1 |
|
$temp, |
170
|
1 |
|
$headers, |
171
|
1 |
|
isset($headers['Cookie']) ? self::parseCookieHeader($headers['Cookie']) : [], |
172
|
1 |
|
static::fixedQueryParams($uri->getQuery()), |
173
|
1 |
|
$params ?? [], |
174
|
1 |
|
$version |
175
|
|
|
); |
176
|
|
|
} |
177
|
2 |
|
public static function fixedQueryParams($query) |
178
|
|
|
{ |
179
|
2 |
|
$data = []; |
180
|
2 |
|
$temp = strlen($query) ? explode('&', $query) : []; |
181
|
2 |
|
foreach ($temp as $var) { |
182
|
2 |
|
$var = explode('=', $var, 2); |
183
|
2 |
|
$name = urldecode($var[0]); |
184
|
2 |
|
$value = isset($var[1]) ? urldecode($var[1]) : ''; |
185
|
2 |
|
$name = explode(']', str_replace(['][', '['], ']', $name)); |
186
|
2 |
|
$name = count($name) > 1 ? array_slice($name, 0, -1) : $name; |
187
|
|
|
|
188
|
2 |
|
$tmp = &$data; |
189
|
2 |
|
foreach ($name as $k) { |
190
|
2 |
|
if ($k === "") { |
191
|
|
|
continue; |
192
|
|
|
} |
193
|
2 |
|
if (!isset($tmp[$k])) { |
194
|
2 |
|
$tmp[$k] = []; |
195
|
|
|
} |
196
|
2 |
|
$tmp = &$tmp[$k]; |
197
|
|
|
} |
198
|
2 |
|
if ($name[count($name) - 1] == '') { |
199
|
|
|
$tmp[] = $value; |
200
|
|
|
} else { |
201
|
2 |
|
$tmp = $value; |
202
|
|
|
} |
203
|
|
|
} |
204
|
2 |
|
return $data; |
205
|
|
|
} |
206
|
1 |
|
private static function parseCookieHeader($cookieHeader) |
207
|
|
|
{ |
208
|
1 |
|
preg_match_all('( |
209
|
|
|
(?:^\\n?[ \t]*|;[ ]) |
210
|
|
|
(?P<name>[!#$%&\'*+-.0-9A-Z^_`a-z|~]+) |
211
|
|
|
= |
212
|
|
|
(?P<DQUOTE>"?) |
213
|
|
|
(?P<value>[\x21\x23-\x2b\x2d-\x3a\x3c-\x5b\x5d-\x7e]*) |
214
|
|
|
(?P=DQUOTE) |
215
|
|
|
(?=\\n?[ \t]*$|;[ ]) |
216
|
1 |
|
)x', $cookieHeader, $matches, PREG_SET_ORDER); |
217
|
|
|
|
218
|
1 |
|
$cookies = []; |
219
|
|
|
|
220
|
1 |
|
if (is_array($matches)) { |
221
|
1 |
|
foreach ($matches as $match) { |
222
|
1 |
|
$cookies[$match['name']] = urldecode($match['value']); |
223
|
|
|
} |
224
|
|
|
} |
225
|
|
|
|
226
|
1 |
|
return $cookies; |
227
|
|
|
} |
228
|
1 |
|
public function __construct( |
229
|
|
|
array $serverParams = [], |
230
|
|
|
array $uploadedFiles = [], |
231
|
|
|
$uri = null, |
232
|
|
|
$method = null, |
233
|
|
|
$body = 'php://input', |
234
|
|
|
array $headers = [], |
235
|
|
|
array $cookies = [], |
236
|
|
|
array $queryParams = [], |
237
|
|
|
$parsedBody = null, |
238
|
|
|
$protocol = '1.1' |
239
|
|
|
) { |
240
|
1 |
|
$uri = new Uri((string)$uri); |
241
|
1 |
|
parent::__construct( |
242
|
1 |
|
$serverParams, |
243
|
1 |
|
$uploadedFiles, |
244
|
1 |
|
$uri, |
245
|
1 |
|
$method, |
246
|
1 |
|
$body, |
247
|
1 |
|
$headers, |
248
|
1 |
|
$cookies, |
249
|
1 |
|
$queryParams, |
250
|
1 |
|
$parsedBody, |
251
|
1 |
|
$protocol |
252
|
|
|
); |
253
|
1 |
|
} |
254
|
1 |
|
protected function cleanValue($value, $mode = null) |
255
|
|
|
{ |
256
|
1 |
|
if (is_array($value)) { |
257
|
|
|
$temp = []; |
258
|
|
|
foreach ($value as $k => $v) { |
259
|
|
|
$temp[$k] = $this->cleanValue($v, $mode); |
260
|
|
|
} |
261
|
|
|
return $temp; |
262
|
|
|
} |
263
|
|
|
// normalize newlines |
264
|
1 |
|
if (strpos((string)$value, "\r") !== false) { |
265
|
|
|
$value = str_replace(array("\r\n", "\r", "\r\n\n"), PHP_EOL, $value); |
266
|
|
|
} |
267
|
|
|
// remove invalid utf8 chars |
268
|
1 |
|
if (preg_match('/[^\x00-\x7F]/S', $value) != 0) { |
269
|
|
|
$temp = @iconv('UTF-8', 'UTF-8//IGNORE', $value); |
270
|
|
|
if ($temp !== false) { |
271
|
|
|
$value = $temp; |
272
|
|
|
} |
273
|
|
|
} |
274
|
|
|
// remove non-printable chars |
275
|
|
|
do { |
276
|
1 |
|
$count = 0; |
277
|
1 |
|
$value = preg_replace(['/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]+/S'], '', $value, -1, $count); |
278
|
1 |
|
} while ((int)$count > 0); |
279
|
|
|
|
280
|
|
|
switch ($mode) { |
281
|
1 |
|
case 'int': |
282
|
1 |
|
$value = (int) $value; |
283
|
1 |
|
break; |
284
|
1 |
|
case 'float': |
285
|
|
|
$value = (float) $value; |
286
|
|
|
break; |
287
|
1 |
|
case 'nohtml': |
288
|
|
|
$value = strip_tags((string) $value); |
289
|
|
|
break; |
290
|
1 |
|
case 'escape': |
291
|
|
|
$value = htmlspecialchars((string) $value, ENT_QUOTES | ENT_SUBSTITUTE); |
292
|
|
|
break; |
293
|
1 |
|
case 'string': |
294
|
|
|
$value = (string) $value; |
295
|
|
|
break; |
296
|
1 |
|
case 'raw': |
297
|
|
|
default: |
298
|
1 |
|
break; |
299
|
|
|
} |
300
|
|
|
|
301
|
1 |
|
return $value; |
302
|
|
|
} |
303
|
1 |
|
protected function getValue(array $collection, $key, $default, $mode) |
304
|
|
|
{ |
305
|
1 |
|
if ($key === null) { |
306
|
|
|
return $this->cleanValue($collection, $mode); |
307
|
|
|
} |
308
|
1 |
|
return isset($collection[$key]) ? $this->cleanValue($collection[$key], $mode) : $default; |
309
|
|
|
} |
310
|
|
|
/** |
311
|
|
|
* Gets a value from a cookie that came with the request |
312
|
|
|
* @param string $key the cookie name |
313
|
|
|
* @param mixed $default optional default value to return if the key is not present (default to `null`) |
314
|
|
|
* @param string $mode optional cleanup of the value, available modes are: int, float, nohtml, escape, string |
315
|
|
|
* @return mixed the value (or values) |
316
|
|
|
*/ |
317
|
1 |
|
public function getCookie($key = null, $default = null, $mode = null) |
318
|
|
|
{ |
319
|
1 |
|
return $this->getValue($this->getCookieParams(), $key, $default, $mode); |
320
|
|
|
} |
321
|
|
|
/** |
322
|
|
|
* Get a GET param from the request URL |
323
|
|
|
* @param string $key the GET param name |
324
|
|
|
* @param mixed $default optional default value to return if the key is not present (default to `null`) |
325
|
|
|
* @param string $mode optional cleanup of the value, available modes are: int, float, nohtml, escape, string |
326
|
|
|
* @return mixed the value (or values) |
327
|
|
|
*/ |
328
|
1 |
|
public function getQuery($key = null, $default = null, $mode = null) |
329
|
|
|
{ |
330
|
1 |
|
return $this->getValue($this->getQueryParams(), $key, $default, $mode); |
331
|
|
|
} |
332
|
|
|
/** |
333
|
|
|
* Get a param from the request body (if it is in JSON format it will be parsed out as well) |
334
|
|
|
* @param string $key the param name |
335
|
|
|
* @param mixed $default optional default value to return if the key is not present (default to `null`) |
336
|
|
|
* @param string $mode optional cleanup of the value, available modes are: int, float, nohtml, escape, string |
337
|
|
|
* @return mixed the value (or values if no key was specified) |
338
|
|
|
*/ |
339
|
|
|
public function getPost($key = null, $default = null, $mode = null) |
340
|
|
|
{ |
341
|
|
|
$body = $this->getParsedBody(); |
342
|
|
|
if (!is_array($body)) { |
343
|
|
|
$body = []; |
344
|
|
|
} |
345
|
|
|
return $this->getValue($body, $key, $default, $mode); |
346
|
|
|
} |
347
|
|
|
/** |
348
|
|
|
* Get any authorization details supplied with the request. |
349
|
|
|
* @return array|null array of extracted values or null (possible keys are username, password and token) |
350
|
|
|
*/ |
351
|
|
|
public function getAuthorization() |
352
|
|
|
{ |
353
|
|
|
if (!$this->hasHeader('Authorization')) { |
354
|
|
|
return null; |
355
|
|
|
} |
356
|
|
|
$temp = explode(' ', trim($this->getHeaderLine('Authorization')), 2); |
357
|
|
|
switch (strtolower($temp[0])) { |
358
|
|
|
case 'basic': |
359
|
|
|
$temp[1] = base64_decode($temp[1]); |
360
|
|
|
$temp[1] = explode(':', $temp[1], 2); |
361
|
|
|
return ['username' => $temp[1][0], 'password' => $temp[1][1] ?? null]; |
362
|
|
|
case 'token': |
363
|
|
|
case 'oauth': |
364
|
|
|
case 'bearer': |
365
|
|
|
return ['token' => $temp[1] ?? null]; |
366
|
|
|
default: |
367
|
|
|
return null; |
368
|
|
|
} |
369
|
|
|
} |
370
|
|
|
public function getUrl() |
371
|
|
|
{ |
372
|
|
|
return $this->getUri(); |
373
|
|
|
} |
374
|
|
|
/** |
375
|
|
|
* Determine if this is an AJAX request |
376
|
|
|
* @return boolean is the request AJAX |
377
|
|
|
*/ |
378
|
1 |
|
public function isAjax() |
379
|
|
|
{ |
380
|
1 |
|
return ($this->getHeaderLine('X-Requested-With') === 'XMLHttpRequest'); |
381
|
|
|
} |
382
|
|
|
/** |
383
|
|
|
* Determine if this is an CORS request |
384
|
|
|
* @return boolean is the request CORS |
385
|
|
|
*/ |
386
|
1 |
|
public function isCors() |
387
|
|
|
{ |
388
|
1 |
|
if (!$this->hasHeader('Origin')) { |
389
|
1 |
|
return false; |
390
|
|
|
} |
391
|
|
|
$origin = parse_url($this->getHeaderLine('Origin')); |
392
|
|
|
$host = $this->getUri()->getHost(); |
393
|
|
|
$scheme = $this->getUri()->getScheme(); |
394
|
|
|
return ( |
395
|
|
|
!$host || |
396
|
|
|
strtolower($origin['scheme']?? '') !== strtolower($scheme) || |
397
|
|
|
strpos(strtolower($origin['host'] ?? ''), strtolower($host)) === false |
398
|
|
|
); |
399
|
|
|
} |
400
|
|
|
/** |
401
|
|
|
* Get the prefered response languages (parses the Accept-Language header if present). |
402
|
|
|
* @param bool $shortNames should values like "en-US", be truncated to "en", defaults to true |
403
|
|
|
* @return array array of ordered lowercase language codes |
404
|
|
|
*/ |
405
|
1 |
|
public function getPreferredResponseLanguages(bool $shortNames = true) : array |
406
|
|
|
{ |
407
|
1 |
|
$acpt = $this->getHeaderLine('Accept-Language') ?: '*'; |
408
|
1 |
|
$acpt = explode(',', $acpt); |
409
|
1 |
|
foreach ($acpt as $k => $v) { |
410
|
1 |
|
$v = array_pad(explode(';', $v, 2), 2, 'q=1'); |
411
|
1 |
|
$v[1] = (float) array_pad(explode('q=', $v[1], 2), 2, '1')[1]; |
412
|
1 |
|
$v[0] = $shortNames ? explode('-', $v[0], 2)[0] : $v[0]; |
413
|
1 |
|
$v[2] = $k; |
414
|
1 |
|
$acpt[$k] = $v; |
415
|
|
|
} |
416
|
|
|
usort($acpt, function ($a, $b) { |
417
|
1 |
|
if ($a[1] > $b[1]) { |
418
|
1 |
|
return -1; |
419
|
|
|
} |
420
|
|
|
if ($a[1] < $b[1]) { |
421
|
|
|
return 1; |
422
|
|
|
} |
423
|
|
|
return $a[2] < $b[2] ? -1 : 1; |
424
|
1 |
|
}); |
425
|
|
|
$acpt = array_map(function ($v) { |
426
|
1 |
|
return strtolower($v[0]); |
427
|
1 |
|
}, $acpt); |
428
|
|
|
$acpt = array_filter($acpt, function ($v) { |
429
|
1 |
|
return $v !== '*'; |
430
|
1 |
|
}); |
431
|
1 |
|
return array_unique($acpt); |
432
|
|
|
} |
433
|
|
|
/** |
434
|
|
|
* Get the preffered response language (parses the Accept-Language header if present). |
435
|
|
|
* @param string $default the default code to return if the header is not found |
436
|
|
|
* @param array|null $allowed an optional list of lowercase language codes to intersect with, defaults to null |
437
|
|
|
* @return string the prefered language code |
438
|
|
|
*/ |
439
|
1 |
|
public function getPreferredResponseLanguage(string $default = 'en', array $allowed = null) : string |
440
|
|
|
{ |
441
|
1 |
|
$acpt = $this->getPreferredResponseLanguages(true); |
442
|
1 |
|
foreach ($acpt as $lang) { |
443
|
1 |
|
if ($allowed === null) { |
444
|
1 |
|
return $lang; |
445
|
|
|
} |
446
|
|
|
if (in_array($lang, $allowed)) { |
447
|
|
|
return $lang; |
448
|
|
|
} |
449
|
|
|
} |
450
|
1 |
|
return $default; |
451
|
|
|
} |
452
|
|
|
/** |
453
|
|
|
* Get the prefered response formats. |
454
|
|
|
* @param string $default the default value to return if the Accept header is not present. |
455
|
|
|
* @return string[] the desired response formats |
456
|
|
|
*/ |
457
|
1 |
|
public function getPreferredResponseFormats($default = 'text/html') |
458
|
|
|
{ |
459
|
|
|
// parse accept header (uses default instead of 406 header) |
460
|
1 |
|
$acpt = $this->getHeaderLine('Accept') ?: $default; |
461
|
1 |
|
$acpt = explode(',', $acpt); |
462
|
1 |
|
foreach ($acpt as $k => $v) { |
463
|
1 |
|
$v = array_pad(explode(';', $v, 2), 2, 'q=1'); |
464
|
1 |
|
$v[1] = (float) array_pad(explode('q=', $v[1], 2), 2, '1')[1]; |
465
|
1 |
|
$v[0] = $v[0]; |
466
|
1 |
|
$v[2] = $k; |
467
|
1 |
|
$acpt[$k] = $v; |
468
|
|
|
} |
469
|
|
|
usort($acpt, function ($a, $b) { |
470
|
1 |
|
if ($a[1] > $b[1]) { |
471
|
1 |
|
return -1; |
472
|
|
|
} |
473
|
1 |
|
if ($a[1] < $b[1]) { |
474
|
|
|
return 1; |
475
|
|
|
} |
476
|
1 |
|
return $a[2] < $b[2] ? -1 : 1; |
477
|
1 |
|
}); |
478
|
|
|
$acpt = array_map(function ($v) { |
479
|
1 |
|
return strtolower($v[0]); |
480
|
1 |
|
}, $acpt); |
481
|
1 |
|
$acpt = array_filter($acpt, function ($v) { |
482
|
1 |
|
return $v !== '*/*'; |
483
|
1 |
|
}); |
484
|
1 |
|
return array_unique($acpt); |
485
|
|
|
} |
486
|
|
|
/** |
487
|
|
|
* Get the preffered response language (parses the Accept-Language header if present). |
488
|
|
|
* @param string $default the default code to return if the header is not found |
489
|
|
|
* @param array|null $allowed an optional list of lowercase language codes to intersect with, defaults to null |
490
|
|
|
* @return string the prefered language code |
491
|
|
|
*/ |
492
|
1 |
|
public function getPreferredResponseFormat(string $default = 'text/html', array $allowed = null) : string |
493
|
|
|
{ |
494
|
|
|
// parse accept header (uses default instead of 406 header) |
495
|
1 |
|
$acpt = $this->getPreferredResponseFormats(); |
496
|
1 |
|
foreach ($acpt as $format) { |
497
|
1 |
|
if ($allowed === null) { |
498
|
1 |
|
return $format; |
499
|
|
|
} |
500
|
|
|
if (in_array($format, $allowed)) { |
501
|
|
|
return $format; |
502
|
|
|
} |
503
|
|
|
} |
504
|
|
|
return $default; |
505
|
|
|
} |
506
|
|
|
/** |
507
|
|
|
* Retrieves the URI instance. |
508
|
|
|
* |
509
|
|
|
* @return \vakata\http\Uri Returns a Uri instance |
510
|
|
|
*/ |
511
|
|
|
public function getUri() |
512
|
|
|
{ |
513
|
|
|
return parent::getUri(); |
514
|
|
|
} |
515
|
|
|
} |
516
|
|
|
|
This method has been deprecated. The supplier of the class has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.