Passed
Push — main ( 56c0cb...e79186 )
by Chema
09:06 queued 14s
created

Route::path()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
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
        if (!$this->methodMatches()) {
85 25
            return false;
86
        }
87
88 82
        if (!$this->pathMatches()) {
89
            return false;
90
        }
91
92 82
        return true;
93
    }
94
95 87
    public function methodMatches(): bool
96
    {
97 87
        return Request::fromGlobals()->isMethod($this->method);
98
    }
99
100 82
    private function pathMatches(): bool
101
    {
102 82
        $path = Request::fromGlobals()->path();
103
104 82
        return preg_match($this->getPathPattern(), $path)
105 82
            || preg_match($this->getPathPatternWithoutOptionals(), $path);
106
    }
107
108 2
    private function getPathPatternWithoutOptionals(): string
109
    {
110 2
        $pattern = preg_replace('#/({.*\?})#U', '(/(.*))?', $this->path);
111
112 2
        return '#^/' . $pattern . '$#';
113
    }
114
}
115