cache.php

Go to the documentation of this file.
00001 <?php
00002 /* SVN FILE: $Id: cache.php 8114 2009-03-17 21:10:28Z renan.saddam $ */
00003 /**
00004  * Caching for CakePHP.
00005  *
00006  *
00007  * PHP versions 4 and 5
00008  *
00009  * CakePHP(tm) :  Rapid Development Framework (http://www.cakephp.org)
00010  * Copyright 2005-2008, Cake Software Foundation, Inc. (http://www.cakefoundation.org)
00011  *
00012  * Licensed under The MIT License
00013  * Redistributions of files must retain the above copyright notice.
00014  *
00015  * @filesource
00016  * @copyright     Copyright 2005-2008, Cake Software Foundation, Inc. (http://www.cakefoundation.org)
00017  * @link          http://www.cakefoundation.org/projects/info/cakephp CakePHP(tm) Project
00018  * @package       cake
00019  * @subpackage    cake.cake.libs
00020  * @since         CakePHP(tm) v 1.2.0.4933
00021  * @version       $Revision: 8114 $
00022  * @modifiedby    $LastChangedBy: renan.saddam $
00023  * @lastmodified  $Date: 2009-03-17 17:10:28 -0400 (Tue, 17 Mar 2009) $
00024  * @license       http://www.opensource.org/licenses/mit-license.php The MIT License
00025  */
00026 /**
00027  * Caching for CakePHP.
00028  *
00029  * @package       cake
00030  * @subpackage    cake.cake.libs
00031  */
00032 class Cache extends Object {
00033 /**
00034  * Cache engine to use
00035  *
00036  * @var CacheEngine
00037  * @access protected
00038  */
00039     var $_Engine = null;
00040 /**
00041  * Cache configuration stack
00042  *
00043  * @var array
00044  * @access private
00045  */
00046     var $__config = array();
00047 /**
00048  * Holds name of the current configuration being used
00049  *
00050  * @var array
00051  * @access private
00052  */
00053     var $__name = 'default';
00054 /**
00055  * whether to reset the settings with the next call to self::set();
00056  *
00057  * @var array
00058  * @access private
00059  */
00060     var $__reset = false;
00061 /**
00062  * Returns a singleton instance
00063  *
00064  * @return object
00065  * @access public
00066  * @static
00067  */
00068     function &getInstance() {
00069         static $instance = array();
00070         if (!$instance) {
00071             $instance[0] =& new Cache();
00072         }
00073         return $instance[0];
00074     }
00075 /**
00076  * Tries to find and include a file for a cache engine and returns object instance
00077  *
00078  * @param $name Name of the engine (without 'Engine')
00079  * @return mixed $engine object or null
00080  * @access private
00081  */
00082     function __loadEngine($name) {
00083         if (!class_exists($name . 'Engine')) {
00084             require LIBS . DS . 'cache' . DS . strtolower($name) . '.php';
00085         }
00086         return true;
00087     }
00088 /**
00089  * Set the cache configuration to use
00090  *
00091  * @see app/config/core.php for configuration settings
00092  * @param string $name Name of the configuration
00093  * @param array $settings Optional associative array of settings passed to the engine
00094  * @return array(engine, settings) on success, false on failure
00095  * @access public
00096  * @static
00097  */
00098     function config($name = null, $settings = array()) {
00099         $_this =& Cache::getInstance();
00100         if (is_array($name)) {
00101             $settings = $name;
00102         }
00103 
00104         if ($name === null || !is_string($name)) {
00105             $name = $_this->__name;
00106         }
00107 
00108         $current = array();
00109         if (isset($_this->__config[$name])) {
00110             $current = $_this->__config[$name];
00111         }
00112 
00113         if (!empty($settings)) {
00114             $_this->__name = null;
00115             $_this->__config[$name] = array_merge($current, $settings);
00116         }
00117 
00118         if (empty($_this->__config[$name]['engine'])) {
00119             return false;
00120         }
00121 
00122         $_this->__name = $name;
00123         $engine = $_this->__config[$name]['engine'];
00124 
00125         if (!$_this->isInitialized($engine)) {
00126             if ($_this->engine($engine, $_this->__config[$name]) === false) {
00127                 return false;
00128             }
00129             $settings = $_this->__config[$name] = $_this->settings($engine);
00130         } else {
00131             $settings = $_this->__config[$name] = $_this->set($_this->__config[$name]);
00132         }
00133         return compact('engine', 'settings');
00134     }
00135 /**
00136  * Set the cache engine to use or modify settings for one instance
00137  *
00138  * @param string $name Name of the engine (without 'Engine')
00139  * @param array $settings Optional associative array of settings passed to the engine
00140  * @return boolean True on success, false on failure
00141  * @access public
00142  * @static
00143  */
00144     function engine($name = 'File', $settings = array()) {
00145         $cacheClass = $name . 'Engine';
00146         $_this =& Cache::getInstance();
00147         if (!isset($_this->_Engine[$name])) {
00148             if ($_this->__loadEngine($name) === false) {
00149                 return false;
00150             }
00151             $_this->_Engine[$name] =& new $cacheClass();
00152         }
00153 
00154         if ($_this->_Engine[$name]->init($settings)) {
00155             if (time() % $_this->_Engine[$name]->settings['probability'] === 0) {
00156                 $_this->_Engine[$name]->gc();
00157             }
00158             return true;
00159         }
00160         $_this->_Engine[$name] = null;
00161         return false;
00162     }
00163 /**
00164  * Temporarily change settings to current config options. if no params are passed, resets settings if needed
00165  * Cache::write() will reset the configuration changes made
00166  *
00167  * @param mixed $settings Optional string for simple name-value pair or array
00168  * @param string $value Optional for a simple name-value pair
00169  * @return array of settings
00170  * @access public
00171  * @static
00172  */
00173     function set($settings = array(), $value = null) {
00174         $_this =& Cache::getInstance();
00175         if (!isset($_this->__config[$_this->__name])) {
00176             return false;
00177         }
00178 
00179         $engine = $_this->__config[$_this->__name]['engine'];
00180 
00181         if (!empty($settings)) {
00182             $_this->__reset = true;
00183         }
00184 
00185         if ($_this->__reset === true) {
00186             if (empty($settings)) {
00187                 $_this->__reset = false;
00188                 $settings = $_this->__config[$_this->__name];
00189             } else {
00190                 if (is_string($settings) && $value !== null) {
00191                     $settings = array($settings => $value);
00192                 }
00193                 $settings = array_merge($_this->__config[$_this->__name], $settings);
00194             }
00195             $_this->_Engine[$engine]->init($settings);
00196         }
00197 
00198         return $_this->settings($engine);
00199     }
00200 /**
00201  * Garbage collection
00202  *
00203  * Permanently remove all expired and deleted data
00204  *
00205  * @return void
00206  * @access public
00207  * @static
00208  */
00209     function gc() {
00210         $_this =& Cache::getInstance();
00211         $config = $_this->config();
00212         $_this->_Engine[$config['engine']]->gc();
00213     }
00214 /**
00215  * Write data for key into cache
00216  *
00217  * @param string $key Identifier for the data
00218  * @param mixed $value Data to be cached - anything except a resource
00219  * @param string $config Optional - string configuration name
00220  * @return boolean True if the data was successfully cached, false on failure
00221  * @access public
00222  * @static
00223  */
00224     function write($key, $value, $config = null) {
00225         $_this =& Cache::getInstance();
00226 
00227         if (is_array($config)) {
00228             extract($config);
00229         } else if ($config && (is_numeric($config) || is_numeric($config[0]) || (isset($config[1]) && is_numeric($config[1])))) {
00230             $config = null;
00231         }
00232 
00233         if ($config && isset($_this->__config[$config])) {
00234             $settings = $_this->set($_this->__config[$config]);
00235         } else {
00236             $settings = $_this->settings();
00237         }
00238 
00239         if (empty($settings)) {
00240             return null;
00241         }
00242         extract($settings);
00243 
00244         if (!$_this->isInitialized($engine)) {
00245             return false;
00246         }
00247 
00248         if (!$key = $_this->_Engine[$engine]->key($key)) {
00249             return false;
00250         }
00251 
00252         if (is_resource($value)) {
00253             return false;
00254         }
00255 
00256         if ($duration < 1) {
00257             return false;
00258         }
00259 
00260         $success = $_this->_Engine[$engine]->write($settings['prefix'] . $key, $value, $duration);
00261         $settings = $_this->set();
00262         return $success;
00263     }
00264 /**
00265  * Read a key from the cache
00266  *
00267  * @param string $key Identifier for the data
00268  * @param string $config name of the configuration to use
00269  * @return mixed The cached data, or false if the data doesn't exist, has expired, or if there was an error fetching it
00270  * @access public
00271  * @static
00272  */
00273     function read($key, $config = null) {
00274         $_this =& Cache::getInstance();
00275 
00276         if (isset($_this->__config[$config])) {
00277             $settings = $_this->set($_this->__config[$config]);
00278         } else {
00279             $settings = $_this->settings();
00280         }
00281 
00282         if (empty($settings)) {
00283             return null;
00284         }
00285         extract($settings);
00286 
00287         if (!$_this->isInitialized($engine)) {
00288             return false;
00289         }
00290         if (!$key = $_this->_Engine[$engine]->key($key)) {
00291             return false;
00292         }
00293         $success = $_this->_Engine[$engine]->read($settings['prefix'] . $key);
00294 
00295         if ($config !== null && $config !== $_this->__name) {
00296             $settings = $_this->set();
00297         }
00298         return $success;
00299     }
00300 /**
00301  * Delete a key from the cache
00302  *
00303  * @param string $key Identifier for the data
00304  * @param string $config name of the configuration to use
00305  * @return boolean True if the value was succesfully deleted, false if it didn't exist or couldn't be removed
00306  * @access public
00307  * @static
00308  */
00309     function delete($key, $config = null) {
00310         $_this =& Cache::getInstance();
00311         if (isset($_this->__config[$config])) {
00312             $settings = $_this->set($_this->__config[$config]);
00313         } else {
00314             $settings = $_this->settings();
00315         }
00316 
00317         if (empty($settings)) {
00318             return null;
00319         }
00320         extract($settings);
00321 
00322         if (!$_this->isInitialized($engine)) {
00323             return false;
00324         }
00325 
00326         if (!$key = $_this->_Engine[$engine]->key($key)) {
00327             return false;
00328         }
00329 
00330         $success = $_this->_Engine[$engine]->delete($settings['prefix'] . $key);
00331         $settings = $_this->set();
00332         return $success;
00333     }
00334 /**
00335  * Delete all keys from the cache
00336  *
00337  * @param boolean $check if true will check expiration, otherwise delete all
00338  * @param string $config name of the configuration to use
00339  * @return boolean True if the cache was succesfully cleared, false otherwise
00340  * @access public
00341  * @static
00342  */
00343     function clear($check = false, $config = null) {
00344         $_this =& Cache::getInstance();
00345         if (isset($_this->__config[$config])) {
00346             $settings = $_this->set($_this->__config[$config]);
00347         } else {
00348             $settings = $_this->settings();
00349         }
00350 
00351         if (empty($settings)) {
00352             return null;
00353         }
00354         extract($settings);
00355 
00356         if (isset($engine) && !$_this->isInitialized($engine)) {
00357             return false;
00358         }
00359         $success = $_this->_Engine[$engine]->clear($check);
00360         $settings = $_this->set();
00361         return $success;
00362     }
00363 /**
00364  * Check if Cache has initialized a working storage engine
00365  *
00366  * @param string $engine Name of the engine
00367  * @param string $config Name of the configuration setting
00368  * @return bool
00369  * @access public
00370  * @static
00371  */
00372     function isInitialized($engine = null) {
00373         if (Configure::read('Cache.disable')) {
00374             return false;
00375         }
00376         $_this =& Cache::getInstance();
00377         if (!$engine && isset($_this->__config[$_this->__name]['engine'])) {
00378             $engine = $_this->__config[$_this->__name]['engine'];
00379         }
00380         return isset($_this->_Engine[$engine]);
00381     }
00382 
00383 /**
00384  * Return the settings for current cache engine
00385  *
00386  * @param string $engine Name of the engine
00387  * @return array list of settings for this engine
00388  * @access public
00389  * @static
00390  */
00391     function settings($engine = null) {
00392         $_this =& Cache::getInstance();
00393         if (!$engine && isset($_this->__config[$_this->__name]['engine'])) {
00394             $engine = $_this->__config[$_this->__name]['engine'];
00395         }
00396 
00397         if (isset($_this->_Engine[$engine]) && !is_null($_this->_Engine[$engine])) {
00398             return $_this->_Engine[$engine]->settings();
00399         }
00400         return array();
00401     }
00402 }
00403 /**
00404  * Storage engine for CakePHP caching
00405  *
00406  * @package       cake
00407  * @subpackage    cake.cake.libs
00408  */
00409 class CacheEngine extends Object {
00410 /**
00411  * settings of current engine instance
00412  *
00413  * @var int
00414  * @access public
00415  */
00416     var $settings = array();
00417 /**
00418  * Iitialize the cache engine
00419  *
00420  * Called automatically by the cache frontend
00421  *
00422  * @param array $params Associative array of parameters for the engine
00423  * @return boolean True if the engine has been succesfully initialized, false if not
00424  * @access public
00425  */
00426     function init($settings = array()) {
00427         $this->settings = array_merge(array('prefix' => 'cake_', 'duration'=> 3600, 'probability'=> 100), $this->settings, $settings);
00428         if (!is_numeric($this->settings['duration'])) {
00429             $this->settings['duration'] = strtotime($this->settings['duration']) - time();
00430         }
00431         return true;
00432     }
00433 /**
00434  * Garbage collection
00435  *
00436  * Permanently remove all expired and deleted data
00437  *
00438  * @access public
00439  */
00440     function gc() {
00441     }
00442 /**
00443  * Write value for a key into cache
00444  *
00445  * @param string $key Identifier for the data
00446  * @param mixed $value Data to be cached
00447  * @param mixed $duration How long to cache the data, in seconds
00448  * @return boolean True if the data was succesfully cached, false on failure
00449  * @access public
00450  */
00451     function write($key, &$value, $duration) {
00452         trigger_error(sprintf(__('Method write() not implemented in %s', true), get_class($this)), E_USER_ERROR);
00453     }
00454 /**
00455  * Read a key from the cache
00456  *
00457  * @param string $key Identifier for the data
00458  * @return mixed The cached data, or false if the data doesn't exist, has expired, or if there was an error fetching it
00459  * @access public
00460  */
00461     function read($key) {
00462         trigger_error(sprintf(__('Method read() not implemented in %s', true), get_class($this)), E_USER_ERROR);
00463     }
00464 /**
00465  * Delete a key from the cache
00466  *
00467  * @param string $key Identifier for the data
00468  * @return boolean True if the value was succesfully deleted, false if it didn't exist or couldn't be removed
00469  * @access public
00470  */
00471     function delete($key) {
00472     }
00473 /**
00474  * Delete all keys from the cache
00475  *
00476  * @param boolean $check if true will check expiration, otherwise delete all
00477  * @return boolean True if the cache was succesfully cleared, false otherwise
00478  * @access public
00479  */
00480     function clear($check) {
00481     }
00482 /**
00483  * Cache Engine settings
00484  *
00485  * @return array settings
00486  * @access public
00487  */
00488     function settings() {
00489         return $this->settings;
00490     }
00491 /**
00492  * generates a safe key
00493  *
00494  * @param string $key the key passed over
00495  * @return mixed string $key or false
00496  * @access public
00497  */
00498     function key($key) {
00499         if (empty($key)) {
00500             return false;
00501         }
00502         $key = Inflector::underscore(str_replace(array(DS, '/', '.'), '_', strval($key)));
00503         return $key;
00504     }
00505 }
00506 ?>

Generated on Sun Nov 22 00:30:52 2009 for CakePHP 1.2.x.x (v1.2.4.8284) by doxygen 1.4.7