Passed
Push — main ( 49082a...35cbbb )
by Chema
01:05 queued 14s
created

Router::configure()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 12
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 1

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 1
eloc 8
nc 1
nop 1
dl 0
loc 12
rs 10
c 2
b 0
f 0
ccs 9
cts 9
cp 1
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Gacela\Router;
6
7
use Closure;
8
use Exception;
9
use Gacela\Container\Container;
10
use Gacela\Router\Entities\Route;
11
use Gacela\Router\Exceptions\NotFound404Exception;
12
use ReflectionFunction;
13
14
use function get_class;
15
use function is_callable;
16
use function is_null;
17
18
final class Router
19
{
20
    private Routes $routes;
21
    private Bindings $bindings;
22
    private Handlers $handlers;
23
24 92
    public function __construct(
25
        Closure $fn = null,
26
    ) {
27 92
        $this->routes = new Routes();
28 92
        $this->bindings = new Bindings();
29 92
        $this->handlers = new Handlers();
30
31 92
        if (!is_null($fn)) {
32 90
            $this->configure($fn);
33
        }
34
    }
35
36 92
    public function configure(Closure $fn): self
37
    {
38 92
        $params = array_map(fn ($param) => match ((string)$param->getType()) {
39 92
            Routes::class => $this->routes,
40 92
            Bindings::class => $this->bindings,
41 92
            Handlers::class => $this->handlers,
42 92
            default => null,
43 92
        }, (new ReflectionFunction($fn))->getParameters());
44
45 92
        $fn(...$params);
46
47 91
        return $this;
48
    }
49
50 91
    public function run(): void
51
    {
52
        try {
53 91
            echo self::findRoute($this->routes)->run($this->bindings);
54 15
        } catch (Exception $exception) {
55 15
            echo self::handleException($this->handlers, $exception);
56
        }
57
    }
58
59 91
    private static function findRoute(Routes $routes): Route
60
    {
61 91
        foreach ($routes->getAllRoutes() as $route) {
62 89
            if ($route->requestMatches()) {
63 84
                return $route;
64
            }
65
        }
66
67 7
        throw new NotFound404Exception();
68
    }
69
70 15
    private static function handleException(Handlers $handlers, Exception $exception): string
71
    {
72 15
        $handler = self::findHandler($handlers, $exception);
73
74 15
        if (is_callable($handler)) {
75 8
            return $handler($exception);
76
        }
77
78
        /** @var mixed $instance */
79 7
        $instance = Container::create($handler);
80
81 7
        if (is_callable($instance)) {
82 7
            return $instance($exception);
83
        }
84
85
        return '';
86
    }
87
88
    /**
89
     * @return callable|class-string
0 ignored issues
show
Documentation Bug introduced by
The doc comment callable|class-string at position 2 could not be parsed: Unknown type name 'class-string' at position 2 in callable|class-string.
Loading history...
90
     */
91 15
    private static function findHandler(Handlers $handlers, Exception $exception): string|callable
92
    {
93 15
        return $handlers->getAllHandlers()[get_class($exception)]
94 15
            ?? $handlers->getAllHandlers()[Exception::class];
95
    }
96
}
97