Completed
Push — master ( 1f65a3...0feaa6 )
by Jean-Christophe
01:28
created

CacheManager::expired()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 3
rs 10
cc 2
eloc 2
nc 2
nop 2
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
16
class CacheManager {
17
	public static $cache;
18
	private static $routes=[ ];
19
	private static $cacheDirectory;
20
	private static $expiredRoutes=[ ];
21
22
	public static function start(&$config) {
23
		self::$cacheDirectory=self::initialGetCacheDirectory($config);
24
		$cacheDirectory=ROOT . DS . self::$cacheDirectory;
25
		Annotations::$config['cache']=new AnnotationCache($cacheDirectory . '/annotations');
26
		self::register(Annotations::getManager());
27
		self::$cache=new ArrayCache($cacheDirectory, ".cache");
28
	}
29
30
	public static function startProd(&$config) {
31
		self::$cacheDirectory=self::initialGetCacheDirectory($config);
32
		$cacheDirectory=ROOT . DS . self::$cacheDirectory;
33
		self::$cache=new ArrayCache($cacheDirectory, ".cache");
34
	}
35
36
	public static function getControllerCache() {
37
		if (self::$cache->exists("controllers/routes"))
38
			return self::$cache->fetch("controllers/routes");
39
		return [ ];
40
	}
41
42
	public static function getRestCache() {
43
		if (self::$cache->exists("controllers/rest"))
44
			return self::$cache->fetch("controllers/rest");
45
		return [ ];
46
	}
47
48
	public static function getRouteCache($routePath, $duration) {
49
		$key=self::getRouteKey($routePath);
50
51
		if (self::$cache->exists("controllers/" . $key) && !self::expired($key, $duration)) {
52
			$response=self::$cache->file_get_contents("controllers/" . $key);
53
			return $response;
54
		} else {
55
			$response=Startup::runAsString($routePath);
56
			return self::storeRouteResponse($key, $response);
57
		}
58
	}
59
60
	public static function expired($key, $duration) {
61
		return self::$cache->expired("controllers/" . $key, $duration) === true || \array_key_exists($key, self::$expiredRoutes);
62
	}
63
64
	public static function isExpired($path,$duration){
65
		$route=Router::getRoute($path,false);
66
		if($route!==false && \is_array($route)){
67
			return self::expired(self::getRouteKey($route), $duration);
68
		}
69
		return true;
70
	}
71
72
	public static function setExpired($routePath, $expired=true) {
73
		$key=self::getRouteKey($routePath);
74
		self::setKeyExpired($key, $expired);
75
	}
76
77
	private static function setKeyExpired($key, $expired=true) {
78
		if ($expired) {
79
			self::$expiredRoutes[$key]=true;
80
		} else {
81
			unset(self::$expiredRoutes[$key]);
82
		}
83
	}
84
85
	public static function setRouteCache($routePath) {
86
		$key=self::getRouteKey($routePath);
87
		$response=Startup::runAsString($routePath);
88
		return self::storeRouteResponse($key, $response);
89
	}
90
91
	private static function storeRouteResponse($key, $response) {
92
		self::setKeyExpired($key, false);
93
		self::$cache->store("controllers/" . $key, $response, false);
94
		return $response;
95
	}
96
97
	private static function getRouteKey($routePath) {
98
		return "path" . \md5(\implode("", $routePath));
99
	}
100
101
	private static function initialGetCacheDirectory(&$config) {
102
		$cacheDirectory=@$config["cacheDirectory"];
103
		if (!isset($cacheDirectory)) {
104
			$config["cacheDirectory"]="cache/";
105
			$cacheDirectory=$config["cacheDirectory"];
106
		}
107
		return $cacheDirectory;
108
	}
109
110
	public static function getCacheDirectory() {
111
		return self::$cacheDirectory;
112
	}
113
114
	public static function createOrmModelCache($classname) {
115
		$key=self::getModelCacheKey($classname);
116
		if(isset(self::$cache)){
117
			if (!self::$cache->exists($key)) {
118
				$p=new ModelParser();
119
				$p->parse($classname);
120
				self::$cache->store($key, $p->__toString());
121
			}
122
			return self::$cache->fetch($key);
123
		}
124
	}
125
126
	public static function getModelCacheKey($classname){
127
		return \str_replace("\\", DIRECTORY_SEPARATOR, $classname);
128
	}
129
130
	public static function modelCacheExists($classname){
131
		$key=self::getModelCacheKey($classname);
132
		if(isset(self::$cache))
133
			return self::$cache->exists($key);
134
		return false;
135
	}
136
137
	private static function addControllerCache($classname) {
138
		$parser=new ControllerParser();
139
		try {
140
			$parser->parse($classname);
141
			self::$routes=\array_merge($parser->asArray(), self::$routes);
142
		} catch ( \Exception $e ) {
143
			// Nothing to do
144
		}
145
	}
146
147
	public static function checkCache(&$config,$silent=false) {
148
		$dirs=self::getCacheDirectories($config,$silent);
149
		foreach ($dirs as $dir){
150
			self::safeMkdir($dir);
151
		}
152
		return $dirs;
153
	}
154
155
	public static function getCacheDirectories(&$config,$silent=false){
156
		$cacheDirectory=self::initialGetCacheDirectory($config);
157
		if(!$silent){
158
			echo "cache directory is " . FsUtils::cleanPathname(ROOT . DS . $cacheDirectory) . "\n";
159
		}
160
		$modelsDir=str_replace("\\", DS, $config["mvcNS"]["models"]);
161
		$controllersDir=str_replace("\\", DS, $config["mvcNS"]["controllers"]);
162
		$annotationCacheDir=ROOT . DS . $cacheDirectory . DS . "annotations";
163
		$modelsCacheDir=ROOT . DS . $cacheDirectory . DS . $modelsDir;
164
		$queriesCacheDir=ROOT . DS . $cacheDirectory . DS . "queries";
165
		$controllersCacheDir=ROOT . DS . $cacheDirectory . DS . $controllersDir;
166
		$viewsCacheDir=ROOT . DS . $cacheDirectory . DS . "views";
167
		return [ "annotations" => $annotationCacheDir,"models" => $modelsCacheDir,"controllers" => $controllersCacheDir,"queries" => $queriesCacheDir ,"views"=>$viewsCacheDir];
168
	}
169
170
	private static function safeMkdir($dir) {
171
		if (!is_dir($dir))
172
			return mkdir($dir, 0777, true);
173
	}
174
175
	public static function clearCache(&$config, $type="all") {
176
		$cacheDirectories=self::checkCache($config);
177
		$cacheDirs=["annotations","controllers","models","queries","views"];
178
		foreach ($cacheDirs as $typeRef){
179
			self::_clearCache($cacheDirectories, $type, $typeRef);
180
		}
181
	}
182
183
	private static function _clearCache($cacheDirectories,$type,$typeRef){
184
		if ($type === "all" || $type === $typeRef)
185
			FsUtils::deleteAllFilesFromFolder($cacheDirectories[$typeRef]);
186
	}
187
188
	public static function initCache(&$config, $type="all") {
189
		self::checkCache($config,$type);
0 ignored issues
show
Documentation introduced by
$type is of type string, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
190
		self::start($config);
191
		if ($type === "all" || $type === "models")
192
			self::initModelsCache($config);
193
		if ($type === "all" || $type === "controllers")
194
			self::initControllersCache($config);
195
		if ($type === "all" || $type === "rest")
196
			self::initRestCache($config);
197
	}
198
199
	public static function initModelsCache(&$config,$forChecking=false,$silent=false) {
200
		$files=self::getModelsFiles($config, "models",$silent);
0 ignored issues
show
Documentation introduced by
'models' is of type string, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
Unused Code introduced by
The call to CacheManager::getModelsFiles() has too many arguments starting with $silent.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
201
		foreach ( $files as $file ) {
202
			if (is_file($file)) {
203
				$model=ClassUtils::getClassFullNameFromFile($file);
204
				if(!$forChecking){
205
					new $model();
206
				}
207
			}
208
		}
209
	}
210
211
	public static function getModelsFiles(&$config,$silent=false){
212
		return self::_getFiles($config, "models",$silent);
213
	}
214
215
	public static function getControllersFiles(&$config,$silent=false){
216
		return self::_getFiles($config, "controllers",$silent);
217
	}
218
219
	private static function _getFiles(&$config,$type,$silent=false){
220
		$typeNS=$config["mvcNS"][$type];
221
		$typeDir=ROOT . DS . str_replace("\\", DS, $typeNS);
222
		if(!$silent)
223
			echo \ucfirst($type)." directory is " . ROOT . $typeNS . "\n";
224
		return FsUtils::glob_recursive($typeDir . DS . '*');
225
	}
226
227
	private static function initControllersCache(&$config) {
228
		$files=self::getControllersFiles($config);
229
		foreach ( $files as $file ) {
230
			if (is_file($file)) {
231
				$controller=ClassUtils::getClassFullNameFromFile($file);
232
				self::addControllerCache($controller);
233
			}
234
		}
235
		if ($config["debug"])
236
			self::addAdminRoutes();
237
		self::$cache->store("controllers/routes", "return " . JArray::asPhpArray(self::$routes, "array") . ";");
238
	}
239
240
	private static function initRestCache(&$config) {
241
		$restCache=[];
242
		$files=self::getControllersFiles($config);
243
		foreach ( $files as $file ) {
244
			if (is_file($file)) {
245
				$controller=ClassUtils::getClassFullNameFromFile($file);
246
				$parser=new RestControllerParser();
247
				$parser->parse($controller,$config);
248
				if($parser->isRest())
249
					$restCache=\array_merge($restCache,$parser->asArray());
250
			}
251
		}
252
		self::$cache->store("controllers/rest", "return " . JArray::asPhpArray($restCache, "array") . ";");
253
	}
254
255
	private static function register(AnnotationManager $annotationManager) {
256
		$annotationManager->registry=array_merge($annotationManager->registry, [
257
				'id' => 'micro\annotations\IdAnnotation',
258
				'manyToOne' => 'micro\annotations\ManyToOneAnnotation',
259
				'oneToMany' => 'micro\annotations\OneToManyAnnotation',
260
				'manyToMany' => 'micro\annotations\ManyToManyAnnotation',
261
				'joinColumn' => 'micro\annotations\JoinColumnAnnotation',
262
				'table' => 'micro\annotations\TableAnnotation',
263
				'transient' => 'micro\annotations\TransientAnnotation',
264
				'column' => 'micro\annotations\ColumnAnnotation',
265
				'joinTable' => 'micro\annotations\JoinTableAnnotation',
266
				'route' => 'micro\annotations\router\RouteAnnotation',
267
				'var' => 'mindplay\annotations\standard\VarAnnotation',
268
				'yuml' => 'micro\annotations\YumlAnnotation',
269
				'rest' => 'micro\annotations\rest\RestAnnotation',
270
				'authorization' => 'micro\annotations\rest\AuthorizationAnnotation'
271
		]);
272
	}
273
274
	public static function addAdminRoutes() {
275
		self::addControllerCache("micro\controllers\Admin");
276
	}
277
278
	public static function getRoutes() {
279
		$result=self::getControllerCache();
280
		return $result;
281
	}
282
283 View Code Duplication
	public static function getRestResource($controllerClass){
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
284
		$cache=self::getRestCache();
285
		if(isset($cache[$controllerClass])){
286
			return $cache[$controllerClass]["resource"];
287
		}
288
		return null;
289
	}
290
291 View Code Duplication
	public static function getRestCacheController($controllerClass){
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
292
		$cache=self::getRestCache();
293
		if(isset($cache[$controllerClass])){
294
			return $cache[$controllerClass];
295
		}
296
		return null;
297
	}
298
299
300
	public static function addRoute($path, $controller, $action="index", $methods=null, $name="") {
301
		$controllerCache=self::getControllerCache();
302
		Router::addRouteToRoutes($controllerCache, $path, $controller, $action, $methods, $name);
303
		self::$cache->store("controllers/routes", "return " . JArray::asPhpArray($controllerCache, "array") . ";");
304
	}
305
}
306