RouteParams::getParams()   A
last analyzed

Complexity

Conditions 5
Paths 8

Size

Total Lines 44
Code Lines 27

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 24
CRAP Score 5

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 5
eloc 27
nc 8
nop 0
dl 0
loc 44
ccs 24
cts 24
cp 1
crap 5
rs 9.1768
c 3
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Gacela\Router\Entities;
6
7
use Gacela\Router\Exceptions\UnsupportedParamTypeException;
8
use ReflectionClass;
9
10
use function count;
11
12
final class RouteParams
13
{
14
    public const MANDATORY_PARAM_PATTERN = '#({.*[^?]})#';
15
    public const OPTIONAL_PARAM_PATTERN = '#(/?{.*\?})#';
16
17
    /** @var array<string, mixed> */
18
    private array $params;
19 97
20
    public function __construct(private Route $route)
21 97
    {
22
        $this->params = $this->getParams();
23
    }
24 95
25
    /**
26 95
     * @return array<string, mixed>
27
     */
28
    public function getAll(): array
29 97
    {
30
        return $this->params;
31 97
    }
32 97
33 97
    /**
34
     * @return array<string, mixed>
35 97
     */
36 97
    private function getParams(): array
37
    {
38 97
        $params = [];
39 97
        $pathParamKeys = [];
40
        $pathParamValues = [];
41 97
42 5
        preg_match($this->route->getPathPattern(), '/' . $this->route->path(), $pathParamKeys);
43
        preg_match($this->route->getPathPattern(), Request::fromGlobals()->path(), $pathParamValues);
44
45 97
        unset($pathParamValues[0], $pathParamKeys[0]);
46 97
        $pathParamKeys = array_map(static fn ($key) => trim($key, '{?}'), $pathParamKeys);
47 97
48 97
        while (count($pathParamValues) !== count($pathParamKeys)) {
49
            array_shift($pathParamKeys);
50 97
        }
51
52 42
        $pathParams = array_combine($pathParamKeys, $pathParamValues);
53
        $actionParams = (new ReflectionClass($this->route->controller()))
54 42
            ->getMethod($this->route->action())
55 1
            ->getParameters();
56
57
        foreach ($actionParams as $actionParam) {
58 41
            /** @var string|null $paramType */
59 41
            $paramType = $actionParam->getType()?->__toString();
60 39
61 39
            if ($paramType === null) {
62 39
                throw UnsupportedParamTypeException::nonTyped();
63 39
            }
64 39
65 39
            $paramName = $actionParam->getName();
66 39
            if (isset($pathParams[$paramName])) {
67
                $value = match ($paramType) {
68 38
                    'string' => $pathParams[$paramName],
69
                    'int' => (int)$pathParams[$paramName],
70
                    'float' => (float)$pathParams[$paramName],
71
                    'bool' => (bool)json_decode($pathParams[$paramName]),
72 95
                    default => throw UnsupportedParamTypeException::fromType($paramType),
73
                };
74
75
                $params[$paramName] = $value;
76
            }
77
        }
78
79
        return $params;
80
    }
81
}
82