Request::referer()   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 1
dl 0
loc 3
rs 10
1
<?php
2
3
/**
4
 * Lenevor Framework
5
 *
6
 * LICENSE
7
 *
8
 * This source file is subject to the new BSD license that is bundled
9
 * with this package in the file license.md.
10
 * It is also available through the world-wide-web at this URL:
11
 * https://lenevor.com/license
12
 * If you did not receive a copy of the license and are unable to
13
 * obtain it through the world-wide-web, please send an email
14
 * to [email protected] so we can send you a copy immediately.
15
 *
16
 * @package     Lenevor
17
 * @subpackage  Base
18
 * @link        https://lenevor.com
19
 * @copyright   Copyright (c) 2019 - 2021 Alexander Campo <[email protected]>
20
 * @license     https://opensource.org/licenses/BSD-3-Clause New BSD license or see https://lenevor.com/license or see /license.md
21
 */
22
23
namespace Syscodes\Http;
24
25
Use Locale;
26
use Closure;
27
use Exception;
28
use LogicException;
29
use Syscodes\Support\Str;
30
use Syscodes\Collections\Arr;
31
use Syscodes\Http\Contributors\Files;
32
use Syscodes\Http\Contributors\Inputs;
33
use Syscodes\Http\Contributors\Server;
34
use Syscodes\Http\Contributors\Headers;
35
use Syscodes\Http\Contributors\Parameters;
36
37
/**
38
 * Request represents an HTTP request.
39
 * 
40
 * @author Alexander Campo <[email protected]>
41
 */
42
class Request
43
{
44
	/**
45
	 * Holds the global active request instance.
46
	 *
47
	 * @var bool $requestURI
48
	 */
49
	protected static $requestURI;
50
51
	/**
52
	 * The base URL.
53
	 * 
54
	 * @var string $baseUrl
55
	 */
56
	protected $baseUrl;
57
58
	/**
59
	 * Gets cookies ($_COOKIE).
60
	 * 
61
	 * @var string $cookies
62
	 */
63
	public $cookies;
64
65
	/**
66
	 * Gets the string with format JSON.
67
	 * 
68
	 * @var string|resource|null $content
69
	 */
70
	protected $content;
71
72
	/**
73
	 * The default Locale this request.
74
	 * 
75
	 * @var string $defaultLocale
76
	 */
77
	protected $defaultLocale = 'en';
78
	
79
	/**
80
	 * Gets files request ($_FILES).
81
	 * 
82
	 * @var string $files
83
	 */
84
	public $files;
85
86
	/**
87
	 * The detected uri and server variables.
88
	 * 
89
	 * @var string $http
90
	 */
91
	protected $http;
92
93
	/**
94
	 * The decoded JSON content for the request.
95
	 * 
96
	 * @var \Syscodes\Http\Contributors\Parameters|null $json
97
	 */
98
	protected $json;
99
100
	/**
101
	 * The current language of the application.
102
	 * 
103
	 * @var string $languages
104
	 */
105
	protected $languages;
106
	
107
	/** 
108
	 * The method name.
109
	 * 
110
	 * @var string $method
111
	 */
112
	protected $method;
113
114
	/**
115
	 * The path info of URL.
116
	 * 
117
	 * @var string $pathInfo
118
	 */
119
	protected $pathInfo;
120
121
	/**
122
	 * Request body parameters ($_POST).
123
	 * 
124
	 * @var \Syscodes\Http\Contributors\Parameters $request
125
	 */
126
	public $request;
127
128
	/**
129
	 * Get request URI.
130
	 * 
131
	 * @var string $requestToURI
132
	 */
133
	protected $requestToURI;
134
135
	/**
136
	 * Get the route resolver callback.
137
	 * 
138
	 * @var \Closure $routeResolver
139
	 */
140
	protected $routeResolver;
141
142
	/**
143
	 * The detected uri and server variables ($_FILES).
144
	 * 
145
	 * @var array $server
146
	 */
147
	public $server = [];
148
149
	/** 
150
	 * List of routes uri.
151
	 *
152
	 * @var string|array $uri 
153
	 */
154
	public $uri;
155
156
	/**
157
	 * Stores the valid locale codes.
158
	 * 
159
	 * @var array $validLocales
160
	 */
161
	protected $validLocales = [];
162
163
	/**
164
	 * Constructor: Create new the Request class.
165
	 * 
166
	 * @param  array  $request
167
	 * @param  array  $cookies
168
	 * @param  array  $files
169
	 * @param  array  $server
170
	 * @param  string|resource|null $content  
171
	 * 
172
	 * @return void
173
	 */
174
	public function __construct(array $request = [], array $cookies = [], array $files = [], array $server = [], $content = null)
175
	{
176
		static::$requestURI = $this;
0 ignored issues
show
Documentation Bug introduced by
It seems like $this of type Syscodes\Http\Request is incompatible with the declared type boolean of property $requestURI.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
177
		
178
		$this->initialize($request, $cookies, $files, $server, $content);
179
180
		$this->detectURI(config('app.uriProtocol'), config('app.baseUrl'));
0 ignored issues
show
Bug introduced by
It seems like config('app.uriProtocol') can also be of type Syscodes\Config\Configure; however, parameter $protocol of Syscodes\Http\Request::detectURI() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

180
		$this->detectURI(/** @scrutinizer ignore-type */ config('app.uriProtocol'), config('app.baseUrl'));
Loading history...
Bug introduced by
It seems like config('app.baseUrl') can also be of type Syscodes\Config\Configure; however, parameter $baseUrl of Syscodes\Http\Request::detectURI() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

180
		$this->detectURI(config('app.uriProtocol'), /** @scrutinizer ignore-type */ config('app.baseUrl'));
Loading history...
181
182
		$this->detectLocale();
183
	}
184
185
	/**
186
	 * Sets the parameters for this request.
187
	 * 
188
	 * @param  array  $request
189
	 * @param  array  $cookies
190
	 * @param  array  $files
191
	 * @param  array  $server
192
	 * 
193
	 * @return void
194
	 */
195
	public function initialize(array $request = [], array $cookies = [], array $files = [], array $server = [], $content = null)
196
	{
197
		$this->request      = new Parameters($request);
198
		$this->cookies      = new Inputs($cookies);
0 ignored issues
show
Documentation Bug introduced by
It seems like new Syscodes\Http\Contributors\Inputs($cookies) of type Syscodes\Http\Contributors\Inputs is incompatible with the declared type string of property $cookies.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
199
		$this->files        = new Files($files);
0 ignored issues
show
Documentation Bug introduced by
It seems like new Syscodes\Http\Contributors\Files($files) of type Syscodes\Http\Contributors\Files is incompatible with the declared type string of property $files.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
200
		$this->server       = new Server($server);
0 ignored issues
show
Documentation Bug introduced by
It seems like new Syscodes\Http\Contributors\Server($server) of type Syscodes\Http\Contributors\Server is incompatible with the declared type array of property $server.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
201
		$this->headers      = new Headers($this->server->all());
0 ignored issues
show
Bug Best Practice introduced by
The property headers does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
202
203
		$this->uri          = new URI;
204
		$this->http         = new Http;
0 ignored issues
show
Documentation Bug introduced by
It seems like new Syscodes\Http\Http() of type Syscodes\Http\Http is incompatible with the declared type string of property $http.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
205
		$this->method       = null;
206
		$this->baseUrl      = null;
207
		$this->content      = $content;
208
		$this->pathInfo     = null;
209
		$this->languages    = null;
210
		$this->validLocales = config('app.supportedLocales');
0 ignored issues
show
Documentation Bug introduced by
It seems like config('app.supportedLocales') can also be of type Syscodes\Config\Configure. However, the property $validLocales is declared as type array. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
211
	}
212
213
	/**
214
	 * Create a new Syscodes HTTP request from server variables.
215
	 * 
216
	 * @return static
217
	 */
218
	public static function capture()
219
	{
220
		return static::createFromRequest(static::createFromRequestGlobals());
221
	}
222
223
	/**
224
	 * Creates an Syscodes request from of the Request class instance.
225
	 * 
226
	 * @param  \Syscodes\Http\Request  $request
227
	 * 
228
	 * @return static
229
	 */
230
	public static function createFromRequest($request)
231
	{
232
		$newRequest = (new static)->duplicate(
233
			$request->request->all(), $request->cookies->all(), 
234
			$request->files->all(), $request->server->all()
235
		);
236
237
		$newRequest->content = $request->content;
238
239
		return $newRequest;
240
	}
241
242
	/**
243
	 * Creates a new request with value from PHP's super global.
244
	 * 
245
	 * @return static
246
	 */
247
	public static function createFromRequestGlobals()
248
	{
249
		$request = static::createFromRequestFactory($_POST, $_COOKIE, $_FILES, $_SERVER);
250
251
		return $request;
252
	}
253
254
	/**
255
	 * Creates a new request from a factory.
256
	 * 
257
	 * @param  array  $request
258
	 * @param  array  $cookies
259
	 * @param  array  $files
260
	 * @param  array  $server
261
	 * 
262
	 * @return static
263
	 */
264
	protected static function createFromRequestFactory(array $request = [], array $cookies = [], array $files = [], array $server = [])
265
	{
266
		if (self::$requestURI) {
267
			$request = (self::$requestURI)($request, $cookies, $files, $server);
268
269
			if ( ! $request instanceof self) {
270
				throw new LogicException('The Request active must return an instance of Syscodes\Http\Request');
271
			}
272
273
			return $request;
274
		}
275
276
		return new static($request, $cookies, $files, $server);
277
	}
278
279
	/**
280
	 * Clones a request and overrides some of its parameters.
281
	 * 
282
	 * @param  array  $request
283
	 * @param  array  $cookies
284
	 * @param  array  $files
285
	 * @param  array  $server
286
	 * 
287
	 * @return static
288
	 */
289
	public function duplicate(array $request = [], array $cookies = [], array $files = [], array $server = [])
290
	{
291
		$duplicate = clone $this;
292
293
		if (null !== $request) {
0 ignored issues
show
introduced by
The condition null !== $request is always true.
Loading history...
294
			$duplicate->request = new Parameters($request);
295
		}
296
297
		if (null !== $cookies) {
0 ignored issues
show
introduced by
The condition null !== $cookies is always true.
Loading history...
298
			$duplicate->cookies = new Inputs($cookies);
0 ignored issues
show
Documentation Bug introduced by
It seems like new Syscodes\Http\Contributors\Inputs($cookies) of type Syscodes\Http\Contributors\Inputs is incompatible with the declared type string of property $cookies.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
299
		}
300
301
		if (null !== $files) {
0 ignored issues
show
introduced by
The condition null !== $files is always true.
Loading history...
302
			$duplicate->files = new Files($files);
0 ignored issues
show
Documentation Bug introduced by
It seems like new Syscodes\Http\Contributors\Files($files) of type Syscodes\Http\Contributors\Files is incompatible with the declared type string of property $files.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
303
		}
304
305
		if (null !== $server) {
0 ignored issues
show
introduced by
The condition null !== $server is always true.
Loading history...
306
			$duplicate->server  = new Server($server);
0 ignored issues
show
Documentation Bug introduced by
It seems like new Syscodes\Http\Contributors\Server($server) of type Syscodes\Http\Contributors\Server is incompatible with the declared type array of property $server.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
307
			$duplicate->headers = new Headers($duplicate->server->all());
0 ignored issues
show
Bug Best Practice introduced by
The property headers does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
308
		}
309
310
		$duplicate->uri          = new URI;
311
		$duplicate->http         = new Http;
0 ignored issues
show
Documentation Bug introduced by
It seems like new Syscodes\Http\Http() of type Syscodes\Http\Http is incompatible with the declared type string of property $http.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
312
		$duplicate->locale       = null;
0 ignored issues
show
Bug Best Practice introduced by
The property locale does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
313
		$duplicate->method       = null;
314
		$duplicate->baseUrl      = null;
315
		$duplicate->pathInfo     = null;
316
		$duplicate->validLocales = config('app.supportedLocales');
0 ignored issues
show
Documentation Bug introduced by
It seems like config('app.supportedLocales') can also be of type Syscodes\Config\Configure. However, the property $validLocales is declared as type array. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
317
318
		return $duplicate;		
319
	}
320
321
	/**
322
	 * Returns the active request currently being used.
323
	 *
324
	 * @param  \Syscodes\Http\Request|bool|null  $request  Overwrite current request 
325
	 *                                                     before returning, false prevents 
326
	 *                                                     overwrite
327
	 *
328
	 * @return \Syscodes\Http\Request
329
	 */
330
	public static function active($request = false)
331
	{
332
		if ($request !== false) {
333
			static::$requestURI = $request;
0 ignored issues
show
Documentation Bug introduced by
It seems like $request can also be of type Syscodes\Http\Request. However, the property $requestURI is declared as type boolean. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
334
		}
335
336
		return static::$requestURI;
0 ignored issues
show
Bug Best Practice introduced by
The expression return static::requestURI returns the type boolean which is incompatible with the documented return type Syscodes\Http\Request.
Loading history...
337
	}
338
339
	/**
340
	 * Returns the desired segment, or $default if it does not exist.
341
	 *
342
	 * @param  int  $index  The segment number (1-based index)
343
	 * @param  mixed  $default  Default value to return
344
	 *
345
	 * @return  string
346
	 */
347
	public function segment($index, $default = null)
348
	{
349
		if ($request = static::active()) {
350
			return $request->uri->getSegment($index, $default);
351
		}
352
353
		return null;
354
	}
355
356
	/**
357
	 * Returns all segments in an array. For total of segments
358
	 * used the function PHP count().
359
	 *
360
	 * @return array
361
	 */
362
	public function segments()
363
	{
364
		if ($request = static::active()) {
365
			return $request->uri->getSegments();
366
		}
367
368
		return null;
369
	}
370
371
	/**
372
	 * Returns the total number of segment.
373
	 *
374
	 * @return int|null  
375
	 */
376
	public function totalSegments()
377
	{
378
		if ($request = static::active()) {
379
			return $request->uri->getTotalSegments();
380
		}
381
382
		return null;
383
	}
384
385
	/**
386
	 * Detects and returns the current URI based on a number of different server variables.
387
	 * 
388
	 * @param  string  $protocol
389
	 * @param  string  $baseUrl
390
	 * 
391
	 * @return string
392
	 */
393
	protected function detectURI(string $protocol, string $baseUrl)
394
	{
395
		$this->uri->setPath($this->http->detectPath($protocol));
396
397
		$baseUrl = ! empty($baseUrl) ? rtrim($baseUrl, '/ ').'/' : $baseUrl;
398
399
		if ( ! empty($baseUrl)) {
400
			$this->uri->setScheme(parse_url($baseUrl, PHP_URL_SCHEME));
401
			$this->uri->setHost(parse_url($baseUrl, PHP_URL_HOST));
402
			$this->uri->setPort(parse_url($baseUrl, PHP_URL_PORT));
403
		} else {
404
			if ( ! $this->http->isCli()) {
405
				exit('You have an empty or invalid base URL. The baseURL value must be set in config/app.php, or through the .env file.');
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
406
			}
407
		}
408
	}
409
410
	/**
411
	 * Handles setting up the locale, auto-detecting of language.
412
	 * 
413
	 * @return void
414
	 */
415
	public function detectLocale()
416
	{
417
		$this->languages = $this->defaultLocale = config('app.locale');
0 ignored issues
show
Documentation Bug introduced by
It seems like config('app.locale') can also be of type Syscodes\Config\Configure. However, the property $defaultLocale is declared as type string. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
Documentation Bug introduced by
It seems like $this->defaultLocale = config('app.locale') can also be of type Syscodes\Config\Configure. However, the property $languages is declared as type string. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
418
419
		$this->setLocale($this->validLocales);
0 ignored issues
show
Bug introduced by
$this->validLocales of type array is incompatible with the type string expected by parameter $locale of Syscodes\Http\Request::setLocale(). ( Ignorable by Annotation )

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

419
		$this->setLocale(/** @scrutinizer ignore-type */ $this->validLocales);
Loading history...
420
	}
421
422
	/**
423
	 * Returns the default locale as set.
424
	 * 
425
	 * @return string
426
	 */
427
	public function getDefaultLocale()
428
	{
429
		return $this->defaultLocale;
430
	}
431
432
	/**
433
	 * Gets the current locale, with a fallback to the default.
434
	 * 
435
	 * @return string 
436
	 */
437
	public function getLocale()
438
	{
439
		return $this->languages ?: $this->defaultLocale;
440
	}
441
442
	/**
443
	 * Sets the locale string for this request.
444
	 * 
445
	 * @param  string  $locale
446
	 * 
447
	 * @return \Syscodes\Http\Request
448
	 */
449
	public function setLocale($locale)
450
	{
451
		if ( ! in_array($locale, $this->validLocales)) {
452
			$locale = $this->defaultLocale;
453
		}
454
		
455
		$this->languages = $locale;
456
457
		try {
458
		    if (class_exists('Locale', false)) {
459
				Locale::setDefault($locale);
460
			}
461
		} catch (Exception $exception) {}
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
462
463
		return $this;
464
	}
465
466
	/**
467
	 * Returns the full request string.
468
	 *
469
	 * @return string|null  The Request string
470
	 */
471
	public function get() 
472
	{
473
		if ($request = static::active()) {
474
			return $request->uri->get();
475
		}
476
477
		return null;
478
	}
479
480
	/**
481
	 * Get the JSON payload for the request.
482
	 * 
483
	 * @param  string|null  $key  
484
	 * @param  mixed  $default  
485
	 * 
486
	 * @return \Syscodes\Http\Contributors\Parameters|mixed
487
	 */
488
	public function json($key = null, $default = null)
489
	{
490
		if ( ! isset($this->json)) {
491
			$this->json = new Parameters((array) json_decode($this->getContent(), true));
492
		}
493
494
		if (is_null($key)) {
495
			return $this->json;
496
		}
497
498
		return Arr::get($this->json->all(), $key, $default);
0 ignored issues
show
Bug introduced by
The method all() does not exist on null. ( Ignorable by Annotation )

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

498
		return Arr::get($this->json->/** @scrutinizer ignore-call */ all(), $key, $default);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
499
	}
500
501
	/**
502
	 * Set the JSON payload for the request
503
	 * 
504
	 * @param  \Syscodes\Http\Contributors\Parameters  $json
505
	 * 
506
	 * @return $this
507
	 */
508
	public function setJson($json)
509
	{
510
		$this->json = $json;
511
512
		return $this;
513
	}
514
515
	/**
516
	 * Returns whether this is an AJAX request or not.
517
	 *
518
	 * @return bool
519
	 */
520
	public function isXmlHttpRequest()
521
	{
522
		return ! empty($this->server->get('HTTP_X_REQUESTED_WITH')) && 
523
				strtolower($this->server->get('HTTP_X_REQUESTED_WITH')) === 'xmlhttprequest';
524
	}
525
526
	/**
527
	 * Returns the input method used (GET, POST, DELETE, etc.).
528
	 *
529
	 * @return string
530
	 * 
531
	 * @throws \LogicException  
532
	 */
533
	public function getmethod()
534
	{
535
		if (null !== $this->method) {
536
			return $this->method;
537
		}
538
		
539
		$method = strtoupper($this->server->get('REQUEST_METHOD', 'GET'));
540
		
541
		if (in_array($method, ['GET', 'HEAD', 'POST', 'PUT', 'DELETE', 'CONNECT', 'OPTIONS', 'PATCH', 'PURGE', 'TRACE'], true)) {
542
			return $this->method = $method;
543
		}
544
		
545
		if ( ! preg_match('~^[A-Z]++$#~D', $method)) {
546
			throw new logicException(sprintf('Invalid method override "%s"', $method));
547
		}
548
549
		return $this->method = $method;
550
	}
551
552
	/**
553
	 * Sets the request method.
554
	 *
555
	 * @param  string  $method  
556
	 *
557
	 * @return string
558
	 */
559
	public function setMethod(string $method) 
560
	{
561
		$this->method = null;
562
563
		$this->server->set('REQUEST_METHOD', $method);
564
	}
565
	
566
	/**
567
	 * Determine if the current request URI matches a pattern.
568
	 * 
569
	 * @param  mixed  ...$patterns
570
	 * 
571
	 * @return bool
572
	 */
573
	public function is(...$patterns)
574
	{
575
		$path = $this->decodedPath();
576
		
577
		foreach ($patterns as $pattern) {
578
			if (Str::is($pattern, $path)) {
579
				return true;
580
			}
581
		}
582
583
		return false;
584
	}
585
586
	/**
587
	 * Determine if the route name matches a given pattern.
588
	 * 
589
	 * @param  mixed  ...$patterns
590
	 * 
591
	 * @return bool
592
	 */
593
	public function routeIs(...$patterns)
594
	{
595
		return $this->route() && $this->route()->is(...$patterns);
0 ignored issues
show
Bug introduced by
The method is() does not exist on Syscodes\Routing\Route. ( Ignorable by Annotation )

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

595
		return $this->route() && $this->route()->/** @scrutinizer ignore-call */ is(...$patterns);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
596
	}
597
598
	/**
599
	 * Get the route handling the request.
600
	 * 
601
	 * @param  string|null  $param  
602
	 * @param  mixed  $default  
603
	 * 
604
	 * @return \Syscodes\Routing\Route|object|string|null
605
	 */
606
	public function route($param = null, $default = null)
607
	{
608
		$route = call_user_func($this->getRouteResolver());
609
610
		if (is_null($route) || is_null($param)) {
611
			return $route;
612
		}
613
614
		return $route->parameter($param, $default);
615
	}
616
617
	/**
618
	 * Get the current decoded path info for the request.
619
	 * 
620
	 * @return string
621
	 */
622
	public function decodedPath()
623
	{
624
		return rawurldecode($this->path());
625
	}
626
627
	/**
628
	 * Get the current path info for the request.
629
	 * 
630
	 * @return string
631
	 */
632
	public function path()
633
	{
634
		$path = trim($this->getPathInfo(), '/');
635
636
		return $path == '' ? '/' : $path;
637
	}
638
639
	/**
640
	 * Retunrs the request body content.
641
	 * 
642
	 * @return string
643
	 */
644
	public function getContent()
645
	{
646
		if (null === $this->content || false === $this->content)
647
		{
648
			$this->content = file_get_contents('php://input');
649
		}
650
651
		return $this->content;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->content also could return the type resource which is incompatible with the documented return type string.
Loading history...
652
	}
653
654
	/**
655
	 * Returns the path being requested relative to the executed script. 
656
	 * 
657
	 * @return string
658
	 */
659
	public function getPathInfo()
660
	{
661
		if (null === $this->pathInfo)
662
		{
663
			$this->pathInfo = $this->http->parsePathInfo();
664
		}
665
666
		return $this->pathInfo;
667
	}
668
669
	/**
670
	 * Returns the root URL from which this request is executed.
671
	 * 
672
	 * @return string
673
	 */
674
	public function getBaseUrl()
675
	{
676
		if (null === $this->baseUrl)
677
		{
678
			$this->baseUrl = $this->http->parseBaseUrl();
679
		}
680
681
		return $this->baseUrl;
682
	}
683
684
	/**
685
	 * Returns the requested URI.
686
	 * 
687
	 * @return string
688
	 */
689
	public function getRequestUri()
690
	{
691
		if (null === $this->requestToUri) {
692
			$this->requestToUri = $this->http->parseRequestUri();
0 ignored issues
show
Bug Best Practice introduced by
The property requestToUri does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
693
		}
694
695
		return $this->requestToUri;
696
	}
697
	
698
	/**
699
	 * Gets the request's scheme.
700
	 * 
701
	 * @return string
702
	 */
703
	public function getScheme()
704
	{
705
		return $this->secure() ? $this->uri->setScheme('https') : $this->uri->setScheme('http');
706
	}
707
708
	/**
709
	 * Returns the host name.
710
	 * 
711
	 * @return void
712
	 */
713
	public function getHost()
714
	{
715
		if ($forwardedHost = $this->server->get('HTTP_X_FORWARDED_HOST')) {
0 ignored issues
show
Unused Code introduced by
The assignment to $forwardedHost is dead and can be removed.
Loading history...
716
			$host = $forawardedHost[0];
0 ignored issues
show
Unused Code introduced by
The assignment to $host is dead and can be removed.
Loading history...
Comprehensibility Best Practice introduced by
The variable $forawardedHost does not exist. Did you maybe mean $forwardedHost?
Loading history...
717
		} elseif ( ! $host = $this->headers->get('HOST')) {
718
			if ( ! $host = $this->server->get('SERVER_NAME')) {
719
				$host = $this->server->get('REMOTE_ADDR', '');
720
			}
721
		}
722
723
		$host = $_SERVER['SERVER_NAME'];
724
725
		$host = strtolower(preg_replace('/:\d+$/', '', trim(($host))));
726
		
727
		return $host;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $host returns the type string which is incompatible with the documented return type void.
Loading history...
728
	}
729
730
	/**
731
	 * Returns the port on which the request is made.
732
	 * 
733
	 * @return int
734
	 */
735
	public function getPort()
736
	{
737
		if ( ! $this->server->get('HTTP_HOST')) 
738
		{
739
			return $this->server->get('SERVER_PORT');
740
		}
741
		
742
		return 'https' === $this->getScheme() ? $this->uri->setPort(443) : $this->uri->setPort(80);
743
	}
744
745
	/**
746
	 * Returns the HTTP host being requested.
747
	 * 
748
	 * @return string
749
	 */
750
	public function getHttpHost()
751
	{
752
		$scheme = $this->getScheme();
753
		$port   = $this->getPort();
754
755
		if (('http' === $scheme && 80 === $port) || ('https' === $scheme && 443 === $port))		
756
		{
757
			return $this->getHost();
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->getHost() returns the type void which is incompatible with the documented return type string.
Loading history...
Bug introduced by
Are you sure the usage of $this->getHost() targeting Syscodes\Http\Request::getHost() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
758
		}
759
760
		return $this->getHost().':'.$port;
0 ignored issues
show
Bug introduced by
Are you sure $this->getHost() of type void can be used in concatenation? ( Ignorable by Annotation )

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

760
		return /** @scrutinizer ignore-type */ $this->getHost().':'.$port;
Loading history...
Bug introduced by
Are you sure the usage of $this->getHost() targeting Syscodes\Http\Request::getHost() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
761
	}
762
763
	/**
764
	 * Gets the scheme and HTTP host.
765
	 * 
766
	 * @return string
767
	 */
768
	public function getSchemeWithHttpHost()
769
	{
770
		return $this->getScheme().'://'.$this->getHttpHost();
771
	}
772
773
	/**
774
	 * Get the root URL for the application.
775
	 * 
776
	 * @return string
777
	 */
778
	public function root()
779
	{
780
		return rtrim($this->getSchemeWithHttpHost().$this->getBaseUrl(), '/');
781
	}
782
783
	/**
784
	 * Get the URL for the request.
785
	 * 
786
	 * @return string
787
	 */
788
	public function url()
789
	{
790
		return trim(preg_replace('/\?.*/', '', $this->get()), '/');
791
	}
792
793
	/**
794
	 * Returns the referer.
795
	 * 
796
	 * @param  string  $default
797
	 * 
798
	 * @return string
799
	 */
800
	public function referer(string $default = '')
801
	{
802
		return $this->server->get('HTTP_REFERER', $default);
803
	}
804
	
805
	/**
806
	 * Attempts to detect if the current connection is secure through 
807
	 * over HTTPS protocol.
808
	 * 
809
	 * @return bool
810
	 */
811
	public function secure()
812
	{
813
		if ( ! empty($this->server->get('HTTPS')) && strtolower($this->server->get('HTTPS')) !== 'off') {
814
			return true;
815
		} elseif (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $this->server->get('HTTP_X_FORWARDED_PROTO') === 'https') {
816
			return true;
817
		} elseif ( ! empty($this->server->get('HTTP_FRONT_END_HTTPS')) && strtolower($this->server->get('HTTP_FRONT_END_HTTPS')) !== 'off') {
818
			return true;
819
		}
820
821
		return false;
822
	}
823
824
	/**
825
	 * Returns the user agent.
826
	 *
827
	 * @param  string|null  $default
828
	 *
829
	 * @return string
830
	 */
831
	public function userAgent(string $default = null)
832
	{
833
		return $this->server->get('HTTP_USER_AGENT', $default);
834
	}
835
836
	/**
837
	 * Get the route resolver callback.
838
	 * 
839
	 * @return \Closure
840
	 */
841
	public function getRouteResolver()
842
	{
843
		return $this->routeResolver ?: function () {
844
			//
845
		};
846
	}
847
848
	/**
849
	 * Set the route resolver callback.
850
	 * 
851
	 * @param  \Closure  $callback
852
	 * 
853
	 * @return $this
854
	 */
855
	public function setRouteResolver(Closure $callback)
856
	{
857
		$this->routeResolver = $callback;
858
859
		return $this;
860
	}
861
862
	/**
863
	 * Get an element from the request.
864
	 * 
865
	 * @return string[]
866
	 */
867
	public function __get($key)
868
	{
869
		$all = $this->server->all();
870
871
		if (array_key_exists($key, $all)) {
872
			return $all[$key];
873
		} else {
874
			return $key;
875
		}
876
	}
877
878
	/**
879
	 * Returns the Request as an HTTP string.
880
	 * 
881
	 * @return string
882
	 */
883
	public function __toString()
884
	{
885
		try
886
		{
887
			$content = $this->getContent();
888
		}
889
		catch (LogicException $e)
890
		{
891
			if (PHP_VERSION_ID > 70400)
892
			{
893
				throw $e;
894
			}
895
896
			return trigger_error($e, E_USER_ERROR);
0 ignored issues
show
Bug Best Practice introduced by
The expression return trigger_error($e,...odes\Http\E_USER_ERROR) returns the type boolean which is incompatible with the documented return type string.
Loading history...
897
		}
898
899
		$cookieHeader = '';
900
		$cookies      = [];
901
902
		foreach ($this->cookies as $key => $value)
0 ignored issues
show
Bug introduced by
The expression $this->cookies of type string is not traversable.
Loading history...
903
		{
904
			$cookies[]= "{$key} = {$value}";
905
		}
906
907
		if ( ! empty($cookies))
908
		{
909
			$cookieHeader = 'Cookie: '.implode('; ', $cookies)."\r\n";
910
		}
911
		
912
		return sprintf('%s %s %s', $this->getMethod(), $this->getRequestUri(), $this->server->get('SERVER_PROTOCOL'))."\r\n".
913
			$this->headers.
914
			$cookieHeader."\r\n".
915
			$content;
916
	}
917
918
	/**
919
	 * Clones the current request.
920
	 * 
921
	 * @return void
922
	 */
923
	public function __clone()
924
	{
925
		$this->request = clone $this->request;
926
		$this->cookies = clone $this->cookies;
0 ignored issues
show
Documentation Bug introduced by
It seems like clone $this->cookies of type object is incompatible with the declared type string of property $cookies.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
927
		$this->files   = clone $this->files;
0 ignored issues
show
Documentation Bug introduced by
It seems like clone $this->files of type object is incompatible with the declared type string of property $files.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
928
		$this->server  = clone $this->server;
0 ignored issues
show
Documentation Bug introduced by
It seems like clone $this->server of type object is incompatible with the declared type array of property $server.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
929
		$this->headers = clone $this->headers;
0 ignored issues
show
Bug Best Practice introduced by
The property headers does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
930
	}
931
}