CacheEngine.php 8.8 KB

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