Completed
Push — master ( 163fd9...314ef3 )
by Neomerx
02:36
created

Router::getCachedRoutes()   B

Complexity

Conditions 3
Paths 3

Size

Total Lines 28
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 19
CRAP Score 3

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 28
ccs 19
cts 19
cp 1
rs 8.8571
cc 3
eloc 17
nc 3
nop 1
crap 3
1
<?php namespace Limoncello\Core\Routing;
2
3
/**
4
 * Copyright 2015-2016 [email protected] (www.neomerx.com)
5
 *
6
 * Licensed under the Apache License, Version 2.0 (the "License");
7
 * you may not use this file except in compliance with the License.
8
 * You may obtain a copy of the License at
9
 *
10
 * http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing, software
13
 * distributed under the License is distributed on an "AS IS" BASIS,
14
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
 * See the License for the specific language governing permissions and
16
 * limitations under the License.
17
 */
18
19
use FastRoute\RouteCollector;
20
use FastRoute\RouteParser\Std;
21
use Limoncello\Core\Contracts\Routing\DispatcherInterface;
22
use Limoncello\Core\Contracts\Routing\GroupInterface;
23
use Limoncello\Core\Contracts\Routing\RouteInterface;
24
use Limoncello\Core\Contracts\Routing\RouterInterface;
25
use LogicException;
26
27
/**
28
 * @package Limoncello\Core
29
 */
30
class Router implements RouterInterface
31
{
32
    /**
33
     * @var false|array
34
     */
35
    private $cachedRoutes = false;
36
37
    /**
38
     * @var string
39
     */
40
    private $generatorClass;
41
42
    /**
43
     * @var string
44
     */
45
    private $dispatcherClass;
46
47
    /**
48
     * @var DispatcherInterface
49
     */
50
    private $dispatcher;
51
52
    /**
53
     * @param string $generatorClass
54
     * @param string $dispatcherClass
55
     */
56 11
    public function __construct($generatorClass, $dispatcherClass)
57
    {
58 11
        $this->generatorClass  = $generatorClass;
59 11
        $this->dispatcherClass = $dispatcherClass;
60 11
    }
61
62
    /**
63
     * @inheritdoc
64
     */
65 10
    public function getCachedRoutes(GroupInterface $group)
66
    {
67 10
        $collector = $this->createRouteCollector();
68
69 10
        $routeIndex         = 0;
70 10
        $allRoutesInfo      = [];
71 10
        $namedRouteUriPaths = [];
72 10
        foreach ($group->getRoutes() as $route) {
73
            /** @var RouteInterface $route */
74 10
            $allRoutesInfo[] = [
75 10
                $route->getHandler(),
76 10
                $route->getMiddleware(),
77 10
                $route->getContainerConfigurators(),
78 10
                $route->getRequestFactory(),
79
            ];
80
81 10
            $routeName = $route->getName();
82 10
            if (empty($routeName) === false) {
83 5
                $namedRouteUriPaths[$routeName] = $route->getUriPath();
84 5
            }
85
86 10
            $collector->addRoute($route->getMethod(), $route->getUriPath(), $routeIndex);
87
88 10
            $routeIndex++;
89 10
        }
90
91 10
        return [$collector->getData(), $allRoutesInfo, $namedRouteUriPaths];
92
    }
93
94
    /**
95
     * @inheritdoc
96
     */
97 10
    public function loadCachedRoutes(array $cachedRoutes)
98
    {
99 10
        $this->cachedRoutes  = $cachedRoutes;
100 10
        list($collectorData) = $cachedRoutes;
101
102 10
        $this->dispatcher = $this->createDispatcher();
103 10
        $this->dispatcher->setData($collectorData);
104 10
    }
105
106
    /**
107
     * @inheritdoc
108
     */
109 11
    public function match($method, $uriPath)
110
    {
111 11
        $this->checkRoutesLoaded();
112
113 10
        $result = $this->dispatcher->dispatch($method, $uriPath);
114
115
        // Array contains matching result code, allowed methods list, handler parameters list, handler,
116
        // middleware list, container configurators list, custom request factory.
117 10
        switch ($result[0]) {
118 10
            case DispatcherInterface::FOUND:
119 8
                $routeIndex    = $result[1];
120 8
                $handlerParams = $result[2];
121
122 8
                list(, $allRoutesInfo) = $this->cachedRoutes;
123 8
                $routeInfo             = $allRoutesInfo[$routeIndex];
124
125 8
                return array_merge([self::MATCH_FOUND, null, $handlerParams], $routeInfo);
126
127 6
            case DispatcherInterface::METHOD_NOT_ALLOWED:
128 5
                $allowedMethods = $result[1];
129
130 5
                return [self::MATCH_METHOD_NOT_ALLOWED, $allowedMethods, null, null, null, null, null];
131
132 5
            default:
133 5
                return [self::MATCH_NOT_FOUND, null, null, null, null, null, null];
134 5
        }
135
    }
136
137
    /**
138
     * @inheritdoc
139
     */
140 4
    public function getUriPath($routeName)
141
    {
142 4
        $this->checkRoutesLoaded();
143
144 4
        list(, , $namedRouteUriPaths) = $this->cachedRoutes;
145
146 4
        $result = array_key_exists($routeName, $namedRouteUriPaths) === true ? $namedRouteUriPaths[$routeName] : null;
147
148 4
        return $result;
149
    }
150
151
    /**
152
     * @return RouteCollector
153
     */
154 10
    protected function createRouteCollector()
155
    {
156 10
        return new RouteCollector(new Std(), new $this->generatorClass);
157
    }
158
159
    /**
160
     * @return DispatcherInterface
161
     */
162 10
    protected function createDispatcher()
163
    {
164 10
        return new $this->dispatcherClass;
165
    }
166
167
    /**
168
     * @return void
169
     */
170 11
    private function checkRoutesLoaded()
171
    {
172 11
        if ($this->cachedRoutes === false) {
173 1
            throw new LogicException('Routes are not loaded yet.');
174
        }
175 10
    }
176
}
177