Passed
Push — develop ( c2ab2c...f46e51 )
by Michael
02:22
created
src/URI.php 1 patch
Indentation   +638 added lines, -638 removed lines patch added patch discarded remove patch
@@ -19,648 +19,648 @@
 block discarded – undo
19 19
  */
20 20
 class URI implements UriInterface
21 21
 {
22
-	const DELIMITER_SCHEME = ':';
23
-	const DELIMITER_AUTHORITY = '//';
24
-	const DELIMITER_USER = '@';
25
-	const DELIMITER_PASSWORD = ':';
26
-	const DELIMITER_PORT = ':';
27
-	const DELIMITER_PATH = '/';
28
-	const DELIMITER_QUERY = '?';
29
-	const DELIMITER_QUERY_PAIR = '&';
30
-	const DELIMITER_QUERY_KEY_VALUE = '=';
31
-	const DELIMITER_FRAGMENT = '#';
32
-
33
-	const SCHEME = 'scheme';
34
-	const AUTHORITY = 'authority';
35
-	const USERNAME = 'user';
36
-	const PASSWORD = 'pass';
37
-	const HOST = 'host';
38
-	const PORT = 'port';
39
-	const PATH = 'path';
40
-	const DIRECTORY = 'directory';
41
-	const FILE = 'file';
42
-	const QUERY = 'query';
43
-	const FRAGMENT = 'fragment';
44
-
45
-	/** @var string The scheme. */
46
-	private $scheme;
47
-
48
-	/** @var string The username. */
49
-	private $username;
50
-
51
-	/** @var string|null The password. */
52
-	private $password;
53
-
54
-	/** @var string The host. */
55
-	private $host;
56
-
57
-	/** @var int|null The port. */
58
-	private $port;
59
-
60
-	/** @var string The directory. */
61
-	private $directory;
62
-
63
-	/** @var string The file. */
64
-	private $file;
65
-
66
-	/** @var array The query. */
67
-	private $query;
68
-
69
-	/** @var string The fragment. */
70
-	private $fragment;
71
-
72
-	/**
73
-	 * Construct a URI object with the given URI.
74
-	 *
75
-	 * @param string $uri
76
-	 * @throws \UnexpectedValueException
77
-	 */
78
-	public function __construct($uri)
79
-	{
80
-		$component = parse_url($uri);
81
-
82
-		if ($component === false) {
83
-			throw new \UnexpectedValueException('Invalid uri');
84
-		}
85
-
86
-		// Replace with the null coalescing in PHP7. E.g. $component[scheme] ?? ''
87
-		$component += [
88
-			static::SCHEME => '',
89
-			static::USERNAME => '',
90
-			static::PASSWORD => null,
91
-			static::HOST => '',
92
-			static::PORT => null,
93
-			static::PATH => '',
94
-			static::QUERY => '',
95
-			static::FRAGMENT => ''
96
-		];
97
-
98
-		$this->setScheme($component[static::SCHEME]);
99
-		$this->setUserInfo($component[static::USERNAME], $component[static::PASSWORD]);
100
-		$this->setHost($component[static::HOST]);
101
-		$this->setPort($component[static::PORT]);
102
-		$this->setPath($component[static::PATH]);
103
-		$this->setQuery($component[static::QUERY]);
104
-		$this->setFragment($component[static::FRAGMENT]);
105
-	}
106
-
107
-	/**
108
-	 * Returns a string representation of the URI object.
109
-	 *
110
-	 * @return string a string representation of the URI object.
111
-	 */
112
-	public function __toString()
113
-	{
114
-		return $this->getUri();
115
-	}
116
-
117
-	/**
118
-	 * Returns the URI with the given start and stop component.
119
-	 *
120
-	 * @param string $start = self::SCHEME
121
-	 * @param string $end = self::FRAGMENT
122
-	 * @return string the URI.
123
-	 */
124
-	public function getUri($start = self::SCHEME, $end = self::FRAGMENT)
125
-	{
126
-		$result = '';
127
-
128
-		switch ($start) {
129
-			default:
130
-			case static::SCHEME:
131
-				$scheme = $this->getScheme();
132
-
133
-				if ($scheme) {
134
-					$result .= $scheme . static::DELIMITER_SCHEME;
135
-				}
136
-
137
-				if ($end === static::SCHEME) {
138
-					break;
139
-				}
22
+    const DELIMITER_SCHEME = ':';
23
+    const DELIMITER_AUTHORITY = '//';
24
+    const DELIMITER_USER = '@';
25
+    const DELIMITER_PASSWORD = ':';
26
+    const DELIMITER_PORT = ':';
27
+    const DELIMITER_PATH = '/';
28
+    const DELIMITER_QUERY = '?';
29
+    const DELIMITER_QUERY_PAIR = '&';
30
+    const DELIMITER_QUERY_KEY_VALUE = '=';
31
+    const DELIMITER_FRAGMENT = '#';
32
+
33
+    const SCHEME = 'scheme';
34
+    const AUTHORITY = 'authority';
35
+    const USERNAME = 'user';
36
+    const PASSWORD = 'pass';
37
+    const HOST = 'host';
38
+    const PORT = 'port';
39
+    const PATH = 'path';
40
+    const DIRECTORY = 'directory';
41
+    const FILE = 'file';
42
+    const QUERY = 'query';
43
+    const FRAGMENT = 'fragment';
44
+
45
+    /** @var string The scheme. */
46
+    private $scheme;
47
+
48
+    /** @var string The username. */
49
+    private $username;
50
+
51
+    /** @var string|null The password. */
52
+    private $password;
53
+
54
+    /** @var string The host. */
55
+    private $host;
56
+
57
+    /** @var int|null The port. */
58
+    private $port;
59
+
60
+    /** @var string The directory. */
61
+    private $directory;
62
+
63
+    /** @var string The file. */
64
+    private $file;
65
+
66
+    /** @var array The query. */
67
+    private $query;
68
+
69
+    /** @var string The fragment. */
70
+    private $fragment;
71
+
72
+    /**
73
+     * Construct a URI object with the given URI.
74
+     *
75
+     * @param string $uri
76
+     * @throws \UnexpectedValueException
77
+     */
78
+    public function __construct($uri)
79
+    {
80
+        $component = parse_url($uri);
81
+
82
+        if ($component === false) {
83
+            throw new \UnexpectedValueException('Invalid uri');
84
+        }
85
+
86
+        // Replace with the null coalescing in PHP7. E.g. $component[scheme] ?? ''
87
+        $component += [
88
+            static::SCHEME => '',
89
+            static::USERNAME => '',
90
+            static::PASSWORD => null,
91
+            static::HOST => '',
92
+            static::PORT => null,
93
+            static::PATH => '',
94
+            static::QUERY => '',
95
+            static::FRAGMENT => ''
96
+        ];
97
+
98
+        $this->setScheme($component[static::SCHEME]);
99
+        $this->setUserInfo($component[static::USERNAME], $component[static::PASSWORD]);
100
+        $this->setHost($component[static::HOST]);
101
+        $this->setPort($component[static::PORT]);
102
+        $this->setPath($component[static::PATH]);
103
+        $this->setQuery($component[static::QUERY]);
104
+        $this->setFragment($component[static::FRAGMENT]);
105
+    }
106
+
107
+    /**
108
+     * Returns a string representation of the URI object.
109
+     *
110
+     * @return string a string representation of the URI object.
111
+     */
112
+    public function __toString()
113
+    {
114
+        return $this->getUri();
115
+    }
116
+
117
+    /**
118
+     * Returns the URI with the given start and stop component.
119
+     *
120
+     * @param string $start = self::SCHEME
121
+     * @param string $end = self::FRAGMENT
122
+     * @return string the URI.
123
+     */
124
+    public function getUri($start = self::SCHEME, $end = self::FRAGMENT)
125
+    {
126
+        $result = '';
127
+
128
+        switch ($start) {
129
+            default:
130
+            case static::SCHEME:
131
+                $scheme = $this->getScheme();
132
+
133
+                if ($scheme) {
134
+                    $result .= $scheme . static::DELIMITER_SCHEME;
135
+                }
136
+
137
+                if ($end === static::SCHEME) {
138
+                    break;
139
+                }
140 140
 
141
-				// no break
141
+                // no break
142 142
 
143
-			case static::AUTHORITY:
144
-			case static::USERNAME:
145
-				$username = $this->getUserInfo();
143
+            case static::AUTHORITY:
144
+            case static::USERNAME:
145
+                $username = $this->getUserInfo();
146 146
 
147
-				if ($username && $this->getHost()) {
148
-					$result .= static::DELIMITER_AUTHORITY . $username . static::DELIMITER_USER;
149
-				}
147
+                if ($username && $this->getHost()) {
148
+                    $result .= static::DELIMITER_AUTHORITY . $username . static::DELIMITER_USER;
149
+                }
150 150
 
151
-				if ($end === static::USERNAME) {
152
-					break;
153
-				}
154
-
155
-				// no break
156
-
157
-			case static::HOST:
158
-				$host = $this->getHost();
159
-
160
-				if ($host && ($result === '' || !$this->getUserInfo())) {
161
-					$result .= static::DELIMITER_AUTHORITY;
162
-				}
163
-
164
-				$result .= $host;
165
-
166
-				if ($end === static::HOST) {
167
-					break;
168
-				}
169
-
170
-				// no break
171
-
172
-			case static::PORT:
173
-				$port = $this->getPort();
174
-
175
-				if ($port !== null && $this->getHost()) {
176
-					$result .= static::DELIMITER_PORT . $port;
177
-				}
178
-
179
-				if ($end === static::PORT || $end === static::AUTHORITY) {
180
-					break;
181
-				}
182
-
183
-				// no break
184
-
185
-			case static::PATH:
186
-			case static::DIRECTORY:
187
-				$directory = $this->getDirectory();
188
-
189
-				if ($result !== '' && $directory !== '' && mb_substr($directory, 0, 1) !== static::DELIMITER_PATH) {
190
-					$result .= static::DELIMITER_PATH;
191
-				}
192
-
193
-				$result .= $directory;
194
-
195
-				if ($end === static::DIRECTORY) {
196
-					break;
197
-				}
198
-
199
-				// no break
200
-
201
-			case static::FILE:
202
-				$file = $this->getFile();
203
-
204
-				if ($result !== '' && mb_substr($result, -1) !== static::DELIMITER_PATH && $file !== '') {
205
-					$result .= static::DELIMITER_PATH;
206
-				}
207
-
208
-				$result .= $this->getFile();
209
-
210
-				if ($end === static::FILE || $end === static::PATH) {
211
-					break;
212
-				}
213
-
214
-				// no break
215
-
216
-			case static::QUERY:
217
-				$query = $this->getQuery();
218
-
219
-				if ($query) {
220
-					$result .= static::DELIMITER_QUERY . $query;
221
-				}
222
-
223
-				if ($end === static::QUERY) {
224
-					break;
225
-				}
151
+                if ($end === static::USERNAME) {
152
+                    break;
153
+                }
154
+
155
+                // no break
156
+
157
+            case static::HOST:
158
+                $host = $this->getHost();
159
+
160
+                if ($host && ($result === '' || !$this->getUserInfo())) {
161
+                    $result .= static::DELIMITER_AUTHORITY;
162
+                }
163
+
164
+                $result .= $host;
165
+
166
+                if ($end === static::HOST) {
167
+                    break;
168
+                }
169
+
170
+                // no break
171
+
172
+            case static::PORT:
173
+                $port = $this->getPort();
174
+
175
+                if ($port !== null && $this->getHost()) {
176
+                    $result .= static::DELIMITER_PORT . $port;
177
+                }
178
+
179
+                if ($end === static::PORT || $end === static::AUTHORITY) {
180
+                    break;
181
+                }
182
+
183
+                // no break
184
+
185
+            case static::PATH:
186
+            case static::DIRECTORY:
187
+                $directory = $this->getDirectory();
188
+
189
+                if ($result !== '' && $directory !== '' && mb_substr($directory, 0, 1) !== static::DELIMITER_PATH) {
190
+                    $result .= static::DELIMITER_PATH;
191
+                }
192
+
193
+                $result .= $directory;
194
+
195
+                if ($end === static::DIRECTORY) {
196
+                    break;
197
+                }
198
+
199
+                // no break
200
+
201
+            case static::FILE:
202
+                $file = $this->getFile();
203
+
204
+                if ($result !== '' && mb_substr($result, -1) !== static::DELIMITER_PATH && $file !== '') {
205
+                    $result .= static::DELIMITER_PATH;
206
+                }
207
+
208
+                $result .= $this->getFile();
209
+
210
+                if ($end === static::FILE || $end === static::PATH) {
211
+                    break;
212
+                }
213
+
214
+                // no break
215
+
216
+            case static::QUERY:
217
+                $query = $this->getQuery();
218
+
219
+                if ($query) {
220
+                    $result .= static::DELIMITER_QUERY . $query;
221
+                }
222
+
223
+                if ($end === static::QUERY) {
224
+                    break;
225
+                }
226 226
 
227
-				// no break
228
-
229
-			case static::FRAGMENT:
230
-				$fragment = $this->getFragment();
227
+                // no break
228
+
229
+            case static::FRAGMENT:
230
+                $fragment = $this->getFragment();
231 231
 
232
-				if ($fragment) {
233
-					$result .= static::DELIMITER_FRAGMENT . $fragment;
234
-				}
235
-
236
-				// no break
237
-		}
238
-
239
-		return $result;
240
-	}
241
-
242
-	/**
243
-	 * {@inheritdoc}
244
-	 */
245
-	public function getScheme()
246
-	{
247
-		return $this->scheme;
248
-	}
249
-
250
-	/**
251
-	 * Set the scheme.
252
-	 *
253
-	 * @param string $scheme
254
-	 * @return $this
255
-	 */
256
-	private function setScheme($scheme)
257
-	{
258
-		$this->scheme = strtolower($scheme);
259
-
260
-		return $this;
261
-	}
262
-
263
-	/**
264
-	 * {@inheritdoc}
265
-	 */
266
-	public function withScheme($scheme)
267
-	{
268
-		$result = clone $this;
269
-
270
-		return $result->setScheme($scheme);
271
-	}
272
-
273
-	/**
274
-	 * {@inheritdoc}
275
-	 */
276
-	public function getAuthority()
277
-	{
278
-		if (!$this->getHost()) {
279
-			return '';
280
-		}
281
-
282
-		return mb_substr($this->getUri(self::USERNAME, self::PORT), 2);
283
-	}
284
-
285
-	/**
286
-	 * {@inheritdoc}
287
-	 */
288
-	public function getUserInfo()
289
-	{
290
-		$result = $this->username;
291
-
292
-		if ($this->password !== null) {
293
-			$result .= static::DELIMITER_PASSWORD . $this->password;
294
-		}
295
-
296
-		return $result;
297
-	}
298
-
299
-	/**
300
-	 * Set the user info.
301
-	 *
302
-	 * @param string $username
303
-	 * @param string|null $password = null
304
-	 * @return $this
305
-	 */
306
-	private function setUserInfo($username, $password = null)
307
-	{
308
-		$this->username = $username;
309
-		$this->password = $password;
310
-
311
-		return $this;
312
-	}
313
-
314
-	/**
315
-	 * {@inheritdoc}
316
-	 */
317
-	public function withUserInfo($username, $password = null)
318
-	{
319
-		$result = clone $this;
320
-
321
-		return $result->setUserInfo($username, $password);
322
-	}
323
-
324
-	/**
325
-	 * {@inheritdoc}
326
-	 */
327
-	public function getHost()
328
-	{
329
-		return $this->host;
330
-	}
331
-
332
-	/**
333
-	 * Set the host.
334
-	 *
335
-	 * @param string $host
336
-	 * @return $this
337
-	 */
338
-	private function setHost($host)
339
-	{
340
-		$this->host = strtolower($host);
341
-
342
-		return $this;
343
-	}
344
-
345
-	/**
346
-	 * {@inheritdoc}
347
-	 */
348
-	public function withHost($host)
349
-	{
350
-		$result = clone $this;
351
-
352
-		return $result->setHost($host);
353
-	}
354
-
355
-	/**
356
-	 * {@inheritdoc}
357
-	 */
358
-	public function getPort()
359
-	{
360
-		return $this->port;
361
-	}
362
-
363
-	/**
364
-	 * Set the port.
365
-	 *
366
-	 * @param int|null $port
367
-	 * @return $this
368
-	 * @throws \InvalidArgumentException
369
-	 */
370
-	private function setPort($port = null)
371
-	{
372
-		if ($port !== null && (1 > $port || 0xffff < $port)) {
373
-			throw new \InvalidArgumentException('Invalid port');
374
-		}
375
-
376
-		$this->port = $port;
377
-
378
-		return $this;
379
-	}
380
-
381
-	/**
382
-	 * {@inheritdoc}
383
-	 */
384
-	public function withPort($port)
385
-	{
386
-		$result = clone $this;
387
-
388
-		return $result->setPort($port);
389
-	}
390
-
391
-	/**
392
-	 * {@inheritdoc}
393
-	 */
394
-	public function getPath()
395
-	{
396
-		$result = $this->getDirectory();
397
-
398
-		if ($result !== '' && mb_substr($result, -1) !== static::DELIMITER_PATH && $this->getFile()) {
399
-			$result .= static::DELIMITER_PATH;
400
-		}
401
-
402
-		return $result . $this->getFile();
403
-	}
404
-
405
-	/**
406
-	 * Set the path.
407
-	 *
408
-	 * @param string $path
409
-	 * @return $this
410
-	 */
411
-	private function setPath($path)
412
-	{
413
-		$directory = dirname($path);
414
-		$file = basename($path);
415
-
416
-		// If dirname is '.'. Then remove it.
417
-		if ($directory === '.') {
418
-			$directory = '';
419
-		}
420
-
421
-		// If the path ends with '/'. Then there is no file.
422
-		if (mb_substr($path, -1) === static::DELIMITER_PATH) {
423
-			$directory = $path;
424
-			$file = '';
425
-		}
426
-
427
-		// If the dirname and basename are both set. Then add the missing '/'.
428
-		if (mb_substr($directory, -1) !== static::DELIMITER_PATH && $directory !== '' && $file !== '') {
429
-			$directory .= static::DELIMITER_PATH;
430
-		}
431
-
432
-		$this->setDirectory($directory);
433
-		$this->setFile($file);
434
-
435
-		return $this;
436
-	}
437
-
438
-	/**
439
-	 * {@inheritdoc}
440
-	 */
441
-	public function withPath($path)
442
-	{
443
-		$result = clone $this;
444
-
445
-		return $result->setPath($path);
446
-	}
447
-
448
-	/**
449
-	 * Returns the URI segements
450
-	 *
451
-	 * @return string[] the URI segments
452
-	 */
453
-	public function getSegments()
454
-	{
455
-		// array_values reindexes the array and array_diff removes the empty elements.
456
-		return array_values(array_diff(explode(static::DELIMITER_PATH, $this->getPath()), ['']));
457
-	}
458
-
459
-	/**
460
-	 * Returns the segment at the given index or null if the segment at the given index doesn't exists.
461
-	 *
462
-	 * @param int $index
463
-	 * @return string|null the segment at the given index or null if the segment at the given index doesn't exists
464
-	 */
465
-	public function getSegment($index)
466
-	{
467
-		$result = $this->getSegments();
468
-
469
-		return isset($result[$index]) ? $result[$index] : null;
470
-	}
471
-
472
-	/**
473
-	 * Returns the directory.
474
-	 *
475
-	 * @return string the directory.
476
-	 */
477
-	public function getDirectory()
478
-	{
479
-		return $this->directory;
480
-	}
481
-
482
-	/**
483
-	 * Set the directory.
484
-	 *
485
-	 * @param string $directory
486
-	 * @return $this
487
-	 */
488
-	private function setDirectory($directory)
489
-	{
490
-		$this->directory = $directory;
491
-
492
-		return $this;
493
-	}
494
-
495
-	/**
496
-	 * Return an instance with the specified directory.
497
-	 *
498
-	 * @param string $directory
499
-	 * @return self
500
-	 */
501
-	public function withDirectory($directory)
502
-	{
503
-		$result = clone $this;
504
-
505
-		return $result->setDirectory($directory);
506
-	}
507
-
508
-	/**
509
-	 * Returns the file.
510
-	 *
511
-	 * @return string the file.
512
-	 */
513
-	public function getFile()
514
-	{
515
-		return $this->file;
516
-	}
517
-
518
-	/**
519
-	 * Set the file.
520
-	 *
521
-	 * @param string $file
522
-	 * @return $this
523
-	 */
524
-	private function setFile($file)
525
-	{
526
-		$this->file = $file;
527
-
528
-		return $this;
529
-	}
530
-
531
-	/**
532
-	 * Return an instance with the specified file.
533
-	 *
534
-	 * @param string $file
535
-	 * @return self
536
-	 */
537
-	public function withFile($file)
538
-	{
539
-		$result = clone $this;
540
-
541
-		return $result->setFile($file);
542
-	}
543
-
544
-	/**
545
-	 * {@inheritdoc}
546
-	 */
547
-	public function getQuery()
548
-	{
549
-		return http_build_query($this->query);
550
-	}
551
-
552
-	/**
553
-	 * Set the query.
554
-	 *
555
-	 * @param string $query
556
-	 * @return $this
557
-	 */
558
-	private function setQuery($query)
559
-	{
560
-		$this->query = [];
561
-
562
-		parse_str($query, $this->query);
563
-
564
-		return $this;
565
-	}
566
-
567
-	/**
568
-	 * {@inheritdoc}
569
-	 */
570
-	public function withQuery($query)
571
-	{
572
-		$result = clone $this;
573
-
574
-		return $result->setQuery($query);
575
-	}
576
-
577
-	/**
578
-	 * Returns the value to which the specified key is mapped, or null if the query map contains no mapping for the key.
579
-	 *
580
-	 * @param string $key
581
-	 * @return string the value to which the specified key is mapped, or null if the query map contains no mapping for the key.
582
-	 */
583
-	public function getQueryValue($key)
584
-	{
585
-		return isset($this->query[$key]) ? $this->query[$key] : null;
586
-	}
587
-
588
-	/**
589
-	 * Associates the specified value with the specified key in the query map.
590
-	 *
591
-	 * @param string $key
592
-	 * @param string $value
593
-	 * @return $this
594
-	 */
595
-	private function setQueryValue($key, $value)
596
-	{
597
-		$this->query[$key] = $value;
598
-
599
-		return $this;
600
-	}
601
-
602
-	/**
603
-	 * Return an instance with the specified query value.
604
-	 *
605
-	 * @param string $key
606
-	 * @param string $value
607
-	 * @return self
608
-	 */
609
-	public function withQueryValue($key, $value)
610
-	{
611
-		$result = clone $this;
612
-
613
-		return $result->setQueryValue($key, $value);
614
-	}
615
-
616
-	/**
617
-	 * {@inheritdoc}
618
-	 */
619
-	public function getFragment()
620
-	{
621
-		return $this->fragment;
622
-	}
623
-
624
-	/**
625
-	 * Set the fragment.
626
-	 *
627
-	 * @param string $fragment
628
-	 * @return $this
629
-	 */
630
-	private function setFragment($fragment)
631
-	{
632
-		$this->fragment = $fragment;
633
-
634
-		return $this;
635
-	}
636
-
637
-	/**
638
-	 * {@inheritdoc}
639
-	 */
640
-	public function withFragment($fragment)
641
-	{
642
-		$result = clone $this;
643
-
644
-		return $result->setFragment($fragment);
645
-	}
646
-
647
-	/**
648
-	 * Returns an instance with the decoded URI.
649
-	 *
650
-	 * @return self
651
-	 */
652
-	public function decode()
653
-	{
654
-		return new URI(html_entity_decode($this));
655
-	}
656
-
657
-	/**
658
-	 * Returns an instance with the encoded URI.
659
-	 *
660
-	 * @return self
661
-	 */
662
-	public function encode()
663
-	{
664
-		return new URI(htmlentities($this));
665
-	}
232
+                if ($fragment) {
233
+                    $result .= static::DELIMITER_FRAGMENT . $fragment;
234
+                }
235
+
236
+                // no break
237
+        }
238
+
239
+        return $result;
240
+    }
241
+
242
+    /**
243
+     * {@inheritdoc}
244
+     */
245
+    public function getScheme()
246
+    {
247
+        return $this->scheme;
248
+    }
249
+
250
+    /**
251
+     * Set the scheme.
252
+     *
253
+     * @param string $scheme
254
+     * @return $this
255
+     */
256
+    private function setScheme($scheme)
257
+    {
258
+        $this->scheme = strtolower($scheme);
259
+
260
+        return $this;
261
+    }
262
+
263
+    /**
264
+     * {@inheritdoc}
265
+     */
266
+    public function withScheme($scheme)
267
+    {
268
+        $result = clone $this;
269
+
270
+        return $result->setScheme($scheme);
271
+    }
272
+
273
+    /**
274
+     * {@inheritdoc}
275
+     */
276
+    public function getAuthority()
277
+    {
278
+        if (!$this->getHost()) {
279
+            return '';
280
+        }
281
+
282
+        return mb_substr($this->getUri(self::USERNAME, self::PORT), 2);
283
+    }
284
+
285
+    /**
286
+     * {@inheritdoc}
287
+     */
288
+    public function getUserInfo()
289
+    {
290
+        $result = $this->username;
291
+
292
+        if ($this->password !== null) {
293
+            $result .= static::DELIMITER_PASSWORD . $this->password;
294
+        }
295
+
296
+        return $result;
297
+    }
298
+
299
+    /**
300
+     * Set the user info.
301
+     *
302
+     * @param string $username
303
+     * @param string|null $password = null
304
+     * @return $this
305
+     */
306
+    private function setUserInfo($username, $password = null)
307
+    {
308
+        $this->username = $username;
309
+        $this->password = $password;
310
+
311
+        return $this;
312
+    }
313
+
314
+    /**
315
+     * {@inheritdoc}
316
+     */
317
+    public function withUserInfo($username, $password = null)
318
+    {
319
+        $result = clone $this;
320
+
321
+        return $result->setUserInfo($username, $password);
322
+    }
323
+
324
+    /**
325
+     * {@inheritdoc}
326
+     */
327
+    public function getHost()
328
+    {
329
+        return $this->host;
330
+    }
331
+
332
+    /**
333
+     * Set the host.
334
+     *
335
+     * @param string $host
336
+     * @return $this
337
+     */
338
+    private function setHost($host)
339
+    {
340
+        $this->host = strtolower($host);
341
+
342
+        return $this;
343
+    }
344
+
345
+    /**
346
+     * {@inheritdoc}
347
+     */
348
+    public function withHost($host)
349
+    {
350
+        $result = clone $this;
351
+
352
+        return $result->setHost($host);
353
+    }
354
+
355
+    /**
356
+     * {@inheritdoc}
357
+     */
358
+    public function getPort()
359
+    {
360
+        return $this->port;
361
+    }
362
+
363
+    /**
364
+     * Set the port.
365
+     *
366
+     * @param int|null $port
367
+     * @return $this
368
+     * @throws \InvalidArgumentException
369
+     */
370
+    private function setPort($port = null)
371
+    {
372
+        if ($port !== null && (1 > $port || 0xffff < $port)) {
373
+            throw new \InvalidArgumentException('Invalid port');
374
+        }
375
+
376
+        $this->port = $port;
377
+
378
+        return $this;
379
+    }
380
+
381
+    /**
382
+     * {@inheritdoc}
383
+     */
384
+    public function withPort($port)
385
+    {
386
+        $result = clone $this;
387
+
388
+        return $result->setPort($port);
389
+    }
390
+
391
+    /**
392
+     * {@inheritdoc}
393
+     */
394
+    public function getPath()
395
+    {
396
+        $result = $this->getDirectory();
397
+
398
+        if ($result !== '' && mb_substr($result, -1) !== static::DELIMITER_PATH && $this->getFile()) {
399
+            $result .= static::DELIMITER_PATH;
400
+        }
401
+
402
+        return $result . $this->getFile();
403
+    }
404
+
405
+    /**
406
+     * Set the path.
407
+     *
408
+     * @param string $path
409
+     * @return $this
410
+     */
411
+    private function setPath($path)
412
+    {
413
+        $directory = dirname($path);
414
+        $file = basename($path);
415
+
416
+        // If dirname is '.'. Then remove it.
417
+        if ($directory === '.') {
418
+            $directory = '';
419
+        }
420
+
421
+        // If the path ends with '/'. Then there is no file.
422
+        if (mb_substr($path, -1) === static::DELIMITER_PATH) {
423
+            $directory = $path;
424
+            $file = '';
425
+        }
426
+
427
+        // If the dirname and basename are both set. Then add the missing '/'.
428
+        if (mb_substr($directory, -1) !== static::DELIMITER_PATH && $directory !== '' && $file !== '') {
429
+            $directory .= static::DELIMITER_PATH;
430
+        }
431
+
432
+        $this->setDirectory($directory);
433
+        $this->setFile($file);
434
+
435
+        return $this;
436
+    }
437
+
438
+    /**
439
+     * {@inheritdoc}
440
+     */
441
+    public function withPath($path)
442
+    {
443
+        $result = clone $this;
444
+
445
+        return $result->setPath($path);
446
+    }
447
+
448
+    /**
449
+     * Returns the URI segements
450
+     *
451
+     * @return string[] the URI segments
452
+     */
453
+    public function getSegments()
454
+    {
455
+        // array_values reindexes the array and array_diff removes the empty elements.
456
+        return array_values(array_diff(explode(static::DELIMITER_PATH, $this->getPath()), ['']));
457
+    }
458
+
459
+    /**
460
+     * Returns the segment at the given index or null if the segment at the given index doesn't exists.
461
+     *
462
+     * @param int $index
463
+     * @return string|null the segment at the given index or null if the segment at the given index doesn't exists
464
+     */
465
+    public function getSegment($index)
466
+    {
467
+        $result = $this->getSegments();
468
+
469
+        return isset($result[$index]) ? $result[$index] : null;
470
+    }
471
+
472
+    /**
473
+     * Returns the directory.
474
+     *
475
+     * @return string the directory.
476
+     */
477
+    public function getDirectory()
478
+    {
479
+        return $this->directory;
480
+    }
481
+
482
+    /**
483
+     * Set the directory.
484
+     *
485
+     * @param string $directory
486
+     * @return $this
487
+     */
488
+    private function setDirectory($directory)
489
+    {
490
+        $this->directory = $directory;
491
+
492
+        return $this;
493
+    }
494
+
495
+    /**
496
+     * Return an instance with the specified directory.
497
+     *
498
+     * @param string $directory
499
+     * @return self
500
+     */
501
+    public function withDirectory($directory)
502
+    {
503
+        $result = clone $this;
504
+
505
+        return $result->setDirectory($directory);
506
+    }
507
+
508
+    /**
509
+     * Returns the file.
510
+     *
511
+     * @return string the file.
512
+     */
513
+    public function getFile()
514
+    {
515
+        return $this->file;
516
+    }
517
+
518
+    /**
519
+     * Set the file.
520
+     *
521
+     * @param string $file
522
+     * @return $this
523
+     */
524
+    private function setFile($file)
525
+    {
526
+        $this->file = $file;
527
+
528
+        return $this;
529
+    }
530
+
531
+    /**
532
+     * Return an instance with the specified file.
533
+     *
534
+     * @param string $file
535
+     * @return self
536
+     */
537
+    public function withFile($file)
538
+    {
539
+        $result = clone $this;
540
+
541
+        return $result->setFile($file);
542
+    }
543
+
544
+    /**
545
+     * {@inheritdoc}
546
+     */
547
+    public function getQuery()
548
+    {
549
+        return http_build_query($this->query);
550
+    }
551
+
552
+    /**
553
+     * Set the query.
554
+     *
555
+     * @param string $query
556
+     * @return $this
557
+     */
558
+    private function setQuery($query)
559
+    {
560
+        $this->query = [];
561
+
562
+        parse_str($query, $this->query);
563
+
564
+        return $this;
565
+    }
566
+
567
+    /**
568
+     * {@inheritdoc}
569
+     */
570
+    public function withQuery($query)
571
+    {
572
+        $result = clone $this;
573
+
574
+        return $result->setQuery($query);
575
+    }
576
+
577
+    /**
578
+     * Returns the value to which the specified key is mapped, or null if the query map contains no mapping for the key.
579
+     *
580
+     * @param string $key
581
+     * @return string the value to which the specified key is mapped, or null if the query map contains no mapping for the key.
582
+     */
583
+    public function getQueryValue($key)
584
+    {
585
+        return isset($this->query[$key]) ? $this->query[$key] : null;
586
+    }
587
+
588
+    /**
589
+     * Associates the specified value with the specified key in the query map.
590
+     *
591
+     * @param string $key
592
+     * @param string $value
593
+     * @return $this
594
+     */
595
+    private function setQueryValue($key, $value)
596
+    {
597
+        $this->query[$key] = $value;
598
+
599
+        return $this;
600
+    }
601
+
602
+    /**
603
+     * Return an instance with the specified query value.
604
+     *
605
+     * @param string $key
606
+     * @param string $value
607
+     * @return self
608
+     */
609
+    public function withQueryValue($key, $value)
610
+    {
611
+        $result = clone $this;
612
+
613
+        return $result->setQueryValue($key, $value);
614
+    }
615
+
616
+    /**
617
+     * {@inheritdoc}
618
+     */
619
+    public function getFragment()
620
+    {
621
+        return $this->fragment;
622
+    }
623
+
624
+    /**
625
+     * Set the fragment.
626
+     *
627
+     * @param string $fragment
628
+     * @return $this
629
+     */
630
+    private function setFragment($fragment)
631
+    {
632
+        $this->fragment = $fragment;
633
+
634
+        return $this;
635
+    }
636
+
637
+    /**
638
+     * {@inheritdoc}
639
+     */
640
+    public function withFragment($fragment)
641
+    {
642
+        $result = clone $this;
643
+
644
+        return $result->setFragment($fragment);
645
+    }
646
+
647
+    /**
648
+     * Returns an instance with the decoded URI.
649
+     *
650
+     * @return self
651
+     */
652
+    public function decode()
653
+    {
654
+        return new URI(html_entity_decode($this));
655
+    }
656
+
657
+    /**
658
+     * Returns an instance with the encoded URI.
659
+     *
660
+     * @return self
661
+     */
662
+    public function encode()
663
+    {
664
+        return new URI(htmlentities($this));
665
+    }
666 666
 }
Please login to merge, or discard this patch.
src/ServerRequest.php 1 patch
Indentation   +408 added lines, -408 removed lines patch added patch discarded remove patch
@@ -21,412 +21,412 @@
 block discarded – undo
21 21
  */
22 22
 class ServerRequest extends Request implements ServerRequestInterface
23 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
-	public function __construct($method = '', UriInterface $uri = null, $version = self::DEFAULT_VERSION, array $headers = [], StreamInterface $body = null)
64
-	{
65
-		if ($body === null) {
66
-			$body = new Stream(fopen('php://input', 'r'));
67
-		}
68
-
69
-		$this->serverParams = $_SERVER;
70
-		$this->cookieParams = $_COOKIE;
71
-		$this->queryParams = $this->initQueryParams($this->serverParams);
72
-		$this->postParams = $_POST;
73
-		$this->filesParams = $_FILES;
74
-		$this->uploadedFiles = $this->initUploadedFiles($this->filesParams);
75
-		$this->attributes = [];
76
-
77
-		parent::__construct($this->initMethod($method), $this->initUri($uri), $version, $this->initHeaders($headers), $body);
78
-	}
79
-
80
-	/**
81
-	 * Initialize the method.
82
-	 *
83
-	 * @param string $method
84
-	 * @return string the method.
85
-	 */
86
-	private function initMethod($method)
87
-	{
88
-		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
-	private function initUri($uri)
98
-	{
99
-		if ($uri !== null) {
100
-			return $uri;
101
-		}
102
-
103
-		$scheme = isset($this->getServerParams()['HTTPS']) ? 'https://' : 'http://';
104
-		$host = isset($this->getServerParams()['HTTP_HOST']) ? $scheme . $this->getServerParams()['HTTP_HOST'] : '';
105
-		$path = isset($this->getServerParams()['REQUEST_URI']) ? $this->getServerParams()['REQUEST_URI'] : '';
106
-
107
-		return new URI($host . $path);
108
-	}
109
-
110
-	/**
111
-	 * Initialize the headers.
112
-	 *
113
-	 * @param array $headers
114
-	 * @return array the headers.
115
-	 */
116
-	private function initHeaders($headers)
117
-	{
118
-		return $headers ?: getallheaders();
119
-	}
120
-
121
-	/**
122
-	 * Initialize the headers.
123
-	 *
124
-	 * @param string $serverParams
125
-	 * @return array the headers.
126
-	 */
127
-	private function initQueryParams($serverParams)
128
-	{
129
-		$result = [];
130
-
131
-		if (isset($serverParams['REQUEST_URI']) && ($query = parse_url($serverParams['REQUEST_URI'], \PHP_URL_QUERY))) {
132
-			parse_str($query, $result);
133
-		}
134
-
135
-		return $result ?? [];
136
-	}
137
-
138
-	/**
139
-	 * Initialize the uploaded files.
140
-	 *
141
-	 * @param array $files
142
-	 * @return array the uploaded files.
143
-	 */
144
-	private function initUploadedFiles(array $files)
145
-	{
146
-		$result = [];
147
-
148
-		foreach ($files as $key => $value) {
149
-			$result[$key] = $this->parseUploadedFiles($value);
150
-		}
151
-
152
-		return $result;
153
-	}
154
-
155
-	/**
156
-	 * Parse uploaded files.
157
-	 *
158
-	 * @param array $files
159
-	 * @return UploadedFile|array uploaded files.
160
-	 */
161
-	private function parseUploadedFiles($files)
162
-	{
163
-		// Empty
164
-		$first = reset($files);
165
-
166
-		// Single
167
-		if (!is_array($first)) {
168
-			return $this->parseSingleUploadedFiles($files);
169
-		}
170
-
171
-		// Multiple
172
-		if (count(array_filter(array_keys($first), 'is_string')) === 0) {
173
-			return $this->parseMultipleUploadedFiles($files);
174
-		}
175
-
176
-		// Namespace
177
-		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
-	private function parseSingleUploadedFiles(array $file)
187
-	{
188
-		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
-	private function parseMultipleUploadedFiles(array $files)
198
-	{
199
-		$count = count($files['name']);
200
-		$result = [];
201
-
202
-		for ($i = 0; $i < $count; $i++) {
203
-			$result[] = new UploadedFile($files['name'][$i], $files['type'][$i], $files['tmp_name'][$i], $files['error'][$i], $files['size'][$i]);
204
-		}
205
-
206
-		return $result;
207
-	}
208
-
209
-	/**
210
-	 * {@inheritdoc}
211
-	 */
212
-	public function getServerParams()
213
-	{
214
-		return $this->serverParams;
215
-	}
216
-
217
-	/**
218
-	 * {@inheritdoc}
219
-	 */
220
-	public function getCookieParams()
221
-	{
222
-		return $this->cookieParams;
223
-	}
224
-
225
-	/**
226
-	 * Set the cookie params.
227
-	 *
228
-	 * @param array $cookieParams
229
-	 * @return $this
230
-	 */
231
-	private function setCookieParams(array $cookieParams)
232
-	{
233
-		$this->cookieParams = $cookieParams;
234
-
235
-		return $this;
236
-	}
237
-
238
-	/**
239
-	 * {@inheritdoc}
240
-	 */
241
-	public function withCookieParams(array $cookieParams)
242
-	{
243
-		$result = clone $this;
244
-
245
-		return $result->setCookieParams($cookieParams);
246
-	}
247
-
248
-	/**
249
-	 * {@inheritdoc}
250
-	 */
251
-	public function getQueryParams()
252
-	{
253
-		return $this->queryParams;
254
-	}
255
-
256
-	/**
257
-	 * Set the query params.
258
-	 *
259
-	 * @param array $queryParams
260
-	 * @return $this
261
-	 */
262
-	private function setQueryParams(array $queryParams)
263
-	{
264
-		$this->queryParams = $queryParams;
265
-
266
-		return $this;
267
-	}
268
-
269
-	/**
270
-	 * {@inheritdoc}
271
-	 */
272
-	public function withQueryParams(array $queryParams)
273
-	{
274
-		$result = clone $this;
275
-
276
-		return $result->setQueryParams($queryParams);
277
-	}
278
-
279
-	/**
280
-	 * {@inheritdoc}
281
-	 */
282
-	public function getUploadedFiles()
283
-	{
284
-		return $this->uploadedFiles;
285
-	}
286
-
287
-	/**
288
-	 * Set the uploaded files.
289
-	 *
290
-	 * @param array $uploadedFiles
291
-	 * @return $this
292
-	 */
293
-	private function setUploadedFiles(array $uploadedFiles)
294
-	{
295
-		$this->uploadedFiles = $uploadedFiles;
296
-
297
-		return $this;
298
-	}
299
-
300
-	/**
301
-	 * {@inheritdoc}
302
-	 */
303
-	public function withUploadedFiles(array $uploadedFiles)
304
-	{
305
-		$result = clone $this;
306
-
307
-		return $result->setUploadedFiles($uploadedFiles);
308
-	}
309
-
310
-	/**
311
-	 * {@inheritdoc}
312
-	 */
313
-	public function getParsedBody()
314
-	{
315
-		if ($this->parsedBody !== null) {
316
-			return $this->parsedBody;
317
-		}
318
-
319
-		if ($this->getMethod() === 'POST' && ($this->hasContentType('application/x-www-form-urlencoded') || $this->hasContentType('multipart/form-data'))) {
320
-			return $this->postParams;
321
-		}
322
-
323
-		if ($this->hasContentType('application/json')) {
324
-			return json_decode((string) $this->getBody());
325
-		}
326
-
327
-		return null;
328
-	}
329
-
330
-	/**
331
-	 * Checks if a content type header exists with the given content type.
332
-	 *
333
-	 * @param string $contentType
334
-	 * @return bool true if a content type header exists with the given content type.
335
-	 */
336
-	private function hasContentType($contentType)
337
-	{
338
-		foreach ($this->getHeader('Content-Type') as $key => $value) {
339
-			if (mb_substr($value, 0, strlen($contentType)) == $contentType) {
340
-				return true;
341
-			}
342
-		}
343
-
344
-		return false;
345
-	}
346
-
347
-	/**
348
-	 * Set the parsed body.
349
-	 *
350
-	 * @param null|array|object $parsedBody
351
-	 * @return $this
352
-	 */
353
-	private function setParsedBody($parsedBody)
354
-	{
355
-		$this->parsedBody = $parsedBody;
356
-
357
-		return $this;
358
-	}
359
-
360
-	/**
361
-	 * {@inheritdoc}
362
-	 */
363
-	public function withParsedBody($parsedBody)
364
-	{
365
-		$result = clone $this;
366
-
367
-		return $result->setParsedBody($parsedBody);
368
-	}
369
-
370
-	/**
371
-	 * {@inheritdoc}
372
-	 */
373
-	public function getAttributes()
374
-	{
375
-		return $this->attributes;
376
-	}
377
-
378
-	/**
379
-	 * {@inheritdoc}
380
-	 */
381
-	public function getAttribute($name, $default = null)
382
-	{
383
-		return isset($this->attributes[$name]) ? $this->attributes[$name] : $default;
384
-	}
385
-
386
-	/**
387
-	 * Set the attribute.
388
-	 *
389
-	 * @param string $name
390
-	 * @param mixed $value
391
-	 * @return $this
392
-	 */
393
-	private function setAttribute($name, $value)
394
-	{
395
-		$this->attributes[$name] = $value;
396
-
397
-		return $this;
398
-	}
399
-
400
-	/**
401
-	 * {@inheritdoc}
402
-	 */
403
-	public function withAttribute($name, $value)
404
-	{
405
-		$result = clone $this;
406
-
407
-		return $result->setAttribute($name, $value);
408
-	}
409
-
410
-	/**
411
-	 * Remove the attribute.
412
-	 *
413
-	 * @param string $name
414
-	 * @return $this
415
-	 */
416
-	private function removeAttribute($name)
417
-	{
418
-		unset($this->attributes[$name]);
419
-
420
-		return $this;
421
-	}
422
-
423
-	/**
424
-	 * {@inheritdoc}
425
-	 */
426
-	public function withoutAttribute($name)
427
-	{
428
-		$result = clone $this;
429
-
430
-		return $result->removeAttribute($name);
431
-	}
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
+    public function __construct($method = '', UriInterface $uri = null, $version = self::DEFAULT_VERSION, array $headers = [], StreamInterface $body = null)
64
+    {
65
+        if ($body === null) {
66
+            $body = new Stream(fopen('php://input', 'r'));
67
+        }
68
+
69
+        $this->serverParams = $_SERVER;
70
+        $this->cookieParams = $_COOKIE;
71
+        $this->queryParams = $this->initQueryParams($this->serverParams);
72
+        $this->postParams = $_POST;
73
+        $this->filesParams = $_FILES;
74
+        $this->uploadedFiles = $this->initUploadedFiles($this->filesParams);
75
+        $this->attributes = [];
76
+
77
+        parent::__construct($this->initMethod($method), $this->initUri($uri), $version, $this->initHeaders($headers), $body);
78
+    }
79
+
80
+    /**
81
+     * Initialize the method.
82
+     *
83
+     * @param string $method
84
+     * @return string the method.
85
+     */
86
+    private function initMethod($method)
87
+    {
88
+        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
+    private function initUri($uri)
98
+    {
99
+        if ($uri !== null) {
100
+            return $uri;
101
+        }
102
+
103
+        $scheme = isset($this->getServerParams()['HTTPS']) ? 'https://' : 'http://';
104
+        $host = isset($this->getServerParams()['HTTP_HOST']) ? $scheme . $this->getServerParams()['HTTP_HOST'] : '';
105
+        $path = isset($this->getServerParams()['REQUEST_URI']) ? $this->getServerParams()['REQUEST_URI'] : '';
106
+
107
+        return new URI($host . $path);
108
+    }
109
+
110
+    /**
111
+     * Initialize the headers.
112
+     *
113
+     * @param array $headers
114
+     * @return array the headers.
115
+     */
116
+    private function initHeaders($headers)
117
+    {
118
+        return $headers ?: getallheaders();
119
+    }
120
+
121
+    /**
122
+     * Initialize the headers.
123
+     *
124
+     * @param string $serverParams
125
+     * @return array the headers.
126
+     */
127
+    private function initQueryParams($serverParams)
128
+    {
129
+        $result = [];
130
+
131
+        if (isset($serverParams['REQUEST_URI']) && ($query = parse_url($serverParams['REQUEST_URI'], \PHP_URL_QUERY))) {
132
+            parse_str($query, $result);
133
+        }
134
+
135
+        return $result ?? [];
136
+    }
137
+
138
+    /**
139
+     * Initialize the uploaded files.
140
+     *
141
+     * @param array $files
142
+     * @return array the uploaded files.
143
+     */
144
+    private function initUploadedFiles(array $files)
145
+    {
146
+        $result = [];
147
+
148
+        foreach ($files as $key => $value) {
149
+            $result[$key] = $this->parseUploadedFiles($value);
150
+        }
151
+
152
+        return $result;
153
+    }
154
+
155
+    /**
156
+     * Parse uploaded files.
157
+     *
158
+     * @param array $files
159
+     * @return UploadedFile|array uploaded files.
160
+     */
161
+    private function parseUploadedFiles($files)
162
+    {
163
+        // Empty
164
+        $first = reset($files);
165
+
166
+        // Single
167
+        if (!is_array($first)) {
168
+            return $this->parseSingleUploadedFiles($files);
169
+        }
170
+
171
+        // Multiple
172
+        if (count(array_filter(array_keys($first), 'is_string')) === 0) {
173
+            return $this->parseMultipleUploadedFiles($files);
174
+        }
175
+
176
+        // Namespace
177
+        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
+    private function parseSingleUploadedFiles(array $file)
187
+    {
188
+        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
+    private function parseMultipleUploadedFiles(array $files)
198
+    {
199
+        $count = count($files['name']);
200
+        $result = [];
201
+
202
+        for ($i = 0; $i < $count; $i++) {
203
+            $result[] = new UploadedFile($files['name'][$i], $files['type'][$i], $files['tmp_name'][$i], $files['error'][$i], $files['size'][$i]);
204
+        }
205
+
206
+        return $result;
207
+    }
208
+
209
+    /**
210
+     * {@inheritdoc}
211
+     */
212
+    public function getServerParams()
213
+    {
214
+        return $this->serverParams;
215
+    }
216
+
217
+    /**
218
+     * {@inheritdoc}
219
+     */
220
+    public function getCookieParams()
221
+    {
222
+        return $this->cookieParams;
223
+    }
224
+
225
+    /**
226
+     * Set the cookie params.
227
+     *
228
+     * @param array $cookieParams
229
+     * @return $this
230
+     */
231
+    private function setCookieParams(array $cookieParams)
232
+    {
233
+        $this->cookieParams = $cookieParams;
234
+
235
+        return $this;
236
+    }
237
+
238
+    /**
239
+     * {@inheritdoc}
240
+     */
241
+    public function withCookieParams(array $cookieParams)
242
+    {
243
+        $result = clone $this;
244
+
245
+        return $result->setCookieParams($cookieParams);
246
+    }
247
+
248
+    /**
249
+     * {@inheritdoc}
250
+     */
251
+    public function getQueryParams()
252
+    {
253
+        return $this->queryParams;
254
+    }
255
+
256
+    /**
257
+     * Set the query params.
258
+     *
259
+     * @param array $queryParams
260
+     * @return $this
261
+     */
262
+    private function setQueryParams(array $queryParams)
263
+    {
264
+        $this->queryParams = $queryParams;
265
+
266
+        return $this;
267
+    }
268
+
269
+    /**
270
+     * {@inheritdoc}
271
+     */
272
+    public function withQueryParams(array $queryParams)
273
+    {
274
+        $result = clone $this;
275
+
276
+        return $result->setQueryParams($queryParams);
277
+    }
278
+
279
+    /**
280
+     * {@inheritdoc}
281
+     */
282
+    public function getUploadedFiles()
283
+    {
284
+        return $this->uploadedFiles;
285
+    }
286
+
287
+    /**
288
+     * Set the uploaded files.
289
+     *
290
+     * @param array $uploadedFiles
291
+     * @return $this
292
+     */
293
+    private function setUploadedFiles(array $uploadedFiles)
294
+    {
295
+        $this->uploadedFiles = $uploadedFiles;
296
+
297
+        return $this;
298
+    }
299
+
300
+    /**
301
+     * {@inheritdoc}
302
+     */
303
+    public function withUploadedFiles(array $uploadedFiles)
304
+    {
305
+        $result = clone $this;
306
+
307
+        return $result->setUploadedFiles($uploadedFiles);
308
+    }
309
+
310
+    /**
311
+     * {@inheritdoc}
312
+     */
313
+    public function getParsedBody()
314
+    {
315
+        if ($this->parsedBody !== null) {
316
+            return $this->parsedBody;
317
+        }
318
+
319
+        if ($this->getMethod() === 'POST' && ($this->hasContentType('application/x-www-form-urlencoded') || $this->hasContentType('multipart/form-data'))) {
320
+            return $this->postParams;
321
+        }
322
+
323
+        if ($this->hasContentType('application/json')) {
324
+            return json_decode((string) $this->getBody());
325
+        }
326
+
327
+        return null;
328
+    }
329
+
330
+    /**
331
+     * Checks if a content type header exists with the given content type.
332
+     *
333
+     * @param string $contentType
334
+     * @return bool true if a content type header exists with the given content type.
335
+     */
336
+    private function hasContentType($contentType)
337
+    {
338
+        foreach ($this->getHeader('Content-Type') as $key => $value) {
339
+            if (mb_substr($value, 0, strlen($contentType)) == $contentType) {
340
+                return true;
341
+            }
342
+        }
343
+
344
+        return false;
345
+    }
346
+
347
+    /**
348
+     * Set the parsed body.
349
+     *
350
+     * @param null|array|object $parsedBody
351
+     * @return $this
352
+     */
353
+    private function setParsedBody($parsedBody)
354
+    {
355
+        $this->parsedBody = $parsedBody;
356
+
357
+        return $this;
358
+    }
359
+
360
+    /**
361
+     * {@inheritdoc}
362
+     */
363
+    public function withParsedBody($parsedBody)
364
+    {
365
+        $result = clone $this;
366
+
367
+        return $result->setParsedBody($parsedBody);
368
+    }
369
+
370
+    /**
371
+     * {@inheritdoc}
372
+     */
373
+    public function getAttributes()
374
+    {
375
+        return $this->attributes;
376
+    }
377
+
378
+    /**
379
+     * {@inheritdoc}
380
+     */
381
+    public function getAttribute($name, $default = null)
382
+    {
383
+        return isset($this->attributes[$name]) ? $this->attributes[$name] : $default;
384
+    }
385
+
386
+    /**
387
+     * Set the attribute.
388
+     *
389
+     * @param string $name
390
+     * @param mixed $value
391
+     * @return $this
392
+     */
393
+    private function setAttribute($name, $value)
394
+    {
395
+        $this->attributes[$name] = $value;
396
+
397
+        return $this;
398
+    }
399
+
400
+    /**
401
+     * {@inheritdoc}
402
+     */
403
+    public function withAttribute($name, $value)
404
+    {
405
+        $result = clone $this;
406
+
407
+        return $result->setAttribute($name, $value);
408
+    }
409
+
410
+    /**
411
+     * Remove the attribute.
412
+     *
413
+     * @param string $name
414
+     * @return $this
415
+     */
416
+    private function removeAttribute($name)
417
+    {
418
+        unset($this->attributes[$name]);
419
+
420
+        return $this;
421
+    }
422
+
423
+    /**
424
+     * {@inheritdoc}
425
+     */
426
+    public function withoutAttribute($name)
427
+    {
428
+        $result = clone $this;
429
+
430
+        return $result->removeAttribute($name);
431
+    }
432 432
 }
Please login to merge, or discard this patch.