Passed
Push — master ( 89971b...1a5c63 )
by Vince
01:47
created

header   C

Complexity

Total Complexity 56

Size/Duplication

Total Lines 409
Duplicated Lines 0 %

Importance

Changes 17
Bugs 1 Features 0
Metric Value
eloc 150
c 17
b 1
f 0
dl 0
loc 409
rs 5.5199
wmc 56

19 Methods

Rating   Name   Duplication   Size   Complexity  
A hasBearerToken() 0 3 1
A getMaxWindow() 0 14 5
A requestType() 0 3 1
A setHeader() 0 6 1
A setAllowedMethods() 0 9 2
B setHeaders() 0 72 9
B requestMethod() 0 54 10
A setHeaderStatus() 0 3 1
A getServerMethod() 0 6 2
A getRequestType() 0 3 1
A __construct() 0 2 1
A headerAuth() 0 7 2
A getMethod() 0 3 1
A apacheRequestHeaders() 0 20 6
A getHeaderStatus() 0 3 1
B getHeaders() 0 35 9
A authorizationHeaders() 0 3 1
A setData() 0 3 1
A unauthorised() 0 3 1

How to fix   Complexity   

Complex Class

Complex classes like header 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 header, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * ==================================
4
 * Responsible PHP API
5
 * ==================================
6
 *
7
 * @link Git https://github.com/vince-scarpa/responsibleAPI.git
8
 *
9
 * @api Responible API
10
 * @package responsible\core\headers
11
 *
12
 * @author Vince scarpa <[email protected]>
13
 *
14
 */
15
namespace responsible\core\headers;
16
17
use responsible\core\auth;
18
use responsible\core\exception;
19
use responsible\core\interfaces;
20
use responsible\core\server;
21
22
class header extends server implements interfaces\optionsInterface
23
{
24
    use \responsible\core\traits\optionsTrait;
25
26
    /**
27
     * Max age constant
28
     */
29
    const MAX_WINDOW = 3600;
30
31
    /**
32
     * [$REQUEST_APPLICATION]
33
     * @var array
34
     */
35
    private $REQUEST_APPLICATION = array(
36
        'xml' => 'text/xml',
37
        'json' => 'application/json',
38
        'html' => 'text/html',
39
        'array' => 'text/plain',
40
        'object' => 'text/plain',
41
    );
42
43
    /**
44
     * [$REQUEST_TYPE / Default is json]
45
     * @var string
46
     */
47
    private $REQUEST_TYPE;
48
49
    /**
50
     * [$REQUEST_METHOD]
51
     * @var array
52
     */
53
    private $REQUEST_METHOD = [];
54
55
    /**
56
     * [$headerAuth Header authorise class object]
57
     * @var object
58
     */
59
    protected $headerAuth;
60
61
    /**
62
     * [__construct]
63
     */
64
    public function __construct()
65
    {}
66
67
    /**
68
     * [requestType]
69
     * @return void
70
     */
71
    public function requestType($type = 'json')
72
    {
73
        $this->REQUEST_TYPE = $type;
74
    }
75
76
    /**
77
     * [getRequestType]
78
     * @return string
79
     */
80
    public function getRequestType()
81
    {
82
        return $this->REQUEST_TYPE;
83
    }
84
85
    /**
86
     * [requestMethod Set and return the request method]
87
     * @return object
88
     */
89
    public function requestMethod()
90
    {
91
        switch (strtolower($_SERVER['REQUEST_METHOD'])) {
92
93
            case 'get':
94
                $this->REQUEST_METHOD = ['method' => 'get', 'data' => $_GET];
95
                break;
96
97
            case 'post':
98
                $_POST_DATA = $_POST;
99
                $jsonData = json_decode(file_get_contents("php://input"));
100
101
                if (is_object($jsonData) || is_array($jsonData)) {
102
                    $_POST_DATA = json_decode(file_get_contents("php://input"), true);
103
                }
104
                $_POST = array_merge($_REQUEST, $_POST);
105
                $_REQUEST = array_merge($_POST, $_POST_DATA);
106
107
                $this->REQUEST_METHOD = ['method' => 'post', 'data' => $_REQUEST];
108
                break;
109
110
            case 'options':
111
                $this->REQUEST_METHOD = ['method' => 'options', 'data' => $_POST];
112
                echo json_encode(['success' => true]);
113
                $this->setHeaders();
114
                exit;
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...
115
                break;
116
117
            case 'put':
118
                parse_str(file_get_contents("php://input"), $_PUT);
119
120
                foreach ($_PUT as $key => $value) {
121
                    unset($_PUT[$key]);
122
                    $_PUT[str_replace('amp;', '', $key)] = $value;
123
                }
124
125
                $_REQUEST = array_merge($_REQUEST, $_PUT);
126
127
                $this->REQUEST_METHOD = ['method' => 'put', 'data' => $_REQUEST];
128
                break;
129
130
            case 'patch':
131
                # [TODO]
132
                $this->REQUEST_METHOD = ['method' => 'patch', 'data' => []];
133
                break;
134
135
            case 'delete':
136
                # [TODO]
137
                $this->REQUEST_METHOD = ['method' => 'delete', 'data' => []];
138
                break;
139
140
            default:
141
                $this->REQUEST_METHOD = [];
142
                break;
143
        }
144
    }
145
146
    /**
147
     * [getMethod Get the request method]
148
     * @return object
149
     */
150
    public function getMethod()
151
    {
152
        return (object) $this->REQUEST_METHOD;
153
    }
154
155
    /**
156
     * [setAllowedMethods Set the allowed methods for endpoints]
157
     * @param array $methods [GET, POST, PUT, PATCH, DELETE, ect..]
158
     */
159
    public function setAllowedMethods(array $methods)
160
    {
161
        $this->setHeader('Access-Control-Allow-Methods', array(
162
            implode(',', $methods),
163
        ));
164
165
        $requestMethod = $this->getServerMethod();
166
        if (!in_array($requestMethod, $methods)) {
167
            (new exception\errorException)->error('METHOD_NOT_ALLOWED');
168
        }
169
    }
170
171
    /**
172
     * [getMethod Get the request method]
173
     * @return string
174
     */
175
    public function getServerMethod()
176
    {
177
        if (!isset($_SERVER['REQUEST_METHOD'])) {
178
            return '';
179
        }
180
        return $_SERVER['REQUEST_METHOD'];
181
    }
182
183
    /**
184
     * [getHeaders List all headers Server headers and Apache headers]
185
     * @return array
186
     */
187
    public function getHeaders()
188
    {
189
        $headers_list = headers_list();
190
        foreach ($headers_list as $index => $headValue) {
191
            @list($key, $value) = explode(": ", $headValue);
192
193
            if (!is_null($key) && !is_null($value)) {
194
                $headers_list[$key] = $value;
195
                unset($headers_list[$index]);
196
            }
197
        }
198
199
        if (!function_exists('apache_request_headers')) {
200
            $apacheRequestHeaders = $this->apacheRequestHeaders();
201
        } else {
202
            $apacheRequestHeaders = apache_request_headers();
203
        }
204
205
        if (is_null($apacheRequestHeaders) || empty($apacheRequestHeaders)) {
206
            return [];
207
        }
208
209
        $apache_headers = array_merge($headers_list, $apacheRequestHeaders);
210
211
        $headers = array();
212
213
        foreach ($_SERVER as $key => $value) {
214
            if (substr($key, 0, 5) != 'HTTP_') {
215
                continue;
216
            }
217
            $header = str_replace(' ', '-', ucwords(str_replace('_', ' ', strtolower(substr($key, 5)))));
218
            $headers[$header] = $value;
219
        }
220
221
        return array_merge($headers, $apache_headers);
222
    }
223
224
    /**
225
     * [setHeader Append aditional headers]
226
     * @return void
227
     */
228
    public function setHeader($header, $headerValue = array(), $status = '', $delimiter = ';')
229
    {
230
        $header = trim(str_replace(':', '', $header)) . ': ';
231
        $headerValue = implode($delimiter . ' ', $headerValue);
232
233
        header($header . $status . $headerValue);
234
    }
235
236
    /**
237
     * [setHeaders Default headers]
238
     * @return void
239
     */
240
    public function setHeaders()
241
    {
242
        $application = 'json';
243
        if (isset($this->REQUEST_APPLICATION[$this->getRequestType()])) {
244
            $application = $this->REQUEST_APPLICATION[$this->getRequestType()];
245
        }
246
247
        $this->setHeader('Content-Type', array(
248
            $application, 'charset=UTF-8',
249
        ));
250
251
        $this->setHeader('Accept-Ranges', array(
252
            'bytes',
253
        ));
254
255
        $this->setHeader('Access-Control-Allow-Credentials', array(
256
            true,
257
        ));
258
259
        $this->setHeader('Access-Control-Allow-Origin', array(
260
            '*',
261
        ));
262
263
        if (!array_key_exists('Access-Control-Allow-Methods', $this->getHeaders())) {
264
            $this->setHeader('Access-Control-Allow-Methods', array(
265
                'GET,POST,OPTIONS',
266
            ));
267
        }
268
269
        $this->setHeader('Access-Control-Expose-Headers', array(
270
            'Content-Range',
271
        ));
272
273
        $this->setHeader('Access-Control-Allow-Headers', array(
274
            'origin,x-requested-with,Authorization,cache-control',
275
        ));
276
277
        $this->setHeader('Access-Control-Max-Age', array(
278
            $this->getMaxWindow(),
279
        ));
280
281
        $this->setHeader('Expires', array(
282
            'Wed, 20 September 1978 00:00:00 GMT',
283
        ));
284
285
        $this->setHeader('Cache-Control', array(
286
            'no-store, no-cache, must-revalidate',
287
        ));
288
289
        $this->setHeader('Cache-Control', array(
290
            'post-check=0, pre-check=0',
291
        ));
292
293
        $this->setHeader('Pragma', array(
294
            'no-cache',
295
        ));
296
297
        $this->setHeader('X-Content-Type-Options', array(
298
            'nosniff',
299
        ));
300
301
        $this->setHeader('X-XSS-Protection', array(
302
            '1', 'mode=block',
303
        ));
304
305
        if (isset($this->getOptions()['addHeaders']) &&
306
            (is_array($this->getOptions()['addHeaders']) && !empty($this->getOptions()['addHeaders']))
307
        ) {
308
            foreach ($this->getOptions()['addHeaders'] as $i => $customHeader) {
309
                if (is_array($customHeader) && sizeof($customHeader) == 2) {
310
                    $this->setHeader($customHeader[0], array(
311
                        $customHeader[1],
312
                    ));
313
                }
314
            }
315
        }
316
    }
317
318
    /**
319
     * [apacheRequestHeaders Native replacment fuction]
320
     * https://www.php.net/manual/en/function.apache-request-headers.php#70810
321
     * @return array
322
     */
323
    public function apacheRequestHeaders()
324
    {
325
        $arh = array();
326
        $rx_http = '/\AHTTP_/';
327
328
        foreach ($_SERVER as $key => $val) {
329
            if (preg_match($rx_http, $key)) {
330
                $arh_key = preg_replace($rx_http, '', $key);
331
                $rx_matches = explode('_', $arh_key);
332
                if (count($rx_matches) > 0 and strlen($arh_key) > 2) {
333
                    foreach ($rx_matches as $ak_key => $ak_val) {
334
                        $rx_matches[$ak_key] = ucfirst($ak_val);
335
                    }
336
337
                    $arh_key = implode('-', $rx_matches);
338
                }
339
                $arh[$arh_key] = $val;
340
            }
341
        }
342
        return ($arh);
343
    }
344
345
    /**
346
     * [headerAuth]
347
     * @return object
348
     */
349
    public function headerAuth()
350
    {
351
        if (is_null($this->headerAuth)) {
352
            $this->headerAuth = new headerAuth;
353
        }
354
        $this->headerAuth->setOptions($this->getOptions());
355
        return $this->headerAuth;
356
    }
357
358
    /**
359
     * [authorizationHeaders Scan for "Authorization" header]
360
     * @return string|array [mixed: string / error]
361
     */
362
    public function authorizationHeaders($skipError = false)
363
    {
364
        return $this->headerAuth()->authorizationHeaders($skipError);
365
    }
366
367
    /**
368
     * [hasBearerToken Check if bearer token is present]
369
     * @return string|null
370
     */
371
    public function hasBearerToken()
372
    {
373
        return $this->headerAuth()->hasBearerToken();
374
    }
375
376
    /**
377
     * [unauthorised Set an unauthorised header]
378
     * @return array [exit exception message]
379
     */
380
    public function unauthorised()
381
    {
382
        $this->headerAuth()->setUnauthorised();
383
    }
384
385
    /**
386
     * [getMaxWindow Get the max control age window]
387
     * @return integer
388
     */
389
    private function getMaxWindow()
390
    {
391
        if ($this->getOptions()) {
392
            if (isset($this->getOptions()['maxWindow']) && !empty($this->getOptions()['maxWindow'])) {
393
                if (!is_numeric($this->getOptions()['maxWindow'])) {
394
                    (new exception\errorException)
395
                        ->message('maxWindow option must be an integer type')
396
                        ->error('APPLICATION_ERROR');
397
                }
398
399
                return $this->getOptions()['maxWindow'];
400
            }
401
        }
402
        return self::MAX_WINDOW;
403
    }
404
405
    /**
406
     * [setHeaderStatus]
407
     * @param void
408
     */
409
    public function setHeaderStatus($status)
410
    {
411
        http_response_code($status);
412
    }
413
414
    /**
415
     * [getHeaderStatus]
416
     * @return integer
417
     */
418
    public function getHeaderStatus()
419
    {
420
        return http_response_code();
421
    }
422
423
    /**
424
     * [setData Set request method data]
425
     * @param array $data
426
     * @return void
427
     */
428
    public function setData($data = [])
429
    {
430
        $this->REQUEST_METHOD['data'] = $data;
431
    }
432
}
433