Passed
Pull Request — master (#114)
by Rustam
02:14
created

Group::getMiddlewares()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

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