Passed
Pull Request — main (#5)
by Chema
02:25
created

Route::methodMatches()   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 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 3
rs 10
ccs 2
cts 2
cp 1
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Gacela\Router;
6
7
use Gacela\Resolver\InstanceCreator;
8
9
use function is_object;
10
11
/**
12
 * @method static get(string $path, object|string $controller, string $action = '__invoke')
13
 * @method static head(string $path, object|string $controller, string $action = '__invoke')
14
 * @method static connect(string $path, object|string $controller, string $action = '__invoke')
15
 * @method static post(string $path, object|string $controller, string $action = '__invoke')
16
 * @method static delete(string $path, object|string $controller, string $action = '__invoke')
17
 * @method static options(string $path, object|string $controller, string $action = '__invoke')
18
 * @method static patch(string $path, object|string $controller, string $action = '__invoke')
19
 * @method static put(string $path, object|string $controller, string $action = '__invoke')
20
 * @method static trace(string $path, object|string $controller, string $action = '__invoke')
21
 */
22
final class Route
23
{
24
    /**
25
     * @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...
26
     */
27 52
    public function __construct(
28
        private string $method,
29
        private string $path,
30
        private object|string $controller,
31
        private string $action = '__invoke',
32
    ) {
33 52
    }
34
35
    /**
36
     * @param callable(RoutingConfigurator):void $fn
37
     */
38 53
    public static function configure(callable $fn): void
39
    {
40 53
        $routingConfigurator = new RoutingConfigurator();
41 53
        $fn($routingConfigurator);
42
43 52
        foreach ($routingConfigurator->routes() as $route) {
44 52
            if ($route->requestMatches()) {
45 50
                echo $route->run($routingConfigurator);
46 50
                break;
47
            }
48
        }
49
    }
50
51
    /**
52
     * @psalm-suppress MixedMethodCall
53
     */
54 50
    public function run(RoutingConfigurator $routingConfigurator): string
55
    {
56 50
        $params = (new RouteParams($this))->asArray();
57
58 50
        if (is_object($this->controller)) {
59
            return (string)$this->controller
60
                ->{$this->action}(...$params);
61
        }
62
63 50
        $creator = new InstanceCreator($routingConfigurator->getMappingInterfaces());
64 50
        $controller = $creator->createByClassName($this->controller);
65
66 50
        return (string)$controller->{$this->action}(...$params);
67
    }
68
69 50
    public function path(): string
70
    {
71 50
        return $this->path;
72
    }
73
74
    /**
75
     * @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...
76
     */
77 50
    public function controller(): object|string
78
    {
79 50
        return $this->controller;
80
    }
81
82 50
    public function action(): string
83
    {
84 50
        return $this->action;
85
    }
86
87 51
    public function getPathPattern(): string
88
    {
89 51
        $pattern = preg_replace('#({.*})#U', '(.*)', $this->path);
90
91 51
        return '#^/' . $pattern . '$#';
92
    }
93
94 52
    private function requestMatches(): bool
95
    {
96 52
        if (!$this->methodMatches()) {
97 9
            return false;
98
        }
99
100 51
        if (!$this->pathMatches()) {
101 1
            return false;
102
        }
103
104 50
        return true;
105
    }
106
107 52
    private function methodMatches(): bool
108
    {
109 52
        return Request::instance()->isMethod($this->method);
110
    }
111
112 51
    private function pathMatches(): bool
113
    {
114 51
        $path = Request::instance()->path();
115
116 51
        return preg_match($this->getPathPattern(), $path)
117 51
            || preg_match($this->getPathPatternWithoutOptionals(), $path);
118
    }
119
120 3
    private function getPathPatternWithoutOptionals(): string
121
    {
122 3
        $pattern = preg_replace('#/({.*\?})#U', '(/(.*))?', $this->path);
123
124 3
        return '#^/' . $pattern . '$#';
125
    }
126
}
127