Passed
Push — 0.8.x ( fca16e...a09e23 )
by Alexander
07:28 queued 04:00
created

Request   F

Complexity

Total Complexity 120

Size/Duplication

Total Lines 1069
Duplicated Lines 0 %

Importance

Changes 12
Bugs 0 Features 0
Metric Value
eloc 225
c 12
b 0
f 0
dl 0
loc 1069
rs 2
wmc 120

58 Methods

Rating   Name   Duplication   Size   Complexity  
A method() 0 3 1
A url() 0 4 1
A getLocale() 0 3 2
A __toString() 0 19 4
A userAgent() 0 3 1
A session() 0 7 2
A setMethod() 0 5 1
A getPassword() 0 7 1
A hasSession() 0 3 1
A getScheme() 0 3 2
A get() 0 15 4
A getRequestUri() 0 7 2
A root() 0 3 1
A initialize() 0 27 1
A ajax() 0 3 1
A segments() 0 3 1
A setLocale() 0 11 2
A getUri() 0 7 2
A getContent() 0 7 3
A json() 0 11 3
A getInputSource() 0 7 3
A route() 0 9 3
A decodedPath() 0 3 1
A isMethod() 0 3 1
A getBaseUrl() 0 7 2
A detectLocale() 0 5 1
A prefetch() 0 4 2
A __clone() 0 9 1
A getAcceptableContentTypes() 0 7 2
A totalSegments() 0 3 1
A path() 0 5 2
A getPathInfo() 0 7 2
A getHost() 0 13 4
A getSession() 0 5 2
A setRouteResolver() 0 5 1
A pjax() 0 3 1
B getmethod() 0 33 8
B secure() 0 11 7
A getHttpHost() 0 10 5
A isXmlHttpRequest() 0 4 2
A segment() 0 3 1
A getQueryString() 0 5 2
A is() 0 11 3
A setSession() 0 3 1
A setJson() 0 5 1
B duplicate() 0 44 7
A getUser() 0 7 1
A referer() 0 3 1
A getRouteResolver() 0 3 2
A fullUrl() 0 7 3
A getUserInfo() 0 3 1
A getPort() 0 7 3
A getSchemeWithHttpHost() 0 3 1
A ip() 0 3 1
A __get() 0 3 1
A getDefaultLocale() 0 3 1
A routeIs() 0 3 2
A __construct() 0 12 1

How to fix   Complexity   

Complex Class

Complex classes like Request often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Request, and based on these observations, apply Extract Interface, too.

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 - 2023 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\Components\Http;
24
25
Use Locale;
26
use Closure;
27
use LogicException;
28
use RuntimeException;
29
use Syscodes\Components\Support\Arr;
30
use Syscodes\Components\Support\Str;
31
use Syscodes\Components\Http\Loaders\Files;
32
use Syscodes\Components\Http\Loaders\Inputs;
33
use Syscodes\Components\Http\Loaders\Server;
34
use Syscodes\Components\Http\Loaders\Headers;
35
use Syscodes\Components\Http\Loaders\Parameters;
36
use Syscodes\Components\Http\Helpers\RequestUtils;
37
use Syscodes\Components\Http\Resources\HttpRequest;
38
use Syscodes\Components\Http\Helpers\RequestClientIP;
39
use Syscodes\Components\Http\Resources\HttpResources;
40
use Syscodes\Components\Http\Session\SessionDecorator;
41
use Syscodes\Components\Http\Concerns\CanBePrecognitive;
42
use Syscodes\Components\Http\Concerns\InteractsWithInput;
43
use Syscodes\Components\Http\Concerns\InteractsWithContentTypes;
44
use Syscodes\Components\Http\Exceptions\SessionNotFoundException;
45
46
/**
47
 * Request represents an HTTP request.
48
 */
49
class Request
50
{
51
	use HttpRequest,
52
	    HttpResources,
53
	    CanBePrecognitive,	    
54
	    InteractsWithInput,
55
	    InteractsWithContentTypes;
56
57
	/**
58
	 * Get the acceptable of content types.
59
	 * 
60
	 * @var string[] $acceptableContenTypes
61
	 */
62
	protected $acceptableContentTypes;
63
64
	/**
65
	 * Get the custom parameters.
66
	 * 
67
	 * @var \Syscodes\Components\Http\Loaders\Parameters $attributes
68
	 */
69
	public $attributes;
70
71
	/**
72
	 * The base URL.
73
	 * 
74
	 * @var string $baseUrl
75
	 */
76
	protected $baseUrl;
77
78
	/**
79
	 * Get the client ip.
80
	 * 
81
	 * @var mixed $clientIp
82
	 */
83
	protected $clientIp;
84
85
	/**
86
	 * Gets cookies ($_COOKIE).
87
	 * 
88
	 * @var \Syscodes\Components\Http\Loaders\Inputs $cookies
89
	 */
90
	public $cookies;
91
92
	/**
93
	 * Gets the string with format JSON.
94
	 * 
95
	 * @var string|resource|object|null $content
96
	 */
97
	protected $content;
98
99
	/**
100
	 * The default Locale this request.
101
	 * 
102
	 * @var string $defaultLocale
103
	 */
104
	protected $defaultLocale = 'en';
105
	
106
	/**
107
	 * Gets files request ($_FILES).
108
	 * 
109
	 * @var \Syscodes\Components\Http\Loaders\Files $files
110
	 */
111
	public $files;
112
	
113
	/**
114
	 * Get the headers request ($_SERVER).
115
	 * 
116
	 * @var \Syscodes\Components\Http\Loaders\Headers $headers
117
	 */
118
	public $headers;
119
120
	/**
121
	 * The decoded JSON content for the request.
122
	 * 
123
	 * @var \Syscodes\Components\Http\Loaders\Parameters|null $json
124
	 */
125
	protected $json;
126
127
	/**
128
	 * The current language of the application.
129
	 * 
130
	 * @var string $languages
131
	 */
132
	protected $languages;
133
	
134
	/**
135
	 * Get the locale.
136
	 * 
137
	 * @var string $locale
138
	 */
139
	protected $locale;
140
	
141
	/** 
142
	 * The method name.
143
	 * 
144
	 * @var string $method
145
	 */
146
	protected $method;
147
148
	/**
149
	 * The path info of URL.
150
	 * 
151
	 * @var string $pathInfo
152
	 */
153
	protected $pathInfo;
154
155
	/**
156
	 * Query string parameters ($_GET).
157
	 * 
158
	 * @var \Syscodes\Components\Http\Loaders\Parameters $query
159
	 */
160
	public $query;
161
162
	/**
163
	 * Request body parameters ($_POST).
164
	 * 
165
	 * @var \Syscodes\Components\Http\Loaders\Parameters $request
166
	 */
167
	public $request;
168
169
	/**
170
	 * Get request URI.
171
	 * 
172
	 * @var string $requestToUri
173
	 */
174
	protected $requestToUri;
175
176
	/**
177
	 * Get the route resolver callback.
178
	 * 
179
	 * @var \Closure $routeResolver
180
	 */
181
	protected $routeResolver;
182
183
	/**
184
	 * The Session implementation.
185
	 * 
186
	 * @var \Syscodes\Components\Contracts\Session\Session $session
187
	 */
188
	protected $session;
189
190
	/**
191
	 * The detected uri and server variables ($_SERVER).
192
	 * 
193
	 * @var \Syscodes\Components\Http\Loaders\Server $server
194
	 */
195
	public $server;
196
197
	/** 
198
	 * List of routes uri.
199
	 *
200
	 * @var \Syscodes\Components\Http\URI $uri 
201
	 */
202
	public $uri;
203
204
	/**
205
	 * Stores the valid locale codes.
206
	 * 
207
	 * @var array $validLocales
208
	 */
209
	protected $validLocales = [];
210
211
	/**
212
	 * Constructor: Create new the Request class.
213
	 * 
214
	 * @param  array  $query
215
	 * @param  array  $request
216
	 * @param  array  $attributes
217
	 * @param  array  $cookies
218
	 * @param  array  $files
219
	 * @param  array  $server
220
	 * @param  string|resource|null $content  
221
	 * 
222
	 * @return void
223
	 */
224
	public function __construct(
225
		array $query = [],
226
		array $request = [],
227
		array $attributes = [],
228
		array $cookies = [],
229
		array $files = [],
230
		array $server = [],
231
		$content = null
232
	) {
233
		$this->initialize($query, $request, $attributes, $cookies, $files, $server, $content);
234
		
235
		$this->detectLocale();
236
	}
237
238
	/**
239
	 * Sets the parameters for this request.
240
	 * 
241
	 * @param  array  $query
242
	 * @param  array  $request
243
	 * @param  array  $attributes
244
	 * @param  array  $cookies
245
	 * @param  array  $files
246
	 * @param  array  $server
247
	 * 
248
	 * @return void
249
	 */
250
	public function initialize(
251
		array $query = [], 
252
		array $request = [],
253
		array $attributes = [],
254
		array $cookies = [], 
255
		array $files = [], 
256
		array $server = [], 
257
		$content = null
258
	): void {
259
		$this->query = new Inputs($query);
260
		$this->request = new Inputs($request);
261
		$this->attributes = new Parameters($attributes);
262
		$this->cookies = new Inputs($cookies);
263
		$this->files = new Files($files);
264
		$this->server = new Server($server);
265
		$this->headers = new Headers($this->server->all());
266
267
		// Variables initialized
268
		$this->uri = new URI;
269
		$this->method = null;
270
		$this->baseUrl = null;
271
		$this->content = $content;
272
		$this->pathInfo = null;
273
		$this->languages = null;
274
		$this->acceptableContentTypes = null;
275
		$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\Components\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...
276
		$this->clientIp = new RequestClientIP($this->server->all());
277
	}
278
279
	/**
280
	 * Clones a request and overrides some of its parameters.
281
	 * 
282
	 * @param  array|null  $query
283
	 * @param  array|null  $request
284
	 * @param  array|null  $attributes
285
	 * @param  array|null  $cookies
286
	 * @param  array|null  $files
287
	 * @param  array|null  $server
288
	 * 
289
	 * @return static
290
	 */
291
	public function duplicate(
292
		array $query = null, 
293
		array $request = null,
294
		array $attributes = null,
295
		array $cookies = null,
296
		array $files = null,
297
		array $server = null
298
	): static {
299
		$duplicate = clone $this;
300
301
		if (null !== $query) {
302
			$duplicate->query = new Inputs($query);
303
		}
304
305
		if (null !== $request) {
306
			$duplicate->request = new Inputs($request);
307
		}
308
309
		if (null !== $attributes) {
310
			$duplicate->attributes = new Parameters($attributes);
311
		}
312
313
		if (null !== $cookies) {
314
			$duplicate->cookies = new Inputs($cookies);
315
		}
316
317
		if (null !== $files) {
318
			$duplicate->files = new Files($files);
319
		}
320
321
		if (null !== $server) {
322
			$duplicate->server  = new Server($server);
323
			$duplicate->headers = new Headers($duplicate->server->all());
324
		}
325
326
		$duplicate->uri = new URI;
327
		$duplicate->locale = null;
328
		$duplicate->method = null;
329
		$duplicate->baseUrl = null;
330
		$duplicate->pathInfo = null;
331
		$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\Components\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...
332
		$duplicate->clientIp = new RequestClientIP($duplicate->server->all());
333
334
		return $duplicate;		
335
	}
336
337
	/**
338
	 * Returns the desired segment, or $default if it does not exist.
339
	 *
340
	 * @param  int  $index  The segment number (1-based index)
341
	 * @param  mixed  $default  Default value to return
342
	 *
343
	 * @return string
344
	 */
345
	public function segment($index, $default = null)
346
	{
347
		return $this->uri->getSegment($index, $default);
348
	}
349
350
	/**
351
	 * Returns all segments in an array. For total of segments
352
	 * used the function PHP count().
353
	 *
354
	 * @return array|null
355
	 */
356
	public function segments()
357
	{
358
		return $this->uri->getSegments();
359
	}
360
361
	/**
362
	 * Returns the total number of segment.
363
	 *
364
	 * @return int|null  
365
	 */
366
	public function totalSegments()
367
	{
368
		return $this->uri->getTotalSegments();
369
	}
370
371
	/**
372
	 * Handles setting up the locale, auto-detecting of language.
373
	 * 
374
	 * @return void
375
	 */
376
	public function detectLocale(): void
377
	{
378
		$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\Components\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\Components\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...
379
380
		$this->setLocale($this->validLocales[0]);
381
	}
382
383
	/**
384
	 * Returns the default locale as set.
385
	 * 
386
	 * @return string
387
	 */
388
	public function getDefaultLocale(): string
389
	{
390
		return $this->defaultLocale;
391
	}
392
393
	/**
394
	 * Gets the current locale, with a fallback to the default.
395
	 * 
396
	 * @return string 
397
	 */
398
	public function getLocale(): string
399
	{
400
		return $this->languages ?: $this->defaultLocale;
401
	}
402
403
	/**
404
	 * Sets the locale string for this request.
405
	 * 
406
	 * @param  string  $locale
407
	 * 
408
	 * @return self
409
	 */
410
	public function setLocale(string $locale): self
411
	{
412
		if ( ! in_array($locale, $this->validLocales, true)) {
413
			$locale = $this->defaultLocale;
414
		}
415
		
416
		$this->languages = $locale;
417
418
		Locale::setDefault($locale);
419
			
420
		return $this;
421
	}
422
423
	/**
424
	 * Returns the full request string.
425
	 * 
426
	 * @param  string  $key
427
	 * @param  mixed  $default
428
	 *
429
	 * @return mixed 
430
	 */
431
	public function get(string $key, $default = null) 
432
	{
433
		if ($this !== $result = $this->attributes->get($key, $this)) {
434
			return $result;
435
		}
436
437
		if ($this->query->has($key)) {
438
			return $this->query->all()[$key];
439
		}
440
		
441
		if ($this->request->has($key)) {
442
			return $this->request->all()[$key];
443
		}
444
		
445
		return $default;
446
	}
447
448
	/**
449
	 * Gets the Session.
450
	 * 
451
	 * @return \Syscodes\Components\Http\Session\SessionInterface
452
	 * 
453
	 * @throws \Syscodes\Components\Http\Exceptions\SessionNotFoundException
454
	 */
455
	public function getSession()
456
	{
457
		$this->hasSession()
458
		            ? new SessionDecorator($this->session())
459
					: throw new SessionNotFoundException;
460
	}
461
462
	/**
463
	 * Whether the request contains a Session object.
464
	 * 
465
	 * @return bool
466
	 */
467
	public function hasSession(): bool
468
	{
469
		return ! is_null($this->session);
470
	}
471
472
	/**
473
	 * Get the session associated with the request.
474
	 * 
475
	 * @return \Syscodes\Components\Contracts\Session\Session
476
	 * 
477
	 * @throws RuntimeException
478
	 */
479
	public function session()
480
	{
481
		if ( ! $this->hasSession()) {
482
			throw new RuntimeException('Session store not set on request');
483
		}
484
		
485
		return $this->session;
486
	}
487
	
488
	/**
489
	 * Set the session instance on the request.
490
	 * 
491
	 * @param  \Syscodes\Components\Contracts\Session\Session  $session
492
	 * 
493
	 * @return void
494
	 */
495
	public function setSession($session): void
496
	{
497
		$this->session = $session;
498
	}
499
500
	/**
501
	 * Get the JSON payload for the request.
502
	 * 
503
	 * @param  string|null  $key  
504
	 * @param  mixed  $default  
505
	 * 
506
	 * @return \Syscodes\Components\Http\Utilities\Parameters|mixed
0 ignored issues
show
Bug introduced by
The type Syscodes\Components\Http\Utilities\Parameters was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
507
	 */
508
	public function json($key = null, $default = null)
509
	{
510
		if ( ! isset($this->json)) {
511
			$this->json = new Parameters((array) json_decode($this->getContent(), true));
512
		}
513
514
		if (is_null($key)) {
515
			return $this->json;
516
		}
517
518
		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

518
		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...
519
	}
520
521
	/**
522
	 * Set the JSON payload for the request.
523
	 * 
524
	 * @param  \Syscodes\Components\Http\Utilities\Parameters  $json
525
	 * 
526
	 * @return static
527
	 */
528
	public function setJson($json): static
529
	{
530
		$this->json = $json;
531
532
		return $this;
533
	}
534
	
535
	/**
536
	 * Gets a list of content types acceptable by the client browser in preferable order.
537
	 * 
538
	 * @return string[]
539
	 */
540
	public function getAcceptableContentTypes(): array
541
	{
542
		if (null !== $this->acceptableContentTypes) {
543
			return $this->acceptableContentTypes;
544
		}
545
		
546
		return $this->acceptableContentTypes = array_map('strval', [$this->headers->get('Accept')]);
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->headers->get('Accept') targeting Syscodes\Components\Http\Loaders\Headers::get() 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...
547
	}
548
549
	/**
550
	 * Returns whether this is an AJAX request or not.
551
	 * Alias of isXmlHttpRequest().
552
	 *
553
	 * @return bool
554
	 */
555
	public function ajax(): bool
556
	{
557
		return $this->isXmlHttpRequest();
558
	}
559
560
	/**
561
	 * Returns whether this is an AJAX request or not.
562
	 *
563
	 * @return bool
564
	 */
565
	public function isXmlHttpRequest(): bool
566
	{
567
		return ! empty($this->server->get('HTTP_X_REQUESTED_WITH')) && 
568
				strtolower($this->server->get('HTTP_X_REQUESTED_WITH')) === 'xmlhttprequest';
569
	}
570
	
571
	/**
572
	 * Determine if the request is the result of a PJAX call.
573
	 * 
574
	 * @return bool
575
	 */
576
	public function pjax(): bool
577
	{
578
		return $this->headers->get('X-PJAX') == true;
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->headers->get('X-PJAX') targeting Syscodes\Components\Http\Loaders\Headers::get() 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...
579
	}
580
	
581
	/**
582
	 * Determine if the request is the result of a prefetch call.
583
	 * 
584
	 * @return bool
585
	 */
586
	public function prefetch(): bool
587
	{
588
		return strcasecmp($this->server->get('HTTP_X_MOZ') ?? '', 'prefetch') === 0 ||
589
		       strcasecmp($this->headers->get('Purpose') ?? '', 'prefetch') === 0;
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->headers->get('Purpose') targeting Syscodes\Components\Http\Loaders\Headers::get() 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...
590
	}
591
592
	/**
593
	 * Checks if the method request is of specified type.
594
	 * 
595
	 * @param  string  $method
596
	 * 
597
	 * @return bool
598
	 */
599
	public function isMethod(string $method): bool
600
	{
601
		return $this->getMethod() === strtoupper($method);
602
	}
603
604
	/**
605
     * Alias of the request method.
606
     * 
607
     * @return string
608
     */
609
    public function method(): string
610
    {
611
        return $this->getMethod();
612
    }
613
614
	/**
615
	 * Returns the input method used (GET, POST, DELETE, etc.).
616
	 *
617
	 * @return string
618
	 * 
619
	 * @throws \LogicException  
620
	 */
621
	public function getmethod(): string
622
	{
623
		if (null !== $this->method) {
624
			return $this->method;
625
		}
626
		
627
		$this->method = strtoupper($this->server->get('REQUEST_METHOD', 'GET'));
628
		
629
		if ('POST' !== $this->method) {
630
			return $this->method;
631
		}
632
		
633
		$method = $this->headers->get('X-HTTP-METHOD-OVERRIDE');
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $method is correct as $this->headers->get('X-HTTP-METHOD-OVERRIDE') targeting Syscodes\Components\Http\Loaders\Headers::get() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

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

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

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

Loading history...
634
		
635
		if ( ! $method && self::$httpMethodParameterOverride) {
0 ignored issues
show
introduced by
$method is of type null, thus it always evaluated to false.
Loading history...
636
			$method = $this->request->get('_method', $this->query->get('_method', 'POST'));
637
		}
638
		
639
		if ( ! is_string($method)) {
640
			return $this->method;
641
		}
642
		
643
		$method = strtoupper($method);
644
		
645
		if (in_array($method, ['GET', 'HEAD', 'POST', 'PUT', 'DELETE', 'CONNECT', 'OPTIONS', 'PATCH', 'PURGE', 'TRACE'], true)) {
646
			return $this->method = $method;
647
		}
648
		
649
		if ( ! preg_match('/^[A-Z]++$/D', $method)) {
650
			throw new LogicException(sprintf('Invalid method override "%s".', $method));
651
		}
652
		
653
		return $this->method = $method;
654
	}
655
656
	/**
657
	 * Sets the request method.
658
	 *
659
	 * @param  string  $method  
660
	 *
661
	 * @return void
662
	 */
663
	public function setMethod(string $method): void
664
	{
665
		$this->method = null;
666
667
		$this->server->set('REQUEST_METHOD', $method);
668
	}
669
670
	/**
671
	 * Get the input source for the request.
672
	 * 
673
	 * @return \Syscodes\Components\Http\Utilities\Parameters
674
	 */
675
	public function getInputSource()
676
	{
677
		if ($this->isJson()) {
678
			return $this->json();
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->json() also could return the type Syscodes\Components\Http\Loaders\Parameters which is incompatible with the documented return type Syscodes\Components\Http\Utilities\Parameters.
Loading history...
679
		}
680
681
		return in_array($this->getMethod(), ['GET', 'HEAD']) ? $this->query : $this->request;
0 ignored issues
show
Bug Best Practice introduced by
The expression return in_array($this->g...>query : $this->request returns the type Syscodes\Components\Http\Loaders\Parameters which is incompatible with the documented return type Syscodes\Components\Http\Utilities\Parameters.
Loading history...
682
	}
683
	
684
	/**
685
	 * Determine if the current request URI matches a pattern.
686
	 * 
687
	 * @param  mixed  ...$patterns
688
	 * 
689
	 * @return bool
690
	 */
691
	public function is(...$patterns): bool
692
	{
693
		$path = $this->decodedPath();
694
		
695
		foreach ($patterns as $pattern) {
696
			if (Str::is($pattern, $path)) {
697
				return true;
698
			}
699
		}
700
701
		return false;
702
	}
703
704
	/**
705
	 * Determine if the route name matches a given pattern.
706
	 * 
707
	 * @param  mixed  ...$patterns
708
	 * 
709
	 * @return bool
710
	 */
711
	public function routeIs(...$patterns): bool
712
	{
713
		return $this->route() && $this->route()->is(...$patterns);
0 ignored issues
show
Bug introduced by
The method is() does not exist on Syscodes\Components\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

713
		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...
714
	}
715
716
	/**
717
	 * Get the route handling the request.
718
	 * 
719
	 * @param  string|null  $param  
720
	 * @param  mixed  $default  
721
	 * 
722
	 * @return \Syscodes\Components\Routing\Route|object|string|null
723
	 */
724
	public function route($param = null, $default = null)
725
	{
726
		$route = call_user_func($this->getRouteResolver());
727
728
		if (is_null($route) || is_null($param)) {
729
			return $route;
730
		}
731
732
		return $route->parameter($param, $default);
733
	}
734
735
	/**
736
	 * Get the current decoded path info for the request.
737
	 * 
738
	 * @return string
739
	 */
740
	public function decodedPath(): string
741
	{
742
		return rawurldecode($this->path());
743
	}
744
745
	/**
746
	 * Get the current path info for the request.
747
	 * 
748
	 * @return string
749
	 */
750
	public function path(): string
751
	{
752
		$path = trim($this->getPathInfo(), '/');
753
754
		return $path == '' ? '/' : $path;
755
	}
756
757
	/**
758
	 * Get the full URL for the request.
759
	 * 
760
	 * @return string
761
	 */
762
	public function fullUrl(): string
763
	{
764
		$query = $this->getQueryString();
765
		
766
		$question = $this->getBaseUrl().$this->getPathInfo() === '/' ? '/?' : '?';
767
		
768
		return $query ? $this->url().$question.$query : $this->url();
769
	}
770
	
771
	/**
772
	 * Generates the normalized query string for the Request.
773
	 * 
774
	 * @return string
775
	 */
776
	public function getQueryString(): ?string
777
	{
778
		$queryString = RequestUtils::normalizedQueryString($this->server->get('QUERY_STRING'));
779
		
780
		return '' === $queryString ? null : $queryString;
781
	}
782
783
	/**
784
	 * Retunrs the request body content.
785
	 * 
786
	 * @return string
787
	 */
788
	public function getContent(): string
789
	{
790
		if (null === $this->content || false === $this->content) {
791
			$this->content = file_get_contents('php://input');
792
		}
793
794
		return $this->content;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->content could return the type object|resource which is incompatible with the type-hinted return string. Consider adding an additional type-check to rule them out.
Loading history...
795
	}
796
797
	/**
798
	 * Returns the path being requested relative to the executed script. 
799
	 * 
800
	 * @return string
801
	 */
802
	public function getPathInfo(): string
803
	{
804
		if (null === $this->pathInfo) {
805
			$this->pathInfo = $this->parsePathInfo();
806
		}
807
808
		return $this->pathInfo;
809
	}
810
811
	/**
812
	 * Returns the root URL from which this request is executed.
813
	 * 
814
	 * @return string
815
	 */
816
	public function getBaseUrl(): string
817
	{
818
		if (null === $this->baseUrl) {
819
			$this->baseUrl = $this->parseBaseUrl();
820
		}
821
822
		return $this->baseUrl;
823
	}
824
825
	/**
826
	 * Returns the requested URI.
827
	 * 
828
	 * @return string
829
	 */
830
	public function getRequestUri(): string
831
	{
832
		if (null === $this->requestToUri) {
833
			$this->requestToUri = $this->parseRequestUri();
834
		}
835
836
		return $this->requestToUri;
837
	}
838
	
839
	/**
840
	 * Generates a normalized URI (URL) for the Request.
841
	 * 
842
	 * @return string
843
	 */
844
	public function getUri(): string
845
	{
846
		if (null !== $query = $this->getQueryString()) {
847
			$query = '?'.$query;
848
		}
849
	
850
		return $this->getSchemeWithHttpHost().$this->getBaseUrl().$this->getPathInfo().$query;
851
	}
852
	
853
	/**
854
	 * Gets the request's scheme.
855
	 * 
856
	 * @return string
857
	 */
858
	public function getScheme(): string
859
	{
860
		return $this->secure() ? $this->uri->setScheme('https') : $this->uri->setScheme('http');
861
	}
862
863
	/**
864
	 * Returns the host name.
865
	 * 
866
	 * @return string
867
	 */
868
	public function getHost(): string
869
	{
870
		if ($forwardedHost = $this->server->get('HTTP_X_FORWARDED_HOST')) {
871
			$host = $forwardedHost[0];
872
		} elseif ( ! $host = $this->headers->get('HOST')) {
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $host is correct as $this->headers->get('HOST') targeting Syscodes\Components\Http\Loaders\Headers::get() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

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

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

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

Loading history...
873
			if ( ! $host = $this->server->get('SERVER_NAME')) {
874
				$host = $this->server->get('REMOTE_ADDR', '');
875
			}
876
		}
877
878
		$host = strtolower(preg_replace('/:\d+$/', '', trim(($host))));
879
		
880
		return $this->uri->setHost($host);
881
	}
882
883
	/**
884
	 * Returns the port on which the request is made.
885
	 * 
886
	 * @return int
887
	 */
888
	public function getPort(): int
889
	{
890
		if ( ! $this->server->get('HTTP_HOST')) {
891
			return $this->server->get('SERVER_PORT');
892
		}
893
		
894
		return 'https' === $this->getScheme() ? $this->uri->setPort(443) : $this->uri->setPort(80);
0 ignored issues
show
Bug Best Practice introduced by
The expression return 'https' === $this...$this->uri->setPort(80) returns the type string which is incompatible with the type-hinted return integer.
Loading history...
895
	}
896
897
	/**
898
	 * Get the user.
899
	 * 
900
	 * @return string|null
901
	 */
902
	public function getUser(): ?string
903
	{
904
		$user = $this->uri->setUser(
905
			$this->headers->get('PHP_AUTH_USER')
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->headers->get('PHP_AUTH_USER') targeting Syscodes\Components\Http\Loaders\Headers::get() 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...
906
		);
907
908
		return $user;
909
	}
910
911
	/**
912
	 * Get the password.
913
	 * 
914
	 * @return string|null
915
	 */
916
	public function getPassword(): ?string
917
	{
918
		$password = $this->uri->setPassword(
919
			$this->headers->get('PHP_AUTH_PW')
0 ignored issues
show
Bug introduced by
Are you sure the usage of $this->headers->get('PHP_AUTH_PW') targeting Syscodes\Components\Http\Loaders\Headers::get() 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...
920
		);
921
922
		return $password;
923
	}
924
925
	/**
926
	 * Gets the user info.
927
	 * 
928
	 * @return string|null
929
	 */
930
	public function getUserInfo(): ?string
931
	{
932
		return $this->uri->getUserInfo();
933
	}
934
935
	/**
936
	 * Returns the HTTP host being requested.
937
	 * 
938
	 * @return string
939
	 */
940
	public function getHttpHost(): string
941
	{
942
		$scheme = $this->getScheme();
943
		$port   = $this->getPort();
944
945
		if (('http' === $scheme && 80 === $port) || ('https' === $scheme && 443 === $port))	{
946
			return $this->getHost();
947
		}
948
949
		return $this->getHost().':'.$port;
950
	}
951
952
	/**
953
	 * Gets the scheme and HTTP host.
954
	 * 
955
	 * @return string
956
	 */
957
	public function getSchemeWithHttpHost(): string
958
	{
959
		return $this->getScheme().'://'.$this->getHttpHost();
960
	}
961
962
	/**
963
	 * Get the root URL for the application.
964
	 * 
965
	 * @return string
966
	 */
967
	public function root(): string
968
	{
969
		return rtrim($this->getSchemeWithHttpHost().$this->getBaseUrl(), '/');
970
	}
971
972
	/**
973
	 * Get the URL for the request.
974
	 * 
975
	 * @return string
976
	 */
977
	public function url(): string
978
	{
979
		// Changed $this->path() for $this->getUri()
980
		return rtrim(preg_replace('/\?.*/', '', $this->getUri()), '/');
981
	}
982
983
	/**
984
	 * Returns the referer.
985
	 * 
986
	 * @param  string  $default
987
	 * 
988
	 * @return string
989
	 */
990
	public function referer(string $default = ''): string
991
	{
992
		return $this->server->get('HTTP_REFERER', $default);
993
	}
994
	
995
	/**
996
	 * Attempts to detect if the current connection is secure through 
997
	 * over HTTPS protocol.
998
	 * 
999
	 * @return bool
1000
	 */
1001
	public function secure(): bool
1002
	{
1003
		if ( ! empty($this->server->get('HTTPS')) && strtolower($this->server->get('HTTPS')) !== 'off') {
1004
			return true;
1005
		} elseif (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $this->server->get('HTTP_X_FORWARDED_PROTO') === 'https') {
1006
			return true;
1007
		} elseif ( ! empty($this->server->get('HTTP_FRONT_END_HTTPS')) && strtolower($this->server->get('HTTP_FRONT_END_HTTPS')) !== 'off') {
1008
			return true;
1009
		}
1010
1011
		return false;
1012
	}
1013
1014
	/**
1015
	 * Returns the user agent.
1016
	 *
1017
	 * @param  string|null  $default
1018
	 *
1019
	 * @return string
1020
	 */
1021
	public function userAgent(string $default = null): string
1022
	{
1023
		return $this->server->get('HTTP_USER_AGENT', $default);
1024
	}
1025
	
1026
	/**
1027
	 * Get the client IP address.
1028
	 * 
1029
	 * @return string|null
1030
	 */
1031
	public function ip(): ?string
1032
	{
1033
		return $this->clientIp->getClientIp();
1034
	}
1035
1036
	/**
1037
	 * Get the route resolver callback.
1038
	 * 
1039
	 * @return \Closure
1040
	 */
1041
	public function getRouteResolver(): Closure
1042
	{
1043
		return $this->routeResolver ?: function () {
1044
			//
1045
		};
1046
	}
1047
1048
	/**
1049
	 * Set the route resolver callback.
1050
	 * 
1051
	 * @param  \Closure  $callback
1052
	 * 
1053
	 * @return static
1054
	 */
1055
	public function setRouteResolver(Closure $callback): static
1056
	{
1057
		$this->routeResolver = $callback;
1058
1059
		return $this;
1060
	}
1061
1062
	/**
1063
	 * Magic method.
1064
	 * 
1065
	 * Get an element from the request.
1066
	 * 
1067
	 * @return string[]
1068
	 */
1069
	public function __get($key)
1070
	{
1071
		return Arr::get($this->all(), $key, fn () => $this->route($key));
1072
	}
1073
1074
	/**
1075
	 * Magic method.
1076
	 * 
1077
	 * Returns the Request as an HTTP string.
1078
	 * 
1079
	 * @return string
1080
	 */
1081
	public function __toString(): string
1082
	{
1083
		$content = $this->getContent();
1084
1085
		$cookieHeader = '';
1086
		$cookies      = [];
1087
1088
		foreach ($this->cookies as $key => $value) {
1089
			$cookies[]= is_array($value) ? http_build_query([$key => $value], '', '; ', PHP_QUERY_RFC3986) : "$key=$value";
1090
		}
1091
1092
		if ($cookies) {
1093
			$cookieHeader = 'Cookie: '.implode('; ', $cookies)."\r\n";
1094
		}
1095
		
1096
		return sprintf('%s %s %s', $this->getMethod(), $this->getRequestUri(), $this->server->get('SERVER_PROTOCOL'))."\r\n".
1097
			$this->headers.
1098
			$cookieHeader."\r\n".
1099
			$content;
1100
	}
1101
1102
	/**
1103
	 * Magic method.
1104
	 * 
1105
	 * Clones the current request.
1106
	 * 
1107
	 * @return void
1108
	 */
1109
	public function __clone()
1110
	{
1111
		$this->query      = clone $this->query;
1112
		$this->request    = clone $this->request;
1113
		$this->attributes = clone $this->attributes;
1114
		$this->cookies    = clone $this->cookies;
1115
		$this->files      = clone $this->files;
1116
		$this->server     = clone $this->server;
1117
		$this->headers    = clone $this->headers;
1118
	}
1119
}