Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
88.31% |
136 / 154 |
|
83.72% |
36 / 43 |
CRAP | |
0.00% |
0 / 1 |
Request | |
88.31% |
136 / 154 |
|
83.72% |
36 / 43 |
118.61 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
7 / 7 |
|
100.00% |
1 / 1 |
4 | |||
create | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
createJson | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
createXml | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
createUrlEncoded | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
createMultipart | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
setMethod | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
3 | |||
getMethod | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
hasMethod | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
addHeader | |
100.00% |
12 / 12 |
|
100.00% |
1 / 1 |
9 | |||
setQuery | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
2 | |||
addQuery | |
75.00% |
6 / 8 |
|
0.00% |
0 / 1 |
3.14 | |||
getQuery | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
hasQuery | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
removeQuery | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
2 | |||
removeAllQuery | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
2 | |||
setData | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
3 | |||
addData | |
66.67% |
4 / 6 |
|
0.00% |
0 / 1 |
3.33 | |||
getData | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
hasData | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
removeData | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
2 | |||
removeAllData | |
83.33% |
5 / 6 |
|
0.00% |
0 / 1 |
3.04 | |||
getUriAsString | |
100.00% |
11 / 11 |
|
100.00% |
1 / 1 |
10 | |||
setRequestType | |
68.75% |
11 / 16 |
|
0.00% |
0 / 1 |
11.47 | |||
getRequestType | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
hasRequestType | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
removeRequestType | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
3 | |||
createAsJson | |
100.00% |
7 / 7 |
|
100.00% |
1 / 1 |
3 | |||
isJson | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
createAsXml | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
3 | |||
isXml | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
createAsUrlEncoded | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
3 | |||
isUrlEncoded | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
createAsMultipart | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
isMultipart | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
createAsCustomType | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
6 | |||
isCustomType | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
30 | |||
isValidMethod | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
hasDataContent | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
2 | |||
getDataContent | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getDataContentLength | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
prepareData | |
75.00% |
3 / 4 |
|
0.00% |
0 / 1 |
2.06 | |||
__call | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
3 |
1 | <?php |
2 | /** |
3 | * Pop PHP Framework (https://www.popphp.org/) |
4 | * |
5 | * @link https://github.com/popphp/popphp-framework |
6 | * @author Nick Sagona, III <dev@noladev.com> |
7 | * @copyright Copyright (c) 2009-2025 NOLA Interactive, LLC. |
8 | * @license https://www.popphp.org/license New BSD License |
9 | */ |
10 | |
11 | /** |
12 | * @namespace |
13 | */ |
14 | namespace Pop\Http\Client; |
15 | |
16 | use Pop\Http\Uri; |
17 | use Pop\Http\AbstractRequest; |
18 | use Pop\Mime\Message; |
19 | use Pop\Mime\Part\Header; |
20 | |
21 | /** |
22 | * HTTP client request class |
23 | * |
24 | * @category Pop |
25 | * @package Pop\Http |
26 | * @author Nick Sagona, III <dev@noladev.com> |
27 | * @copyright Copyright (c) 2009-2025 NOLA Interactive, LLC. |
28 | * @license https://www.popphp.org/license New BSD License |
29 | * @version 5.3.2 |
30 | */ |
31 | class Request extends AbstractRequest |
32 | { |
33 | |
34 | /** |
35 | * Request type constants |
36 | * @var string |
37 | */ |
38 | const URLENCODED = 'application/x-www-form-urlencoded'; |
39 | const JSON = 'application/json'; |
40 | const XML = 'application/xml'; |
41 | const MULTIPART = 'multipart/form-data'; |
42 | |
43 | /** |
44 | * Request method |
45 | * @var ?string |
46 | */ |
47 | protected ?string $method = null; |
48 | |
49 | /** |
50 | * Request type |
51 | * @var ?string |
52 | */ |
53 | protected ?string $requestType = null; |
54 | |
55 | /** |
56 | * Client request query data object |
57 | * |
58 | * Can only be a URL-encoded query string on the URI |
59 | * |
60 | * @var ?Data |
61 | */ |
62 | protected ?Data $query = null; |
63 | |
64 | /** |
65 | * Client request data object |
66 | * |
67 | * Can be any type of supported request data: |
68 | * - URL-encoded query string on the URI (GET method) |
69 | * - URL-encoded body (any method other than GET) |
70 | * - JSON-encoded body |
71 | * - XML-encoded body |
72 | * - Multipart/form body |
73 | * |
74 | * @var ?Data |
75 | */ |
76 | protected ?Data $data = null; |
77 | |
78 | /** |
79 | * Constructor |
80 | * |
81 | * Instantiate the request data object |
82 | * |
83 | * @param Uri|string|null $uri |
84 | * @param string $method |
85 | * @param mixed $data |
86 | * @param ?string $type |
87 | * @param bool $strict |
88 | * @throws Exception|\Pop\Http\Exception |
89 | */ |
90 | public function __construct(Uri|string|null $uri = null, string $method = 'GET', mixed $data = null, ?string $type = null, bool $strict = false) |
91 | { |
92 | parent::__construct($uri); |
93 | |
94 | if ($method !== null) { |
95 | $this->setMethod($method, $strict); |
96 | } |
97 | if ($data !== null) { |
98 | $this->setData($data); |
99 | } |
100 | if ($type !== null) { |
101 | $this->setRequestType($type); |
102 | } |
103 | } |
104 | |
105 | /** |
106 | * Factory method to create a Request object |
107 | * |
108 | * @param Uri|string|null $uri |
109 | * @param string $method |
110 | * @param mixed $data |
111 | * @param ?string $type |
112 | * @param bool $strict |
113 | * @throws Exception|\Pop\Http\Exception |
114 | * @return Request |
115 | */ |
116 | public static function create(Uri|string|null $uri = null, string $method = 'GET', mixed $data = null, ?string $type = null, bool $strict = false): Request |
117 | { |
118 | return new self($uri, $method, $data, $type, $strict); |
119 | } |
120 | |
121 | /** |
122 | * Factory method to create a JSON Request object |
123 | * |
124 | * @param Uri|string|null $uri |
125 | * @param string $method |
126 | * @param mixed $data |
127 | * @param bool $strict |
128 | * @throws Exception|\Pop\Http\Exception |
129 | * @return Request |
130 | */ |
131 | public static function createJson(Uri|string|null $uri = null, string $method = 'POST', mixed $data = null, bool $strict = false): Request |
132 | { |
133 | return new self($uri, $method, $data, Request::JSON, $strict); |
134 | } |
135 | |
136 | /** |
137 | * Factory method to create an XML Request object |
138 | * |
139 | * @param Uri|string|null $uri |
140 | * @param string $method |
141 | * @param mixed $data |
142 | * @param bool $strict |
143 | * @throws Exception|\Pop\Http\Exception |
144 | * @return Request |
145 | */ |
146 | public static function createXml(Uri|string|null $uri = null, string $method = 'POST', mixed $data = null, bool $strict = false): Request |
147 | { |
148 | return new self($uri, $method, $data, Request::XML, $strict); |
149 | } |
150 | |
151 | /** |
152 | * Factory method to create a URL-encoded Request object |
153 | * |
154 | * @param Uri|string|null $uri |
155 | * @param string $method |
156 | * @param mixed $data |
157 | * @param bool $strict |
158 | * @throws Exception|\Pop\Http\Exception |
159 | * @return Request |
160 | */ |
161 | public static function createUrlEncoded(Uri|string|null $uri = null, string $method = 'GET', mixed $data = null, bool $strict = false): Request |
162 | { |
163 | return new self($uri, $method, $data, Request::URLENCODED, $strict); |
164 | } |
165 | |
166 | /** |
167 | * Factory method to create a multipart Request object |
168 | * |
169 | * @param Uri|string|null $uri |
170 | * @param string $method |
171 | * @param mixed $data |
172 | * @param bool $strict |
173 | * @throws Exception|\Pop\Http\Exception |
174 | * @return Request |
175 | */ |
176 | public static function createMultipart(Uri|string|null $uri = null, string $method = 'POST', mixed $data = null, bool $strict = false): Request |
177 | { |
178 | return new self($uri, $method, $data, Request::MULTIPART, $strict); |
179 | } |
180 | |
181 | /** |
182 | * Set method |
183 | * |
184 | * @param string $method |
185 | * @param bool $strict |
186 | * @throws Exception |
187 | * @return Request |
188 | */ |
189 | public function setMethod(string $method, bool $strict = false): Request |
190 | { |
191 | $method = strtoupper($method); |
192 | |
193 | if ($strict) { |
194 | if (!$this->isValidMethod($method)) { |
195 | throw new Exception('Error: That request method is not valid.'); |
196 | } |
197 | } |
198 | |
199 | $this->method = $method; |
200 | return $this; |
201 | } |
202 | |
203 | /** |
204 | * Get method |
205 | * |
206 | * @return ?string |
207 | */ |
208 | public function getMethod(): ?string |
209 | { |
210 | return $this->method; |
211 | } |
212 | |
213 | /** |
214 | * Has method |
215 | * |
216 | * @return bool |
217 | */ |
218 | public function hasMethod(): bool |
219 | { |
220 | return ($this->method !== null); |
221 | } |
222 | |
223 | /** |
224 | * Add a header |
225 | * |
226 | * @param Header|string|int $header |
227 | * @param ?string $value |
228 | * @return Request |
229 | */ |
230 | public function addHeader(Header|string|int $header, ?string $value = null): Request |
231 | { |
232 | $contentType = null; |
233 | if (is_numeric($header) && ($value !== null)) { |
234 | $header = Header::parse($value); |
235 | $value = null; |
236 | } |
237 | if (is_string($header) && ($header == 'Content-Type')) { |
238 | $contentType = $value; |
239 | } else if (($header instanceof Header) && ($header->getName() == 'Content-Type')) { |
240 | $contentType = $header->getValue()->getValue(); |
241 | } |
242 | |
243 | if (($contentType !== null) && ($this->requestType === null)) { |
244 | $this->requestType = $contentType; |
245 | } |
246 | |
247 | parent::addHeader($header, $value); |
248 | return $this; |
249 | } |
250 | |
251 | /** |
252 | * Set query data |
253 | * |
254 | * @param mixed $query |
255 | * @param mixed $filters |
256 | * @return Request |
257 | */ |
258 | public function setQuery(mixed $query, mixed $filters = null): Request |
259 | { |
260 | $this->setRequestType(Request::URLENCODED); |
261 | $this->query = ($query instanceof Data) ? $query : new Data($query, $filters, $this); |
262 | return $this; |
263 | } |
264 | |
265 | /** |
266 | * Add query data |
267 | * |
268 | * @param mixed $name |
269 | * @param mixed $value |
270 | * @return Request |
271 | */ |
272 | public function addQuery(mixed $name, mixed $value): Request |
273 | { |
274 | $this->setRequestType(Request::URLENCODED); |
275 | if ($this->query === null) { |
276 | $this->setRequestType(Request::URLENCODED); |
277 | $this->query = new Data([], null, $this); |
278 | } else if (!$this->query->hasRequest()) { |
279 | $this->query->setRequest($this); |
280 | } |
281 | $this->query->addData($name, $value); |
282 | |
283 | return $this; |
284 | } |
285 | |
286 | /** |
287 | * Get query data |
288 | * |
289 | * @return ?Data |
290 | */ |
291 | public function getQuery(): ?Data |
292 | { |
293 | return $this->query; |
294 | } |
295 | |
296 | /** |
297 | * Has query data |
298 | * |
299 | * @return bool |
300 | */ |
301 | public function hasQuery(): bool |
302 | { |
303 | return !empty($this->query); |
304 | } |
305 | |
306 | /** |
307 | * Remove query data |
308 | * |
309 | * @param string $key |
310 | * @return Request |
311 | */ |
312 | public function removeQuery(string $key): Request |
313 | { |
314 | if ($this->query->hasData($key)) { |
315 | $this->query->removeData($key); |
316 | } |
317 | return $this; |
318 | } |
319 | |
320 | /** |
321 | * Remove all query data |
322 | * |
323 | * @return Request |
324 | */ |
325 | public function removeAllQuery(): Request |
326 | { |
327 | $this->query = null; |
328 | |
329 | if ($this->hasHeader('Content-Type')) { |
330 | $this->removeHeader('Content-Type'); |
331 | } |
332 | return $this; |
333 | } |
334 | |
335 | /** |
336 | * Set data |
337 | * |
338 | * @param mixed $data |
339 | * @param mixed $filters |
340 | * @return Request |
341 | */ |
342 | public function setData(mixed $data, mixed $filters = null): Request |
343 | { |
344 | if ($data instanceof Data) { |
345 | if (!$data->hasRequest()) { |
346 | $data->setRequest($this); |
347 | } |
348 | } else { |
349 | $data = new Data($data, $filters, $this); |
350 | } |
351 | |
352 | $this->data = $data; |
353 | |
354 | return $this; |
355 | } |
356 | |
357 | /** |
358 | * Add data |
359 | * |
360 | * @param mixed $name |
361 | * @param mixed $value |
362 | * @return Request |
363 | */ |
364 | public function addData(mixed $name, mixed $value): Request |
365 | { |
366 | if ($this->data === null) { |
367 | $this->data = new Data([], null, $this); |
368 | } else if (!$this->data->hasRequest()) { |
369 | $this->data->setRequest($this); |
370 | } |
371 | $this->data->addData($name, $value); |
372 | |
373 | return $this; |
374 | } |
375 | |
376 | /** |
377 | * Get data |
378 | * |
379 | * @return ?Data |
380 | */ |
381 | public function getData(): ?Data |
382 | { |
383 | return $this->data; |
384 | } |
385 | |
386 | /** |
387 | * Has data |
388 | * |
389 | * @return bool |
390 | */ |
391 | public function hasData(): bool |
392 | { |
393 | return !empty($this->data); |
394 | } |
395 | |
396 | /** |
397 | * Remove data |
398 | * |
399 | * @param string $key |
400 | * @return Request |
401 | */ |
402 | public function removeData(string $key): Request |
403 | { |
404 | if ($this->data->hasData($key)) { |
405 | $this->data->removeData($key); |
406 | } |
407 | return $this; |
408 | } |
409 | |
410 | /** |
411 | * Remove all data |
412 | * |
413 | * @return Request |
414 | */ |
415 | public function removeAllData(): Request |
416 | { |
417 | $this->data = null; |
418 | |
419 | if ($this->hasHeader('Content-Type')) { |
420 | $this->removeHeader('Content-Type'); |
421 | } |
422 | if ($this->hasHeader('Content-Length')) { |
423 | $this->removeHeader('Content-Length'); |
424 | } |
425 | return $this; |
426 | } |
427 | |
428 | /** |
429 | * Get full URI as string |
430 | * |
431 | * @param bool $query |
432 | * @return string |
433 | */ |
434 | public function getUriAsString(bool $query = true): string |
435 | { |
436 | $uri = parent::getUriAsString(); |
437 | |
438 | if ($query) { |
439 | $queryString = null; |
440 | |
441 | // If request has generic query data |
442 | if ($this->hasQuery()) { |
443 | $queryString = $this->query->prepare()->getDataContent(); |
444 | // Else, if request has explicit data configured to be a query string over GET |
445 | } else if (($this->method == 'GET') && ($this->hasData()) && |
446 | (($this->requestType === null) || ($this->requestType == self::URLENCODED))) { |
447 | $queryString = $this->data->prepare()->getDataContent(); |
448 | } |
449 | |
450 | if (!empty($queryString) && !str_contains($uri, $queryString)) { |
451 | $uri .= ((str_contains($uri, '?')) ? '&' : '?') . $queryString; |
452 | } |
453 | } |
454 | |
455 | return $uri; |
456 | } |
457 | |
458 | /** |
459 | * Set request type |
460 | * |
461 | * @param ?string $type |
462 | * @param bool $handleHeader |
463 | * @return Request |
464 | */ |
465 | public function setRequestType(string $type = null, bool $handleHeader = true): Request |
466 | { |
467 | switch ($type) { |
468 | case self::JSON: |
469 | $this->createAsJson($type, $handleHeader); |
470 | break; |
471 | case self::XML: |
472 | $this->createAsXml($type, $handleHeader); |
473 | break; |
474 | case self::URLENCODED: |
475 | $this->createAsUrlEncoded($type, $handleHeader); |
476 | break; |
477 | case self::MULTIPART: |
478 | $this->createAsMultipart($type); |
479 | break; |
480 | default: |
481 | // Custom content-types |
482 | if ($type !== null) { |
483 | if (strrpos($type, 'json') !== false) { |
484 | $this->createAsJson($type); |
485 | } else if (strrpos($type, 'xml') !== false) { |
486 | $this->createAsXml($type); |
487 | } else { |
488 | $this->createAsCustomType($type); |
489 | } |
490 | } else { |
491 | $this->removeRequestType($handleHeader); |
492 | } |
493 | |
494 | } |
495 | |
496 | return $this; |
497 | } |
498 | |
499 | /** |
500 | * Get request type |
501 | * |
502 | * @return ?string |
503 | */ |
504 | public function getRequestType(): ?string |
505 | { |
506 | return $this->requestType; |
507 | } |
508 | |
509 | /** |
510 | * Has request type |
511 | * |
512 | * @return bool |
513 | */ |
514 | public function hasRequestType(): bool |
515 | { |
516 | return ($this->requestType !== null); |
517 | } |
518 | |
519 | /** |
520 | * Remove request type |
521 | * |
522 | * @param bool $removeHeader |
523 | * @return Request |
524 | */ |
525 | public function removeRequestType(bool $removeHeader = false): Request |
526 | { |
527 | $this->requestType = null; |
528 | if (($removeHeader) && ($this->hasHeader('Content-Type'))) { |
529 | $this->removeHeader('Content-Type'); |
530 | } |
531 | return $this; |
532 | } |
533 | |
534 | /** |
535 | * Create request as JSON |
536 | * |
537 | * @param string $type |
538 | * @param bool $addHeader |
539 | * @return Request |
540 | */ |
541 | public function createAsJson(string $type = self::JSON, bool $addHeader = true): Request |
542 | { |
543 | $this->requestType = $type; |
544 | |
545 | if ($this->hasHeader('Content-Type')) { |
546 | $this->removeHeader('Content-Type'); |
547 | } |
548 | if ($addHeader) { |
549 | $this->addHeader('Content-Type', $this->requestType); |
550 | } |
551 | $this->addHeader('Content-Type', $this->requestType); |
552 | |
553 | return $this; |
554 | } |
555 | |
556 | /** |
557 | * Check if request is JSON |
558 | * |
559 | * @return bool |
560 | */ |
561 | public function isJson(): bool |
562 | { |
563 | return str_contains(strtolower($this->requestType), 'json'); |
564 | } |
565 | |
566 | /** |
567 | * Create request as XML |
568 | * |
569 | * @param string $type |
570 | * @param bool $addHeader |
571 | * @return Request |
572 | */ |
573 | public function createAsXml(string $type = self::XML, bool $addHeader = true): Request |
574 | { |
575 | $this->requestType = $type; |
576 | |
577 | if ($this->hasHeader('Content-Type')) { |
578 | $this->removeHeader('Content-Type'); |
579 | } |
580 | |
581 | if ($addHeader) { |
582 | $this->addHeader('Content-Type', $this->requestType); |
583 | } |
584 | |
585 | return $this; |
586 | } |
587 | |
588 | /** |
589 | * Check if request is XML |
590 | * |
591 | * @return bool |
592 | */ |
593 | public function isXml(): bool |
594 | { |
595 | return str_contains(strtolower($this->requestType), 'xml'); |
596 | } |
597 | |
598 | /** |
599 | * Create request as a URL-encoded form |
600 | * |
601 | * @param string $type |
602 | * @param bool $addHeader |
603 | * @return Request |
604 | */ |
605 | public function createAsUrlEncoded(string $type = self::URLENCODED, bool $addHeader = true): Request |
606 | { |
607 | $this->requestType = $type; |
608 | |
609 | if ($this->hasHeader('Content-Type')) { |
610 | $this->removeHeader('Content-Type'); |
611 | } |
612 | |
613 | if ($addHeader) { |
614 | $this->addHeader('Content-Type', $this->requestType); |
615 | } |
616 | |
617 | return $this; |
618 | } |
619 | |
620 | /** |
621 | * Check if request is a URL-encoded form |
622 | * |
623 | * @return bool |
624 | */ |
625 | public function isUrlEncoded(): bool |
626 | { |
627 | return ($this->requestType == self::URLENCODED); |
628 | } |
629 | |
630 | /** |
631 | * Create request as a multipart form |
632 | * |
633 | * @param string $type |
634 | * @return Request |
635 | */ |
636 | public function createAsMultipart(string $type = self::MULTIPART): Request |
637 | { |
638 | $this->requestType = $type; |
639 | return $this; |
640 | } |
641 | |
642 | /** |
643 | * Check if request is a multipart form |
644 | * |
645 | * @return bool |
646 | */ |
647 | public function isMultipart(): bool |
648 | { |
649 | return str_contains(strtolower($this->requestType), self::MULTIPART); |
650 | } |
651 | |
652 | /** |
653 | * Create request as custom content type |
654 | * |
655 | * @param string $type |
656 | * @param bool $addHeader |
657 | * @return Request |
658 | */ |
659 | public function createAsCustomType(string $type, bool $addHeader = true): Request |
660 | { |
661 | $this->requestType = $type; |
662 | |
663 | if ($addHeader) { |
664 | $this->addHeader('Content-Type', $this->requestType); |
665 | } |
666 | return $this; |
667 | } |
668 | |
669 | /** |
670 | * Check if request is a custom content type |
671 | * |
672 | * @return bool |
673 | */ |
674 | public function isCustomType(): bool |
675 | { |
676 | return (!empty($this->requestType) && (strrpos($this->requestType, 'json') !== false) && |
677 | (strrpos($this->requestType, 'xml') !== false) && ($this->requestType !== self::URLENCODED) && |
678 | ($this->requestType !== self::MULTIPART)); |
679 | } |
680 | |
681 | /** |
682 | * Is valid method |
683 | * |
684 | * @param string $method |
685 | * @return bool |
686 | */ |
687 | public function isValidMethod(string $method): bool |
688 | { |
689 | return in_array(strtoupper($method), ['GET', 'HEAD', 'POST', 'PUT', 'PATCH', 'DELETE', 'CONNECT', 'OPTIONS', 'TRACE']); |
690 | } |
691 | |
692 | /** |
693 | * Has data content |
694 | * |
695 | * @return bool |
696 | */ |
697 | public function hasDataContent(): bool |
698 | { |
699 | return (($this->data !== null) && ($this->data->hasDataContent())); |
700 | } |
701 | |
702 | /** |
703 | * Get the data content |
704 | * |
705 | * @return ?string |
706 | */ |
707 | public function getDataContent(): ?string |
708 | { |
709 | return $this->data?->getDataContent(); |
710 | } |
711 | |
712 | /** |
713 | * Get the data content length |
714 | * |
715 | * @param bool $mb |
716 | * @return int|null |
717 | */ |
718 | public function getDataContentLength(bool $mb = false): int|null |
719 | { |
720 | return $this->data?->getDataContentLength($mb); |
721 | } |
722 | |
723 | /** |
724 | * Prepare request data |
725 | * |
726 | * @return Request |
727 | */ |
728 | public function prepareData(): Request |
729 | { |
730 | if (!$this->data->hasRequest()) { |
731 | $this->data->setRequest($this); |
732 | } |
733 | |
734 | $this->data->prepare(); |
735 | |
736 | return $this; |
737 | } |
738 | |
739 | /** |
740 | * Magic method to check the is[Method](), i.e. $request->isPost(); |
741 | * |
742 | * @param string $methodName |
743 | * @param ?array $arguments |
744 | * @throws Exception |
745 | * @return bool |
746 | */ |
747 | public function __call(string $methodName, ?array $arguments = null): bool |
748 | { |
749 | if (str_starts_with($methodName, 'is')) { |
750 | $method = strtoupper(substr($methodName, 2)); |
751 | if ($this->isValidMethod($method)) { |
752 | return ($this->method == $method); |
753 | } else { |
754 | throw new Exception('Error: That request method is not valid.'); |
755 | } |
756 | } else { |
757 | throw new Exception('Error: That method/function is not valid.'); |
758 | } |
759 | } |
760 | |
761 | } |