GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — master ( 611a27...a833ec )
by Olivier
01:50
created

Request::get_options_mapper()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 4
rs 10
cc 2
eloc 2
nc 2
nop 0
1
<?php
2
3
/*
4
 * This file is part of the ICanBoogie package.
5
 *
6
 * (c) Olivier Laviale <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace ICanBoogie\HTTP;
13
14
use ICanBoogie\Accessor\AccessorTrait;
15
use ICanBoogie\Prototype\MethodNotDefined;
16
17
/**
18
 * An HTTP request.
19
 *
20
 * <pre>
21
 * <?php
22
 *
23
 * use ICanBoogie\HTTP\Request;
24
 *
25
 * # Creating the main request
26
 *
27
 * $request = Request::from($_SERVER);
28
 *
29
 * # Creating a request from scratch, with the current environment.
30
 *
31
 * $request = Request::from([
32
 *
33
 *     Request::OPTION_URI => '/path/to/my/page.html?page=2',
34
 *     Request::OPTION_USER_AGENT => 'Mozilla'
35
 *     Request::OPTION_IS_GET => true,
36
 *     Request::OPTION_IS_XHR => true,
37
 *     Request::OPTION_IS_LOCAL => true
38
 *
39
 * ], $_SERVER);
40
 * </pre>
41
 *
42
 * @method Response connect() connect(array $params=null)
43
 * @method Response delete() delete(array $params=null)
44
 * @method Response get() get(array $params=null)
45
 * @method Response head() head(array $params=null)
46
 * @method Response options() options(array $params=null)
47
 * @method Response post() post(array $params=null)
48
 * @method Response put() put(array $params=null)
49
 * @method Response patch() patch(array $params=null)
50
 * @method Response trace() trace(array $params=null)
51
 *
52
 * @property-read Request\Context $context the request's context.
53
 * @property-read Request $parent Parent request.
54
 * @property-read FileList $files The files associated with the request.
55
 *
56
 * @property-read boolean $authorization Authorization of the request.
57
 * @property-read int $content_length Length of the request content.
58
 * @property-read Headers\CacheControl $cache_control
59
 * @property-read string $ip Remote IP of the request.
60
 * @property-read boolean $is_delete Is this a `DELETE` request?
61
 * @property-read boolean $is_get Is this a `GET` request?
62
 * @property-read boolean $is_head Is this a `HEAD` request?
63
 * @property-read boolean $is_options Is this a `OPTIONS` request?
64
 * @property-read boolean $is_patch Is this a `PATCH` request?
65
 * @property-read boolean $is_post Is this a `POST` request?
66
 * @property-read boolean $is_put Is this a `PUT` request?
67
 * @property-read boolean $is_trace Is this a `TRACE` request?
68
 * @property-read boolean $is_local Is this a local request?
69
 * @property-read boolean $is_xhr Is this an Ajax request?
70
 * @property-read string $method Method of the request.
71
 * @property-read string $normalized_path Path of the request normalized using the {@link \ICanBoogie\normalize_url_path()} function.
72
 * @property-read string $path Path info of the request.
73
 * @property-read string $extension The extension of the path.
74
 * @property-read int $port Port of the request.
75
 * @property-read string $query_string Query string of the request.
76
 * @property-read string $script_name Name of the entered script.
77
 * @property-read string $referer Referer of the request.
78
 * @property-read string $user_agent User agent of the request.
79
 * @property-read string $uri URI of the request. The `QUERY_STRING` value of the environment
80
 * is overwritten when the instance is created with the {@link $uri} property.
81
 *
82
 * @see http://en.wikipedia.org/wiki/Uniform_resource_locator
83
 */
84
class Request implements \ArrayAccess, \IteratorAggregate, RequestMethods, RequestOptions
85
{
86
	use AccessorTrait;
87
88
	static public $methods = [
89
90
		self::METHOD_CONNECT,
91
		self::METHOD_DELETE,
92
		self::METHOD_GET,
93
		self::METHOD_HEAD,
94
		self::METHOD_OPTIONS,
95
		self::METHOD_POST,
96
		self::METHOD_PUT,
97
		self::METHOD_PATCH,
98
		self::METHOD_TRACE
99
100
	];
101
102
	/**
103
	 * Current request.
104
	 *
105
	 * @var Request
106
	 */
107
	static protected $current_request;
108
109
	/**
110
	 * Returns the current request.
111
	 *
112
	 * @return Request
113
	 */
114
	static public function get_current_request()
115
	{
116
		return self::$current_request;
117
	}
118
119
	/**
120
	 * Parameters extracted from the request path.
121
	 *
122
	 * @var array
123
	 */
124
	public $path_params = [];
125
126
	/**
127
	 * Parameters defined by the query string.
128
	 *
129
	 * @var array
130
	 */
131
	public $query_params = [];
132
133
	/**
134
	 * Parameters defined by the request body.
135
	 *
136
	 * @var array
137
	 */
138
	public $request_params = [];
139
140
	/**
141
	 * Union of {@link $path_params}, {@link $request_params} and {@link $query_params}.
142
	 *
143
	 * @var array
144
	 */
145
	public $params;
146
147
	/**
148
	 * General purpose container.
149
	 *
150
	 * @var Request\Context
151
	 */
152
	protected $context;
153
154
	/**
155
	 * The headers of the request.
156
	 *
157
	 * @var Headers
158
	 */
159
	public $headers;
160
161
	/**
162
	 * Request environment.
163
	 *
164
	 * @var array
165
	 */
166
	protected $env;
167
168
	/**
169
	 * Files associated with the request.
170
	 *
171
	 * @var FileList
172
	 */
173
	protected $files;
174
175
	protected function get_files()
176
	{
177
		if ($this->files instanceof FileList)
178
		{
179
			return $this->files;
180
		}
181
182
		return $this->files = FileList::from($this->files);
183
	}
184
185
	public $cookie;
186
187
	/**
188
	 * Parent request.
189
	 *
190
	 * @var Request
191
	 */
192
	protected $parent;
193
194
	/**
195
	 * A request may be created from the `$_SERVER` super global array. In that case `$_SERVER` is
196
	 * used as environment the request is created with the following properties:
197
	 *
198
	 * - {@link $cookie}: a reference to the `$_COOKIE` super global array.
199
	 * - {@link $path_params}: initialized to an empty array.
200
	 * - {@link $query_params}: a reference to the `$_GET` super global array.
201
	 * - {@link $request_params}: a reference to the `$_POST` super global array.
202
	 * - {@link $files}: a reference to the `$_FILES` super global array.
203
	 *
204
	 * A request may also be created from an array of properties, in which case most of them are
205
	 * mapped to the `$env` constructor param. For instance, `is_xhr` set the
206
	 * `HTTP_X_REQUESTED_WITH` environment property to 'XMLHttpRequest'. In fact, only the
207
	 * following options are preserved:
208
	 *
209
	 * - Request::OPTION_PATH_PARAMS
210
	 * - Request::OPTION_QUERY_PARAMS
211
	 * - Request::OPTION_REQUEST_PARAMS
212
	 * - Request::OPTION_FILES: The files associated with the request.
213
	 * - Request::OPTION_HEADERS: The header fields of the request. If specified, the headers
214
	 * available in the environment are ignored.
215
	 *
216
	 * @param array $properties Properties of the request.
217
	 * @param array $env Environment, usually the `$_SERVER` array.
218
	 *
219
	 * @throws \InvalidArgumentException in attempt to use an unsupported option.
220
	 *
221
	 * @return Request
222
	 */
223
	static public function from($properties = null, array $env = [])
224
	{
225
		if (!$properties)
226
		{
227
			return new static([], $env);
228
		}
229
230
		if ($properties === $_SERVER)
231
		{
232
			return static::from_server();
233
		}
234
235
		if (is_string($properties) || (is_object($properties) && method_exists($properties, '__toString')))
236
		{
237
			return static::from_uri((string) $properties, $env);
238
		}
239
240
		return static::from_options($properties, $env);
241
	}
242
243
	/**
244
	 * Creates an instance from the `$_SERVER` array.
245
	 *
246
	 * @return Request
247
	 */
248
	static protected function from_server()
249
	{
250
		return static::from([
251
252
			self::OPTION_COOKIE => &$_COOKIE,
253
			self::OPTION_PATH_PARAMS => [],
254
			self::OPTION_QUERY_PARAMS => &$_GET,
255
			self::OPTION_REQUEST_PARAMS => &$_POST,
256
			self::OPTION_FILES => &$_FILES // @codeCoverageIgnore
257
258
		], $_SERVER);
259
	}
260
261
	/**
262
	 * Creates an instance from an URI.
263
	 *
264
	 * @param string $uri
265
	 * @param array $env
266
	 *
267
	 * @return Request
268
	 */
269
	static protected function from_uri($uri, array $env)
270
	{
271
		return static::from([ self::OPTION_URI => $uri ], $env);
272
	}
273
274
	/**
275
	 * Creates an instance from an array of properties.
276
	 *
277
	 * @param array $options
278
	 * @param array $env
279
	 *
280
	 * @return Request
281
	 */
282
	static protected function from_options(array $options, array $env)
283
	{
284
		if ($options)
285
		{
286
			static::get_options_mapper()->map($options, $env);
287
		}
288
289
		if (!empty($env['QUERY_STRING']))
290
		{
291
			parse_str($env['QUERY_STRING'], $options[self::OPTION_QUERY_PARAMS]);
292
		}
293
294
		return new static($options, $env);
295
	}
296
297
	/**
298
	 * @var RequestOptionsMapper
299
	 */
300
	static private $options_mapper;
301
302
	/**
303
	 * @return RequestOptionsMapper
304
	 */
305
	static protected function get_options_mapper()
306
	{
307
		return self::$options_mapper ?: self::$options_mapper = new RequestOptionsMapper;
308
	}
309
310
	/**
311
	 * Initialize the properties {@link $env}, {@link $headers} and {@link $context}.
312
	 *
313
	 * If the {@link $params} property is `null` it is set with an union of {@link $path_params},
314
	 * {@link $request_params} and {@link $query_params}.
315
	 *
316
	 * @param array $properties Initial properties.
317
	 * @param array $env Environment of the request, usually the `$_SERVER` super global.
318
	 *
319
	 * @throws MethodNotSupported when the request method is not supported.
320
	 */
321
	protected function __construct(array $properties, array $env = [])
322
	{
323
		$this->context = new Request\Context($this);
324
		$this->env = $env;
325
326
		foreach ($properties as $property => $value)
327
		{
328
			$this->$property = $value;
329
		}
330
331
		$this->assert_method($this->method);
332
333
		if (!$this->headers)
334
		{
335
			$this->headers = new Headers($env);
336
		}
337
338
		if ($this->params === null)
339
		{
340
			$this->params = $this->path_params + $this->request_params + $this->query_params;
341
		}
342
	}
343
344
	/**
345
	 * Clone {@link $headers} and {@link $context}, and unset {@link $params}.
346
	 */
347
	public function __clone()
348
	{
349
		$this->headers = clone $this->headers;
350
		$this->context = clone $this->context;
351
		unset($this->params);
352
	}
353
354
	/**
355
	 * Alias for {@link send()}.
356
	 *
357
	 * @return Response The response to the request.
358
	 */
359
	public function __invoke()
360
	{
361
		return $this->send();
362
	}
363
364
	/**
365
	 * Dispatch the request.
366
	 *
367
	 * The {@link parent} property is used for request chaining.
368
	 *
369
	 * Note: If an exception is thrown during dispatch {@link $current_request} is not updated!
370
	 *
371
	 * Note: If the request is changed because of the `$method` or `$params` parameters, it
372
	 * is the _changed_ instance that is dispatched, not the actual instance.
373
	 *
374
	 * @param string|null $method Use this parameter to change the request method.
375
	 * @param array|null $params Use this parameter to change the {@link $request_params}
376
	 * property of the request.
377
	 *
378
	 * @return Response The response to the request.
379
	 *
380
	 * @throws \Exception re-throws exception raised during dispatch.
381
	 */
382
	public function send($method = null, array $params = null)
383
	{
384
		$request = $this->adapt($method, $params);
385
386
		$this->parent = self::$current_request;
387
388
		self::$current_request = $request;
389
390
		try
391
		{
392
			$response = $request->dispatch();
393
394
			self::$current_request = $request->parent;
395
396
			return $response;
397
		}
398
		catch (\Exception $e)
399
		{
400
			self::$current_request = $request->parent;
401
402
			throw $e;
403
		}
404
	}
405
406
	/**
407
	 * Dispatches the request using the {@link dispatch()} helper.
408
	 *
409
	 * @return Response
410
	 */
411
	protected function dispatch()
412
	{
413
		return dispatch($this); // @codeCoverageIgnore
414
	}
415
416
	/**
417
	 * Asserts that a method is supported.
418
	 *
419
	 * @param string $method
420
	 *
421
	 * @throws MethodNotSupported
422
	 */
423
	private function assert_method($method)
424
	{
425
		if (!in_array($method, self::$methods))
426
		{
427
			throw new MethodNotSupported($method);
428
		}
429
	}
430
431
	/**
432
	 * Returns a new instance with the specified changed properties.
433
	 *
434
	 * @param array $options
435
	 *
436
	 * @throws \InvalidArgumentException
437
	 *
438
	 * @return Request
439
	 */
440
	public function with(array $options)
441
	{
442
		$changed = clone $this;
443
444
		if ($options)
445
		{
446
			static::get_options_mapper()->map($options, $changed->env);
447
448
			foreach ($options as $option => &$value)
449
			{
450
				$changed->$option = $value;
451
			}
452
		}
453
454
		return $changed;
455
	}
456
457
	/**
458
	 * Adapts the request to the specified method and params.
459
	 *
460
	 * @param string $method The method.
461
	 * @param array $params The params.
462
	 *
463
	 * @return Request The same instance is returned if the method is the same and the params
464
	 * are `null`. Otherwise a _changed_ request is returned.
465
	 */
466
	protected function adapt($method, array $params = null)
467
	{
468
		if ((!$method || $method == $this->method) && !$params)
469
		{
470
			return $this;
471
		}
472
473
		$properties = [];
474
475
		if ($method)
476
		{
477
			$properties = [ self::OPTION_METHOD => $method ];
478
		}
479
480
		if ($params !== null)
481
		{
482
			$properties[self::OPTION_REQUEST_PARAMS] = $params;
483
			$properties[self::OPTION_PATH_PARAMS] = [];
484
			$properties[self::OPTION_QUERY_PARAMS] = [];
485
		}
486
487
		return $this->with($properties);
488
	}
489
490
	/**
491
	 * Overrides the method to provide a virtual method for each request method.
492
	 *
493
	 * Example:
494
	 *
495
	 * <pre>
496
	 * <?php
497
	 *
498
	 * Request::from('/api/core/aloha')->get();
499
	 * </pre>
500
	 *
501
	 * @param $method
502
	 * @param $arguments
503
	 *
504
	 * @return mixed
505
	 */
506
	public function __call($method, $arguments)
507
	{
508
		$http_method = strtoupper($method);
509
510
		if (in_array($http_method, self::$methods))
511
		{
512
			array_unshift($arguments, $http_method);
513
514
			return call_user_func_array([ $this, 'send' ], $arguments);
515
		}
516
517
		throw new MethodNotDefined($method, $this);
518
	}
519
520
	/**
521
	 * Checks if the specified param exists in the request's params.
522
	 *
523
	 * @param string $param The name of the parameter.
524
	 *
525
	 * @return bool
526
	 */
527
	public function offsetExists($param)
528
	{
529
		return isset($this->params[$param]);
530
	}
531
532
	/**
533
	 * Get the specified param from the request's params.
534
	 *
535
	 * @param string $param The name of the parameter.
536
	 *
537
	 * @return mixed|null The value of the parameter, or `null` if the parameter does not exists.
538
	 */
539
	public function offsetGet($param)
540
	{
541
		return isset($this->params[$param]) ? $this->params[$param] : null;
542
	}
543
544
	/**
545
	 * Set the specified param to the specified value.
546
	 *
547
	 * @param string $param The name of the parameter.
548
	 * @param mixed $value The value of the parameter.
549
	 */
550
	public function offsetSet($param, $value)
551
	{
552
		$this->params;
553
		$this->params[$param] = $value;
554
		$this->request_params[$param] = $value;
555
	}
556
557
	/**
558
	 * Remove the specified param from the request's parameters.
559
	 *
560
	 * @param mixed $param
561
	 */
562
	public function offsetUnset($param)
563
	{
564
		unset($this->params[$param]);
565
	}
566
567
	/**
568
	 * Returns an array iterator for the params.
569
	 *
570
	 * @return \ArrayIterator
571
	 */
572
	public function getIterator()
573
	{
574
		return new \ArrayIterator($this->params);
575
	}
576
577
	/**
578
	 * Returns the parent request.
579
	 *
580
	 * @return Request
581
	 */
582
	protected function get_parent()
583
	{
584
		return $this->parent;
585
	}
586
587
	/**
588
	 * Returns the request's context.
589
	 *
590
	 * @return Request\Context
591
	 */
592
	protected function get_context()
593
	{
594
		return $this->context;
595
	}
596
597
	/**
598
	 * Returns the `Cache-Control` header.
599
	 *
600
	 * @return Headers\CacheControl
601
	 */
602
	protected function get_cache_control()
603
	{
604
		return $this->headers['Cache-Control'];
605
	}
606
607
	/**
608
	 * Returns the script name.
609
	 *
610
	 * The setter is volatile, the value is returned from the ENV key `SCRIPT_NAME`.
611
	 *
612
	 * @return string
613
	 */
614
	protected function get_script_name()
615
	{
616
		return $this->env['SCRIPT_NAME'];
617
	}
618
619
	/**
620
	 * Returns the request method.
621
	 *
622
	 * This is the getter for the `method` magic property.
623
	 *
624
	 * The method is retrieved from {@link $env}, if the key `REQUEST_METHOD` is not defined,
625
	 * the method defaults to {@link METHOD_GET}.
626
	 *
627
	 * @return string
628
	 */
629
	protected function get_method()
630
	{
631
		$method = isset($this->env['REQUEST_METHOD']) ? $this->env['REQUEST_METHOD'] : self::METHOD_GET;
632
633
		if ($method == self::METHOD_POST && !empty($this->request_params['_method']))
634
		{
635
			$method = strtoupper($this->request_params['_method']);
636
		}
637
638
		return $method;
639
	}
640
641
	/**
642
	 * Returns the query string of the request.
643
	 *
644
	 * The value is obtained from the `QUERY_STRING` key of the {@link $env} array.
645
	 *
646
	 * @return string|null
647
	 */
648
	protected function get_query_string()
649
	{
650
		return isset($this->env['QUERY_STRING']) ? $this->env['QUERY_STRING'] : null;
651
	}
652
653
	/**
654
	 * Returns the content length of the request.
655
	 *
656
	 * The value is obtained from the `CONTENT_LENGTH` key of the {@link $env} array.
657
	 *
658
	 * @return int|null
659
	 */
660
	protected function get_content_length()
661
	{
662
		return isset($this->env['CONTENT_LENGTH']) ? $this->env['CONTENT_LENGTH'] : null;
663
	}
664
665
	/**
666
	 * Returns the referer of the request.
667
	 *
668
	 * The value is obtained from the `HTTP_REFERER` key of the {@link $env} array.
669
	 *
670
	 * @return string|null
671
	 */
672
	protected function get_referer()
673
	{
674
		return isset($this->env['HTTP_REFERER']) ? $this->env['HTTP_REFERER'] : null;
675
	}
676
677
	/**
678
	 * Returns the user agent of the request.
679
	 *
680
	 * The value is obtained from the `HTTP_USER_AGENT` key of the {@link $env} array.
681
	 *
682
	 * @return string|null
683
	 */
684
	protected function get_user_agent()
685
	{
686
		return isset($this->env['HTTP_USER_AGENT']) ? $this->env['HTTP_USER_AGENT'] : null;
687
	}
688
689
	/**
690
	 * Checks if the request method is `DELETE`.
691
	 *
692
	 * @return boolean
693
	 */
694
	protected function get_is_delete()
695
	{
696
		return $this->method == self::METHOD_DELETE;
697
	}
698
699
	/**
700
	 * Checks if the request method is `GET`.
701
	 *
702
	 * @return boolean
703
	 */
704
	protected function get_is_get()
705
	{
706
		return $this->method == self::METHOD_GET;
707
	}
708
709
	/**
710
	 * Checks if the request method is `HEAD`.
711
	 *
712
	 * @return boolean
713
	 */
714
	protected function get_is_head()
715
	{
716
		return $this->method == self::METHOD_HEAD;
717
	}
718
719
	/**
720
	 * Checks if the request method is `OPTIONS`.
721
	 *
722
	 * @return boolean
723
	 */
724
	protected function get_is_options()
725
	{
726
		return $this->method == self::METHOD_OPTIONS;
727
	}
728
729
	/**
730
	 * Checks if the request method is `PATCH`.
731
	 *
732
	 * @return boolean
733
	 */
734
	protected function get_is_patch()
735
	{
736
		return $this->method == self::METHOD_PATCH;
737
	}
738
739
	/**
740
	 * Checks if the request method is `POST`.
741
	 *
742
	 * @return boolean
743
	 */
744
	protected function get_is_post()
745
	{
746
		return $this->method == self::METHOD_POST;
747
	}
748
749
	/**
750
	 * Checks if the request method is `PUT`.
751
	 *
752
	 * @return boolean
753
	 */
754
	protected function get_is_put()
755
	{
756
		return $this->method == self::METHOD_PUT;
757
	}
758
759
	/**
760
	 * Checks if the request method is `TRACE`.
761
	 *
762
	 * @return boolean
763
	 */
764
	protected function get_is_trace()
765
	{
766
		return $this->method == self::METHOD_TRACE;
767
	}
768
769
	/**
770
	 * Checks if the request is a `XMLHTTPRequest`.
771
	 *
772
	 * @return boolean
773
	 */
774
	protected function get_is_xhr()
775
	{
776
		return !empty($this->env['HTTP_X_REQUESTED_WITH']) && preg_match('/XMLHttpRequest/', $this->env['HTTP_X_REQUESTED_WITH']);
777
	}
778
779
	/**
780
	 * Checks if the request is local.
781
	 *
782
	 * @return boolean
783
	 */
784
	protected function get_is_local()
785
	{
786
		$ip = $this->ip;
787
788
		if ($ip == '::1' || preg_match('/^127\.0\.0\.\d{1,3}$/', $ip))
789
		{
790
			return true;
791
		}
792
793
		return preg_match('/^0:0:0:0:0:0:0:1(%.*)?$/', $ip);
794
	}
795
796
	/**
797
	 * Returns the remote IP of the request.
798
	 *
799
	 * If defined, the `HTTP_X_FORWARDED_FOR` header is used to retrieve the original IP.
800
	 *
801
	 * If the `REMOTE_ADDR` header is empty the request is considered local thus `::1` is returned.
802
	 *
803
	 * @see http://en.wikipedia.org/wiki/X-Forwarded-For
804
	 *
805
	 * @return string
806
	 */
807
	protected function get_ip()
808
	{
809
		$forwarded_for = $this->headers['X-Forwarded-For'];
810
811
		if ($forwarded_for)
812
		{
813
			list($ip) = explode(',', $forwarded_for);
814
815
			return $ip;
816
		}
817
818
		return (isset($this->env['REMOTE_ADDR']) ? $this->env['REMOTE_ADDR'] : null) ?: '::1';
819
	}
820
821
	protected function get_authorization()
822
	{
823
		if (isset($this->env['HTTP_AUTHORIZATION']))
824
		{
825
			return $this->env['HTTP_AUTHORIZATION'];
826
		}
827
		else if (isset($this->env['X-HTTP_AUTHORIZATION']))
828
		{
829
			return $this->env['X-HTTP_AUTHORIZATION'];
830
		}
831
		else if (isset($this->env['X_HTTP_AUTHORIZATION']))
832
		{
833
			return $this->env['X_HTTP_AUTHORIZATION'];
834
		}
835
		else if (isset($this->env['REDIRECT_X_HTTP_AUTHORIZATION']))
836
		{
837
			return $this->env['REDIRECT_X_HTTP_AUTHORIZATION'];
838
		}
839
840
		return null;
841
	}
842
843
	/**
844
	 * Returns the `REQUEST_URI` environment key.
845
	 *
846
	 * If the `REQUEST_URI` key is not defined by the environment, the value is fetched from
847
	 * the `$_SERVER` array. If the key is not defined in the `$_SERVER` array `null` is returned.
848
	 *
849
	 * @return string
850
	 */
851
	protected function get_uri()
852
	{
853
		return isset($this->env['REQUEST_URI'])
854
			? $this->env['REQUEST_URI']
855
			: (isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : null);
856
	}
857
858
	/**
859
	 * Returns the port of the request.
860
	 *
861
	 * @return int
862
	 */
863
	protected function get_port()
864
	{
865
		return $this->env['REQUEST_PORT'];
866
	}
867
868
	/**
869
	 * Returns the path of the request, that is the `REQUEST_URI` without the query string.
870
	 *
871
	 * @return string
872
	 */
873
	protected function get_path()
874
	{
875
		$uri = $this->uri;
876
		$qs_pos = strpos($uri, '?');
877
878
		return ($qs_pos === false) ? $uri : substr($uri, 0, $qs_pos);
879
	}
880
881
	/**
882
	 * Returns the {@link $path} property normalized using the
883
	 * {@link \ICanBoogie\normalize_url_path()} function.
884
	 *
885
	 * @return string
886
	 */
887
	protected function get_normalized_path()
888
	{
889
		return \ICanBoogie\normalize_url_path($this->path);
890
	}
891
892
	/**
893
	 * Returns the extension of the path info.
894
	 *
895
	 * @return mixed
896
	 */
897
	protected function get_extension()
898
	{
899
		return pathinfo($this->path, PATHINFO_EXTENSION);
900
	}
901
902
	protected function lazy_set_params($params)
903
	{
904
		return $params;
905
	}
906
907
	/**
908
	 * Returns the union of the {@link path_params}, {@link request_params} and
909
	 * {@link query_params} properties.
910
	 *
911
	 * This method is the getter of the {@link $params} magic property.
912
	 *
913
	 * @return array
914
	 */
915
	protected function lazy_get_params()
916
	{
917
		return $this->path_params + $this->request_params + $this->query_params;
918
	}
919
}
920