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

server   B

Complexity

Total Complexity 47

Size/Duplication

Total Lines 445
Duplicated Lines 0 %

Importance

Changes 18
Bugs 0 Features 1
Metric Value
eloc 129
c 18
b 0
f 1
dl 0
loc 445
rs 8.64
wmc 47

17 Methods

Rating   Name   Duplication   Size   Complexity  
A setOptions() 0 8 2
A requestType() 0 5 1
A setDependencies() 0 21 5
A getConfig() 0 7 1
A setResponse() 0 21 5
A isMockTest() 0 5 2
C route() 0 90 10
A response() 0 22 3
A getOptions() 0 3 1
A getResponse() 0 3 1
A coredata() 0 10 2
A getRequestType() 0 3 1
A DB() 0 3 1
A __construct() 0 14 5
A rateLimit() 0 5 1
A authenticate() 0 38 5
A getRouter() 0 3 1

How to fix   Complexity   

Complex Class

Complex classes like server 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 server, 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
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 class object]
92
     * @var object
93
     */
94
    protected $router;
95
96
    /**
97
     * [__construct]
98
     * @param array  $config 
99
     *        environment variables
100
     * @param boolean $db
101
     */
102
    public function __construct(array $config = [], array $options = [], $db = false)
103
    {
104
        $this->setOptions($options);
105
106
        if ($db && !$this->isMockTest()) {
107
            if (empty($config)) {
108
                $config = $this->getConfig();
109
            }
110
            if (is_null($this->DB)) {
111
                $this->DB = new connect\DB($config['DB_HOST'], $config['DB_NAME'], $config['DB_USER'], $config['DB_PASSWORD']);
112
            }
113
        }
114
115
        $this->setDependencies();
116
    }
117
118
    /**
119
     * [getConfig]
120
     * @return array
121
     */
122
    public function getConfig()
123
    {
124
        $config = new configuration\config;
125
        $config->responsibleDefault();
126
        $config = $config->getConfig();
127
128
        return $config;
129
    }
130
131
    /**
132
     * [setDependencies Setup all dependent classes]
133
     */
134
    private function setDependencies()
135
    {
136
        $options = $this->getOptions();
137
138
        if (is_null($this->header)) {
139
            $this->header = new headers\header;
140
            $this->header->setOptions($options);
141
        }
142
143
        if (is_null($this->keys)) {
144
            $this->keys = new keys\key;
145
        }
146
147
        if (is_null($this->endpoints)) {
148
            $this->endpoints = new endpoints\map;
149
            $this->endpoints->setOptions($options);
150
        }
151
152
        if (is_null($this->auth)) {
153
            $this->auth = new auth\authorise($options);
154
            $this->auth->header = $this->header;
155
        }
156
    }
157
158
    /**
159
     * [options Responsible API options]
160
     * @param array $options
161
     */
162
    public function setOptions($options)
163
    {
164
        if (!is_null($this->options)) {
165
            array_merge($this->options, $options);
166
            return;
167
        }
168
169
        $this->options = $options;
170
    }
171
172
    /**
173
     * [getOptions Get the stored Responsible API options]
174
     * @return array|null
175
     */
176
    public function getOptions():?array
177
    {
178
        return $this->options;
179
    }
180
181
    /**
182
     * [DB Get the database instance]
183
     * @return object
184
     */
185
    public function DB()
186
    {
187
        return $this->DB;
188
    }
189
190
    /**
191
     * [requestType]
192
     * @var string $type
193
     * @return self
194
     */
195
    public function requestType($type)
196
    {
197
        $this->header->requestType($type);
198
        $this->header->requestMethod();
199
        return $this;
200
    }
201
202
    /**
203
     * [getRequestType]
204
     * @return string
205
     */
206
    public function getRequestType()
207
    {
208
        return $this->header->getRequestType();
209
    }
210
211
    /**
212
     * [setResponse Append the Responsible API response]
213
     * @param string|array $key
214
     * @param array|object|null $response
215
     */
216
    public function setResponse($key, $response)
217
    {
218
        $this->RESPONSE = [
219
            'headerStatus' => $this->header->getHeaderStatus(),
220
            'expires_in' => $this->auth->getJWTObject('expiresIn'),
221
            'access_token' => $this->auth->getJWTObject('token'),
222
            'refresh_token' => $this->auth->getJWTObject('refresh'),
223
        ];
224
225
        if (isset($this->RESPONSE['response'][$key])) {
226
            $this->RESPONSE['response'][$key][] = $response;
227
            return;
228
        }
229
        if (is_null($key) || $key == '') {
230
            if( !is_null($response) ) {
231
                $this->RESPONSE['response'] = $response;
232
            }
233
            return;
234
        }
235
236
        $this->RESPONSE['response'][$key] = $response;
237
    }
238
239
    /**
240
     * [getResponse Get the Responsible API output response]
241
     * @return array
242
     */
243
    private function getResponse()
244
    {
245
        return $this->RESPONSE;
246
    }
247
248
    /**
249
     * [rate Set the API rate limit]
250
     * @param  integer $limit [The request limit]
251
     * @param  string|integer $rate  [The request window]
252
     * @return self
253
     */
254
    public function rateLimit($limit = null, $rate = null)
255
    {
256
        $this->limiter = new throttle\limiter($limit, $rate);
257
        $this->limiter->setOptions($this->getOptions());
258
        return $this;
259
    }
260
261
    /**
262
     * [authenticate Parse the requests to Responsible API]
263
     *
264
     * 1. Authorise the requests JWT
265
     * 2. Throttle the requests
266
     *
267
     * @return self
268
     */
269
    public function authenticate()
270
    {
271
        $options = $this->getOptions();
272
        $route = (isset($options['route']) && !empty($options['route']) ) ? $options['route'] : '';
273
274
        $this->endpoints->baseApiRoot(dirname(__DIR__));
275
        $this->endpoints->register();
276
        
277
        $router = new route\router();
278
        $router->baseApiRoot(dirname(__DIR__));
279
280
        $this->router = $router->route($route);
281
        $endpoint = $this->endpoints->isEndpoint($router->getApi(), $router->getPath());
282
283
        if(isset($endpoint->model['scope'])) {
284
            $_REQUEST['scope'] = $endpoint->model['scope'];
285
            $this->header->setData($_REQUEST);
286
        }
287
288
        /**
289
         * Authenticate the JWT
290
         */
291
        $this->auth->authorise();
292
293
        /**
294
         * Call the rate limiter then throttle
295
         */
296
        if (!isset($this->limiter)) {
297
            $this->rateLimit();
298
        }
299
        
300
        $this->limiter
301
            ->setAccount($this->auth->user())
302
            ->setupOptions()
303
            ->throttleRequest()
304
        ;
305
306
        return $this;
307
    }
308
309
    /**
310
     * [route Build the Responsible router]
311
     *
312
     * 1. Endpoints registry
313
     * 2. Build router
314
     * 3. Try run middleware
315
     *
316
     * @return self
317
     */
318
    public function route($route)
319
    {
320
        /**
321
         * Register endpoints
322
         */
323
        $this->endpoints->baseApiRoot(dirname(__DIR__));
324
        $this->endpoints->register();
325
326
        /**
327
         * Initialise the router
328
         */
329
        $router = new route\router();
330
        $router->baseApiRoot(dirname(__DIR__));
331
        $this->router = $router->route($route);
332
        $this->router->options = $this->getOptions();
333
        $this->router->auth = $this->auth->user();
334
        $this->router->limiter = $this->limiter->getThrottle();
335
336
        /**
337
         * Endpoint tiers must be larger than 1
338
         */
339
        if ($router->getSize() < 2) {
340
            (new exception\errorException)->error('NOT_FOUND');
341
        }
342
343
        /**
344
         * Check if the requested endpoint is allowed
345
         */
346
        if (!$this->router->endpoint =
347
            $this->endpoints->isEndpoint($router->getApi(), $router->getPath())
348
        ) {
349
            (new exception\errorException)->error('BAD_REQUEST');
350
        }
351
352
        $this->router->endpoint->header = [
353
            'method' => $this->header->getServerMethod(),
354
            'status' => $this->header->getHeaderStatus(),
355
            'body' => $this->header->getMethod(),
356
        ];
357
358
        /**
359
         * Check if theres a payload sent
360
         */
361
        if(isset($_REQUEST['payload'])) {
362
            $router->setRequestBody($_REQUEST['payload']);
363
        }
364
        // print_r($_REQUEST);
365
        /*if(isset($_POST) && !empty($_POST)) {
366
            $router->setPostBody($_POST);
367
        }*/
368
        $this->router->payload = $router->getRequestBody();
369
370
        /**
371
         * Check the access scope
372
         */
373
        if( !isset($this->router->endpoint->model['scope']) ) {
374
            $this->router->endpoint->model['scope'] = 'private';
375
        }
376
377
        if( isset($this->header->getMethod()->data['scope']) && 
378
            ($this->header->getMethod()->data['scope'] == 'anonymous')
379
        ) {
380
            $this->router->endpoint->model['scope'] = 'anonymous';
381
        }
382
383
        $router->setScope($this->router->endpoint->model['scope']);
384
        
385
        if (!$this->auth->isGrantType()) {
386
            if (!$router->systemAccess($this->auth->user())) {
387
                $this->header->unauthorised();
388
            }
389
        }
390
391
        /**
392
         * Try run the requests
393
         */
394
        if ($router->getScope() !== 'system') {
395
            $response = $router->run();
396
397
        } else {
398
            /*$response = [
399
                'system' => $router->getApi(),
400
            ];*/
401
402
            $response = $router->run();
403
        }
404
405
        $this->setResponse('', $response);
406
407
        return $this;
408
    }
409
410
    /**
411
     * [getRouter Get the details of the Responsible API router]
412
     * @return object
413
     */
414
    public function getRouter()
415
    {
416
        return $this->router;
417
    }
418
419
    /**
420
     * [coredata Get the core data response]
421
     * @return object
422
     */
423
    public function coredata()
424
    {
425
        /**
426
         * Set the core data response
427
         * Used for debugging
428
         */
429
        foreach ($this->router as $key => $value) {
430
            $this->setResponse($key, $value);
431
        }
432
        return $this;
433
    }
434
435
    /**
436
     * [response Finnal response output]
437
     * @return array|object
438
     */
439
    public function response($debug = '')
440
    {
441
        /**
442
         * Output bebug functions
443
         */
444
        if (!empty($debug)) {
445
            if (method_exists($this, $debug)) {
446
                call_user_func(array($this, $debug));
447
            }
448
        }
449
450
        /**
451
         * Set the Responsible headers
452
         */
453
        $this->header->requestType($this->getRequestType());
454
        $this->header->setHeaders();
455
456
        /**
457
         * Output the response if any
458
         */
459
        return (new request\application($this->getRequestType()))
460
            ->data($this->getResponse());
461
    }
462
463
    /**
464
     * isMockTest
465
     *     Check if there's a mock test request
466
     * @return boolean
467
     */
468
    public function isMockTest():bool
469
    {
470
        $config = $this->getConfig();
471
472
        return (isset($this->options['mock']) && $this->options['mock'] == $config['MASTER_KEY']);
473
    }
474
}
475