Passed
Push — master ( 635200...ad05d4 )
by Vince
03:32 queued 01:55
created

header::headerAuth()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 4
c 1
b 0
f 0
nc 2
nop 0
dl 0
loc 7
rs 10
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 = 'json';
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
        $verbs = new headerVerbs;
92
93
        switch (strtolower($_SERVER['REQUEST_METHOD'])) {
94
95
            case 'get':
96
                return $this->REQUEST_METHOD = $verbs->get();
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->REQUEST_METHOD = $verbs->get() returns the type array<string,array|mixed|string> which is incompatible with the documented return type object.
Loading history...
97
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
98
99
            case 'post':
100
                return $this->REQUEST_METHOD = $verbs->post();
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->REQUEST_METHOD = $verbs->post() returns the type array<string,array|string> which is incompatible with the documented return type object.
Loading history...
101
                break;
102
103
            case 'options':
104
                $this->REQUEST_METHOD = $verbs->post();
105
                echo json_encode(['success' => true]);
106
                $this->setHeaders();
107
                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...
108
                break;
109
110
            case 'put':
111
                $this->REQUEST_METHOD = $verbs->put();
112
                break;
113
114
            case 'patch':
115
                $this->REQUEST_METHOD = $verbs->patch();
116
                break;
117
118
            case 'delete':
119
                $this->REQUEST_METHOD = $verbs->delete();
120
                break;
121
122
            default:
123
                $this->REQUEST_METHOD = [];
124
                break;
125
        }
126
    }
127
128
    /**
129
     * [getMethod Get the request method]
130
     * @return object
131
     */
132
    public function getMethod()
133
    {
134
        return (object) $this->REQUEST_METHOD;
135
    }
136
137
    /**
138
     * [getBody Get the post body]
139
     * @return array
140
     */
141
    public function getBody():array
142
    {
143
        if (isset($this->getMethod()->data) && !empty($this->getMethod()->data)) {
144
            return $this->getMethod()->data;
145
        }
146
        return [];
147
    }
148
149
    /**
150
     * [setAllowedMethods Set the allowed methods for endpoints]
151
     * @param array $methods [GET, POST, PUT, PATCH, DELETE, ect..]
152
     */
153
    public function setAllowedMethods(array $methods)
154
    {
155
        $this->setHeader('Access-Control-Allow-Methods', array(
156
            implode(',', $methods),
157
        ));
158
159
        $requestMethod = $this->getServerMethod();
160
        if (!in_array($requestMethod, $methods)) {
161
            (new exception\errorException)
162
                ->setOptions($this->getOptions())
163
                ->error('METHOD_NOT_ALLOWED');
164
        }
165
    }
166
167
    /**
168
     * [getMethod Get the request method]
169
     * @return string
170
     */
171
    public function getServerMethod()
172
    {
173
        if (!isset($_SERVER['REQUEST_METHOD'])) {
174
            return '';
175
        }
176
        return $_SERVER['REQUEST_METHOD'];
177
    }
178
179
    /**
180
     * [getHeaders List all headers Server headers and Apache headers]
181
     * @return array
182
     */
183
    public function getHeaders()
184
    {
185
        $headers_list = $this->headersList();
186
        foreach ($headers_list as $index => $headValue) {
187
            @list($key, $value) = explode(": ", $headValue);
188
189
            if (!is_null($key) && !is_null($value)) {
190
                $headers_list[$key] = $value;
191
                unset($headers_list[$index]);
192
            }
193
        }
194
195
        if (!function_exists('apache_request_headers')) {
196
            $apacheRequestHeaders = $this->apacheRequestHeaders();
197
        } else {
198
            $apacheRequestHeaders = apache_request_headers();
199
        }
200
201
        if (is_null($apacheRequestHeaders) || empty($apacheRequestHeaders)) {
202
            return [];
203
        }
204
205
        $apache_headers = array_merge($headers_list, $apacheRequestHeaders);
206
207
        $headers = array();
208
209
        foreach ($_SERVER as $key => $value) {
210
            if (substr($key, 0, 5) != 'HTTP_') {
211
                continue;
212
            }
213
            $header = str_replace(' ', '-', ucwords(str_replace('_', ' ', strtolower(substr($key, 5)))));
214
            $headers[$header] = $value;
215
        }
216
217
        return array_merge($headers, $apache_headers);
218
    }
219
220
    /**
221
     * [headersList Get the default header list]
222
     * @return array
223
     */
224
    private function headersList()
225
    {
226
        $server = new server([], $this->getOptions());
227
        if ($isMockTest = $server->isMockTest()) {
0 ignored issues
show
Unused Code introduced by
The assignment to $isMockTest is dead and can be removed.
Loading history...
228
            return $this->apacheRequestHeaders();
229
        }
230
        
231
        return headers_list();
232
    }
233
234
    /**
235
     * [apacheRequestHeaders Native replacment fuction]
236
     * https://www.php.net/manual/en/function.apache-request-headers.php#70810
237
     * @return array
238
     */
239
    public function apacheRequestHeaders()
240
    {
241
        $arh = array();
242
        $rx_http = '/\AHTTP_/';
243
244
        foreach ($_SERVER as $key => $val) {
245
            if (preg_match($rx_http, $key)) {
246
                $arh_key = preg_replace($rx_http, '', $key);
247
                $rx_matches = explode('_', $arh_key);
248
                if (count($rx_matches) > 0 and strlen($arh_key) > 2) {
249
                    foreach ($rx_matches as $ak_key => $ak_val) {
250
                        $rx_matches[$ak_key] = ucfirst($ak_val);
251
                    }
252
253
                    $arh_key = implode('-', $rx_matches);
254
                }
255
                $arh[$arh_key] = $val;
256
            }
257
        }
258
        return ($arh);
259
    }
260
261
    /**
262
     * [setHeader Append aditional headers]
263
     * @return void
264
     */
265
    public function setHeader($header, $headerValue = array(), $status = '', $delimiter = ';')
266
    {
267
        $header = trim(str_replace(':', '', $header)) . ': ';
268
        $headerValue = implode($delimiter . ' ', $headerValue);
269
270
        header($header . $status . $headerValue);
271
    }
272
273
    /**
274
     * [setHeaders Default headers]
275
     * @return void
276
     */
277
    public function setHeaders()
278
    {
279
        $application = 'json';
280
        if (isset($this->REQUEST_APPLICATION[$this->getRequestType()])) {
281
            $application = $this->REQUEST_APPLICATION[$this->getRequestType()];
282
        }
283
284
        $this->setHeader('Content-Type', array(
285
            $application, 'charset=UTF-8',
286
        ));
287
288
        $this->setHeader('Accept-Ranges', array(
289
            'bytes',
290
        ));
291
292
        $this->setHeader('Access-Control-Allow-Credentials', array(
293
            true,
294
        ));
295
296
        $this->setHeader('Access-Control-Allow-Origin', array(
297
            '*',
298
        ));
299
300
        if (!array_key_exists('Access-Control-Allow-Methods', $this->getHeaders())) {
301
            $this->setHeader('Access-Control-Allow-Methods', array(
302
                'GET,POST,OPTIONS',
303
            ));
304
        }
305
306
        $this->setHeader('Access-Control-Expose-Headers', array(
307
            'Content-Range',
308
        ));
309
310
        $this->setHeader('Access-Control-Allow-Headers', array(
311
            'origin,x-requested-with,Authorization,cache-control',
312
        ));
313
314
        $this->setHeader('Access-Control-Max-Age', array(
315
            $this->getMaxWindow(),
316
        ));
317
318
        $this->setHeader('Expires', array(
319
            'Wed, 20 September 1978 00:00:00 GMT',
320
        ));
321
322
        $this->setHeader('Cache-Control', array(
323
            'no-store, no-cache, must-revalidate',
324
        ));
325
326
        $this->setHeader('Cache-Control', array(
327
            'post-check=0, pre-check=0',
328
        ));
329
330
        $this->setHeader('Pragma', array(
331
            'no-cache',
332
        ));
333
334
        $this->setHeader('X-Content-Type-Options', array(
335
            'nosniff',
336
        ));
337
338
        $this->setHeader('X-XSS-Protection', array(
339
            '1', 'mode=block',
340
        ));
341
342
        if (isset($this->getOptions()['addHeaders']) &&
343
            (is_array($this->getOptions()['addHeaders']) && !empty($this->getOptions()['addHeaders']))
344
        ) {
345
            foreach ($this->getOptions()['addHeaders'] as $i => $customHeader) {
346
                if (is_array($customHeader) && sizeof($customHeader) == 2) {
347
                    $this->setHeader($customHeader[0], array(
348
                        $customHeader[1],
349
                    ));
350
                }
351
            }
352
        }
353
    }
354
355
    /**
356
     * [headerAuth]
357
     * @return object
358
     */
359
    public function headerAuth()
360
    {
361
        if (is_null($this->headerAuth)) {
362
            $this->headerAuth = new headerAuth;
363
        }
364
        $this->headerAuth->setOptions($this->getOptions());
365
        return $this->headerAuth;
366
    }
367
368
    /**
369
     * [authorizationHeaders Scan for "Authorization" header]
370
     * @return string|array [mixed: string / error]
371
     */
372
    public function authorizationHeaders($skipError = false)
373
    {
374
        return $this->headerAuth()->authorizationHeaders($skipError);
375
    }
376
377
    /**
378
     * [hasBearerToken Check if bearer token is present]
379
     * @return string|null
380
     */
381
    public function hasBearerToken()
382
    {
383
        return $this->headerAuth()->hasBearerToken();
384
    }
385
386
    /**
387
     * [unauthorised Set an unauthorised header]
388
     * @return array [exit exception message]
389
     */
390
    public function unauthorised()
391
    {
392
        $this->headerAuth()->setUnauthorised();
393
    }
394
395
    /**
396
     * [getMaxWindow Get the max control age window]
397
     * @return integer
398
     */
399
    private function getMaxWindow()
400
    {
401
        if ($this->getOptions()) {
402
            if (isset($this->getOptions()['maxWindow']) && !empty($this->getOptions()['maxWindow'])) {
403
                if (!is_numeric($this->getOptions()['maxWindow'])) {
404
                    (new exception\errorException)
405
                        ->setOptions($this->getOptions())
406
                        ->message('maxWindow option must be an integer type')
407
                        ->error('APPLICATION_ERROR');
408
                }
409
410
                return $this->getOptions()['maxWindow'];
411
            }
412
        }
413
        return self::MAX_WINDOW;
414
    }
415
416
    /**
417
     * [setHeaderStatus]
418
     * @param void
419
     */
420
    public function setHeaderStatus($status)
421
    {
422
        http_response_code($status);
423
    }
424
425
    /**
426
     * [getHeaderStatus]
427
     * @return integer
428
     */
429
    public function getHeaderStatus()
430
    {
431
        return http_response_code();
432
    }
433
434
    /**
435
     * [setData Set request method data]
436
     * @param array $data
437
     * @return void
438
     */
439
    public function setData($data = [])
440
    {
441
        $this->REQUEST_METHOD['data'] = $data;
442
    }
443
}
444