Passed
Push — master ( 570be6...1a3368 )
by Jean-Christophe
01:28
created

Router::path()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

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