* Copyright 2001-2009 Strangecode Internet Consultancy
*
* 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
}
?>