Issues (2)

src/ServerRequest.php (1 issue)

Labels
Severity
1
<?php
2
3
/**
4
 * This file is part of the miBadger package.
5
 *
6
 * @author Michael Webbers <[email protected]>
7
 * @license http://opensource.org/licenses/Apache-2.0 Apache v2 License
8
 */
9
10
namespace miBadger\Http;
11
12
use Psr\Http\Message\ServerRequestInterface;
13
use Psr\Http\Message\StreamInterface;
14
use Psr\Http\Message\UriInterface;
15
16
/**
17
 * The server request class
18
 *
19
 * @see http://www.php-fig.org/psr/psr-7/
20
 * @since 1.0.0
21
 */
22
class ServerRequest extends Request implements ServerRequestInterface
23
{
24
	/** @var array The server parameters. */
25
	private $serverParams;
26
27
	/** @var array The cookie parameters. */
28
	private $cookieParams;
29
30
	/** @var array The query parameters. */
31
	private $queryParams;
32
33
	/** @var array The post parameters. */
34
	private $postParams;
35
36
	/** @var array The files parameters. */
37
	private $filesParams;
38
39
	/** @var array The uploaded files. */
40
	private $uploadedFiles;
41
42
	/** @var null|array|object The parsed body. */
43
	private $parsedBody;
44
45
	/** @var array The attributes. */
46
	private $attributes;
47
48
	/**
49
	 * Construct a Request object with the given method, uri, version, headers & body.
50
	 *
51
	 * @global array $_SERVER The server parameters.
52
	 * @global array $_COOKIE The cookie parameters.
53
	 * @global array $_GET The query parameters.
54
	 * @global array $_POST The post parameters.
55
	 * @global array $_FILES The files parameters.
56
	 *
57
	 * @param string $method = ''
58
	 * @param UriInterface|null $uri = null
59
	 * @param string $version = self::DEFAULT_VERSION
60
	 * @param array $headers = []
61
	 * @param StreamInterface|null $body = null
62
	 */
63 20
	public function __construct($method = '', UriInterface $uri = null, $version = self::DEFAULT_VERSION, array $headers = [], StreamInterface $body = null)
64
	{
65 20
		if ($body === null) {
66 20
			$body = new Stream(fopen('php://input', 'r'));
67
		}
68
69 20
		$this->serverParams = $_SERVER;
70 20
		$this->cookieParams = $_COOKIE;
71 20
		$this->queryParams = $this->initQueryParams($this->serverParams);
0 ignored issues
show
$this->serverParams of type array is incompatible with the type string expected by parameter $serverParams of miBadger\Http\ServerRequest::initQueryParams(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

71
		$this->queryParams = $this->initQueryParams(/** @scrutinizer ignore-type */ $this->serverParams);
Loading history...
72 20
		$this->postParams = $_POST;
73 20
		$this->filesParams = $_FILES;
74 20
		$this->uploadedFiles = $this->initUploadedFiles($this->filesParams);
75 20
		$this->attributes = [];
76
77 20
		parent::__construct($this->initMethod($method), $this->initUri($uri), $version, $this->initHeaders($headers), $body);
78 20
	}
79
80
	/**
81
	 * Initialize the method.
82
	 *
83
	 * @param string $method
84
	 * @return string the method.
85
	 */
86 20
	private function initMethod($method)
87
	{
88 20
		return $method === '' && isset($this->getServerParams()['REQUEST_METHOD']) ? $this->getServerParams()['REQUEST_METHOD'] : $method;
89
	}
90
91
	/**
92
	 * Initialize the URI.
93
	 *
94
	 * @param UriInterface|null $uri
95
	 * @return UriInterface the URI.
96
	 */
97 20
	private function initUri($uri)
98
	{
99 20
		if ($uri !== null) {
100 1
			return $uri;
101
		}
102
103 20
		$scheme = isset($this->getServerParams()['HTTPS']) ? 'https://' : 'http://';
104 20
		$host = isset($this->getServerParams()['HTTP_HOST']) ? $scheme . $this->getServerParams()['HTTP_HOST'] : '';
105 20
		$path = isset($this->getServerParams()['REQUEST_URI']) ? $this->getServerParams()['REQUEST_URI'] : '';
106
107 20
		return new URI($host . $path);
108
	}
109
110
	/**
111
	 * Initialize the headers.
112
	 *
113
	 * @param array $headers
114
	 * @return array the headers.
115
	 */
116 20
	private function initHeaders($headers)
117
	{
118 20
		return $headers ?: getallheaders();
119
	}
120
121
	/**
122
	 * Initialize the headers.
123
	 *
124
	 * @param string $serverParams
125
	 * @return array the headers.
126
	 */
127 20
	private function initQueryParams($serverParams)
128
	{
129 20
		$result = [];
130
131 20
		if (isset($serverParams['REQUEST_URI']) && ($query = parse_url($serverParams['REQUEST_URI'], \PHP_URL_QUERY))) {
132 20
			parse_str($query, $result);
133
		}
134
135 20
		return $result ?? [];
136
	}
137
138
	/**
139
	 * Initialize the uploaded files.
140
	 *
141
	 * @param array $files
142
	 * @return array the uploaded files.
143
	 */
144 20
	private function initUploadedFiles(array $files)
145
	{
146 20
		$result = [];
147
148 20
		foreach ($files as $key => $value) {
149 20
			$result[$key] = $this->parseUploadedFiles($value);
150
		}
151
152 20
		return $result;
153
	}
154
155
	/**
156
	 * Parse uploaded files.
157
	 *
158
	 * @param array $files
159
	 * @return UploadedFile|array uploaded files.
160
	 */
161 20
	private function parseUploadedFiles($files)
162
	{
163
		// Empty
164 20
		$first = reset($files);
165
166
		// Single
167 20
		if (!is_array($first)) {
168 20
			return $this->parseSingleUploadedFiles($files);
169
		}
170
171
		// Multiple
172 20
		if (count(array_filter(array_keys($first), 'is_string')) === 0) {
173 20
			return $this->parseMultipleUploadedFiles($files);
174
		}
175
176
		// Namespace
177 20
		return $this->initUploadedFiles($files);
178
	}
179
180
	/**
181
	 * Parse single uploaded file.
182
	 *
183
	 * @param array $file
184
	 * @return UploadedFile single uploaded file.
185
	 */
186 20
	private function parseSingleUploadedFiles(array $file)
187
	{
188 20
		return new UploadedFile($file['name'], $file['type'], $file['tmp_name'], $file['error'], $file['size']);
189
	}
190
191
	/**
192
	 * Parse multiple uploaded files.
193
	 *
194
	 * @param array $files
195
	 * @return UploadedFiles[] multiple uploaded files.
196
	 */
197 20
	private function parseMultipleUploadedFiles(array $files)
198
	{
199 20
		$count = count($files['name']);
200 20
		$result = [];
201
202 20
		for ($i = 0; $i < $count; $i++) {
203 20
			$result[] = new UploadedFile($files['name'][$i], $files['type'][$i], $files['tmp_name'][$i], $files['error'][$i], $files['size'][$i]);
204
		}
205
206 20
		return $result;
207
	}
208
209
	/**
210
	 * {@inheritdoc}
211
	 */
212 20
	public function getServerParams()
213
	{
214 20
		return $this->serverParams;
215
	}
216
217
	/**
218
	 * {@inheritdoc}
219
	 */
220 1
	public function getCookieParams()
221
	{
222 1
		return $this->cookieParams;
223
	}
224
225
	/**
226
	 * Set the cookie params.
227
	 *
228
	 * @param array $cookieParams
229
	 * @return $this
230
	 */
231 1
	private function setCookieParams(array $cookieParams)
232
	{
233 1
		$this->cookieParams = $cookieParams;
234
235 1
		return $this;
236
	}
237
238
	/**
239
	 * {@inheritdoc}
240
	 */
241 1
	public function withCookieParams(array $cookieParams)
242
	{
243 1
		$result = clone $this;
244
245 1
		return $result->setCookieParams($cookieParams);
246
	}
247
248
	/**
249
	 * {@inheritdoc}
250
	 */
251 3
	public function getQueryParams()
252
	{
253 3
		return $this->queryParams;
254
	}
255
256
	/**
257
	 * Set the query params.
258
	 *
259
	 * @param array $queryParams
260
	 * @return $this
261
	 */
262 1
	private function setQueryParams(array $queryParams)
263
	{
264 1
		$this->queryParams = $queryParams;
265
266 1
		return $this;
267
	}
268
269
	/**
270
	 * {@inheritdoc}
271
	 */
272 1
	public function withQueryParams(array $queryParams)
273
	{
274 1
		$result = clone $this;
275
276 1
		return $result->setQueryParams($queryParams);
277
	}
278
279
	/**
280
	 * {@inheritdoc}
281
	 */
282 2
	public function getUploadedFiles()
283
	{
284 2
		return $this->uploadedFiles;
285
	}
286
287
	/**
288
	 * Set the uploaded files.
289
	 *
290
	 * @param array $uploadedFiles
291
	 * @return $this
292
	 */
293 1
	private function setUploadedFiles(array $uploadedFiles)
294
	{
295 1
		$this->uploadedFiles = $uploadedFiles;
296
297 1
		return $this;
298
	}
299
300
	/**
301
	 * {@inheritdoc}
302
	 */
303 1
	public function withUploadedFiles(array $uploadedFiles)
304
	{
305 1
		$result = clone $this;
306
307 1
		return $result->setUploadedFiles($uploadedFiles);
308
	}
309
310
	/**
311
	 * {@inheritdoc}
312
	 * @throws \JsonException
313
	 */
314 7
	public function getParsedBody()
315
	{
316 7
		if ($this->parsedBody !== null) {
317 1
			return $this->parsedBody;
318
		}
319 6
		if ($this->getMethod() === 'POST' && ($this->hasContentType('application/x-www-form-urlencoded') || $this->hasContentType('multipart/form-data'))) {
320 3
			return $this->postParams;
321
		}
322 3
		if ($this->hasContentType('application/json') || $this->hasContentType('text/plain')) {
323 2
			return json_decode((string) $this->getBody(), true, 512, \JSON_THROW_ON_ERROR);
324
		}
325 1
		return null;
326
	}
327
328
329
	/**
330
	 * Checks if a content type header exists with the given content type.
331
	 *
332
	 * @param string $contentType
333
	 * @return bool true if a content type header exists with the given content type.
334
	 */
335 6
	private function hasContentType($contentType)
336
	{
337 6
		foreach ($this->getHeader('Content-Type') as $key => $value) {
338 5
			if (mb_substr($value, 0, strlen($contentType)) == $contentType) {
339 5
				return true;
340
			}
341
		}
342
343 3
		return false;
344
	}
345
346
	/**
347
	 * Set the parsed body.
348
	 *
349
	 * @param null|array|object $parsedBody
350
	 * @return $this
351
	 */
352 1
	private function setParsedBody($parsedBody)
353
	{
354 1
		$this->parsedBody = $parsedBody;
355
356 1
		return $this;
357
	}
358
359
	/**
360
	 * {@inheritdoc}
361
	 */
362 1
	public function withParsedBody($parsedBody)
363
	{
364 1
		$result = clone $this;
365
366 1
		return $result->setParsedBody($parsedBody);
367
	}
368
369
	/**
370
	 * {@inheritdoc}
371
	 */
372 1
	public function getAttributes()
373
	{
374 1
		return $this->attributes;
375
	}
376
377
	/**
378
	 * {@inheritdoc}
379
	 */
380 3
	public function getAttribute($name, $default = null)
381
	{
382 3
		return isset($this->attributes[$name]) ? $this->attributes[$name] : $default;
383
	}
384
385
	/**
386
	 * Set the attribute.
387
	 *
388
	 * @param string $name
389
	 * @param mixed $value
390
	 * @return $this
391
	 */
392 1
	private function setAttribute($name, $value)
393
	{
394 1
		$this->attributes[$name] = $value;
395
396 1
		return $this;
397
	}
398
399
	/**
400
	 * {@inheritdoc}
401
	 */
402 1
	public function withAttribute($name, $value)
403
	{
404 1
		$result = clone $this;
405
406 1
		return $result->setAttribute($name, $value);
407
	}
408
409
	/**
410
	 * Remove the attribute.
411
	 *
412
	 * @param string $name
413
	 * @return $this
414
	 */
415 1
	private function removeAttribute($name)
416
	{
417 1
		unset($this->attributes[$name]);
418
419 1
		return $this;
420
	}
421
422
	/**
423
	 * {@inheritdoc}
424
	 */
425 1
	public function withoutAttribute($name)
426
	{
427 1
		$result = clone $this;
428
429 1
		return $result->removeAttribute($name);
430
	}
431
}
432