Request   A
last analyzed

Complexity

Total Complexity 21

Size/Duplication

Total Lines 138
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 50
dl 0
loc 138
rs 10
c 0
b 0
f 0
wmc 21

8 Methods

Rating   Name   Duplication   Size   Complexity  
A updateHostFromUri() 0 21 4
A withUri() 0 14 3
A getUri() 0 2 1
A getMethod() 0 2 1
A withRequestTarget() 0 10 2
A getRequestTarget() 0 17 4
A withMethod() 0 16 3
A __construct() 0 12 3
1
<?php
2
/**
3
 * Class Request
4
 *
5
 * @created      11.08.2018
6
 * @author       smiley <[email protected]>
7
 * @copyright    2018 smiley
8
 * @license      MIT
9
 *
10
 * @phan-file-suppress PhanParamSignatureMismatch
11
 */
12
13
namespace chillerlan\HTTP\Psr7;
14
15
use Fig\Http\Message\RequestMethodInterface;
16
use InvalidArgumentException;
17
use Psr\Http\Message\{RequestInterface, UriInterface};
18
19
use function is_string, preg_match, strtoupper, trim;
20
21
class Request extends Message implements RequestInterface, RequestMethodInterface{
22
23
	protected string       $method;
24
	protected UriInterface $uri;
25
	protected ?string      $requestTarget = null;
26
27
	/**
28
	 * Request constructor.
29
	 */
30
	public function __construct(string $method, UriInterface|string $uri){
31
		parent::__construct();
32
33
		$this->method = strtoupper(trim($method));
34
35
		if($method === ''){
36
			throw new InvalidArgumentException('HTTP method must not be empty');
37
		}
38
39
		$this->uri = $uri instanceof UriInterface ? $uri : new Uri($uri);
40
41
		$this->updateHostFromUri();
42
	}
43
44
	/**
45
	 * @inheritDoc
46
	 */
47
	public function getRequestTarget():string{
48
49
		if($this->requestTarget !== null){
50
			return $this->requestTarget;
51
		}
52
53
		$target = $this->uri->getPath();
54
55
		if($target === ''){
56
			$target = '/';
57
		}
58
59
		if($this->uri->getQuery() !== ''){
60
			$target .= '?'.$this->uri->getQuery();
61
		}
62
63
		return $target;
64
	}
65
66
	/**
67
	 * @inheritDoc
68
	 */
69
	public function withRequestTarget($requestTarget):RequestInterface{
70
71
		if(preg_match('#\s#', $requestTarget)){
72
			throw new InvalidArgumentException('Invalid request target provided; cannot contain whitespace');
73
		}
74
75
		$clone                = clone $this;
76
		$clone->requestTarget = $requestTarget;
77
78
		return $clone;
79
	}
80
81
	/**
82
	 * @inheritDoc
83
	 */
84
	public function getMethod():string{
85
		return $this->method;
86
	}
87
88
	/**
89
	 * @inheritDoc
90
	 */
91
	public function withMethod($method):RequestInterface{
92
93
		if(!is_string($method)){
94
			throw new InvalidArgumentException('Method must be a string');
95
		}
96
97
		$method = trim($method);
98
99
		if($method === ''){
100
			throw new InvalidArgumentException('HTTP method must not be empty');
101
		}
102
103
		$clone         = clone $this;
104
		$clone->method = strtoupper($method);
105
106
		return $clone;
107
	}
108
109
	/**
110
	 * @inheritDoc
111
	 */
112
	public function getUri():UriInterface{
113
		return $this->uri;
114
	}
115
116
	/**
117
	 * @inheritDoc
118
	 */
119
	public function withUri(UriInterface $uri, $preserveHost = false):RequestInterface{
120
121
		if($uri === $this->uri){
122
			return $this;
123
		}
124
125
		$new      = clone $this;
126
		$new->uri = $uri;
127
128
		if(!$preserveHost){
129
			$new->updateHostFromUri();
130
		}
131
132
		return $new;
133
	}
134
135
	/**
136
	 *
137
	 */
138
	protected function updateHostFromUri():void{
139
		$host = $this->uri->getHost();
140
141
		if($host === ''){
142
			return;
143
		}
144
145
		if(($port = $this->uri->getPort()) !== null){
146
			$host .= ':'.$port;
147
		}
148
149
		if(isset($this->headerNames['host'])){
150
			$header = $this->headerNames['host'];
151
		}
152
		else{
153
			$header                    = 'Host';
154
			$this->headerNames['host'] = 'Host';
155
		}
156
		// Ensure Host is the first header.
157
		// See: http://tools.ietf.org/html/rfc7230#section-5.4
158
		$this->headers = [$header => [$host]] + $this->headers;
159
	}
160
161
}
162