Issues (47)

src/Router/Entities/Route.php (4 issues)

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Gacela\Router\Entities;
6
7
use Gacela\Container\Container;
8
use Gacela\Router\Configure\Bindings;
9
use Gacela\Router\Exceptions\UnsupportedResponseTypeException;
10
use Gacela\Router\Middleware\MiddlewareInterface;
11
use Gacela\Router\Validators\PathPatternGenerator;
12
use Stringable;
13
14
use function is_object;
15
use function is_string;
16
17
final class Route
18
{
19
    /** @var list<MiddlewareInterface|class-string<MiddlewareInterface>|string> */
20 102
    private array $middlewares = [];
21
22
    /**
23
     * @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...
24
     */
25
    public function __construct(
26
        private readonly string $method,
27 102
        private readonly string $path,
28
        private readonly object|string $controller,
29
        private readonly string $action = '__invoke',
30
        private ?string $pathPattern = null,
31
    ) {
32 97
    }
33
34 97
    /**
35
     * @psalm-suppress MixedMethodCall
36 95
     */
37 70
    public function run(Bindings $bindings): string|Stringable
38
    {
39 70
        $params = (new RouteParams($this))->getAll();
40 70
41
        if (!is_object($this->controller)) {
42
            $creator = new Container($bindings->getAllBindings());
43 25
            /** @var object $controller */
44
            $controller = $creator->get($this->controller);
45
            $response = $controller->{$this->action}(...$params);
46 90
        } else {
47 4
            /** @var string|Stringable $response */
48
            $response = $this->controller->{$this->action}(...$params);
49
        }
50 86
51
        if (!is_string($response) && !($response instanceof Stringable)) {
52
            throw UnsupportedResponseTypeException::fromType($response);
53 97
        }
54
55 97
        return $response;
56
    }
57
58
    public function path(): string
59
    {
60
        return $this->path;
61 97
    }
62
63 97
    /**
64
     * @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...
65
     */
66 97
    public function controller(): object|string
67
    {
68 97
        return $this->controller;
69
    }
70
71 97
    public function action(): string
72
    {
73 97
        return $this->action;
74 97
    }
75
76
    /**
77 97
     * @param MiddlewareInterface|class-string<MiddlewareInterface>|string $middleware
0 ignored issues
show
Documentation Bug introduced by
The doc comment MiddlewareInterface|clas...lewareInterface>|string at position 2 could not be parsed: Unknown type name 'class-string' at position 2 in MiddlewareInterface|class-string<MiddlewareInterface>|string.
Loading history...
78
     */
79
    public function middleware(MiddlewareInterface|string $middleware): self
80 102
    {
81
        $this->middlewares[] = $middleware;
82 102
        return $this;
83
    }
84
85 102
    /**
86
     * @return list<MiddlewareInterface|class-string<MiddlewareInterface>|string>
87 102
     */
88
    public function getMiddlewares(): array
89
    {
90 97
        return $this->middlewares;
91
    }
92 97
93
    public function getPathPattern(): string
94 97
    {
95
        if ($this->pathPattern === null) {
96
            $this->pathPattern = PathPatternGenerator::generate($this->path);
97
        }
98
99
        return $this->pathPattern;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->pathPattern could return the type null which is incompatible with the type-hinted return string. Consider adding an additional type-check to rule them out.
Loading history...
100
    }
101
102 97
    public function requestMatches(): bool
103
    {
104 97
        return $this->methodMatches() && $this->pathMatches();
105 1
    }
106
107
    private function methodMatches(): bool
108 97
    {
109 97
        return Request::fromGlobals()->isMethod($this->method);
110 97
    }
111 97
112 43
    private function pathMatches(): bool
113 93
    {
114 8
        $path = Request::fromGlobals()->path();
115
116 93
        return (bool)preg_match($this->getPathPattern(), $path);
117
    }
118
}
119