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

Router::loadingRoutes()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 13
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 2.1481

Importance

Changes 0
Metric Value
dl 0
loc 13
ccs 6
cts 9
cp 0.6667
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 8
nc 2
nop 0
crap 2.1481
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
     */
104
    public function getCurrentRoute(): Route
105
    {
106
        return $this->getRoute(Server::sharedInstance()->path());
107
    }
108
109
    /**
110
     * @param string $path
111
     * @param string $host
112
     * @param string $protocol
113
     *
114
     * @return Route
115
     *
116
     * @throws Exceptions\NotFound\Data
117
     * @throws Exceptions\NotFound\Path
118
     * @throws Exceptions\NotFound\Page
119
     */
120 3
    public function getRoute(string $path, string $host = null, string $protocol = null): Route
121
    {
122 3
        return $this->find(Server::url($path, $host, $protocol));
123
    }
124
125
    /**
126
     * @return string
127
     */
128
    protected function hash(): string
129
    {
130
        return self::VERSION . \crc32(\json_encode($this->config));
131
    }
132
133
    /**
134
     * loading mounted groups
135
     */
136 5
    protected function loadingGroups(): void
137
    {
138 5
        foreach ($this->groups as $group) {
139
            $this->addPattern($group->toArray());
140
        }
141 5
    }
142
143
    /**
144
     * @return array
145
     * @throws
146
     */
147 5
    protected function loadingRoutes(): array
148
    {
149 5
        $this->loadingGroups();
150 5
        $loader = new Loader($this->config);
151 5
        $this->routes = $loader->simplify();
152
153 3
        if ($this->pool) {
154
            $item = $this->pool->getItem($this->hash());
155
            $item->set($this->routes);
156
            $this->pool->save($item);
157
        }
158
159 3
        return $this->routes;
160
    }
161
162
    /**
163
     * @return array
164
     * @throws
165
     */
166 5
    protected function bootRoutes(): array
167
    {
168 5
        if ($this->pool) {
169
            $item = $this->pool->getItem($this->hash());
170
            $data = $item->get();
171
            if ($data) {
172
                return $data;
173
            }
174
        }
175
176 5
        return $this->loadingRoutes();
177
    }
178
179
    /**
180
     * @return Route[]
181
     */
182 5
    public function routes(): array 
183
    {
184 5
        if (empty($this->routes)) {
185 5
            $this->routes = $this->bootRoutes();
186
        }
187
188 3
        return $this->routes;
189
    }
190
191
    /**
192
     * @param string $path
193
     *
194
     * @return Route
195
     *
196
     * @throws Exceptions\NotFound\Path
197
     */
198
    public function route(string $path): Route
199
    {
200
        $routes = $this->routes();
201
202
        if (empty($routes[$path])) {
203
            throw new Exceptions\NotFound\Path('Route `' . $path . '` not found');
204
        }
205
206
        return $routes[$path];
207
    }
208
209
    /**
210
     * @param string $subject
211
     * @return Route
212
     * @throws Exceptions\NotFound\Page
213
     */
214 3
    protected function find(string $subject): Route
215
    {
216 3
        foreach ($this->routes() as $name => $patternRule) {
217 3
            $match = new Match($patternRule, $subject, Server::sharedInstance()->method());
218 3
            if ($match->isTest()) {
219 3
                return new Route($match);
220
            }
221
        }
222
223 1
        throw new Exceptions\NotFound\Page('Page `' . $subject . '` not found', 404);
224
    }
225
226
}
227