* @version 2.1 * @since 2001 */ // Flags. define('CACHE_IGNORE_SIZE', 1); class Cache { var $_params = array( 'enabled' => true, 'soft_limit' => 204800, 'hard_limit' => 4194304, 'min_items' => 3, ); /** * This method enforces the singleton pattern for this class. * * @return object Reference to the global Cache object. * @access public * @static */ function &getInstance() { static $instance = null; if ($instance === null) { $instance = new Cache(); } return $instance; } /** * Set (or overwrite existing) parameters by passing an array of new parameters. * * @access public * @param array $params Array of parameters (key => val pairs). */ function setParam($params) { $app =& App::getInstance(); if (isset($params) && is_array($params)) { // Merge new parameters with old overriding only those passed. $this->_params = array_merge($this->_params, $params); } else { $app->logMsg(sprintf('Parameters are not an array: %s', $params), LOG_ERR, __FILE__, __LINE__); } } /** * Return the value of a parameter, if it exists. * * @access public * @param string $param Which parameter to return. * @return mixed Configured parameter value. */ function getParam($param) { $app =& App::getInstance(); if (isset($this->_params[$param])) { return $this->_params[$param]; } else { $app->logMsg(sprintf('Parameter is not set: %s', $param), LOG_NOTICE, __FILE__, __LINE__); return null; } } /** * Stores a new variable in the session cache. The $key is is md5'ed * because if a variable id is a very large integer, the array_shift function * will reset the key to the next largest int key. Weird behavior I can't * understand. $session_cache[32341234123] will become $session_cache[0] * for example. Usage warning: if the variable is too big to fit, or is * old and discarded, you must provide alternative ways of accessing the data. * * @param str $key An identifier for the cached object. * @param mixed $var The var to store in the session cache. * @param bool $flags If we have something really big that we * still want to cache, setting this to * CACHE_IGNORE_SIZE allows this. * * @return bool True on success, false otherwise. */ function set($key, $var, $flags=0) { $app =& App::getInstance(); if (!$this->getParam('enabled')) { $app->logMsg(sprintf('Cache not enabled, not saving data.', null), LOG_DEBUG, __FILE__, __LINE__); return false; } $key = md5($key); $serialized_var = serialize($var); $serialized_var_len = strlen($serialized_var); if ($flags & CACHE_IGNORE_SIZE > 0 && $serialized_var_len >= $this->getParam('soft_limit')) { $app->logMsg(sprintf('Serialized variable (%s bytes) more than soft_limit (%s bytes).', $serialized_var_len, $this->getParam('soft_limit')), LOG_NOTICE, __FILE__, __LINE__); return false; } if ($serialized_var_len >= $this->getParam('hard_limit')) { $app->logMsg(sprintf('Serialized variable (%s bytes) more than hard_limit (%s bytes).', $serialized_var_len, $this->getParam('hard_limit')), LOG_NOTICE, __FILE__, __LINE__); return false; } if (!isset($_SESSION['_session_cache'])) { $_SESSION['_session_cache'] = array(); } else { unset($_SESSION['_session_cache'][$key]); // Continue to prune the cache if it's length is too long for the new variable to fit, but keep at least MIN_ITEMS at least. while (strlen(serialize($_SESSION['_session_cache'])) + $serialized_var_len >= $this->getParam('soft_limit') && sizeof($_SESSION['_session_cache']) >= $this->getParam('min_items')) { array_shift($_SESSION['_session_cache']); } } $_SESSION['_session_cache'][$key] =& $serialized_var; if ($serialized_var_len >= 1024000) { $app->logMsg(sprintf('Successfully cached oversized variable (%s bytes).', $serialized_var_len), LOG_DEBUG, __FILE__, __LINE__); } return true; } /** * Retrives an object from the session cache and returns it unserialized. * It also moves it to the top of the stack, which makes it such that the * cache flushing mechanism of putCache deletes the oldest referenced items * first. * * @param string $key The key for the datum to retrieve. * * @return mixed The requested datum, or false on failure. */ function get($key) { if (!$this->getParam('enabled')) { return false; } $key = md5($key); if (isset($_SESSION['_session_cache'][$key])) { // Move the accessed cached datum to the top of the stack. Maybe somebody knows a better way to do this? $tmp =& $_SESSION['_session_cache'][$key]; unset($_SESSION['_session_cache'][$key]); $_SESSION['_session_cache'][$key] =& $tmp; // Return the unserialized datum. return unserialize($_SESSION['_session_cache'][$key]); } else { return false; } } /** * Tells you if the object is cached. * * @param string $key The key of the object to check. * * @return bool The return from isset(). */ function exists($key) { if (!$this->getParam('enabled')) { return false; } $key = md5($key); return isset($_SESSION['_session_cache'][$key]); } /** * Tells you if the object is cached. * * @param string $key The key of the object to check. * * @return bool The return from isset(). */ function delete($key) { $key = md5($key); if (isset($_SESSION['_session_cache'][$key])) { unset($_SESSION['_session_cache'][$key]); } } // END Cache } ?>