Passed
Pull Request — master (#103)
by
unknown
08:33
created

Route::disableMiddleware()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 1
dl 0
loc 5
ccs 0
cts 4
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Router;
6
7
use RuntimeException;
8
use Yiisoft\Http\Method;
9
use Yiisoft\Middleware\Dispatcher\MiddlewareDispatcher;
10
11
/**
12
 * Route defines a mapping from URL to callback / name and vice versa.
13
 */
14
final class Route
15
{
16
    private ?string $name = null;
17
    /** @var string[] */
18
    private array $methods;
19
    private string $pattern;
20
    private ?string $host = null;
21
    private bool $override = false;
22
    private ?MiddlewareDispatcher $dispatcher;
23
    private bool $actionAdded = false;
24
    private array $middlewareDefinitions = [];
25
    private array $disabledMiddlewareDefinitions = [];
26
    private array $defaults = [];
27
28 30
    private function __construct(?MiddlewareDispatcher $dispatcher = null)
29
    {
30 30
        $this->dispatcher = $dispatcher;
31 30
    }
32
33 5
    public function injectDispatcher(MiddlewareDispatcher $dispatcher): void
34
    {
35 5
        $this->dispatcher = $dispatcher;
36 5
    }
37
38 2
    public function withDispatcher(MiddlewareDispatcher $dispatcher): self
39
    {
40 2
        $route = clone $this;
41 2
        $route->dispatcher = $dispatcher;
42 2
        return $route;
43
    }
44
45 6
    public function getDispatcherWithMiddlewares(): MiddlewareDispatcher
46
    {
47 6
        if ($this->dispatcher->hasMiddlewares()) {
0 ignored issues
show
Bug introduced by
The method hasMiddlewares() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

47
        if ($this->dispatcher->/** @scrutinizer ignore-call */ hasMiddlewares()) {

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
48
            return $this->dispatcher;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->dispatcher could return the type null which is incompatible with the type-hinted return Yiisoft\Middleware\Dispatcher\MiddlewareDispatcher. Consider adding an additional type-check to rule them out.
Loading history...
49
        }
50
51 6
        foreach ($this->middlewareDefinitions as $index => $definition) {
52 6
            if (in_array($definition, $this->disabledMiddlewareDefinitions, true)) {
53
                unset($this->middlewareDefinitions[$index]);
54
            }
55
        }
56
57 6
        return $this->dispatcher = $this->dispatcher->withMiddlewares($this->middlewareDefinitions);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->dispatcher...>middlewareDefinitions) could return the type null which is incompatible with the type-hinted return Yiisoft\Middleware\Dispatcher\MiddlewareDispatcher. Consider adding an additional type-check to rule them out.
Loading history...
58
    }
59
60 10
    public function hasDispatcher(): bool
61
    {
62 10
        return $this->dispatcher !== null;
63
    }
64
65
    /**
66
     * @param string $pattern
67
     * @param MiddlewareDispatcher|null $dispatcher
68
     *
69
     * @return self
70
     */
71 20
    public static function get(string $pattern, ?MiddlewareDispatcher $dispatcher = null): self
72
    {
73 20
        return self::methods([Method::GET], $pattern, $dispatcher);
74
    }
75
76
    /**
77
     * @param string $pattern
78
     * @param MiddlewareDispatcher|null $dispatcher
79
     *
80
     * @return self
81
     */
82 3
    public static function post(string $pattern, ?MiddlewareDispatcher $dispatcher = null): self
83
    {
84 3
        return self::methods([Method::POST], $pattern, $dispatcher);
85
    }
86
87
    /**
88
     * @param string $pattern
89
     * @param MiddlewareDispatcher|null $dispatcher
90
     *
91
     * @return self
92
     */
93 1
    public static function put(string $pattern, ?MiddlewareDispatcher $dispatcher = null): self
94
    {
95 1
        return self::methods([Method::PUT], $pattern, $dispatcher);
96
    }
97
98
    /**
99
     * @param string $pattern
100
     * @param MiddlewareDispatcher|null $dispatcher
101
     *
102
     * @return self
103
     */
104 1
    public static function delete(string $pattern, ?MiddlewareDispatcher $dispatcher = null): self
105
    {
106 1
        return self::methods([Method::DELETE], $pattern, $dispatcher);
107
    }
108
109
    /**
110
     * @param string $pattern
111
     * @param MiddlewareDispatcher|null $dispatcher
112
     *
113
     * @return self
114
     */
115 1
    public static function patch(string $pattern, ?MiddlewareDispatcher $dispatcher = null): self
116
    {
117 1
        return self::methods([Method::PATCH], $pattern, $dispatcher);
118
    }
119
120
    /**
121
     * @param string $pattern
122
     * @param MiddlewareDispatcher|null $dispatcher
123
     *
124
     * @return self
125
     */
126 1
    public static function head(string $pattern, ?MiddlewareDispatcher $dispatcher = null): self
127
    {
128 1
        return self::methods([Method::HEAD], $pattern, $dispatcher);
129
    }
130
131
    /**
132
     * @param string $pattern
133
     * @param MiddlewareDispatcher|null $dispatcher
134
     *
135
     * @return self
136
     */
137 1
    public static function options(string $pattern, ?MiddlewareDispatcher $dispatcher = null): self
138
    {
139 1
        return self::methods([Method::OPTIONS], $pattern, $dispatcher);
140
    }
141
142
    /**
143
     * @param string $pattern
144
     * @param MiddlewareDispatcher|null $dispatcher
145
     *
146
     * @return self
147
     */
148 1
    public static function anyMethod(string $pattern, ?MiddlewareDispatcher $dispatcher = null): self
149
    {
150 1
        return self::methods(Method::ALL, $pattern, $dispatcher);
151
    }
152
153
    /**
154
     * @param array $methods
155
     * @param string $pattern
156
     * @param MiddlewareDispatcher|null $dispatcher
157
     *
158
     * @return self
159
     */
160 30
    public static function methods(
161
        array $methods,
162
        string $pattern,
163
        ?MiddlewareDispatcher $dispatcher = null
164
    ): self {
165 30
        $route = new self($dispatcher);
166 30
        $route->methods = $methods;
167 30
        $route->pattern = $pattern;
168
169 30
        return $route;
170
    }
171
172 9
    public function name(string $name): self
173
    {
174 9
        $route = clone $this;
175 9
        $route->name = $name;
176 9
        return $route;
177
    }
178
179 7
    public function pattern(string $pattern): self
180
    {
181 7
        $new = clone $this;
182 7
        $new->pattern = $pattern;
183 7
        return $new;
184
    }
185
186 2
    public function host(string $host): self
187
    {
188 2
        $route = clone $this;
189 2
        $route->host = rtrim($host, '/');
190 2
        return $route;
191
    }
192
193
    /**
194
     * Marks route as override. When added it will replace existing route with the same name.
195
     *
196
     * @return self
197
     */
198 2
    public function override(): self
199
    {
200 2
        $route = clone $this;
201 2
        $route->override = true;
202 2
        return $route;
203
    }
204
205
    /**
206
     * Parameter default values indexed by parameter names.
207
     *
208
     * @param array $defaults
209
     *
210
     * @return self
211
     */
212 1
    public function defaults(array $defaults): self
213
    {
214 1
        $route = clone $this;
215 1
        $route->defaults = $defaults;
216 1
        return $route;
217
    }
218
219
    /**
220
     * Appends a handler middleware definition that should be invoked for a matched route.
221
     * First added handler will be executed first.
222
     *
223
     * @param mixed $middlewareDefinition
224
     *
225
     * @return self
226
     */
227 2
    public function middleware($middlewareDefinition): self
228
    {
229 2
        if ($this->actionAdded) {
230
            throw new RuntimeException('middleware() can not be used after action().');
231
        }
232 2
        $route = clone $this;
233 2
        array_unshift($route->middlewareDefinitions, $middlewareDefinition);
234 2
        return $route;
235
    }
236
237
    /**
238
     * Prepends a handler middleware definition that should be invoked for a matched route.
239
     * Last added handler will be executed first.
240
     *
241
     * @param mixed $middlewareDefinition
242
     *
243
     * @return self
244
     */
245 4
    public function prependMiddleware($middlewareDefinition): self
246
    {
247 4
        if (!$this->actionAdded) {
248
            throw new RuntimeException('prependMiddleware() can not be used before action().');
249
        }
250 4
        $route = clone $this;
251 4
        $route->middlewareDefinitions[] = $middlewareDefinition;
252 4
        return $route;
253
    }
254
255
    /**
256
     * Appends action handler. It is a primary middleware definition that should be invoked last for a matched route.
257
     *
258
     * @param mixed $middlewareDefinition
259
     *
260
     * @return self
261
     */
262 5
    public function action($middlewareDefinition): self
263
    {
264 5
        $route = clone $this;
265 5
        array_unshift($route->middlewareDefinitions, $middlewareDefinition);
266 5
        $route->actionAdded = true;
267 5
        return $route;
268
    }
269
270
    /**
271
     * Excludes middleware from being invoked when action is handled.
272
     * It is useful to avoid invoking one of the parent group middleware for
273
     * a certain route.
274
     *
275
     * @param mixed $middlewareDefinition
276
     *
277
     * @return $this
278
     */
279
    public function disableMiddleware($middlewareDefinition): self
280
    {
281
        $route = clone $this;
282
        $route->disabledMiddlewareDefinitions[] = $middlewareDefinition;
283
        return $route;
284
    }
285
286 2
    public function __toString(): string
287
    {
288 2
        $result = '';
289
290 2
        if ($this->name !== null) {
291 1
            $result .= '[' . $this->name . '] ';
292
        }
293
294 2
        if ($this->methods !== []) {
295 2
            $result .= implode(',', $this->methods) . ' ';
296
        }
297 2
        if ($this->host !== null && strrpos($this->pattern, $this->host) === false) {
298 1
            $result .= $this->host;
299
        }
300 2
        $result .= $this->pattern;
301
302 2
        return $result;
303
    }
304
305 8
    public function getName(): string
306
    {
307 8
        return $this->name ?? (implode(', ', $this->methods) . ' ' . $this->host . $this->pattern);
308
    }
309
310 9
    public function getMethods(): array
311
    {
312 9
        return $this->methods;
313
    }
314
315 7
    public function getPattern(): string
316
    {
317 7
        return $this->pattern;
318
    }
319
320 1
    public function getHost(): ?string
321
    {
322 1
        return $this->host;
323
    }
324
325 3
    public function isOverride(): bool
326
    {
327 3
        return $this->override;
328
    }
329
330 1
    public function getDefaults(): array
331
    {
332 1
        return $this->defaults;
333
    }
334
335 6
    public function hasMiddlewares(): bool
336
    {
337 6
        return $this->middlewareDefinitions !== [];
338
    }
339
}
340