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

server::route()   C

Complexity

Conditions 11
Paths 192

Size

Total Lines 98
Code Lines 43

Duplication

Lines 0
Ratio 0 %

Importance

Changes 10
Bugs 0 Features 1
Metric Value
cc 11
eloc 43
c 10
b 0
f 1
nc 192
nop 1
dl 0
loc 98
rs 6.55

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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
11
 *
12
 * @author Vince scarpa <[email protected]>
13
 *
14
 */
15
namespace responsible\core;
16
17
use responsible\core\auth;
18
use responsible\core\configuration;
19
use responsible\core\connect;
20
use responsible\core\endpoints;
21
use responsible\core\exception;
22
use responsible\core\headers;
23
use responsible\core\keys;
24
use responsible\core\request;
25
use responsible\core\route;
26
use responsible\core\throttle;
27
28
class server
29
{
30
    /**
31
     * [$config]
32
     * @var object
33
     */
34
    protected $config;
35
36
    /**
37
     * [$options Variable store for the Responsible API options set]
38
     * @var array|null
39
     */
40
    private $options = null;
41
42
    /**
43
     * [$DB Database PDO connector]
44
     * @var object|null
45
     */
46
    protected $DB = null;
47
48
    /**
49
     * [$grant_access If grant type is set then allow system scope override]
50
     * @var boolean
51
     */
52
    protected $grantAccess = false;
53
54
    /**
55
     * [$RESPONSE]
56
     * @var array
57
     */
58
    protected $RESPONSE = array();
59
60
    /**
61
     * [$header Header class object]
62
     * @var object
63
     */
64
    protected $header;
65
66
    /**
67
     * [$endpoints Endpoints class object]
68
     * @var object
69
     */
70
    protected $endpoints;
71
72
    /**
73
     * [$keys Keys class object]
74
     * @var object
75
     */
76
    protected $keys;
77
78
    /**
79
     * [$auth Auth class object]
80
     * @var object
81
     */
82
    protected $auth;
83
84
    /**
85
     * [$limiter Limiter class object]
86
     * @var object
87
     */
88
    protected $limiter;
89
90
    /**
91
     * [$router Router object]
92
     * @var object
93
     */
94
    protected $router;
95
96
    /**
97
     * [$routerClass Router class object]
98
     * @var object
99
     */
100
    protected $routerClass;
101
102
    /**
103
     * [$renderError]
104
     * @var boolean
105
     */
106
    protected $renderError = false;
107
108
    /**
109
     * [__construct]
110
     * @param array  $config 
111
     *        environment variables
112
     * @param boolean $db
113
     */
114
    public function __construct(array $config = [], array $options = [], $db = false)
115
    {
116
        $this->setOptions($options);
117
118
        // @codeCoverageIgnoreStart
119
        if ($db && !$this->isMockTest()) {
120
            if (empty($config)) {
121
                $config = $this->getConfig();
122
            }
123
            if (is_null($this->DB)) {
124
                $this->DB = new connect\DB($config['DB_HOST'], $config['DB_NAME'], $config['DB_USER'], $config['DB_PASSWORD']);
125
            }
126
        }
127
        // @codeCoverageIgnoreEnd
128
129
        $this->setDependencies();
130
    }
131
132
    /**
133
     * [getConfig]
134
     * @return array
135
     */
136
    public function getConfig()
137
    {
138
        $config = new configuration\config;
139
        $config->responsibleDefault();
140
        $config = $config->getConfig();
141
142
        return $config;
143
    }
144
145
    /**
146
     * [setDependencies Setup all dependent classes]
147
     */
148
    private function setDependencies()
149
    {
150
        $options = $this->getOptions();
151
152
        if (is_null($this->header)) {
153
            $this->header = new headers\header;
154
            $this->header->setOptions($options);
155
156
            if (empty((array)$this->header->getMethod())) {
157
                $this->header->requestMethod();
158
            }
159
        }
160
161
        if (is_null($this->keys)) {
162
            $this->keys = new keys\key;
163
        }
164
165
        if (is_null($this->endpoints)) {
166
            $this->endpoints = new endpoints\map;
167
            $this->endpoints->setOptions($options);
168
        }
169
170
        if (is_null($this->auth)) {
171
            $this->auth = new auth\authorise($options);
172
            $this->auth->header = $this->header;
173
        }
174
    }
175
176
    /**
177
     * [getInstance Get a child dependency of sever class]
178
     * @param  [type] $class
0 ignored issues
show
Documentation Bug introduced by
The doc comment [type] at position 0 could not be parsed: Unknown type name '[' at position 0 in [type].
Loading history...
179
     * @return object|null
180
     */
181
    public function getInstance($class)
182
    {
183
        if (property_exists($this, $class)) {
184
            if (!is_null($this->{$class})) {
185
                return $this->{$class};
186
            }
187
        }
188
        return null;
189
    }
190
191
    /**
192
     * [options Responsible API options]
193
     * @param array $options
194
     */
195
    public function setOptions($options)
196
    {
197
        if (!is_null($this->options)) {
198
            array_merge($this->options, $options);
199
            return;
200
        }
201
202
        $this->options = $options;
203
    }
204
205
    /**
206
     * [getOptions Get the stored Responsible API options]
207
     * @return array|null
208
     */
209
    public function getOptions():?array
210
    {
211
        return $this->options;
212
    }
213
214
    /**
215
     * [DB Get the database instance]
216
     * @codeCoverageIgnore
217
     * @return object
218
     */
219
    public function DB()
220
    {
221
        return $this->DB;
222
    }
223
224
    /**
225
     * [requestType]
226
     * @var string $type
227
     * @return self
228
     */
229
    public function requestType($type)
230
    {
231
        $this->header->requestType($type);
232
        $this->header->requestMethod();
233
        return $this;
234
    }
235
236
    /**
237
     * [getRequestType]
238
     * @return string
239
     */
240
    public function getRequestType()
241
    {
242
        return $this->header->getRequestType();
243
    }
244
245
    /**
246
     * [setResponse Append the Responsible API response]
247
     * @param string|array $key
248
     * @param array|object|null $response
249
     */
250
    public function setResponse($key, $response)
251
    {
252
        $responseHeader = [
253
            'headerStatus' => $this->header->getHeaderStatus(),
254
            'expires_in' => $this->auth->getJWTObject('expiresIn'),
255
            'access_token' => $this->auth->getJWTObject('token'),
256
            'refresh_token' => $this->auth->getJWTObject('refresh'),
257
        ];
258
259
        if (isset($this->RESPONSE['response'][$key])) {
260
            $this->RESPONSE['response'][$key][] = $response;
261
            $this->RESPONSE = array_merge($responseHeader, $this->RESPONSE);
262
            return;
263
        }
264
265
        if (is_null($key) || $key == '') {
266
            if( !is_null($response) ) {
267
                $this->RESPONSE['response'] = $response;
268
            }
269
            $this->RESPONSE = array_merge($responseHeader, $this->RESPONSE);
270
            return;
271
        }
272
273
        $this->RESPONSE['response'][$key] = $response;
274
        $this->RESPONSE = array_merge($responseHeader, $this->RESPONSE);
275
    }
276
277
    /**
278
     * [getResponse Get the Responsible API output response]
279
     * @return array
280
     */
281
    public function getResponse()
282
    {
283
        if(isset($this->RESPONSE['response']['response'])) {
284
            $this->RESPONSE['response'] = $this->RESPONSE['response']['response'];
285
        }
286
        return $this->RESPONSE;
287
    }
288
289
    /**
290
     * [rate Set the API rate limit]
291
     * @param  integer $limit [The request limit]
292
     * @param  string|integer $rate  [The request window]
293
     * @return self
294
     */
295
    public function rateLimit($limit = null, $rate = null)
296
    {
297
        $this->limiter = new throttle\limiter($limit, $rate);
298
        $this->limiter->setOptions($this->getOptions());
299
        return $this;
300
    }
301
302
    /**
303
     * [authenticate Parse the requests to Responsible API]
304
     *
305
     * 1. Authorise the requests JWT
306
     * 2. Throttle the requests
307
     *
308
     * @return self
309
     */
310
    public function authenticate()
311
    {
312
        $options = $this->getOptions();
313
        $route = (isset($options['route']) && !empty($options['route']) ) ? $options['route'] : '';
314
315
        $this->endpoints->baseApiRoot(dirname(__DIR__));
316
        $this->endpoints->register();
317
        
318
        $router = new route\router();
319
        $router->baseApiRoot(dirname(__DIR__));
320
321
        $this->router = $router->route($route);
322
        $endpoint = $this->endpoints->isEndpoint($router->getApi(), $router->getPath());
323
324
        if(isset($endpoint->model['scope'])) {
325
            $_REQUEST['scope'] = $endpoint->model['scope'];
326
            $this->header->setData($_REQUEST);
327
        }
328
329
        /**
330
         * Authenticate the JWT
331
         */
332
        $this->auth->authorise();
333
334
        /**
335
         * Call the rate limiter then throttle
336
         */
337
        if (!isset($this->limiter)) {
338
            $this->rateLimit();
339
        }
340
        
341
        $this->limiter
342
            ->setAccount($this->auth->user())
343
            ->setupOptions()
344
            ->throttleRequest()
345
        ;
346
347
        return $this;
348
    }
349
350
    /**
351
     * [route Build the Responsible router]
352
     *
353
     * 1. Endpoints registry
354
     * 2. Build router
355
     * 3. Try run middleware
356
     *
357
     * @return self
358
     */
359
    public function route($route)
360
    {
361
        /**
362
         * Register endpoints
363
         */
364
        $this->endpoints->baseApiRoot(dirname(__DIR__));
365
        $this->endpoints->register();
366
367
        /**
368
         * Initialise the router
369
         */
370
        $this->routerClass = new route\router();
371
        $this->routerClass->setOptions($this->getOptions());
372
        $router = $this->routerClass;
373
374
        $router->baseApiRoot(dirname(__DIR__));
375
        $this->router = $router->route($route);
376
        $this->router->options = $this->getOptions();
377
        $this->router->auth = $this->auth->user();
378
        $this->router->limiter = $this->limiter->getThrottle();
379
380
        /**
381
         * Endpoint tiers must be larger than 1
382
         */
383
        if ($router->getSize() < 2) {
384
            (new exception\errorException)
385
                ->setOptions($this->getOptions())
386
                ->error('NOT_FOUND');
387
        }
388
389
        /**
390
         * Check if the requested endpoint is allowed
391
         */
392
        if (!$this->router->endpoint =
393
            $this->endpoints->isEndpoint($router->getApi(), $router->getPath())
394
        ) {
395
            (new exception\errorException)
396
                ->setOptions($this->getOptions())
397
                ->error('BAD_REQUEST');
398
        }
399
400
        $this->router->endpoint->header = [
401
            'method' => $this->header->getServerMethod(),
402
            'status' => $this->header->getHeaderStatus(),
403
            'body' => $this->header->getMethod(),
404
        ];
405
406
        /**
407
         * Check if theres a request payload sent
408
         */
409
        if(isset($_REQUEST['payload'])) {
410
            $router->setRequestBody($_REQUEST['payload']);
411
        }
412
        $router->setPostBody($this->header->getBody());
413
414
        $this->router->payload = $router->getRequestBody();
415
        $this->router->body = $router->getBody();
416
417
        /**
418
         * Check the access scope
419
         */
420
        if( !isset($this->router->endpoint->model['scope']) ) {
421
            $this->router->endpoint->model['scope'] = 'private';
422
        }
423
424
        if( isset($this->header->getMethod()->data['scope']) && 
425
            ($this->header->getMethod()->data['scope'] == 'anonymous')
426
        ) {
427
            $this->router->endpoint->model['scope'] = 'anonymous';
428
        }
429
430
        $router->setScope($this->router->endpoint->model['scope']);
431
        
432
        // @codeCoverageIgnoreStart
433
        if (!$this->auth->isGrantType() && !$this->isMockTest()) {
434
            if (!$router->systemAccess($this->auth->user())) {
435
                $this->header->unauthorised();
436
            }
437
        }
438
        // @codeCoverageIgnoreEnd
439
440
        /**
441
         * Try run the requests
442
         */
443
        if ($router->getScope() !== 'system') {
444
            $response = $router->run();
445
446
        } else {
447
            /*$response = [
448
                'system' => $router->getApi(),
449
            ];*/
450
451
            $response = $router->run();
452
        }
453
454
        $this->setResponse('', $response);
455
456
        return $this;
457
    }
458
459
    /**
460
     * [getRouter Get the details of the Responsible API router]
461
     * @return object
462
     */
463
    public function getRouter()
464
    {
465
        return $this->router;
466
    }
467
468
    /**
469
     * [coredata Get the core data response]
470
     * @return object
471
     */
472
    public function coredata()
473
    {
474
        /**
475
         * Set the core data response
476
         * Used for debugging
477
         */
478
        foreach ($this->router as $key => $value) {
479
            $this->setResponse($key, $value);
480
        }
481
        return $this;
482
    }
483
484
    /**
485
     * [response Finnal response output]
486
     * @return array|object
487
     */
488
    public function response($debug = '')
489
    {
490
        /**
491
         * Output bebug functions
492
         */
493
        if (!empty($debug)) {
494
            if (method_exists($this, $debug)) {
495
                call_user_func(array($this, $debug));
496
            }
497
        }
498
499
        /**
500
         * Set the Responsible headers
501
         */
502
        $this->header->requestType($this->getRequestType());
503
        $this->header->setHeaders();
504
505
        /**
506
         * Output the response if any
507
         */
508
        $requestApplication = new request\application($this->getRequestType());
509
        $requestApplication->setOptions($this->getOptions());
510
        return $requestApplication->data($this->getResponse());
511
    }
512
513
    /**
514
     * isMockTest
515
     *     Check if there's a mock test request
516
     * @return boolean
517
     */
518
    public function isMockTest():bool
519
    {
520
        $config = $this->getConfig();
521
522
        return (isset($this->options['mock']) && $this->options['mock'] == $config['MASTER_KEY']);
523
    }
524
}
525