Passed
Push — master ( f0ea68...084641 )
by Jean-Christophe
06:04
created

Router::getRouteByName()   A

Complexity

Conditions 5
Paths 6

Size

Total Lines 12
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 5.2742

Importance

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