CacheEngine.php 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. <?php
  2. /**
  3. * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
  4. * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
  5. *
  6. * Licensed under The MIT License
  7. * For full copyright and license information, please see the LICENSE.txt
  8. * Redistributions of files must retain the above copyright notice.
  9. *
  10. * @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
  11. * @link https://cakephp.org CakePHP(tm) Project
  12. * @since 1.2.0
  13. * @license https://opensource.org/licenses/mit-license.php MIT License
  14. */
  15. namespace Cake\Cache;
  16. use Cake\Core\InstanceConfigTrait;
  17. use InvalidArgumentException;
  18. /**
  19. * Storage engine for CakePHP caching
  20. *
  21. * @mixin \Cake\Core\InstanceConfigTrait
  22. */
  23. abstract class CacheEngine
  24. {
  25. use InstanceConfigTrait;
  26. /**
  27. * The default cache configuration is overridden in most cache adapters. These are
  28. * the keys that are common to all adapters. If overridden, this property is not used.
  29. *
  30. * - `duration` Specify how long items in this cache configuration last.
  31. * - `groups` List of groups or 'tags' associated to every key stored in this config.
  32. * handy for deleting a complete group from cache.
  33. * - `prefix` Prefix appended to all entries. Good for when you need to share a keyspace
  34. * with either another cache config or another application.
  35. * - `probability` Probability of hitting a cache gc cleanup. Setting to 0 will disable
  36. * cache::gc from ever being called automatically.
  37. *
  38. * @var array
  39. */
  40. protected $_defaultConfig = [
  41. 'duration' => 3600,
  42. 'groups' => [],
  43. 'prefix' => 'cake_',
  44. 'probability' => 100
  45. ];
  46. /**
  47. * Contains the compiled string with all groups
  48. * prefixes to be prepended to every key in this cache engine
  49. *
  50. * @var string
  51. */
  52. protected $_groupPrefix;
  53. /**
  54. * Initialize the cache engine
  55. *
  56. * Called automatically by the cache frontend. Merge the runtime config with the defaults
  57. * before use.
  58. *
  59. * @param array $config Associative array of parameters for the engine
  60. * @return bool True if the engine has been successfully initialized, false if not
  61. */
  62. public function init(array $config = [])
  63. {
  64. $this->setConfig($config);
  65. if (!empty($this->_config['groups'])) {
  66. sort($this->_config['groups']);
  67. $this->_groupPrefix = str_repeat('%s_', count($this->_config['groups']));
  68. }
  69. if (!is_numeric($this->_config['duration'])) {
  70. $this->_config['duration'] = strtotime($this->_config['duration']) - time();
  71. }
  72. return true;
  73. }
  74. /**
  75. * Garbage collection
  76. *
  77. * Permanently remove all expired and deleted data
  78. *
  79. * @param int|null $expires [optional] An expires timestamp, invalidating all data before.
  80. * @return void
  81. */
  82. public function gc($expires = null)
  83. {
  84. }
  85. /**
  86. * Write value for a key into cache
  87. *
  88. * @param string $key Identifier for the data
  89. * @param mixed $value Data to be cached
  90. * @return bool True if the data was successfully cached, false on failure
  91. */
  92. abstract public function write($key, $value);
  93. /**
  94. * Write data for many keys into cache
  95. *
  96. * @param array $data An array of data to be stored in the cache
  97. * @return array of bools for each key provided, true if the data was successfully cached, false on failure
  98. */
  99. public function writeMany($data)
  100. {
  101. $return = [];
  102. foreach ($data as $key => $value) {
  103. $return[$key] = $this->write($key, $value);
  104. }
  105. return $return;
  106. }
  107. /**
  108. * Read a key from the cache
  109. *
  110. * @param string $key Identifier for the data
  111. * @return mixed The cached data, or false if the data doesn't exist, has expired, or if there was an error fetching it
  112. */
  113. abstract public function read($key);
  114. /**
  115. * Read multiple keys from the cache
  116. *
  117. * @param array $keys An array of identifiers for the data
  118. * @return array For each cache key (given as the array key) the cache data associated or false if the data doesn't
  119. * exist, has expired, or if there was an error fetching it
  120. */
  121. public function readMany($keys)
  122. {
  123. $return = [];
  124. foreach ($keys as $key) {
  125. $return[$key] = $this->read($key);
  126. }
  127. return $return;
  128. }
  129. /**
  130. * Increment a number under the key and return incremented value
  131. *
  132. * @param string $key Identifier for the data
  133. * @param int $offset How much to add
  134. * @return bool|int New incremented value, false otherwise
  135. */
  136. abstract public function increment($key, $offset = 1);
  137. /**
  138. * Decrement a number under the key and return decremented value
  139. *
  140. * @param string $key Identifier for the data
  141. * @param int $offset How much to subtract
  142. * @return bool|int New incremented value, false otherwise
  143. */
  144. abstract public function decrement($key, $offset = 1);
  145. /**
  146. * Delete a key from the cache
  147. *
  148. * @param string $key Identifier for the data
  149. * @return bool True if the value was successfully deleted, false if it didn't exist or couldn't be removed
  150. */
  151. abstract public function delete($key);
  152. /**
  153. * Delete all keys from the cache
  154. *
  155. * @param bool $check if true will check expiration, otherwise delete all
  156. * @return bool True if the cache was successfully cleared, false otherwise
  157. */
  158. abstract public function clear($check);
  159. /**
  160. * Deletes keys from the cache
  161. *
  162. * @param array $keys An array of identifiers for the data
  163. * @return array For each provided cache key (given back as the array key) true if the value was successfully deleted,
  164. * false if it didn't exist or couldn't be removed
  165. */
  166. public function deleteMany($keys)
  167. {
  168. $return = [];
  169. foreach ($keys as $key) {
  170. $return[$key] = $this->delete($key);
  171. }
  172. return $return;
  173. }
  174. /**
  175. * Add a key to the cache if it does not already exist.
  176. *
  177. * Defaults to a non-atomic implementation. Subclasses should
  178. * prefer atomic implementations.
  179. *
  180. * @param string $key Identifier for the data.
  181. * @param mixed $value Data to be cached.
  182. * @return bool True if the data was successfully cached, false on failure.
  183. */
  184. public function add($key, $value)
  185. {
  186. $cachedValue = $this->read($key);
  187. if ($cachedValue === false) {
  188. return $this->write($key, $value);
  189. }
  190. return false;
  191. }
  192. /**
  193. * Clears all values belonging to a group. Is up to the implementing engine
  194. * to decide whether actually delete the keys or just simulate it to achieve
  195. * the same result.
  196. *
  197. * @param string $group name of the group to be cleared
  198. * @return bool
  199. */
  200. public function clearGroup($group)
  201. {
  202. return false;
  203. }
  204. /**
  205. * Does whatever initialization for each group is required
  206. * and returns the `group value` for each of them, this is
  207. * the token representing each group in the cache key
  208. *
  209. * @return array
  210. */
  211. public function groups()
  212. {
  213. return $this->_config['groups'];
  214. }
  215. /**
  216. * Generates a safe key for use with cache engine storage engines.
  217. *
  218. * @param string $key the key passed over
  219. * @return bool|string string key or false
  220. */
  221. public function key($key)
  222. {
  223. if (!$key) {
  224. return false;
  225. }
  226. $prefix = '';
  227. if ($this->_groupPrefix) {
  228. $prefix = md5(implode('_', $this->groups()));
  229. }
  230. $key = preg_replace('/[\s]+/', '_', strtolower(trim(str_replace([DIRECTORY_SEPARATOR, '/', '.'], '_', (string)$key))));
  231. return $prefix . $key;
  232. }
  233. /**
  234. * Generates a safe key, taking account of the configured key prefix
  235. *
  236. * @param string $key the key passed over
  237. * @return mixed string $key or false
  238. * @throws \InvalidArgumentException If key's value is empty
  239. */
  240. protected function _key($key)
  241. {
  242. $key = $this->key($key);
  243. if ($key === false) {
  244. throw new InvalidArgumentException('An empty value is not valid as a cache key');
  245. }
  246. return $this->_config['prefix'] . $key;
  247. }
  248. }