PageRenderTime 57ms CodeModel.GetById 27ms RepoModel.GetById 1ms app.codeStats 0ms

/cake/libs/cache.php

https://github.com/Forbin/cakephp2x
PHP | 536 lines | 227 code | 45 blank | 264 comment | 52 complexity | 354e88f580c3a2b06b232975ca3378f7 MD5 | raw file
  1. <?php
  2. /**
  3. * Caching for CakePHP.
  4. *
  5. *
  6. * PHP Version 5.x
  7. *
  8. * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  9. * Copyright 2005-2009, Cake Software Foundation, Inc. (http://cakefoundation.org)
  10. *
  11. * Licensed under The MIT License
  12. * Redistributions of files must retain the above copyright notice.
  13. *
  14. * @copyright Copyright 2005-2009, Cake Software Foundation, Inc. (http://cakefoundation.org)
  15. * @link http://cakephp.org CakePHP(tm) Project
  16. * @package cake
  17. * @subpackage cake.cake.libs
  18. * @since CakePHP(tm) v 1.2.0.4933
  19. * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
  20. */
  21. /**
  22. * Caching for CakePHP.
  23. *
  24. * @package cake
  25. * @subpackage cake.cake.libs
  26. */
  27. class Cache {
  28. /**
  29. * Cache configuration stack
  30. * Keeps the permanent/default settings for each cache engine.
  31. * These settings are used to reset the engines after temporary modification.
  32. *
  33. * @var array
  34. * @access private
  35. */
  36. private static $__config = array();
  37. /**
  38. * Holds name of the current configuration name being used.
  39. *
  40. * @var array
  41. * @access private
  42. */
  43. private static $__name = 'default';
  44. /**
  45. * Whether to reset the settings with the next call to Cache::set();
  46. *
  47. * @var array
  48. * @access private
  49. */
  50. private static $__reset = false;
  51. /**
  52. * Engine instances keyed by configuration name.
  53. *
  54. * @var array
  55. * @access protected
  56. */
  57. protected $_engines = array();
  58. /**
  59. * Returns a singleton instance
  60. *
  61. * @return object
  62. * @access public
  63. * @static
  64. */
  65. /*
  66. private function &getInstance() {
  67. static $instance = array();
  68. if (!$instance) {
  69. $instance[0] = new Cache();
  70. }
  71. return $instance[0];
  72. }
  73. */
  74. /**
  75. * Set the cache configuration to use. config() can
  76. * both create new configurations, return the settings for already configured
  77. * configurations. It also sets the 'default' configuration to use for subsequent
  78. * operations.
  79. *
  80. * To create a new configuration:
  81. *
  82. * `Cache::config('my_config', array('engine' => 'File', 'path' => TMP));`
  83. *
  84. * To get the settings for a configuration, and set it as the currently selected configuration
  85. *
  86. * `Cache::config('default');`
  87. *
  88. * @see app/config/core.php for configuration settings
  89. * @param string $name Name of the configuration
  90. * @param array $settings Optional associative array of settings passed to the engine
  91. * @return array(engine, settings) on success, false on failure
  92. * @access public
  93. * @static
  94. */
  95. public function config($name = null, $settings = array()) {
  96. if (is_array($name)) {
  97. $settings = $name;
  98. }
  99. if ($name === null || !is_string($name)) {
  100. $name = self::$__name;
  101. }
  102. $current = array();
  103. if (isset(self::$__config[$name])) {
  104. $current = self::$__config[$name];
  105. }
  106. if (!empty($settings)) {
  107. self::$__config[$name] = array_merge($current, $settings);
  108. }
  109. if (empty(self::$__config[$name]['engine'])) {
  110. return false;
  111. }
  112. $engine = self::$__config[$name]['engine'];
  113. self::$__name = $name;
  114. if (!isset(self::$_engines[$name])) {
  115. self::_buildEngine($name);
  116. $settings = self::$__config[$name] = self::settings($name);
  117. } elseif ($settings = self::set(self::$__config[$name])) {
  118. self::$__config[$name] = $settings;
  119. }
  120. return compact('engine', 'settings');
  121. }
  122. /**
  123. * Finds and builds the instance of the required engine class.
  124. *
  125. * @param string $name Name of the config array that needs an engine instance built
  126. * @return void
  127. * @access protected
  128. */
  129. protected function _buildEngine($name) {
  130. $config = self::$__config[$name];
  131. list($plugin, $class) = pluginSplit($config['engine']);
  132. $cacheClass = $class . 'Engine';
  133. if (!class_exists($cacheClass) && self::__loadEngine($class, $plugin) === false) {
  134. return false;
  135. }
  136. $cacheClass = $class . 'Engine';
  137. self::$_engines[$name] = new $cacheClass();
  138. if (self::$_engines[$name]->init($config)) {
  139. if (time() % self::$_engines[$name]->settings['probability'] === 0) {
  140. self::$_engines[$name]->gc();
  141. }
  142. return true;
  143. }
  144. return false;
  145. }
  146. /**
  147. * Returns an array containing the currently configured Cache settings.
  148. *
  149. * @return array
  150. * @access public
  151. */
  152. public function configured() {
  153. return array_keys(self::$__config);
  154. }
  155. /**
  156. * Drops a cache engine. Deletes the cache configuration information
  157. * If the deleted configuration is the last configuration using an certain engine,
  158. * the Engine instance is also unset.
  159. *
  160. * @param string $name A currently configured cache config you wish to remove.
  161. * @return boolen success of the removal, returns false when the config does not exist.
  162. * @access public
  163. */
  164. public function drop($name) {
  165. if (!isset(self::$__config[$name])) {
  166. return false;
  167. }
  168. unset(self::$__config[$name]);
  169. unset(self::$_engines[$name]);
  170. return true;
  171. }
  172. /**
  173. * Tries to find and include a file for a cache engine and returns object instance
  174. *
  175. * @param $name Name of the engine (without 'Engine')
  176. * @return mixed $engine object or null
  177. * @access private
  178. */
  179. private function __loadEngine($name, $plugin = null) {
  180. if ($plugin) {
  181. return App::import('Lib', $plugin . '.cache' . DS . $name, false);
  182. } else {
  183. $core = App::core();
  184. $path = $core['libs'][0] . 'cache' . DS . strtolower($name) . '.php';
  185. if (file_exists($path)) {
  186. require $path;
  187. return true;
  188. }
  189. return App::import('Lib', 'cache' . DS . $name, false);
  190. }
  191. }
  192. /**
  193. * Temporarily change settings to current config options. if no params are passed, resets settings if needed
  194. * Cache::write() will reset the configuration changes made
  195. *
  196. * @param mixed $settings Optional string for simple name-value pair or array
  197. * @param string $value Optional for a simple name-value pair
  198. * @return array of settings
  199. * @access public
  200. * @static
  201. */
  202. function set($settings = array(), $value = null) {
  203. if (!isset(self::$__config[self::$__name]) || !isset(self::$_engines[self::$__name])) {
  204. return false;
  205. }
  206. $name = self::$__name;
  207. if (!empty($settings)) {
  208. self::$__reset = true;
  209. }
  210. if (self::$__reset === true) {
  211. if (empty($settings)) {
  212. self::$__reset = false;
  213. $settings = self::$__config[$name];
  214. } else {
  215. if (is_string($settings) && $value !== null) {
  216. $settings = array($settings => $value);
  217. }
  218. $settings = array_merge(self::$__config[self::$__name], $settings);
  219. if (isset($settings['duration']) && !is_numeric($settings['duration'])) {
  220. $settings['duration'] = strtotime($settings['duration']) - time();
  221. }
  222. }
  223. self::$_engines[$name]->settings = $settings;
  224. }
  225. return self::settings($name);
  226. }
  227. /**
  228. * Garbage collection
  229. *
  230. * Permanently remove all expired and deleted data
  231. *
  232. * @return void
  233. * @access public
  234. * @static
  235. */
  236. public function gc() {
  237. self::$_engines[self::$__name]->gc();
  238. }
  239. /**
  240. * Write data for key into cache
  241. *
  242. * @param string $key Identifier for the data
  243. * @param mixed $value Data to be cached - anything except a resource
  244. * @param string $config Optional - string configuration name
  245. * @return boolean True if the data was successfully cached, false on failure
  246. * @access public
  247. * @static
  248. */
  249. public function write($key, $value, $config = null) {
  250. if (!$config) {
  251. $config = self::$__name;
  252. }
  253. $settings = self::settings($config);
  254. if (empty($settings)) {
  255. return null;
  256. }
  257. if (!self::isInitialized($config)) {
  258. return false;
  259. }
  260. $key = self::$_engines[$config]->key($key);
  261. if (!$key || is_resource($value) || $settings['duration'] < 1) {
  262. return false;
  263. }
  264. $success = self::$_engines[$config]->write($settings['prefix'] . $key, $value, $settings['duration']);
  265. self::set();
  266. return $success;
  267. }
  268. /**
  269. * Read a key from the cache
  270. *
  271. * @param string $key Identifier for the data
  272. * @param string $config name of the configuration to use
  273. * @return mixed The cached data, or false if the data doesn't exist, has expired, or if there was an error fetching it
  274. * @access public
  275. * @static
  276. */
  277. public function read($key, $config = null) {
  278. if (!$config) {
  279. $config = self::$__name;
  280. }
  281. $settings = self::settings($config);
  282. if (empty($settings)) {
  283. return null;
  284. }
  285. if (!self::isInitialized($config)) {
  286. return false;
  287. }
  288. $key = self::$_engines[$config]->key($key);
  289. if (!$key) {
  290. return false;
  291. }
  292. $success = self::$_engines[$config]->read($settings['prefix'] . $key);
  293. if ($config !== null && $config !== self::$__name) {
  294. self::set();
  295. }
  296. return $success;
  297. }
  298. /**
  299. * Delete a key from the cache
  300. *
  301. * @param string $key Identifier for the data
  302. * @param string $config name of the configuration to use
  303. * @return boolean True if the value was succesfully deleted, false if it didn't exist or couldn't be removed
  304. * @access public
  305. * @static
  306. */
  307. public function delete($key, $config = null) {
  308. if (!$config) {
  309. $config = self::$__name;
  310. }
  311. $settings = self::settings($config);
  312. if (empty($settings)) {
  313. return null;
  314. }
  315. if (!self::isInitialized($config)) {
  316. return false;
  317. }
  318. $key = self::$_engines[$config]->key($key);
  319. if (!$key) {
  320. return false;
  321. }
  322. $success = self::$_engines[$config]->delete($settings['prefix'] . $key);
  323. self::set();
  324. return $success;
  325. }
  326. /**
  327. * Delete all keys from the cache
  328. *
  329. * @param boolean $check if true will check expiration, otherwise delete all
  330. * @param string $config name of the configuration to use
  331. * @return boolean True if the cache was succesfully cleared, false otherwise
  332. * @access public
  333. * @static
  334. */
  335. public function clear($check = false, $config = null) {
  336. if (!$config) {
  337. $config = self::$__name;
  338. }
  339. $settings = self::settings($config);
  340. if (empty($settings)) {
  341. return null;
  342. }
  343. if (!self::isInitialized($config)) {
  344. return false;
  345. }
  346. $success = self::$_engines[$config]->clear($check);
  347. self::set();
  348. return $success;
  349. }
  350. /**
  351. * Check if Cache has initialized a working config for the given name.
  352. *
  353. * @param string $engine Name of the engine
  354. * @param string $config Name of the configuration setting
  355. * @return bool
  356. * @access public
  357. * @static
  358. */
  359. public function isInitialized($name = null) {
  360. if (Configure::read('Cache.disable')) {
  361. return false;
  362. }
  363. if (!$name && isset(self::$__config[self::$__name])) {
  364. $name = self::$__name;
  365. }
  366. return isset(self::$_engines[$name]);
  367. }
  368. /**
  369. * Return the settings for current cache engine. If no name is supplied the settings
  370. * for the 'active default' configuration will be returned. To set the 'active default'
  371. * configuration use `Cache::config()`
  372. *
  373. * @param string $engine Name of the configuration to get settings for.
  374. * @return array list of settings for this engine
  375. * @see Cache::config()
  376. * @access public
  377. * @static
  378. */
  379. public function settings($name = null) {
  380. if (!$name && isset(self::$__config[self::$__name])) {
  381. $name = self::$__name;
  382. }
  383. if (!empty(self::$_engines[$name])) {
  384. return self::$_engines[$name]->settings();
  385. }
  386. return array();
  387. }
  388. }
  389. /**
  390. * Storage engine for CakePHP caching
  391. *
  392. * @package cake
  393. * @subpackage cake.cake.libs
  394. */
  395. class CacheEngine {
  396. /**
  397. * settings of current engine instance
  398. *
  399. * @var int
  400. * @access public
  401. */
  402. protected $settings = array();
  403. /**
  404. * Initialize the cache engine
  405. *
  406. * Called automatically by the cache frontend
  407. *
  408. * @param array $params Associative array of parameters for the engine
  409. * @return boolean True if the engine has been succesfully initialized, false if not
  410. * @access public
  411. */
  412. public function init($settings = array()) {
  413. $this->settings = array_merge(array('prefix' => 'cake_', 'duration'=> 3600, 'probability'=> 100), $this->settings, $settings);
  414. if (!is_numeric($this->settings['duration'])) {
  415. $this->settings['duration'] = strtotime($this->settings['duration']) - time();
  416. }
  417. return true;
  418. }
  419. /**
  420. * Garbage collection
  421. *
  422. * Permanently remove all expired and deleted data
  423. *
  424. * @access public
  425. */
  426. public function gc() {
  427. }
  428. /**
  429. * Write value for a key into cache
  430. *
  431. * @param string $key Identifier for the data
  432. * @param mixed $value Data to be cached
  433. * @param mixed $duration How long to cache the data, in seconds
  434. * @return boolean True if the data was succesfully cached, false on failure
  435. * @access public
  436. */
  437. public function write($key, &$value, $duration) {
  438. trigger_error(sprintf(__('Method write() not implemented in %s', true), get_class($this)), E_USER_ERROR);
  439. }
  440. /**
  441. * Read a key from the cache
  442. *
  443. * @param string $key Identifier for the data
  444. * @return mixed The cached data, or false if the data doesn't exist, has expired, or if there was an error fetching it
  445. * @access public
  446. */
  447. public function read($key) {
  448. trigger_error(sprintf(__('Method read() not implemented in %s', true), get_class($this)), E_USER_ERROR);
  449. }
  450. /**
  451. * Delete a key from the cache
  452. *
  453. * @param string $key Identifier for the data
  454. * @return boolean True if the value was succesfully deleted, false if it didn't exist or couldn't be removed
  455. * @access public
  456. */
  457. public function delete($key) {
  458. }
  459. /**
  460. * Delete all keys from the cache
  461. *
  462. * @param boolean $check if true will check expiration, otherwise delete all
  463. * @return boolean True if the cache was succesfully cleared, false otherwise
  464. * @access public
  465. */
  466. public function clear($check) {
  467. }
  468. /**
  469. * Cache Engine settings
  470. *
  471. * @return array settings
  472. * @access public
  473. */
  474. public function settings() {
  475. return $this->settings;
  476. }
  477. /**
  478. * generates a safe key
  479. *
  480. * @param string $key the key passed over
  481. * @return mixed string $key or false
  482. * @access public
  483. */
  484. public function key($key) {
  485. if (empty($key)) {
  486. return false;
  487. }
  488. return Inflector::underscore(str_replace(array(DS, '/', '.'), '_', strval($key)));
  489. }
  490. }
  491. ?>