Test Failed
Push — master ( 26590d...3034a5 )
by Jean-Christophe
14:48 queued 27s
created

RouterCacheTrait::parseControllerFiles()   A

Complexity

Conditions 5
Paths 9

Size

Total Lines 20
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 5

Importance

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