Passed
Push — master ( a04f2e...1b5a9b )
by Fran
05:36
created

Request::isAjax()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 3
nc 2
nop 0
dl 0
loc 5
rs 9.4285
c 0
b 0
f 0
ccs 3
cts 3
cp 1
crap 2
1
<?php
2
namespace PSFS\base;
3
4
use PSFS\base\types\traits\SingletonTrait;
5
6
/**
7
 * Class Request
8
 * @package PSFS
9
 */
10
class Request
11
{
12
    use SingletonTrait;
13
14
    const VERB_GET = 'GET';
15
    const VERB_POST = 'POST';
16
    const VERB_PUT = 'PUT';
17
    const VERB_DELETE = 'DELETE';
18
    const VERB_OPTIONS = 'OPTIONS';
19
    const VERB_HEAD = 'HEAD';
20
    const VERB_PATCH = 'PATCH';
21
22
    /**
23
     * @var array
24
     */
25
    protected $server;
26
    /**
27
     * @var array
28
     */
29
    protected $cookies;
30
    /**
31
     * @var array
32
     */
33
    protected $upload;
34
    /**
35
     * @var array
36
     */
37
    protected $header;
38
    /**
39
     * @var array
40
     */
41
    protected $data;
42
    /**
43
     * @var array
44
     */
45
    protected $raw = [];
46
    /**
47
     * @var array
48
     */
49
    protected $query;
50
    /**
51
     * @var bool
52
     */
53
    private $isLoaded = false;
54
55 2
    public function init()
0 ignored issues
show
Coding Style introduced by
init 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...
Coding Style introduced by
init uses the super-global variable $_COOKIE 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
init 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
init uses the super-global variable $_REQUEST 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
init 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...
56
    {
57 2
        $this->server = $_SERVER or [];
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as or instead of || is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
58 2
        $this->cookies = $_COOKIE or [];
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as or instead of || is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
59 2
        $this->upload = $_FILES or [];
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as or instead of || is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
60 2
        $this->header = $this->parseHeaders();
61 2
        $this->data = $_REQUEST or [];
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as or instead of || is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
62 2
        $this->query = $_GET or [];
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as or instead of || is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
63 2
        $this->raw = json_decode(file_get_contents('php://input'), true) ?: [];
64 2
        $this->isLoaded = true;
65 2
    }
66
67
    /**
68
     * @return bool
69
     */
70 1
    public function isLoaded() {
71 1
        return $this->isLoaded;
72
    }
73
74
    /**
75
     * Método que devuelve las cabeceras de la petición
76
     * @return array
77
     */
78 2
    private function parseHeaders()
79
    {
80 2
        return getallheaders();
81
    }
82
83
    /**
84
     * Método que verifica si existe una cabecera concreta
85
     * @param $header
86
     *
87
     * @return boolean
88
     */
89 4
    public function hasHeader($header)
90
    {
91 4
        return array_key_exists($header, $this->header);
92
    }
93
94
95
    /**
96
     * Método que indica si una petición tiene cookies
97
     * @return boolean
98
     */
99 1
    public function hasCookies()
100
    {
101 1
        return (null !== $this->cookies && 0 !== count($this->cookies));
102
    }
103
104
    /**
105
     * Método que indica si una petición tiene cookies
106
     * @return boolean
107
     */
108 1
    public function hasUpload()
109
    {
110 1
        return (null !== $this->upload && 0 !== count($this->upload));
111
    }
112
113
    /**
114
     * Método que devuelve el TimeStamp de la petición
115
     *
116
     * @param boolean $formatted
117
     *
118
     * @return string
119
     */
120
    public static function ts($formatted = false)
121
    {
122
        return self::getInstance()->getTs($formatted);
123
    }
124
125 1
    public function getTs($formatted = false)
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
126
    {
127 1
        return ($formatted) ? date('Y-m-d H:i:s', $this->server['REQUEST_TIME_FLOAT']) : $this->server['REQUEST_TIME_FLOAT'];
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 125 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
128
    }
129
130
    /**
131
     * Método que devuelve el Método HTTP utilizado
132
     * @return string
133
     */
134 4
    public function getMethod()
135
    {
136 4
        return array_key_exists('REQUEST_METHOD', $this->server) ? strtoupper($this->server['REQUEST_METHOD']) : 'GET';
137
    }
138
139
    /**
140
     * Método que devuelve una cabecera de la petición si existe
141
     * @param string $name
142
     * @param string $default
0 ignored issues
show
Documentation introduced by
Should the type for parameter $default not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
143
     *
144
     * @return string|null
145
     */
146 3
    public static function header($name, $default = null)
147
    {
148 3
        return self::getInstance()->getHeader($name,  $default);
149
    }
150
151
    /**
152
     * @param string $name
153
     * @param string $default
0 ignored issues
show
Documentation introduced by
Should the type for parameter $default not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
154
     * @return string|null
155
     */
156 3
    public function getHeader($name, $default = null)
157
    {
158 3
        $header = null;
159 3
        if ($this->hasHeader($name)) {
160
            $header = $this->header[$name];
161 3
        } else if(array_key_exists('h_' . strtolower($name), $this->query)) {
162
            $header = $this->query['h_' . strtolower($name)];
163 3
        } else if(array_key_exists('HTTP_' . strtoupper(str_replace('-', '_', $name)), $this->server)) {
164
            $header = $this->server['HTTP_' . strtoupper(str_replace('-', '_', $name))];
165
        }
166 3
        return $header ?: $default;
167
    }
168
169
    /**
170
     * Método que devuelve la url solicitada
171
     * @return string|null
172
     */
173 1
    public static function requestUri()
174
    {
175 1
        return self::getInstance()->getRequestUri();
176
    }
177
178
    /**
179
     * @return string
180
     */
181 7
    public function getRequestUri()
182
    {
183 7
        return array_key_exists('REQUEST_URI', $this->server) ? $this->server['REQUEST_URI'] : '';
184
    }
185
186
    /**
187
     * Método que devuelve el idioma de la petición
188
     * @return string
189
     */
190
    public function getLanguage()
191
    {
192
        return array_key_exists('HTTP_ACCEPT_LANGUAGE', $this->server) ? $this->server['HTTP_ACCEPT_LANGUAGE'] : 'es_ES';
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 121 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
193
    }
194
195
    /**
196
     * Método que determina si se ha solicitado un fichero
197
     * @return boolean
198
     */
199 4
    public function isFile()
200
    {
201 4
        return preg_match('/\.[a-z0-9]{2,4}$/', $this->getRequestUri()) !== 0;
202
    }
203
204
    /**
205
     * Get query params
206
     *
207
     * @param string $queryParams
208
     *
209
     * @return mixed
210
     */
211
    public function getQuery($queryParams)
212
    {
213
        return (array_key_exists($queryParams, $this->query)) ? $this->query[$queryParams] : null;
214
    }
215
216
    /**
217
     * Get all query params
218
     *
219
     * @return mixed
220
     */
221 1
    public function getQueryParams()
222
    {
223 1
        return $this->query;
224
    }
225
226
    /**
227
     * Método que devuelve un parámetro de la solicitud
228
     * @param string $param
229
     *
230
     * @return string|null
231
     */
232
    public function get($param)
233
    {
234
        return array_key_exists($param, $this->data) ? $this->data[$param] : null;
235
    }
236
237
    /**
238
     * Método que devuelve todos los datos del Request
239
     * @return array
240
     */
241 1
    public function getData()
242
    {
243 1
        return array_merge($this->data, $this->raw);
244
    }
245
246
    /**
247
     * @return array
248
     */
249
    public function getRawData() {
250
        return $this->raw;
251
    }
252
253
    /**
254
     * Método que realiza una redirección a la url dada
255
     * @param string $url
256
     */
257
    public function redirect($url = null)
258
    {
259
        if (null === $url) $url = $this->getServer('HTTP_ORIGIN');
260
        ob_start();
261
        header('Location: ' . $url);
262
        ob_end_clean();
263
        Security::getInstance()->updateSession();
264
        exit(_('Redireccionando...'));
265
    }
266
267
    /**
268
     * Devuelve un parámetro de $_SERVER
269
     * @param string $param
270
     * @param $default
271
     * @return string|null
272
     */
273 5
    public function getServer($param, $default = null)
274
    {
275 5
        return array_key_exists($param, $this->server) ? $this->server[$param] : $default;
276
    }
277
278
    /**
279
     * Devuelve el nombre del servidor
280
     * @return string|null
281
     */
282 2
    public function getServerName()
283
    {
284 2
        return $this->getServer('SERVER_NAME');
285
    }
286
287
    /**
288
     * Devuelve el protocolo de la conexión
289
     * @return string
290
     */
291 2
    public function getProtocol()
292
    {
293 2
        return ($this->getServer('HTTPS') || $this->getServer('https')) ? 'https://' : 'http://';
294
    }
295
296
    /**
297
     * Devuelve la url completa de base
298
     * @param boolean $protocol
299
     * @return string
300
     */
301 2
    public function getRootUrl($protocol = true)
302
    {
303 2
        $url = $this->getServerName();
304 2
        $protocol = $protocol ? $this->getProtocol() : '';
305 2
        if (!empty($protocol)) $url = $protocol . $url;
306 2
        if (!in_array($this->getServer('SERVER_PORT'), [80, 443], true)) {
307 2
            $url .= ':' . $this->getServer('SERVER_PORT');
308
        }
309 2
        return $url;
310
    }
311
312
    /**
313
     * Método que devuelve el valor de una cookie en caso de que exista
314
     * @param string $name
315
     *
316
     * @return string
317
     */
318 1
    public function getCookie($name)
319
    {
320 1
        return array_key_exists($name, $this->cookies) ? $this->cookies[$name] : null;
321
    }
322
323
    /**
324
     * Método que devuelve los files subidos por POST
325
     * @param $name
326
     *
327
     * @return array
328
     */
329
    public function getFile($name)
330
    {
331
        return array_key_exists($name, $this->upload) ? $this->upload[$name] : array();
332
    }
333
334
    /**
335
     * Método que devuelve si la petición es ajax o no
336
     * @return boolean
337
     */
338 1
    public function isAjax()
339
    {
340 1
        $requested = $this->getServer('HTTP_X_REQUESTED_WITH');
341 1
        return (null !== $requested && strtolower($requested) === 'xmlhttprequest');
342
    }
343
344
}
345