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

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