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