You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

135 lines
4.0 KiB

  1. <?php
  2. /**
  3. * Класс кеша.
  4. * Отвечает за кеширование результатов выполнения действий.
  5. *
  6. * @copyright NetMonsters <team@netmonsters.ru>
  7. * @link
  8. * @package Majestic
  9. * @subpackage Cache
  10. * @since
  11. * @version SVN: $Id$
  12. * @filesource $URL$
  13. */
  14. final class Cache
  15. {
  16. private $cache_file;
  17. private $cache_folder;
  18. private $cache_time;
  19. private $mode = 0777;
  20. private $infofile = '_infofile';
  21. const HASH_ENABLE = true;
  22. function __construct($cache_name, $cache_time)
  23. {
  24. if (!preg_match('/[a-zA-Z0-9_]/', $cache_name)) {
  25. throw new MJException('Wrong cache identifier "'.$cache_name.'". Must use only [a-zA-Z0-9_]');
  26. }
  27. if ($cache_name == $this->infofile) {
  28. throw new MJException('Name "'.$this->infofile.'" is reserved. Try another one.');
  29. }
  30. if ($cache_time == 0) {
  31. throw new MJException('cache_time must be non-zero');
  32. }
  33. if ($cache_time > 86400) {
  34. throw new MJException('cache_time cannot be greater than 86400 sec (24 hours)');
  35. }
  36. if (substr($cache_name, 0, 1) == '_') {
  37. $this->cache_folder = CACHE_PATH;
  38. } else {
  39. $parts = explode('_', $cache_name, 2);
  40. $this->cache_folder = CACHE_PATH.'/'.(isset($parts[1]) ? $parts[0] : '_all');
  41. if (self::HASH_ENABLE) {
  42. $hash = md5($cache_name);
  43. $this->cache_folder .= '/'.substr($hash, 0, 1).'/'.substr($hash, 0, 2);
  44. }
  45. }
  46. $this->cache_file = $this->cache_folder.'/'.$cache_name;
  47. if (!is_writable($this->cache_folder)) {
  48. mkdir($this->cache_folder, $this->mode, true);
  49. }
  50. $this->cache_time = (int) $cache_time;
  51. }
  52. /**
  53. * Сохраняет кэш в файл
  54. *
  55. * @param string/array $data - строка (либо одномерный массив) сохраняемых данных
  56. * @return boolean - сохранил или нет
  57. */
  58. function save($data)
  59. {
  60. if ($this->cache_time != 0 && is_writable($this->cache_folder)) {
  61. $this->clearOld(); //очистка старых файлов.
  62. // а был-ли кеш?
  63. $exists = file_exists($this->cache_file);
  64. $result = file_put_contents($this->cache_file, $data);
  65. // если не существовал кеш - выставляем корректные права на него.
  66. if ($result && !$exists) {
  67. chmod($this->cache_file, 0664);
  68. }
  69. return (bool)$result;
  70. }
  71. return false;
  72. }
  73. /**
  74. * Достает кэш из файла
  75. *
  76. * @return string - содержимое кеша
  77. */
  78. function load()
  79. {
  80. if ($this->cache_time != 0) {
  81. return file_get_contents($this->cache_file);
  82. }
  83. return false;
  84. }
  85. /**
  86. * Принудительно очистить кеш
  87. *
  88. */
  89. function reset()
  90. {
  91. @unlink($this->cache_file);
  92. }
  93. /**
  94. * Проверяет, закешированы ли данные с таким именем
  95. *
  96. * @return boolean - закеширован или нет
  97. */
  98. function isCached()
  99. {
  100. if (is_readable($this->cache_file)) {
  101. if ($this->cache_time < 0 || $this->cache_time + filemtime($this->cache_file) > time()) {
  102. return true;
  103. }
  104. $this->reset(); //удалим просроченый файл
  105. }
  106. return false;
  107. }
  108. /**
  109. * Удаление файлов старше суток
  110. *
  111. */
  112. function clearOld()
  113. {
  114. $file = CACHE_PATH . '/' . $this->infofile;
  115. if (!file_exists($file) || date('Ymd', filemtime($file)) != date('Ymd')) {
  116. exec('find ' . CACHE_PATH . '/ -type f \! -path "*.svn*" -mtime +1 -delete'); //не удаляет папки сохраняя структуру
  117. touch($file);
  118. }
  119. }
  120. }
  121. ?>