Passed
Branch master (634da9)
by refat
03:15
created

Request::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 1
dl 0
loc 4
rs 10
c 0
b 0
f 0
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];
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->files[$input]; (System\Http\UploadeFile) is incompatible with the return type documented by System\Http\Request::file of type array.

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:

class Author {
    private $name;

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

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
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();
0 ignored issues
show
Documentation introduced by
The property load does not exist on object<System\Application>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
373
374
            if (!$output) {
375
                return false;
376
            }
377
        }
378
379
        return true;
380
    }
381
}
382