ResourceRoute::__construct()   B
last analyzed

Complexity

Conditions 8
Paths 9

Size

Total Lines 23
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 8

Importance

Changes 0
Metric Value
eloc 12
dl 0
loc 23
ccs 11
cts 11
cp 1
rs 8.4444
c 0
b 0
f 0
cc 8
nc 9
nop 3
crap 8
1
<?php
2
3
namespace kalanis\Restful\Application\Routes;
4
5
6
use kalanis\Restful\Application\IResourceRouter;
7
use Nette\Application\Routers\Route;
8
use Nette\Http;
9
use Nette\Utils\Strings;
10
11
12
/**
13
 * ResourceRoute
14
 * @package kalanis\Restful\Routes
15
 */
16 1
class ResourceRoute extends Route implements IResourceRouter
17
{
18
19
    /** @var array<int, string> */
20
    public array $actionDictionary = [];
21
22
    /** @var array<string, int> */
23
    private array $methodDictionary = [
24
        Http\IRequest::Get => self::GET,
25
        Http\IRequest::Post => self::POST,
26
        Http\IRequest::Put => self::PUT,
27
        Http\IRequest::Head => self::HEAD,
28
        Http\IRequest::Delete => self::DELETE,
29
        'PATCH' => self::PATCH,
30
        'OPTIONS' => self::OPTIONS
31
    ];
32
33
    /**
34
     * @param string $mask
35
     * @param array<string, string|array<string>>|string $metadata
36
     * @param int $flags all available route types with bitwise add
37
     */
38
    public function __construct(
39
        string       $mask,
40
        array|string $metadata = [],
41
        int          $flags = IResourceRouter::GET
42
    )
43
    {
44 1
        if (isset($metadata['action']) && is_array($metadata['action'])) {
45 1
            $this->actionDictionary = $metadata['action'];
46 1
            $metadata['action'] = 'default';
47
        } else {
48 1
            $action = is_array($metadata) && !empty($metadata['action']) ? strval($metadata['action']) : 'default';
49 1
            if (is_string($metadata)) {
50 1
                $metadataParts = explode(':', $metadata);
51 1
                $action = end($metadataParts);
52
            }
53 1
            foreach ($this->methodDictionary as $methodName => $methodFlag) {
54 1
                if (($flags & $methodFlag) == $methodFlag) {
55 1
                    $this->actionDictionary[$methodFlag] = $action;
56
                }
57
            }
58
        }
59
60 1
        parent::__construct($mask, $metadata);
61 1
    }
62
63
    /**
64
     * Get action dictionary
65
     * @return array<int, string>
66
     */
67
    public function getActionDictionary(): array
68
    {
69 1
        return $this->actionDictionary;
70
    }
71
72
    /**
73
     * Set action dictionary
74
     * @param array<int, string> $actionDictionary
75
     * @return $this
76
     */
77
    public function setActionDictionary(array $actionDictionary): static
78
    {
79
        $this->actionDictionary = $actionDictionary;
80
        return $this;
81
    }
82
83
    /**
84
     * @param Http\IRequest $httpRequest
85
     * @return array<string, mixed>|null
86
     */
87
    public function match(Http\IRequest $httpRequest): ?array
88
    {
89 1
        $appRequest = parent::match($httpRequest);
90 1
        if (is_null($appRequest)) {
91 1
            return null;
92
        }
93
94
        // Check requested method
95 1
        $methodFlag = $this->getMethod($httpRequest);
96 1
        if (is_null($methodFlag) || !$this->isMethod($methodFlag)) {
97 1
            return null;
98
        }
99
100
        // If there is action dictionary, set method
101 1
        if (!empty($this->actionDictionary)) {
102 1
            $appRequest['action'] = $this->actionDictionary[$methodFlag];
103 1
            $appRequest['action'] = self::formatActionName($this->actionDictionary[$methodFlag], $appRequest);
104
        }
105
106 1
        return $appRequest;
107
    }
108
109
    /**
110
     * Get request method flag
111
     */
112
    public function getMethod(Http\IRequest $httpRequest): ?int
113
    {
114 1
        $method = strtoupper($httpRequest->getMethod());
115 1
        if (!isset($this->methodDictionary[$method])) {
116
            return null;
117
        }
118 1
        return $this->methodDictionary[$method];
119
    }
120
121
    /**
122
     * Is this route mapped to given method
123
     */
124
    public function isMethod(int $method): bool
125
    {
126 1
        $common = [self::CRUD, self::RESTFUL];
127 1
        $isActionDefined = !empty($this->actionDictionary) && !in_array($method, $common)
128 1
            ? isset($this->actionDictionary[$method])
129 1
            : true;
130
//        return ($this->getFlag() & $method) == $method && $isActionDefined; // getFlag is somewhere else now
131 1
        return $isActionDefined;
132
    }
133
134
    /**
135
     * Format action name
136
     * @param string $action
137
     * @param array<string|int, mixed> $parameters
138
     * @return string
139
     */
140
    protected static function formatActionName(string $action, array $parameters): string
141
    {
142 1
        return Strings::replace($action, "@<([0-9a-zA-Z_-]+)>@i", function ($m) use ($parameters) {
143
            $key = strtolower((string) $m[1]);
144
            return $parameters[$key] ?? '';
145 1
        });
146
    }
147
}
148