1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace System\Http; |
4
|
|
|
|
5
|
|
|
use System\Application; |
6
|
|
|
|
7
|
|
|
class Request |
8
|
|
|
{ |
9
|
|
|
/** |
10
|
|
|
* Application Object |
11
|
|
|
* |
12
|
|
|
* @var \System\Application |
13
|
|
|
*/ |
14
|
|
|
private $app; |
15
|
|
|
|
16
|
|
|
/** |
17
|
|
|
* Url |
18
|
|
|
* |
19
|
|
|
* @var string |
20
|
|
|
*/ |
21
|
|
|
private $url; |
22
|
|
|
|
23
|
|
|
/** |
24
|
|
|
* Base Url |
25
|
|
|
* |
26
|
|
|
* @var string |
27
|
|
|
*/ |
28
|
|
|
private $baseUrl; |
29
|
|
|
|
30
|
|
|
/** |
31
|
|
|
* Uploaded files container |
32
|
|
|
* |
33
|
|
|
* @var array |
34
|
|
|
*/ |
35
|
|
|
private $files = []; |
36
|
|
|
|
37
|
|
|
/** |
38
|
|
|
* Host |
39
|
|
|
* |
40
|
|
|
* @var string |
41
|
|
|
*/ |
42
|
|
|
private $host; |
43
|
|
|
|
44
|
|
|
/** |
45
|
|
|
* Constructor |
46
|
|
|
* |
47
|
|
|
* @param \System\Application $app |
48
|
|
|
*/ |
49
|
|
|
public function __construct(Application $app) |
50
|
|
|
{ |
51
|
|
|
$this->app = $app; |
52
|
|
|
} |
53
|
|
|
|
54
|
|
|
/** |
55
|
|
|
* Prepare url |
56
|
|
|
* |
57
|
|
|
* @return void |
58
|
|
|
*/ |
59
|
|
|
public function prepareUrl() |
60
|
|
|
{ |
61
|
|
|
$script = dirname($this->server('SCRIPT_NAME')); |
62
|
|
|
|
63
|
|
|
$requestUri = $this->server('REQUEST_URI'); |
64
|
|
|
|
65
|
|
|
if (strpos($requestUri, '?')) { |
66
|
|
|
list($requestUri) = explode('?', $requestUri); |
67
|
|
|
} |
68
|
|
|
|
69
|
|
|
$this->url = $this->cleanUrl($script, $requestUri); |
70
|
|
|
|
71
|
|
|
$REQUEST_PROTOCOL = $this->isSecure() ? 'https' : 'http'; |
72
|
|
|
|
73
|
|
|
$this->host = $REQUEST_PROTOCOL . '://' . $this->server('HTTP_HOST'); |
74
|
|
|
|
75
|
|
|
$this->baseUrl = $this->host . $requestUri; |
76
|
|
|
} |
77
|
|
|
|
78
|
|
|
/** |
79
|
|
|
* Clean url |
80
|
|
|
* |
81
|
|
|
* @param string $script |
82
|
|
|
* @param string $requestUri |
83
|
|
|
* @return string |
84
|
|
|
*/ |
85
|
|
|
private function cleanUrl($script, $requestUri) |
86
|
|
|
{ |
87
|
|
|
if (!in_array($script, ['/', '\\'])) { |
88
|
|
|
$url = preg_replace('#^' . $script . '#', '', $requestUri); |
89
|
|
|
} else { |
90
|
|
|
$url = $requestUri; |
91
|
|
|
} |
92
|
|
|
|
93
|
|
|
if ($url !== '/') { |
94
|
|
|
$url = rtrim($url, '/'); |
95
|
|
|
} |
96
|
|
|
|
97
|
|
|
return $url; |
98
|
|
|
} |
99
|
|
|
|
100
|
|
|
/** |
101
|
|
|
* Check if the website is secure |
102
|
|
|
* |
103
|
|
|
* @return bool |
104
|
|
|
*/ |
105
|
|
|
private function isSecure() |
106
|
|
|
{ |
107
|
|
|
if ($this->checkHttp() || $this->checkHttpXforwardedProto() || $this->checkHttpXforwardedSsl()) { |
108
|
|
|
return true; |
109
|
|
|
} |
110
|
|
|
|
111
|
|
|
return false; |
112
|
|
|
} |
113
|
|
|
|
114
|
|
|
/** |
115
|
|
|
* Check if HTTPS is 'on' |
116
|
|
|
* |
117
|
|
|
* @return bool |
118
|
|
|
*/ |
119
|
|
|
private function checkHttp() |
120
|
|
|
{ |
121
|
|
|
if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') { |
122
|
|
|
return true; |
123
|
|
|
} |
124
|
|
|
|
125
|
|
|
return false; |
126
|
|
|
} |
127
|
|
|
|
128
|
|
|
/** |
129
|
|
|
* Check if HTTP_X_FORWARDED_PROTO is not empty or 'https' |
130
|
|
|
* |
131
|
|
|
* @return bool |
132
|
|
|
*/ |
133
|
|
|
private function checkHttpXforwardedProto() |
134
|
|
|
{ |
135
|
|
|
if (!empty($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') { |
136
|
|
|
return true; |
137
|
|
|
} |
138
|
|
|
|
139
|
|
|
return false; |
140
|
|
|
} |
141
|
|
|
|
142
|
|
|
/** |
143
|
|
|
* Check if HTTP_X_FORWARDED_SSL is 'on' |
144
|
|
|
* |
145
|
|
|
* @return bool |
146
|
|
|
*/ |
147
|
|
|
private function checkHttpXforwardedSsl() |
148
|
|
|
{ |
149
|
|
|
if (!empty($_SERVER['HTTP_X_FORWARDED_SSL']) && $_SERVER['HTTP_X_FORWARDED_SSL'] == 'on') { |
150
|
|
|
return true; |
151
|
|
|
} |
152
|
|
|
|
153
|
|
|
return false; |
154
|
|
|
} |
155
|
|
|
|
156
|
|
|
/** |
157
|
|
|
* Get value from spcefic request type |
158
|
|
|
* |
159
|
|
|
* @param array $requestType |
160
|
|
|
* @param string $key |
161
|
|
|
* @return mixed |
162
|
|
|
*/ |
163
|
|
|
private function getValueOfRequest($requestType, $key) |
164
|
|
|
{ |
165
|
|
|
$value = array_get($requestType, $key); |
166
|
|
|
|
167
|
|
|
if (is_array($value)) { |
168
|
|
|
$value = array_filter($value); |
169
|
|
|
} else { |
170
|
|
|
$value = trim($value); |
171
|
|
|
} |
172
|
|
|
|
173
|
|
|
return $value; |
174
|
|
|
} |
175
|
|
|
|
176
|
|
|
/** |
177
|
|
|
* Get value from $_GET by the given key |
178
|
|
|
* |
179
|
|
|
* @param string $key |
180
|
|
|
* @return mixed |
181
|
|
|
*/ |
182
|
|
|
public function get($key) |
183
|
|
|
{ |
184
|
|
|
return $this->getValueOfRequest($_GET, $key); |
185
|
|
|
} |
186
|
|
|
|
187
|
|
|
/** |
188
|
|
|
* Get value from $_POST by the given key |
189
|
|
|
* |
190
|
|
|
* @param string $key |
191
|
|
|
* @return mixed |
192
|
|
|
*/ |
193
|
|
|
public function post($key) |
194
|
|
|
{ |
195
|
|
|
return $this->getValueOfRequest($_POST, $key); |
196
|
|
|
} |
197
|
|
|
|
198
|
|
|
/** |
199
|
|
|
* Set value To $_POST For the given key |
200
|
|
|
* |
201
|
|
|
* @param string $key |
202
|
|
|
* @param mixed $value |
203
|
|
|
* @return mixed |
204
|
|
|
*/ |
205
|
|
|
public function setPost($key, $value) |
206
|
|
|
{ |
207
|
|
|
$_POST[$key] = $value; |
208
|
|
|
} |
209
|
|
|
|
210
|
|
|
/** |
211
|
|
|
* Get $_POST |
212
|
|
|
* |
213
|
|
|
* @return array |
214
|
|
|
*/ |
215
|
|
|
public function posts() |
216
|
|
|
{ |
217
|
|
|
return $_POST; |
218
|
|
|
} |
219
|
|
|
|
220
|
|
|
/** |
221
|
|
|
* Get $_GET |
222
|
|
|
* |
223
|
|
|
* @return array |
224
|
|
|
*/ |
225
|
|
|
public function gets() |
226
|
|
|
{ |
227
|
|
|
return $_GET; |
228
|
|
|
} |
229
|
|
|
|
230
|
|
|
/** |
231
|
|
|
* Get $_FILES |
232
|
|
|
* |
233
|
|
|
* @return array |
234
|
|
|
*/ |
235
|
|
|
public function files() |
236
|
|
|
{ |
237
|
|
|
return $_FILES; |
238
|
|
|
} |
239
|
|
|
|
240
|
|
|
/** |
241
|
|
|
* Get the uploaded file object for the given input |
242
|
|
|
* |
243
|
|
|
* @param string $input |
244
|
|
|
* @return array |
245
|
|
|
*/ |
246
|
|
|
public function file($input) |
247
|
|
|
{ |
248
|
|
|
if (isset($this->files[$input])) { |
249
|
|
|
return $this->files[$input]; |
250
|
|
|
} |
251
|
|
|
|
252
|
|
|
$upoadedFile = new UploadeFile($this->app, $input); |
253
|
|
|
|
254
|
|
|
$this->files[$input] = $upoadedFile; |
255
|
|
|
|
256
|
|
|
return $this->files[$input]; |
|
|
|
|
257
|
|
|
} |
258
|
|
|
|
259
|
|
|
/** |
260
|
|
|
* Get value from $_SERVER by the given key |
261
|
|
|
* |
262
|
|
|
* @param string $key |
263
|
|
|
* @return mixed |
264
|
|
|
*/ |
265
|
|
|
public function server($key) |
266
|
|
|
{ |
267
|
|
|
return array_get($_SERVER, $key); |
268
|
|
|
} |
269
|
|
|
|
270
|
|
|
/** |
271
|
|
|
* Get current request method |
272
|
|
|
* |
273
|
|
|
* @return string |
274
|
|
|
*/ |
275
|
|
|
public function method() |
276
|
|
|
{ |
277
|
|
|
return $this->server('REQUEST_METHOD'); |
278
|
|
|
} |
279
|
|
|
|
280
|
|
|
/** |
281
|
|
|
* Get the referer link |
282
|
|
|
* |
283
|
|
|
* @return string |
284
|
|
|
*/ |
285
|
|
|
public function referer() |
286
|
|
|
{ |
287
|
|
|
return $this->server('HTTP_REFERER'); |
288
|
|
|
} |
289
|
|
|
|
290
|
|
|
/** |
291
|
|
|
* Get full url of the script |
292
|
|
|
* |
293
|
|
|
* @return string |
294
|
|
|
*/ |
295
|
|
|
public function baseUrl() |
296
|
|
|
{ |
297
|
|
|
return $this->baseUrl; |
298
|
|
|
} |
299
|
|
|
|
300
|
|
|
/** |
301
|
|
|
* Get only relative url (clean url) |
302
|
|
|
* |
303
|
|
|
* @return string |
304
|
|
|
*/ |
305
|
|
|
public function url() |
306
|
|
|
{ |
307
|
|
|
return $this->url; |
308
|
|
|
} |
309
|
|
|
|
310
|
|
|
/** |
311
|
|
|
* Get only host |
312
|
|
|
* |
313
|
|
|
* @return string |
314
|
|
|
*/ |
315
|
|
|
public function host() |
316
|
|
|
{ |
317
|
|
|
return $this->host; |
318
|
|
|
} |
319
|
|
|
|
320
|
|
|
/** |
321
|
|
|
* Check if the request to the admin panel |
322
|
|
|
* |
323
|
|
|
* @return bool |
324
|
|
|
*/ |
325
|
|
|
public function isRequestToAdminManagement() |
326
|
|
|
{ |
327
|
|
|
$url = $this->url; |
328
|
|
|
|
329
|
|
|
$url = ltrim($url, '/'); |
330
|
|
|
|
331
|
|
|
$url = explode('/', $url)[0]; |
332
|
|
|
|
333
|
|
|
return $url == 'admin'; |
334
|
|
|
} |
335
|
|
|
|
336
|
|
|
/** |
337
|
|
|
* Check the request method |
338
|
|
|
* |
339
|
|
|
* @return bool |
340
|
|
|
*/ |
341
|
|
|
public function isMatchingRequestMethod($methods = ['GET']) |
342
|
|
|
{ |
343
|
|
|
if (!is_array($methods)) { |
344
|
|
|
$methods = [$methods]; |
345
|
|
|
} |
346
|
|
|
|
347
|
|
|
if (empty($methods)) { |
348
|
|
|
$methods = ['GET']; |
349
|
|
|
} |
350
|
|
|
|
351
|
|
|
foreach ($methods as $method) { |
352
|
|
|
if ($this->method() == strtoupper($method)) { |
353
|
|
|
return true; |
354
|
|
|
} |
355
|
|
|
} |
356
|
|
|
|
357
|
|
|
return false; |
358
|
|
|
} |
359
|
|
|
|
360
|
|
|
/** |
361
|
|
|
* Check if the request can be Continued |
362
|
|
|
* @property object $load |
363
|
|
|
* @return bool |
364
|
|
|
*/ |
365
|
|
|
public function canRequestContinue($middlewares) |
366
|
|
|
{ |
367
|
|
|
if (empty($middlewares)) { |
368
|
|
|
return true; |
369
|
|
|
} |
370
|
|
|
|
371
|
|
|
foreach ($middlewares as $middleware) { |
372
|
|
|
$output = $this->app->load->middleware($middleware)->handle(); |
|
|
|
|
373
|
|
|
|
374
|
|
|
if (!$output) { |
375
|
|
|
return false; |
376
|
|
|
} |
377
|
|
|
} |
378
|
|
|
|
379
|
|
|
return true; |
380
|
|
|
} |
381
|
|
|
} |
382
|
|
|
|
If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.
Let’s take a look at an example:
Our function
my_function
expects aPost
object, and outputs the author of the post. The base classPost
returns a simple string and outputting a simple string will work just fine. However, the child classBlogPost
which is a sub-type ofPost
instead decided to return anobject
, and is therefore violating the SOLID principles. If aBlogPost
were passed tomy_function
, PHP would not complain, but ultimately fail when executing thestrtoupper
call in its body.