Message::charset()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 3
rs 10
1
<?php
2
3
namespace alkemann\h2l;
4
5
use alkemann\h2l\util\Http;
6
7
/**
8
 * Class Message
9
 *
10
 * Container for requests and responses made with the Remote class
11
 *
12
 * @package alkemann\h2l
13
 */
14
class Message
15
{
16
    /**
17
     * @var int
18
     */
19
    protected int $code = 0;
20
    /**
21
     * @var string
22
     */
23
    protected string $url = '';
24
    /**
25
     * Enum with Http::GET, Http::POST etc
26
     * @var string
27
     */
28
    protected string $method = Http::GET;
29
    /**
30
     * @var string
31
     */
32
    protected string $body = '';
33
    /**
34
     * @var array<string, mixed>
35
     */
36
    protected array $meta = [];
37
    /**
38
     * @var array<string, mixed>
39
     */
40
    protected array $headers = [];
41
    /**
42
     * @var array<string, mixed>
43
     */
44
    protected array $options = [];
45
    /**
46
     * @var string
47
     */
48
    protected string $content_type = Http::CONTENT_HTML;
49
    /**
50
     * @var string
51
     */
52
    protected string $content_charset = 'utf-8';
53
54
    /**
55
     * @return string
56
     */
57
    public function url(): string
58
    {
59
        return $this->url;
60
    }
61
62
    /**
63
     * @return string
64
     */
65
    public function method(): string
66
    {
67
        return $this->method;
68
    }
69
70
    /**
71
     * @return string
72
     */
73
    public function body(): string
74
    {
75
        return $this->body;
76
    }
77
78
    /**
79
     * @return null|string|array<mixed>|\SimpleXMLElement|\DOMDocument body converted from raw format
80
     */
81
    public function content()
82
    {
83
        switch ($this->contentType()) {
84
            case Http::CONTENT_JSON:
85
                return json_decode($this->body, true, 512, JSON_THROW_ON_ERROR | JSON_BIGINT_AS_STRING);
86
            case Http::CONTENT_XML:
87
                return new \SimpleXMLElement($this->body);
88
            case Http::CONTENT_HTML:
89
                $doc = new \DOMDocument();
90
                $doc->loadHTML($this->body);
91
                return $doc;
92
            case Http::CONTENT_FORM:
93
                // @TODO some php method that converts form to array?
94
            case null:
95
            default:
96
                return $this->body;
97
        }
98
    }
99
100
    /**
101
     * @return string
102
     */
103
    public function contentType(): string
104
    {
105
        return $this->content_type;
106
    }
107
108
    /**
109
     * @return string
110
     */
111
    public function charset(): string
112
    {
113
        return $this->content_charset;
114
    }
115
116
    /**
117
     * @param string $name
118
     * @return null|string
119
     */
120
    public function header(string $name): ?string
121
    {
122
        foreach ($this->headers as $key => $value) {
123
            if (strcasecmp($key, $name) === 0) {
124
                return $value;
125
            }
126
        }
127
        return null;
128
    }
129
130
    /**
131
     * @param string $class name of class that must take data array as constructor
132
     * @return object body json decoded and sent to constructor of $class
133
     */
134
    public function as(string $class): object
135
    {
136
        return new $class($this->content());
137
    }
138
139
    /**
140
     * @return array<string, mixed>
141
     */
142
    public function headers(): array
143
    {
144
        return $this->headers;
145
    }
146
147
    /**
148
     * @return array<string, mixed>
149
     */
150
    public function meta(): array
151
    {
152
        return $this->meta;
153
    }
154
155
    /**
156
     * @return array<string, mixed>
157
     */
158
    public function options(): array
159
    {
160
        return $this->options;
161
    }
162
163
    /**
164
     * @return int
165
     */
166
    public function code(): int
167
    {
168
        return $this->code;
169
    }
170
171
    /**
172
     * @param int $code
173
     * @return Message
174
     */
175
    public function withCode(int $code): Message
176
    {
177
        $new = clone $this;
178
        $new->code = $code;
179
        return $new;
180
    }
181
182
    /**
183
     * @param string $url
184
     * @return Message
185
     */
186
    public function withUrl(string $url): Message
187
    {
188
        $new = clone $this;
189
        $new->url = $url;
190
        return $new;
191
    }
192
193
    /**
194
     * @param string $method
195
     * @return Message
196
     */
197
    public function withMethod(string $method): Message
198
    {
199
        $new = clone $this;
200
        $new->method = $method;
201
        return $new;
202
    }
203
204
    /**
205
     * @param string $body
206
     * @return static
207
     */
208
    public function withBody(string $body): object
209
    {
210
        $new = clone $this;
211
        $new->body = $body;
212
        return $new;
213
    }
214
215
    /**
216
     * @param array<string, mixed> $headers
217
     * @return Message
218
     */
219
    public function withHeaders(array $headers): Message
220
    {
221
        $new = clone $this;
222
        $new->headers = $headers;
223
        $new->setContentHeaderTypeAndCharset();
224
        return $new;
225
    }
226
227
    private function setContentHeaderTypeAndCharset(): void
228
    {
229
        $content_header = $this->header('Content-Type');
230
        if (is_string($content_header)) {
231
            if (strpos($content_header, ';') === false) {
232
                $this->content_type = trim(strtolower($content_header));
233
            } else {
234
                list($type, $other) = explode(';', $content_header, 2);
235
                $this->content_type = trim(strtolower($type));
236
                list($key, $charset) = explode('=', $other, 2);
237
                if ('charset' === strtolower(trim($key))) {
238
                    $this->content_charset = strtolower(trim(trim($charset, '"')));
239
                }
240
            }
241
        }
242
    }
243
244
    /**
245
     * @param string $name
246
     * @param string $value
247
     * @return Message
248
     */
249
    public function withHeader(string $name, string $value): Message
250
    {
251
        $new = clone $this;
252
        $new->headers[$name] = $value;
253
        if ($name === 'Content-Type') {
254
            $new->setContentHeaderTypeAndCharset();
255
        }
256
        return $new;
257
    }
258
259
    /**
260
     * @param array<string, mixed> $options
261
     * @return Message
262
     */
263
    public function withOptions(array $options): Message
264
    {
265
        $new = clone $this;
266
        $new->options = $options;
267
        return $new;
268
    }
269
270
    /**
271
     * @param array<string, mixed> $meta
272
     * @return Message
273
     */
274
    public function withMeta(array $meta): Message
275
    {
276
        $new = clone $this;
277
        $new->meta = $meta;
278
        return $new;
279
    }
280
281
    /**
282
     * @return string the raw body of the message
283
     */
284
    public function __toString(): string
285
    {
286
        return $this->body;
287
    }
288
}
289