Completed
Push — master ( af7267...09bff1 )
by Matthias
02:44
created

RouteManager::parseRouteParam()   B

Complexity

Conditions 5
Paths 3

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 10
rs 8.8571
c 0
b 0
f 0
cc 5
eloc 5
nc 3
nop 2
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
    public function __construct(Framework $framework, ObjectBackendAbstract $routeObjectBackend)
77
    {
78
        $this->framework = $framework;
79
        $this->routeObjectBackend = $routeObjectBackend;
80
    }
81
    
82
    /**
83
     * Initializes the routing table. The function loads
84
     * the saved routes from the object backend.
85
     * 
86
     * @access public
87
     */
88
    public function initializeRoutingTable()
89
    {
90
        $routes = $this->routeObjectBackend->loadObject();
91
        if (!is_array($routes)) {
92
            $routes = array();
93
        }
94
        
95
        $this->routes = $routes;
96
    }
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
    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
        if (!isset($this->routes[$priority])) {
112
            $this->routes[$priority] = array();
113
            ksort($this->routes);
114
        }
115
        
116
        // If we had the route already registred, return at this point
117
        if (isset($this->routes[$priority][$route])) {
118
            return true;
119
        }
120
        
121
        // Add the route and save the new routes array
122
        $this->routes[$priority][$route] = $eventName;
123
        $this->saveRoutes();
124
        
125
        return true;
126
    }
127
    
128
    /**
129
     * Removes a route for the given priority.
130
     * 
131
     * @access public
132
     * @param string $route
133
     * @param string $eventName
134
     * @param integer $priority
135
     * @return boolean
136
     */
137
    public function removeRoute($route, $eventName, $priority = 50)
0 ignored issues
show
Unused Code introduced by
The parameter $eventName is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
138
    {
139
        // If the priority isn't existing we return at this point
140
        if (!isset($this->routes[$priority])) {
141
            return true;
142
        }
143
        
144
        // If the route isn't registred we return with true.
145
        if (!isset($this->routes[$priority][$route])) {
146
            return true;
147
        }
148
        
149
        // Remove the route from the array
150
        unset($this->routes[$priority][$route]);
151
        $this->saveRoutes();
152
        
153
        return true;
154
    }
155
    
156
    /**
157
     * Clears the route cache and reactivates the modules
158
     * to rebuild the cache.
159
     * 
160
     * @access public
161
     * @param boolean $reactivateModules
162
     */
163
    public function clearCache($reactivateModules = true)
164
    {
165
        $this->routes = array();
166
        
167
        if ($reactivateModules) {
168
            $this->framework->getModuleManager()->reactivateModules();
169
        }
170
    }
171
    
172
    /**
173
     * Saves the routes in the object backend
174
     * 
175
     * @access protected
176
     */
177
    protected function saveRoutes()
178
    {
179
        $this->routeObjectBackend->saveObject($this->routes);
180
    }
181
    
182
    /**
183
     * Returns the event name for the given request. The function uses
184
     * the first possible match. The routes are sorted by the priority.
185
     * 
186
     * @access public
187
     * @param \Zepi\Turbo\Request\RequestAbstract $request
188
     * @return false|string
189
     */
190
    public function getEventNameForRoute(RequestAbstract $request)
191
    {
192
        // Loop trough the priorities
193
        foreach ($this->routes as $priority => $routes) {
194
            // Loop trough the routes for each priority
195
            foreach ($routes as $route => $eventName) {
196
                $result = $this->compareRoute($route, $request);
197
                
198
                if ($result) {
199
                    // The routes are equal - we have an event name
200
                    return $eventName;
201
                }
202
            }
203
        }
204
        
205
        return false;
206
    }
207
    
208
    /**
209
     * Compares the target route with the found route in the routing table.
210
     * 
211
     * @access protected
212
     * @param string $route
213
     * @param \Zepi\Turbo\Request\RequestAbstract $request
214
     * @return boolean
215
     */
216
    protected function compareRoute($route, RequestAbstract $request)
217
    {
218
        // Replace the normal route delimiter with the request route delimiter
219
        $route = str_replace('|', $request->getRouteDelimiter(), $route);
220
        
221
        // Split the two routes into parts
222
        $routeParts = explode($request->getRouteDelimiter(), $route);
223
        $targetRouteParts = explode($request->getRouteDelimiter(), trim($request->getRoute(), '/'));
224
        $numberOfTargetRouteParts = count($targetRouteParts);
225
        
226
        // If we have different number of parts between the two routes
227
        // there are not equal so we have no equal route.
228
        if (count($routeParts) != $numberOfTargetRouteParts) {
229
            return false;
230
        }
231
        
232
        // Define the data types
233
        $dataTypes = array('[d]', '[s]');
234
        $routeParams = array();
235
        
236
        // Loop through the route parts and compare each part
237
        for ($pos = 0; $pos < $numberOfTargetRouteParts; $pos++) {
238
            $part = $routeParts[$pos];
239
            $targetPart = $targetRouteParts[$pos];
240
241
            if (in_array($part, $dataTypes) && $targetPart != '') {
242
                $routeParams[] = $this->parseRouteParam($part, $targetPart);
243
            } else if ($part !== $targetPart) {
244
                // The part isn't equal == the route can't be equal
245
                return false;
246
            }
247
        }
248
        
249
        // Save the route parameters in the request
250
        $request->setRouteParams($routeParams);
251
        
252
        return true;
253
    }
254
    
255
    /**
256
     * Parses the route param data to the correct format
257
     * 
258
     * @access protected
259
     * @param string $part
260
     * @param string $targetPart
261
     * @return mixed
262
     */
263
    protected function parseRouteParam($part, $targetPart)
264
    {
265
        // If the part is a data type we need this route parameter
266
        if ($part === '[d]' && is_numeric($targetPart)) {
267
            // Transform the value into the correct data type
268
            return $targetPart * 1;
269
        } else if ($part === '[s]' && is_string($targetPart)) {
270
            return $targetPart;
271
        }
272
    }
273
}
274