Passed
Push — master ( a586e8...77a217 )
by Alexander
01:33
created

Group::validateMiddleware()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 13
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 4.5923

Importance

Changes 0
Metric Value
cc 4
eloc 6
c 0
b 0
f 0
nc 3
nop 1
dl 0
loc 13
ccs 4
cts 6
cp 0.6667
crap 4.5923
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Router;
6
7
use InvalidArgumentException;
8
use Psr\Container\ContainerInterface;
9
use Psr\Http\Server\MiddlewareInterface;
10
11
final class Group implements RouteCollectorInterface
12
{
13
    /**
14
     * @var Group[]|Route[]
15
     */
16
    protected array $items = [];
17
    protected ?string $prefix;
18
    protected array $middlewares = [];
19
    private ?ContainerInterface $container = null;
20
21 10
    private function __construct(?string $prefix = null, ?callable $callback = null, ContainerInterface $container = null)
22
    {
23 10
        $this->container = $container;
24 10
        $this->prefix = $prefix;
25
26 10
        if ($callback !== null) {
27 10
            $callback($this);
28
        }
29
    }
30
31
    /**
32
     * Create a new instance
33
     *
34
     * @param string $prefix
35
     * @param callable|array $routes
36
     * @param ContainerInterface $container
37
     *
38
     * @return self
39
     */
40 10
    final public static function create(?string $prefix = null, $routes = [], ContainerInterface $container = null): self
41
    {
42 10
        if (\is_callable($routes)) {
43 4
            $callback = $routes;
44 9
        } elseif (is_array($routes)) {
45
            $callback = static function (Group $group) use (&$routes) {
46 9
                foreach ($routes as $route) {
47 3
                    if ($route instanceof Route) {
48 3
                        $group->addRoute($route);
49 3
                    } elseif ($route instanceof Group) {
50 3
                        $group->addGroup($route);
51
                    } else {
52
                        throw new InvalidArgumentException('Route should be either instance of Route or Group.');
53
                    }
54
                }
55 9
            };
56
        } else {
57
            $callback = null;
58
        }
59
60 10
        return new self($prefix, $callback, $container);
61
    }
62
63 3
    final public function withContainer(ContainerInterface $container): self
64
    {
65 3
        $group = clone $this;
66 3
        $group->container = $container;
67 3
        foreach ($group->items as $index => $item) {
68 3
            if (!$item->hasContainer()) {
69 3
                $item = $item->withContainer($container);
70 3
                $group->items[$index] = $item;
71
            }
72
        }
73
74 3
        return $group;
75
    }
76
77 9
    final public function hasContainer(): bool
78
    {
79 9
        return $this->container !== null;
80
    }
81
82 9
    final public function addRoute(Route $route): self
83
    {
84 9
        if (!$route->hasContainer() && $this->hasContainer()) {
85 4
            $route = $route->withContainer($this->container);
86
        }
87 9
        $this->items[] = $route;
88 9
        return $this;
89
    }
90
91 7
    final public function addGroup(Group $group): self
92
    {
93 7
        if (!$group->hasContainer() && $this->hasContainer()) {
94 3
            $group = $group->withContainer($this->container);
95
        }
96 7
        $this->items[] = $group;
97 7
        return $this;
98
    }
99
100
    /**
101
     * @param MiddlewareInterface|callable|string|array $middleware
102
     */
103 6
    private function validateMiddleware($middleware): void
104
    {
105
        if (
106 6
            is_string($middleware) && is_subclass_of($middleware, MiddlewareInterface::class)
107
        ) {
108
            return;
109
        }
110
111 6
        if (is_callable($middleware)) {
112 6
            return;
113
        }
114
115
        throw new InvalidArgumentException('Parameter should be either PSR middleware instance, PSR middleware class name, handler action or a callable.');
116
    }
117
118
    /**
119
     * @param callable|MiddlewareInterface $middleware
120
     * @return $this
121
     */
122 6
    final public function addMiddleware($middleware): self
123
    {
124 6
        $this->validateMiddleware($middleware);
125 6
        $this->middlewares[] = $middleware;
126
127 6
        return $this;
128
    }
129
130
    /**
131
     * @return Route|Group[]
132
     */
133 9
    final public function getItems(): array
134
    {
135 9
        return $this->items;
136
    }
137
138 5
    final public function getPrefix(): ?string
139
    {
140 5
        return $this->prefix;
141
    }
142
143 7
    final public function getMiddlewares(): array
144
    {
145 7
        return $this->middlewares;
146
    }
147
}
148