Passed
Pull Request — master (#3)
by Бабичев
01:37
created

Router::group()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 5
ccs 0
cts 4
cp 0
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 2
crap 2
1
<?php
2
3
namespace Bavix\Router;
4
5
use Bavix\Router\Rules\PatternRule;
6
use Psr\Cache\CacheItemPoolInterface;
7
use Bavix\Exceptions;
8
9
class Router
10
{
11
12
    /**
13
     * Router version
14
     */
15
    public const VERSION = '2.0.0';
16
17
    /**
18
     * @var Group[]
19
     */
20
    protected $groups = [];
21
22
    /**
23
     * @var PatternRule[]
24
     */
25
    protected $routes;
26
27
    /**
28
     * @var iterable
29
     */
30
    protected $config = [];
31
32
    /**
33
     * @var CacheItemPoolInterface
34
     */
35
    protected $pool;
36
37
    /**
38
     * Router constructor.
39
     *
40
     * @param iterable $data
41
     * @param CacheItemPoolInterface   $pool
42
     */
43 5
    public function __construct($data, CacheItemPoolInterface $pool = null)
44
    {
45 5
        $this->addPattern($data);
46 5
        $this->pool = $pool;
47 5
    }
48
49
    /**
50
     * @param string   $prefix
51
     * @param callable $callback
52
     *
53
     * @return Group
54
     */
55
    public function group(string $prefix, callable $callback): Group
56
    {
57
        $group = new Group($prefix, $callback);
58
        $this->mount($group);
59
        return $group;
60
    }
61
62
    /**
63
     * @param Group $group
64
     * @return Router
65
     */
66
    public function mount(Group $group): self
67
    {
68
        $this->routes = null;
69
        $this->groups[] = $group;
70
        return $this;
71
    }
72
73
    /**
74
     * @param Pattern $pattern
75
     * @return Router
76
     */
77
    public function push(Pattern $pattern): self
78
    {
79
        return $this->addPattern($pattern->toArray());
80
    }
81
82
    /**
83
     * @param \Traversable|iterable $config
84
     * @return Router
85
     */
86 5
    protected function addPattern($config): self
87
    {
88 5
        $this->routes = null;
89 5
        $this->config = \array_merge(
90 5
            $this->config,
0 ignored issues
show
Bug introduced by
$this->config of type iterable is incompatible with the type array expected by parameter $array1 of array_merge(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

90
            /** @scrutinizer ignore-type */ $this->config,
Loading history...
91 5
            \iterator_to_array($config)
92
        );
93
94 5
        return $this;
95
    }
96
97
    /**
98
     * @return Route
99
     *
100
     * @throws Exceptions\NotFound\Data
101
     * @throws Exceptions\NotFound\Path
102
     * @throws Exceptions\NotFound\Page
103
     * @throws \Psr\Cache\InvalidArgumentException
104
     */
105
    public function getCurrentRoute(): Route
106
    {
107
        return $this->find(Server::sharedInstance()->path());
108
    }
109
110
    /**
111
     * @param string $path
112
     * @param string $host
113
     * @param string $protocol
114
     *
115
     * @return Route
116
     *
117
     * @throws Exceptions\NotFound\Data
118
     * @throws Exceptions\NotFound\Path
119
     * @throws Exceptions\NotFound\Page
120
     * @throws \Psr\Cache\InvalidArgumentException
121
     */
122 3
    public function getRoute(string $path, string $host = null, string $protocol = null): Route
123
    {
124 3
        return $this->find(Server::url($path, $host, $protocol));
125
    }
126
127
    /**
128
     * @return string
129
     */
130
    protected function hash(): string
131
    {
132
        return self::VERSION . \crc32(\json_encode($this->config));
133
    }
134
135
    /**
136
     * loading mounted groups
137
     */
138 5
    protected function loadingGroups(): void
139
    {
140 5
        foreach ($this->groups as $group) {
141
            $this->addPattern($group->toArray());
142
        }
143 5
    }
144
145
    /**
146
     * @return array
147
     * @throws \Psr\Cache\InvalidArgumentException
148
     */
149 5
    protected function loadingRoutes(): array
150
    {
151 5
        $this->loadingGroups();
152 5
        $loader = new Loader($this->config);
153 5
        $this->routes = $loader->simplify();
154
155 3
        if ($this->pool) {
156
            $item = $this->pool->getItem($this->hash());
157
            $item->set($this->routes);
158
            $this->pool->save($item);
159
        }
160
161 3
        return $this->routes;
162
    }
163
164
    /**
165
     * @return array
166
     * @throws \Psr\Cache\InvalidArgumentException
167
     */
168 5
    protected function bootRoutes(): array
169
    {
170 5
        if ($this->pool) {
171
            $item = $this->pool->getItem($this->hash());
172
            $data = $item->get();
173
            if ($data) {
174
                return $data;
175
            }
176
        }
177
178 5
        return $this->loadingRoutes();
179
    }
180
181
    /**
182
     * @return Route[]
183
     * @throws \Psr\Cache\InvalidArgumentException
184
     */
185 5
    public function routes(): array 
186
    {
187 5
        if (empty($this->routes)) {
188 5
            $this->routes = $this->bootRoutes();
189
        }
190
191 3
        return $this->routes;
192
    }
193
194
    /**
195
     * @param string $path
196
     *
197
     * @return Route
198
     *
199
     * @throws Exceptions\NotFound\Path
200
     * @throws \Psr\Cache\InvalidArgumentException
201
     */
202
    public function route(string $path): Route
203
    {
204
        $routes = $this->routes();
205
206
        if (empty($routes[$path])) {
207
            throw new Exceptions\NotFound\Path('Route `' . $path . '` not found');
208
        }
209
210
        return $routes[$path];
211
    }
212
213
    /**
214
     * @param string $subject
215
     * @return Route
216
     * @throws Exceptions\NotFound\Page
217
     * @throws \Psr\Cache\InvalidArgumentException
218
     */
219 3
    protected function find(string $subject): Route
220
    {
221 3
        foreach ($this->routes() as $name => $patternRule) {
222 3
            $match = new Match($patternRule, $subject, Server::sharedInstance()->method());
223 3
            if ($match->isTest()) {
224 3
                return new Route($match);
225
            }
226
        }
227
228 1
        throw new Exceptions\NotFound\Page('Page `' . $subject . '` not found', 404);
229
    }
230
231
}
232