PageRenderTime 53ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/cake/libs/cache.php

https://github.com/msadouni/cakephp2x
PHP | 535 lines | 225 code | 46 blank | 264 comment | 51 complexity | d8025290432c29ea79452d1ac77d3d93 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. self::$__name = $name;
  113. $engine = self::$__config[$name]['engine'];
  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. $app = App::import('Lib', 'cache' . DS . $name, false);
  184. if (!$app) {
  185. require LIBS . 'cache' . DS . strtolower($name) . '.php';
  186. }
  187. return true;
  188. }
  189. }
  190. /**
  191. * Temporarily change settings to current config options. if no params are passed, resets settings if needed
  192. * Cache::write() will reset the configuration changes made
  193. *
  194. * @param mixed $settings Optional string for simple name-value pair or array
  195. * @param string $value Optional for a simple name-value pair
  196. * @return array of settings
  197. * @access public
  198. * @static
  199. */
  200. public function set($settings = array(), $value = null) {
  201. if (!isset(self::$__config[self::$__name])) {
  202. return false;
  203. }
  204. $name = self::$__name;
  205. if (!empty($settings)) {
  206. self::$__reset = true;
  207. }
  208. if (self::$__reset === true) {
  209. if (empty($settings)) {
  210. self::$__reset = false;
  211. $settings = self::$__config[$name];
  212. } else {
  213. if (is_string($settings) && $value !== null) {
  214. $settings = array($settings => $value);
  215. }
  216. $settings = array_merge(self::$__config[self::$__name], $settings);
  217. if (isset($settings['duration']) && !is_numeric($settings['duration'])) {
  218. $settings['duration'] = strtotime($settings['duration']) - time();
  219. }
  220. }
  221. self::$_engines[$name]->settings = $settings;
  222. }
  223. return self::settings($name);
  224. }
  225. /**
  226. * Garbage collection
  227. *
  228. * Permanently remove all expired and deleted data
  229. *
  230. * @return void
  231. * @access public
  232. * @static
  233. */
  234. public function gc() {
  235. self::$_engines[self::$__name]->gc();
  236. }
  237. /**
  238. * Write data for key into cache
  239. *
  240. * @param string $key Identifier for the data
  241. * @param mixed $value Data to be cached - anything except a resource
  242. * @param string $config Optional - string configuration name
  243. * @return boolean True if the data was successfully cached, false on failure
  244. * @access public
  245. * @static
  246. */
  247. public function write($key, $value, $config = null) {
  248. if (!$config) {
  249. $config = self::$__name;
  250. }
  251. $settings = self::settings($config);
  252. if (empty($settings)) {
  253. return null;
  254. }
  255. if (!self::isInitialized($config)) {
  256. return false;
  257. }
  258. $key = self::$_engines[$config]->key($key);
  259. if (!$key || is_resource($value) || $settings['duration'] < 1) {
  260. return false;
  261. }
  262. $success = self::$_engines[$config]->write($settings['prefix'] . $key, $value, $settings['duration']);
  263. self::set();
  264. return $success;
  265. }
  266. /**
  267. * Read a key from the cache
  268. *
  269. * @param string $key Identifier for the data
  270. * @param string $config name of the configuration to use
  271. * @return mixed The cached data, or false if the data doesn't exist, has expired, or if there was an error fetching it
  272. * @access public
  273. * @static
  274. */
  275. public function read($key, $config = null) {
  276. if (!$config) {
  277. $config = self::$__name;
  278. }
  279. $settings = self::settings($config);
  280. if (empty($settings)) {
  281. return null;
  282. }
  283. if (!self::isInitialized($config)) {
  284. return false;
  285. }
  286. $key = self::$_engines[$config]->key($key);
  287. if (!$key) {
  288. return false;
  289. }
  290. $success = self::$_engines[$config]->read($settings['prefix'] . $key);
  291. if ($config !== null && $config !== self::$__name) {
  292. self::set();
  293. }
  294. return $success;
  295. }
  296. /**
  297. * Delete a key from the cache
  298. *
  299. * @param string $key Identifier for the data
  300. * @param string $config name of the configuration to use
  301. * @return boolean True if the value was succesfully deleted, false if it didn't exist or couldn't be removed
  302. * @access public
  303. * @static
  304. */
  305. public function delete($key, $config = null) {
  306. if (!$config) {
  307. $config = self::$__name;
  308. }
  309. $settings = self::settings($config);
  310. if (empty($settings)) {
  311. return null;
  312. }
  313. if (!self::isInitialized($config)) {
  314. return false;
  315. }
  316. $key = self::$_engines[$config]->key($key);
  317. if (!$key) {
  318. return false;
  319. }
  320. $success = self::$_engines[$config]->delete($settings['prefix'] . $key);
  321. self::set();
  322. return $success;
  323. }
  324. /**
  325. * Delete all keys from the cache
  326. *
  327. * @param boolean $check if true will check expiration, otherwise delete all
  328. * @param string $config name of the configuration to use
  329. * @return boolean True if the cache was succesfully cleared, false otherwise
  330. * @access public
  331. * @static
  332. */
  333. public function clear($check = false, $config = null) {
  334. if (!$config) {
  335. $config = self::$__name;
  336. }
  337. $settings = self::settings($config);
  338. if (empty($settings)) {
  339. return null;
  340. }
  341. if (!self::isInitialized($config)) {
  342. return false;
  343. }
  344. $success = self::$_engines[$config]->clear($check);
  345. self::set();
  346. return $success;
  347. }
  348. /**
  349. * Check if Cache has initialized a working config for the given name.
  350. *
  351. * @param string $engine Name of the engine
  352. * @param string $config Name of the configuration setting
  353. * @return bool
  354. * @access public
  355. * @static
  356. */
  357. public function isInitialized($name = null) {
  358. if (Configure::read('Cache.disable')) {
  359. return false;
  360. }
  361. if (!$name && isset(self::$__config[self::$__name])) {
  362. $name = self::$__name;
  363. }
  364. return isset(self::$_engines[$name]);
  365. }
  366. /**
  367. * Return the settings for current cache engine. If no name is supplied the settings
  368. * for the 'active default' configuration will be returned. To set the 'active default'
  369. * configuration use `Cache::config()`
  370. *
  371. * @param string $engine Name of the configuration to get settings for.
  372. * @return array list of settings for this engine
  373. * @see Cache::config()
  374. * @access public
  375. * @static
  376. */
  377. public function settings($name = null) {
  378. if (!$name && isset(self::$__config[self::$__name])) {
  379. $name = self::$__name;
  380. }
  381. if (!empty(self::$_engines[$name])) {
  382. return self::$_engines[$name]->settings();
  383. }
  384. return array();
  385. }
  386. }
  387. /**
  388. * Storage engine for CakePHP caching
  389. *
  390. * @package cake
  391. * @subpackage cake.cake.libs
  392. */
  393. class CacheEngine {
  394. /**
  395. * settings of current engine instance
  396. *
  397. * @var int
  398. * @access public
  399. */
  400. protected $settings = array();
  401. /**
  402. * Initialize the cache engine
  403. *
  404. * Called automatically by the cache frontend
  405. *
  406. * @param array $params Associative array of parameters for the engine
  407. * @return boolean True if the engine has been succesfully initialized, false if not
  408. * @access public
  409. */
  410. public function init($settings = array()) {
  411. $this->settings = array_merge(array('prefix' => 'cake_', 'duration'=> 3600, 'probability'=> 100), $this->settings, $settings);
  412. if (!is_numeric($this->settings['duration'])) {
  413. $this->settings['duration'] = strtotime($this->settings['duration']) - time();
  414. }
  415. return true;
  416. }
  417. /**
  418. * Garbage collection
  419. *
  420. * Permanently remove all expired and deleted data
  421. *
  422. * @access public
  423. */
  424. public function gc() {
  425. }
  426. /**
  427. * Write value for a key into cache
  428. *
  429. * @param string $key Identifier for the data
  430. * @param mixed $value Data to be cached
  431. * @param mixed $duration How long to cache the data, in seconds
  432. * @return boolean True if the data was succesfully cached, false on failure
  433. * @access public
  434. */
  435. public function write($key, &$value, $duration) {
  436. trigger_error(sprintf(__('Method write() not implemented in %s', true), get_class($this)), E_USER_ERROR);
  437. }
  438. /**
  439. * Read a key from the cache
  440. *
  441. * @param string $key Identifier for the data
  442. * @return mixed The cached data, or false if the data doesn't exist, has expired, or if there was an error fetching it
  443. * @access public
  444. */
  445. public function read($key) {
  446. trigger_error(sprintf(__('Method read() not implemented in %s', true), get_class($this)), E_USER_ERROR);
  447. }
  448. /**
  449. * Delete a key from the cache
  450. *
  451. * @param string $key Identifier for the data
  452. * @return boolean True if the value was succesfully deleted, false if it didn't exist or couldn't be removed
  453. * @access public
  454. */
  455. public function delete($key) {
  456. }
  457. /**
  458. * Delete all keys from the cache
  459. *
  460. * @param boolean $check if true will check expiration, otherwise delete all
  461. * @return boolean True if the cache was succesfully cleared, false otherwise
  462. * @access public
  463. */
  464. public function clear($check) {
  465. }
  466. /**
  467. * Cache Engine settings
  468. *
  469. * @return array settings
  470. * @access public
  471. */
  472. public function settings() {
  473. return $this->settings;
  474. }
  475. /**
  476. * generates a safe key
  477. *
  478. * @param string $key the key passed over
  479. * @return mixed string $key or false
  480. * @access public
  481. */
  482. public function key($key) {
  483. if (empty($key)) {
  484. return false;
  485. }
  486. return Inflector::underscore(str_replace(array(DS, '/', '.'), '_', strval($key)));
  487. }
  488. }
  489. ?>