Completed
Pull Request — master (#24)
by Alexander
02:05
created

Message::httpCodeToMessage()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace alkemann\h2l;
4
5
/**
6
 * Class Message
7
 *
8
 * Container for requests and responses made with the Remote class
9
 *
10
 * @package alkemann\h2l
11
 */
12
class Message
13
{
14
    const CONTENT_JSON = 'application/json';
15
    const CONTENT_FORM = 'application/x-www-form-urlencoded';
16
    const CONTENT_HTML = 'text/html';
17
    const CONTENT_TEXT = 'text/plain';
18
    const CONTENT_XML = 'application/xml';
19
    const CONTENT_TEXT_XML = 'text/xml';
20
21
    private static $code_to_message = [
22
        // Informational 1xx
23
        100 => 'Continue',
24
        101 => 'Switching Protocols',
25
        // Successful 2xx
26
        200 => 'OK',
27
        201 => 'Created',
28
        202 => 'Accepted',
29
        203 => 'Non-Authoritative Information',
30
        204 => 'No Content',
31
        205 => 'Reset Content',
32
        206 => 'Partial Content',
33
        // Redirection 3xx
34
        300 => 'Multiple Choices',
35
        301 => 'Moved Permanently',
36
        302 => 'Found',
37
        303 => 'See Other',
38
        304 => 'Not Modified',
39
        305 => 'Use Proxy',
40
        307 => 'Temporary Redirect',
41
        // Client Error 4xx
42
        400 => 'Bad Request',
43
        401 => 'Unauthorized',
44
        402 => 'Payment Required',
45
        403 => 'Forbidden',
46
        404 => 'Not Found',
47
        405 => 'Method Not Allowed',
48
        406 => 'Not Acceptable',
49
        407 => 'Proxy Authentication Required',
50
        408 => 'Request Timeout',
51
        409 => 'Conflict',
52
        410 => 'Gone',
53
        411 => 'Length Required',
54
        412 => 'Precondition Failed',
55
        413 => 'Request Entity Too Large',
56
        414 => 'Request-URI Too Long',
57
        415 => 'Unsupported Media Type',
58
        416 => 'Requested Range Not Satisfiable',
59
        417 => 'Expectation Failed',
60
        // Server Error 5xx
61
        500 => 'Internal Server Error',
62
        501 => 'Not Implemented',
63
        502 => 'Bad Gateway',
64
        503 => 'Service Unavailable',
65
        504 => 'Gateway Timeout',
66
        505 => 'HTTP Version Not Supported',
67
    ];
68
69
    public static function httpCodeToMessage(int $code): string
70
    {
71
        return self::$code_to_message[$code] ?? "Unknown";
72
    }
73
74
    /**
75
     * @var int
76
     */
77
    protected $code;
78
    /**
79
     * @var string
80
     */
81
    protected $url = '';
82
    /**
83
     * Enum with Request::GET, Request::POST etc
84
     * @var string
85
     */
86
    protected $method = Request::GET;
87
    /**
88
     * @var string
89
     */
90
    protected $body;
91
    /**
92
     * @var array
93
     */
94
    protected $meta = [];
95
    /**
96
     * @var array
97
     */
98
    protected $headers = [];
99
    /**
100
     * @var array
101
     */
102
    protected $options = [];
103
    /**
104
     * @var string
105
     */
106
    protected $content_type = Message::CONTENT_HTML;
107
    /**
108
     * @var string
109
     */
110
    protected $content_charset = 'utf-8';
111
112
    /**
113
     * @return string
114
     */
115
    public function url(): string
116
    {
117
        return $this->url;
118
    }
119
120
    /**
121
     * @return string
122
     */
123
    public function method(): string
124
    {
125
        return $this->method;
126
    }
127
128
    /**
129
     * @return null|string
130
     */
131
    public function body(): ?string
132
    {
133
        return $this->body;
134
    }
135
136
    /**
137
     * @return null|string|array|\SimpleXMLElement body converted from raw format
138
     */
139
    public function content()
140
    {
141
        switch ($this->contentType()) {
142
            case static::CONTENT_JSON:
143
                return json_decode($this->body, true);
144
            case static::CONTENT_XML:
145
                return new \SimpleXMLElement($this->body);
146
            case static::CONTENT_HTML:
147
                $doc = new \DOMDocument();
148
                $doc->loadHTML($this->body);
149
                return $doc;
150
            case null:
151
            default:
152
                return $this->body;
153
        }
154
    }
155
156
    /**
157
     * @return string
158
     */
159
    public function contentType(): string
160
    {
161
        return $this->content_type;
162
    }
163
164
    /**
165
     * @return string
166
     */
167
    public function charset(): string
168
    {
169
        return $this->content_charset;
170
    }
171
172
    /**
173
     * @param string $name
174
     * @return null|string
175
     */
176
    public function header(string $name): ?string
177
    {
178
        foreach ($this->headers as $key => $value) {
179
            if (strcasecmp($key, $name) === 0) {
180
                return $value;
181
            }
182
        }
183
        return null;
184
    }
185
186
    /**
187
     * @param string $class name of class that must take data array as constructor
188
     * @return object body json decoded and sent to constructor of $class
189
     */
190
    public function as(string $class)
191
    {
192
        return new $class($this->content());
193
    }
194
195
    /**
196
     * @return array
197
     */
198
    public function headers(): array
199
    {
200
        return $this->headers;
201
    }
202
203
    /**
204
     * @return array
205
     */
206
    public function meta(): array
207
    {
208
        return $this->meta;
209
    }
210
211
    /**
212
     * @return array
213
     */
214
    public function options(): array
215
    {
216
        return $this->options;
217
    }
218
219
    /**
220
     * @return int|null
221
     */
222
    public function code(): ?int
223
    {
224
        return $this->code;
225
    }
226
227
    /**
228
     * @param int $code
229
     * @return Message
230
     */
231
    public function withCode(int $code): Message
232
    {
233
        $new = clone $this;
234
        $new->code = $code;
235
        return $new;
236
    }
237
238
    /**
239
     * @param string $url
240
     * @return Message
241
     */
242
    public function withUrl(string $url): Message
243
    {
244
        $new = clone $this;
245
        $new->url = $url;
246
        return $new;
247
    }
248
249
    /**
250
     * @param string $method
251
     * @return Message
252
     */
253
    public function withMethod(string $method): Message
254
    {
255
        $new = clone $this;
256
        $new->method = $method;
257
        return $new;
258
    }
259
260
    /**
261
     * @param string $body
262
     * @return Message
263
     */
264
    public function withBody(string $body): Message
265
    {
266
        $new = clone $this;
267
        $new->body = $body;
268
        return $new;
269
    }
270
271
    /**
272
     * @param array $headers
273
     * @return Message
274
     */
275
    public function withHeaders(array $headers): Message
276
    {
277
        $new = clone $this;
278
        $new->headers = $headers;
279
        $content_header = $new->header('Content-Type');
280
        if (is_string($content_header)) {
281
            if (strpos($content_header, ';') === false) {
282
                $new->content_type = trim(strtolower($content_header));
283
            } else {
284
                list($type, $other) = explode(';', $content_header, 2);
285
                $new->content_type = trim(strtolower($type));
286
                list($key, $charset) = explode('=', $other, 2);
287
                if ('charset' === strtolower(trim($key))) {
288
                    $new->content_charset = strtolower(trim(trim($charset, '"')));
289
                }
290
            }
291
        }
292
        return $new;
293
    }
294
295
    /**
296
     * @param array $options
297
     * @return Message
298
     */
299
    public function withOptions(array $options): Message
300
    {
301
        $new = clone $this;
302
        $new->options = $options;
303
        return $new;
304
    }
305
306
    /**
307
     * @param array $meta
308
     * @return Message
309
     */
310
    public function withMeta(array $meta): Message
311
    {
312
        $new = clone $this;
313
        $new->meta = $meta;
314
        return $new;
315
    }
316
317
    /**
318
     * @return string the raw body of the message
319
     */
320
    public function __toString(): string
321
    {
322
        return $this->body ?? '';
323
    }
324
}
325