Passed
Push — main ( e79186...65f6d6 )
by Chema
01:07 queued 14s
created

Route   A

Complexity

Total Complexity 16

Size/Duplication

Total Lines 89
Duplicated Lines 0 %

Test Coverage

Coverage 94.12%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 23
dl 0
loc 89
ccs 32
cts 34
cp 0.9412
rs 10
c 1
b 0
f 0
wmc 16

11 Methods

Rating   Name   Duplication   Size   Complexity  
A action() 0 3 1
A method() 0 3 1
A path() 0 3 1
A getPathPattern() 0 5 1
A controller() 0 3 1
A __construct() 0 6 1
A run() 0 18 4
A requestMatches() 0 3 2
A methodMatches() 0 3 1
A getPathPatternWithoutOptionals() 0 5 1
A pathMatches() 0 6 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Gacela\Router\Entities;
6
7
use Gacela\Resolver\InstanceCreator;
8
use Gacela\Router\Bindings;
9
10
use Gacela\Router\Exceptions\UnsupportedResponseTypeException;
11
use Stringable;
12
13
use function is_object;
14
use function is_string;
15
16
final class Route
17
{
18
    /**
19
     * @param object|class-string $controller
0 ignored issues
show
Documentation Bug introduced by
The doc comment object|class-string at position 2 could not be parsed: Unknown type name 'class-string' at position 2 in object|class-string.
Loading history...
20
     */
21 87
    public function __construct(
22
        private string $method,
23
        private string $path,
24
        private object|string $controller,
25
        private string $action = '__invoke',
26
    ) {
27 87
    }
28
29
    /**
30
     * @psalm-suppress MixedMethodCall
31
     */
32 82
    public function run(Bindings $bindings): string|Stringable
33
    {
34 82
        $params = (new RouteParams($this))->asArray();
35
36 82
        if (!is_object($this->controller)) {
37 59
            $creator = new InstanceCreator($bindings->getAllBindings());
38 59
            $controller = $creator->createByClassName($this->controller);
39 59
            $response = $controller->{$this->action}(...$params);
40
        } else {
41
            /** @var string|Stringable $response */
42 23
            $response = $this->controller->{$this->action}(...$params);
43
        }
44
45 78
        if (!is_string($response) && !($response instanceof Stringable)) {
46 4
            throw UnsupportedResponseTypeException::fromType($response);
47
        }
48
49 74
        return $response;
50
    }
51
52 82
    public function path(): string
53
    {
54 82
        return $this->path;
55
    }
56
57
    public function method(): string
58
    {
59
        return $this->method;
60
    }
61
62
    /**
63
     * @return object|class-string
0 ignored issues
show
Documentation Bug introduced by
The doc comment object|class-string at position 2 could not be parsed: Unknown type name 'class-string' at position 2 in object|class-string.
Loading history...
64
     */
65 82
    public function controller(): object|string
66
    {
67 82
        return $this->controller;
68
    }
69
70 82
    public function action(): string
71
    {
72 82
        return $this->action;
73
    }
74
75 82
    public function getPathPattern(): string
76
    {
77 82
        $pattern = preg_replace('#({.*})#U', '(.*)', $this->path);
78
79 82
        return '#^/' . $pattern . '$#';
80
    }
81
82 87
    public function requestMatches(): bool
83
    {
84 87
        return $this->methodMatches() && $this->pathMatches();
85
    }
86
87 87
    public function methodMatches(): bool
88
    {
89 87
        return Request::fromGlobals()->isMethod($this->method);
90
    }
91
92 82
    private function pathMatches(): bool
93
    {
94 82
        $path = Request::fromGlobals()->path();
95
96 82
        return preg_match($this->getPathPattern(), $path)
97 82
            || preg_match($this->getPathPatternWithoutOptionals(), $path);
98
    }
99
100 2
    private function getPathPatternWithoutOptionals(): string
101
    {
102 2
        $pattern = preg_replace('#/({.*\?})#U', '(/(.*))?', $this->path);
103
104 2
        return '#^/' . $pattern . '$#';
105
    }
106
}
107