Passed
Pull Request — master (#138)
by Rustam
02:27
created

Group::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 InvalidArgumentException;
8
use RuntimeException;
9
use Yiisoft\Middleware\Dispatcher\MiddlewareDispatcher;
10
11
use function get_class;
12
use function in_array;
13
use function is_object;
14
15
final class Group
16
{
17
    /**
18
     * @var Group[]|Route[]
19
     */
20
    private array $items = [];
21
    private ?string $prefix;
22
    private array $middlewareDefinitions = [];
23
    private ?string $host = null;
24
    private ?string $namePrefix = null;
25
    private bool $routesAdded = false;
26
    private bool $middlewareAdded = false;
27
    private array $disabledMiddlewareDefinitions = [];
28
    /**
29
     * @var mixed Middleware definition for CORS requests.
30
     */
31
    private $corsMiddleware;
32
    private ?MiddlewareDispatcher $dispatcher;
33
34 26
    private function __construct(?string $prefix = null, MiddlewareDispatcher $dispatcher = null)
35
    {
36 26
        $this->dispatcher = $dispatcher;
37 26
        $this->prefix = $prefix;
38 26
    }
39
40
    /**
41
     * Create a new group instance.
42
     *
43
     * @param string|null $prefix URL prefix to prepend to all routes of the group.
44
     * @param MiddlewareDispatcher|null $dispatcher Middleware dispatcher to use for the group.
45
     *
46
     * @return self
47
     */
48 26
    public static function create(
49
        ?string $prefix = null,
50
        MiddlewareDispatcher $dispatcher = null
51
    ): self {
52 26
        return new self($prefix, $dispatcher);
53
    }
54
55 23
    public function routes(...$routes): self
56
    {
57 23
        if ($this->middlewareAdded) {
58 1
            throw new RuntimeException('routes() can not be used after prependMiddleware().');
59
        }
60 22
        $new = clone $this;
61 22
        foreach ($routes as $route) {
62 22
            if ($route instanceof Route || $route instanceof self) {
63 21
                if (!$route->hasDispatcher() && $new->hasDispatcher()) {
64 5
                    $route = $route->withDispatcher($new->dispatcher);
65
                }
66 21
                $new->items[] = $route;
67
            } else {
68 1
                $type = is_object($route) ? get_class($route) : gettype($route);
69 1
                throw new InvalidArgumentException(
70 1
                    sprintf('Route should be either an instance of Route or Group, %s given.', $type)
71
                );
72
            }
73
        }
74
75 21
        $new->routesAdded = true;
76
77 21
        return $new;
78
    }
79
80 2
    public function withDispatcher(MiddlewareDispatcher $dispatcher): self
81
    {
82 2
        $group = clone $this;
83 2
        $group->dispatcher = $dispatcher;
84 2
        foreach ($group->items as $index => $item) {
85 2
            if (!$item->hasDispatcher()) {
86 2
                $item = $item->withDispatcher($dispatcher);
87 2
                $group->items[$index] = $item;
88
            }
89
        }
90
91 2
        return $group;
92
    }
93
94
    /**
95
     * Adds a middleware definition that handles CORS requests.
96
     * If set, routes for {@see Method::OPTIONS} request will be added automatically.
97
     *
98
     * @param mixed $middlewareDefinition Middleware definition for CORS requests.
99
     *
100
     * @return self
101
     */
102 5
    public function withCors($middlewareDefinition): self
103
    {
104 5
        $group = clone $this;
105 5
        $group->corsMiddleware = $middlewareDefinition;
106
107 5
        return $group;
108
    }
109
110
    /**
111
     * @return bool Middleware definition for CORS requests.
112
     */
113 18
    public function hasCorsMiddleware(): bool
114
    {
115 18
        return $this->corsMiddleware !== null;
116
    }
117
118 21
    public function hasDispatcher(): bool
119
    {
120 21
        return $this->dispatcher !== null;
121
    }
122
123
    /**
124
     * Appends a handler middleware definition that should be invoked for a matched route.
125
     * First added handler will be executed first.
126
     *
127
     * @param mixed $middlewareDefinition
128
     *
129
     * @return self
130
     */
131 7
    public function middleware($middlewareDefinition): self
132
    {
133 7
        if ($this->routesAdded) {
134
            throw new RuntimeException('middleware() can not be used after routes().');
135
        }
136 7
        $new = clone $this;
137 7
        array_unshift($new->middlewareDefinitions, $middlewareDefinition);
138 7
        return $new;
139
    }
140
141
    /**
142
     * Prepends a handler middleware definition that should be invoked for a matched route.
143
     * First added handler will be executed last.
144
     *
145
     * @param mixed $middlewareDefinition
146
     *
147
     * @return self
148
     */
149 3
    public function prependMiddleware($middlewareDefinition): self
150
    {
151 3
        $new = clone $this;
152 3
        $new->middlewareDefinitions[] = $middlewareDefinition;
153 3
        $new->middlewareAdded = true;
154 3
        return $new;
155
    }
156
157 3
    public function namePrefix(string $namePrefix): self
158
    {
159 3
        $new = clone $this;
160 3
        $new->namePrefix = $namePrefix;
161 3
        return $new;
162
    }
163
164 2
    public function host(string $host): self
165
    {
166 2
        $new = clone $this;
167 2
        $new->host = rtrim($host, '/');
168 2
        return $new;
169
    }
170
171
    /**
172
     * Excludes middleware from being invoked when action is handled.
173
     * It is useful to avoid invoking one of the parent group middleware for
174
     * a certain route.
175
     *
176
     * @param mixed $middlewareDefinition
177
     *
178
     * @return self
179
     */
180
    public function disableMiddleware($middlewareDefinition): self
181
    {
182
        $new = clone $this;
183
        $new->disabledMiddlewareDefinitions[] = $middlewareDefinition;
184
        return $new;
185
    }
186
187
    /**
188
     * @param string $key
189
     *
190
     * @return mixed
191
     */
192 22
    public function getData(string $key)
193
    {
194 22
        switch ($key) {
195 22
            case 'prefix':
196 19
                return $this->prefix;
197 22
            case 'namePrefix':
198 19
                return $this->namePrefix;
199 21
            case 'host':
200 19
                return $this->host;
201 20
            case 'corsMiddleware':
202 5
                return $this->corsMiddleware;
203 20
            case 'items':
204 20
                return $this->items;
205
            default:
206
                throw new InvalidArgumentException('Unknown data key: ' . $key);
207
        }
208
    }
209
210 16
    public function getMiddlewareDefinitions(): array
211
    {
212 16
        foreach ($this->middlewareDefinitions as $index => $definition) {
213 8
            if (in_array($definition, $this->disabledMiddlewareDefinitions, true)) {
214
                unset($this->middlewareDefinitions[$index]);
215
            }
216
        }
217
218 16
        return $this->middlewareDefinitions;
219
    }
220
}
221