Completed
Push — master ( 2106b4...7c92dc )
by Jean-Christophe
01:31
created

CacheManager::getCacheInstance()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 10
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 10
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 7
nc 3
nop 3
1
<?php
2
3
namespace micro\cache;
4
5
use mindplay\annotations\Annotations;
6
use mindplay\annotations\AnnotationCache;
7
use mindplay\annotations\AnnotationManager;
8
use micro\orm\parser\ModelParser;
9
use micro\utils\JArray;
10
use micro\controllers\Router;
11
use micro\controllers\Startup;
12
use micro\utils\FsUtils;
13
use micro\cache\parser\ControllerParser;
14
use micro\cache\parser\RestControllerParser;
15
use micro\exceptions\RestException;
16
use micro\exceptions\RouterException;
17
18
class CacheManager {
19
	public static $cache;
20
	private static $cacheDirectory;
21
	private static $expiredRoutes=[ ];
22
23
	public static function start(&$config) {
24
		self::$cacheDirectory=self::initialGetCacheDirectory($config);
25
		$cacheDirectory=ROOT . DS . self::$cacheDirectory;
26
		Annotations::$config['cache']=new AnnotationCache($cacheDirectory . '/annotations');
27
		self::register(Annotations::getManager());
28
		self::getCacheInstance($config, $cacheDirectory, ".cache");
29
		//self::$cache=new ArrayCache($cacheDirectory, ".cache");
0 ignored issues
show
Unused Code Comprehensibility introduced by
72% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
30
	}
31
32
	public static function startProd(&$config) {
33
		self::$cacheDirectory=self::initialGetCacheDirectory($config);
34
		$cacheDirectory=ROOT . DS . self::$cacheDirectory;
35
		self::getCacheInstance($config,$cacheDirectory, ".cache");
36
	}
37
38
	protected static function getCacheInstance(&$config,$cacheDirectory,$postfix){
39
		$cacheSystem='micro\cache\ArrayCache';
40
		if(!isset(self::$cache)){
41
			if(isset($config["cache"]["system"])){
42
				$cacheSystem=$config["cache"]["system"];
43
			}
44
			self::$cache=new $cacheSystem($cacheDirectory,$postfix);
45
		}
46
		return self::$cache;
47
	}
48
49
	public static function getControllerCache($isRest=false) {
50
		$key=($isRest)?"rest":"default";
51
		if (self::$cache->exists("controllers/routes.".$key))
52
			return self::$cache->fetch("controllers/routes.".$key);
53
		return [];
54
		//throw new RouterException( $key." cache does not exist : the file `".FsUtils::cleanPathname(ROOT.DS.self::getCacheDirectory()."controllers/routes.").$key.".cache.php` is missing.\nTry to Re-init cache.");
0 ignored issues
show
Unused Code Comprehensibility introduced by
52% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
55
	}
56
57
	public static function getRestCache() {
58
		if (self::$cache->exists("controllers/rest"))
59
			return self::$cache->fetch("controllers/rest");
60
		throw new RestException("Rest cache does not exist : the file `".FsUtils::cleanPathname(ROOT.DS.self::getCacheDirectory()."controllers/")."rest.cache.php` is missing.\nTry to Re-init Rest cache.");
61
	}
62
63
	public static function getRouteCache($routePath, $duration) {
64
		$key=self::getRouteKey($routePath);
65
66
		if (self::$cache->exists("controllers/" . $key) && !self::expired($key, $duration)) {
67
			$response=self::$cache->file_get_contents("controllers/" . $key);
68
			return $response;
69
		} else {
70
			$response=Startup::runAsString($routePath);
71
			return self::storeRouteResponse($key, $response);
72
		}
73
	}
74
75
	public static function expired($key, $duration) {
76
		return self::$cache->expired("controllers/" . $key, $duration) === true || \array_key_exists($key, self::$expiredRoutes);
77
	}
78
79
	public static function isExpired($path,$duration){
80
		$route=Router::getRoute($path,false);
81
		if($route!==false && \is_array($route)){
82
			return self::expired(self::getRouteKey($route), $duration);
83
		}
84
		return true;
85
	}
86
87
	public static function setExpired($routePath, $expired=true) {
88
		$key=self::getRouteKey($routePath);
89
		self::setKeyExpired($key, $expired);
90
	}
91
92
	private static function setKeyExpired($key, $expired=true) {
93
		if ($expired) {
94
			self::$expiredRoutes[$key]=true;
95
		} else {
96
			unset(self::$expiredRoutes[$key]);
97
		}
98
	}
99
100
	public static function setRouteCache($routePath) {
101
		$key=self::getRouteKey($routePath);
102
		$response=Startup::runAsString($routePath);
103
		return self::storeRouteResponse($key, $response);
104
	}
105
106
	private static function storeRouteResponse($key, $response) {
107
		self::setKeyExpired($key, false);
108
		self::$cache->store("controllers/" . $key, $response, false);
109
		return $response;
110
	}
111
112
	private static function getRouteKey($routePath) {
113
		return "path" . \md5(\implode("", $routePath));
114
	}
115
116
	private static function initialGetCacheDirectory(&$config) {
117
		$cacheDirectory=@$config["cache"]["directory"];
118
		if (!isset($cacheDirectory)) {
119
			$config["cache"]["directory"]="cache/";
120
			$cacheDirectory=$config["cache"]["directory"];
121
		}
122
		return $cacheDirectory;
123
	}
124
125
	public static function getCacheDirectory() {
126
		return self::$cacheDirectory;
127
	}
128
129
	public static function createOrmModelCache($classname) {
130
		$key=self::getModelCacheKey($classname);
131
		if(isset(self::$cache)){
132
			if (!self::$cache->exists($key)) {
133
				$p=new ModelParser();
134
				$p->parse($classname);
135
				self::$cache->store($key, $p->__toString());
136
			}
137
			return self::$cache->fetch($key);
138
		}
139
	}
140
141
	public static function getOrmModelCache($classname) {
142
		return self::$cache->fetch(self::getModelCacheKey($classname));
143
	}
144
145
	public static function getModelCacheKey($classname){
146
		return \str_replace("\\", DIRECTORY_SEPARATOR, $classname);
147
	}
148
149
	public static function modelCacheExists($classname){
150
		$key=self::getModelCacheKey($classname);
151
		if(isset(self::$cache))
152
			return self::$cache->exists($key);
153
		return false;
154
	}
155
156
	private static function addControllerCache($classname) {
157
		$parser=new ControllerParser();
158
		try {
159
			$parser->parse($classname);
160
			return $parser->asArray();
161
		} catch ( \Exception $e ) {
162
			// Nothing to do
163
		}
164
		return [];
165
	}
166
167
	public static function checkCache(&$config,$silent=false) {
168
		$dirs=self::getCacheDirectories($config,$silent);
169
		foreach ($dirs as $dir){
170
			self::safeMkdir($dir);
171
		}
172
		return $dirs;
173
	}
174
175
	public static function getCacheDirectories(&$config,$silent=false){
176
		$cacheDirectory=self::initialGetCacheDirectory($config);
177
		if(!$silent){
178
			echo "cache directory is " . FsUtils::cleanPathname(ROOT . DS . $cacheDirectory) . "\n";
179
		}
180
		$modelsDir=str_replace("\\", DS, $config["mvcNS"]["models"]);
181
		$controllersDir=str_replace("\\", DS, $config["mvcNS"]["controllers"]);
182
		$annotationCacheDir=ROOT . DS . $cacheDirectory . DS . "annotations";
183
		$modelsCacheDir=ROOT . DS . $cacheDirectory . DS . $modelsDir;
184
		$queriesCacheDir=ROOT . DS . $cacheDirectory . DS . "queries";
185
		$controllersCacheDir=ROOT . DS . $cacheDirectory . DS . $controllersDir;
186
		$viewsCacheDir=ROOT . DS . $cacheDirectory . DS . "views";
187
		return [ "annotations" => $annotationCacheDir,"models" => $modelsCacheDir,"controllers" => $controllersCacheDir,"queries" => $queriesCacheDir ,"views"=>$viewsCacheDir];
188
	}
189
190
	private static function safeMkdir($dir) {
191
		if (!is_dir($dir))
192
			return mkdir($dir, 0777, true);
193
	}
194
195
	public static function clearCache(&$config, $type="all") {
196
		$cacheDirectories=self::checkCache($config);
197
		$cacheDirs=["annotations","controllers","models","queries","views"];
198
		foreach ($cacheDirs as $typeRef){
199
			self::_clearCache($cacheDirectories, $type, $typeRef);
200
		}
201
	}
202
203
	private static function _clearCache($cacheDirectories,$type,$typeRef){
204
		if ($type === "all" || $type === $typeRef)
205
			FsUtils::deleteAllFilesFromFolder($cacheDirectories[$typeRef]);
206
	}
207
208
	public static function initCache(&$config, $type="all",$silent=false) {
209
		self::checkCache($config,$silent);
210
		self::start($config);
211
		if ($type === "all" || $type === "models")
212
			self::initModelsCache($config,false,$silent);
213
		if ($type === "all" || $type === "controllers")
214
			self::initRouterCache($config,$silent);
215
		if ($type === "all" || $type === "rest")
216
			self::initRestCache($config,$silent);
217
	}
218
219
	public static function initModelsCache(&$config,$forChecking=false,$silent=false) {
220
		$files=self::getModelsFiles($config,$silent);
221
		foreach ( $files as $file ) {
222
			if (is_file($file)) {
223
				$model=ClassUtils::getClassFullNameFromFile($file);
224
				if(!$forChecking){
225
					self::createOrmModelCache($model);
226
				}
227
			}
228
		}
229
		if(!$silent){
230
			echo "Models cache reset\n";
231
		}
232
	}
233
234
	public static function getModelsFiles(&$config,$silent=false){
235
		return self::_getFiles($config, "models",$silent);
236
	}
237
238
	public static function getModels(&$config,$silent=false){
239
		$result=[];
240
		$files=self::getModelsFiles($config,$silent);
241
		foreach ($files as $file){
242
			$result[]=ClassUtils::getClassFullNameFromFile($file);
243
		}
244
		return $result;
245
	}
246
247
	public static function getControllersFiles(&$config,$silent=false){
248
		return self::_getFiles($config, "controllers",$silent);
249
	}
250
251
	private static function _getFiles(&$config,$type,$silent=false){
252
		$typeNS=$config["mvcNS"][$type];
253
		$typeDir=ROOT . DS . str_replace("\\", DS, $typeNS);
254
		if(!$silent)
255
			echo \ucfirst($type)." directory is " . ROOT . $typeNS . "\n";
256
		return FsUtils::glob_recursive($typeDir . DS . '*');
257
	}
258
259
	private static function initRouterCache(&$config,$silent=false) {
260
		$routes=["rest"=>[],"default"=>[]];
261
		$files=self::getControllersFiles($config);
262
		foreach ( $files as $file ) {
263
			if (is_file($file)) {
264
				$controller=ClassUtils::getClassFullNameFromFile($file);
265
				$parser=new ControllerParser();
266
				try {
267
					$parser->parse($controller);
268
					$ret= $parser->asArray();
269
					$key=($parser->isRest())?"rest":"default";
270
					$routes[$key]=\array_merge($routes[$key], $ret);
271
				} catch ( \Exception $e ) {
272
					// Nothing to do
273
				}
274
275
			}
276
		}
277
		self::$cache->store("controllers/routes.default", "return " . JArray::asPhpArray($routes["default"], "array") . ";");
278
		self::$cache->store("controllers/routes.rest", "return " . JArray::asPhpArray($routes["rest"], "array") . ";");
279
		if(!$silent){
280
			echo "Router cache reset\n";
281
		}
282
	}
283
284
	private static function initRestCache(&$config,$silent=false) {
285
		$restCache=[];
286
		$files=self::getControllersFiles($config);
287
		foreach ( $files as $file ) {
288
			if (is_file($file)) {
289
				$controller=ClassUtils::getClassFullNameFromFile($file);
290
				$parser=new RestControllerParser();
291
				$parser->parse($controller,$config);
292
				if($parser->isRest())
293
					$restCache=\array_merge($restCache,$parser->asArray());
294
			}
295
		}
296
		self::$cache->store("controllers/rest", "return " . JArray::asPhpArray($restCache, "array") . ";");
297
		if(!$silent){
298
			echo "Rest cache reset\n";
299
		}
300
	}
301
302
	private static function register(AnnotationManager $annotationManager) {
303
		$annotationManager->registry=array_merge($annotationManager->registry, [
304
				'id' => 'micro\annotations\IdAnnotation',
305
				'manyToOne' => 'micro\annotations\ManyToOneAnnotation',
306
				'oneToMany' => 'micro\annotations\OneToManyAnnotation',
307
				'manyToMany' => 'micro\annotations\ManyToManyAnnotation',
308
				'joinColumn' => 'micro\annotations\JoinColumnAnnotation',
309
				'table' => 'micro\annotations\TableAnnotation',
310
				'transient' => 'micro\annotations\TransientAnnotation',
311
				'column' => 'micro\annotations\ColumnAnnotation',
312
				'joinTable' => 'micro\annotations\JoinTableAnnotation',
313
				'route' => 'micro\annotations\router\RouteAnnotation',
314
				'var' => 'mindplay\annotations\standard\VarAnnotation',
315
				'yuml' => 'micro\annotations\YumlAnnotation',
316
				'rest' => 'micro\annotations\rest\RestAnnotation',
317
				'authorization' => 'micro\annotations\rest\AuthorizationAnnotation'
318
		]);
319
	}
320
321
	public static function addAdminRoutes() {
322
		self::addControllerCache("micro\controllers\Admin");
323
	}
324
325
	public static function getRoutes() {
326
		$result=self::getControllerCache();
327
		return $result;
328
	}
329
330
	public static function getRestRoutes() {
331
		$result=[];
332
		$restCache=self::getRestCache();
333
		foreach ($restCache as $controllerClass=>$restAttributes){
334
			if(isset($restCache[$controllerClass])){
335
				$result[$controllerClass]=["restAttributes"=>$restAttributes,"routes"=>self::getControllerRoutes($controllerClass,true)];
336
			}
337
		}
338
		return $result;
339
	}
340
341
	public static function getControllerRoutes($controllerClass,$isRest=false){
342
		$result=[];
343
		$ctrlCache=self::getControllerCache($isRest);
344
		foreach ($ctrlCache as $path=>$routeAttributes){
345
			if(isset($routeAttributes["controller"])){
346
				if($routeAttributes["controller"]===$controllerClass){
347
					$result[$path]=$routeAttributes;
348
				}
349
			}else{
350
				$firstValue=reset($routeAttributes);
351
				if(isset($firstValue)&&isset($firstValue["controller"])){
352
					if($firstValue["controller"]===$controllerClass){
353
						$result[$path]=$routeAttributes;
354
					}
355
				}
356
			}
357
		}
358
		return $result;
359
	}
360
361
	public static function getRestResource($controllerClass){
362
		$cacheControllerClass=self::getRestCacheController($controllerClass);
363
		if(isset($cacheControllerClass))
364
			return $cacheControllerClass["resource"];
365
		return null;
366
	}
367
368
	public static function getRestCacheController($controllerClass){
369
		$cache=self::getRestCache();
370
		if(isset($cache[$controllerClass])){
371
			return $cache[$controllerClass];
372
		}
373
		return null;
374
	}
375
376
377
	public static function addRoute($path, $controller, $action="index", $methods=null, $name="") {
378
		$controllerCache=self::getControllerCache();
379
		Router::addRouteToRoutes($controllerCache, $path, $controller, $action, $methods, $name);
380
		self::$cache->store("controllers/routes", "return " . JArray::asPhpArray($controllerCache, "array") . ";");
381
	}
382
}
383