Passed
Push — master ( ce58fd...b8d195 )
by Matthias
02:26
created

RouteManager   A

Complexity

Total Complexity 27

Size/Duplication

Total Lines 224
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Test Coverage

Coverage 98.48%

Importance

Changes 0
Metric Value
wmc 27
c 0
b 0
f 0
lcom 1
cbo 4
dl 0
loc 224
ccs 65
cts 66
cp 0.9848
rs 10

9 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A initializeRoutingTable() 0 9 2
A addRoute() 0 20 3
A removeRoute() 0 18 3
A getEventNameForRoute() 0 17 4
B compareRoute() 0 38 6
A clearCache() 0 8 2
A saveRoutes() 0 4 1
B parseRouteParam() 0 10 5
1
<?php
2
/*
3
 * The MIT License (MIT)
4
 *
5
 * Copyright (c) 2015 zepi
6
 *
7
 * Permission is hereby granted, free of charge, to any person obtaining a copy
8
 * of this software and associated documentation files (the "Software"), to deal
9
 * in the Software without restriction, including without limitation the rights
10
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
 * copies of the Software, and to permit persons to whom the Software is
12
 * furnished to do so, subject to the following conditions:
13
 *
14
 * The above copyright notice and this permission notice shall be included in
15
 * all copies or substantial portions of the Software.
16
 *
17
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
 * THE SOFTWARE.
24
 *
25
 */
26
27
/**
28
 * The RouteManager registers and manages all routes. The
29
 * routes are saved in an object backend.
30
 * 
31
 * @package Zepi\Turbo\Manager
32
 * @author Matthias Zobrist <[email protected]>
33
 * @copyright Copyright (c) 2015 zepi
34
 */
35
36
namespace Zepi\Turbo\Manager;
37
38
use \Zepi\Turbo\Framework;
39
use \Zepi\Turbo\Backend\ObjectBackendAbstract;
40
use \Zepi\Turbo\Request\RequestAbstract;
41
42
/**
43
 * The RouteManager registers and manages all routes. The
44
 * routes are saved in an object backend.
45
 * 
46
 * @author Matthias Zobrist <[email protected]>
47
 * @copyright Copyright (c) 2015 zepi
48
 */
49
class RouteManager
50
{
51
    /**
52
     * @access protected
53
     * @var Framework
54
     */
55
    protected $framework;
56
    
57
    /**
58
     * @access protected
59
     * @var ObjectBackendAbstract
60
     */
61
    protected $routeObjectBackend;
62
    
63
    /**
64
     * @access protected
65
     * @var array
66
     */
67
    protected $routes = array();
68
    
69
    /**
70
     * Constructs the object
71
     * 
72
     * @access public
73
     * @param \Zepi\Turbo\Framework $framework
74
     * @param \Zepi\Turbo\Backend\ObjectBackendAbstract $routeObjectBackend
75
     */
76 26
    public function __construct(Framework $framework, ObjectBackendAbstract $routeObjectBackend)
77
    {
78 26
        $this->framework = $framework;
79 26
        $this->routeObjectBackend = $routeObjectBackend;
80 26
    }
81
    
82
    /**
83
     * Initializes the routing table. The function loads
84
     * the saved routes from the object backend.
85
     * 
86
     * @access public
87
     */
88 26
    public function initializeRoutingTable()
89
    {
90 26
        $routes = $this->routeObjectBackend->loadObject();
91 26
        if (!is_array($routes)) {
92 26
            $routes = array();
93
        }
94
        
95 26
        $this->routes = $routes;
96 26
    }
97
    
98
    /**
99
     * Adds an event handler for the given event.
100
     * 
101
     * @access public
102
     * @param string $route
103
     * @param string $eventName
104
     * @param integer $priority
105
     * @return boolean
106
     */
107 8
    public function addRoute($route, $eventName, $priority = 50)
108
    {
109
        // If the priority isn't existing we add the priority as 
110
        // a new array.
111 8
        if (!isset($this->routes[$priority])) {
112 8
            $this->routes[$priority] = array();
113 8
            ksort($this->routes);
114
        }
115
        
116
        // If we had the route already registred, return at this point
117 8
        if (isset($this->routes[$priority][$route])) {
118 1
            return true;
119
        }
120
        
121
        // Add the route and save the new routes array
122 8
        $this->routes[$priority][$route] = $eventName;
123 8
        $this->saveRoutes();
124
        
125 8
        return true;
126
    }
127
    
128
    /**
129
     * Removes a route for the given priority.
130
     * 
131
     * @access public
132
     * @param string $route
133
     * @param integer $priority
134
     * @return boolean
135
     */
136 3
    public function removeRoute($route, $priority = 50)
137
    {
138
        // If the priority isn't existing we return at this point
139 3
        if (!isset($this->routes[$priority])) {
140 1
            return true;
141
        }
142
        
143
        // If the route isn't registred we return with true.
144 2
        if (!isset($this->routes[$priority][$route])) {
145 1
            return true;
146
        }
147
        
148
        // Remove the route from the array
149 2
        unset($this->routes[$priority][$route]);
150 2
        $this->saveRoutes();
151
        
152 2
        return true;
153
    }
154
    
155
    /**
156
     * Clears the route cache and reactivates the modules
157
     * to rebuild the cache.
158
     * 
159
     * @access public
160
     * @param boolean $reactivateModules
161
     */
162 1
    public function clearCache($reactivateModules = true)
163
    {
164 1
        $this->routes = array();
165
        
166 1
        if ($reactivateModules) {
167 1
            $this->framework->getModuleManager()->reactivateModules();
168
        }
169 1
    }
170
    
171
    /**
172
     * Saves the routes in the object backend
173
     * 
174
     * @access protected
175
     */
176 8
    protected function saveRoutes()
177
    {
178 8
        $this->routeObjectBackend->saveObject($this->routes);
179 8
    }
180
    
181
    /**
182
     * Returns the event name for the given request. The function uses
183
     * the first possible match. The routes are sorted by the priority.
184
     * 
185
     * @access public
186
     * @param \Zepi\Turbo\Request\RequestAbstract $request
187
     * @return false|string
188
     */
189 10
    public function getEventNameForRoute(RequestAbstract $request)
190
    {
191
        // Loop trough the priorities
192 10
        foreach ($this->routes as $priority => $routes) {
193
            // Loop trough the routes for each priority
194 8
            foreach ($routes as $route => $eventName) {
195 8
                $result = $this->compareRoute($route, $request);
196
                
197 8
                if ($result) {
198
                    // The routes are equal - we have an event name
199 8
                    return $eventName;
200
                }
201
            }
202
        }
203
        
204 6
        return false;
205
    }
206
    
207
    /**
208
     * Compares the target route with the found route in the routing table.
209
     * 
210
     * @access protected
211
     * @param string $route
212
     * @param \Zepi\Turbo\Request\RequestAbstract $request
213
     * @return boolean
214
     */
215 8
    protected function compareRoute($route, RequestAbstract $request)
216
    {
217
        // Replace the normal route delimiter with the request route delimiter
218 8
        $route = str_replace('|', $request->getRouteDelimiter(), $route);
219
        
220
        // Split the two routes into parts
221 8
        $routeParts = explode($request->getRouteDelimiter(), $route);
222 8
        $targetRouteParts = explode($request->getRouteDelimiter(), trim($request->getRoute(), '/'));
223 8
        $numberOfTargetRouteParts = count($targetRouteParts);
224
        
225
        // If we have different number of parts between the two routes
226
        // there are not equal so we have no equal route.
227 8
        if (count($routeParts) != $numberOfTargetRouteParts) {
228 1
            return false;
229
        }
230
        
231
        // Define the data types
232 7
        $dataTypes = array('[d]', '[s]');
233 7
        $routeParams = array();
234
        
235
        // Loop through the route parts and compare each part
236 7
        for ($pos = 0; $pos < $numberOfTargetRouteParts; $pos++) {
237 7
            $part = $routeParts[$pos];
238 7
            $targetPart = $targetRouteParts[$pos];
239
240 7
            if (in_array($part, $dataTypes) && $targetPart != '') {
241 1
                $routeParams[] = $this->parseRouteParam($part, $targetPart);
242 7
            } else if ($part !== $targetPart) {
243
                // The part isn't equal == the route can't be equal
244 1
                return false;
245
            }
246
        }
247
        
248
        // Save the route parameters in the request
249 6
        $request->setRouteParams($routeParams);
250
        
251 6
        return true;
252
    }
253
    
254
    /**
255
     * Parses the route param data to the correct format
256
     * 
257
     * @access protected
258
     * @param string $part
259
     * @param string $targetPart
260
     * @return mixed
261
     */
262 1
    protected function parseRouteParam($part, $targetPart)
263
    {
264
        // If the part is a data type we need this route parameter
265 1
        if ($part === '[d]' && is_numeric($targetPart)) {
266
            // Transform the value into the correct data type
267 1
            return $targetPart * 1;
268 1
        } else if ($part === '[s]' && is_string($targetPart)) {
269 1
            return $targetPart;
270
        }
271
    }
272
}
273