Completed
Pull Request — master (#3)
by Бабичев
06:31
created

Router::bootRoutes()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 4.679

Importance

Changes 0
Metric Value
dl 0
loc 11
ccs 3
cts 7
cp 0.4286
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 6
nc 3
nop 0
crap 4.679
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->pushConfig($data);
41 5
        $this->pool = $pool;
42 5
    }
43
44
    /**
45
     * @param \Traversable|iterable $config
46
     * @return Router
47
     */
48 5
    protected function pushConfig($config): self
49
    {
50 5
        $this->routes = null;
51 5
        $this->config = \array_merge(
52 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

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