<?php
/**
* General purpose runtime cache for variables and objects
*
* @package tv2-engine
* @author Emilis Dambauskas (hide@address.com)
* @copyright 20022003 Emilis Dambauskas under {@link http://opensource.org/licenses/artistic-license.php Artistic license}
* @version $Id: ctlRtVarCache.class.php,v 1.2 2003/07/09 05:36:03 lunaticlt Exp $
* @class ctlRtVarCache
*/
class ctlRTvarCache
{
/**
* Stored data array
* @attribute private array $data
*/
var $data;
/**
* Array containing types of vars/objects stored in cache
* @attribute private array $types
*/
var $types;
/**
* Key array
* @attribute private array $keys
*/
var $keys;
/**
* Counter. Needed for indexing vars
* @attribute private int $counter
*/
var $counter;
/**
* Cache size
* @attribute private int size
*/
var $size;
/**
* Constructor. Initializes attributes
*
* @constructor ctlRtVarCache
* @param optional int limit cache size (default 100)
*/
function ctlRTvarCache($limit = 100)
{
$this->size = $limit;
$this->types = array();
$this->keys = array();
$this->data = array();
$this->counter = 1;
}
/**
* Sends an error to the {@link $errors} object and returns FALSE
*
* @method private error
* @return boolean always FALSE
* @param string $msg error message
* @use $errors
*/
function error($msg)
{
$GLOBALS['errors']->add(get_class($this).': '.$msg);
return FALSE;
}
/**
* This function prints info about cache contents grouped by types. Usefull
* for debugging purposes.
*
* @method public debugOut
*/
function debugOut()
{
foreach($this->types as $typeId => $typeN)
{
echo "\n<hr><b>".$typeN." (".sizeof($this->keys[$typeId])."):</b><bR><pre>";
print_r($this->keys[$typeId]);
echo "</pre>\n";
}
}
/**
* This method calls a method on object in cache with given $id. Used in
* $this->delete() and $this->deleteKeys() methods.
*
* @method private callObjectMethod
* @return mixed whatever the object method returns or FALSE on failure
* @param mixed $id id of object in cache
* @param string $ObjectMethod Object method name
* @param optional array $ObjectMethodParams Array of parameters to be passed to the method.
*/
function callObjectMethod($id, $ObjectMethod, $ObjectMethodParams = FALSE)
{
if ($ObjectMethod && is_object($this->data[$id]))
{
if ($ObjectMethodParams === FALSE)
$result = call_user_func_array(array(&$this->data[$id], $ObjectMethod));
else
$result = call_user_func_array(array(&$this->data[$id], $ObjectMethod), $ObjectMethodParams);
return $result;
}
else return FALSE;
}
/**
* Returns internal type id
*
* @method private findTypeId
* @return mixed type id or FALSE on failure
* @param string $type type name
*/
function findTypeId($type)
{
return array_search($type, $this->types, TRUE);
}
/**
* Returns internal variable id
*
* @method private findId
* @return mixed var id or FALSE on failure
* @param string $type type name
* @param mixed $keys key name or key name array
*/
function findId($type, $keys)
{
$t_id = $this->findTypeId($type);
if (!$t_id)
return FALSE;
if (!is_array($keys))
$keys = (array) $keys;
while ($key = array_pop($keys))
if (isset($this->keys[$t_id][$key]))
return $this->keys[$t_id][$key];
return FALSE;
}
/**
* Adds var to cache
*
* @method public add
* @return boolean TRUE on success, FALSE on error
* @param string $type type name
* @param mixed $keys key name, or key name array
* @param optional string $ObjectMethod method name to call on object
* @param optional array $ObjectMethodParams parameters for the method
*/
function add($type, $keys, &$data, $ObjectMethod = FALSE, $ObjectMethodParams = FALSE)
{
$foundType = TRUE;
if (!is_array($keys))
$keys = (array)$keys;
// 1. check if type exists:
$t_id = $this->findTypeId($type);
if (!$t_id)
{
$foundType = FALSE;
$t_id = $this->counter++;
$this->types[$t_id] = $type;
}
// 2. check if entity exists and add or update it:
if (!$foundType || !($id = $this->findId($type, $keys)))
$id = $this->counter++;
while ($key = array_pop($keys))
$this->keys[$t_id][$key] = $id;
// 3. remove first element if cache full:
if (sizeof($this->data) >= $this->size)
array_shift($this->data);
$this->data[$id] = &$data;
// call object methods if needed:
if ($ObjectMethod)
$this->callObjectMethod($id, $ObjectMethod, $ObjectMethodParams);
return $id;
}
/**
* Adds another key alias for a var
*
* @method public addKey
* @return boolean TRUE on success, FALSE on failure
* @param string $type type name
* @param array $keys array of keys (should contain at least one previously used key).
*/
function addKey($type, $keys)
{
if (!is_array($keys))
$keys = (array) $keys;
$t_id = $this->findTypeId($type);
if (!$t_id)
return FALSE;
$id = $this->findId($type, $keys);
if (!$id)
return FALSE;
while ($key = array_pop($keys))
$this->keys[$t_id][$key] = $id;
return TRUE;
} // end of function addKey()
/**
* Deletes entity from cache. Can optionally call a method on objects.
*
* @method public delete
* @return boolean TRUE on success, FALSE on failure
* @param string $type type name
* @param mixed $keys key name or key name array
* @param optional string $ObjectMethod method name to call on object
* @param optional array $ObjectMethodParams parameters for the method
*/
function delete($type, $keys, $ObjectMethod = FALSE, $ObjectMethodParams = FALSE)
{
if ($id = $this->findId($type, $keys))
{
// call object methods if needed:
if ($ObjectMethod)
$this->callObjectMethod($id, $ObjectMethod, $ObjectMethodParams);
// remove all data about the entity:
$rm_keys = array_search($id, $this->keys[$type]);
if (!is_array($rm_keys))
$rm_keys = (array) $rm_keys;
while ($key = array_pop($rm_keys))
unset($this->keys[$t_id][$key]);
unset($this->data[$id]);
return TRUE;
}
else
return FALSE;
} // end of function delete();
/**
* Removes keys that correspond to the var.
*
* @method public deleteKeys
* @return boolean FALSE on failure
* @param string $type type name
* @param mixed $keys key name or array of key names
* @param optional boolean $many If $many == TRUE it means that $keys may belong to different entities (makes operate slower). Default is FALSE.
* @param optional string $ObjectMethod method name to call on object
* @param optional array $ObjectMethodParams parameters for the method
*/
function deleteKeys($type, $keys, $many = FALSE, $ObjectMethod = FALSE, $ObjectMethodParams = FALSE)
{
// 1. check if type exists:
$t_id = $this->findTypeId($type);
if (!$t_id)
{
$this->error('Unknown type \''.$type.'\' passed to function deleteKeys.');
return FALSE;
}
// 2. $keys has to be an array:
if (is_array($keys))
$keys = (array) $keys;
// 3a. we have got keys of one entity:
if (!$many)
{
$id = $this->findId($type, $keys);
while ($key = array_pop($keys))
unset($this->keys[$t_id]);
if (!array_search($id, $this->keys[$t_id]))
{
if ($ObjectMethod)
$this->callObjectMethod($id, $ObjectMethod, $ObjectMethodParams);
unset($this->data[$id]);
}
} // end of 3a.
// 3b. we have got keys of multiple entities:
else
{
while ($key = array_pop($keys))
{
if ($id = $this->findId($type, $keys))
{
unset($this->keys[$t_id]);
if (!array_search($id, $this->keys[$t_id]))
{
if ($ObjectMethod)
$this->callObjectMethod($id, $ObjectMethod, $ObjectMethodParams);
unset($this->data[$id]);
}
}
}
} // end of 3b.
} // end of function deleteKeys()
/**
* Checks if var exists in cache
*
* @method public exists
* @return mixed internal id on success, FALSE on failure
* @param string $type type name
* @param mixed $keys key name or key name array
*/
function exists($type, $keys)
{
$t_id = $this->findTypeId($type);
if (!$t_id)
return FALSE;
$id = $this->findId($type, $keys);
if (!$id)
return FALSE;
return $id;
} // end of function exists
/**
* Searches for var and returns a reference to it
*
* @method public find
* @return ref mixed whatever the variable is
* @param string $type type name
* @param mixed $keys key name or array of key names
*/
function &find($type, $keys)
{
$id = $this->findId($type, $keys);
if (!$id)
return FALSE;
else
return $this->data[$id];
} // end of function &find()
} // end of class ctlRTvarCache
?>