Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
cache.php
1<?php
9namespace Bitrix\Main\Data;
10
11use Bitrix\Main;
14
15class Cache
16{
18 protected $cacheEngine;
19
20 protected $content;
21 protected $vars;
22 protected int $ttl = 0;
23 protected string $uniqueString = '';
24 protected string $baseDir = 'cache';
25 protected string $initDir = '';
26 protected string $filename = '';
27 protected bool $isStarted = false;
28
29 protected static $showCacheStat = false;
30 protected static $clearCache = null;
31 protected static $clearCacheSession = null;
32
33 protected bool $forceRewriting = false;
34 protected bool $hasOutput = true;
35
36 public static function createCacheEngine($params = [])
37 {
38 static $cacheEngine = null;
39 if ($cacheEngine)
40 {
41 return clone $cacheEngine;
42 }
43
44 // Events can't be used here because events use cache
45
46 $cacheType = 'files';
47 $v = Config\Configuration::getValue('cache');
48 if ($v != null && isset($v['type']) && !empty($v['type']))
49 {
50 $cacheType = $v['type'];
51 }
52
53 if (is_array($cacheType))
54 {
55 if (isset($cacheType['class_name']))
56 {
57 if (!isset($cacheType['extension']) || extension_loaded($cacheType['extension']))
58 {
59 if (isset($cacheType['required_file']) && ($requiredFile = Main\Loader::getLocal($cacheType['required_file'])) !== false)
60 {
61 require_once($requiredFile);
62 }
63
64 if (isset($cacheType['required_remote_file']))
65 {
66 require_once($cacheType['required_remote_file']);
67 }
68
69 $className = $cacheType['class_name'];
70 if (class_exists($className))
71 {
72 $cacheEngine = new $className($params);
73 }
74 }
75 }
76 }
77 else
78 {
79 switch ($cacheType)
80 {
81 case 'redis':
82 $cacheEngine = new CacheEngineRedis($params);
83 break;
84 case 'memcached':
86 break;
87 case 'memcache':
88 $cacheEngine = new CacheEngineMemcache($params);
89 break;
90 case 'apc':
91 case 'apcu':
92 $cacheEngine = new CacheEngineApc($params);
93 break;
94 case 'files':
95 $cacheEngine = new CacheEngineFiles($params);
96 break;
97 default:
99 break;
100 }
101 }
102
103 if ($cacheEngine == null)
104 {
106 trigger_error('Cache engine is not found', E_USER_WARNING);
107 }
108
109 if (!$cacheEngine->isAvailable())
110 {
112 trigger_error('Cache engine is not available', E_USER_WARNING);
113 }
114
115 return clone $cacheEngine;
116 }
117
118 public static function getCacheEngineType()
119 {
120 $obj = static::createCacheEngine();
121 $class = get_class($obj);
122 if (($pos = mb_strrpos($class, "\\")) !== false)
123 {
124 $class = mb_substr($class, $pos + 1);
125 }
126
127 return mb_strtolower($class);
128 }
129
134 public static function createInstance($params = [])
135 {
136 $cacheEngine = static::createCacheEngine($params);
137 return new static($cacheEngine);
138 }
139
140 public function __construct($cacheEngine)
141 {
142 $this->cacheEngine = $cacheEngine;
143 }
144
145 public static function setShowCacheStat($showCacheStat)
146 {
147 static::$showCacheStat = $showCacheStat;
148 }
149
150 public static function getShowCacheStat()
151 {
152 return static::$showCacheStat;
153 }
154
159 public static function setClearCache($clearCache)
160 {
161 static::$clearCache = $clearCache;
162 }
163
169 {
170 static::$clearCacheSession = $clearCacheSession;
171 }
172
173 public static function getSalt()
174 {
175 $context = Main\Application::getInstance()->getContext();
176 $server = $context->getServer();
177
178 $scriptName = $server->get('SCRIPT_NAME');
179 if ($scriptName == '/bitrix/urlrewrite.php' && (($v = $server->get('REAL_FILE_PATH')) != null))
180 {
181 $scriptName = $v;
182 }
183 elseif ($scriptName == '/404.php' && (($v = $server->get('REAL_FILE_PATH')) != null))
184 {
185 $scriptName = $v;
186 }
187 return '/' . mb_substr(md5($scriptName), 0, 3);
188 }
189
194 public static function shouldClearCache()
195 {
196 global $USER;
197
198 $application = Main\Application::getInstance();
199
200 if (!$application->isInitialized())
201 {
202 return false;
203 }
204
205 $kernelSession = $application->getKernelSession();
206
207 if (isset(static::$clearCacheSession) || isset(static::$clearCache))
208 {
209 if ($USER instanceof \CUser && $USER->CanDoOperation('cache_control'))
210 {
211 if (isset(static::$clearCacheSession))
212 {
213 if (static::$clearCacheSession === true)
214 {
215 $kernelSession['SESS_CLEAR_CACHE'] = 'Y';
216 }
217 else
218 {
219 unset($kernelSession['SESS_CLEAR_CACHE']);
220 }
221 }
222
223 if (isset(static::$clearCache) && (static::$clearCache === true))
224 {
225 return true;
226 }
227 }
228 }
229
230 if (isset($kernelSession['SESS_CLEAR_CACHE']) && $kernelSession['SESS_CLEAR_CACHE'] === 'Y')
231 {
232 return true;
233 }
234
235 return false;
236 }
237
238 public static function getPath($uniqueString)
239 {
240 $un = md5($uniqueString);
241 return mb_substr($un, 0, 2) . '/' . $un . '.php';
242 }
243
244 public function clean($uniqueString, $initDir = false, $baseDir = 'cache')
245 {
246 $personalRoot = Main\Application::getPersonalRoot();
247 $baseDir = $personalRoot . '/' . $baseDir . '/';
248 $filename = $this->getPath($uniqueString);
249
250 if (static::$showCacheStat)
251 {
252 Diag\CacheTracker::add(0, '', $baseDir, $initDir, '/' . $filename, 'C');
253 }
254
255 return $this->cacheEngine->clean($baseDir, $initDir, '/' . $filename);
256 }
257
258 public function cleanDir($initDir = false, $baseDir = 'cache')
259 {
260 $personalRoot = Main\Application::getPersonalRoot();
261 $baseDir = $personalRoot . '/' . $baseDir . '/';
262
263 if (static::$showCacheStat)
264 {
265 Diag\CacheTracker::add(0, "", $baseDir, $initDir, "", "C");
266 }
267
268 return $this->cacheEngine->clean($baseDir, $initDir);
269 }
270
271 public function initCache($ttl, $uniqueString, $initDir = false, $baseDir = 'cache')
272 {
273 if ($initDir === false)
274 {
275 $initDir = 'default';
276 }
277
278 $personalRoot = Main\Application::getPersonalRoot();
279 $this->baseDir = $personalRoot . '/' . $baseDir . '/';
280 $this->initDir = $initDir;
281 $this->filename = '/' . $this->getPath($uniqueString);
282 $this->ttl = $ttl;
283 $this->uniqueString = $uniqueString;
284 $this->vars = false;
285
286 if ($ttl <= 0 || $this->forceRewriting || static::shouldClearCache())
287 {
288 return false;
289 }
290
291 $data = ['CONTENT' => '', 'VARS' => ''];
292 if (!$this->cacheEngine->read($data, $this->baseDir, $this->initDir, $this->filename, $this->ttl))
293 {
294 return false;
295 }
296
297 if (!is_array($data) || empty($data) || !isset($data['CONTENT']) || !isset($data['VARS']))
298 {
299 return false;
300 }
301
302 if (static::$showCacheStat)
303 {
304 $read = 0;
305 $path = '';
306 if ($this->cacheEngine instanceof ICacheEngineStat)
307 {
308 $read = $this->cacheEngine->getReadBytes();
309 $path = $this->cacheEngine->getCachePath();
310 }
311 elseif ($this->cacheEngine instanceof \ICacheBackend)
312 {
314 $read = $this->cacheEngine->read;
315
317 $path = $this->cacheEngine->path;
318 }
319
320 Diag\CacheTracker::addCacheStatBytes($read);
321 Diag\CacheTracker::add($read, $path, $this->baseDir, $this->initDir, $this->filename, 'R');
322 }
323
324 $this->content = $data['CONTENT'];
325 $this->vars = $data['VARS'];
326
327 return true;
328 }
329
330 public function output()
331 {
332 if ($this->hasOutput)
333 {
334 echo $this->content;
335 }
336 }
337
338 public function noOutput()
339 {
340 $this->hasOutput = false;
341 }
342
343 public function getVars()
344 {
345 return $this->vars;
346 }
347
348 public function startDataCache($TTL = false, $uniqueString = false, $initDir = false, $vars = array(), $baseDir = 'cache')
349 {
350 $narg = func_num_args();
351 if ($narg <= 0)
352 {
353 $TTL = $this->ttl;
354 }
355
356 if ($narg <= 1)
357 {
359 }
360
361 if ($narg <= 2)
362 {
364 }
365
366 if ($narg <= 3)
367 {
369 }
370
371 if ($this->initCache($TTL, $uniqueString, $initDir, $baseDir))
372 {
373 $this->output();
374 return false;
375 }
376
377 if ($TTL <= 0)
378 {
379 return true;
380 }
381
382 if ($this->hasOutput)
383 {
384 ob_start();
385 }
386
387 $this->vars = $vars;
388 $this->isStarted = true;
389
390 return true;
391 }
392
393 public function abortDataCache()
394 {
395 if (!$this->isStarted)
396 {
397 return;
398 }
399
400 $this->isStarted = false;
401 if ($this->hasOutput)
402 {
403 ob_end_flush();
404 }
405 }
406
407 public function endDataCache($vars = false)
408 {
409 if (!$this->isStarted)
410 {
411 return;
412 }
413
414 $this->isStarted = false;
415 $data = [
416 'CONTENT' => $this->hasOutput ? ob_get_contents() : '',
417 'VARS' => ($vars !== false ? $vars : $this->vars),
418 ];
419
420 $this->cacheEngine->write($data, $this->baseDir, $this->initDir, $this->filename, $this->ttl);
421
422 if (static::$showCacheStat)
423 {
424 $written = 0;
425 $path = '';
426 if ($this->cacheEngine instanceof ICacheEngineStat)
427 {
428 $written = $this->cacheEngine->getWrittenBytes();
429 $path = $this->cacheEngine->getCachePath();
430 }
431 elseif ($this->cacheEngine instanceof \ICacheBackend)
432 {
434 $written = $this->cacheEngine->written;
435
437 $path = $this->cacheEngine->path;
438 }
439 Diag\CacheTracker::addCacheStatBytes($written);
440 Diag\CacheTracker::add($written, $path, $this->baseDir, $this->initDir, $this->filename, 'W');
441 }
442
443 if ($this->hasOutput)
444 {
445 if (ob_get_contents() <> '')
446 {
447 ob_end_flush();
448 }
449 else
450 {
451 ob_end_clean();
452 }
453 }
454 }
455
456 public function isCacheExpired($path)
457 {
458 return $this->cacheEngine->isCacheExpired($path);
459 }
460
461 public function isStarted()
462 {
463 return $this->isStarted;
464 }
465
466 public static function clearCache($full = false, $initDir = ''): bool
467 {
468 if (($full !== true) && ($full !== false) && ($initDir === '') && is_string($full))
469 {
470 $initDir = $full;
471 $full = true;
472 }
473
474 $res = true;
475
476 if ($full === true)
477 {
478 $obCache = static::createInstance();
479 $obCache->cleanDir($initDir, 'cache');
480 }
481
482 $path = Main\Loader::getPersonal('cache' . $initDir);
483 if (is_dir($path) && ($handle = opendir($path)))
484 {
485 while (($file = readdir($handle)) !== false)
486 {
487 if ($file === '.' || $file === '..')
488 {
489 continue;
490 }
491
492 if (is_dir($path . '/' . $file))
493 {
494 if (!static::clearCache($full, $initDir . '/' . $file))
495 {
496 $res = false;
497 }
498 else
499 {
500 @chmod($path . '/' . $file, BX_DIR_PERMISSIONS);
501 //We suppress error handle here because there may be valid cache files in this dir
502 @rmdir($path . '/' . $file);
503 }
504 }
505 elseif ($full)
506 {
507 @chmod($path . '/' . $file, BX_FILE_PERMISSIONS);
508 if (!unlink($path . '/' . $file))
509 {
510 $res = false;
511 }
512 }
513 elseif (mb_substr($file, -4) === '.php')
514 {
515 $c = static::createInstance();
516 if ($c->isCacheExpired($path . '/' . $file))
517 {
518 @chmod($path . '/' . $file, BX_FILE_PERMISSIONS);
519 if (!unlink($path . '/' . $file))
520 {
521 $res = false;
522 }
523 }
524 }
525 else
526 {
527 //We should skip unknown file
528 //it will be deleted with full cache cleanup
529 }
530 }
531 closedir($handle);
532 }
533
534 return $res;
535 }
536
541 public function forceRewriting($mode)
542 {
543 $this->forceRewriting = (bool) $mode;
544 }
545}
clean($uniqueString, $initDir=false, $baseDir='cache')
Definition cache.php:244
endDataCache($vars=false)
Definition cache.php:407
static clearCache($full=false, $initDir='')
Definition cache.php:466
static createInstance($params=[])
Definition cache.php:134
static getCacheEngineType()
Definition cache.php:118
static setClearCacheSession($clearCacheSession)
Definition cache.php:168
static shouldClearCache()
Definition cache.php:194
static $clearCacheSession
Definition cache.php:31
static setClearCache($clearCache)
Definition cache.php:159
cleanDir($initDir=false, $baseDir='cache')
Definition cache.php:258
__construct($cacheEngine)
Definition cache.php:140
static getPath($uniqueString)
Definition cache.php:238
static setShowCacheStat($showCacheStat)
Definition cache.php:145
static createCacheEngine($params=[])
Definition cache.php:36
startDataCache($TTL=false, $uniqueString=false, $initDir=false, $vars=array(), $baseDir='cache')
Definition cache.php:348
initCache($ttl, $uniqueString, $initDir=false, $baseDir='cache')
Definition cache.php:271
static getShowCacheStat()
Definition cache.php:150
static getLocal($path, $root=null)
Definition loader.php:529