File.php 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. <?php
  2. /**
  3. * Lithium: the most rad php framework
  4. *
  5. * @copyright Copyright 2013, Union of RAD (http://union-of-rad.org)
  6. * @license http://opensource.org/licenses/bsd-license.php The BSD License
  7. */
  8. namespace lithium\storage\cache\adapter;
  9. use SplFileInfo;
  10. use RecursiveIteratorIterator;
  11. use RecursiveDirectoryIterator;
  12. use lithium\core\Libraries;
  13. /**
  14. * A minimal file-based cache.
  15. *
  16. * This File adapter provides basic support for `write`, `read`, `delete`
  17. * and `clear` cache functionality, as well as allowing the first four
  18. * methods to be filtered as per the Lithium filtering system. The File adapter
  19. * is a very simple cache, and should only be used for prototyping or for specifically
  20. * caching _files_. For more general caching needs, please consider using a more
  21. * appropriate cache adapter.
  22. *
  23. * This adapter does *not* provide increment/decrement functionality. For such
  24. * functionality, please use a more appropriate cache adapter.
  25. *
  26. * This adapter does *not* allow multi-key operations for any methods.
  27. *
  28. * The path that the cached files will be written to defaults to
  29. * `<app>/resources/tmp/cache`, but is user-configurable on cache configuration.
  30. *
  31. * Note that the cache expiration time is stored within the first few bytes
  32. * of the cached data, and is transparently added and/or removed when values
  33. * are stored and/or retrieved from the cache.
  34. *
  35. * @see lithium\storage\cache\adapter
  36. */
  37. class File extends \lithium\core\Object {
  38. /**
  39. * Class constructor.
  40. *
  41. * @see lithium\storage\Cache::config()
  42. * @param array $config Configuration parameters for this cache adapter. These settings are
  43. * indexed by name and queryable through `Cache::config('name')`.
  44. * The defaults are:
  45. * - 'path' : Path where cached entries live `LITHIUM_APP_PATH . '/resources/tmp/cache'`.
  46. * - 'expiry' : Default expiry time used if none is explicitly set when calling
  47. * `Cache::write()`.
  48. */
  49. public function __construct(array $config = array()) {
  50. $defaults = array(
  51. 'path' => Libraries::get(true, 'resources') . '/tmp/cache',
  52. 'prefix' => '',
  53. 'expiry' => '+1 hour'
  54. );
  55. parent::__construct($config + $defaults);
  56. }
  57. /**
  58. * Write value(s) to the cache.
  59. *
  60. * @param string $key The key to uniquely identify the cached item.
  61. * @param mixed $data The value to be cached.
  62. * @param null|string $expiry A strtotime() compatible cache time. If no expiry time is set,
  63. * then the default cache expiration time set with the cache configuration will be used.
  64. * @return closure Function returning boolean `true` on successful write, `false` otherwise.
  65. */
  66. public function write($key, $data, $expiry = null) {
  67. $path = $this->_config['path'];
  68. $expiry = ($expiry) ?: $this->_config['expiry'];
  69. return function($self, $params) use (&$path, $expiry) {
  70. $expiry = strtotime($expiry);
  71. $data = "{:expiry:{$expiry}}\n{$params['data']}";
  72. $path = "{$path}/{$params['key']}";
  73. return file_put_contents($path, $data);
  74. };
  75. }
  76. /**
  77. * Read value(s) from the cache.
  78. *
  79. * @param string $key The key to uniquely identify the cached item.
  80. * @return closure Function returning cached value if successful, `false` otherwise.
  81. */
  82. public function read($key) {
  83. $path = $this->_config['path'];
  84. return function($self, $params) use (&$path) {
  85. extract($params);
  86. $path = "$path/$key";
  87. $file = new SplFileInfo($path);
  88. if (!$file->isFile() || !$file->isReadable()) {
  89. return false;
  90. }
  91. $data = file_get_contents($path);
  92. preg_match('/^\{\:expiry\:(\d+)\}\\n/', $data, $matches);
  93. $expiry = $matches[1];
  94. if ($expiry < time()) {
  95. unlink($path);
  96. return false;
  97. }
  98. return preg_replace('/^\{\:expiry\:\d+\}\\n/', '', $data, 1);
  99. };
  100. }
  101. /**
  102. * Delete an entry from the cache.
  103. *
  104. * @param string $key The key to uniquely identify the cached item.
  105. * @return closure Function returning boolean `true` on successful delete, `false` otherwise.
  106. */
  107. public function delete($key) {
  108. $path = $this->_config['path'];
  109. return function($self, $params) use (&$path) {
  110. extract($params);
  111. $path = "$path/$key";
  112. $file = new SplFileInfo($path);
  113. if ($file->isFile() && $file->isReadable()) {
  114. return unlink($path);
  115. }
  116. return false;
  117. };
  118. }
  119. /**
  120. * The File adapter does not provide any facilities for atomic incrementing
  121. * of cache items. If you need this functionality, please use a cache adapter
  122. * which provides native support for atomic increment.
  123. *
  124. * This method is not implemented, and will simply return false.
  125. *
  126. * @param string $key Key of numeric cache item to increment
  127. * @param integer $offset Offset to increment - defaults to 1.
  128. * @return boolean False - this method is not implemented
  129. */
  130. public function increment($key, $offset = 1) {
  131. return false;
  132. }
  133. /**
  134. * The File adapter does not provide any facilities for atomic decrementing
  135. * of cache items. If you need this functionality, please use a cache adapter
  136. * which provides native support for atomic decrement.
  137. *
  138. * This method is not implemented, and will simply return false.
  139. *
  140. * @param string $key Key of numeric cache item to decrement
  141. * @param integer $offset Offset to increment - defaults to 1.
  142. * @return boolean False - this method is not implemented
  143. */
  144. public function decrement($key, $offset = 1) {
  145. return false;
  146. }
  147. /**
  148. * Clears user-space cache.
  149. *
  150. * @return mixed True on successful clear, false otherwise.
  151. */
  152. public function clear() {
  153. $base = new RecursiveDirectoryIterator($this->_config['path']);
  154. $iterator = new RecursiveIteratorIterator($base);
  155. foreach ($iterator as $file) {
  156. if ($file->isFile()) {
  157. unlink($file->getPathName());
  158. }
  159. }
  160. return true;
  161. }
  162. /**
  163. * Implements cache adapter support-detection interface.
  164. *
  165. * @return boolean Always returns `true`.
  166. */
  167. public static function enabled() {
  168. return true;
  169. }
  170. }
  171. ?>