PageRenderTime 43ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/cake/cake/libs/cache.php

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