Completed
Push — master ( 8e1c51...cf1361 )
by Jean-Christophe
04:46
created

Router   B

Complexity

Total Complexity 44

Size/Duplication

Total Lines 198
Duplicated Lines 0 %

Test Coverage

Coverage 53.68%

Importance

Changes 0
Metric Value
wmc 44
eloc 83
dl 0
loc 198
ccs 51
cts 95
cp 0.5368
rs 8.8798
c 0
b 0
f 0

16 Methods

Rating   Name   Duplication   Size   Complexity  
A cleanParam() 0 4 2
A getRoute() 0 12 4
A startAll() 0 2 1
A setParamsInOrder() 0 18 6
A getRouteUrlParts() 0 19 6
A setExpired() 0 2 1
A start() 0 2 1
A _getURL() 0 8 2
A slashPath() 0 6 3
A url() 0 2 1
A startRest() 0 2 1
A getRoute_() 0 11 3
A checkRouteName() 0 8 6
A path() 0 2 1
A getRouteByName() 0 12 5
A getRoutes() 0 2 1

How to fix   Complexity   

Complex Class

Complex classes like Router often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Router, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace Ubiquity\controllers;
4
5
use Ubiquity\cache\CacheManager;
6
use Ubiquity\utils\http\URequest;
7
use Ubiquity\utils\base\UString;
8
use Ubiquity\log\Logger;
9
use Ubiquity\controllers\traits\RouterModifierTrait;
10
use Ubiquity\controllers\traits\RouterAdminTrait;
11
12
/**
13
 * Router manager
14
 * This class is part of Ubiquity
15
 *
16
 * @author jcheron <[email protected]>
17
 * @version 1.0.3
18
 */
19
class Router {
20
	use RouterModifierTrait,RouterAdminTrait;
21
	protected static $routes;
22
23
	/**
24
	 * Starts the router by loading normal routes (not rest)
25
	 */
26 11
	public static function start() {
27 11
		self::$routes = CacheManager::getControllerCache ();
28 11
	}
29
30
	/**
31
	 * Starts the router by loading rest routes (not normal routes)
32
	 */
33 1
	public static function startRest() {
34 1
		self::$routes = CacheManager::getControllerCache ( true );
35 1
	}
36
37
	/**
38
	 * Starts the router by loading all routes (normal + rest routes)
39
	 */
40
	public static function startAll() {
41
		self::$routes = array_merge ( CacheManager::getControllerCache (), CacheManager::getControllerCache ( true ) );
42
	}
43
44
	/**
45
	 * Returns the route corresponding to a path
46
	 *
47
	 * @param string $path
48
	 * @param boolean $cachedResponse
49
	 * @return boolean|mixed[]|string
50
	 */
51 5
	public static function getRoute($path, $cachedResponse = true) {
52 5
		$path = self::slashPath ( $path );
53 5
		if (isset ( self::$routes [$path] )) {
54 4
			return self::getRoute_ ( self::$routes [$path], $path, [ $path ], $cachedResponse );
55
		}
56 5
		foreach ( self::$routes as $routePath => $routeDetails ) {
57 5
			if (preg_match ( "@^" . $routePath . "$@s", $path, $matches )) {
58 5
				return self::getRoute_ ( $routeDetails, $routePath, $matches, $cachedResponse );
59
			}
60
		}
61 5
		Logger::warn ( "Router", "No route found for {$path}", "getRoute" );
62 5
		return false;
63
	}
64
65 4
	private static function getRoute_(&$routeDetails, $routePath, $matches, $cachedResponse) {
66 4
		if (! isset ( $routeDetails ["controller"] )) {
67
			$method = URequest::getMethod ();
68
			if (isset ( $routeDetails [$method] )) {
69
				$routeDetailsMethod = $routeDetails [$method];
70
				return self::getRouteUrlParts ( [ "path" => $routePath,"details" => $routeDetailsMethod ], $matches, $routeDetailsMethod ["cache"] ?? false, $routeDetailsMethod ["duration"] ?? null, $cachedResponse );
71
			}
72
		} else {
73 4
			return self::getRouteUrlParts ( [ "path" => $routePath,"details" => $routeDetails ], $matches, $routeDetails ["cache"] ?? false, $routeDetails ["duration"] ?? null, $cachedResponse );
74
		}
75
		return false;
76
	}
77
78
	/**
79
	 * Returns the generated path from a route
80
	 *
81
	 * @param string $name
82
	 *        	name of the route
83
	 * @param array $parameters
84
	 *        	array of the route parameters. default : []
85
	 * @param boolean $absolute
86
	 */
87
	public static function getRouteByName($name, $parameters = [], $absolute = true) {
88
		foreach ( self::$routes as $routePath => $routeDetails ) {
89
			if (self::checkRouteName ( $routeDetails, $name )) {
90
				if (\sizeof ( $parameters ) > 0)
91
					$routePath = self::_getURL ( $routePath, $parameters );
92
				if (! $absolute)
93
					return \ltrim ( $routePath, '/' );
94
				else
95
					return $routePath;
96
			}
97
		}
98
		return false;
99
	}
100
101
	/**
102
	 * Returns the generated path from a route
103
	 *
104
	 * @param string $name
105
	 *        	the route name
106
	 * @param array $parameters
107
	 *        	default: []
108
	 * @param boolean $absolute
109
	 *        	true if the path is absolute (/ at first)
110
	 * @return boolean|string|array|mixed the generated path (/path/to/route)
111
	 */
112
	public static function path($name, $parameters = [], $absolute = false) {
113
		return self::getRouteByName ( $name, $parameters, $absolute );
114
	}
115
116
	/**
117
	 * Returns the generated url from a route
118
	 *
119
	 * @param string $name
120
	 *        	the route name
121
	 * @param array $parameters
122
	 *        	default: []
123
	 * @return string the generated url (http://myApp/path/to/route)
124
	 */
125
	public static function url($name, $parameters = []) {
126
		return URequest::getUrl ( self::getRouteByName ( $name, $parameters, false ) );
127
	}
128
129
	protected static function _getURL($routePath, $params) {
130
		$result = \preg_replace_callback ( '~\((.*?)\)~', function () use (&$params) {
131
			return array_shift ( $params );
132
		}, $routePath );
133
		if (\sizeof ( $params ) > 0) {
134
			$result = \rtrim ( $result, '/' ) . '/' . \implode ( '/', $params );
135
		}
136
		return $result;
137
	}
138
139
	protected static function checkRouteName($routeDetails, $name) {
140
		if (! isset ( $routeDetails ["name"] )) {
141
			foreach ( $routeDetails as $methodRouteDetail ) {
142
				if (isset ( $methodRouteDetail ["name"] ) && $methodRouteDetail == $name)
143
					return true;
144
			}
145
		}
146
		return isset ( $routeDetails ["name"] ) && $routeDetails ["name"] == $name;
147
	}
148
149 4
	public static function getRouteUrlParts($routeArray, $params, $cached = false, $duration = NULL, $cachedResponse = true) {
150 4
		\array_shift ( $params );
151 4
		$routeDetails = $routeArray ["details"];
152 4
		if (is_callable ( $routeDetails ["controller"] )) {
153
			$result = [ $routeDetails ["controller"] ];
154
			$resultStr = "callable function";
155
		} else {
156 4
			$result = [ str_replace ( "\\\\", "\\", $routeDetails ["controller"] ),$routeDetails ["action"] ];
157 4
			$resultStr = implode ( "/", $result );
158
		}
159 4
		if (($paramsOrder = $routeDetails ["parameters"]) && (sizeof ( $paramsOrder ) > 0)) {
160 2
			self::setParamsInOrder ( $result, $paramsOrder, $params );
161
		}
162 4
		if (! $cached || ! $cachedResponse) {
163 4
			Logger::info ( 'Router', sprintf ( 'Route found for %s : %s', $routeArray ["path"], $resultStr ), 'getRouteUrlParts' );
164 4
			return $result;
165
		}
166
		Logger::info ( 'Router', sprintf ( 'Route found for %s (from cache) : %s', $routeArray ["path"], $resultStr ), 'getRouteUrlParts' );
167
		return CacheManager::getRouteCache ( $result, $duration );
168
	}
169
170 2
	protected static function setParamsInOrder(&$routeUrlParts, $paramsOrder, $params) {
171 2
		$index = 0;
172 2
		foreach ( $paramsOrder as $order ) {
173 2
			if ($order === '*') {
174
				if (isset ( $params [$index] ))
175
					$routeUrlParts = \array_merge ( $routeUrlParts, \array_diff ( \explode ( "/", $params [$index] ), [ "" ] ) );
176
				break;
177
			}
178 2
			if ($order [0] === '~') {
179 2
				$order = \intval ( \substr ( $order, 1, 1 ) );
180 2
				if (isset ( $params [$order] )) {
181 2
					$routeUrlParts = \array_merge ( $routeUrlParts, \array_diff ( \explode ( "/", $params [$order] ), [ "" ] ) );
182 2
					break;
183
				}
184
			}
185 2
			$routeUrlParts [] = self::cleanParam ( $params [$order] );
186 2
			unset ( $params [$order] );
187 2
			$index ++;
188
		}
189 2
	}
190
191 2
	private static function cleanParam($param) {
192 2
		if (UString::endswith ( $param, "/" ))
193
			return \substr ( $param, 0, - 1 );
194 2
		return $param;
195
	}
196
197 5
	protected static function slashPath($path) {
198 5
		if (UString::startswith ( $path, "/" ) === false)
199 5
			$path = "/" . $path;
200 5
		if (! UString::endswith ( $path, "/" ))
201 5
			$path = $path . "/";
202 5
		return $path;
203
	}
204
205
	/**
206
	 * Declare a route as expired or not
207
	 *
208
	 * @param string $routePath
209
	 * @param boolean $expired
210
	 */
211
	public static function setExpired($routePath, $expired = true) {
212
		CacheManager::setExpired ( $routePath, $expired );
213
	}
214
215
	public static function getRoutes() {
216
		return self::$routes;
217
	}
218
}
219