Passed
Pull Request — master (#225)
by Rustam
11:11 queued 08:15
created

Route::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 16
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 5
nc 1
nop 9
dl 0
loc 16
ccs 6
cts 6
cp 1
crap 1
rs 10
c 1
b 0
f 0

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Router;
6
7
use InvalidArgumentException;
8
use Stringable;
9
use Yiisoft\Router\Internal\MiddlewareFilter;
10
11
/**
12
 * Route defines a mapping from URL to callback / name and vice versa.
13
 */
14
final class Route implements Stringable
15
{
16
    /**
17
     * @var string[]
18
     * @psalm-var array<array-key, string>
19
     */
20
    private array $methods = [];
21
22
    /**
23
     * @var string[]
24
     */
25
    private array $hosts = [];
26
27
    /**
28
     * @var array|callable|string|null
29
     */
30
    private $action = null;
31
32
    /**
33
     * @var array[]|callable[]|string[]
34
     * @psalm-var list<array|callable|string>
35
     */
36
    private array $middlewares = [];
37
38
    /**
39
     * @psalm-var list<array|callable|string>|null
40
     */
41
    private ?array $enabledMiddlewaresCache = null;
42
43
    /**
44
     * @var array<array-key,string>
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<array-key,string> at position 2 could not be parsed: Unknown type name 'array-key' at position 2 in array<array-key,string>.
Loading history...
45
     */
46
    private array $defaults = [];
47
48
    /**
49
     * @param array|callable|string|null $action Action handler. It is a primary middleware definition that
50
     * should be invoked last for a matched route.
51
     * @param array<array-key,scalar|Stringable|null> $defaults Parameter default values indexed by parameter names.
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<array-key,scalar|Stringable|null> at position 2 could not be parsed: Unknown type name 'array-key' at position 2 in array<array-key,scalar|Stringable|null>.
Loading history...
52
     * @param bool $override Marks route as override. When added it will replace existing route with the same name.
53
     * @param array $disabledMiddlewares Excludes middleware from being invoked when action is handled.
54
     * It is useful to avoid invoking one of the parent group middleware for
55
     * a certain route.
56
     */
57 102
    public function __construct(
58
        array $methods,
59
        private string $pattern,
60
        private ?string $name = null,
61
        array|callable|string $action = null,
62
        array $middlewares = [],
63
        array $defaults = [],
64
        array $hosts = [],
65
        private bool $override = false,
66
        private array $disabledMiddlewares = [],
67
    ) {
68 102
        $this->setMethods($methods);
69 100
        $this->action = $action;
70 100
        $this->setMiddlewares($middlewares);
71 99
        $this->setHosts($hosts);
72 98
        $this->setDefaults($defaults);
73
    }
74
75
    /**
76
     * @return string[]
77
     */
78 32
    public function getMethods(): array
79
    {
80 32
        return $this->methods;
81
    }
82
83 26
    public function getAction(): array|callable|string|null
84
    {
85 26
        return $this->action;
86
    }
87
88 31
    public function getMiddlewares(): array
89
    {
90 31
        return $this->middlewares;
91
    }
92
93
    /**
94
     * @return string[]
95
     */
96 16
    public function getHosts(): array
97
    {
98 16
        return $this->hosts;
99
    }
100
101 2
    public function getDefaults(): array
102
    {
103 2
        return $this->defaults;
104
    }
105
106 27
    public function getPattern(): string
107
    {
108 27
        return $this->pattern;
109
    }
110
111 39
    public function getName(): string
112
    {
113 39
        return $this->name ??= (implode(', ', $this->methods) . ' ' . implode('|', $this->hosts) . $this->pattern);
114
    }
115
116 6
    public function isOverride(): bool
117
    {
118 6
        return $this->override;
119
    }
120
121 1
    public function getDisabledMiddlewares(): array
122
    {
123 1
        return $this->disabledMiddlewares;
124
    }
125
126
    /**
127
     * @return array[]|callable[]|string[]
128
     * @psalm-return list<array|callable|string>
129
     */
130 30
    public function getEnabledMiddlewares(): array
131
    {
132 30
        if ($this->enabledMiddlewaresCache !== null) {
133 1
            return $this->enabledMiddlewaresCache;
134
        }
135
136 30
        $this->enabledMiddlewaresCache = MiddlewareFilter::filter($this->middlewares, $this->disabledMiddlewares);
137 30
        if ($this->action !== null) {
138 20
            $this->enabledMiddlewaresCache[] = $this->action;
139
        }
140
141 30
        return $this->enabledMiddlewaresCache;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->enabledMiddlewaresCache returns the type null which is incompatible with the type-hinted return array.
Loading history...
142
    }
143
144 102
    public function setMethods(array $methods): self
145
    {
146 102
        if (empty($methods)) {
147 1
            throw new InvalidArgumentException('$methods cannot be empty.');
148
        }
149 101
        foreach ($methods as $method) {
150 101
            if (!is_string($method)) {
151 1
                throw new \InvalidArgumentException('Invalid $methods provided, list of string expected.');
152
            }
153 100
            $this->methods[] = $method;
154
        }
155 100
        return $this;
156
    }
157
158 99
    public function setHosts(array $hosts): self
159
    {
160 99
        $this->hosts = [];
161 99
        foreach ($hosts as $host) {
162 19
            if (!is_string($host)) {
163 1
                throw new \InvalidArgumentException('Invalid $hosts provided, list of string expected.');
164
            }
165 19
            $host = rtrim($host, '/');
166
167 19
            if ($host !== '' && !in_array($host, $this->hosts, true)) {
168 19
                $this->hosts[] = $host;
169
            }
170
        }
171
172 98
        return $this;
173
    }
174
175 7
    public function setAction(callable|array|string|null $action): self
176
    {
177 7
        $this->action = $action;
178 7
        return $this;
179
    }
180
181 100
    public function setMiddlewares(array $middlewares): self
182
    {
183 100
        $this->assertMiddlewares($middlewares);
184 99
        $this->middlewares = $middlewares;
185 99
        $this->enabledMiddlewaresCache = null;
186 99
        return $this;
187
    }
188
189 98
    public function setDefaults(array $defaults): self
190
    {
191
        /** @var mixed $value */
192 98
        foreach ($defaults as $key => $value) {
193 6
            if (!is_scalar($value) && !($value instanceof Stringable) && null !== $value) {
194 1
                throw new \InvalidArgumentException(
195 1
                    'Invalid $defaults provided, indexed array of scalar or `Stringable` or null expected.'
196 1
                );
197
            }
198 6
            $this->defaults[$key] = (string) $value;
199
        }
200 97
        return $this;
201
    }
202
203 23
    public function setPattern(string $pattern): self
204
    {
205 23
        $this->pattern = $pattern;
206 23
        return $this;
207
    }
208
209 17
    public function setName(?string $name): self
210
    {
211 17
        $this->name = $name;
212 17
        return $this;
213
    }
214
215 1
    public function setOverride(bool $override): self
216
    {
217 1
        $this->override = $override;
218 1
        return $this;
219
    }
220
221 2
    public function setDisabledMiddlewares(array $disabledMiddlewares): self
222
    {
223 2
        $this->disabledMiddlewares = $disabledMiddlewares;
224 2
        $this->enabledMiddlewaresCache = null;
225 2
        return $this;
226
    }
227
228 8
    public function __toString(): string
229
    {
230 8
        $result = $this->name === null
231 2
            ? ''
232 6
            : '[' . $this->name . '] ';
233
234 8
        if ($this->methods !== []) {
235 8
            $result .= implode(',', $this->methods) . ' ';
236
        }
237
238 8
        if (!empty($this->hosts)) {
239 4
            $quoted = array_map(static fn ($host) => preg_quote($host, '/'), $this->hosts);
240
241 4
            if (!preg_match('/' . implode('|', $quoted) . '/', $this->pattern)) {
242 4
                $result .= implode('|', $this->hosts);
243
            }
244
        }
245
246 8
        $result .= $this->pattern;
247
248 8
        return $result;
249
    }
250
251 3
    public function __debugInfo()
252
    {
253 3
        return [
254 3
            'name' => $this->name,
255 3
            'methods' => $this->methods,
256 3
            'pattern' => $this->pattern,
257 3
            'action' => $this->action,
258 3
            'hosts' => $this->hosts,
259 3
            'defaults' => $this->defaults,
260 3
            'override' => $this->override,
261 3
            'middlewares' => $this->middlewares,
262 3
            'disabledMiddlewares' => $this->disabledMiddlewares,
263 3
            'enabledMiddlewares' => $this->getEnabledMiddlewares(),
264 3
        ];
265
    }
266
267
    /**
268
     * @psalm-assert list<array|callable|string> $middlewares
269
     */
270 100
    private function assertMiddlewares(array $middlewares): void
271
    {
272
        /** @var mixed $middleware */
273 100
        foreach ($middlewares as $middleware) {
274 36
            if (is_string($middleware)) {
275 15
                continue;
276
            }
277
278 21
            if (is_callable($middleware) || is_array($middleware)) {
279 21
                continue;
280
            }
281
282 1
            throw new \InvalidArgumentException(
283 1
                'Invalid $middlewares provided, list of string or array or callable expected.'
284 1
            );
285
        }
286
    }
287
}
288