Route::setPath()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 5
c 0
b 0
f 0
rs 9.4285
cc 1
eloc 3
nc 1
nop 1
1
<?php
2
declare(strict_types = 1);
3
4
/**
5
 * Micro
6
 *
7
 * @author    Raffael Sahli <[email protected]>
8
 * @copyright Copyright (c) 2017 gyselroth GmbH (https://gyselroth.com)
9
 * @license   MIT https://opensource.org/licenses/MIT
10
 */
11
12
namespace Micro\Http\Router;
13
14
use \Micro\Exception;
15
use \Micro\Http\Router;
16
use \Psr\Container\ContainerInterface;
17
18
class Route
19
{
20
    /**
21
     * Router
22
     *
23
     * @var Router
24
     */
25
    protected $router;
26
27
28
    /**
29
     * Continue propagation if match
30
     *
31
     * @var bool
32
     */
33
    protected $continue_propagation = false;
34
35
36
    /**
37
     * Route path
38
     *
39
     * @var string
40
     */
41
    protected $path;
42
43
44
    /**
45
     * Class to be instanced if route match was found
46
     *
47
     * @var string|object
48
     */
49
    protected $class;
50
51
52
    /**
53
     * Method to be executed if route match was found
54
     *
55
     * @var string
56
     */
57
    protected $method;
58
59
60
    /**
61
     * Found request parameters
62
     *
63
     * @var array
64
     */
65
    protected $params = [];
66
67
68
    /**
69
     * Instance route
70
     *
71
     * @param   string $path
72
     * @param   string $class
73
     * @param   string $method
74
     * @param   array $params
75
     * @return  void
0 ignored issues
show
Comprehensibility Best Practice introduced by
Adding a @return annotation to constructors is generally not recommended as a constructor does not have a meaningful return value.

Adding a @return annotation to a constructor is not recommended, since a constructor does not have a meaningful return value.

Please refer to the PHP core documentation on constructors.

Loading history...
76
     */
77
    public function __construct(string $path, $class, ? string $method = null, array $params = [])
78
    {
79
        $this->setPath($path);
80
        $this->setClass($class);
81
        $this->setMethod($method);
82
        $this->setParams($params);
83
    }
84
85
86
    /**
87
     * Check if route does match the current http request
88
     *
89
     * @return bool
90
     */
91
    public function match(): bool
92
    {
93
        $regex = preg_replace_callback('#({([A-Z0-9a-z]+)\:\#(.+?)\#})|\{(.+?)\}#', function($match) {
94
            if (count($match) === 4) {
95
                return '(?<'.$match[2].'>'.$match[3].'+)';
96
            } else {
97
                return '(?<'.end($match).'>\w+)';
98
            }
99
        }, $this->path);
100
101
        if (preg_match('#^'.$regex.'#', $this->router->getPath(), $matches)) {
102
            foreach ($matches as $key => $value) {
103
                if (!is_int($key)) {
104
                    $this->params[$key] = $value;
105
                }
106
            }
107
108
            return true;
109
        }
110
111
        return false;
112
    }
113
114
115
    /**
116
     * Get callable
117
     *
118
     * @param  ContainerInterface $container
119
     * @return array
120
     */
121
    public function getCallable(?ContainerInterface $container=null): array
122
    {
123
        if (is_object($this->class)) {
124
            $instance = $this->class;
125
        } else {
126
            if($container === null) {
127
                $instance = new $this->class();
128
            } else {
129
                $instance = $container->get($this->class);
130
            }
131
        }
132
133
        if ($this->method !== null) {
134
            return [&$instance, $this->method];
135
        }
136
137
        return [&$instance, $this->getMethod()];
138
    }
139
140
141
    /**
142
     * Build method name
143
     *
144
     * @param   string $name
145
     * @return  string
146
     */
147
    protected function buildMethodName(? string $name) : string
148
    {
149
        $result = $this->router->getVerb();
150
151
        if ($name !== null) {
152
            $split = explode('-', $name);
153
            foreach ($split as $part) {
154
                $result .= ucfirst($part);
155
            }
156
        }
157
158
        return $result;
159
    }
160
161
162
    /**
163
     * Get http router
164
     *
165
     * @return Router
166
     */
167
    public function getRouter(): Router
168
    {
169
        return $this->router;
170
    }
171
172
173
    /**
174
     * Set http router
175
     *
176
     * @param  Router $router
177
     * @return Route
178
     */
179
    public function setRouter(Router $router): Route
180
    {
181
        $this->router = $router;
182
        return $this;
183
    }
184
185
186
    /**
187
     * Get path
188
     *
189
     * @return string
190
     */
191
    public function getPath(): string
192
    {
193
        return $this->path;
194
    }
195
196
197
    /**
198
     * Set path
199
     *
200
     * @param  string $path
201
     * @return Route
202
     */
203
    public function setPath(string $path): Route
204
    {
205
        $this->path = (string)$path;
206
        return $this;
207
    }
208
209
210
    /**
211
     * Get class
212
     *
213
     * @return string
214
     */
215
    public function getClass(): string
216
    {
217
        if (is_object($this->class)) {
218
            return get_class($this->class);
219
        }
220
221
        return $this->class;
222
    }
223
224
225
    /**
226
     * Set clas
227
     *
228
     * @param   string|object $class
229
     * @return  Route
230
     */
231
    public function setClass($class): Route
232
    {
233
        $this->class = $class;
234
        return $this;
235
    }
236
237
238
    /**
239
     * Convert camelCase to dashes
240
     *
241
     * @param  string $value
242
     * @return string
243
     */
244
    protected function camelCase2Dashes(string $value): string
245
    {
246
        return strtolower(preg_replace('/([a-z])([A-Z])/', '$1-$2', $value));
247
    }
248
249
250
    /**
251
     * Get method
252
     *
253
     * @return string
254
     */
255
    public function getMethod(): string
256
    {
257
        if (substr($this->path, -1) === '$') {
258
            return $this->router->getVerb();
259
        }
260
261
        $path = $this->router->getPath();
262
        $action = substr($path, strrpos($path, '/') + 1);
263
264
        if (!in_array($action, $this->params)) {
265
            $this->method = $action;
266
        }
267
268
        $short = $this->camelCase2Dashes(substr($this->class, strrpos($this->class, '\\') + 1));
269
270
        if ($this->camelCase2Dashes($short) === $action) {
271
            $this->method = '';
272
        }
273
274
        return $this->buildMethodName($this->method);
275
    }
276
277
278
    /**
279
     * Set method
280
     *
281
     * @param   string $method
282
     * @return  Route
283
     */
284
    public function setMethod(? string $method) : Route
285
    {
286
        $this->method = $method;
287
        return $this;
288
    }
289
290
291
    /**
292
     * Set params
293
     *
294
     * @param   array $params
295
     * @return  Route
296
     */
297
    public function setParams(array $params): Route
298
    {
299
        $this->params = $params;
300
        return $this;
301
    }
302
303
304
    /**
305
     * Get translated regex variable values
306
     *
307
     * @return array
308
     */
309
    public function getParams(): array
310
    {
311
        return $this->params;
312
    }
313
314
315
    /**
316
     * Continue propagation after match
317
     *
318
     * @return bool
319
     */
320
    public function continueAfterMatch(): bool
321
    {
322
        return $this->continue_propagation;
323
    }
324
325
326
    /**
327
     * Halt propagation after match
328
     *
329
     * @param  bool $next
330
     * @return Route
331
     */
332
    public function continuePropagation($next = true): Route
333
    {
334
        $this->continue_propagation = (bool)$next;
335
        return $this;
336
    }
337
}
338