Passed
Push — master ( 510786...275623 )
by Fran
04:26
created

Request   C

Complexity

Total Complexity 56

Size/Duplication

Total Lines 292
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Test Coverage

Coverage 51.16%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
dl 0
loc 292
ccs 44
cts 86
cp 0.5116
rs 6.5957
c 1
b 0
f 0
wmc 56
lcom 1
cbo 2

27 Methods

Rating   Name   Duplication   Size   Complexity  
A hasHeader() 0 4 1
A get() 0 4 2
C init() 0 17 10
A isLoaded() 0 3 1
A parseHeaders() 0 4 1
A hasCookies() 0 4 2
A hasUpload() 0 4 2
A ts() 0 4 1
A getTs() 0 4 2
A getMethod() 0 4 2
A header() 0 4 1
A getHeader() 0 8 2
A requestUri() 0 4 1
A getRequestUri() 0 4 2
A getLanguage() 0 4 2
A isFile() 0 5 1
A getQuery() 0 4 2
A getQueryParams() 0 4 1
A getData() 0 4 1
A redirect() 0 9 2
A getServer() 0 4 2
A getServerName() 0 4 1
A getProtocol() 0 4 3
B getRootUrl() 0 11 5
A getCookie() 0 4 2
A getFile() 0 4 2
A isAjax() 0 5 2

How to fix   Complexity   

Complex Class

Complex classes like Request often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Request, and based on these observations, apply Extract Interface, too.

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
    protected $server;
14
    protected $cookies;
15
    protected $upload;
16
    protected $header;
17
    protected $data;
18
    protected $query;
19
    private $isLoaded = false;
20
21 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...
22
    {
23 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...
24 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...
25 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...
26 2
        $this->header = $this->parseHeaders();
27 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...
28 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...
29 2
        $contentType = $this->getHeader('Content-Type');
30 2
        if(null === $contentType) {
31 2
            $contentType = $this->getServer('CONTENT_TYPE') ?: 'text/html';
32 2
        }
33 2
        if (preg_match('/application\/json/i', $contentType)) {
34
            $this->data += json_decode(file_get_contents("php://input"), true) ?: array();
35
        }
36 2
        $this->isLoaded = true;
37 2
    }
38
39
    /**
40
     * @return bool
41
     */
42 1
    public function isLoaded() {
43 1
        return $this->isLoaded;
44
    }
45
46
    /**
47
     * Método que devuelve las cabeceras de la petición
48
     * @return array
49
     */
50 2
    private function parseHeaders()
51
    {
52 2
        return getallheaders();
53
    }
54
55
    /**
56
     * Método que verifica si existe una cabecera concreta
57
     * @param $header
58
     *
59
     * @return boolean
60
     */
61 3
    public function hasHeader($header)
62
    {
63 3
        return array_key_exists($header, $this->header);
64
    }
65
66
67
    /**
68
     * Método que indica si una petición tiene cookies
69
     * @return boolean
70
     */
71 1
    public function hasCookies()
72
    {
73 1
        return (null !== $this->cookies && 0 !== count($this->cookies));
74
    }
75
76
    /**
77
     * Método que indica si una petición tiene cookies
78
     * @return boolean
79
     */
80 1
    public function hasUpload()
81
    {
82 1
        return (null !== $this->upload && 0 !== count($this->upload));
83
    }
84
85
    /**
86
     * Método que devuelve el TimeStamp de la petición
87
     *
88
     * @param boolean $formatted
89
     *
90
     * @return string
91
     */
92
    public static function ts($formatted = false)
93
    {
94
        return self::getInstance()->getTs($formatted);
95
    }
96
97 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...
98
    {
99 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...
100
    }
101
102
    /**
103
     * Método que devuelve el Método HTTP utilizado
104
     * @return string
105
     */
106 3
    public function getMethod()
107
    {
108 3
        return (array_key_exists('REQUEST_METHOD', $this->server)) ? strtoupper($this->server['REQUEST_METHOD']) : 'GET';
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...
109
    }
110
111
    /**
112
     * Método que devuelve una cabecera de la petición si existe
113
     * @param $name
114
     *
115
     * @return string|null
116
     */
117
    public static function header($name)
118
    {
119
        return self::getInstance()->getHeader($name);
120
    }
121
122 2
    public function getHeader($name)
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...
123
    {
124 2
        $header = null;
125 2
        if ($this->hasHeader($name)) {
126
            $header = $this->header[$name];
127
        }
128 2
        return $header;
129
    }
130
131
    /**
132
     * Método que devuelve la url solicitada
133
     * @return string|null
134
     */
135
    public static function requestUri()
136
    {
137
        return self::getInstance()->getRequestUri();
138
    }
139
140
    /**
141
     * @return string
142
     */
143 6
    public function getRequestUri()
144
    {
145 6
        return array_key_exists('REQUEST_URI', $this->server) ? $this->server['REQUEST_URI'] : '';
146
    }
147
148
    /**
149
     * Método que devuelve el idioma de la petición
150
     * @return string
151
     */
152
    public function getLanguage()
153
    {
154
        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...
155
    }
156
157
    /**
158
     * Método que determina si se ha solicitado un fichero
159
     * @return boolean
160
     */
161 4
    public function isFile()
162
    {
163 4
        $file = (preg_match('/\.[a-z0-9]{2,4}$/', $this->getRequestUri()) !== 0);
164 4
        return $file;
165
    }
166
167
    /**
168
     * Get query params
169
     *
170
     * @param string $queryParams
171
     *
172
     * @return mixed
173
     */
174
    public function getQuery($queryParams)
175
    {
176
        return (array_key_exists($queryParams, $this->query)) ? $this->query[$queryParams] : null;
177
    }
178
179
    /**
180
     * Get all query params
181
     *
182
     * @return mixed
183
     */
184
    public function getQueryParams()
185
    {
186
        return $this->query;
187
    }
188
189
    /**
190
     * Método que devuelve un parámetro de la solicitud
191
     * @param string $param
192
     *
193
     * @return string|null
194
     */
195
    public function get($param)
196
    {
197
        return (array_key_exists($param, $this->data)) ? $this->data[$param] : null;
198
    }
199
200
    /**
201
     * Método que devuelve todos los datos del Request
202
     * @return array
203
     */
204
    public function getData()
205
    {
206
        return $this->data;
207
    }
208
209
    /**
210
     * Método que realiza una redirección a la url dada
211
     * @param string $url
212
     */
213
    public function redirect($url = null)
214
    {
215
        if (null === $url) $url = $this->getServer('HTTP_ORIGIN');
216
        ob_start();
217
        header('Location: ' . $url);
218
        ob_end_clean();
219
        Security::getInstance()->updateSession();
220
        exit(_("Redireccionando..."));
221
    }
222
223
    /**
224
     * Devuelve un parámetro de $_SERVER
225
     * @param string $param
226
     *
227
     * @return string|null
228
     */
229 3
    public function getServer($param)
230
    {
231 3
        return array_key_exists($param, $this->server) ? $this->server[$param] : null;
232
    }
233
234
    /**
235
     * Devuelve el nombre del servidor
236
     * @return string|null
237
     */
238
    public function getServerName()
239
    {
240
        return $this->getServer("SERVER_NAME");
241
    }
242
243
    /**
244
     * Devuelve el protocolo de la conexión
245
     * @return string
246
     */
247
    public function getProtocol()
248
    {
249
        return ($this->getServer("HTTPS") || $this->getServer("https")) ? 'https://' : 'http://';
250
    }
251
252
    /**
253
     * Devuelve la url completa de base
254
     * @param boolean $protocol
255
     * @return string
256
     */
257
    public function getRootUrl($protocol = true)
258
    {
259
        $host = $this->getServerName();
260
        $protocol = $protocol ? $this->getProtocol() : '';
261
        $url = '';
262
        if (!empty($host) && !empty($protocol)) $url = $protocol . $host;
263
        if (!in_array($this->getServer('SERVER_PORT'), [80, 443])) {
264
            $url .= ':' . $this->getServer('SERVER_PORT');
265
        }
266
        return $url;
267
    }
268
269
    /**
270
     * Método que devuelve el valor de una cookie en caso de que exista
271
     * @param string $name
272
     *
273
     * @return string
274
     */
275 1
    public function getCookie($name)
276
    {
277 1
        return array_key_exists($name, $this->cookies) ? $this->cookies[$name] : null;
278
    }
279
280
    /**
281
     * Método que devuelve los files subidos por POST
282
     * @param $name
283
     *
284
     * @return array
285
     */
286
    public function getFile($name)
287
    {
288
        return array_key_exists($name, $this->upload) ? $this->upload[$name] : array();
289
    }
290
291
    /**
292
     * Método que devuelve si la petición es ajax o no
293
     * @return boolean
294
     */
295 1
    public function isAjax()
296
    {
297 1
        $requested = $this->getServer("HTTP_X_REQUESTED_WITH");
298 1
        return (null !== $requested && strtolower($requested) == 'xmlhttprequest');
299
    }
300
301
}
302