Passed
Pull Request — master (#115)
by Rustam
02:17
created

Group::prependMiddleware()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

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