Passed
Push — master ( 9f07a5...afc511 )
by Anatoly
03:40 queued 01:13
created

Route::getHolder()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 15
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 3

Importance

Changes 0
Metric Value
eloc 7
c 0
b 0
f 0
dl 0
loc 15
ccs 8
cts 8
cp 1
rs 10
cc 3
nc 3
nop 0
crap 3
1
<?php declare(strict_types=1);
2
3
/**
4
 * It's free open-source software released under the MIT License.
5
 *
6
 * @author Anatoly Fenric <[email protected]>
7
 * @copyright Copyright (c) 2018, Anatoly Fenric
8
 * @license https://github.com/sunrise-php/http-router/blob/master/LICENSE
9
 * @link https://github.com/sunrise-php/http-router
10
 */
11
12
namespace Sunrise\Http\Router;
13
14
/**
15
 * Import classes
16
 */
17
use Psr\Http\Message\ResponseInterface;
18
use Psr\Http\Message\ServerRequestInterface;
19
use Psr\Http\Server\MiddlewareInterface;
20
use Psr\Http\Server\RequestHandlerInterface;
21
use Sunrise\Http\Router\RequestHandler\CallableRequestHandler;
22
use Sunrise\Http\Router\RequestHandler\QueueableRequestHandler;
23
use Closure;
24
use ReflectionClass;
25
use ReflectionMethod;
26
use ReflectionFunction;
27
use Reflector;
28
29
/**
30
 * Import functions
31
 */
32
use function rtrim;
33
use function strtoupper;
34
35
/**
36
 * Route
37
 *
38
 * Use the {@see RouteFactory} factory to create this class.
39
 */
40
class Route implements RouteInterface
41
{
42
43
    /**
44
     * Server Request attribute name for the route
45
     *
46
     * @var string
47
     *
48
     * @deprecated 2.11.0 Use the RouteInterface::ATTR_ROUTE constant.
49
     */
50
    public const ATTR_NAME_FOR_ROUTE = self::ATTR_ROUTE;
51
52
    /**
53
     * Server Request attribute name for the route name
54
     *
55
     * @var string
56
     *
57
     * @deprecated 2.9.0
58
     */
59
    public const ATTR_NAME_FOR_ROUTE_NAME = '@route-name';
60
61
    /**
62
     * The route name
63
     *
64
     * @var string
65
     */
66
    private $name;
67
68
    /**
69
     * The route host
70
     *
71
     * @var string|null
72
     */
73
    private $host = null;
74
75
    /**
76
     * The route path
77
     *
78
     * @var string
79
     */
80
    private $path;
81
82
    /**
83
     * The route methods
84
     *
85
     * @var string[]
86
     */
87
    private $methods;
88
89
    /**
90
     * The route request handler
91
     *
92
     * @var RequestHandlerInterface
93
     */
94
    private $requestHandler;
95
96
    /**
97
     * The route middlewares
98
     *
99
     * @var MiddlewareInterface[]
100
     */
101
    private $middlewares = [];
102
103
    /**
104
     * The route attributes
105
     *
106
     * @var array
107
     */
108
    private $attributes = [];
109
110
    /**
111
     * The route summary
112
     *
113
     * @var string
114
     */
115
    private $summary = '';
116
117
    /**
118
     * The route description
119
     *
120
     * @var string
121
     */
122
    private $description = '';
123
124
    /**
125
     * The route tags
126
     *
127
     * @var string[]
128
     */
129
    private $tags = [];
130
131
    /**
132
     * Constructor of the class
133
     *
134
     * @param string $name
135
     * @param string $path
136
     * @param string[] $methods
137
     * @param RequestHandlerInterface $requestHandler
138
     * @param MiddlewareInterface[] $middlewares
139
     * @param array $attributes
140
     */
141 90
    public function __construct(
142
        string $name,
143
        string $path,
144
        array $methods,
145
        RequestHandlerInterface $requestHandler,
146
        array $middlewares = [],
147
        array $attributes = []
148
    ) {
149 90
        $this->setName($name);
150 90
        $this->setPath($path);
151 90
        $this->setMethods(...$methods);
152 90
        $this->setRequestHandler($requestHandler);
153 90
        $this->setMiddlewares(...$middlewares);
154 90
        $this->setAttributes($attributes);
155
    }
156
157
    /**
158
     * {@inheritdoc}
159
     */
160 59
    public function getName() : string
161
    {
162 59
        return $this->name;
163
    }
164
165
    /**
166
     * {@inheritdoc}
167
     */
168 25
    public function getHost() : ?string
169
    {
170 25
        return $this->host;
171
    }
172
173
    /**
174
     * {@inheritdoc}
175
     */
176 41
    public function getPath() : string
177
    {
178 41
        return $this->path;
179
    }
180
181
    /**
182
     * {@inheritdoc}
183
     */
184 40
    public function getMethods() : array
185
    {
186 40
        return $this->methods;
187
    }
188
189
    /**
190
     * {@inheritdoc}
191
     */
192 20
    public function getRequestHandler() : RequestHandlerInterface
193
    {
194 20
        return $this->requestHandler;
195
    }
196
197
    /**
198
     * {@inheritdoc}
199
     */
200 23
    public function getMiddlewares() : array
201
    {
202 23
        return $this->middlewares;
203
    }
204
205
    /**
206
     * {@inheritdoc}
207
     */
208 16
    public function getAttributes() : array
209
    {
210 16
        return $this->attributes;
211
    }
212
213
    /**
214
     * {@inheritdoc}
215
     */
216 3
    public function getSummary() : string
217
    {
218 3
        return $this->summary;
219
    }
220
221
    /**
222
     * {@inheritdoc}
223
     */
224 3
    public function getDescription() : string
225
    {
226 3
        return $this->description;
227
    }
228
229
    /**
230
     * {@inheritdoc}
231
     */
232 3
    public function getTags() : array
233
    {
234 3
        return $this->tags;
235
    }
236
237
    /**
238
     * {@inheritdoc}
239
     */
240 3
    public function getHolder() : Reflector
241
    {
242 3
        $handler = $this->requestHandler;
243 3
        if ($handler instanceof CallableRequestHandler) {
244 2
            $callback = $handler->getCallback();
245 2
            if ($callback instanceof Closure) {
246 1
                return new ReflectionFunction($callback);
247
            }
248
249
            /** @var array{0: class-string|object, 1: string} $callback */
250
251 1
            return new ReflectionMethod(...$callback);
0 ignored issues
show
Bug introduced by
$callback is expanded, but the parameter $objectOrMethod of ReflectionMethod::__construct() does not expect variable arguments. ( Ignorable by Annotation )

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

251
            return new ReflectionMethod(/** @scrutinizer ignore-type */ ...$callback);
Loading history...
252
        }
253
254 1
        return new ReflectionClass($handler);
255
    }
256
257
    /**
258
     * {@inheritdoc}
259
     */
260 90
    public function setName(string $name) : RouteInterface
261
    {
262 90
        $this->name = $name;
263
264 90
        return $this;
265
    }
266
267
    /**
268
     * {@inheritdoc}
269
     */
270 15
    public function setHost(?string $host) : RouteInterface
271
    {
272 15
        $this->host = $host;
273
274 15
        return $this;
275
    }
276
277
    /**
278
     * {@inheritdoc}
279
     */
280 90
    public function setPath(string $path) : RouteInterface
281
    {
282 90
        $this->path = $path;
283
284 90
        return $this;
285
    }
286
287
    /**
288
     * {@inheritdoc}
289
     */
290 90
    public function setMethods(string ...$methods) : RouteInterface
291
    {
292 90
        foreach ($methods as &$method) {
293 87
            $method = strtoupper($method);
294
        }
295
296 90
        $this->methods = $methods;
297
298 90
        return $this;
299
    }
300
301
    /**
302
     * {@inheritdoc}
303
     */
304 90
    public function setRequestHandler(RequestHandlerInterface $requestHandler) : RouteInterface
305
    {
306 90
        $this->requestHandler = $requestHandler;
307
308 90
        return $this;
309
    }
310
311
    /**
312
     * {@inheritdoc}
313
     */
314 90
    public function setMiddlewares(MiddlewareInterface ...$middlewares) : RouteInterface
315
    {
316 90
        $this->middlewares = $middlewares;
317
318 90
        return $this;
319
    }
320
321
    /**
322
     * {@inheritdoc}
323
     */
324 90
    public function setAttributes(array $attributes) : RouteInterface
325
    {
326 90
        $this->attributes = $attributes;
327
328 90
        return $this;
329
    }
330
331
    /**
332
     * {@inheritdoc}
333
     */
334 12
    public function setSummary(string $summary) : RouteInterface
335
    {
336 12
        $this->summary = $summary;
337
338 12
        return $this;
339
    }
340
341
    /**
342
     * {@inheritdoc}
343
     */
344 12
    public function setDescription(string $description) : RouteInterface
345
    {
346 12
        $this->description = $description;
347
348 12
        return $this;
349
    }
350
351
    /**
352
     * {@inheritdoc}
353
     */
354 12
    public function setTags(string ...$tags) : RouteInterface
355
    {
356 12
        $this->tags = $tags;
357
358 12
        return $this;
359
    }
360
361
    /**
362
     * {@inheritdoc}
363
     */
364 3
    public function addPrefix(string $prefix) : RouteInterface
365
    {
366
        // https://github.com/sunrise-php/http-router/issues/26
367 3
        $prefix = rtrim($prefix, '/');
368
369 3
        $this->path = $prefix . $this->path;
370
371 3
        return $this;
372
    }
373
374
    /**
375
     * {@inheritdoc}
376
     */
377 2
    public function addSuffix(string $suffix) : RouteInterface
378
    {
379 2
        $this->path .= $suffix;
380
381 2
        return $this;
382
    }
383
384
    /**
385
     * {@inheritdoc}
386
     */
387 3
    public function addMethod(string ...$methods) : RouteInterface
388
    {
389 3
        foreach ($methods as $method) {
390 3
            $this->methods[] = strtoupper($method);
391
        }
392
393 3
        return $this;
394
    }
395
396
    /**
397
     * {@inheritdoc}
398
     */
399 5
    public function addMiddleware(MiddlewareInterface ...$middlewares) : RouteInterface
400
    {
401 5
        foreach ($middlewares as $middleware) {
402 5
            $this->middlewares[] = $middleware;
403
        }
404
405 5
        return $this;
406
    }
407
408
    /**
409
     * {@inheritdoc}
410
     */
411 10
    public function withAddedAttributes(array $attributes) : RouteInterface
412
    {
413 10
        $clone = clone $this;
414
415 10
        foreach ($attributes as $key => $value) {
416 1
            $clone->attributes[$key] = $value;
417
        }
418
419 10
        return $clone;
420
    }
421
422
    /**
423
     * {@inheritdoc}
424
     */
425 10
    public function handle(ServerRequestInterface $request) : ResponseInterface
426
    {
427 10
        $request = $request->withAttribute(self::ATTR_ROUTE, $this);
428
429
        /** @todo Must be removed from the 3.0.0 version */
430 10
        $request = $request->withAttribute(self::ATTR_NAME_FOR_ROUTE_NAME, $this->name);
0 ignored issues
show
Deprecated Code introduced by
The constant Sunrise\Http\Router\Rout...TTR_NAME_FOR_ROUTE_NAME has been deprecated: 2.9.0 ( Ignorable by Annotation )

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

430
        $request = $request->withAttribute(/** @scrutinizer ignore-deprecated */ self::ATTR_NAME_FOR_ROUTE_NAME, $this->name);

This class constant has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the constant will be removed from the class and what other constant to use instead.

Loading history...
431
432 10
        foreach ($this->attributes as $key => $value) {
433 1
            $request = $request->withAttribute($key, $value);
434
        }
435
436 10
        if (empty($this->middlewares)) {
437 8
            return $this->requestHandler->handle($request);
438
        }
439
440 2
        $handler = new QueueableRequestHandler($this->requestHandler);
441 2
        $handler->add(...$this->middlewares);
442
443 2
        return $handler->handle($request);
444
    }
445
}
446