Passed
Push — main ( 50aede...a9f24b )
by Chema
01:07 queued 13s
created

Route   A

Complexity

Total Complexity 15

Size/Duplication

Total Lines 85
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 22
c 2
b 0
f 0
dl 0
loc 85
ccs 32
cts 32
cp 1
rs 10
wmc 15

10 Methods

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