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

RouterCacheTrait::parseControllerFiles()   A

Complexity

Conditions 5
Paths 9

Size

Total Lines 20
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 5.0073

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 15
dl 0
loc 20
ccs 14
cts 15
cp 0.9333
rs 9.4555
c 2
b 0
f 0
cc 5
nc 9
nop 2
crap 5.0073
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