Passed
Push — develop ( 254dd6...fd5b3b )
by Mathieu
01:47
created

Request   B

Complexity

Total Complexity 51

Size/Duplication

Total Lines 392
Duplicated Lines 0 %

Test Coverage

Coverage 71.67%

Importance

Changes 0
Metric Value
eloc 172
dl 0
loc 392
ccs 86
cts 120
cp 0.7167
rs 7.92
c 0
b 0
f 0
wmc 51

34 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A parse() 0 14 4
A setContentType() 0 10 2
A isOK() 0 3 1
A addHeader() 0 5 1
A setMethod() 0 11 2
A setRequestUri() 0 5 1
A hasParam() 0 4 2
A redirectWithError() 0 3 1
A isClientError() 0 3 2
A setBody() 0 5 1
A getMethod() 0 3 1
A write() 0 25 5
A getBody() 0 3 1
A getHeaders() 0 3 1
A getHttpCode() 0 3 1
A redirectWithInfo() 0 3 1
A isServerError() 0 3 2
A getPath() 0 3 1
A getStringForHttpCode() 0 6 2
A redirect() 0 7 1
A setHttpCode() 0 5 1
A isRedirect() 0 3 2
A getUrl() 0 3 1
A setHeaders() 0 5 1
A flashData() 0 5 1
A getPostParam() 0 6 2
A getRequestUri() 0 3 1
A getParam() 0 10 3
A getQuery() 0 3 1
A flash() 0 5 1
A redirectWithSuccess() 0 3 1
A redirectWithData() 0 3 1
A setUrl() 0 5 1

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.

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 declare(strict_types=1);
2
namespace Suricate;
3
4
/**
5
 * @SuppressWarnings("StaticAccess")
6
 */
7
class Request
8
{
9
    const HTTP_METHOD_GET = 'GET';
10
    const HTTP_METHOD_POST = 'POST';
11
    const HTTP_METHOD_PUT = 'PUT';
12
    const HTTP_METHOD_DELETE = 'DELETE';
13
    const HTTP_METHOD_HEAD = 'HEAD';
14
    const HTTP_METHOD_OPTIONS = 'OPTIONS';
15
16
    private $method = self::HTTP_METHOD_GET;
17
    private $methods = [
18
        self::HTTP_METHOD_GET => 'GET',
19
        self::HTTP_METHOD_POST => 'POST',
20
        self::HTTP_METHOD_PUT => 'PUT',
21
        self::HTTP_METHOD_DELETE => 'DELETE',
22
        self::HTTP_METHOD_HEAD => 'HEAD',
23
        self::HTTP_METHOD_OPTIONS => 'OPTIONS'
24
    ];
25
26
    private $httpCodeString = [
27
        100 => 'Continue',
28
        101 => 'Switching Protocols',
29
        102 => 'Processing',
30
        200 => 'OK',
31
        201 => 'Created',
32
        202 => 'Accepted',
33
        203 => 'Non-Authoritative Information',
34
        204 => 'No Content',
35
        205 => 'Reset Content',
36
        206 => 'Partial Content',
37
        207 => 'Multi-Status',
38
        208 => 'Already Reported',
39
        226 => 'IM Used',
40
        250 => 'Low on Storage Space',
41
        300 => 'Multiple Choices',
42
        301 => 'Moved Permanently',
43
        302 => 'Found',
44
        303 => 'See Other',
45
        304 => 'Not Modified',
46
        305 => 'Use Proxy',
47
        306 => '306 Switch Proxy',
48
        307 => 'Temporary Redirect',
49
        308 => 'Permanent Redirect',
50
        400 => 'Bad Request',
51
        401 => 'Unauthorized',
52
        402 => 'Payment Required',
53
        403 => 'Forbidden',
54
        404 => 'Not Found',
55
        405 => 'Method Not Allowed',
56
        406 => 'Not Acceptable',
57
        407 => 'Proxy Authentication Required',
58
        408 => 'Request Timeout',
59
        409 => 'Conflict',
60
        410 => 'Gone',
61
        411 => 'Length Required',
62
        412 => 'Precondition Failed',
63
        413 => 'Request Entity Too Large',
64
        414 => 'Request-URI Too Long',
65
        415 => 'Unsupported Media Type',
66
        416 => 'Requested Range Not Satisfiable',
67
        417 => 'Expectation Failed',
68
        422 => 'Unprocessable Entity',
69
        423 => 'Locked',
70
        424 => 'Failed Dependency',
71
        425 => 'Unordered Collection',
72
        426 => 'Upgrade Required',
73
        428 => 'Precondition Required',
74
        429 => 'Too Many Requests',
75
        431 => 'Request Header Fields Too Large',
76
        444 => 'No Response',
77
        449 => 'Retry With',
78
        450 => 'Blocked by Windows Parental Controls',
79
        494 => 'Request Header Too Large',
80
        495 => 'Cert Error',
81
        496 => 'No Cert',
82
        497 => 'HTTP to HTTPS',
83
        499 => 'Client Closed Request',
84
        500 => 'Internal Server Error',
85
        501 => 'Not Implemented',
86
        502 => 'Bad Gateway',
87
        503 => 'Service Unavailable',
88
        504 => 'Gateway Timeout',
89
        505 => 'HTTP Version Not Supported',
90
        506 => 'Variant Also Negotiates',
91
        507 => 'Insufficient Storage',
92
        508 => 'Loop Detected',
93
        509 => 'Bandwidth Limit Exceeded',
94
        510 => 'Not Extended',
95
        511 => 'Network Authentication Required'
96
    ];
97
98
    private $httpCode;
99
    private $headers = [];
100
    private $requestUri = '';
101
    private $url;
102
    private $body;
103
    private $path;
104
    private $query;
105
106 18
    public function __construct()
107
    {
108 18
        $this->headers = [];
109 18
        $this->httpCode = 200;
110 18
    }
111
112 9
    public function parse()
113
    {
114 9
        if (isset($_SERVER['REQUEST_URI'])) {
115 5
            $this->setRequestUri($_SERVER['REQUEST_URI']);
116 5
            $parseResult = parse_url($_SERVER['REQUEST_URI']);
117 5
            $this->path = dataGet($parseResult, 'path');
118 5
            $this->query = dataGet($parseResult, 'query');
119
        }
120
121 9
        if (isset($_SERVER['REQUEST_METHOD'])) {
122 1
            $this->setMethod($_SERVER['REQUEST_METHOD']);
123
        }
124 9
        if (isset($_POST['_method'])) {
125 5
            $this->setMethod($_POST['_method']);
126
        }
127 9
    }
128
129 7
    public function setMethod($method)
130
    {
131 7
        if (!isset($this->methods[$method])) {
132 1
            throw new \InvalidArgumentException(
133 1
                'Invalid HTTP Method ' . $method
134
            );
135
        }
136
137 7
        $this->method = $method;
138
139 7
        return $this;
140
    }
141
142 3
    public function getMethod()
143
    {
144 3
        return $this->method;
145
    }
146
147 2
    public function setUrl($url)
148
    {
149 2
        $this->url = $url;
150
151 2
        return $this;
152
    }
153 2
    public function getUrl()
154
    {
155 2
        return $this->url;
156
    }
157
158 10
    public function setRequestUri($uri)
159
    {
160 10
        $this->requestUri = $uri;
161
162 10
        return $this;
163
    }
164
165 11
    public function getRequestUri()
166
    {
167 11
        return $this->requestUri;
168
    }
169
170 1
    public function getPath()
171
    {
172 1
        return $this->path;
173
    }
174
175 1
    public function getQuery()
176
    {
177 1
        return $this->query;
178
    }
179
180 1
    public static function getPostParam($variable, $defaultValue = null)
181
    {
182 1
        if (array_key_exists($variable, $_POST)) {
183 1
            return $_POST[$variable];
184
        }
185 1
        return $defaultValue;
186
    }
187
188 1
    public static function getParam($variable, $defaultValue = null)
189
    {
190 1
        if (array_key_exists($variable, $_GET)) {
191 1
            return $_GET[$variable];
192
        }
193 1
        if (array_key_exists($variable, $_POST)) {
194 1
            return $_POST[$variable];
195
        }
196
197 1
        return $defaultValue;
198
    }
199
200 1
    public static function hasParam($variable)
201
    {
202 1
        return array_key_exists($variable, $_GET) ||
203 1
            array_key_exists($variable, $_POST);
204
    }
205
206
    /**
207
     * Set request headers
208
     *
209
     * @param array $headers Headers to set key => $value
210
     * @return Request
211
     */
212 1
    public function setHeaders(array $headers): Request
213
    {
214 1
        $this->headers = $headers;
215
216 1
        return $this;
217
    }
218
219
    /**
220
     * Add specific header
221
     *
222
     * @param string $header header name
223
     * @param string $value  header value
224
     * @return Request
225
     */
226 1
    public function addHeader($header, $value): Request
227
    {
228 1
        $this->headers[$header] = $value;
229
230 1
        return $this;
231
    }
232
233
    /**
234
     * Get request headers
235
     *
236
     * @return array
237
     */
238 1
    public function getHeaders(): array
239
    {
240 1
        return $this->headers;
241
    }
242
243 1
    public function setContentType(
244
        string $contentType,
245
        $encoding = null
246
    ): Request {
247 1
        if ($encoding !== null) {
248 1
            $contentType .= '; charset=' . $encoding;
249
        }
250 1
        $this->addHeader('Content-type', $contentType);
251
252 1
        return $this;
253
    }
254
255 1
    public function setBody(string $body): Request
256
    {
257 1
        $this->body = $body;
258
259 1
        return $this;
260
    }
261
262 1
    public function getBody(): string
263
    {
264 1
        return $this->body;
265
    }
266
267
    public function write()
268
    {
269
        if (!headers_sent()) {
270
            if (substr(php_sapi_name(), 0, 3) == 'cgi') {
271
                $headerString = 'Status: ' . $this->getStringForHttpCode();
272
            } else {
273
                $headerString = 'HTTP/1.1 ' . $this->getStringForHttpCode();
274
            }
275
276
            header($headerString);
277
278
            // Send headers
279
            foreach ($this->headers as $headerName => $headerValue) {
280
                header($headerName . ':' . $headerValue);
281
            }
282
        }
283
284
        /**
285
         TODO HANDLE HTTP RESPONSE CODE
286
         */
287
        if ($this->httpCode !== null) {
288
        }
289
290
        // Send body
291
        echo $this->body;
292
    }
293
294
    //
295
    // HTTP Code
296
    //
297
298 1
    public function setHttpCode($code): Request
299
    {
300 1
        $this->httpCode = $code;
301
302 1
        return $this;
303
    }
304
305 1
    public function getHttpCode()
306
    {
307 1
        return $this->httpCode;
308
    }
309
310
    public function flash(string $type, string $data)
311
    {
312
        Flash::writeMessage($type, $data);
313
314
        return $this;
315
    }
316
317
    public function flashData($name, $value)
318
    {
319
        Flash::writeData($name, $value);
320
321
        return $this;
322
    }
323
324
    public function redirect($url, $httpCode = 302)
325
    {
326
        $this->setHttpCode($httpCode);
327
        $this->addHeader('Location', $url);
328
329
        $this->write();
330
        die();
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
331
    }
332
333
    public function redirectWithSuccess($url, $message)
334
    {
335
        $this->flash('success', $message)->redirect($url);
336
    }
337
338
    public function redirectWithInfo($url, $message)
339
    {
340
        $this->flash('info', $message)->redirect($url);
341
    }
342
343
    public function redirectWithError($url, $message)
344
    {
345
        $this->flash('error', $message)->redirect($url);
346
    }
347
348
    public function redirectWithData($url, $key, $value)
349
    {
350
        $this->flashData($key, $value)->redirect($url);
351
    }
352
353
    /**
354
     * Check if request has a 200 OK Code
355
     *
356
     * @return boolean
357
     */
358 1
    public function isOK(): bool
359
    {
360 1
        return $this->httpCode == 200;
361
    }
362
363
    /**
364
     * Check if request has a 3XX HTTP code
365
     *
366
     * @return boolean
367
     */
368 1
    public function isRedirect(): bool
369
    {
370 1
        return $this->httpCode >= 300 && $this->httpCode < 400;
371
    }
372
373
    /**
374
     * Check is request has a 4XX HTTP code
375
     *
376
     * @return boolean
377
     */
378 1
    public function isClientError(): bool
379
    {
380 1
        return $this->httpCode >= 400 && $this->httpCode < 500;
381
    }
382
383
    /**
384
     * Check if request has a 5XX HTTP code
385
     *
386
     * @return boolean
387
     */
388 1
    public function isServerError(): bool
389
    {
390 1
        return $this->httpCode >= 500 && $this->httpCode < 600;
391
    }
392
393 1
    private function getStringForHttpCode()
394
    {
395 1
        if (isset($this->httpCodeString[$this->httpCode])) {
396 1
            return $this->httpCode .
397 1
                ' ' .
398 1
                $this->httpCodeString[$this->httpCode];
399
        }
400 1
    }
401
}
402