* Copyright 2001-2010 Strangecode, LLC * * This file is part of The Strangecode Codebase. * * The Strangecode Codebase is free software: you can redistribute it and/or * modify it under the terms of the GNU General Public License as published by the * Free Software Foundation, either version 3 of the License, or (at your option) * any later version. * * The Strangecode Codebase is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * The Strangecode Codebase. If not, see . */ /** * Cache.inc.php * * Provides an API for storing a limited amount of data * intended to have a short lifetime in a user's session. * * @author Quinn Comendant * @version 2.1 * @since 2001 */ // Flags. define('CACHE_ALLOW_OVERSIZED', 1); class Cache { // Namespace of this instance of Prefs. var $_ns; // Configuration parameters for this object. var $_params = array( // If false nothing will be cached or retrieved. Useful for testing realtime data requests. 'enabled' => true, // The maximum size in bytes of any one variable. 'item_size_limit' => 4194304, // 4 MB // The maximum size in bytes before the cache will begin flushing out old items. 'stack_size_limit' => 4194304, // 4 MB // The minimum items to keep in the cache regardless of item or cache size. 'min_items' => 5, ); /* * Constructor * * @access public * @param string $namespace This object will store data under this realm. * @author Quinn Comendant * @version 1.0 * @since 05 Jun 2006 23:14:21 */ function Cache($namespace='') { $app =& App::getInstance(); $this->_ns = $namespace; if (true !== $app->getParam('enable_session')) { $app->logMsg('Cache disabled, enable_session is false.', LOG_DEBUG, __FILE__, __LINE__); $this->setParam(array('enabled' => false)); } if (!isset($_SESSION['_cache'][$this->_ns])) { $this->clear(); } } /** * This method enforces the singleton pattern for this class. * * @return object Reference to the global Cache object. * @access public * @static */ function &getInstance($namespace='') { static $instances = array(); if (!array_key_exists($namespace, $instances)) { $instances[$namespace] = new Cache($namespace); } return $instances[$namespace]; } /** * 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_DEBUG, __FILE__, __LINE__); return null; } } /** * Stores a new variable in the session cache. The $key should not be numeric * because the array_shift function will reset the key to the next largest * int key. Weird behavior I can't understand. For example $cache["123"] will become $cache[0] * * @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_ALLOW_OVERSIZED allows this. * @return bool True on success, false otherwise. */ function set($key, $var, $flags=0) { $app =& App::getInstance(); if (true !== $this->getParam('enabled')) { $app->logMsg(sprintf('Cache disabled, not saving data.', null), LOG_DEBUG, __FILE__, __LINE__); return false; } $var = serialize($var); $var_len = mb_strlen($var); if ($var_len >= $this->getParam('item_size_limit')) { $app->logMsg(sprintf('Serialized variable (%s bytes) more than item_size_limit (%s bytes).', $var_len, $this->getParam('item_size_limit')), LOG_NOTICE, __FILE__, __LINE__); return false; } if ($flags & CACHE_ALLOW_OVERSIZED == 0 && $var_len >= $this->getParam('stack_size_limit')) { $app->logMsg(sprintf('Serialized variable (%s bytes) more than stack_size_limit (%s bytes).', $var_len, $this->getParam('stack_size_limit')), LOG_NOTICE, __FILE__, __LINE__); return false; } // Remove any value already stored under this key. unset($_SESSION['_cache'][$this->_ns][$key]); // Continue to prune the cache if its size is greater than stack_size_limit, but keep at least min_items. while (mb_strlen(serialize($_SESSION['_cache'][$this->_ns])) + $var_len >= $this->getParam('stack_size_limit') && sizeof($_SESSION['_cache'][$this->_ns]) >= $this->getParam('min_items')) { array_shift($_SESSION['_cache'][$this->_ns]); } // Save this value under the specified key. $_SESSION['_cache'][$this->_ns][$key] =& $var; if ($var_len >= 1024000) { $app->logMsg(sprintf('Successfully cached oversized variable (%s bytes).', $var_len), LOG_DEBUG, __FILE__, __LINE__); } return true; } /** * Retrieves 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) { $app =& App::getInstance(); if (true !== $this->getParam('enabled')) { $app->logMsg(sprintf('Cache disabled, not getting data.', null), LOG_DEBUG, __FILE__, __LINE__); return false; } if (array_key_exists($key, $_SESSION['_cache'][$this->_ns])) { $app->logMsg(sprintf('Retreiving %s from cache.', $key), LOG_DEBUG, __FILE__, __LINE__); // Move the accessed cached datum to the top of the stack. Maybe somebody knows a better way to do this? $tmp =& $_SESSION['_cache'][$this->_ns][$key]; unset($_SESSION['_cache'][$this->_ns][$key]); $_SESSION['_cache'][$this->_ns][$key] =& $tmp; // Return the unserialized datum. return unserialize($_SESSION['_cache'][$this->_ns][$key]); } else { $app->logMsg(sprintf('Missing %s from cache.', $key), LOG_DEBUG, __FILE__, __LINE__); return false; } } /** * Tells you if the object is cached. * * @param string $key The key of the object to check. * @return bool True if a value exists for the given key. */ function exists($key) { if (true !== $this->getParam('enabled')) { return false; } return array_key_exists($key, $_SESSION['_cache'][$this->_ns]); } /** * Removes a cached object. * * @param string $key The key of the object to check. * @return bool True if the value existed before being unset. */ function delete($key) { if (array_key_exists($key, $_SESSION['_cache'][$this->_ns])) { unset($_SESSION['_cache'][$this->_ns][$key]); return true; } else { return false; } } /* * Delete all existing items from the cache. * * @access public * @author Quinn Comendant * @version 1.0 * @since 05 Jun 2006 23:51:34 */ function clear() { $_SESSION['_cache'][$this->_ns] = array(); } // END Cache } ?>