Passed
Push — master ( 298035...f88e8a )
by Vince
06:31
created

server::route()   C

Complexity

Conditions 10
Paths 192

Size

Total Lines 90
Code Lines 37

Duplication

Lines 0
Ratio 0 %

Importance

Changes 8
Bugs 0 Features 1
Metric Value
cc 10
eloc 37
c 8
b 0
f 1
nc 192
nop 1
dl 0
loc 90
rs 6.9

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
39
     */
40
    private $options;
41
42
    /**
43
     * [$DB Database PDO connector]
44
     * @var object
45
     */
46
    protected $DB;
47
48
    /**
49
     * [$router The responsible API router]
50
     * @var array
51
     */
52
    protected $router;
53
54
    /**
55
     * [$grant_access If grant type is set then allow system scope override]
56
     * @var boolean
57
     */
58
    protected $grantAccess = false;
59
60
    /**
61
     * [$ALLOWED_METHODS]
62
     * @var array
63
     */
64
    private $ALLOWED_METHODS = array(
0 ignored issues
show
introduced by
The private property $ALLOWED_METHODS is not used, and could be removed.
Loading history...
65
        'GET',
66
        'POST',
67
        'PUT',
68
        'PATCH',
69
        'DELETE',
70
    );
71
72
    /**
73
     * [$RESPONSE]
74
     * @var array
75
     */
76
    protected $RESPONSE = array();
77
78
    /**
79
     * [__construct]
80
     * @param array  $config [environment variables]
81
     * @param boolean $db on / off
82
     */
83
    public function __construct(array $config = [], array $options = [], $db = false)
84
    {
85
        $this->options($options);
86
87
        if ($db && !$this->isMockTest()) {
88
            if (empty($config)) {
89
                $config = new configuration\config;
90
                $config->responsibleDefault();
91
                $config = $config->getConfig();
92
            }
93
            $this->DB = new connect\DB($config['DB_HOST'], $config['DB_NAME'], $config['DB_USER'], $config['DB_PASSWORD']);
94
        }
95
96
        $this->header = new headers\header;
0 ignored issues
show
Bug Best Practice introduced by
The property header does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
97
        $this->header->setOptions($options);
98
99
        $this->keys = new keys\key;
0 ignored issues
show
Bug Best Practice introduced by
The property keys does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
100
        $this->endpoints = new endpoints\map;
0 ignored issues
show
Bug Best Practice introduced by
The property endpoints does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
101
        $this->endpoints->options($options);
102
103
        $this->auth = new auth\authorise($options);
0 ignored issues
show
Bug Best Practice introduced by
The property auth does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
104
        $this->auth->header = $this->header;
105
    }
106
107
    /**
108
     * [options Responsible API options]
109
     * @param array $options
110
     */
111
    protected function options($options)
112
    {
113
        if (!is_null($this->options)) {
0 ignored issues
show
introduced by
The condition is_null($this->options) is always false.
Loading history...
114
            array_merge($this->options, $options);
115
            return;
116
        }
117
118
        $this->options = $options;
119
    }
120
121
    /**
122
     * [getOptions Get the stored Responsible API options]
123
     * @return array
124
     */
125
    protected function getOptions()
126
    {
127
        return $this->options;
128
    }
129
130
    /**
131
     * [DB Get the database instance]
132
     * @return object
133
     */
134
    public function DB()
135
    {
136
        return $this->DB;
137
    }
138
139
    /**
140
     * [requestType]
141
     * @var string $type
142
     * @return self
143
     */
144
    public function requestType($type)
145
    {
146
        $this->header->requestType($type);
147
        $this->header->requestMethod();
148
        return $this;
149
    }
150
151
    /**
152
     * [getRequestType]
153
     * @return string
154
     */
155
    public function getRequestType()
156
    {
157
        return $this->header->getRequestType();
158
    }
159
160
    /**
161
     * [setResponse Append the Responsible API response]
162
     * @param [string/array] $key [Array key]
0 ignored issues
show
Documentation Bug introduced by
The doc comment [string/array] at position 0 could not be parsed: Unknown type name '[' at position 0 in [string/array].
Loading history...
163
     * @param array|null $response [Array value]
164
     */
165
    public function setResponse($key, $response)
166
    {
167
        $this->RESPONSE = [
168
            'headerStatus' => $this->header->getHeaderStatus(),
169
            'expires_in' => $this->auth->getJWTObject('expiresIn'),
170
            'access_token' => $this->auth->getJWTObject('token'),
171
            'refresh_token' => $this->auth->getJWTObject('refresh'),
172
        ];
173
174
        if (isset($this->RESPONSE['response'][$key])) {
175
            $this->RESPONSE['response'][$key][] = $response;
176
            return;
177
        }
178
        if (is_null($key) || $key == '') {
179
            if( !is_null($response) ) {
180
                $this->RESPONSE['response'] = $response;
181
            }
182
            return;
183
        }
184
185
        $this->RESPONSE['response'][$key] = $response;
186
    }
187
188
    /**
189
     * [getResponse Get the Responsible API output response]
190
     * @return array
191
     */
192
    private function getResponse()
193
    {
194
        return $this->RESPONSE;
195
    }
196
197
    /**
198
     * [rate Set the API rate limit]
199
     * @param  integer $limit [The request limit]
200
     * @param  string|integer $rate  [The request window]
201
     * @return self
202
     */
203
    public function rateLimit($limit = null, $rate = null)
204
    {
205
        $this->limiter = new throttle\limiter($limit, $rate);
0 ignored issues
show
Bug Best Practice introduced by
The property limiter does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
Unused Code introduced by
The call to responsible\core\throttle\limiter::__construct() has too many arguments starting with $limit. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

205
        $this->limiter = /** @scrutinizer ignore-call */ new throttle\limiter($limit, $rate);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
206
        return $this;
207
    }
208
209
    /**
210
     * [authenticate Parse the requests to Responsible API]
211
     *
212
     * 1. Authorise the requests JWT
213
     * 2. Throttle the requests
214
     *
215
     * @return self
216
     */
217
    public function authenticate()
218
    {
219
        $options = $this->getOptions();
220
        $route = (isset($options['route']) && !empty($options['route']) ) ? $options['route'] : '';
221
222
        $this->endpoints->baseApiRoot(dirname(__DIR__));
223
        $this->endpoints->register();
224
        
225
        $router = new route\router();
226
        $router->baseApiRoot(dirname(__DIR__));
227
228
        $this->router = $router->route($route);
0 ignored issues
show
Documentation Bug introduced by
It seems like $router->route($route) of type object is incompatible with the declared type array of property $router.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
229
        $endpoint = $this->endpoints->isEndpoint($router->getApi(), $router->getPath());
230
231
        if(isset($endpoint->model['scope'])) {
232
            $_REQUEST['scope'] = $endpoint->model['scope'];
233
            $this->header->setData($_REQUEST);
234
        }
235
236
        /**
237
         * Authenticate the JWT
238
         */
239
        $this->auth->authorise();
240
241
        /**
242
         * Call the rate limiter then throttle
243
         */
244
        if (!isset($this->limiter)) {
245
            $this->rateLimit();
246
        }
247
        
248
        $this->limiter
249
            ->options($this->getOptions())
250
            ->setAccount($this->auth->user())
251
            ->setupOptions()
252
            ->throttleRequest()
253
        ;
254
255
        return $this;
256
    }
257
258
    /**
259
     * [route Build the Responsible router]
260
     *
261
     * 1. Endpoints registry
262
     * 2. Build router
263
     * 3. Try run middleware
264
     *
265
     * @return array
266
     */
267
    public function route($route)
268
    {
269
        /**
270
         * Register endpoints
271
         */
272
        $this->endpoints->baseApiRoot(dirname(__DIR__));
273
        $this->endpoints->register();
274
275
        /**
276
         * Initialise the router
277
         */
278
        $router = new route\router();
279
        $router->baseApiRoot(dirname(__DIR__));
280
        $this->router = $router->route($route);
0 ignored issues
show
Documentation Bug introduced by
It seems like $router->route($route) of type object is incompatible with the declared type array of property $router.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
281
        $this->router->options = $this->getOptions();
282
        $this->router->auth = $this->auth->user();
283
        $this->router->limiter = $this->limiter->getThrottle();
284
285
        /**
286
         * Endpoint tiers must be larger than 1
287
         */
288
        if ($router->getSize() < 2) {
289
            (new exception\errorException)->error('NOT_FOUND');
290
        }
291
292
        /**
293
         * Check if the requested endpoint is allowed
294
         */
295
        if (!$this->router->endpoint =
296
            $this->endpoints->isEndpoint($router->getApi(), $router->getPath())
297
        ) {
298
            (new exception\errorException)->error('BAD_REQUEST');
299
        }
300
301
        $this->router->endpoint->header = [
302
            'method' => $this->header->getServerMethod(),
303
            'status' => $this->header->getHeaderStatus(),
304
            'body' => $this->header->getMethod(),
305
        ];
306
307
        /**
308
         * Check if theres a payload sent
309
         */
310
        if(isset($_REQUEST['payload'])) {
311
            $router->setRequestBody($_REQUEST['payload']);
312
        }
313
        // print_r($_REQUEST);
314
        /*if(isset($_POST) && !empty($_POST)) {
315
            $router->setPostBody($_POST);
316
        }*/
317
        $this->router->payload = $router->getRequestBody();
318
319
        /**
320
         * Check the access scope
321
         */
322
        if( !isset($this->router->endpoint->model['scope']) ) {
323
            $this->router->endpoint->model['scope'] = 'private';
324
        }
325
326
        if( isset($this->header->getMethod()->data['scope']) && 
327
            ($this->header->getMethod()->data['scope'] == 'anonymous')
328
        ) {
329
            $this->router->endpoint->model['scope'] = 'anonymous';
330
        }
331
332
        $router->setScope($this->router->endpoint->model['scope']);
333
        
334
        if (!$this->auth->isGrantType()) {
335
            if (!$router->systemAccess($this->auth->user())) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $router->systemAccess($this->auth->user()) of type null|true is loosely compared to false; this is ambiguous if the boolean can be false. You might want to explicitly use !== null instead.

If an expression can have both false, and null as possible values. It is generally a good practice to always use strict comparison to clearly distinguish between those two values.

$a = canBeFalseAndNull();

// Instead of
if ( ! $a) { }

// Better use one of the explicit versions:
if ($a !== null) { }
if ($a !== false) { }
if ($a !== null && $a !== false) { }
Loading history...
336
                $this->header->unauthorised();
337
            }
338
        }
339
340
        /**
341
         * Try run the requests
342
         */
343
        if ($router->getScope() !== 'system') {
344
            $response = $router->run();
345
346
        } else {
347
            $response = [
0 ignored issues
show
Unused Code introduced by
The assignment to $response is dead and can be removed.
Loading history...
348
                'system' => $router->getApi(),
349
            ];
350
351
            $response = $router->run();
352
        }
353
354
        $this->setResponse('', $response);
355
356
        return $this;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this returns the type responsible\core\server which is incompatible with the documented return type array.
Loading history...
357
    }
358
359
    /**
360
     * [getRouter Get the details of the Responsible API router]
361
     * @return array
362
     */
363
    public function getRouter()
364
    {
365
        return $this->router;
366
    }
367
368
    /**
369
     * [coredata Get the core data response]
370
     * @return object
371
     */
372
    public function coredata()
373
    {
374
        /**
375
         * Set the core data response
376
         * Used for debugging
377
         */
378
        foreach ($this->router as $key => $value) {
379
            $this->setResponse($key, $value);
380
        }
381
        return $this;
382
    }
383
384
    /**
385
     * [response Finnal response output]
386
     * @return array|object
387
     */
388
    public function response($debug = '')
389
    {
390
        /**
391
         * Output bebug functions
392
         */
393
        if (!empty($debug)) {
394
            if (method_exists($this, $debug)) {
395
                call_user_func(array($this, $debug));
396
            }
397
        }
398
399
        /**
400
         * Set the Responsible headers
401
         */
402
        $this->header->requestType($this->getRequestType());
403
        $this->header->setHeaders();
404
405
        /**
406
         * Output the response if any
407
         */
408
        return (new request\application($this->getRequestType()))
409
            ->data($this->getResponse());
410
    }
411
412
    /**
413
     * isMockTest
414
     *     Check if there's a mook server request
415
     * @return boolean
416
     */
417
    public function isMockTest():bool
418
    {
419
        if (isset($this->options['mock']) && 
420
            $this->options['mock'] == 'mock:3$_\7ucJ#D4,Yy=qzwY{&E+Mk_h,7L8:key'
421
        ) {
422
            return true;
423
        }
424
425
        return false;
426
    }
427
}
428