ElggFileCache.php 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. <?php
  2. /**
  3. * \ElggFileCache
  4. * Store cached data in a file store.
  5. *
  6. * @package Elgg.Core
  7. * @subpackage Caches
  8. */
  9. class ElggFileCache extends \ElggCache {
  10. /**
  11. * Set the Elgg cache.
  12. *
  13. * @param string $cache_path The cache path.
  14. * @param int $max_age Maximum age in seconds, 0 if no limit.
  15. * @param int $max_size Maximum size of cache in seconds, 0 if no limit.
  16. *
  17. * @throws ConfigurationException
  18. */
  19. public function __construct($cache_path, $max_age = 0, $max_size = 0) {
  20. $this->setVariable("cache_path", $cache_path);
  21. $this->setVariable("max_age", $max_age);
  22. $this->setVariable("max_size", $max_size);
  23. if ($cache_path == "") {
  24. throw new \ConfigurationException("Cache path set to nothing!");
  25. }
  26. }
  27. // @codingStandardsIgnoreStart
  28. /**
  29. * Create and return a handle to a file.
  30. *
  31. * @deprecated 1.8 Use \ElggFileCache::createFile()
  32. *
  33. * @param string $filename Filename to save as
  34. * @param string $rw Write mode
  35. *
  36. * @return mixed
  37. */
  38. protected function create_file($filename, $rw = "rb") {
  39. elgg_deprecated_notice('\ElggFileCache::create_file() is deprecated by ::createFile()', 1.8);
  40. return $this->createFile($filename, $rw);
  41. }
  42. // @codingStandardsIgnoreEnd
  43. /**
  44. * Create and return a handle to a file.
  45. *
  46. * @param string $filename Filename to save as
  47. * @param string $rw Write mode
  48. *
  49. * @return mixed
  50. */
  51. protected function createFile($filename, $rw = "rb") {
  52. // Create a filename matrix
  53. $matrix = "";
  54. $depth = strlen($filename);
  55. if ($depth > 5) {
  56. $depth = 5;
  57. }
  58. // Create full path
  59. $path = $this->getVariable("cache_path") . $matrix;
  60. if (!is_dir($path)) {
  61. mkdir($path, 0700, true);
  62. }
  63. // Open the file
  64. if ((!file_exists($path . $filename)) && ($rw == "rb")) {
  65. return false;
  66. }
  67. return fopen($path . $filename, $rw);
  68. }
  69. // @codingStandardsIgnoreStart
  70. /**
  71. * Create a sanitised filename for the file.
  72. *
  73. * @deprecated 1.8 Use \ElggFileCache::sanitizeFilename()
  74. *
  75. * @param string $filename The filename
  76. *
  77. * @return string
  78. */
  79. protected function sanitise_filename($filename) {
  80. // @todo : Writeme
  81. return $filename;
  82. }
  83. // @codingStandardsIgnoreEnd
  84. /**
  85. * Create a sanitised filename for the file.
  86. *
  87. * @param string $filename The filename
  88. *
  89. * @return string
  90. */
  91. protected function sanitizeFilename($filename) {
  92. // @todo : Writeme
  93. return $filename;
  94. }
  95. /**
  96. * Save a key
  97. *
  98. * @param string $key Name
  99. * @param string $data Value
  100. *
  101. * @return boolean
  102. */
  103. public function save($key, $data) {
  104. $f = $this->createFile($this->sanitizeFilename($key), "wb");
  105. if ($f) {
  106. $result = fwrite($f, $data);
  107. fclose($f);
  108. return $result;
  109. }
  110. return false;
  111. }
  112. /**
  113. * Load a key
  114. *
  115. * @param string $key Name
  116. * @param int $offset Offset
  117. * @param int $limit Limit
  118. *
  119. * @return string
  120. */
  121. public function load($key, $offset = 0, $limit = null) {
  122. $f = $this->createFile($this->sanitizeFilename($key));
  123. if ($f) {
  124. if (!$limit) {
  125. $limit = -1;
  126. }
  127. $data = stream_get_contents($f, $limit, $offset);
  128. fclose($f);
  129. return $data;
  130. }
  131. return false;
  132. }
  133. /**
  134. * Invalidate a given key.
  135. *
  136. * @param string $key Name
  137. *
  138. * @return bool
  139. */
  140. public function delete($key) {
  141. $dir = $this->getVariable("cache_path");
  142. if (file_exists($dir . $key)) {
  143. return unlink($dir . $key);
  144. }
  145. return true;
  146. }
  147. /**
  148. * Delete all files in the directory of this file cache
  149. *
  150. * @return void
  151. */
  152. public function clear() {
  153. $dir = $this->getVariable("cache_path");
  154. $exclude = array(".", "..");
  155. $files = scandir($dir);
  156. if (!$files) {
  157. return;
  158. }
  159. foreach ($files as $f) {
  160. if (!in_array($f, $exclude)) {
  161. unlink($dir . $f);
  162. }
  163. }
  164. }
  165. /**
  166. * Preform cleanup and invalidates cache upon object destruction
  167. *
  168. * @throws IOException
  169. */
  170. public function __destruct() {
  171. // @todo Check size and age, clean up accordingly
  172. $size = 0;
  173. $dir = $this->getVariable("cache_path");
  174. // Short circuit if both size and age are unlimited
  175. if (($this->getVariable("max_age") == 0) && ($this->getVariable("max_size") == 0)) {
  176. return;
  177. }
  178. $exclude = array(".", "..");
  179. $files = scandir($dir);
  180. if (!$files) {
  181. throw new \IOException($dir . " is not a directory.");
  182. }
  183. // Perform cleanup
  184. foreach ($files as $f) {
  185. if (!in_array($f, $exclude)) {
  186. $stat = stat($dir . $f);
  187. // Add size
  188. $size .= $stat['size'];
  189. // Is this older than my maximum date?
  190. if (($this->getVariable("max_age") > 0) && (time() - $stat['mtime'] > $this->getVariable("max_age"))) {
  191. unlink($dir . $f);
  192. }
  193. // @todo Size
  194. }
  195. }
  196. }
  197. }