Passed
Push — master ( 4cfdc5...37c7d0 )
by Alex
07:00
created

SimpleRoutesSet::getAllRoutesTrace()   A

Complexity

Conditions 6
Paths 9

Size

Total Lines 31
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
eloc 19
c 1
b 0
f 1
dl 0
loc 31
rs 9.0111
cc 6
nc 9
nop 0
1
<?php
2
namespace Mezon\Router;
3
4
trait SimpleRoutesSet
5
{
6
7
    // TODO Exclude duplicates
8
9
    /**
10
     * List of static routes for all supported request methods
11
     *
12
     * @var array
13
     */
14
    protected $staticRoutes = [
15
        'GET' => [],
16
        'POST' => [],
17
        'PUT' => [],
18
        'DELETE' => [],
19
        'OPTION' => [],
20
        'PATCH' => []
21
    ];
22
23
    /**
24
     * List of non static routes
25
     *
26
     * @var array
27
     */
28
    protected $paramRoutes = [
29
        'GET' => [],
30
        'POST' => [],
31
        'PUT' => [],
32
        'DELETE' => [],
33
        'OPTION' => [],
34
        'PATCH' => []
35
    ];
36
37
    /**
38
     * Method adds param router
39
     *
40
     * @param string $requestMethod
41
     *            request method
42
     * @param string $route
43
     *            route
44
     * @param mixed $callback
45
     *            callback method
46
     */
47
    protected function addParamRoute(string $requestMethod, string $route, $callback): void
48
    {
49
        if (empty($this->paramRoutes[$requestMethod])) {
50
            $this->paramRoutes[$requestMethod] = [];
51
        }
52
53
        $this->paramRoutes[$requestMethod][] = [
54
            'pattern' => $route,
55
            'callback' => $callback
56
        ];
57
    }
58
59
    /**
60
     * Route names
61
     *
62
     * @var array
63
     */
64
    private $routeNames = [];
65
66
    /**
67
     * Method validates request method
68
     *
69
     * @param string $requestMethod
70
     *            HTTP request method
71
     */
72
    protected function validateRequestMethod(string $requestMethod): void
73
    {
74
        if (isset($this->staticRoutes[$requestMethod]) === false) {
75
            throw (new \Exception('Unsupported request method: "' . $requestMethod . '"'));
76
        }
77
    }
78
79
    /**
80
     * Method returns a list of supported request methods
81
     *
82
     * @return array list of supported request methods
83
     */
84
    public static function getListOfSupportedRequestMethods(): array
85
    {
86
        // TODO move to the base trait common with RoutesSet
87
        return [
88
            'GET',
89
            'POST',
90
            'PUT',
91
            'DELETE',
92
            'OPTION',
93
            'PATCH'
94
        ];
95
    }
96
97
    /**
98
     * Method clears router data
99
     */
100
    public function clear(): void
101
    {
102
        $this->routeNames = [];
103
104
        foreach (self::getListOfSupportedRequestMethods() as $requestMethod) {
105
            $this->staticRoutes[$requestMethod] = [];
106
            $this->paramRoutes[$requestMethod] = [];
107
        }
108
109
        $this->middleware = [];
0 ignored issues
show
Bug Best Practice introduced by
The property middleware does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
110
    }
111
112
    /**
113
     * Method returns true if the param router exists
114
     *
115
     * @param string $route
116
     *            checking route
117
     * @param string $requestMethod
118
     *            HTTP request method
119
     * @return bool true if the param router exists, false otherwise
120
     */
121
    private function paramRouteExists(string $route, string $requestMethod): bool
122
    {
123
        foreach ($this->paramRoutes[$requestMethod] as $item) {
124
            if ($item['pattern'] === $route) {
125
                return true;
126
            }
127
        }
128
129
        return false;
130
    }
131
132
    /**
133
     * Method returns true if the router exists
134
     *
135
     * @param string $route
136
     *            checking route
137
     * @return bool true if the router exists, false otherwise
138
     */
139
    public function routeExists(string $route): bool
140
    {
141
        $route = trim($route, '/');
142
143
        foreach (self::getListOfSupportedRequestMethods() as $requestMethod) {
144
            if (isset($this->staticRoutes[$requestMethod][$route])) {
145
                return true;
146
            } else {
147
                if ($this->paramRouteExists($route, $requestMethod)) {
148
                    return true;
149
                }
150
            }
151
        }
152
153
        return false;
154
    }
155
156
    /**
157
     * Method rturns all available routes
158
     *
159
     * @return string trace
160
     */
161
    public function getAllRoutesTrace(): string
162
    {
163
        $fullTrace = [];
164
165
        foreach (self::getListOfSupportedRequestMethods() as $requestMethod) {
166
            $trace = [
167
                $requestMethod . ' : '
168
            ];
169
            $hasRoutes = false;
170
            if (! empty($this->staticRoutes[$requestMethod])) {
171
                $trace[] = implode(', ', array_keys($this->staticRoutes[$requestMethod]));
172
                $trace[] = ', ';
173
                $hasRoutes = true;
174
            }
175
            if (! empty($this->paramRoutes[$requestMethod])) {
176
                $items = [];
177
                foreach ($this->paramRoutes[$requestMethod] as $item) {
178
                    $items[] = $item['pattern'];
179
                    $hasRoutes = true;
180
                    $trace[] = implode(', ', $items);
181
                }
182
            }
183
184
            if (! $hasRoutes) {
185
                $trace[] = '<none>';
186
            }
187
188
            $fullTrace[] = implode('', $trace);
189
        }
190
191
        return implode('; ', $fullTrace);
192
    }
193
194
    /**
195
     * Method adds route and it's handler
196
     *
197
     * $callback function may have two parameters - $route and $parameters. Where $route is a called route,
198
     * and $parameters is associative array (parameter name => parameter value) with URL parameters
199
     *
200
     * @param string $route
201
     *            Route
202
     * @param mixed $callback
203
     *            Collback wich will be processing route call.
204
     * @param string|array $requestMethod
205
     *            Request type
206
     * @param string $routeName
207
     *            name of the route
208
     */
209
    public function addRoute(string $route, $callback, $requestMethod = 'GET', string $routeName = ''): void
210
    {
211
        $route = Utils::prepareRoute($route);
212
213
        if (is_array($requestMethod)) {
214
            foreach ($requestMethod as $r) {
215
                $this->addRoute($route, $callback, $r, $routeName);
216
            }
217
        } else {
218
            $this->validateRequestMethod($requestMethod);
219
220
            if (strpos($route, '[') === false) {
221
                $this->staticRoutes[$requestMethod][$route] = $callback;
222
            } else {
223
                $this->addParamRoute($requestMethod, $route, $callback);
224
            }
225
            // register route name
226
            $this->registerRouteName($routeName, $route);
227
        }
228
    }
229
230
    /**
231
     * Additing route for GET request
232
     *
233
     * @param string $route
234
     *            route
235
     * @param object $object
236
     *            callback object
237
     * @param string $method
238
     *            callback method
239
     */
240
    public function addGetRoute(string $route, object $object, string $method): void
241
    {
242
        $this->addRoute($route, [
243
            $object,
244
            $method
245
        ], 'GET');
246
    }
247
248
    /**
249
     * Additing route for GET request
250
     *
251
     * @param string $route
252
     *            route
253
     * @param object $object
254
     *            callback object
255
     * @param string $method
256
     *            callback method
257
     */
258
    public function addPostRoute(string $route, object $object, string $method): void
259
    {
260
        $this->addRoute($route, [
261
            $object,
262
            $method
263
        ], 'POST');
264
    }
265
266
    /**
267
     * Method registers name of the route
268
     *
269
     * @param string $routeName
270
     *            route's name
271
     * @param string $route
272
     *            route
273
     */
274
    protected function registerRouteName(string $routeName, string $route): void
275
    {
276
        if ($routeName != '') {
277
            $this->routeNames[$routeName] = $route;
278
        }
279
    }
280
281
    /**
282
     * Validating that route name exists
283
     *
284
     * @param string $routeName
285
     * @return bool
286
     */
287
    protected function routeNameExists(string $routeName): bool
288
    {
289
        return isset($this->routeNames[$routeName]);
290
    }
291
292
    /**
293
     * Getting route by name
294
     *
295
     * @param string $routeName
296
     *            route's name
297
     * @return string route
298
     */
299
    public function getRouteByName(string $routeName): string
300
    {
301
        if ($this->routeNameExists($routeName) === false) {
302
            throw (new \Exception('Route with name ' . $routeName . ' does not exist'));
303
        }
304
305
        return $this->routeNames[$routeName];
306
    }
307
308
    /**
309
     * Method dumps all routes and their names on disk
310
     *
311
     * @param string $filePath
312
     *            file path to cache
313
     * @codeCoverageIgnore
314
     */
315
    public function dumpOnDisk(string $filePath = './cache/cache.php'): void
316
    {
317
        file_put_contents(
318
            $filePath,
319
            '<?php return ' .
320
            var_export(
321
                [
322
                    0 => $this->staticRoutes,
323
                    1 => $this->paramRoutes,
324
                    2 => $this->routeNames
325
                ],
326
                true) . ';');
327
    }
328
329
    /**
330
     * Method loads routes from disk
331
     *
332
     * @param string $filePath
333
     *            file path to cache
334
     * @codeCoverageIgnore
335
     * @psalm-suppress UnresolvableInclude
336
     */
337
    public function loadFromDisk(string $filePath = './cache/cache.php'): void
338
    {
339
        list ($this->staticRoutes, $this->paramRoutes, $this->routeNames, $this->cachedRegExps, $this->cachedParameters) = require ($filePath);
0 ignored issues
show
Bug Best Practice introduced by
The property cachedRegExps does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
Bug Best Practice introduced by
The property cachedParameters does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
340
    }
341
}
342