Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
46 / 46
100.00% covered (success)
100.00%
15 / 15
CRAP
100.00% covered (success)
100.00%
1 / 1
Request
100.00% covered (success)
100.00%
46 / 46
100.00% covered (success)
100.00%
15 / 15
32
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
5
 get
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
2
 server
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
2
 httpMethod
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 ip
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
4
 setHeader
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 header
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 cookie
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
2
 body
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setBody
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 bodyAsJson
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
3
 uploadedFile
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
2
 createUploadedFiles
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
3
 createUploadedFilesFromArray
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
2
 createUploadedFile
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3namespace Dynart\Micro;
4
5class 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}