Route::generate()   A
last analyzed

Complexity

Conditions 3
Paths 2

Size

Total Lines 18
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 10
c 0
b 0
f 0
dl 0
loc 18
rs 9.9332
cc 3
nc 2
nop 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Furious\Router\Route;
6
7
use Furious\Router\Exception\InvalidArgumentException;
8
use Furious\Router\Exception\InvalidMethodException;
9
use Furious\Router\Http\Methods;
10
use Furious\Router\Match\RouteMatch;
11
use Furious\Router\Pattern\PatternReplacer;
12
use Psr\Http\Message\ServerRequestInterface;
13
use function in_array;
14
15
final class Route implements RouteInterface
16
{
17
    private string $name;
18
    private string $pattern;
19
    private string $action;
20
    private array $tokens;
21
    private array $methods;
22
23
    public function __construct(
24
        string $name, string $pattern, string $action,
25
        array $methods, array $tokens = []
26
    )
27
    {
28
        $this->name = $name;
29
        $this->pattern = $pattern;
30
        $this->action = $action;
31
        $this->tokens = $tokens;
32
        $this->validateMethods($methods);
33
        $this->methods = $methods;
34
    }
35
36
    public function generate(string $name, array $params = []): ?string
37
    {
38
        $arguments = array_filter($params);
39
40
        if ($name !== $this->name) {
41
            return null;
42
        }
43
44
        /** @var string|null $url */
45
        $url = preg_replace_callback('~\{([^\}]+)\}~', function (array $matches) use (&$arguments) {
46
            $argument = $matches[1];
47
            if (!array_key_exists($argument, $arguments)) {
48
                throw new InvalidArgumentException('Missing parameter "' . $argument . '"');
49
            }
50
            return $arguments[$argument];
51
        }, $this->pattern);
52
53
        return $url;
54
    }
55
56
    public function match(ServerRequestInterface $request): ?RouteMatch
57
    {
58
        if (!$this->matchMethod($request->getMethod())) {
59
            return null;
60
        }
61
62
        $pattern  = (new PatternReplacer())->replace($this->pattern, $this->tokens);
63
64
        $path = $request->getUri()->getPath();
65
66
        if (!preg_match('~^' . $pattern . '$~i', $path, $matches)) {
67
            return null;
68
        }
69
70
        return new RouteMatch(
71
            $this->name,
72
            $this->action,
73
            array_filter(
74
                $matches, 'is_string',
75
                ARRAY_FILTER_USE_KEY
76
            )
77
        );
78
    }
79
80
    private function matchMethod(string $method): bool
81
    {
82
        return in_array($method, $this->methods, true);
83
    }
84
85
    private function validateMethods(array $methods): void
86
    {
87
        foreach ($methods as $method) {
88
            if (!in_array($method, Methods::LIST)) {
89
                throw new InvalidMethodException($method);
90
            }
91
        }
92
    }
93
}