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

Router::mount()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 6
ccs 0
cts 4
cp 0
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 3
nc 2
nop 1
crap 6
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 PatternRule[]
19
     */
20
    protected $routes;
21
22
    /**
23
     * @var iterable
24
     */
25
    protected $config = [];
26
27
    /**
28
     * @var CacheItemPoolInterface
29
     */
30
    protected $pool;
31
32
    /**
33
     * Router constructor.
34
     *
35
     * @param iterable $data
36
     * @param CacheItemPoolInterface   $pool
37
     */
38 5
    public function __construct($data, CacheItemPoolInterface $pool = null)
39
    {
40 5
        $this->add($data);
41 5
        $this->pool = $pool;
42 5
    }
43
44
    /**
45
     * @param Group $group
46
     * @return Router
47
     */
48
    public function mount(Group $group): self
49
    {
50
        foreach ($group as $pattern) {
51
            $this->push($pattern);
52
        }
53
        return $this;
54
    }
55
56
    /**
57
     * @param Pattern $pattern
58
     * @return Router
59
     */
60
    public function push(Pattern $pattern): self
61
    {
62
        return $this->add($pattern->toArray());
63
    }
64
65
    /**
66
     * @param \Traversable|iterable $config
67
     * @return Router
68
     */
69 5
    protected function add($config): self
70
    {
71 5
        $this->routes = null;
72 5
        $this->config = \array_merge(
73 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

73
            /** @scrutinizer ignore-type */ $this->config,
Loading history...
74 5
            \iterator_to_array($config)
75
        );
76
77 5
        return $this;
78
    }
79
80
    /**
81
     * @return Route
82
     *
83
     * @throws Exceptions\NotFound\Data
84
     * @throws Exceptions\NotFound\Path
85
     */
86
    public function getCurrentRoute(): Route
87
    {
88
        return $this->find(Server::sharedInstance()->path());
89
    }
90
91
    /**
92
     * @param string $path
93
     * @param string $host
94
     * @param string $protocol
95
     *
96
     * @return Route
97
     * @throws Exceptions\NotFound\Data
98
     * @throws Exceptions\NotFound\Path
99
     */
100 3
    public function getRoute(string $path, string $host = null, string $protocol = null): Route
101
    {
102 3
        return $this->find(Server::url($path, $host, $protocol));
103
    }
104
105
    /**
106
     * @return string
107
     */
108
    protected function hash(): string
109
    {
110
        return self::VERSION . \crc32(\json_encode($this->config));
111
    }
112
113
    /**
114
     * @return array
115
     * @throws
116
     */
117 5
    protected function loadingRoutes(): array
118
    {
119 5
        $loader = new Loader($this->config);
120 5
        $this->routes = $loader->simplify();
121
122 3
        if ($this->pool) {
123
            $item = $this->pool->getItem($this->hash());
124
            $item->set($this->routes);
125
            $this->pool->save($item);
126
        }
127
128 3
        return $this->routes;
129
    }
130
131
    /**
132
     * @return array
133
     * @throws
134
     */
135 5
    protected function bootRoutes(): array
136
    {
137 5
        if ($this->pool) {
138
            $item = $this->pool->getItem($this->hash());
139
            $data = $item->get();
140
            if ($data) {
141
                return $data;
142
            }
143
        }
144
145 5
        return $this->loadingRoutes();
146
    }
147
148
    /**
149
     * @return Route[]
150
     */
151 5
    public function routes(): array 
152
    {
153 5
        if (empty($this->routes)) {
154 5
            $this->routes = $this->bootRoutes();
155
        }
156
157 3
        return $this->routes;
158
    }
159
160
    /**
161
     * @param string $path
162
     *
163
     * @return Route
164
     *
165
     * @throws Exceptions\NotFound\Path
166
     */
167
    public function route(string $path): Route
168
    {
169
        $routes = $this->routes();
170
171
        if (empty($routes[$path])) {
172
            throw new Exceptions\NotFound\Path('Route `' . $path . '` not found');
173
        }
174
175
        return $routes[$path];
176
    }
177
178
    /**
179
     * @param string $subject
180
     * @return Route
181
     */
182 3
    protected function find(string $subject): Route
183
    {
184 3
        foreach ($this->routes() as $name => $patternRule) {
185 3
            $match = new Match($patternRule, $subject, Server::sharedInstance()->method());
186 3
            if ($match->isTest()) {
187 3
                return new Route($match);
188
            }
189
        }
190
191 1
        throw new Exceptions\NotFound\Page('Page `' . $subject . '` not found', 404);
192
    }
193
194
}
195