BaseGroup::getMiddleware()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 6
ccs 3
cts 3
cp 1
rs 10
c 0
b 0
f 0
cc 1
crap 1
nc 1
nop 0
1
<?php declare(strict_types=1);
2
3
namespace Limoncello\Core\Routing;
4
5
/**
6
 * Copyright 2015-2020 [email protected]
7
 *
8
 * Licensed under the Apache License, Version 2.0 (the "License");
9
 * you may not use this file except in compliance with the License.
10
 * You may obtain a copy of the License at
11
 *
12
 * http://www.apache.org/licenses/LICENSE-2.0
13
 *
14
 * Unless required by applicable law or agreed to in writing, software
15
 * distributed under the License is distributed on an "AS IS" BASIS,
16
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
 * See the License for the specific language governing permissions and
18
 * limitations under the License.
19
 */
20
21
use Closure;
22
use Limoncello\Common\Reflection\CheckCallableTrait;
23
use Limoncello\Contracts\Routing\GroupInterface;
24
use Limoncello\Contracts\Routing\RouteInterface;
25
use Limoncello\Core\Routing\Traits\CallableTrait;
26
use Limoncello\Core\Routing\Traits\HasConfiguratorsTrait;
27
use Limoncello\Core\Routing\Traits\HasMiddlewareTrait;
28
use Limoncello\Core\Routing\Traits\HasRequestFactoryTrait;
29
use Limoncello\Core\Routing\Traits\UriTrait;
30
use ReflectionException;
31
use function array_key_exists;
32
use function array_merge;
33
34
/**
35
 * @package Limoncello\Core
36
 *
37
 * @SuppressWarnings(PHPMD.TooManyPublicMethods)
38
 */
39
abstract class BaseGroup implements GroupInterface
40
{
41
    use CallableTrait, UriTrait, HasRequestFactoryTrait, CheckCallableTrait;
42
43
    use HasMiddlewareTrait {
44
        addMiddleware as private addMiddlewareImpl;
45
    }
46
47
    use HasConfiguratorsTrait {
48
        addConfigurators as private addConfiguratorsImpl;
49
    }
50
51
    /** Default value if routes should use request factory from its group */
52
    const USE_FACTORY_FROM_GROUP_DEFAULT = true;
53
54
    /**
55
     * @var null|GroupInterface
56
     */
57
    private $parent;
58
59
    /**
60
     * @var string
61
     */
62
    private $uriPrefix = '';
63
64
    /**
65
     * @var string|null
66
     */
67
    private $name = null;
68
69
    /**
70
     * @var array
71
     */
72
    private $items = [];
73
74
    /**
75
     * @var bool
76
     */
77
    private $trailSlashes = false;
78
79
    /**
80
     * @return self
0 ignored issues
show
Documentation introduced by
Should the return type not be \self?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
81
     */
82
    abstract protected function createGroup(): self;
83
84
    /**
85
     * @param GroupInterface $parent
86
     *
87
     * @return $this
88
     */
89 17
    public function setParentGroup(GroupInterface $parent)
90
    {
91 17
        $this->parent = $parent;
92
93 17
        return $this;
94
    }
95
96
    /**
97
     * @param string $uriPrefix
98
     *
99
     * @return self
100
     */
101 17
    public function setUriPrefix(string $uriPrefix): self
102
    {
103 17
        $this->uriPrefix = $uriPrefix;
104
105 17
        return $this;
106
    }
107
108
    /**
109
     * @param string $name
110
     *
111
     * @return self
112
     */
113 1
    public function setName(string $name): self
114
    {
115 1
        $this->name = $name;
116
117 1
        return $this;
118
    }
119
120
    /**
121
     * @return self
122
     */
123 17
    public function clearName(): self
124
    {
125 17
        $this->name = null;
126
127 17
        return $this;
128
    }
129
130
    /**
131
     * @param bool $trailSlashes
132
     *
133
     * @return self
134
     */
135 17
    public function setHasTrailSlash(bool $trailSlashes): self
136
    {
137 17
        $this->trailSlashes = $trailSlashes;
138
139 17
        return $this;
140
    }
141
142
    /**
143
     * @inheritdoc
144
     */
145 18
    public function parentGroup(): ?GroupInterface
146
    {
147 18
        return $this->parent;
148
    }
149
150
    /**
151
     * @inheritdoc
152
     */
153 18
    public function getUriPrefix(): string
154
    {
155 18
        $parentPrefix = $this->getParentUriPrefix();
156 18
        if ($parentPrefix !== null) {
157 17
            return $this->normalizeUri($this->concatUri($parentPrefix, $this->uriPrefix), $this->hasTrailSlash());
158
        }
159
160 18
        return $this->normalizeUri($this->uriPrefix, $this->hasTrailSlash());
161
    }
162
163
    /**
164
     * @inheritdoc
165
     */
166 8
    public function getName(): ?string
167
    {
168 8
        return $this->name;
169
    }
170
171
    /**
172
     * @inheritdoc
173
     */
174 17
    public function getMiddleware(): array
175
    {
176 17
        $result = array_merge($this->getParentMiddleware(), $this->middleware);
177
178 17
        return $result;
179
    }
180
181
    /**
182
     * @inheritdoc
183
     */
184 1
    public function addMiddleware(array $middleware): GroupInterface
185
    {
186 1
        return $this->addMiddlewareImpl($middleware);
187
    }
188
189
    /**
190
     * @inheritdoc
191
     */
192 17
    public function getContainerConfigurators(): array
193
    {
194 17
        $result = array_merge($this->getParentConfigurators(), $this->configurators);
195
196 17
        return $result;
197
    }
198
199
    /**
200
     * @inheritdoc
201
     */
202 1
    public function addContainerConfigurators(array $configurators): GroupInterface
203
    {
204 1
        return $this->addConfiguratorsImpl($configurators);
205
    }
206
207
    /**
208
     * @inheritdoc
209
     */
210 17
    public function getRequestFactory(): ?callable
211
    {
212 17
        if ($this->isRequestFactorySet() === true) {
213 9
            return $this->requestFactory;
214
        }
215
216 15
        $parent = $this->parentGroup();
217 15
        $result = $parent === null ? $this->getDefaultRequestFactory() : $parent->getRequestFactory();
218
219 15
        return $result;
220
    }
221
222
    /**
223
     * @inheritdoc
224
     */
225 18
    public function getRoutes(): iterable
226
    {
227 18
        foreach ($this->items as $routeOrGroup) {
228 18
            if ($routeOrGroup instanceof RouteInterface) {
229
                /** @var RouteInterface $routeOrGroup */
230 18
                yield $routeOrGroup;
231 18
                continue;
232
            }
233
234
            /** @var GroupInterface $routeOrGroup */
235 17
            foreach ($routeOrGroup->getRoutes() as $route) {
236 17
                yield $route;
237
            }
238
        }
239
    }
240
241
    /**
242
     * @inheritdoc
243
     */
244 17
    public function group(string $prefix, Closure $closure, array $parameters = []): GroupInterface
245
    {
246
        list($middleware, $configurators, $factoryWasGiven, $requestFactory, $name) =
247 17
            $this->normalizeGroupParameters($parameters);
248
249 17
        $group = $this->createGroup()
250 17
            ->setUriPrefix($prefix)
251 17
            ->setMiddleware($middleware)
252 17
            ->setConfigurators($configurators);
253 17
        $name === null ? $group->clearName() : $group->setName($name);
254
255 17
        $factoryWasGiven === false ?: $group->setRequestFactory($requestFactory);
256
257 17
        return $this->addGroup($closure, $group);
258
    }
259
260
    /**
261
     * @inheritdoc
262
     */
263 17
    public function addGroup(Closure $closure, GroupInterface $group): GroupInterface
264
    {
265 17
        $closure($group);
266
267 17
        $this->items[] = $group;
268
269 17
        return $this;
270
    }
271
272
    /**
273
     * @inheritdoc
274
     */
275 18
    public function addRoute(RouteInterface $route): GroupInterface
276
    {
277 18
        $this->items[] = $route;
278
279 18
        return $this;
280
    }
281
282
    /**
283
     * @inheritdoc
284
     *
285
     * @throws ReflectionException
286
     */
287 22
    public function method(string $method, string $uriPath, callable $handler, array $parameters = []): GroupInterface
288
    {
289
        list($middleware, $configurators, $requestFactory, $useGroupFactory, $name) =
290 22
            $this->normalizeRouteParameters($parameters);
291
292 22
        $uriPath = $this->normalizeUri($uriPath, $this->hasTrailSlash());
293
294 22
        $route = $this->createRoute($this, $method, $uriPath, $handler)
295 21
            ->setUseGroupRequestFactory($useGroupFactory)
296 21
            ->setRequestFactory($requestFactory)
297 20
            ->setConfigurators($configurators)
298 19
            ->setMiddleware($middleware)
299 18
            ->setName($name);
300
301 18
        return $this->addRoute($route);
302
    }
303
304
    /**
305
     * @inheritdoc
306
     *
307
     * @throws ReflectionException
308
     */
309 22
    public function get(string $uriPath, callable $handler, array $parameters = []): GroupInterface
310
    {
311 22
        return $this->method('GET', $uriPath, $handler, $parameters);
312
    }
313
314
    /**
315
     * @inheritdoc
316
     *
317
     * @throws ReflectionException
318
     */
319 16
    public function post(string $uriPath, callable $handler, array $parameters = []): GroupInterface
320
    {
321 16
        return $this->method('POST', $uriPath, $handler, $parameters);
322
    }
323
324
    /**
325
     * @inheritdoc
326
     *
327
     * @throws ReflectionException
328
     */
329 1
    public function put(string $uriPath, callable $handler, array $parameters = []): GroupInterface
330
    {
331 1
        return $this->method('PUT', $uriPath, $handler, $parameters);
332
    }
333
334
    /**
335
     * @inheritdoc
336
     *
337
     * @throws ReflectionException
338
     */
339 2
    public function patch(string $uriPath, callable $handler, array $parameters = []): GroupInterface
340
    {
341 2
        return $this->method('PATCH', $uriPath, $handler, $parameters);
342
    }
343
344
    /**
345
     * @inheritdoc
346
     *
347
     * @throws ReflectionException
348
     */
349 10
    public function delete(string $uriPath, callable $handler, array $parameters = []): GroupInterface
350
    {
351 10
        return $this->method('DELETE', $uriPath, $handler, $parameters);
352
    }
353
354
    /**
355
     * @inheritdoc
356
     */
357 22
    public function hasTrailSlash(): bool
358
    {
359 22
        return $this->trailSlashes;
360
    }
361
362
    /**
363
     * @param GroupInterface $group
364
     * @param string         $method
365
     * @param string         $uriPath
366
     * @param callable       $handler
367
     *
368
     * @return Route
369
     *
370
     * @throws ReflectionException
371
     */
372 22
    protected function createRoute(GroupInterface $group, string $method, string $uriPath, callable $handler): Route
373
    {
374 22
        $route = (new Route($group, $method, $uriPath, $handler));
375
376 21
        return $route;
377
    }
378
379
    /**
380
     * @param array $parameters
381
     *
382
     * @return array
383
     */
384 22
    protected function normalizeRouteParameters(array $parameters): array
385
    {
386 22
        $factoryWasGiven = array_key_exists(RouteInterface::PARAM_REQUEST_FACTORY, $parameters);
387
        $useGroupFactory =
388 22
            $parameters[RouteInterface::PARAM_FACTORY_FROM_GROUP] ?? self::USE_FACTORY_FROM_GROUP_DEFAULT;
389
390
        return [
391 22
            $parameters[RouteInterface::PARAM_MIDDLEWARE_LIST] ?? [],
392 22
            $parameters[RouteInterface::PARAM_CONTAINER_CONFIGURATORS] ?? [],
393 22
            $parameters[RouteInterface::PARAM_REQUEST_FACTORY] ?? null,
394 22
            $factoryWasGiven === true ? false : $useGroupFactory,
395 22
            $parameters[RouteInterface::PARAM_NAME] ?? null,
396
        ];
397
    }
398
399
    /**
400
     * @param array $parameters
401
     *
402
     * @return array
403
     */
404 25
    protected function normalizeGroupParameters(array $parameters): array
405
    {
406 25
        $factoryWasGiven = array_key_exists(GroupInterface::PARAM_REQUEST_FACTORY, $parameters);
407
408
        return [
409 25
            $parameters[GroupInterface::PARAM_MIDDLEWARE_LIST] ?? [],
410 25
            $parameters[GroupInterface::PARAM_CONTAINER_CONFIGURATORS] ?? [],
411 25
            $factoryWasGiven,
412 25
            $parameters[GroupInterface::PARAM_REQUEST_FACTORY] ?? null,
413 25
            $parameters[GroupInterface::PARAM_NAME_PREFIX] ?? null,
414
        ];
415
    }
416
417
    /**
418
     * @return null|string
419
     */
420 18
    private function getParentUriPrefix(): ?string
421
    {
422 18
        $parent = $this->parentGroup();
423 18
        $result = $parent === null ? null : $parent->getUriPrefix();
424
425 18
        return $result;
426
    }
427
428
    /**
429
     * @return array
430
     */
431 17
    private function getParentMiddleware(): array
432
    {
433 17
        $parent = $this->parentGroup();
434 17
        $result = $parent === null ? [] : $parent->getMiddleware();
435
436 17
        return $result;
437
    }
438
439
    /**
440
     * @return array
441
     */
442 17
    private function getParentConfigurators(): array
443
    {
444 17
        $parent = $this->parentGroup();
445 17
        $result = $parent === null ? [] : $parent->getContainerConfigurators();
446
447 17
        return $result;
448
    }
449
}
450