PageRenderTime 54ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/webapp-php/system/libraries/drivers/Cache/File.php

https://github.com/AlinT/socorro
PHP | 245 lines | 191 code | 14 blank | 40 comment | 4 complexity | 43e90606a5679f6c7fe8faba4eb88927 MD5 | raw file
  1. <?php defined('SYSPATH') or die('No direct script access.');
  2. /**
  3. * File-based Cache driver.
  4. *
  5. * $Id: File.php 3160 2008-07-20 16:03:48Z Shadowhand $
  6. *
  7. * @package Cache
  8. * @author Kohana Team
  9. * @copyright (c) 2007-2008 Kohana Team
  10. * @license http://kohanaphp.com/license.html
  11. */
  12. class Cache_File_Driver implements Cache_Driver {
  13. protected $directory = '';
  14. /**
  15. * Tests that the storage location is a directory and is writable.
  16. */
  17. public function __construct($directory)
  18. {
  19. // Find the real path to the directory
  20. $directory = str_replace('\\', '/', realpath($directory)).'/';
  21. // Make sure the cache directory is writable
  22. if ( ! is_dir($directory) OR ! is_writable($directory))
  23. throw new Kohana_Exception('cache.unwritable', $directory);
  24. // Directory is valid
  25. $this->directory = $directory;
  26. }
  27. /**
  28. * Finds an array of files matching the given id or tag.
  29. *
  30. * @param string cache id or tag
  31. * @param bool search for tags
  32. * @return array of filenames matching the id or tag
  33. * @return void if no matching files are found
  34. */
  35. public function exists($id, $tag = FALSE)
  36. {
  37. if ($id === TRUE)
  38. {
  39. // Find all the files
  40. $files = glob($this->directory.'*~*~*');
  41. }
  42. elseif ($tag == TRUE)
  43. {
  44. // Find all the files that have the tag name
  45. $files = glob($this->directory.'*~*'.$id.'*~*');
  46. // Find all tags matching the given tag
  47. foreach ($files as $i => $file)
  48. {
  49. // Split the files
  50. $tags = explode('~', $file);
  51. // Find valid tags
  52. if (count($tags) !== 3 OR empty($tags[1]))
  53. continue;
  54. // Split the tags by plus signs, used to separate tags
  55. $tags = explode('+', $tags[1]);
  56. if ( ! in_array($tag, $tags))
  57. {
  58. // This entry does not match the tag
  59. unset($files[$i]);
  60. }
  61. }
  62. }
  63. else
  64. {
  65. // Find all the files matching the given id
  66. $files = glob($this->directory.$id.'~*');
  67. }
  68. return empty($files) ? NULL : $files;
  69. }
  70. /**
  71. * Sets a cache item to the given data, tags, and lifetime.
  72. *
  73. * @param string cache id to set
  74. * @param string data in the cache
  75. * @param array cache tags
  76. * @param integer lifetime
  77. * @return bool
  78. */
  79. public function set($id, $data, $tags, $lifetime)
  80. {
  81. // Remove old cache files
  82. $this->delete($id);
  83. // Cache File driver expects unix timestamp
  84. if ($lifetime !== 0)
  85. {
  86. $lifetime += time();
  87. }
  88. // Construct the filename
  89. $filename = $id.'~'.implode('+', $tags).'~'.$lifetime;
  90. // Write the file, appending the sha1 signature to the beginning of the data
  91. return (bool) file_put_contents($this->directory.$filename, sha1($data).$data);
  92. }
  93. /**
  94. * Finds an array of ids for a given tag.
  95. *
  96. * @param string tag name
  97. * @return array of ids that match the tag
  98. */
  99. public function find($tag)
  100. {
  101. if ($files = $this->exists($tag, TRUE))
  102. {
  103. // Length of directory name
  104. $offset = strlen($this->directory);
  105. // Find all the files with the given tag
  106. $array = array();
  107. foreach ($files as $file)
  108. {
  109. // Get the id from the filename
  110. $array[] = substr(current(explode('~', $file)), $offset);
  111. }
  112. return $array;
  113. }
  114. return FALSE;
  115. }
  116. /**
  117. * Fetches a cache item. This will delete the item if it is expired or if
  118. * the hash does not match the stored hash.
  119. *
  120. * @param string cache id
  121. * @return mixed|NULL
  122. */
  123. public function get($id)
  124. {
  125. if ($file = $this->exists($id))
  126. {
  127. // Always process the first result
  128. $file = current($file);
  129. // Validate that the cache has not expired
  130. if ($this->expired($file))
  131. {
  132. // Remove this cache, it has expired
  133. $this->delete($id);
  134. }
  135. else
  136. {
  137. $data = file_get_contents($file);
  138. // Find the hash of the data
  139. $hash = substr($data, 0, 40);
  140. // Remove the hash from the data
  141. $data = substr($data, 40);
  142. if ($hash !== sha1($data))
  143. {
  144. // Remove this cache, it doesn't validate
  145. $this->delete($id);
  146. // Unset data to prevent it from being returned
  147. unset($data);
  148. }
  149. }
  150. }
  151. // Return NULL if there is no data
  152. return isset($data) ? $data : NULL;
  153. }
  154. /**
  155. * Deletes a cache item by id or tag
  156. *
  157. * @param string cache id or tag, or TRUE for "all items"
  158. * @param boolean use tags
  159. * @return boolean
  160. */
  161. public function delete($id, $tag = FALSE)
  162. {
  163. $files = $this->exists($id, $tag);
  164. if (empty($files))
  165. return FALSE;
  166. // Disable all error reporting while deleting
  167. $ER = error_reporting(0);
  168. foreach ($files as $file)
  169. {
  170. // Remove the cache file
  171. if ( ! unlink($file))
  172. Kohana::log('error', 'Cache: Unable to delete cache file: '.$file);
  173. }
  174. // Turn on error reporting again
  175. error_reporting($ER);
  176. return TRUE;
  177. }
  178. /**
  179. * Deletes all cache files that are older than the current time.
  180. *
  181. * @return void
  182. */
  183. public function delete_expired()
  184. {
  185. if ($files = $this->exists(TRUE))
  186. {
  187. foreach ($files as $file)
  188. {
  189. if ($this->expired($file))
  190. {
  191. // The cache file has already expired, delete it
  192. @unlink($file) or Kohana::log('error', 'Cache: Unable to delete cache file: '.$file);
  193. }
  194. }
  195. }
  196. }
  197. /**
  198. * Check if a cache file has expired by filename.
  199. *
  200. * @param string filename
  201. * @return bool
  202. */
  203. protected function expired($file)
  204. {
  205. // Get the expiration time
  206. $expires = (int) substr($file, strrpos($file, '~') + 1);
  207. // Expirations of 0 are "never expire"
  208. return ($expires !== 0 AND $expires <= time());
  209. }
  210. } // End Cache File Driver