Passed
Push — master ( 934f11...8ba0cf )
by Jean-Christophe
10:32
created

RouterCacheTrait::addRoute()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 4
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 3
c 2
b 0
f 0
dl 0
loc 4
ccs 4
cts 4
cp 1
rs 10
cc 2
nc 1
nop 8
crap 2

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
namespace Ubiquity\cache\traits;
4
5
use Ubiquity\controllers\Startup;
6
use Ubiquity\controllers\Router;
7
use Ubiquity\cache\parser\ControllerParser;
8
use Ubiquity\cache\ClassUtils;
9
use Ubiquity\utils\base\UArray;
10
use Ubiquity\cache\CacheManager;
11
use Ubiquity\controllers\di\DiManager;
12
use Ubiquity\utils\base\UIntrospection;
13
use Ubiquity\controllers\Controller;
14
use Ubiquity\controllers\StartupAsync;
15
use Ubiquity\utils\http\UResponse;
16
17
/**
18
 *
19
 * Ubiquity\cache\traits$RouterCacheTrait
20
 * This class is part of Ubiquity
21
 *
22
 * @author jcheron <[email protected]>
23
 * @version 1.0.9
24
 * @property \Ubiquity\cache\system\AbstractDataCache $cache
25
 *
26
 */
27
trait RouterCacheTrait {
28
29
	abstract protected static function _getFiles(&$config, $type, $silent = false);
30
31
	private static function addControllerCache($classname) {
32
		$parser = new ControllerParser ();
33
		try {
34
			$parser->parse ( $classname );
35
			return $parser->asArray ();
36
		} catch ( \Exception $e ) {
37
			// Nothing to do
38
		}
39
		return [ ];
40
	}
41
42 16
	private static function parseControllerFiles(&$config, $silent = false) {
43 16
		$routes = [ 'rest' => [ ],'default' => [ ] ];
44 16
		$files = self::getControllersFiles ( $config, $silent );
45 16
		foreach ( $files as $file ) {
46 16
			if (is_file ( $file )) {
47 16
				$controller = ClassUtils::getClassFullNameFromFile ( $file );
48 16
				$parser = new ControllerParser ();
49
				try {
50 16
					$parser->parse ( $controller );
51 16
					$ret = $parser->asArray ();
52 16
					$key = ($parser->isRest ()) ? 'rest' : 'default';
53 16
					$routes [$key] = \array_merge ( $routes [$key], $ret );
54
				} catch ( \Exception $e ) {
55
					// Nothing to do
56
				}
57
			}
58
		}
59 16
		self::sortByPriority ( $routes ['default'] );
60 16
		self::sortByPriority ( $routes ['rest'] );
61 16
		return $routes;
62
	}
63
64 16
	protected static function sortByPriority(&$array) {
65
		\uasort ( $array, function ($item1, $item2) {
66 16
			return UArray::getRecursive ( $item2, 'priority', 0 ) <=> UArray::getRecursive ( $item1, 'priority', 0 );
67 16
		} );
68 16
		UArray::removeRecursive ( $array, 'priority' );
69 16
	}
70
71 8
	private static function initRouterCache(&$config, $silent = false) {
72 8
		$routes = self::parseControllerFiles ( $config, $silent );
73 8
		self::$cache->store ( 'controllers/routes.default', $routes ['default'], 'controllers' );
74 8
		self::$cache->store ( 'controllers/routes.rest', $routes ['rest'], 'controllers' );
75 8
		DiManager::init ( $config );
76 8
		if (! $silent) {
77 8
			echo "Router cache reset\n";
78
		}
79 8
	}
80
81 10
	public static function controllerCacheUpdated(&$config) {
82 10
		$result = false;
83 10
		$newRoutes = self::parseControllerFiles ( $config, true );
84 10
		$ctrls = self::getControllerCache ();
85 10
		if ($newRoutes ['default'] != $ctrls) {
86 2
			$result ['default'] = true;
87
		}
88 10
		$ctrls = self::getControllerCache ( true );
89 10
		if ($newRoutes ['rest'] != $ctrls) {
90
			$result ['rest'] = true;
91
		}
92 10
		return $result;
93
	}
94
95
	public static function storeDynamicRoutes($isRest = false) {
96
		$routes = Router::getRoutes ();
97
		$part = ($isRest) ? 'rest' : 'default';
98
		self::$cache->store ( 'controllers/routes.' . $part, $routes, 'controllers' );
99
	}
100
101
	private static function storeRouteResponse($key, $response) {
102
		$cache = [ 'content-type' => UResponse::$headers ['Content-Type'] ?? 'text/html','content' => $response ];
103
		self::$cache->store ( 'controllers/' . $key, $cache, 'controllers' );
104
		return $response;
105
	}
106
107 1
	private static function getRouteKey($routePath) {
108 1
		if (\is_array ( $routePath )) {
109
			return 'path' . \md5 ( \implode ( '', $routePath ) );
110
		}
111 1
		return 'path' . \md5 ( Router::slashPath ( $routePath ) );
112
	}
113
114
	/**
115
	 *
116
	 * @param boolean $isRest
117
	 * @return array
118
	 */
119 77
	public static function getControllerCache($isRest = false) {
120 77
		$key = ($isRest) ? 'rest' : 'default';
121 77
		if (self::$cache->exists ( 'controllers/routes.' . $key ))
122 77
			return self::$cache->fetch ( 'controllers/routes.' . $key );
123
		return [ ];
124
	}
125
126
	public static function getRouteCache($routePath, $routeArray, $duration) {
127
		$key = self::getRouteKey ( $routePath );
128
129
		if (self::$cache->exists ( 'controllers/' . $key ) && ! self::expired ( $key, $duration )) {
130
			$response = self::$cache->fetch ( 'controllers/' . $key );
131
			if ($ct = $response ['content-type'] ?? false) {
132
				UResponse::setContentType ( $ct );
133
			}
134
			return $response ['content'] ?? '';
135
		} else {
136
			$response = Startup::runAsString ( $routeArray );
137
			return self::storeRouteResponse ( $key, $response );
138
		}
139
	}
140
141
	protected static function expired($key, $duration) {
142
		return self::$cache->expired ( "controllers/" . $key, $duration ) === true;
143
	}
144
145
	public static function isExpired($routePath, $duration) {
146
		return self::expired ( self::getRouteKey ( $routePath ), $duration );
147
	}
148
149 1
	public static function setExpired($routePath) {
150 1
		$key = self::getRouteKey ( $routePath );
151 1
		if (self::$cache->exists ( 'controllers/' . $key )) {
152
			self::$cache->remove ( 'controllers/' . $key );
153
		}
154 1
	}
155
156
	public static function setRouteCache($routePath) {
157
		$key = self::getRouteKey ( $routePath );
158
		$response = Startup::runAsString ( $routePath );
159
		return self::storeRouteResponse ( $key, $response );
160
	}
161
162
	public static function addAdminRoutes() {
163
		self::addControllerCache ( 'Ubiquity\controllers\Admin' );
164
	}
165
166 2
	public static function getRoutes() {
167 2
		$result = self::getControllerCache ();
168 2
		return $result;
169
	}
170
171 1
	public static function getControllerRoutes($controllerClass, $isRest = false) {
172 1
		$result = [ ];
173 1
		$ctrlCache = self::getControllerCache ( $isRest );
174 1
		foreach ( $ctrlCache as $path => $routeAttributes ) {
175 1
			if (isset ( $routeAttributes ['controller'] )) {
176 1
				if ($routeAttributes ['controller'] === $controllerClass) {
177 1
					$result [$path] = $routeAttributes;
178
				}
179
			} else {
180 1
				$firstValue = current ( $routeAttributes );
181 1
				if (isset ( $firstValue ) && isset ( $firstValue ['controller'] )) {
182 1
					if ($firstValue ['controller'] === $controllerClass) {
183 1
						$result [$path] = $routeAttributes;
184
					}
185
				}
186
			}
187
		}
188 1
		return $result;
189
	}
190
191 1
	public static function addRoute($path, $controller, $action = 'index', $methods = null, $name = '', $isRest = false, $priority = 0, $callback = null) {
192 1
		$controllerCache = self::getControllerCache ( $isRest );
193 1
		Router::addRouteToRoutes ( $controllerCache, $path, $controller, $action, $methods, $name, false, null, [ ], $priority, $callback );
194 1
		self::$cache->store ( 'controllers/routes.' . ($isRest ? 'rest' : 'default'), $controllerCache, 'controllers' );
195 1
	}
196
197
	public static function addRoutes($pathArray, $controller, $action = 'index', $methods = null, $name = '') {
198
		self::addRoutes_ ( $pathArray, $controller, $action, $methods, $name, false );
199
	}
200
201
	public static function addRestRoutes($pathArray, $controller, $action = 'index', $methods = null, $name = '') {
202
		self::addRoutes_ ( $pathArray, $controller, $action, $methods, $name, true );
203
	}
204
205
	private static function addRoutes_($pathArray, $controller, $action = 'index', $methods = null, $name = '', $isRest = false) {
206
		$controllerCache = self::getControllerCache ( $isRest );
207
		$postfix = 'default';
208
		if ($isRest) {
209
			$postfix = 'rest';
210
		}
211
		Router::addRoutesToRoutes ( $controllerCache, $pathArray, $controller, $action, $methods, $name );
212
		self::$cache->store ( 'controllers/routes.' . $postfix, $controllerCache, 'controllers' );
213
	}
214
215 16
	public static function getControllersFiles(&$config, $silent = false) {
216 16
		return self::_getFiles ( $config, 'controllers', $silent );
217
	}
218
219 10
	public static function getControllers($subClass = "\\Ubiquity\\controllers\\Controller", $backslash = false, $includeSubclass = false, $includeAbstract = false) {
220 10
		$result = [ ];
221 10
		if ($includeSubclass) {
222 1
			$result [] = $subClass;
223
		}
224 10
		$config = Startup::getConfig ();
225 10
		$files = self::getControllersFiles ( $config, true );
226
		try {
227 10
			$restCtrls = CacheManager::getRestCache ();
228
		} catch ( \Exception $e ) {
229
			$restCtrls = [ ];
230
		}
231 10
		foreach ( $files as $file ) {
232 10
			if (\is_file ( $file )) {
233 10
				$controllerClass = ClassUtils::getClassFullNameFromFile ( $file, $backslash );
234 10
				if (\class_exists ( $controllerClass ) && isset ( $restCtrls [$controllerClass] ) === false) {
235 10
					$r = new \ReflectionClass ( $controllerClass );
236 10
					if ($r->isSubclassOf ( $subClass ) && ($includeAbstract || ! $r->isAbstract ())) {
237 10
						$result [] = $controllerClass;
238
					}
239
				}
240
			}
241
		}
242 10
		return $result;
243
	}
244
245
	/**
246
	 * Preloads controllers.
247
	 * To use only with async servers (Swoole, Workerman)
248
	 *
249
	 * @param ?array $controllers
250
	 */
251
	public static function warmUpControllers($controllers = null) {
252
		$controllers = $controllers ?? self::getControllers ();
253
		foreach ( $controllers as $ctrl ) {
254
			$controller = StartupAsync::getControllerInstance ( $ctrl );
255
			$binary = UIntrospection::implementsMethod ( $controller, 'isValid', Controller::class ) ? 1 : 0;
256
			$binary += UIntrospection::implementsMethod ( $controller, 'initialize', Controller::class ) ? 2 : 0;
257
			$binary += UIntrospection::implementsMethod ( $controller, 'finalize', Controller::class ) ? 4 : 0;
258
			$controller->_binaryCalls = $binary;
259
		}
260
	}
261
}
262