Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
| Total | |
100.00% |
46 / 46 |
|
100.00% |
15 / 15 |
CRAP | |
100.00% |
1 / 1 |
| Request | |
100.00% |
46 / 46 |
|
100.00% |
15 / 15 |
32 | |
100.00% |
1 / 1 |
| __construct | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
5 | |||
| get | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
2 | |||
| server | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
2 | |||
| httpMethod | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| ip | |
100.00% |
7 / 7 |
|
100.00% |
1 / 1 |
4 | |||
| setHeader | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| header | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
2 | |||
| cookie | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
2 | |||
| body | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| setBody | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| bodyAsJson | |
100.00% |
7 / 7 |
|
100.00% |
1 / 1 |
3 | |||
| uploadedFile | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
2 | |||
| createUploadedFiles | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
3 | |||
| createUploadedFilesFromArray | |
100.00% |
9 / 9 |
|
100.00% |
1 / 1 |
2 | |||
| createUploadedFile | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
1 | |||
| 1 | <?php |
| 2 | |
| 3 | namespace Dynart\Micro; |
| 4 | |
| 5 | class Request implements RequestInterface { |
| 6 | |
| 7 | /** The incoming HTTP request headers. */ |
| 8 | protected array $headers = []; |
| 9 | |
| 10 | /** The incoming uploaded files. */ |
| 11 | protected array $uploadedFiles = []; |
| 12 | |
| 13 | /** Stores the request body */ |
| 14 | protected string $body = ''; |
| 15 | |
| 16 | /** |
| 17 | * Fills up the `headers` and the `uploadedFiles` arrays. |
| 18 | */ |
| 19 | public function __construct() { |
| 20 | $headers = function_exists('getallheaders') ? getallheaders() : ['x-test-header' => 'test-value']; |
| 21 | foreach ($headers as $key => $value) { |
| 22 | $this->headers[strtolower($key)] = $value; |
| 23 | } |
| 24 | if (!empty($_FILES)) { |
| 25 | $this->createUploadedFiles(); |
| 26 | } |
| 27 | $this->body = file_get_contents('php://input') ?: ''; |
| 28 | } |
| 29 | |
| 30 | public function get(string $name, mixed $default = null): mixed { |
| 31 | return array_key_exists($name, $_REQUEST) ? $_REQUEST[$name] : $default; |
| 32 | } |
| 33 | |
| 34 | public function server(string $name, mixed $default = null): mixed { |
| 35 | return array_key_exists($name, $_SERVER) ? $_SERVER[$name] : $default; |
| 36 | } |
| 37 | |
| 38 | public function httpMethod(): string { |
| 39 | return $this->server('REQUEST_METHOD'); |
| 40 | } |
| 41 | |
| 42 | public function ip(): ?string { |
| 43 | if (!empty($_SERVER['HTTP_CLIENT_IP'])) { |
| 44 | return $_SERVER['HTTP_CLIENT_IP']; |
| 45 | } else if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])){ |
| 46 | return $_SERVER['HTTP_X_FORWARDED_FOR']; |
| 47 | } else if (!empty($_SERVER['REMOTE_ADDR'])) { |
| 48 | return $_SERVER['REMOTE_ADDR']; |
| 49 | } |
| 50 | return null; |
| 51 | } |
| 52 | |
| 53 | public function setHeader(string $name, string $value): void { |
| 54 | $this->headers[strtolower($name)] = $value; |
| 55 | } |
| 56 | |
| 57 | public function header(string $name, mixed $default = null): mixed { |
| 58 | $lowerName = strtolower($name); |
| 59 | return isset($this->headers[$lowerName]) ? $this->headers[$lowerName] : $default; |
| 60 | } |
| 61 | |
| 62 | public function cookie(string $name, mixed $default = null): mixed { |
| 63 | return array_key_exists($name, $_COOKIE) ? $_COOKIE[$name] : $default; |
| 64 | } |
| 65 | |
| 66 | public function body(): string { |
| 67 | return $this->body; |
| 68 | } |
| 69 | |
| 70 | public function setBody(string $content): void { |
| 71 | $this->body = $content; |
| 72 | } |
| 73 | |
| 74 | public function bodyAsJson(): ?array { |
| 75 | $json = $this->body(); |
| 76 | if (!$json) { |
| 77 | return null; |
| 78 | } |
| 79 | $result = json_decode($json, true); |
| 80 | if ($result) { |
| 81 | return $result; |
| 82 | } |
| 83 | throw new MicroException("The request body is not a valid JSON: ".$json); |
| 84 | } |
| 85 | |
| 86 | public function uploadedFile(string $name): UploadedFile|array|null { |
| 87 | return isset($this->uploadedFiles[$name]) ? $this->uploadedFiles[$name] : null; |
| 88 | } |
| 89 | |
| 90 | /** |
| 91 | * It will fill up the `uploadedFiles` array |
| 92 | */ |
| 93 | protected function createUploadedFiles(): void { |
| 94 | foreach ($_FILES as $name => $file) { |
| 95 | if (is_array($file['name'])) { |
| 96 | $this->createUploadedFilesFromArray($name, $file); |
| 97 | } else { |
| 98 | $this->uploadedFiles[$name] = $this->createUploadedFile($file); |
| 99 | } |
| 100 | } |
| 101 | } |
| 102 | |
| 103 | /** |
| 104 | * It will create an UploadedFile array by parameter name and puts into the `uploadedFiles` array |
| 105 | */ |
| 106 | protected function createUploadedFilesFromArray(string $name, array $file): void { |
| 107 | $this->uploadedFiles[$name] = []; |
| 108 | foreach (array_keys($file['name']) as $index) { |
| 109 | $this->uploadedFiles[$name][$index] = $this->createUploadedFile([ |
| 110 | 'name' => $file['name'][$index], |
| 111 | 'tmp_name' => $file['tmp_name'][$index], |
| 112 | 'error' => $file['error'][$index], |
| 113 | 'type' => $file['type'][$index], |
| 114 | 'size' => $file['size'][$index] |
| 115 | ]); |
| 116 | } |
| 117 | } |
| 118 | |
| 119 | /** |
| 120 | * It will create an UploadedFile instance by an array (one element from the $_FILES) |
| 121 | */ |
| 122 | protected function createUploadedFile(array $file): UploadedFile { |
| 123 | return Micro::create(UploadedFile::class, [ |
| 124 | $file['name'], $file['tmp_name'], $file['error'], $file['type'], $file['size'] |
| 125 | ]); |
| 126 | } |
| 127 | |
| 128 | } |