GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

Request::name()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 2
eloc 2
nc 2
nop 0
1
<?php
2
3
/**
4
 * Request class.
5
 *
6
 * It contains the request information and provide methods to fetch request body
7
 *
8
 * @license    http://opensource.org/licenses/MIT The MIT License (MIT)
9
 * @author     Omar El Gabry <[email protected]>
10
 */
11
12
class Request{
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
13
14
    /**
15
     * Set a list of trusted hosts patterns.
16
     * 
17
     * @var array
18
     */
19
    private static $trustedHostPatterns = [];
20
21
    /**
22
     * Array of parameters parsed from the URL.
23
     *
24
     * @var array
25
    */
26
     public $params = [
27
        "controller" => null, "action"  => null, "args"  => null
28
    ];
29
30
    /**
31
     * Array of POST data as well as uploaded files.
32
     *
33
     * @var array
34
     */
35
    public $data = [];
36
37
    /**
38
     * Array of querystring arguments
39
     *
40
     * @var array
41
     */
42
     public $query = [];
43
44
    /**
45
     * The URL used to make the request.
46
     *
47
     * @var string
48
     */
49
    public $url = null;
50
51
     /**
52
      * Constructor
53
      * Create a new request from PHP superglobals.
54
      *
55
      * @param array $config user provided config
56
      */
57
    public function __construct($config = []){
0 ignored issues
show
Coding Style introduced by
__construct uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

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

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
Coding Style introduced by
__construct uses the super-global variable $_FILES which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

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

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
Coding Style introduced by
__construct uses the super-global variable $_GET which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

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

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
58
59
        $this->data    = $this->mergeData($_POST, $_FILES);
60
        $this->query   = $_GET;
61
        $this->params += isset($config["params"])? $config["params"]: [];
62
        $this->url     = $this->fullUrl();
63
    }
64
65
    /**
66
     * merge post and files data
67
     * You shouldn't have two fields with the same 'name' attribute in $_POST & $_FILES
68
     *
69
     * @param  array $post
70
     * @param  array $files
71
     * @return array the merged array
72
     */
73
    private function mergeData(array $post, array $files){
74
        foreach($post as $key => $value) {
75
            if(is_string($value)) { $post[$key] = trim($value); }
76
        }
77
        return array_merge($files, $post);
78
    }
79
80
     /**
81
      * count fields in $this->data and optionally exclude some fields
82
      *
83
      * @param  array   $exclude
84
      * @return mixed
85
      */
86
     public function countData(array $exclude = []){
87
         $count = count($this->data);
88
         foreach($exclude as $field){
89
             if(array_key_exists($field, $this->data)){
90
                 $count--;
91
             }
92
         }
93
         return $count;
94
     }
95
96
     /**
97
      * safer and better access to $this->data
98
      *
99
      * @param  string   $key
100
      * @return mixed
101
      */
102
     public function data($key){
103
         return array_key_exists($key, $this->data)? $this->data[$key]: null;
104
     }
105
106
     /**
107
      * safer and better access to $this->query
108
      *
109
      * @param  string   $key
110
      * @return mixed
111
      */
112
     public function query($key){
113
         return array_key_exists($key, $this->query)? $this->query[$key]: null;
114
     }
115
116
     /**
117
      * safer and better access to $this->params
118
      *
119
      * @param  string   $key
120
      * @return mixed
121
      */
122
     public function param($key){
123
         return array_key_exists($key, $this->params)? $this->params[$key]: null;
124
     }
125
126
    /**
127
     * detect if request is Ajax
128
     *
129
     * @return boolean
130
     */
131
    public function isAjax(){
0 ignored issues
show
Coding Style introduced by
isAjax uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

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

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
132
        if(!empty($_SERVER['HTTP_X_REQUESTED_WITH'])){
133
            return strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest';
134
        }
135
        return false;
136
    }
137
138
    /**
139
     * detect if request is POST request
140
     *
141
     * @return boolean
142
     */
143
    public function isPost(){
0 ignored issues
show
Coding Style introduced by
isPost uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

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

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
144
        return $_SERVER["REQUEST_METHOD"] === "POST";
145
    }
146
147
     /**
148
      * detect if request is GET request
149
      *
150
      * @return boolean
151
      */
152
     public function isGet(){
0 ignored issues
show
Coding Style introduced by
isGet uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

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

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
153
         return $_SERVER["REQUEST_METHOD"] === "GET";
154
     }
155
156
    /**
157
     * detect if request over secured connection(SSL)
158
     *
159
     * @return boolean
160
     *
161
     */
162
    public function isSSL(){
0 ignored issues
show
Coding Style introduced by
isSSL uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

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

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
163
        return isset($_SERVER['HTTPS']) && !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== "off";
164
    }
165
166
    /**
167
     * Add parameters to $this->params.
168
     *
169
     * @param  array $params
170
     * @return Request
171
     */
172
    public function addParams(array $params){
173
        $this->params = array_merge($this->params, $params);
174
        return $this;
175
    }
176
177
     /**
178
      * get content length
179
      *
180
      * @return integer
181
      */
182
     public function contentLength(){
0 ignored issues
show
Coding Style introduced by
contentLength uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

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

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
183
         return (int)$_SERVER['CONTENT_LENGTH'];
184
     }
185
186
     /**
187
      * checks if there is overflow in POST & FILES data.
188
      * This will lead to having both $_POST & $_FILES = empty array.
189
      *
190
      * @return bool
191
      */
192
     public function dataSizeOverflow(){
193
         $contentLength = $this->contentLength();
194
         return empty($this->data) && isset($contentLength);
195
     }
196
197
    /**
198
     * get the current uri of the request
199
     *
200
     * @return string|null
201
     */
202
    public function uri(){
0 ignored issues
show
Coding Style introduced by
uri uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

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

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
203
        return isset($_SERVER['REQUEST_URI'])? $_SERVER['REQUEST_URI']: null;
204
    }
205
206
    /**
207
     * Get the current host of the request
208
     *
209
     * @return string
210
     * @throws UnexpectedValueException if the hostname is invalid
211
     */
212
    public function host(){
213
214
        if (!$host = Environment::get('HTTP_HOST')) {
215
            if (!$host = $this->name()) {
216
                $host = Enviroment::get('SERVER_ADDR');
217
            }
218
        }
219
220
        // trim and remove port number from host
221
        $host = strtolower(preg_replace('/:\d+$/', '', trim($host)));
222
223
        // check that it does not contain forbidden characters
224
        if ($host && preg_replace('/(?:^\[)?[a-zA-Z0-9-:\]_]+\.?/', '', $host) !== '') {
225
            throw new UnexpectedValueException(sprintf('Invalid Host "%s"', $host));
226
        }
227
228
        // TODO
229
        // check the hostname against a trusted list of host patterns to avoid host header injection attacks
230
        if (count(self::$trustedHostPatterns) > 0) {
231
232
            foreach (self::$trustedHostPatterns as $pattern) {
233
                if (preg_match($pattern, $host)) {
234
                    return $host;
235
                }
236
            }
237
238
            throw new UnexpectedValueException(sprintf('Untrusted Host "%s"', $host));
239
        }
240
241
        return $host;
242
    }
243
244
    /**
245
     * Get the name of the server host
246
     *
247
     * @return string|null
248
     */
249
    public function name(){
0 ignored issues
show
Coding Style introduced by
name uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

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

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
250
        return isset($_SERVER['SERVER_NAME'])? $_SERVER['SERVER_NAME']: null;
251
    }
252
253
    /**
254
     * Get the referer of this request.
255
     *
256
     * @return string|null
257
     */
258
    public function referer(){
0 ignored issues
show
Coding Style introduced by
referer uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

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

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
259
        return isset($_SERVER['HTTP_REFERER'])? $_SERVER['HTTP_REFERER']: null;
260
    }
261
262
    /**
263
     * get the client IP addresses.
264
     *
265
     * 'REMOTE_ADDR' is the most trusted one,
266
     * otherwise you can use HTTP_CLIENT_IP, or HTTP_X_FORWARDED_FOR.
267
     *
268
     * @return string|null
269
     */
270
    public function clientIp(){
0 ignored issues
show
Coding Style introduced by
clientIp uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

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

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
271
        return isset($_SERVER['REMOTE_ADDR'])? $_SERVER['REMOTE_ADDR']: null;
272
    }
273
274
    /**
275
     * get the contents of the User Agent
276
     *
277
     * @return string|null
278
     */
279
    public function userAgent(){
0 ignored issues
show
Coding Style introduced by
userAgent uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

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

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
280
        return isset($_SERVER['HTTP_USER_AGENT'])? $_SERVER['HTTP_USER_AGENT']: null;
281
    }
282
283
    /**
284
     * Gets the request's protocol.
285
     *
286
     * @return string
287
     */
288
    public function protocol(){
289
        return $this->isSSL() ? 'https' : 'http';
290
    }
291
292
    /**
293
     * Gets the protocol and HTTP host.
294
     *
295
     * @return string The protocol and the host
296
     */
297
    public function getProtocolAndHost(){
298
        return $this->protocol() . '://' . $this->host();
299
    }
300
301
    /**
302
     * Get the full URL for the request with the added query string parameters.
303
     *
304
     * @return string
305
     */
306
    public function fullUrl(){
307
308
        // get uri
309
        $uri = $this->uri();
310
        if (strpos($uri, '?') !== false) {
311
            list($uri) = explode('?', $uri, 2);
312
        }
313
314
        // add querystring arguments(neglect 'url' & 'redirect')
315
        $query    = "";
316
        $queryArr = $this->query;
317
        unset($queryArr['url']);
318
        unset($queryArr['redirect']);
319
320
        if(!empty($queryArr)){
321
            $query .= '?' . http_build_query($queryArr, null, '&');
322
        }
323
324
        return  $this->getProtocolAndHost() . $uri . $query;
325
    }
326
327
    /**
328
     * Get the full URL for the request without the protocol.
329
     * 
330
     * It could be useful to force a specific protocol.
331
     *
332
     * @return string
333
     */
334
    public function fullUrlWithoutProtocol(){
335
        return preg_replace('#^https?://#', '', $this->fullUrl());
336
    }
337
338
    /**
339
     * Returns the base URL.
340
     *
341
     * Examples:
342
     *  * http://localhost/                         returns an empty string
343
     *  * http://localhost/miniphp/public/user      returns miniphp
344
     *  * http://localhost/miniphp/posts/view/123   returns miniphp
345
     *
346
     * @return string
347
     */
348
    public function getBaseUrl(){
349
        $baseUrl = str_replace(['public', '\\'], ['', '/'], dirname(Environment::get('SCRIPT_NAME')));
350
        return $baseUrl;
351
    }
352
353
    /**
354
     * Get the root URL for the application.
355
     *
356
     * @return string
357
     */
358
    public function root(){
359
        return $this->getProtocolAndHost() . $this->getBaseUrl();
360
    }
361
}