Test Failed
Pull Request — master (#225)
by Alexander
12:36
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 89
     * 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 89
     * It is useful to avoid invoking one of the parent group middleware for
55
     * a certain route.
56 77
     */
57
    public function __construct(
58 77
        array $methods,
59
        private string $pattern,
60
        private ?string $name = null,
61 9
        array|callable|string $action = null,
62
        array $middlewares = [],
63 9
        array $defaults = [],
64
        array $hosts = [],
65
        private bool $override = false,
66 4
        private array $disabledMiddlewares = [],
67
    ) {
68 4
        $this->setMethods($methods);
69
        $this->action = $action;
70
        $this->setMiddlewares($middlewares);
71 1
        $this->setHosts($hosts);
72
        $this->setDefaults($defaults);
73 1
    }
74
75
    /**
76 1
     * @return string[]
77
     */
78 1
    public function getMethods(): array
79
    {
80
        return $this->methods;
81 1
    }
82
83 1
    public function getAction(): array|callable|string|null
84
    {
85
        return $this->action;
86 9
    }
87
88 9
    public function getMiddlewares(): array
89
    {
90
        return $this->middlewares;
91
    }
92
93
    /**
94 89
     * @return string[]
95
     */
96 89
    public function getHosts(): array
97
    {
98
        return $this->hosts;
99 25
    }
100
101 25
    public function getDefaults(): array
102 25
    {
103 25
        return $this->defaults;
104
    }
105
106 24
    public function getPattern(): string
107
    {
108 24
        return $this->pattern;
109 24
    }
110 24
111
    public function getName(): string
112
    {
113 11
        return $this->name ??= (implode(', ', $this->methods) . ' ' . implode('|', $this->hosts) . $this->pattern);
114
    }
115 11
116
    public function isOverride(): bool
117
    {
118 15
        return $this->override;
119
    }
120 15
121 15
    public function getDisabledMiddlewares(): array
122
    {
123 15
        return $this->disabledMiddlewares;
124 15
    }
125
126 15
    /**
127 14
     * @return array[]|callable[]|string[]
128
     * @psalm-return list<array|callable|string>
129
     */
130
    public function getEnabledMiddlewares(): array
131 15
    {
132
        if ($this->enabledMiddlewaresCache !== null) {
133
            return $this->enabledMiddlewaresCache;
134
        }
135
136
        $this->enabledMiddlewaresCache = MiddlewareFilter::filter($this->middlewares, $this->disabledMiddlewares);
137 4
        if ($this->action !== null) {
138
            $this->enabledMiddlewaresCache[] = $this->action;
139 4
        }
140 4
141 4
        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
    public function setMethods(array $methods): self
145
    {
146
        if (empty($methods)) {
147
            throw new InvalidArgumentException('$methods cannot be empty.');
148
        }
149 5
        foreach ($methods as $method) {
150
            if (!is_string($method)) {
151 5
                throw new \InvalidArgumentException('Invalid $methods provided, list of string expected.');
152 5
            }
153 5
            $this->methods[] = $method;
154
        }
155
        return $this;
156
    }
157
158
    public function setHosts(array $hosts): self
159
    {
160 28
        $this->hosts = [];
161
        foreach ($hosts as $host) {
162 28
            if (!is_string($host)) {
163 1
                throw new \InvalidArgumentException('Invalid $hosts provided, list of string expected.');
164
            }
165
            $host = rtrim($host, '/');
166 27
167 27
            if ($host !== '' && !in_array($host, $this->hosts, true)) {
168 27
                $this->hosts[] = $host;
169 27
            }
170 27
        }
171
172 27
        return $this;
173
    }
174 27
175
    public function setAction(callable|array|string|null $action): self
176
    {
177
        $this->action = $action;
178
        return $this;
179
    }
180
181 27
    public function setMiddlewares(array $middlewares): self
182
    {
183 27
        $this->assertMiddlewares($middlewares);
184 1
        $this->middlewares = $middlewares;
185
        $this->enabledMiddlewaresCache = null;
186
        return $this;
187 26
    }
188 26
189 26
    public function setDefaults(array $defaults): self
190 26
    {
191 26
        /** @var mixed $value */
192
        foreach ($defaults as $key => $value) {
193 26
            if (!is_scalar($value) && !($value instanceof Stringable) && null !== $value) {
194
                throw new \InvalidArgumentException(
195 26
                    'Invalid $defaults provided, indexed array of scalar or `Stringable` or null expected.'
196
                );
197
            }
198
            $this->defaults[$key] = (string) $value;
199
        }
200
        return $this;
201 30
    }
202
203 30
    public function setPattern(string $pattern): self
204 30
    {
205 30
        $this->pattern = $pattern;
206 30
        return $this;
207
    }
208
209
    public function setName(?string $name): self
210
    {
211
        $this->name = $name;
212
        return $this;
213
    }
214 6
215
    public function setOverride(bool $override): self
216 6
    {
217 6
        $this->override = $override;
218 6
        return $this;
219 6
    }
220 6
221
    public function setDisabledMiddlewares(array $disabledMiddlewares): self
222 6
    {
223
        $this->disabledMiddlewares = $disabledMiddlewares;
224 6
        $this->enabledMiddlewaresCache = null;
225
        return $this;
226
    }
227
228
    public function __toString(): string
229
    {
230
        $result = $this->name === null
231
            ? ''
232
            : '[' . $this->name . '] ';
233
234
        if ($this->methods !== []) {
235
            $result .= implode(',', $this->methods) . ' ';
236
        }
237
238
        if (!empty($this->hosts)) {
239
            $quoted = array_map(static fn ($host) => preg_quote($host, '/'), $this->hosts);
240
241
            if (!preg_match('/' . implode('|', $quoted) . '/', $this->pattern)) {
242
                $result .= implode('|', $this->hosts);
243
            }
244
        }
245
246
        $result .= $this->pattern;
247 67
248
        return $result;
249 67
    }
250 67
251 36
    public function __debugInfo()
252 67
    {
253 67
        return [
254 67
            'name' => $this->name,
255 67
            'methods' => $this->methods,
256 67
            'pattern' => $this->pattern,
257 67
            'action' => $this->action,
258 67
            'hosts' => $this->hosts,
259 67
            'defaults' => $this->defaults,
260 67
            'override' => $this->override,
261 67
            'middlewares' => $this->middlewares,
262
            'disabledMiddlewares' => $this->disabledMiddlewares,
263
            'enabledMiddlewares' => $this->getEnabledMiddlewares(),
264 5
        ];
265
    }
266 5
267 2
    /**
268 3
     * @psalm-assert list<array|callable|string> $middlewares
269
     */
270 5
    private function assertMiddlewares(array $middlewares): void
271 5
    {
272
        /** @var mixed $middleware */
273
        foreach ($middlewares as $middleware) {
274 5
            if (is_string($middleware)) {
275 2
                continue;
276
            }
277 2
278 2
            if (is_callable($middleware) || is_array($middleware)) {
279
                continue;
280
            }
281
282 5
            throw new \InvalidArgumentException(
283
                'Invalid $middlewares provided, list of string or array or callable expected.'
284 5
            );
285
        }
286
    }
287
}
288