Passed
Push — master ( 3985de...9157a0 )
by Vince
01:47
created

map::isEndpoint()   D

Complexity

Conditions 28
Paths 106

Size

Total Lines 162
Code Lines 82

Duplication

Lines 0
Ratio 0 %

Importance

Changes 9
Bugs 0 Features 0
Metric Value
cc 28
eloc 82
c 9
b 0
f 0
nc 106
nop 2
dl 0
loc 162
rs 4.1166

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
 * ==================================
5
 * Responsible PHP API
6
 * ==================================
7
 *
8
 * @link Git https://github.com/vince-scarpa/responsibleAPI.git
9
 *
10
 * @api Responible API
11
 * @package responsible\core\endpoints
12
 *
13
 * @author Vince scarpa <[email protected]>
14
 *
15
 */
16
17
namespace responsible\core\endpoints;
18
19
use responsible\core\endpoints;
20
use responsible\core\exception;
21
use responsible\core\route;
22
use responsible\core\interfaces;
23
24
class map extends route\router implements interfaces\optionsInterface
25
{
26
    use \responsible\core\traits\optionsTrait;
27
28
    /**
29
     * [$BASE_ENDPOINTS]
30
     * @var array
31
     */
32
    private $BASE_ENDPOINTS = array();
33
34
    /**
35
     * [$BASE_ENDPOINTS]
36
     * @var array
37
     */
38
    private $NAMESPACE_ENDPOINTS = array();
39
40
    /**
41
     * [$registry]
42
     * @var array
43
     */
44
    private $registry = array();
45
46
    /**
47
     * [$middleWareClass Holds middleware class object]
48
     * @var object
49
     */
50
    private static $middleWareClass;
51
52
    /**
53
     * [$SYSTEM_ENDPOINTS Reserved system Endpoints]
54
     * @var array
55
     */
56
    public const SYSTEM_ENDPOINTS = [
57
        'token' => '/token/access_token',
58
        'user' => [
59
            '/user/create',
60
            '/user/load',
61
        ],
62
    ];
63
64
    /**
65
     * [__construct Silence...]
66
     */
67
    public function __construct()
68
    {
69
    }
70
71
    /**
72
     * [register Scan and register endpoints defined in services]
73
     * @return array
74
     */
75
    public function register()
76
    {
77
        $options = $this->options;
78
79
        /**
80
         * Check if a custom directory was set in the Responsible API options
81
         */
82
        if (
83
            (isset($options['classRoute']) && !empty($options['classRoute'])) &&
84
            (isset($options['classRoute']['directory']) && isset($options['classRoute']['namespace']))
85
        ) {
86
            $customService = $this->options['classRoute'];
87
            $directory = $customService['directory'];
88
            $middleware = $customService['namespace'];
89
        } else {
90
            $middleware = 'responsible';
91
92
            $endpoint = str_replace(
93
                array('core', '/', '\\'),
94
                array('service', DIRECTORY_SEPARATOR, DIRECTORY_SEPARATOR),
95
                __NAMESPACE__
96
            );
97
98
            $directory = $this->route()->base['root'] . '/' . str_replace('responsible/', '', $endpoint);
99
        }
100
101
        if (!is_dir($directory)) {
102
            (new exception\errorException())
103
                ->setOptions($this->getOptions())
104
                ->message('Directory Error:: responsible\service needs to exist. See documentation on setting up a service.')
105
                ->error('NOT_EXTENDED');
106
        }
107
108
        $scanned = '';
109
        $scanDir = scandir($directory);
110
111
        if (!empty($scanDir)) {
112
            $scanned = array_values(
113
                array_diff(
114
                    $scanDir,
115
                    array('..', '.', '.DS_Store')
116
                )
117
            );
118
        }
119
120
        if (empty($scanned)) {
121
            (new exception\errorException())
122
                ->setOptions($this->getOptions())
123
                ->message('Class Error:: responsible\service\endpoints needs at least 1 class file. See documentation on setting up a service.')
124
                ->error('NOT_EXTENDED');
125
        }
126
127
        foreach ($scanned as $e => $point) {
128
            if (substr($point, -4) == '.php') {
129
                $point = str_replace('.php', '', $point);
130
131
                $this->BASE_ENDPOINTS[] = $point;
132
133
                $endpoint = str_replace('core', 'service', __NAMESPACE__) . '\\' . $point;
134
135
                if ($middleware !== 'responsible') {
136
                    $endpoint = $middleware . '\\service\\endpoints\\' . $point;
137
                }
138
139
                $child = $endpoint;
140
141
                $this->NAMESPACE_ENDPOINTS[$point] = $endpoint;
142
143
                if (class_exists($child) && method_exists($child, 'middleware')) {
144
                    self::$middleWareClass = new $child();
145
                    $this->registry[$point] = self::$middleWareClass->middleware();
146
                } elseif (class_exists($child) && method_exists($child, 'register')) {
147
                    self::$middleWareClass = new $child();
148
                    $this->registry[$point] = self::$middleWareClass->register();
149
                } else {
150
                    (new exception\errorException())
151
                        ->setOptions($this->getOptions())
152
                        ->message("Class Error:: class {$child} needs to exist. See documentation on setting up a service.")
153
                        ->error('NOT_EXTENDED');
154
                }
155
            }
156
        }
157
        return $this->registry;
158
    }
159
160
    /**
161
     * [isSystemEndpoint Check if the endpoint request is a ResponsibleAPI reserved endpoint]
162
     * @param  string  $api
163
     * @param  string  $endpoint
164
     * @return object|null
165
     */
166
    private function isSystemEndpoint($api, $endpoint)
167
    {
168
        if (
169
            isset(self::SYSTEM_ENDPOINTS[$api]) &&
170
            (
171
                in_array($endpoint, self::SYSTEM_ENDPOINTS) ||
172
                array_search($endpoint, self::SYSTEM_ENDPOINTS[$api]) !== false
173
            )
174
        ) {
175
            $endpointSettings = [];
176
            $methodCreate = explode('/', $endpoint);
177
            $methodCreate = array_values(array_filter($methodCreate));
178
            $method = '';
179
180
            foreach ($methodCreate as $i => $parts) {
181
                if (preg_match_all('#_#', $parts)) {
182
                    $parts = str_replace('_', '', lcfirst(ucwords($parts, '_')));
183
                }
184
                if ($i > 0) {
185
                    $method .= ucfirst($parts);
186
                } else {
187
                    $method .= $parts;
188
                }
189
            }
190
191
            $endpointSettings['model'] = array(
192
                'scope' => 'system',
193
                'namespace' => 'responsible\core\endpoints\system',
194
                'class' => 'system',
195
                'method' => $method,
196
                'arguments' => '',
197
            );
198
199
            return (object) $endpointSettings;
200
        }
201
202
        return null;
203
    }
204
205
    /**
206
     * [isEndpoint Check the requested endpoint, scope and tier parts]
207
     * @param  string  $api
208
     * @param  string  $endpoint
209
     * @return object|null
210
     */
211
    public function isEndpoint($api, $endpoint)
212
    {
213
        /**
214
         * Return if it's a system endpoint
215
         */
216
        if (null !== ($endpointSettings = $this->isSystemEndpoint($api, $endpoint))) {
217
            return $endpointSettings;
218
        }
219
220
        /**
221
         * Check if the endpoint is a RouterInterface
222
         */
223
        $endpoint = htmlspecialchars($endpoint, ENT_QUOTES, 'UTF-8');
224
        $index = array_search($api, $this->BASE_ENDPOINTS);
225
226
        if ($index !== false) {
227
            if (isset($this->registry[$api])) {
228
                $endpointSettings = array(
229
                    'path' => $endpoint,
230
                    'model' => array(
231
                        'namespace' => $this->NAMESPACE_ENDPOINTS[$api],
232
                        'class' => $this->BASE_ENDPOINTS[$index],
233
                        'method' => basename($endpoint),
234
                        'scope' => 'private',
235
                    ),
236
                );
237
238
                /**
239
                 * Nothing dynamic, found an exact match
240
                 * @var array
241
                 */
242
                if (array_search($endpoint, $this->registry[$api]) !== false) {
243
                    if (method_exists($this->NAMESPACE_ENDPOINTS[$api], 'scope')) {
244
                        $classScope = (new $this->NAMESPACE_ENDPOINTS[$api]())->scope();
245
                        $position = array_search($endpoint, $this->registry[$api]);
246
247
                        if (is_array($classScope) && isset($classScope[$position])) {
248
                            $endpointSettings['model']['scope'] = $classScope[$position];
249
                        } else {
250
                            if (!is_array($classScope)) {
251
                                $endpointSettings['model']['scope'] = $classScope;
252
                            }
253
                        }
254
                    }
255
                    return (object) $endpointSettings;
256
                }
257
258
                /**
259
                 * Check for exact match in middleware routes
260
                 */
261
                foreach ($this->registry[$api] as $i => $path) {
262
                    if ($path instanceof \responsible\core\endpoints\RouteMiddlewareInterface) {
263
                        $middlewareRoute = $path->getRoute();
264
                        if ($middlewareRoute === $endpoint) {
265
                            $scope = $path->getScope();
266
                            if ($scope == 'public') {
267
                                $scope = 'anonymous';
268
                            }
269
                            $endpointSettings['model']['scope'] = $scope;
270
                            $endpointSettings['model']['middleware'] = $path;
271
                            return (object) $endpointSettings;
272
                        }
273
                    }
274
                }
275
276
                /**
277
                 * Check for dynamic uri eg: {asset_id}
278
                 * Dynamic uri's must be wrapped in {} for a true return
279
                 */
280
                foreach ($this->registry[$api] as $i => $path) {
281
                    $endpointRegister = $path;
282
                    $methodArgs = [];
283
284
                    $routeInstance = null;
285
                    if ($path instanceof \responsible\core\endpoints\RouteMiddlewareInterface) {
286
                        $routeInstance = $path;
287
                        $endpointRegister = $path = $routeInstance->getRoute();
288
                        $scope = $routeInstance->getScope();
0 ignored issues
show
Unused Code introduced by
The assignment to $scope is dead and can be removed.
Loading history...
289
290
                        if (isset($_SERVER['REQUEST_METHOD'])) {
291
                            $serverMethod = $_SERVER['REQUEST_METHOD'];
292
                            if ($routeInstance->getVerb() !== $serverMethod) {
293
                                continue;
294
                            }
295
                        } else {
296
                            // If no request method is set then continue to force a bad request
297
                            continue;
298
                        }
299
                    }
300
301
                    /**
302
                     * If comparing the two sizes are not equal
303
                     * then no use continuing through the loop
304
                     */
305
                    if (!$this->uriCheckSize($endpointRegister, $endpoint)) {
306
                        continue;
307
                    }
308
309
                    /**
310
                     * This replacment will create a pattern to use as a match all expression
311
                     * @var [string]
312
                     */
313
                    $endpointRegister = preg_replace('@/{(.*?)}@', '/(.*?)', $endpointRegister);
314
315
                    if (preg_match_all('@^' . $endpointRegister . '$@i', $endpoint, $dynamicParts)) {
316
                        $endpointFilter = $this->filterParts($endpoint, $dynamicParts);
317
                        $model = $this->getClassModel($path);
318
319
                        /**
320
                         * Find the dynamic parts and set them as argument key(s)
321
                         * then combine them with the endpoint request and set the request parts
322
                         * as argument value(s)
323
                         */
324
                        if (preg_match_all("/(?<={).*?(?=})/", $path, $registerParts)) {
325
                            if (isset($registerParts[0][0])) {
326
                                $registerParts = $registerParts[0];
327
328
                                if (sizeof($endpointFilter) == sizeof($registerParts)) {
329
                                    $methodArgs = array_combine($registerParts, $endpointFilter);
330
                                }
331
                            }
332
                        }
333
334
                        $scope = 'private';
335
                        if ($routeInstance instanceof \responsible\core\endpoints\RouteMiddlewareInterface) {
336
                            $scope = $routeInstance->getScope();
337
                            if ($scope == 'public') {
338
                                $scope = 'anonymous';
339
                            }
340
                        }
341
342
                        if (method_exists($this->NAMESPACE_ENDPOINTS[$api], 'scope')) {
343
                            $classScope = (new $this->NAMESPACE_ENDPOINTS[$api]())->scope();
344
                            $position = array_search($path, $this->registry[$api]);
345
346
                            if (is_array($classScope) && isset($classScope[$position])) {
347
                                $scope = $classScope[$position];
348
                            } else {
349
                                if (!is_array($classScope)) {
350
                                    $scope = $classScope;
351
                                }
352
                            }
353
                        }
354
355
                        $endpointSettings['model'] = array(
356
                            'scope' => $scope,
357
                            'namespace' => $this->NAMESPACE_ENDPOINTS[$api],
358
                            'class' => $model['class'],
359
                            'method' => $model['method'],
360
                            'arguments' => $methodArgs,
361
                            'middleware' => $routeInstance,
362
                        );
363
364
                        return (object) $endpointSettings;
365
                    } else {
366
                        continue;
367
                    }
368
                }
369
            }
370
        }
371
372
        return;
373
    }
374
375
    /**
376
     * [filterParts Prepare routed parts]
377
     * @return array
378
     */
379
    private function filterParts($uri, $parts)
380
    {
381
        $filter = array();
382
383
        foreach ($parts as $p => $part) {
384
            if (is_array($part)) {
385
                foreach ($part as $i => $parti) {
386
                    if ($parti !== $uri) {
387
                        $filter[] = $parti;
388
                    }
389
                }
390
            }
391
        }
392
393
        return $filter;
394
    }
395
396
    /**
397
     * [uriCheckSize]
398
     *
399
     * Compare the current request endpoint with the registered endpoint
400
     * only return the same tier sizes
401
     *
402
     * @return boolean
403
     */
404
    private function uriCheckSize($endpointRegister, $endpoint)
405
    {
406
        $registerExplode = explode('/', $endpointRegister);
407
        $endpointExplode = explode('/', $endpoint);
408
        return (sizeof($registerExplode) === sizeof($endpointExplode));
409
    }
410
411
    /**
412
     * [getClassModel Class, Method]
413
     * @return array
414
     */
415
    private function getClassModel($request_path)
416
    {
417
        $cm = explode('/', $request_path);
418
419
        if (!empty($cm) && sizeof($cm) >= 2) {
420
            $cm = array_values(array_filter($cm));
421
422
            return array(
423
                'class' => $cm[0],
424
                'method' => $cm[1] ?? '',
425
            );
426
        }
427
428
        return [
429
            'class' => '',
430
            'method' => '',
431
        ];
432
    }
433
}
434