Passed
Push — master ( cfbfb8...ab20eb )
by Rustam
01:31
created

Group::getPrefix()   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 1
Bugs 0 Features 0
Metric Value
eloc 1
c 1
b 0
f 0
dl 0
loc 3
rs 10
ccs 2
cts 2
cp 1
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 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 10
    }
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
    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 9
            $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
    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
    public function hasContainer(): bool
78
    {
79 9
        return $this->container !== null;
80
    }
81
82 9
    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
    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 ($this->isCallable($middleware) && (!is_array($middleware) || !is_object($middleware[0]))) {
112 6
            return;
113
        }
114
115
        throw new InvalidArgumentException('Parameter should be either PSR middleware class name or a callable.');
116
    }
117
118 6
    private function isCallable($definition): bool
119
    {
120 6
        if (is_callable($definition)) {
121 6
            return true;
122
        }
123
124
        return is_array($definition) && array_keys($definition) === [0, 1] && in_array($definition[1], get_class_methods($definition[0]) ?? [], true);
125
    }
126
127
    /**
128
     * @param callable|MiddlewareInterface $middleware
129
     * @return $this
130
     */
131 6
    public function addMiddleware($middleware): self
132
    {
133 6
        $this->validateMiddleware($middleware);
134 6
        $this->middlewares[] = $middleware;
135
136 6
        return $this;
137
    }
138
139
    /**
140
     * @return Route|Group[]
141
     */
142 9
    public function getItems(): array
143
    {
144 9
        return $this->items;
145
    }
146
147 5
    public function getPrefix(): ?string
148
    {
149 5
        return $this->prefix;
150
    }
151
152 7
    public function getMiddlewares(): array
153
    {
154 7
        return $this->middlewares;
155
    }
156
}
157