summaryrefslogtreecommitdiff
path: root/framework/Caching
diff options
context:
space:
mode:
authorctrlaltca <>2012-07-12 11:21:01 +0000
committerctrlaltca <>2012-07-12 11:21:01 +0000
commit903ae8a581fac1e6917fc3e31d2ad8fb91df80c3 (patch)
treee08bf04f0823650a231227ac3499121270172a23 /framework/Caching
parent3e4e6e66aeb3f8fea4e1eb4237498ef9d2358f63 (diff)
standardize the use of unix eol; use svn properties to enforce native eol
Diffstat (limited to 'framework/Caching')
-rw-r--r--framework/Caching/TAPCCache.php266
-rw-r--r--framework/Caching/TCache.php1440
-rw-r--r--framework/Caching/TDbCache.php1156
-rw-r--r--framework/Caching/TSqliteCache.php448
-rw-r--r--framework/Caching/TXCache.php262
5 files changed, 1786 insertions, 1786 deletions
diff --git a/framework/Caching/TAPCCache.php b/framework/Caching/TAPCCache.php
index 49cbd137..e0117a0c 100644
--- a/framework/Caching/TAPCCache.php
+++ b/framework/Caching/TAPCCache.php
@@ -1,133 +1,133 @@
-<?php
-/**
- * TAPCCache class file
- *
- * @author Alban Hanry <compte_messagerie@hotmail.com>
- * @link http://www.pradosoft.com/
- * @copyright Copyright &copy; 2005-2012 PradoSoft
- * @license http://www.pradosoft.com/license/
- * @version $Id$
- * @package System.Caching
- */
-
-/**
- * TAPCCache class
- *
- * TAPCCache implements a cache application module based on {@link http://www.php.net/apc APC}.
- *
- * By definition, cache does not ensure the existence of a value
- * even if it never expires. Cache is not meant to be an persistent storage.
- *
- * To use this module, the APC PHP extension must be loaded and set in the php.ini file the following:
- * <code>
- * apc.cache_by_default=0
- * </code>
- *
- * Some usage examples of TAPCCache are as follows,
- * <code>
- * $cache=new TAPCCache; // TAPCCache may also be loaded as a Prado application module
- * $cache->init(null);
- * $cache->add('object',$object);
- * $object2=$cache->get('object');
- * </code>
- *
- * If loaded, TAPCCache will register itself with {@link TApplication} as the
- * cache module. It can be accessed via {@link TApplication::getCache()}.
- *
- * TAPCCache may be configured in application configuration file as follows
- * <code>
- * <module id="cache" class="System.Caching.TAPCCache" />
- * </code>
- *
- * @author Alban Hanry <compte_messagerie@hotmail.com>
- * @author Knut Urdalen <knut.urdalen@gmail.com>
- * @version $Id$
- * @package System.Caching
- * @since 3.0b
- */
-class TAPCCache extends TCache
-{
- /**
- * Initializes this module.
- * This method is required by the IModule interface.
- * @param TXmlElement configuration for this module, can be null
- * @throws TConfigurationException if apc extension is not installed or not started, check your php.ini
- */
- public function init($config)
- {
- if(!extension_loaded('apc'))
- throw new TConfigurationException('apccache_extension_required');
-
- if(ini_get('apc.enabled') == false)
- throw new TConfigurationException('apccache_extension_not_enabled');
-
- if(substr(php_sapi_name(), 0, 3) === 'cli' and ini_get('apc.enable_cli') == false)
- throw new TConfigurationException('apccache_extension_not_enabled_cli');
-
- parent::init($config);
- }
-
- /**
- * Retrieves a value from cache with a specified key.
- * This is the implementation of the method declared in the parent class.
- * @param string a unique key identifying the cached value
- * @return string the value stored in cache, false if the value is not in the cache or expired.
- */
- protected function getValue($key)
- {
- return apc_fetch($key);
- }
-
- /**
- * Stores a value identified by a key in cache.
- * This is the implementation of the method declared in the parent class.
- *
- * @param string the key identifying the value to be cached
- * @param string the value to be cached
- * @param integer the number of seconds in which the cached value will expire. 0 means never expire.
- * @return boolean true if the value is successfully stored into cache, false otherwise
- */
- protected function setValue($key,$value,$expire)
- {
- return apc_store($key,$value,$expire);
- }
-
- /**
- * Stores a value identified by a key into cache if the cache does not contain this key.
- * This is the implementation of the method declared in the parent class.
- *
- * @param string the key identifying the value to be cached
- * @param string the value to be cached
- * @param integer the number of seconds in which the cached value will expire. 0 means never expire.
- * @return boolean true if the value is successfully stored into cache, false otherwise
- */
- protected function addValue($key,$value,$expire)
- {
- if(function_exists('apc_add')) {
- return apc_add($key,$value,$expire);
- } else {
- throw new TNotSupportedException('apccache_add_unsupported');
- }
- }
-
- /**
- * Deletes a value with the specified key from cache
- * This is the implementation of the method declared in the parent class.
- * @param string the key of the value to be deleted
- * @return boolean if no error happens during deletion
- */
- protected function deleteValue($key)
- {
- return apc_delete($key);
- }
-
- /**
- * Deletes all values from cache.
- * Be careful of performing this operation if the cache is shared by multiple applications.
- */
- public function flush()
- {
- return apc_clear_cache('user');
- }
-}
-
+<?php
+/**
+ * TAPCCache class file
+ *
+ * @author Alban Hanry <compte_messagerie@hotmail.com>
+ * @link http://www.pradosoft.com/
+ * @copyright Copyright &copy; 2005-2012 PradoSoft
+ * @license http://www.pradosoft.com/license/
+ * @version $Id$
+ * @package System.Caching
+ */
+
+/**
+ * TAPCCache class
+ *
+ * TAPCCache implements a cache application module based on {@link http://www.php.net/apc APC}.
+ *
+ * By definition, cache does not ensure the existence of a value
+ * even if it never expires. Cache is not meant to be an persistent storage.
+ *
+ * To use this module, the APC PHP extension must be loaded and set in the php.ini file the following:
+ * <code>
+ * apc.cache_by_default=0
+ * </code>
+ *
+ * Some usage examples of TAPCCache are as follows,
+ * <code>
+ * $cache=new TAPCCache; // TAPCCache may also be loaded as a Prado application module
+ * $cache->init(null);
+ * $cache->add('object',$object);
+ * $object2=$cache->get('object');
+ * </code>
+ *
+ * If loaded, TAPCCache will register itself with {@link TApplication} as the
+ * cache module. It can be accessed via {@link TApplication::getCache()}.
+ *
+ * TAPCCache may be configured in application configuration file as follows
+ * <code>
+ * <module id="cache" class="System.Caching.TAPCCache" />
+ * </code>
+ *
+ * @author Alban Hanry <compte_messagerie@hotmail.com>
+ * @author Knut Urdalen <knut.urdalen@gmail.com>
+ * @version $Id$
+ * @package System.Caching
+ * @since 3.0b
+ */
+class TAPCCache extends TCache
+{
+ /**
+ * Initializes this module.
+ * This method is required by the IModule interface.
+ * @param TXmlElement configuration for this module, can be null
+ * @throws TConfigurationException if apc extension is not installed or not started, check your php.ini
+ */
+ public function init($config)
+ {
+ if(!extension_loaded('apc'))
+ throw new TConfigurationException('apccache_extension_required');
+
+ if(ini_get('apc.enabled') == false)
+ throw new TConfigurationException('apccache_extension_not_enabled');
+
+ if(substr(php_sapi_name(), 0, 3) === 'cli' and ini_get('apc.enable_cli') == false)
+ throw new TConfigurationException('apccache_extension_not_enabled_cli');
+
+ parent::init($config);
+ }
+
+ /**
+ * Retrieves a value from cache with a specified key.
+ * This is the implementation of the method declared in the parent class.
+ * @param string a unique key identifying the cached value
+ * @return string the value stored in cache, false if the value is not in the cache or expired.
+ */
+ protected function getValue($key)
+ {
+ return apc_fetch($key);
+ }
+
+ /**
+ * Stores a value identified by a key in cache.
+ * This is the implementation of the method declared in the parent class.
+ *
+ * @param string the key identifying the value to be cached
+ * @param string the value to be cached
+ * @param integer the number of seconds in which the cached value will expire. 0 means never expire.
+ * @return boolean true if the value is successfully stored into cache, false otherwise
+ */
+ protected function setValue($key,$value,$expire)
+ {
+ return apc_store($key,$value,$expire);
+ }
+
+ /**
+ * Stores a value identified by a key into cache if the cache does not contain this key.
+ * This is the implementation of the method declared in the parent class.
+ *
+ * @param string the key identifying the value to be cached
+ * @param string the value to be cached
+ * @param integer the number of seconds in which the cached value will expire. 0 means never expire.
+ * @return boolean true if the value is successfully stored into cache, false otherwise
+ */
+ protected function addValue($key,$value,$expire)
+ {
+ if(function_exists('apc_add')) {
+ return apc_add($key,$value,$expire);
+ } else {
+ throw new TNotSupportedException('apccache_add_unsupported');
+ }
+ }
+
+ /**
+ * Deletes a value with the specified key from cache
+ * This is the implementation of the method declared in the parent class.
+ * @param string the key of the value to be deleted
+ * @return boolean if no error happens during deletion
+ */
+ protected function deleteValue($key)
+ {
+ return apc_delete($key);
+ }
+
+ /**
+ * Deletes all values from cache.
+ * Be careful of performing this operation if the cache is shared by multiple applications.
+ */
+ public function flush()
+ {
+ return apc_clear_cache('user');
+ }
+}
+
diff --git a/framework/Caching/TCache.php b/framework/Caching/TCache.php
index d4f74bf0..00d69c3c 100644
--- a/framework/Caching/TCache.php
+++ b/framework/Caching/TCache.php
@@ -1,720 +1,720 @@
-<?php
-/**
- * TCache and cache dependency classes.
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @link http://www.pradosoft.com/
- * @copyright Copyright &copy; 2005-2012 PradoSoft
- * @license http://www.pradosoft.com/license/
- * @version $Id$
- * @package System.Caching
- */
-
-Prado::using('System.Collections.TList');
-
-/**
- * TCache class
- *
- * TCache is the base class for cache classes with different cache storage implementation.
- *
- * TCache implements the interface {@link ICache} with the following methods,
- * - {@link get} : retrieve the value with a key (if any) from cache
- * - {@link set} : store the value with a key into cache
- * - {@link add} : store the value only if cache does not have this key
- * - {@link delete} : delete the value with the specified key from cache
- * - {@link flush} : delete all values from cache
- *
- * Each value is associated with an expiration time. The {@link get} operation
- * ensures that any expired value will not be returned. The expiration time by
- * the number of seconds. A expiration time 0 represents never expire.
- *
- * By definition, cache does not ensure the existence of a value
- * even if it never expires. Cache is not meant to be an persistent storage.
- *
- * Child classes must implement the following methods:
- * - {@link getValue}
- * - {@link setValue}
- * - {@link addValue}
- * - {@link deleteValue}
- * and optionally {@link flush}
- *
- * Since version 3.1.2, TCache implements the ArrayAccess interface such that
- * the cache acts as an array.
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @version $Id$
- * @package System.Caching
- * @since 3.0
- */
-abstract class TCache extends TModule implements ICache, ArrayAccess
-{
- private $_prefix=null;
- private $_primary=true;
-
- /**
- * Initializes the cache module.
- * This method initializes the cache key prefix and registers the cache module
- * with the application if the cache is primary.
- * @param TXmlElement the module configuration
- */
- public function init($config)
- {
- if($this->_prefix===null)
- $this->_prefix=$this->getApplication()->getUniqueID();
- if($this->_primary)
- {
- if($this->getApplication()->getCache()===null)
- $this->getApplication()->setCache($this);
- else
- throw new TConfigurationException('cache_primary_duplicated',get_class($this));
- }
- }
-
- /**
- * @return boolean whether this cache module is used as primary/system cache.
- * A primary cache is used by PRADO core framework to cache data such as
- * parsed templates, themes, etc.
- */
- public function getPrimaryCache()
- {
- return $this->_primary;
- }
-
- /**
- * @param boolean whether this cache module is used as primary/system cache. Defaults to false.
- * @see getPrimaryCache
- */
- public function setPrimaryCache($value)
- {
- $this->_primary=TPropertyValue::ensureBoolean($value);
- }
-
- /**
- * @return string a unique prefix for the keys of cached values.
- * If it is not explicitly set, it will take the value of {@link TApplication::getUniqueID}.
- */
- public function getKeyPrefix()
- {
- return $this->_prefix;
- }
-
- /**
- * @param string a unique prefix for the keys of cached values
- */
- public function setKeyPrefix($value)
- {
- $this->_prefix=$value;
- }
-
- /**
- * @param string a key identifying a value to be cached
- * @return sring a key generated from the provided key which ensures the uniqueness across applications
- */
- protected function generateUniqueKey($key)
- {
- return md5($this->_prefix.$key);
- }
-
- /**
- * Retrieves a value from cache with a specified key.
- * @param string a key identifying the cached value
- * @return mixed the value stored in cache, false if the value is not in the cache or expired.
- */
- public function get($id)
- {
- if(($data=$this->getValue($this->generateUniqueKey($id)))!==false)
- {
- if(!is_array($data))
- return false;
- if(!($data[1] instanceof ICacheDependency) || !$data[1]->getHasChanged())
- return $data[0];
- }
- return false;
- }
-
- /**
- * Stores a value identified by a key into cache.
- * If the cache already contains such a key, the existing value and
- * expiration time will be replaced with the new ones. If the value is
- * empty, the cache key will be deleted.
- *
- * @param string the key identifying the value to be cached
- * @param mixed the value to be cached
- * @param integer the number of seconds in which the cached value will expire. 0 means never expire.
- * @param ICacheDependency dependency of the cached item. If the dependency changes, the item is labeled invalid.
- * @return boolean true if the value is successfully stored into cache, false otherwise
- */
- public function set($id,$value,$expire=0,$dependency=null)
- {
- if(empty($value) && $expire === 0)
- $this->delete($id);
- else
- {
- $data=array($value,$dependency);
- return $this->setValue($this->generateUniqueKey($id),$data,$expire);
- }
- }
-
- /**
- * Stores a value identified by a key into cache if the cache does not contain this key.
- * Nothing will be done if the cache already contains the key or if value is empty.
- * @param string the key identifying the value to be cached
- * @param mixed the value to be cached
- * @param integer the number of seconds in which the cached value will expire. 0 means never expire.
- * @param ICacheDependency dependency of the cached item. If the dependency changes, the item is labeled invalid.
- * @return boolean true if the value is successfully stored into cache, false otherwise
- */
- public function add($id,$value,$expire=0,$dependency=null)
- {
- if(empty($value) && $expire === 0)
- return false;
- $data=array($value,$dependency);
- return $this->addValue($this->generateUniqueKey($id),$data,$expire);
- }
-
- /**
- * Deletes a value with the specified key from cache
- * @param string the key of the value to be deleted
- * @return boolean if no error happens during deletion
- */
- public function delete($id)
- {
- return $this->deleteValue($this->generateUniqueKey($id));
- }
-
- /**
- * Deletes all values from cache.
- * Be careful of performing this operation if the cache is shared by multiple applications.
- * Child classes may implement this method to realize the flush operation.
- * @throws TNotSupportedException if this method is not overridden by child classes
- */
- public function flush()
- {
- throw new TNotSupportedException('cache_flush_unsupported');
- }
-
- /**
- * Retrieves a value from cache with a specified key.
- * This method should be implemented by child classes to store the data
- * in specific cache storage. The uniqueness and dependency are handled
- * in {@link get()} already. So only the implementation of data retrieval
- * is needed.
- * @param string a unique key identifying the cached value
- * @return string the value stored in cache, false if the value is not in the cache or expired.
- */
- abstract protected function getValue($key);
-
- /**
- * Stores a value identified by a key in cache.
- * This method should be implemented by child classes to store the data
- * in specific cache storage. The uniqueness and dependency are handled
- * in {@link set()} already. So only the implementation of data storage
- * is needed.
- *
- * @param string the key identifying the value to be cached
- * @param string the value to be cached
- * @param integer the number of seconds in which the cached value will expire. 0 means never expire.
- * @return boolean true if the value is successfully stored into cache, false otherwise
- */
- abstract protected function setValue($key,$value,$expire);
-
- /**
- * Stores a value identified by a key into cache if the cache does not contain this key.
- * This method should be implemented by child classes to store the data
- * in specific cache storage. The uniqueness and dependency are handled
- * in {@link add()} already. So only the implementation of data storage
- * is needed.
- *
- * @param string the key identifying the value to be cached
- * @param string the value to be cached
- * @param integer the number of seconds in which the cached value will expire. 0 means never expire.
- * @return boolean true if the value is successfully stored into cache, false otherwise
- */
- abstract protected function addValue($key,$value,$expire);
-
- /**
- * Deletes a value with the specified key from cache
- * This method should be implemented by child classes to delete the data from actual cache storage.
- * @param string the key of the value to be deleted
- * @return boolean if no error happens during deletion
- */
- abstract protected function deleteValue($key);
-
- /**
- * Returns whether there is a cache entry with a specified key.
- * This method is required by the interface ArrayAccess.
- * @param string a key identifying the cached value
- * @return boolean
- */
- public function offsetExists($id)
- {
- return $this->get($id) !== false;
- }
-
- /**
- * Retrieves the value from cache with a specified key.
- * This method is required by the interface ArrayAccess.
- * @param string a key identifying the cached value
- * @return mixed the value stored in cache, false if the value is not in the cache or expired.
- */
- public function offsetGet($id)
- {
- return $this->get($id);
- }
-
- /**
- * Stores the value identified by a key into cache.
- * If the cache already contains such a key, the existing value will be
- * replaced with the new ones. To add expiration and dependencies, use the set() method.
- * This method is required by the interface ArrayAccess.
- * @param string the key identifying the value to be cached
- * @param mixed the value to be cached
- */
- public function offsetSet($id, $value)
- {
- $this->set($id, $value);
- }
-
- /**
- * Deletes the value with the specified key from cache
- * This method is required by the interface ArrayAccess.
- * @param string the key of the value to be deleted
- * @return boolean if no error happens during deletion
- */
- public function offsetUnset($id)
- {
- $this->delete($id);
- }
-}
-
-
-/**
- * TCacheDependency class.
- *
- * TCacheDependency is the base class implementing {@link ICacheDependency} interface.
- * Descendant classes must implement {@link getHasChanged()} to provide
- * actual dependency checking logic.
- *
- * The property value of {@link getHasChanged HasChanged} tells whether
- * the dependency is changed or not.
- *
- * You may disable the dependency checking by setting {@link setEnabled Enabled}
- * to false.
- *
- * Note, since the dependency objects often need to be serialized so that
- * they can persist across requests, you may need to implement __sleep() and
- * __wakeup() if the dependency objects contain resource handles which are
- * not serializable.
- *
- * Currently, the following dependency classes are provided in the PRADO release:
- * - {@link TFileCacheDependency}: checks whether a file is changed or not
- * - {@link TDirectoryCacheDependency}: checks whether a directory is changed or not
- * - {@link TGlobalStateCacheDependency}: checks whether a global state is changed or not
- * - {@link TChainedCacheDependency}: checks whether any of a list of dependencies is changed or not
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @version $Id$
- * @package System.Caching
- * @since 3.1.0
- */
-abstract class TCacheDependency extends TComponent implements ICacheDependency
-{
-}
-
-
-/**
- * TFileCacheDependency class.
- *
- * TFileCacheDependency performs dependency checking based on the
- * last modification time of the file specified via {@link setFileName FileName}.
- * The dependency is reported as unchanged if and only if the file's
- * last modification time remains unchanged.
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @version $Id$
- * @package System.Caching
- * @since 3.1.0
- */
-class TFileCacheDependency extends TCacheDependency
-{
- private $_fileName;
- private $_timestamp;
-
- /**
- * Constructor.
- * @param string name of the file whose change is to be checked.
- */
- public function __construct($fileName)
- {
- $this->setFileName($fileName);
- }
-
- /**
- * @return string the name of the file whose change is to be checked
- */
- public function getFileName()
- {
- return $this->_fileName;
- }
-
- /**
- * @param string the name of the file whose change is to be checked
- */
- public function setFileName($value)
- {
- $this->_fileName=$value;
- $this->_timestamp=@filemtime($value);
- }
-
- /**
- * @return int the last modification time of the file
- */
- public function getTimestamp()
- {
- return $this->_timestamp;
- }
-
- /**
- * Performs the actual dependency checking.
- * This method returns true if the last modification time of the file is changed.
- * @return boolean whether the dependency is changed or not.
- */
- public function getHasChanged()
- {
- return @filemtime($this->_fileName)!==$this->_timestamp;
- }
-}
-
-/**
- * TDirectoryCacheDependency class.
- *
- * TDirectoryCacheDependency performs dependency checking based on the
- * modification time of the files contained in the specified directory.
- * The directory being checked is specified via {@link setDirectory Directory}.
- *
- * By default, all files under the specified directory and subdirectories
- * will be checked. If the last modification time of any of them is changed
- * or if different number of files are contained in a directory, the dependency
- * is reported as changed. By specifying {@link setRecursiveCheck RecursiveCheck}
- * and {@link setRecursiveLevel RecursiveLevel}, one can limit the checking
- * to a certain depth of the subdirectories.
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @version $Id$
- * @package System.Caching
- * @since 3.1.0
- */
-class TDirectoryCacheDependency extends TCacheDependency
-{
- private $_recursiveCheck=true;
- private $_recursiveLevel=-1;
- private $_timestamps;
- private $_directory;
-
- /**
- * Constructor.
- * @param string the directory to be checked
- */
- public function __construct($directory)
- {
- $this->setDirectory($directory);
- }
-
- /**
- * @return string the directory to be checked
- */
- public function getDirectory()
- {
- return $this->_directory;
- }
-
- /**
- * @param string the directory to be checked
- * @throws TInvalidDataValueException if the directory does not exist
- */
- public function setDirectory($directory)
- {
- if(($path=realpath($directory))===false || !is_dir($path))
- throw new TInvalidDataValueException('directorycachedependency_directory_invalid',$directory);
- $this->_directory=$path;
- $this->_timestamps=$this->generateTimestamps($path);
- }
-
- /**
- * @return boolean whether the subdirectories of the directory will also be checked.
- * It defaults to true.
- */
- public function getRecursiveCheck()
- {
- return $this->_recursiveCheck;
- }
-
- /**
- * @param boolean whether the subdirectories of the directory will also be checked.
- */
- public function setRecursiveCheck($value)
- {
- $this->_recursiveCheck=TPropertyValue::ensureBoolean($value);
- }
-
- /**
- * @return int the depth of the subdirectories to be checked.
- * It defaults to -1, meaning unlimited depth.
- */
- public function getRecursiveLevel()
- {
- return $this->_recursiveLevel;
- }
-
- /**
- * Sets a value indicating the depth of the subdirectories to be checked.
- * This is meaningful only when {@link getRecursiveCheck RecursiveCheck}
- * is true.
- * @param int the depth of the subdirectories to be checked.
- * If the value is less than 0, it means unlimited depth.
- * If the value is 0, it means checking the files directly under the specified directory.
- */
- public function setRecursiveLevel($value)
- {
- $this->_recursiveLevel=TPropertyValue::ensureInteger($value);
- }
-
- /**
- * Performs the actual dependency checking.
- * This method returns true if the directory is changed.
- * @return boolean whether the dependency is changed or not.
- */
- public function getHasChanged()
- {
- return $this->generateTimestamps($this->_directory)!=$this->_timestamps;
- }
-
- /**
- * Checks to see if the file should be checked for dependency.
- * This method is invoked when dependency of the whole directory is being checked.
- * By default, it always returns true, meaning the file should be checked.
- * You may override this method to check only certain files.
- * @param string the name of the file that may be checked for dependency.
- * @return boolean whether this file should be checked.
- */
- protected function validateFile($fileName)
- {
- return true;
- }
-
- /**
- * Checks to see if the specified subdirectory should be checked for dependency.
- * This method is invoked when dependency of the whole directory is being checked.
- * By default, it always returns true, meaning the subdirectory should be checked.
- * You may override this method to check only certain subdirectories.
- * @param string the name of the subdirectory that may be checked for dependency.
- * @return boolean whether this subdirectory should be checked.
- */
- protected function validateDirectory($directory)
- {
- return true;
- }
-
- /**
- * Determines the last modification time for files under the directory.
- * This method may go recursively into subdirectories if
- * {@link setRecursiveCheck RecursiveCheck} is set true.
- * @param string the directory name
- * @param int level of the recursion
- * @return array list of file modification time indexed by the file path
- */
- protected function generateTimestamps($directory,$level=0)
- {
- if(($dir=opendir($directory))===false)
- throw new TIOException('directorycachedependency_directory_invalid',$directory);
- $timestamps=array();
- while(($file=readdir($dir))!==false)
- {
- $path=$directory.DIRECTORY_SEPARATOR.$file;
- if($file==='.' || $file==='..')
- continue;
- else if(is_dir($path))
- {
- if(($this->_recursiveLevel<0 || $level<$this->_recursiveLevel) && $this->validateDirectory($path))
- $timestamps=array_merge($this->generateTimestamps($path,$level+1));
- }
- else if($this->validateFile($path))
- $timestamps[$path]=filemtime($path);
- }
- closedir($dir);
- return $timestamps;
- }
-}
-
-
-/**
- * TGlobalStateCacheDependency class.
- *
- * TGlobalStateCacheDependency checks if a global state is changed or not.
- * If the global state is changed, the dependency is reported as changed.
- * To specify which global state this dependency should check with,
- * set {@link setStateName StateName} to the name of the global state.
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @version $Id$
- * @package System.Caching
- * @since 3.1.0
- */
-class TGlobalStateCacheDependency extends TCacheDependency
-{
- private $_stateName;
- private $_stateValue;
-
- /**
- * Constructor.
- * @param string the name of the global state
- */
- public function __construct($name)
- {
- $this->setStateName($name);
- }
-
- /**
- * @return string the name of the global state
- */
- public function getStateName()
- {
- return $this->_stateName;
- }
-
- /**
- * @param string the name of the global state
- * @see TApplication::setGlobalState
- */
- public function setStateName($value)
- {
- $this->_stateName=$value;
- $this->_stateValue=Prado::getApplication()->getGlobalState($value);
- }
-
- /**
- * Performs the actual dependency checking.
- * This method returns true if the specified global state is changed.
- * @return boolean whether the dependency is changed or not.
- */
- public function getHasChanged()
- {
- return $this->_stateValue!==Prado::getApplication()->getGlobalState($this->_stateName);
- }
-}
-
-
-/**
- * TChainedCacheDependency class.
- *
- * TChainedCacheDependency represents a list of cache dependency objects
- * and performs the dependency checking based on the checking results of
- * these objects. If any of them reports a dependency change, TChainedCacheDependency
- * will return true for the checking.
- *
- * To add dependencies to TChainedCacheDependency, use {@link getDependencies Dependencies}
- * which gives a {@link TCacheDependencyList} instance and can be used like an array
- * (see {@link TList} for more details}).
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @version $Id$
- * @package System.Caching
- * @since 3.1.0
- */
-class TChainedCacheDependency extends TCacheDependency
-{
- private $_dependencies=null;
-
- /**
- * @return TCacheDependencyList list of dependency objects
- */
- public function getDependencies()
- {
- if($this->_dependencies===null)
- $this->_dependencies=new TCacheDependencyList;
- return $this->_dependencies;
- }
-
- /**
- * Performs the actual dependency checking.
- * This method returns true if any of the dependency objects
- * reports a dependency change.
- * @return boolean whether the dependency is changed or not.
- */
- public function getHasChanged()
- {
- if($this->_dependencies!==null)
- {
- foreach($this->_dependencies as $dependency)
- if($dependency->getHasChanged())
- return true;
- }
- return false;
- }
-}
-
-
-/**
- * TApplicationStateCacheDependency class.
- *
- * TApplicationStateCacheDependency performs dependency checking based on
- * the mode of the currently running PRADO application.
- * The dependency is reportedly as unchanged if and only if the application
- * is running in performance mode.
- *
- * You may chain this dependency together with other dependencies
- * so that only when the application is not in performance mode the other dependencies
- * will be checked.
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @version $Id$
- * @package System.Caching
- * @since 3.1.0
- */
-class TApplicationStateCacheDependency extends TCacheDependency
-{
- /**
- * Performs the actual dependency checking.
- * This method returns true if the currently running application is not in performance mode.
- * @return boolean whether the dependency is changed or not.
- */
- public function getHasChanged()
- {
- return Prado::getApplication()->getMode()!==TApplicationMode::Performance;
- }
-}
-
-/**
- * TCacheDependencyList class.
- *
- * TCacheDependencyList represents a list of cache dependency objects.
- * Only objects implementing {@link ICacheDependency} can be added into this list.
- *
- * TCacheDependencyList can be used like an array. See {@link TList}
- * for more details.
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @version $Id$
- * @package System.Caching
- * @since 3.1.0
- */
-class TCacheDependencyList extends TList
-{
- /**
- * Inserts an item at the specified position.
- * This overrides the parent implementation by performing additional type checking
- * for each newly added item.
- * @param integer the specified position.
- * @param mixed new item
- * @throws TInvalidDataTypeException if the item to be inserted is not a dependency instance
- */
- public function insertAt($index,$item)
- {
- if($item instanceof ICacheDependency)
- parent::insertAt($index,$item);
- else
- throw new TInvalidDataTypeException('cachedependencylist_cachedependency_required');
- }
-}
-
-?>
+<?php
+/**
+ * TCache and cache dependency classes.
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @link http://www.pradosoft.com/
+ * @copyright Copyright &copy; 2005-2012 PradoSoft
+ * @license http://www.pradosoft.com/license/
+ * @version $Id$
+ * @package System.Caching
+ */
+
+Prado::using('System.Collections.TList');
+
+/**
+ * TCache class
+ *
+ * TCache is the base class for cache classes with different cache storage implementation.
+ *
+ * TCache implements the interface {@link ICache} with the following methods,
+ * - {@link get} : retrieve the value with a key (if any) from cache
+ * - {@link set} : store the value with a key into cache
+ * - {@link add} : store the value only if cache does not have this key
+ * - {@link delete} : delete the value with the specified key from cache
+ * - {@link flush} : delete all values from cache
+ *
+ * Each value is associated with an expiration time. The {@link get} operation
+ * ensures that any expired value will not be returned. The expiration time by
+ * the number of seconds. A expiration time 0 represents never expire.
+ *
+ * By definition, cache does not ensure the existence of a value
+ * even if it never expires. Cache is not meant to be an persistent storage.
+ *
+ * Child classes must implement the following methods:
+ * - {@link getValue}
+ * - {@link setValue}
+ * - {@link addValue}
+ * - {@link deleteValue}
+ * and optionally {@link flush}
+ *
+ * Since version 3.1.2, TCache implements the ArrayAccess interface such that
+ * the cache acts as an array.
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @version $Id$
+ * @package System.Caching
+ * @since 3.0
+ */
+abstract class TCache extends TModule implements ICache, ArrayAccess
+{
+ private $_prefix=null;
+ private $_primary=true;
+
+ /**
+ * Initializes the cache module.
+ * This method initializes the cache key prefix and registers the cache module
+ * with the application if the cache is primary.
+ * @param TXmlElement the module configuration
+ */
+ public function init($config)
+ {
+ if($this->_prefix===null)
+ $this->_prefix=$this->getApplication()->getUniqueID();
+ if($this->_primary)
+ {
+ if($this->getApplication()->getCache()===null)
+ $this->getApplication()->setCache($this);
+ else
+ throw new TConfigurationException('cache_primary_duplicated',get_class($this));
+ }
+ }
+
+ /**
+ * @return boolean whether this cache module is used as primary/system cache.
+ * A primary cache is used by PRADO core framework to cache data such as
+ * parsed templates, themes, etc.
+ */
+ public function getPrimaryCache()
+ {
+ return $this->_primary;
+ }
+
+ /**
+ * @param boolean whether this cache module is used as primary/system cache. Defaults to false.
+ * @see getPrimaryCache
+ */
+ public function setPrimaryCache($value)
+ {
+ $this->_primary=TPropertyValue::ensureBoolean($value);
+ }
+
+ /**
+ * @return string a unique prefix for the keys of cached values.
+ * If it is not explicitly set, it will take the value of {@link TApplication::getUniqueID}.
+ */
+ public function getKeyPrefix()
+ {
+ return $this->_prefix;
+ }
+
+ /**
+ * @param string a unique prefix for the keys of cached values
+ */
+ public function setKeyPrefix($value)
+ {
+ $this->_prefix=$value;
+ }
+
+ /**
+ * @param string a key identifying a value to be cached
+ * @return sring a key generated from the provided key which ensures the uniqueness across applications
+ */
+ protected function generateUniqueKey($key)
+ {
+ return md5($this->_prefix.$key);
+ }
+
+ /**
+ * Retrieves a value from cache with a specified key.
+ * @param string a key identifying the cached value
+ * @return mixed the value stored in cache, false if the value is not in the cache or expired.
+ */
+ public function get($id)
+ {
+ if(($data=$this->getValue($this->generateUniqueKey($id)))!==false)
+ {
+ if(!is_array($data))
+ return false;
+ if(!($data[1] instanceof ICacheDependency) || !$data[1]->getHasChanged())
+ return $data[0];
+ }
+ return false;
+ }
+
+ /**
+ * Stores a value identified by a key into cache.
+ * If the cache already contains such a key, the existing value and
+ * expiration time will be replaced with the new ones. If the value is
+ * empty, the cache key will be deleted.
+ *
+ * @param string the key identifying the value to be cached
+ * @param mixed the value to be cached
+ * @param integer the number of seconds in which the cached value will expire. 0 means never expire.
+ * @param ICacheDependency dependency of the cached item. If the dependency changes, the item is labeled invalid.
+ * @return boolean true if the value is successfully stored into cache, false otherwise
+ */
+ public function set($id,$value,$expire=0,$dependency=null)
+ {
+ if(empty($value) && $expire === 0)
+ $this->delete($id);
+ else
+ {
+ $data=array($value,$dependency);
+ return $this->setValue($this->generateUniqueKey($id),$data,$expire);
+ }
+ }
+
+ /**
+ * Stores a value identified by a key into cache if the cache does not contain this key.
+ * Nothing will be done if the cache already contains the key or if value is empty.
+ * @param string the key identifying the value to be cached
+ * @param mixed the value to be cached
+ * @param integer the number of seconds in which the cached value will expire. 0 means never expire.
+ * @param ICacheDependency dependency of the cached item. If the dependency changes, the item is labeled invalid.
+ * @return boolean true if the value is successfully stored into cache, false otherwise
+ */
+ public function add($id,$value,$expire=0,$dependency=null)
+ {
+ if(empty($value) && $expire === 0)
+ return false;
+ $data=array($value,$dependency);
+ return $this->addValue($this->generateUniqueKey($id),$data,$expire);
+ }
+
+ /**
+ * Deletes a value with the specified key from cache
+ * @param string the key of the value to be deleted
+ * @return boolean if no error happens during deletion
+ */
+ public function delete($id)
+ {
+ return $this->deleteValue($this->generateUniqueKey($id));
+ }
+
+ /**
+ * Deletes all values from cache.
+ * Be careful of performing this operation if the cache is shared by multiple applications.
+ * Child classes may implement this method to realize the flush operation.
+ * @throws TNotSupportedException if this method is not overridden by child classes
+ */
+ public function flush()
+ {
+ throw new TNotSupportedException('cache_flush_unsupported');
+ }
+
+ /**
+ * Retrieves a value from cache with a specified key.
+ * This method should be implemented by child classes to store the data
+ * in specific cache storage. The uniqueness and dependency are handled
+ * in {@link get()} already. So only the implementation of data retrieval
+ * is needed.
+ * @param string a unique key identifying the cached value
+ * @return string the value stored in cache, false if the value is not in the cache or expired.
+ */
+ abstract protected function getValue($key);
+
+ /**
+ * Stores a value identified by a key in cache.
+ * This method should be implemented by child classes to store the data
+ * in specific cache storage. The uniqueness and dependency are handled
+ * in {@link set()} already. So only the implementation of data storage
+ * is needed.
+ *
+ * @param string the key identifying the value to be cached
+ * @param string the value to be cached
+ * @param integer the number of seconds in which the cached value will expire. 0 means never expire.
+ * @return boolean true if the value is successfully stored into cache, false otherwise
+ */
+ abstract protected function setValue($key,$value,$expire);
+
+ /**
+ * Stores a value identified by a key into cache if the cache does not contain this key.
+ * This method should be implemented by child classes to store the data
+ * in specific cache storage. The uniqueness and dependency are handled
+ * in {@link add()} already. So only the implementation of data storage
+ * is needed.
+ *
+ * @param string the key identifying the value to be cached
+ * @param string the value to be cached
+ * @param integer the number of seconds in which the cached value will expire. 0 means never expire.
+ * @return boolean true if the value is successfully stored into cache, false otherwise
+ */
+ abstract protected function addValue($key,$value,$expire);
+
+ /**
+ * Deletes a value with the specified key from cache
+ * This method should be implemented by child classes to delete the data from actual cache storage.
+ * @param string the key of the value to be deleted
+ * @return boolean if no error happens during deletion
+ */
+ abstract protected function deleteValue($key);
+
+ /**
+ * Returns whether there is a cache entry with a specified key.
+ * This method is required by the interface ArrayAccess.
+ * @param string a key identifying the cached value
+ * @return boolean
+ */
+ public function offsetExists($id)
+ {
+ return $this->get($id) !== false;
+ }
+
+ /**
+ * Retrieves the value from cache with a specified key.
+ * This method is required by the interface ArrayAccess.
+ * @param string a key identifying the cached value
+ * @return mixed the value stored in cache, false if the value is not in the cache or expired.
+ */
+ public function offsetGet($id)
+ {
+ return $this->get($id);
+ }
+
+ /**
+ * Stores the value identified by a key into cache.
+ * If the cache already contains such a key, the existing value will be
+ * replaced with the new ones. To add expiration and dependencies, use the set() method.
+ * This method is required by the interface ArrayAccess.
+ * @param string the key identifying the value to be cached
+ * @param mixed the value to be cached
+ */
+ public function offsetSet($id, $value)
+ {
+ $this->set($id, $value);
+ }
+
+ /**
+ * Deletes the value with the specified key from cache
+ * This method is required by the interface ArrayAccess.
+ * @param string the key of the value to be deleted
+ * @return boolean if no error happens during deletion
+ */
+ public function offsetUnset($id)
+ {
+ $this->delete($id);
+ }
+}
+
+
+/**
+ * TCacheDependency class.
+ *
+ * TCacheDependency is the base class implementing {@link ICacheDependency} interface.
+ * Descendant classes must implement {@link getHasChanged()} to provide
+ * actual dependency checking logic.
+ *
+ * The property value of {@link getHasChanged HasChanged} tells whether
+ * the dependency is changed or not.
+ *
+ * You may disable the dependency checking by setting {@link setEnabled Enabled}
+ * to false.
+ *
+ * Note, since the dependency objects often need to be serialized so that
+ * they can persist across requests, you may need to implement __sleep() and
+ * __wakeup() if the dependency objects contain resource handles which are
+ * not serializable.
+ *
+ * Currently, the following dependency classes are provided in the PRADO release:
+ * - {@link TFileCacheDependency}: checks whether a file is changed or not
+ * - {@link TDirectoryCacheDependency}: checks whether a directory is changed or not
+ * - {@link TGlobalStateCacheDependency}: checks whether a global state is changed or not
+ * - {@link TChainedCacheDependency}: checks whether any of a list of dependencies is changed or not
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @version $Id$
+ * @package System.Caching
+ * @since 3.1.0
+ */
+abstract class TCacheDependency extends TComponent implements ICacheDependency
+{
+}
+
+
+/**
+ * TFileCacheDependency class.
+ *
+ * TFileCacheDependency performs dependency checking based on the
+ * last modification time of the file specified via {@link setFileName FileName}.
+ * The dependency is reported as unchanged if and only if the file's
+ * last modification time remains unchanged.
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @version $Id$
+ * @package System.Caching
+ * @since 3.1.0
+ */
+class TFileCacheDependency extends TCacheDependency
+{
+ private $_fileName;
+ private $_timestamp;
+
+ /**
+ * Constructor.
+ * @param string name of the file whose change is to be checked.
+ */
+ public function __construct($fileName)
+ {
+ $this->setFileName($fileName);
+ }
+
+ /**
+ * @return string the name of the file whose change is to be checked
+ */
+ public function getFileName()
+ {
+ return $this->_fileName;
+ }
+
+ /**
+ * @param string the name of the file whose change is to be checked
+ */
+ public function setFileName($value)
+ {
+ $this->_fileName=$value;
+ $this->_timestamp=@filemtime($value);
+ }
+
+ /**
+ * @return int the last modification time of the file
+ */
+ public function getTimestamp()
+ {
+ return $this->_timestamp;
+ }
+
+ /**
+ * Performs the actual dependency checking.
+ * This method returns true if the last modification time of the file is changed.
+ * @return boolean whether the dependency is changed or not.
+ */
+ public function getHasChanged()
+ {
+ return @filemtime($this->_fileName)!==$this->_timestamp;
+ }
+}
+
+/**
+ * TDirectoryCacheDependency class.
+ *
+ * TDirectoryCacheDependency performs dependency checking based on the
+ * modification time of the files contained in the specified directory.
+ * The directory being checked is specified via {@link setDirectory Directory}.
+ *
+ * By default, all files under the specified directory and subdirectories
+ * will be checked. If the last modification time of any of them is changed
+ * or if different number of files are contained in a directory, the dependency
+ * is reported as changed. By specifying {@link setRecursiveCheck RecursiveCheck}
+ * and {@link setRecursiveLevel RecursiveLevel}, one can limit the checking
+ * to a certain depth of the subdirectories.
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @version $Id$
+ * @package System.Caching
+ * @since 3.1.0
+ */
+class TDirectoryCacheDependency extends TCacheDependency
+{
+ private $_recursiveCheck=true;
+ private $_recursiveLevel=-1;
+ private $_timestamps;
+ private $_directory;
+
+ /**
+ * Constructor.
+ * @param string the directory to be checked
+ */
+ public function __construct($directory)
+ {
+ $this->setDirectory($directory);
+ }
+
+ /**
+ * @return string the directory to be checked
+ */
+ public function getDirectory()
+ {
+ return $this->_directory;
+ }
+
+ /**
+ * @param string the directory to be checked
+ * @throws TInvalidDataValueException if the directory does not exist
+ */
+ public function setDirectory($directory)
+ {
+ if(($path=realpath($directory))===false || !is_dir($path))
+ throw new TInvalidDataValueException('directorycachedependency_directory_invalid',$directory);
+ $this->_directory=$path;
+ $this->_timestamps=$this->generateTimestamps($path);
+ }
+
+ /**
+ * @return boolean whether the subdirectories of the directory will also be checked.
+ * It defaults to true.
+ */
+ public function getRecursiveCheck()
+ {
+ return $this->_recursiveCheck;
+ }
+
+ /**
+ * @param boolean whether the subdirectories of the directory will also be checked.
+ */
+ public function setRecursiveCheck($value)
+ {
+ $this->_recursiveCheck=TPropertyValue::ensureBoolean($value);
+ }
+
+ /**
+ * @return int the depth of the subdirectories to be checked.
+ * It defaults to -1, meaning unlimited depth.
+ */
+ public function getRecursiveLevel()
+ {
+ return $this->_recursiveLevel;
+ }
+
+ /**
+ * Sets a value indicating the depth of the subdirectories to be checked.
+ * This is meaningful only when {@link getRecursiveCheck RecursiveCheck}
+ * is true.
+ * @param int the depth of the subdirectories to be checked.
+ * If the value is less than 0, it means unlimited depth.
+ * If the value is 0, it means checking the files directly under the specified directory.
+ */
+ public function setRecursiveLevel($value)
+ {
+ $this->_recursiveLevel=TPropertyValue::ensureInteger($value);
+ }
+
+ /**
+ * Performs the actual dependency checking.
+ * This method returns true if the directory is changed.
+ * @return boolean whether the dependency is changed or not.
+ */
+ public function getHasChanged()
+ {
+ return $this->generateTimestamps($this->_directory)!=$this->_timestamps;
+ }
+
+ /**
+ * Checks to see if the file should be checked for dependency.
+ * This method is invoked when dependency of the whole directory is being checked.
+ * By default, it always returns true, meaning the file should be checked.
+ * You may override this method to check only certain files.
+ * @param string the name of the file that may be checked for dependency.
+ * @return boolean whether this file should be checked.
+ */
+ protected function validateFile($fileName)
+ {
+ return true;
+ }
+
+ /**
+ * Checks to see if the specified subdirectory should be checked for dependency.
+ * This method is invoked when dependency of the whole directory is being checked.
+ * By default, it always returns true, meaning the subdirectory should be checked.
+ * You may override this method to check only certain subdirectories.
+ * @param string the name of the subdirectory that may be checked for dependency.
+ * @return boolean whether this subdirectory should be checked.
+ */
+ protected function validateDirectory($directory)
+ {
+ return true;
+ }
+
+ /**
+ * Determines the last modification time for files under the directory.
+ * This method may go recursively into subdirectories if
+ * {@link setRecursiveCheck RecursiveCheck} is set true.
+ * @param string the directory name
+ * @param int level of the recursion
+ * @return array list of file modification time indexed by the file path
+ */
+ protected function generateTimestamps($directory,$level=0)
+ {
+ if(($dir=opendir($directory))===false)
+ throw new TIOException('directorycachedependency_directory_invalid',$directory);
+ $timestamps=array();
+ while(($file=readdir($dir))!==false)
+ {
+ $path=$directory.DIRECTORY_SEPARATOR.$file;
+ if($file==='.' || $file==='..')
+ continue;
+ else if(is_dir($path))
+ {
+ if(($this->_recursiveLevel<0 || $level<$this->_recursiveLevel) && $this->validateDirectory($path))
+ $timestamps=array_merge($this->generateTimestamps($path,$level+1));
+ }
+ else if($this->validateFile($path))
+ $timestamps[$path]=filemtime($path);
+ }
+ closedir($dir);
+ return $timestamps;
+ }
+}
+
+
+/**
+ * TGlobalStateCacheDependency class.
+ *
+ * TGlobalStateCacheDependency checks if a global state is changed or not.
+ * If the global state is changed, the dependency is reported as changed.
+ * To specify which global state this dependency should check with,
+ * set {@link setStateName StateName} to the name of the global state.
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @version $Id$
+ * @package System.Caching
+ * @since 3.1.0
+ */
+class TGlobalStateCacheDependency extends TCacheDependency
+{
+ private $_stateName;
+ private $_stateValue;
+
+ /**
+ * Constructor.
+ * @param string the name of the global state
+ */
+ public function __construct($name)
+ {
+ $this->setStateName($name);
+ }
+
+ /**
+ * @return string the name of the global state
+ */
+ public function getStateName()
+ {
+ return $this->_stateName;
+ }
+
+ /**
+ * @param string the name of the global state
+ * @see TApplication::setGlobalState
+ */
+ public function setStateName($value)
+ {
+ $this->_stateName=$value;
+ $this->_stateValue=Prado::getApplication()->getGlobalState($value);
+ }
+
+ /**
+ * Performs the actual dependency checking.
+ * This method returns true if the specified global state is changed.
+ * @return boolean whether the dependency is changed or not.
+ */
+ public function getHasChanged()
+ {
+ return $this->_stateValue!==Prado::getApplication()->getGlobalState($this->_stateName);
+ }
+}
+
+
+/**
+ * TChainedCacheDependency class.
+ *
+ * TChainedCacheDependency represents a list of cache dependency objects
+ * and performs the dependency checking based on the checking results of
+ * these objects. If any of them reports a dependency change, TChainedCacheDependency
+ * will return true for the checking.
+ *
+ * To add dependencies to TChainedCacheDependency, use {@link getDependencies Dependencies}
+ * which gives a {@link TCacheDependencyList} instance and can be used like an array
+ * (see {@link TList} for more details}).
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @version $Id$
+ * @package System.Caching
+ * @since 3.1.0
+ */
+class TChainedCacheDependency extends TCacheDependency
+{
+ private $_dependencies=null;
+
+ /**
+ * @return TCacheDependencyList list of dependency objects
+ */
+ public function getDependencies()
+ {
+ if($this->_dependencies===null)
+ $this->_dependencies=new TCacheDependencyList;
+ return $this->_dependencies;
+ }
+
+ /**
+ * Performs the actual dependency checking.
+ * This method returns true if any of the dependency objects
+ * reports a dependency change.
+ * @return boolean whether the dependency is changed or not.
+ */
+ public function getHasChanged()
+ {
+ if($this->_dependencies!==null)
+ {
+ foreach($this->_dependencies as $dependency)
+ if($dependency->getHasChanged())
+ return true;
+ }
+ return false;
+ }
+}
+
+
+/**
+ * TApplicationStateCacheDependency class.
+ *
+ * TApplicationStateCacheDependency performs dependency checking based on
+ * the mode of the currently running PRADO application.
+ * The dependency is reportedly as unchanged if and only if the application
+ * is running in performance mode.
+ *
+ * You may chain this dependency together with other dependencies
+ * so that only when the application is not in performance mode the other dependencies
+ * will be checked.
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @version $Id$
+ * @package System.Caching
+ * @since 3.1.0
+ */
+class TApplicationStateCacheDependency extends TCacheDependency
+{
+ /**
+ * Performs the actual dependency checking.
+ * This method returns true if the currently running application is not in performance mode.
+ * @return boolean whether the dependency is changed or not.
+ */
+ public function getHasChanged()
+ {
+ return Prado::getApplication()->getMode()!==TApplicationMode::Performance;
+ }
+}
+
+/**
+ * TCacheDependencyList class.
+ *
+ * TCacheDependencyList represents a list of cache dependency objects.
+ * Only objects implementing {@link ICacheDependency} can be added into this list.
+ *
+ * TCacheDependencyList can be used like an array. See {@link TList}
+ * for more details.
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @version $Id$
+ * @package System.Caching
+ * @since 3.1.0
+ */
+class TCacheDependencyList extends TList
+{
+ /**
+ * Inserts an item at the specified position.
+ * This overrides the parent implementation by performing additional type checking
+ * for each newly added item.
+ * @param integer the specified position.
+ * @param mixed new item
+ * @throws TInvalidDataTypeException if the item to be inserted is not a dependency instance
+ */
+ public function insertAt($index,$item)
+ {
+ if($item instanceof ICacheDependency)
+ parent::insertAt($index,$item);
+ else
+ throw new TInvalidDataTypeException('cachedependencylist_cachedependency_required');
+ }
+}
+
+?>
diff --git a/framework/Caching/TDbCache.php b/framework/Caching/TDbCache.php
index 7a149346..b4ddd086 100644
--- a/framework/Caching/TDbCache.php
+++ b/framework/Caching/TDbCache.php
@@ -1,578 +1,578 @@
-<?php
-/**
- * TDbCache class file
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @link http://www.pradosoft.com/
- * @copyright Copyright &copy; 2005-2012 PradoSoft
- * @license http://www.pradosoft.com/license/
- * @version $Id$
- * @package System.Caching
- */
-
-Prado::using('System.Data.TDbConnection');
-
-/**
- * TDbCache class
- *
- * TDbCache implements a cache application module by storing cached data in a database.
- *
- * TDbCache relies on {@link http://www.php.net/manual/en/ref.pdo.php PDO} to retrieve
- * data from databases. In order to use TDbCache, you need to enable the PDO extension
- * as well as the corresponding PDO DB driver. For example, to use SQLite database
- * to store cached data, you need both php_pdo and php_pdo_sqlite extensions.
- *
- * By default, TDbCache creates and uses an SQLite database under the application
- * runtime directory. You may change this default setting by specifying the following
- * properties:
- * - {@link setConnectionID ConnectionID} or
- * - {@link setConnectionString ConnectionString}, {@link setUsername Username} and {@link setPassword Pasword}.
- *
- * The cached data is stored in a table in the specified database.
- * By default, the name of the table is called 'pradocache'. If the table does not
- * exist in the database, it will be automatically created with the following structure:
- * <code>
- * CREATE TABLE pradocache (itemkey CHAR(128), value BLOB, expire INT)
- * CREATE INDEX IX_itemkey ON pradocache (itemkey)
- * CREATE INDEX IX_expire ON pradocache (expire)
- * </code>
- *
- * Note, some DBMS might not support BLOB type. In this case, replace 'BLOB' with a suitable
- * binary data type (e.g. LONGBLOB in MySQL, BYTEA in PostgreSQL.)
- *
- * Important: Make sure that the indices are non-unique!
- *
- * If you want to change the cache table name, or if you want to create the table by yourself,
- * you may set {@link setCacheTableName CacheTableName} and {@link setAutoCreateCacheTable AutoCreateCacheTableName} properties.
- *
- * {@link setFlushInterval FlushInterval} control how often expired items will be removed from cache.
- * If you prefer to remove expired items manualy e.g. via cronjob you can disable automatic deletion by setting FlushInterval to '0'.
- *
- * The following basic cache operations are implemented:
- * - {@link get} : retrieve the value with a key (if any) from cache
- * - {@link set} : store the value with a key into cache
- * - {@link add} : store the value only if cache does not have this key
- * - {@link delete} : delete the value with the specified key from cache
- * - {@link flush} : delete all values from cache
- *
- * Each value is associated with an expiration time. The {@link get} operation
- * ensures that any expired value will not be returned. The expiration time by
- * the number of seconds. A expiration time 0 represents never expire.
- *
- * By definition, cache does not ensure the existence of a value
- * even if it never expires. Cache is not meant to be an persistent storage.
- *
- * Do not use the same database file for multiple applications using TDbCache.
- * Also note, cache is shared by all user sessions of an application.
- *
- * Some usage examples of TDbCache are as follows,
- * <code>
- * $cache=new TDbCache; // TDbCache may also be loaded as a Prado application module
- * $cache->init(null);
- * $cache->add('object',$object);
- * $object2=$cache->get('object');
- * </code>
- *
- * If loaded, TDbCache will register itself with {@link TApplication} as the
- * cache module. It can be accessed via {@link TApplication::getCache()}.
- *
- * TDbCache may be configured in application configuration file as follows
- * <code>
- * <module id="cache" class="System.Caching.TDbCache" />
- * </code>
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @version $Id$
- * @package System.Caching
- * @since 3.1.0
- */
-class TDbCache extends TCache
-{
- /**
- * @var string the ID of TDataSourceConfig module
- */
- private $_connID='';
- /**
- * @var TDbConnection the DB connection instance
- */
- private $_db;
- /**
- * @var string name of the DB cache table
- */
- private $_cacheTable='pradocache';
- /**
- * @var integer Interval expired items will be removed from cache
- */
- private $_flushInterval=60;
- /**
- * @var boolean
- */
- private $_cacheInitialized = false;
- /**
- * @var boolean
- */
- private $_createCheck= false;
- /**
- * @var boolean whether the cache DB table should be created automatically
- */
- private $_autoCreate=true;
- private $_username='';
- private $_password='';
- private $_connectionString='';
-
- /**
- * Destructor.
- * Disconnect the db connection.
- */
- public function __destruct()
- {
- if($this->_db!==null)
- $this->_db->setActive(false);
- }
-
- /**
- * Initializes this module.
- * This method is required by the IModule interface.
- * attach {@link doInitializeCache} to TApplication.OnLoadStateComplete event
- * attach {@link doFlushCacheExpired} to TApplication.OnSaveState event
- *
- * @param TXmlElement configuration for this module, can be null
- */
- public function init($config)
- {
- $this -> getApplication() -> attachEventHandler('OnLoadStateComplete', array($this, 'doInitializeCache'));
- $this -> getApplication() -> attachEventHandler('OnSaveState', array($this, 'doFlushCacheExpired'));
- parent::init($config);
- }
-
- /**
- * Event listener for TApplication.OnSaveState
- * @return void
- * @since 3.1.5
- * @see flushCacheExpired
- */
- public function doFlushCacheExpired()
- {
- $this->flushCacheExpired(false);
- }
-
- /**
- * Event listener for TApplication.OnLoadStateComplete
- *
- * @return void
- * @since 3.1.5
- * @see initializeCache
- */
- public function doInitializeCache()
- {
- $this->initializeCache();
- }
-
- /**
- * Initialize TDbCache
- *
- * If {@link setAutoCreateCacheTable AutoCreateCacheTableName} is 'true' check existence of cache table
- * and create table if does not exist.
- *
- * @param boolean Force override global state check
- * @return void
- * @throws TConfigurationException if any error happens during creating database or cache table.
- * @since 3.1.5
- */
- protected function initializeCache($force=false)
- {
- if($this->_cacheInitialized && !$force) return;
- $db=$this->getDbConnection();
- try
- {
- $key = 'TDbCache:' . $this->_cacheTable . ':created';
- if($force)
- $this -> _createCheck = false;
- else
- $this -> _createCheck = $this -> getApplication() -> getGlobalState($key, 0);
-
- if($this->_autoCreate && !$this -> _createCheck) {
-
- Prado::trace(($force ? 'Force initializing: ' : 'Initializing: ') . $this -> id . ', ' . $this->_cacheTable, 'System.Caching.TDbCache');
-
- $sql='SELECT 1 FROM '.$this->_cacheTable.' WHERE 0=1';
- $db->createCommand($sql)->queryScalar();
-
- $this -> _createCheck = true;
- $this -> getApplication() -> setGlobalState($key, time());
- }
- }
- catch(Exception $e)
- {
- // DB table not exists
- if($this->_autoCreate)
- {
- Prado::trace('Autocreate: ' . $this->_cacheTable, 'System.Caching.TDbCache');
-
- $driver=$db->getDriverName();
- if($driver==='mysql')
- $blob='LONGBLOB';
- else if($driver==='pgsql')
- $blob='BYTEA';
- else
- $blob='BLOB';
-
- $sql='CREATE TABLE '.$this->_cacheTable." (itemkey CHAR(128) PRIMARY KEY, value $blob, expire INTEGER)";
- $db->createCommand($sql)->execute();
-
- $sql='CREATE INDEX IX_expire ON ' . $this->_cacheTable . ' (expire)';
- $db->createCommand($sql)->execute();
-
- $this -> _createCheck = true;
- $this -> getApplication() -> setGlobalState($key, time());
- }
- else
- throw new TConfigurationException('db_cachetable_inexistent',$this->_cacheTable);
- }
- $this->_cacheInitialized = true;
- }
-
- /**
- * Flush expired values from cache depending on {@link setFlushInterval FlushInterval}
- * @param boolean override {@link setFlushInterval FlushInterval} and force deletion of expired items
- * @return void
- * @since 3.1.5
- */
- public function flushCacheExpired($force=false)
- {
- $interval = $this -> getFlushInterval();
- if(!$force && $interval === 0) return;
-
- $key = 'TDbCache:' . $this->_cacheTable . ':flushed';
- $now = time();
- $next = $interval + (integer)$this -> getApplication() -> getGlobalState($key, 0);
-
- if($force || $next <= $now)
- {
- if(!$this->_cacheInitialized) $this->initializeCache();
- Prado::trace(($force ? 'Force flush of expired items: ' : 'Flush expired items: ') . $this -> id . ', ' . $this->_cacheTable, 'System.Caching.TDbCache');
- $sql='DELETE FROM '.$this->_cacheTable.' WHERE expire<>0 AND expire<'.$now;
- $this->getDbConnection()->createCommand($sql)->execute();
- $this -> getApplication() -> setGlobalState($key, $now);
- }
- }
-
- /**
- * @return integer Interval in sec expired items will be removed from cache. Default to 60
- * @since 3.1.5
- */
- public function getFlushInterval()
- {
- return $this->_flushInterval;
- }
-
- /**
- * Sets interval expired items will be removed from cache
- *
- * To disable automatic deletion of expired items,
- * e.g. for external flushing via cron you can set value to '0'
- *
- * @param integer Interval in sec
- * @since 3.1.5
- */
- public function setFlushInterval($value)
- {
- $this->_flushInterval = (integer) $value;
- }
-
- /**
- * Creates the DB connection.
- * @param string the module ID for TDataSourceConfig
- * @return TDbConnection the created DB connection
- * @throws TConfigurationException if module ID is invalid or empty
- */
- protected function createDbConnection()
- {
- if($this->_connID!=='')
- {
- $config=$this->getApplication()->getModule($this->_connID);
- if($config instanceof TDataSourceConfig)
- return $config->getDbConnection();
- else
- throw new TConfigurationException('dbcache_connectionid_invalid',$this->_connID);
- }
- else
- {
- $db=new TDbConnection;
- if($this->_connectionString!=='')
- {
- $db->setConnectionString($this->_connectionString);
- if($this->_username!=='')
- $db->setUsername($this->_username);
- if($this->_password!=='')
- $db->setPassword($this->_password);
- }
- else
- {
- // default to SQLite3 database
- $dbFile=$this->getApplication()->getRuntimePath().'/sqlite3.cache';
- $db->setConnectionString('sqlite:'.$dbFile);
- }
- return $db;
- }
- }
-
- /**
- * @return TDbConnection the DB connection instance
- */
- public function getDbConnection()
- {
- if($this->_db===null)
- $this->_db=$this->createDbConnection();
-
- $this->_db->setActive(true);
- return $this->_db;
- }
-
- /**
- * @return string the ID of a {@link TDataSourceConfig} module. Defaults to empty string, meaning not set.
- * @since 3.1.1
- */
- public function getConnectionID()
- {
- return $this->_connID;
- }
-
- /**
- * Sets the ID of a TDataSourceConfig module.
- * The datasource module will be used to establish the DB connection for this cache module.
- * The database connection can also be specified via {@link setConnectionString ConnectionString}.
- * When both ConnectionID and ConnectionString are specified, the former takes precedence.
- * @param string ID of the {@link TDataSourceConfig} module
- * @since 3.1.1
- */
- public function setConnectionID($value)
- {
- $this->_connID=$value;
- }
-
- /**
- * @return string The Data Source Name, or DSN, contains the information required to connect to the database.
- */
- public function getConnectionString()
- {
- return $this->_connectionString;
- }
-
- /**
- * @param string The Data Source Name, or DSN, contains the information required to connect to the database.
- * @see http://www.php.net/manual/en/function.pdo-construct.php
- */
- public function setConnectionString($value)
- {
- $this->_connectionString=$value;
- }
-
- /**
- * @return string the username for establishing DB connection. Defaults to empty string.
- */
- public function getUsername()
- {
- return $this->_username;
- }
-
- /**
- * @param string the username for establishing DB connection
- */
- public function setUsername($value)
- {
- $this->_username=$value;
- }
-
- /**
- * @return string the password for establishing DB connection. Defaults to empty string.
- */
- public function getPassword()
- {
- return $this->_password;
- }
-
- /**
- * @param string the password for establishing DB connection
- */
- public function setPassword($value)
- {
- $this->_password=$value;
- }
-
- /**
- * @return string the name of the DB table to store cache content. Defaults to 'pradocache'.
- * @see setAutoCreateCacheTable
- */
- public function getCacheTableName()
- {
- return $this->_cacheTable;
- }
-
- /**
- * Sets the name of the DB table to store cache content.
- * Note, if {@link setAutoCreateCacheTable AutoCreateCacheTable} is false
- * and you want to create the DB table manually by yourself,
- * you need to make sure the DB table is of the following structure:
- * <code>
- * CREATE TABLE pradocache (itemkey CHAR(128), value BLOB, expire INT)
- * CREATE INDEX IX_itemkey ON pradocache (itemkey)
- * CREATE INDEX IX_expire ON pradocache (expire)
- * </code>
- *
- * Note, some DBMS might not support BLOB type. In this case, replace 'BLOB' with a suitable
- * binary data type (e.g. LONGBLOB in MySQL, BYTEA in PostgreSQL.)
- *
- * Important: Make sure that the indices are non-unique!
- *
- * @param string the name of the DB table to store cache content
- * @see setAutoCreateCacheTable
- */
- public function setCacheTableName($value)
- {
- $this->_cacheTable=$value;
- }
-
- /**
- * @return boolean whether the cache DB table should be automatically created if not exists. Defaults to true.
- * @see setAutoCreateCacheTable
- */
- public function getAutoCreateCacheTable()
- {
- return $this->_autoCreate;
- }
-
- /**
- * @param boolean whether the cache DB table should be automatically created if not exists.
- * @see setCacheTableName
- */
- public function setAutoCreateCacheTable($value)
- {
- $this->_autoCreate=TPropertyValue::ensureBoolean($value);
- }
-
- /**
- * Retrieves a value from cache with a specified key.
- * This is the implementation of the method declared in the parent class.
- * @param string a unique key identifying the cached value
- * @return string the value stored in cache, false if the value is not in the cache or expired.
- */
- protected function getValue($key)
- {
- if(!$this->_cacheInitialized) $this->initializeCache();
- try {
- $sql='SELECT value FROM '.$this->_cacheTable.' WHERE itemkey=\''.$key.'\' AND (expire=0 OR expire>'.time().') ORDER BY expire DESC';
- $command=$this->getDbConnection()->createCommand($sql);
- return Prado::unserialize($command->queryScalar());
- }
- catch(Exception $e)
- {
- $this->initializeCache(true);
- return Prado::unserialize($command->queryScalar());
- }
- }
-
- /**
- * Stores a value identified by a key in cache.
- * This is the implementation of the method declared in the parent class.
- *
- * @param string the key identifying the value to be cached
- * @param string the value to be cached
- * @param integer the number of seconds in which the cached value will expire. 0 means never expire.
- * @return boolean true if the value is successfully stored into cache, false otherwise
- */
- protected function setValue($key,$value,$expire)
- {
- $this->deleteValue($key);
- return $this->addValue($key,$value,$expire);
- }
-
- /**
- * Stores a value identified by a key into cache if the cache does not contain this key.
- * This is the implementation of the method declared in the parent class.
- *
- * @param string the key identifying the value to be cached
- * @param string the value to be cached
- * @param integer the number of seconds in which the cached value will expire. 0 means never expire.
- * @return boolean true if the value is successfully stored into cache, false otherwise
- */
- protected function addValue($key,$value,$expire)
- {
- if(!$this->_cacheInitialized) $this->initializeCache();
- $expire=($expire<=0)?0:time()+$expire;
- $sql="INSERT INTO {$this->_cacheTable} (itemkey,value,expire) VALUES(:key,:value,$expire)";
- try
- {
- $command=$this->getDbConnection()->createCommand($sql);
- $command->bindValue(':key',$key,PDO::PARAM_STR);
- $command->bindValue(':value',Prado::serialize($value),PDO::PARAM_LOB);
- $command->execute();
- return true;
- }
- catch(Exception $e)
- {
- try
- {
- $this->initializeCache(true);
- $command->execute();
- return true;
- }
- catch(Exception $e)
- {
- return false;
- }
- }
- }
-
- /**
- * Deletes a value with the specified key from cache
- * This is the implementation of the method declared in the parent class.
- * @param string the key of the value to be deleted
- * @return boolean if no error happens during deletion
- */
- protected function deleteValue($key)
- {
- if(!$this->_cacheInitialized) $this->initializeCache();
- try
- {
- $command=$this->getDbConnection()->createCommand("DELETE FROM {$this->_cacheTable} WHERE itemkey=:key");
- $command->bindValue(':key',$key,PDO::PARAM_STR);
- $command->execute();
- return true;
- }
- catch(Exception $e)
- {
- $this->initializeCache(true);
- $command->execute();
- return true;
- }
- }
-
- /**
- * Deletes all values from cache.
- * Be careful of performing this operation if the cache is shared by multiple applications.
- */
- public function flush()
- {
- if(!$this->_cacheInitialized) $this->initializeCache();
- try
- {
- $command = $this->getDbConnection()->createCommand("DELETE FROM {$this->_cacheTable}");
- $command->execute();
- }
- catch(Exception $e)
- {
- try
- {
- $this->initializeCache(true);
- $command->execute();
- return true;
- }
- catch(Exception $e)
- {
- return false;
- }
- }
- return true;
- }
-}
+<?php
+/**
+ * TDbCache class file
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @link http://www.pradosoft.com/
+ * @copyright Copyright &copy; 2005-2012 PradoSoft
+ * @license http://www.pradosoft.com/license/
+ * @version $Id$
+ * @package System.Caching
+ */
+
+Prado::using('System.Data.TDbConnection');
+
+/**
+ * TDbCache class
+ *
+ * TDbCache implements a cache application module by storing cached data in a database.
+ *
+ * TDbCache relies on {@link http://www.php.net/manual/en/ref.pdo.php PDO} to retrieve
+ * data from databases. In order to use TDbCache, you need to enable the PDO extension
+ * as well as the corresponding PDO DB driver. For example, to use SQLite database
+ * to store cached data, you need both php_pdo and php_pdo_sqlite extensions.
+ *
+ * By default, TDbCache creates and uses an SQLite database under the application
+ * runtime directory. You may change this default setting by specifying the following
+ * properties:
+ * - {@link setConnectionID ConnectionID} or
+ * - {@link setConnectionString ConnectionString}, {@link setUsername Username} and {@link setPassword Pasword}.
+ *
+ * The cached data is stored in a table in the specified database.
+ * By default, the name of the table is called 'pradocache'. If the table does not
+ * exist in the database, it will be automatically created with the following structure:
+ * <code>
+ * CREATE TABLE pradocache (itemkey CHAR(128), value BLOB, expire INT)
+ * CREATE INDEX IX_itemkey ON pradocache (itemkey)
+ * CREATE INDEX IX_expire ON pradocache (expire)
+ * </code>
+ *
+ * Note, some DBMS might not support BLOB type. In this case, replace 'BLOB' with a suitable
+ * binary data type (e.g. LONGBLOB in MySQL, BYTEA in PostgreSQL.)
+ *
+ * Important: Make sure that the indices are non-unique!
+ *
+ * If you want to change the cache table name, or if you want to create the table by yourself,
+ * you may set {@link setCacheTableName CacheTableName} and {@link setAutoCreateCacheTable AutoCreateCacheTableName} properties.
+ *
+ * {@link setFlushInterval FlushInterval} control how often expired items will be removed from cache.
+ * If you prefer to remove expired items manualy e.g. via cronjob you can disable automatic deletion by setting FlushInterval to '0'.
+ *
+ * The following basic cache operations are implemented:
+ * - {@link get} : retrieve the value with a key (if any) from cache
+ * - {@link set} : store the value with a key into cache
+ * - {@link add} : store the value only if cache does not have this key
+ * - {@link delete} : delete the value with the specified key from cache
+ * - {@link flush} : delete all values from cache
+ *
+ * Each value is associated with an expiration time. The {@link get} operation
+ * ensures that any expired value will not be returned. The expiration time by
+ * the number of seconds. A expiration time 0 represents never expire.
+ *
+ * By definition, cache does not ensure the existence of a value
+ * even if it never expires. Cache is not meant to be an persistent storage.
+ *
+ * Do not use the same database file for multiple applications using TDbCache.
+ * Also note, cache is shared by all user sessions of an application.
+ *
+ * Some usage examples of TDbCache are as follows,
+ * <code>
+ * $cache=new TDbCache; // TDbCache may also be loaded as a Prado application module
+ * $cache->init(null);
+ * $cache->add('object',$object);
+ * $object2=$cache->get('object');
+ * </code>
+ *
+ * If loaded, TDbCache will register itself with {@link TApplication} as the
+ * cache module. It can be accessed via {@link TApplication::getCache()}.
+ *
+ * TDbCache may be configured in application configuration file as follows
+ * <code>
+ * <module id="cache" class="System.Caching.TDbCache" />
+ * </code>
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @version $Id$
+ * @package System.Caching
+ * @since 3.1.0
+ */
+class TDbCache extends TCache
+{
+ /**
+ * @var string the ID of TDataSourceConfig module
+ */
+ private $_connID='';
+ /**
+ * @var TDbConnection the DB connection instance
+ */
+ private $_db;
+ /**
+ * @var string name of the DB cache table
+ */
+ private $_cacheTable='pradocache';
+ /**
+ * @var integer Interval expired items will be removed from cache
+ */
+ private $_flushInterval=60;
+ /**
+ * @var boolean
+ */
+ private $_cacheInitialized = false;
+ /**
+ * @var boolean
+ */
+ private $_createCheck= false;
+ /**
+ * @var boolean whether the cache DB table should be created automatically
+ */
+ private $_autoCreate=true;
+ private $_username='';
+ private $_password='';
+ private $_connectionString='';
+
+ /**
+ * Destructor.
+ * Disconnect the db connection.
+ */
+ public function __destruct()
+ {
+ if($this->_db!==null)
+ $this->_db->setActive(false);
+ }
+
+ /**
+ * Initializes this module.
+ * This method is required by the IModule interface.
+ * attach {@link doInitializeCache} to TApplication.OnLoadStateComplete event
+ * attach {@link doFlushCacheExpired} to TApplication.OnSaveState event
+ *
+ * @param TXmlElement configuration for this module, can be null
+ */
+ public function init($config)
+ {
+ $this -> getApplication() -> attachEventHandler('OnLoadStateComplete', array($this, 'doInitializeCache'));
+ $this -> getApplication() -> attachEventHandler('OnSaveState', array($this, 'doFlushCacheExpired'));
+ parent::init($config);
+ }
+
+ /**
+ * Event listener for TApplication.OnSaveState
+ * @return void
+ * @since 3.1.5
+ * @see flushCacheExpired
+ */
+ public function doFlushCacheExpired()
+ {
+ $this->flushCacheExpired(false);
+ }
+
+ /**
+ * Event listener for TApplication.OnLoadStateComplete
+ *
+ * @return void
+ * @since 3.1.5
+ * @see initializeCache
+ */
+ public function doInitializeCache()
+ {
+ $this->initializeCache();
+ }
+
+ /**
+ * Initialize TDbCache
+ *
+ * If {@link setAutoCreateCacheTable AutoCreateCacheTableName} is 'true' check existence of cache table
+ * and create table if does not exist.
+ *
+ * @param boolean Force override global state check
+ * @return void
+ * @throws TConfigurationException if any error happens during creating database or cache table.
+ * @since 3.1.5
+ */
+ protected function initializeCache($force=false)
+ {
+ if($this->_cacheInitialized && !$force) return;
+ $db=$this->getDbConnection();
+ try
+ {
+ $key = 'TDbCache:' . $this->_cacheTable . ':created';
+ if($force)
+ $this -> _createCheck = false;
+ else
+ $this -> _createCheck = $this -> getApplication() -> getGlobalState($key, 0);
+
+ if($this->_autoCreate && !$this -> _createCheck) {
+
+ Prado::trace(($force ? 'Force initializing: ' : 'Initializing: ') . $this -> id . ', ' . $this->_cacheTable, 'System.Caching.TDbCache');
+
+ $sql='SELECT 1 FROM '.$this->_cacheTable.' WHERE 0=1';
+ $db->createCommand($sql)->queryScalar();
+
+ $this -> _createCheck = true;
+ $this -> getApplication() -> setGlobalState($key, time());
+ }
+ }
+ catch(Exception $e)
+ {
+ // DB table not exists
+ if($this->_autoCreate)
+ {
+ Prado::trace('Autocreate: ' . $this->_cacheTable, 'System.Caching.TDbCache');
+
+ $driver=$db->getDriverName();
+ if($driver==='mysql')
+ $blob='LONGBLOB';
+ else if($driver==='pgsql')
+ $blob='BYTEA';
+ else
+ $blob='BLOB';
+
+ $sql='CREATE TABLE '.$this->_cacheTable." (itemkey CHAR(128) PRIMARY KEY, value $blob, expire INTEGER)";
+ $db->createCommand($sql)->execute();
+
+ $sql='CREATE INDEX IX_expire ON ' . $this->_cacheTable . ' (expire)';
+ $db->createCommand($sql)->execute();
+
+ $this -> _createCheck = true;
+ $this -> getApplication() -> setGlobalState($key, time());
+ }
+ else
+ throw new TConfigurationException('db_cachetable_inexistent',$this->_cacheTable);
+ }
+ $this->_cacheInitialized = true;
+ }
+
+ /**
+ * Flush expired values from cache depending on {@link setFlushInterval FlushInterval}
+ * @param boolean override {@link setFlushInterval FlushInterval} and force deletion of expired items
+ * @return void
+ * @since 3.1.5
+ */
+ public function flushCacheExpired($force=false)
+ {
+ $interval = $this -> getFlushInterval();
+ if(!$force && $interval === 0) return;
+
+ $key = 'TDbCache:' . $this->_cacheTable . ':flushed';
+ $now = time();
+ $next = $interval + (integer)$this -> getApplication() -> getGlobalState($key, 0);
+
+ if($force || $next <= $now)
+ {
+ if(!$this->_cacheInitialized) $this->initializeCache();
+ Prado::trace(($force ? 'Force flush of expired items: ' : 'Flush expired items: ') . $this -> id . ', ' . $this->_cacheTable, 'System.Caching.TDbCache');
+ $sql='DELETE FROM '.$this->_cacheTable.' WHERE expire<>0 AND expire<'.$now;
+ $this->getDbConnection()->createCommand($sql)->execute();
+ $this -> getApplication() -> setGlobalState($key, $now);
+ }
+ }
+
+ /**
+ * @return integer Interval in sec expired items will be removed from cache. Default to 60
+ * @since 3.1.5
+ */
+ public function getFlushInterval()
+ {
+ return $this->_flushInterval;
+ }
+
+ /**
+ * Sets interval expired items will be removed from cache
+ *
+ * To disable automatic deletion of expired items,
+ * e.g. for external flushing via cron you can set value to '0'
+ *
+ * @param integer Interval in sec
+ * @since 3.1.5
+ */
+ public function setFlushInterval($value)
+ {
+ $this->_flushInterval = (integer) $value;
+ }
+
+ /**
+ * Creates the DB connection.
+ * @param string the module ID for TDataSourceConfig
+ * @return TDbConnection the created DB connection
+ * @throws TConfigurationException if module ID is invalid or empty
+ */
+ protected function createDbConnection()
+ {
+ if($this->_connID!=='')
+ {
+ $config=$this->getApplication()->getModule($this->_connID);
+ if($config instanceof TDataSourceConfig)
+ return $config->getDbConnection();
+ else
+ throw new TConfigurationException('dbcache_connectionid_invalid',$this->_connID);
+ }
+ else
+ {
+ $db=new TDbConnection;
+ if($this->_connectionString!=='')
+ {
+ $db->setConnectionString($this->_connectionString);
+ if($this->_username!=='')
+ $db->setUsername($this->_username);
+ if($this->_password!=='')
+ $db->setPassword($this->_password);
+ }
+ else
+ {
+ // default to SQLite3 database
+ $dbFile=$this->getApplication()->getRuntimePath().'/sqlite3.cache';
+ $db->setConnectionString('sqlite:'.$dbFile);
+ }
+ return $db;
+ }
+ }
+
+ /**
+ * @return TDbConnection the DB connection instance
+ */
+ public function getDbConnection()
+ {
+ if($this->_db===null)
+ $this->_db=$this->createDbConnection();
+
+ $this->_db->setActive(true);
+ return $this->_db;
+ }
+
+ /**
+ * @return string the ID of a {@link TDataSourceConfig} module. Defaults to empty string, meaning not set.
+ * @since 3.1.1
+ */
+ public function getConnectionID()
+ {
+ return $this->_connID;
+ }
+
+ /**
+ * Sets the ID of a TDataSourceConfig module.
+ * The datasource module will be used to establish the DB connection for this cache module.
+ * The database connection can also be specified via {@link setConnectionString ConnectionString}.
+ * When both ConnectionID and ConnectionString are specified, the former takes precedence.
+ * @param string ID of the {@link TDataSourceConfig} module
+ * @since 3.1.1
+ */
+ public function setConnectionID($value)
+ {
+ $this->_connID=$value;
+ }
+
+ /**
+ * @return string The Data Source Name, or DSN, contains the information required to connect to the database.
+ */
+ public function getConnectionString()
+ {
+ return $this->_connectionString;
+ }
+
+ /**
+ * @param string The Data Source Name, or DSN, contains the information required to connect to the database.
+ * @see http://www.php.net/manual/en/function.pdo-construct.php
+ */
+ public function setConnectionString($value)
+ {
+ $this->_connectionString=$value;
+ }
+
+ /**
+ * @return string the username for establishing DB connection. Defaults to empty string.
+ */
+ public function getUsername()
+ {
+ return $this->_username;
+ }
+
+ /**
+ * @param string the username for establishing DB connection
+ */
+ public function setUsername($value)
+ {
+ $this->_username=$value;
+ }
+
+ /**
+ * @return string the password for establishing DB connection. Defaults to empty string.
+ */
+ public function getPassword()
+ {
+ return $this->_password;
+ }
+
+ /**
+ * @param string the password for establishing DB connection
+ */
+ public function setPassword($value)
+ {
+ $this->_password=$value;
+ }
+
+ /**
+ * @return string the name of the DB table to store cache content. Defaults to 'pradocache'.
+ * @see setAutoCreateCacheTable
+ */
+ public function getCacheTableName()
+ {
+ return $this->_cacheTable;
+ }
+
+ /**
+ * Sets the name of the DB table to store cache content.
+ * Note, if {@link setAutoCreateCacheTable AutoCreateCacheTable} is false
+ * and you want to create the DB table manually by yourself,
+ * you need to make sure the DB table is of the following structure:
+ * <code>
+ * CREATE TABLE pradocache (itemkey CHAR(128), value BLOB, expire INT)
+ * CREATE INDEX IX_itemkey ON pradocache (itemkey)
+ * CREATE INDEX IX_expire ON pradocache (expire)
+ * </code>
+ *
+ * Note, some DBMS might not support BLOB type. In this case, replace 'BLOB' with a suitable
+ * binary data type (e.g. LONGBLOB in MySQL, BYTEA in PostgreSQL.)
+ *
+ * Important: Make sure that the indices are non-unique!
+ *
+ * @param string the name of the DB table to store cache content
+ * @see setAutoCreateCacheTable
+ */
+ public function setCacheTableName($value)
+ {
+ $this->_cacheTable=$value;
+ }
+
+ /**
+ * @return boolean whether the cache DB table should be automatically created if not exists. Defaults to true.
+ * @see setAutoCreateCacheTable
+ */
+ public function getAutoCreateCacheTable()
+ {
+ return $this->_autoCreate;
+ }
+
+ /**
+ * @param boolean whether the cache DB table should be automatically created if not exists.
+ * @see setCacheTableName
+ */
+ public function setAutoCreateCacheTable($value)
+ {
+ $this->_autoCreate=TPropertyValue::ensureBoolean($value);
+ }
+
+ /**
+ * Retrieves a value from cache with a specified key.
+ * This is the implementation of the method declared in the parent class.
+ * @param string a unique key identifying the cached value
+ * @return string the value stored in cache, false if the value is not in the cache or expired.
+ */
+ protected function getValue($key)
+ {
+ if(!$this->_cacheInitialized) $this->initializeCache();
+ try {
+ $sql='SELECT value FROM '.$this->_cacheTable.' WHERE itemkey=\''.$key.'\' AND (expire=0 OR expire>'.time().') ORDER BY expire DESC';
+ $command=$this->getDbConnection()->createCommand($sql);
+ return Prado::unserialize($command->queryScalar());
+ }
+ catch(Exception $e)
+ {
+ $this->initializeCache(true);
+ return Prado::unserialize($command->queryScalar());
+ }
+ }
+
+ /**
+ * Stores a value identified by a key in cache.
+ * This is the implementation of the method declared in the parent class.
+ *
+ * @param string the key identifying the value to be cached
+ * @param string the value to be cached
+ * @param integer the number of seconds in which the cached value will expire. 0 means never expire.
+ * @return boolean true if the value is successfully stored into cache, false otherwise
+ */
+ protected function setValue($key,$value,$expire)
+ {
+ $this->deleteValue($key);
+ return $this->addValue($key,$value,$expire);
+ }
+
+ /**
+ * Stores a value identified by a key into cache if the cache does not contain this key.
+ * This is the implementation of the method declared in the parent class.
+ *
+ * @param string the key identifying the value to be cached
+ * @param string the value to be cached
+ * @param integer the number of seconds in which the cached value will expire. 0 means never expire.
+ * @return boolean true if the value is successfully stored into cache, false otherwise
+ */
+ protected function addValue($key,$value,$expire)
+ {
+ if(!$this->_cacheInitialized) $this->initializeCache();
+ $expire=($expire<=0)?0:time()+$expire;
+ $sql="INSERT INTO {$this->_cacheTable} (itemkey,value,expire) VALUES(:key,:value,$expire)";
+ try
+ {
+ $command=$this->getDbConnection()->createCommand($sql);
+ $command->bindValue(':key',$key,PDO::PARAM_STR);
+ $command->bindValue(':value',Prado::serialize($value),PDO::PARAM_LOB);
+ $command->execute();
+ return true;
+ }
+ catch(Exception $e)
+ {
+ try
+ {
+ $this->initializeCache(true);
+ $command->execute();
+ return true;
+ }
+ catch(Exception $e)
+ {
+ return false;
+ }
+ }
+ }
+
+ /**
+ * Deletes a value with the specified key from cache
+ * This is the implementation of the method declared in the parent class.
+ * @param string the key of the value to be deleted
+ * @return boolean if no error happens during deletion
+ */
+ protected function deleteValue($key)
+ {
+ if(!$this->_cacheInitialized) $this->initializeCache();
+ try
+ {
+ $command=$this->getDbConnection()->createCommand("DELETE FROM {$this->_cacheTable} WHERE itemkey=:key");
+ $command->bindValue(':key',$key,PDO::PARAM_STR);
+ $command->execute();
+ return true;
+ }
+ catch(Exception $e)
+ {
+ $this->initializeCache(true);
+ $command->execute();
+ return true;
+ }
+ }
+
+ /**
+ * Deletes all values from cache.
+ * Be careful of performing this operation if the cache is shared by multiple applications.
+ */
+ public function flush()
+ {
+ if(!$this->_cacheInitialized) $this->initializeCache();
+ try
+ {
+ $command = $this->getDbConnection()->createCommand("DELETE FROM {$this->_cacheTable}");
+ $command->execute();
+ }
+ catch(Exception $e)
+ {
+ try
+ {
+ $this->initializeCache(true);
+ $command->execute();
+ return true;
+ }
+ catch(Exception $e)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+}
diff --git a/framework/Caching/TSqliteCache.php b/framework/Caching/TSqliteCache.php
index 2668e3cc..6cba94ae 100644
--- a/framework/Caching/TSqliteCache.php
+++ b/framework/Caching/TSqliteCache.php
@@ -1,224 +1,224 @@
-<?php
-/**
- * TSqliteCache class file
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @link http://www.pradosoft.com/
- * @copyright Copyright &copy; 2005-2012 PradoSoft
- * @license http://www.pradosoft.com/license/
- * @version $Id$
- * @package System.Caching
- */
-
-/**
- * TSqliteCache class
- *
- * TSqliteCache implements a cache application module based on SQLite database.
- *
- * THIS CLASS IS DEPRECATED since it relies on the sqlite PHP extension, that is
- * no longer loaded by default since PHP 5.1. You are discouraged from using it:
- * use {@link TDbCache} instead.
- *
- * Since PRADO v3.1.0, a new DB-based cache module called {@link TDbCache}
- * is provided. If you have PDO extension installed, you may consider using
- * the new cache module instead as it allows you to use different database
- * to store the cached data.
- *
- * The database file is specified by the {@link setDbFile DbFile} property.
- * If not set, the database file will be created under the system state path.
- * If the specified database file does not exist, it will be created automatically.
- * Make sure the directory containing the specified DB file and the file itself is
- * writable by the Web server process.
- *
- * The following basic cache operations are implemented:
- * - {@link get} : retrieve the value with a key (if any) from cache
- * - {@link set} : store the value with a key into cache
- * - {@link add} : store the value only if cache does not have this key
- * - {@link delete} : delete the value with the specified key from cache
- * - {@link flush} : delete all values from cache
- *
- * Each value is associated with an expiration time. The {@link get} operation
- * ensures that any expired value will not be returned. The expiration time by
- * the number of seconds. A expiration time 0 represents never expire.
- *
- * By definition, cache does not ensure the existence of a value
- * even if it never expires. Cache is not meant to be an persistent storage.
- *
- * Do not use the same database file for multiple applications using TSqliteCache.
- * Also note, cache is shared by all user sessions of an application.
- *
- * Some usage examples of TSqliteCache are as follows,
- * <code>
- * $cache=new TSqliteCache; // TSqliteCache may also be loaded as a Prado application module
- * $cache->setDbFile($dbFilePath);
- * $cache->init(null);
- * $cache->add('object',$object);
- * $object2=$cache->get('object');
- * </code>
- *
- * If loaded, TSqliteCache will register itself with {@link TApplication} as the
- * cache module. It can be accessed via {@link TApplication::getCache()}.
- *
- * TSqliteCache may be configured in application configuration file as follows
- * <code>
- * <module id="cache" class="System.Caching.TSqliteCache" DbFile="Application.Data.site" />
- * </code>
- * where {@link getDbFile DbFile} is a property specifying the location of the
- * SQLite DB file (in the namespace format).
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @version $Id$
- * @package System.Caching
- * @since 3.0
- */
-class TSqliteCache extends TCache
-{
- /**
- * name of the table storing cache data
- */
- const CACHE_TABLE='cache';
- /**
- * extension of the db file name
- */
- const DB_FILE_EXT='.db';
-
- /**
- * @var boolean if the module has been initialized
- */
- private $_initialized=false;
- /**
- * @var SQLiteDatabase the sqlite database instance
- */
- private $_db=null;
- /**
- * @var string the database file name
- */
- private $_file=null;
-
- /**
- * Destructor.
- * Disconnect the db connection.
- */
- public function __destruct()
- {
- $this->_db=null;
- }
-
- /**
- * Initializes this module.
- * This method is required by the IModule interface. It checks if the DbFile
- * property is set, and creates a SQLiteDatabase instance for it.
- * The database or the cache table does not exist, they will be created.
- * Expired values are also deleted.
- * @param TXmlElement configuration for this module, can be null
- * @throws TConfigurationException if sqlite extension is not installed,
- * DbFile is set invalid, or any error happens during creating database or cache table.
- */
- public function init($config)
- {
- if(!function_exists('sqlite_open'))
- throw new TConfigurationException('sqlitecache_extension_required');
- if($this->_file===null)
- $this->_file=$this->getApplication()->getRuntimePath().'/sqlite.cache';
- $error='';
- if(($this->_db=new SQLiteDatabase($this->_file,0666,$error))===false)
- throw new TConfigurationException('sqlitecache_connection_failed',$error);
- if(@$this->_db->query('DELETE FROM '.self::CACHE_TABLE.' WHERE expire<>0 AND expire<'.time())===false)
- {
- if($this->_db->query('CREATE TABLE '.self::CACHE_TABLE.' (key CHAR(128) PRIMARY KEY, value BLOB, expire INT)')===false)
- throw new TConfigurationException('sqlitecache_table_creation_failed',sqlite_error_string(sqlite_last_error()));
- }
- $this->_initialized=true;
- parent::init($config);
- }
-
- /**
- * @return string database file path (in namespace form)
- */
- public function getDbFile()
- {
- return $this->_file;
- }
-
- /**
- * @param string database file path (in namespace form)
- * @throws TInvalidOperationException if the module is already initialized
- * @throws TConfigurationException if the file is not in proper namespace format
- */
- public function setDbFile($value)
- {
- if($this->_initialized)
- throw new TInvalidOperationException('sqlitecache_dbfile_unchangeable');
- else if(($this->_file=Prado::getPathOfNamespace($value,self::DB_FILE_EXT))===null)
- throw new TConfigurationException('sqlitecache_dbfile_invalid',$value);
- }
-
- /**
- * Retrieves a value from cache with a specified key.
- * This is the implementation of the method declared in the parent class.
- * @param string a unique key identifying the cached value
- * @return string the value stored in cache, false if the value is not in the cache or expired.
- */
- protected function getValue($key)
- {
- $sql='SELECT value FROM '.self::CACHE_TABLE.' WHERE key=\''.$key.'\' AND (expire=0 OR expire>'.time().') LIMIT 1';
- if(($ret=$this->_db->query($sql))!=false && ($row=$ret->fetch(SQLITE_ASSOC))!==false)
- return Prado::unserialize($row['value']);
- else
- return false;
- }
-
- /**
- * Stores a value identified by a key in cache.
- * This is the implementation of the method declared in the parent class.
- *
- * @param string the key identifying the value to be cached
- * @param string the value to be cached
- * @param integer the number of seconds in which the cached value will expire. 0 means never expire.
- * @return boolean true if the value is successfully stored into cache, false otherwise
- */
- protected function setValue($key,$value,$expire)
- {
- $expire=($expire<=0)?0:time()+$expire;
- $sql='REPLACE INTO '.self::CACHE_TABLE.' VALUES(\''.$key.'\',\''.sqlite_escape_string(Prado::serialize($value)).'\','.$expire.')';
- return $this->_db->query($sql)!==false;
- }
-
- /**
- * Stores a value identified by a key into cache if the cache does not contain this key.
- * This is the implementation of the method declared in the parent class.
- *
- * @param string the key identifying the value to be cached
- * @param string the value to be cached
- * @param integer the number of seconds in which the cached value will expire. 0 means never expire.
- * @return boolean true if the value is successfully stored into cache, false otherwise
- */
- protected function addValue($key,$value,$expire)
- {
- $expire=($expire<=0)?0:time()+$expire;
- $sql='INSERT INTO '.self::CACHE_TABLE.' VALUES(\''.$key.'\',\''.sqlite_escape_string(Prado::serialize($value)).'\','.$expire.')';
- return @$this->_db->query($sql)!==false;
- }
-
- /**
- * Deletes a value with the specified key from cache
- * This is the implementation of the method declared in the parent class.
- * @param string the key of the value to be deleted
- * @return boolean if no error happens during deletion
- */
- protected function deleteValue($key)
- {
- $sql='DELETE FROM '.self::CACHE_TABLE.' WHERE key=\''.$key.'\'';
- return $this->_db->query($sql)!==false;
- }
-
- /**
- * Deletes all values from cache.
- * Be careful of performing this operation if the cache is shared by multiple applications.
- */
- public function flush()
- {
- return $this->_db->query('DELETE FROM '.self::CACHE_TABLE)!==false;
- }
-}
-
+<?php
+/**
+ * TSqliteCache class file
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @link http://www.pradosoft.com/
+ * @copyright Copyright &copy; 2005-2012 PradoSoft
+ * @license http://www.pradosoft.com/license/
+ * @version $Id$
+ * @package System.Caching
+ */
+
+/**
+ * TSqliteCache class
+ *
+ * TSqliteCache implements a cache application module based on SQLite database.
+ *
+ * THIS CLASS IS DEPRECATED since it relies on the sqlite PHP extension, that is
+ * no longer loaded by default since PHP 5.1. You are discouraged from using it:
+ * use {@link TDbCache} instead.
+ *
+ * Since PRADO v3.1.0, a new DB-based cache module called {@link TDbCache}
+ * is provided. If you have PDO extension installed, you may consider using
+ * the new cache module instead as it allows you to use different database
+ * to store the cached data.
+ *
+ * The database file is specified by the {@link setDbFile DbFile} property.
+ * If not set, the database file will be created under the system state path.
+ * If the specified database file does not exist, it will be created automatically.
+ * Make sure the directory containing the specified DB file and the file itself is
+ * writable by the Web server process.
+ *
+ * The following basic cache operations are implemented:
+ * - {@link get} : retrieve the value with a key (if any) from cache
+ * - {@link set} : store the value with a key into cache
+ * - {@link add} : store the value only if cache does not have this key
+ * - {@link delete} : delete the value with the specified key from cache
+ * - {@link flush} : delete all values from cache
+ *
+ * Each value is associated with an expiration time. The {@link get} operation
+ * ensures that any expired value will not be returned. The expiration time by
+ * the number of seconds. A expiration time 0 represents never expire.
+ *
+ * By definition, cache does not ensure the existence of a value
+ * even if it never expires. Cache is not meant to be an persistent storage.
+ *
+ * Do not use the same database file for multiple applications using TSqliteCache.
+ * Also note, cache is shared by all user sessions of an application.
+ *
+ * Some usage examples of TSqliteCache are as follows,
+ * <code>
+ * $cache=new TSqliteCache; // TSqliteCache may also be loaded as a Prado application module
+ * $cache->setDbFile($dbFilePath);
+ * $cache->init(null);
+ * $cache->add('object',$object);
+ * $object2=$cache->get('object');
+ * </code>
+ *
+ * If loaded, TSqliteCache will register itself with {@link TApplication} as the
+ * cache module. It can be accessed via {@link TApplication::getCache()}.
+ *
+ * TSqliteCache may be configured in application configuration file as follows
+ * <code>
+ * <module id="cache" class="System.Caching.TSqliteCache" DbFile="Application.Data.site" />
+ * </code>
+ * where {@link getDbFile DbFile} is a property specifying the location of the
+ * SQLite DB file (in the namespace format).
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @version $Id$
+ * @package System.Caching
+ * @since 3.0
+ */
+class TSqliteCache extends TCache
+{
+ /**
+ * name of the table storing cache data
+ */
+ const CACHE_TABLE='cache';
+ /**
+ * extension of the db file name
+ */
+ const DB_FILE_EXT='.db';
+
+ /**
+ * @var boolean if the module has been initialized
+ */
+ private $_initialized=false;
+ /**
+ * @var SQLiteDatabase the sqlite database instance
+ */
+ private $_db=null;
+ /**
+ * @var string the database file name
+ */
+ private $_file=null;
+
+ /**
+ * Destructor.
+ * Disconnect the db connection.
+ */
+ public function __destruct()
+ {
+ $this->_db=null;
+ }
+
+ /**
+ * Initializes this module.
+ * This method is required by the IModule interface. It checks if the DbFile
+ * property is set, and creates a SQLiteDatabase instance for it.
+ * The database or the cache table does not exist, they will be created.
+ * Expired values are also deleted.
+ * @param TXmlElement configuration for this module, can be null
+ * @throws TConfigurationException if sqlite extension is not installed,
+ * DbFile is set invalid, or any error happens during creating database or cache table.
+ */
+ public function init($config)
+ {
+ if(!function_exists('sqlite_open'))
+ throw new TConfigurationException('sqlitecache_extension_required');
+ if($this->_file===null)
+ $this->_file=$this->getApplication()->getRuntimePath().'/sqlite.cache';
+ $error='';
+ if(($this->_db=new SQLiteDatabase($this->_file,0666,$error))===false)
+ throw new TConfigurationException('sqlitecache_connection_failed',$error);
+ if(@$this->_db->query('DELETE FROM '.self::CACHE_TABLE.' WHERE expire<>0 AND expire<'.time())===false)
+ {
+ if($this->_db->query('CREATE TABLE '.self::CACHE_TABLE.' (key CHAR(128) PRIMARY KEY, value BLOB, expire INT)')===false)
+ throw new TConfigurationException('sqlitecache_table_creation_failed',sqlite_error_string(sqlite_last_error()));
+ }
+ $this->_initialized=true;
+ parent::init($config);
+ }
+
+ /**
+ * @return string database file path (in namespace form)
+ */
+ public function getDbFile()
+ {
+ return $this->_file;
+ }
+
+ /**
+ * @param string database file path (in namespace form)
+ * @throws TInvalidOperationException if the module is already initialized
+ * @throws TConfigurationException if the file is not in proper namespace format
+ */
+ public function setDbFile($value)
+ {
+ if($this->_initialized)
+ throw new TInvalidOperationException('sqlitecache_dbfile_unchangeable');
+ else if(($this->_file=Prado::getPathOfNamespace($value,self::DB_FILE_EXT))===null)
+ throw new TConfigurationException('sqlitecache_dbfile_invalid',$value);
+ }
+
+ /**
+ * Retrieves a value from cache with a specified key.
+ * This is the implementation of the method declared in the parent class.
+ * @param string a unique key identifying the cached value
+ * @return string the value stored in cache, false if the value is not in the cache or expired.
+ */
+ protected function getValue($key)
+ {
+ $sql='SELECT value FROM '.self::CACHE_TABLE.' WHERE key=\''.$key.'\' AND (expire=0 OR expire>'.time().') LIMIT 1';
+ if(($ret=$this->_db->query($sql))!=false && ($row=$ret->fetch(SQLITE_ASSOC))!==false)
+ return Prado::unserialize($row['value']);
+ else
+ return false;
+ }
+
+ /**
+ * Stores a value identified by a key in cache.
+ * This is the implementation of the method declared in the parent class.
+ *
+ * @param string the key identifying the value to be cached
+ * @param string the value to be cached
+ * @param integer the number of seconds in which the cached value will expire. 0 means never expire.
+ * @return boolean true if the value is successfully stored into cache, false otherwise
+ */
+ protected function setValue($key,$value,$expire)
+ {
+ $expire=($expire<=0)?0:time()+$expire;
+ $sql='REPLACE INTO '.self::CACHE_TABLE.' VALUES(\''.$key.'\',\''.sqlite_escape_string(Prado::serialize($value)).'\','.$expire.')';
+ return $this->_db->query($sql)!==false;
+ }
+
+ /**
+ * Stores a value identified by a key into cache if the cache does not contain this key.
+ * This is the implementation of the method declared in the parent class.
+ *
+ * @param string the key identifying the value to be cached
+ * @param string the value to be cached
+ * @param integer the number of seconds in which the cached value will expire. 0 means never expire.
+ * @return boolean true if the value is successfully stored into cache, false otherwise
+ */
+ protected function addValue($key,$value,$expire)
+ {
+ $expire=($expire<=0)?0:time()+$expire;
+ $sql='INSERT INTO '.self::CACHE_TABLE.' VALUES(\''.$key.'\',\''.sqlite_escape_string(Prado::serialize($value)).'\','.$expire.')';
+ return @$this->_db->query($sql)!==false;
+ }
+
+ /**
+ * Deletes a value with the specified key from cache
+ * This is the implementation of the method declared in the parent class.
+ * @param string the key of the value to be deleted
+ * @return boolean if no error happens during deletion
+ */
+ protected function deleteValue($key)
+ {
+ $sql='DELETE FROM '.self::CACHE_TABLE.' WHERE key=\''.$key.'\'';
+ return $this->_db->query($sql)!==false;
+ }
+
+ /**
+ * Deletes all values from cache.
+ * Be careful of performing this operation if the cache is shared by multiple applications.
+ */
+ public function flush()
+ {
+ return $this->_db->query('DELETE FROM '.self::CACHE_TABLE)!==false;
+ }
+}
+
diff --git a/framework/Caching/TXCache.php b/framework/Caching/TXCache.php
index 6750d5b8..31f2a4d2 100644
--- a/framework/Caching/TXCache.php
+++ b/framework/Caching/TXCache.php
@@ -1,131 +1,131 @@
-<?php
-/**
- * TXCache class file
- *
- * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
- * @link http://www.pradosoft.com/
- * @copyright Copyright &copy; 2005-2012 PradoSoft
- * @license http://www.pradosoft.com/license/
- * @version $Id: TXCache.php 1994 2007-06-11 16:02:28Z knut $
- * @package System.Caching
- */
-
-/**
- * TXCache class
- *
- * TXCache implements a cache application module based on {@link http://xcache.lighttpd.net/ xcache}.
- *
- * By definition, cache does not ensure the existence of a value
- * even if it never expires. Cache is not meant to be an persistent storage.
- *
- * To use this module, the xcache PHP extension must be loaded and configured in the php.ini.
- *
- * Some usage examples of TXCache are as follows,
- * <code>
- * $cache=new TXCache; // TXCache may also be loaded as a Prado application module
- * $cache->init(null);
- * $cache->add('object',$object);
- * $object2=$cache->get('object');
- * </code>
- *
- * If loaded, TXCache will register itself with {@link TApplication} as the
- * cache module. It can be accessed via {@link TApplication::getCache()}.
- *
- * TXCache may be configured in application configuration file as follows
- * <code>
- * <module id="cache" class="System.Caching.TXCache" />
- * </code>
- *
- * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
- * @version $Id: TXCache.php 1994 2007-06-11 16:02:28Z knut $
- * @package System.Caching
- * @since 3.1.1
- */
-class TXCache extends TCache
-{
- /**
- * Initializes this module.
- * This method is required by the IModule interface.
- * @param TXmlElement configuration for this module, can be null
- * @throws TConfigurationException if xcache extension is not installed or not started, check your php.ini
- */
- public function init($config)
- {
- if(!function_exists('xcache_isset'))
- throw new TConfigurationException('xcache_extension_required');
-
- $enabled = (int)ini_get('xcache.cacher') !== 0;
- $var_size = (int)ini_get('xcache.var_size');
-
- if(!($enabled && $var_size > 0))
- throw new TConfigurationException('xcache_extension_not_enabled');
-
- parent::init($config);
- }
-
- /**
- * Retrieves a value from cache with a specified key.
- * This is the implementation of the method declared in the parent class.
- * @param string a unique key identifying the cached value
- * @return string the value stored in cache, false if the value is not in the cache or expired.
- */
- protected function getValue($key)
- {
- return xcache_isset($key) ? xcache_get($key) : false;
- }
-
- /**
- * Stores a value identified by a key in cache.
- * This is the implementation of the method declared in the parent class.
- *
- * @param string the key identifying the value to be cached
- * @param string the value to be cached
- * @param integer the number of seconds in which the cached value will expire. 0 means never expire.
- * @return boolean true if the value is successfully stored into cache, false otherwise
- */
- protected function setValue($key,$value,$expire)
- {
- return xcache_set($key,$value,$expire);
- }
-
- /**
- * Stores a value identified by a key into cache if the cache does not contain this key.
- * This is the implementation of the method declared in the parent class.
- *
- * @param string the key identifying the value to be cached
- * @param string the value to be cached
- * @param integer the number of seconds in which the cached value will expire. 0 means never expire.
- * @return boolean true if the value is successfully stored into cache, false otherwise
- */
- protected function addValue($key,$value,$expire)
- {
- return !xcache_isset($key) ? $this->setValue($key,$value,$expire) : false;
- }
-
- /**
- * Deletes a value with the specified key from cache
- * This is the implementation of the method declared in the parent class.
- * @param string the key of the value to be deleted
- * @return boolean if no error happens during deletion
- */
- protected function deleteValue($key)
- {
- return xcache_unset($key);
- }
-
- /**
- * Deletes all values from cache.
- * Be careful of performing this operation if the cache is shared by multiple applications.
- */
- public function flush()
- {
- for($i=0, $max=xcache_count(XC_TYPE_VAR); $i<$max; $i++)
- {
- if(xcache_clear_cache(XC_TYPE_VAR, $i)===false)
- return false;
- }
- return true;
- }
-}
-
-?>
+<?php
+/**
+ * TXCache class file
+ *
+ * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
+ * @link http://www.pradosoft.com/
+ * @copyright Copyright &copy; 2005-2012 PradoSoft
+ * @license http://www.pradosoft.com/license/
+ * @version $Id: TXCache.php 1994 2007-06-11 16:02:28Z knut $
+ * @package System.Caching
+ */
+
+/**
+ * TXCache class
+ *
+ * TXCache implements a cache application module based on {@link http://xcache.lighttpd.net/ xcache}.
+ *
+ * By definition, cache does not ensure the existence of a value
+ * even if it never expires. Cache is not meant to be an persistent storage.
+ *
+ * To use this module, the xcache PHP extension must be loaded and configured in the php.ini.
+ *
+ * Some usage examples of TXCache are as follows,
+ * <code>
+ * $cache=new TXCache; // TXCache may also be loaded as a Prado application module
+ * $cache->init(null);
+ * $cache->add('object',$object);
+ * $object2=$cache->get('object');
+ * </code>
+ *
+ * If loaded, TXCache will register itself with {@link TApplication} as the
+ * cache module. It can be accessed via {@link TApplication::getCache()}.
+ *
+ * TXCache may be configured in application configuration file as follows
+ * <code>
+ * <module id="cache" class="System.Caching.TXCache" />
+ * </code>
+ *
+ * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
+ * @version $Id: TXCache.php 1994 2007-06-11 16:02:28Z knut $
+ * @package System.Caching
+ * @since 3.1.1
+ */
+class TXCache extends TCache
+{
+ /**
+ * Initializes this module.
+ * This method is required by the IModule interface.
+ * @param TXmlElement configuration for this module, can be null
+ * @throws TConfigurationException if xcache extension is not installed or not started, check your php.ini
+ */
+ public function init($config)
+ {
+ if(!function_exists('xcache_isset'))
+ throw new TConfigurationException('xcache_extension_required');
+
+ $enabled = (int)ini_get('xcache.cacher') !== 0;
+ $var_size = (int)ini_get('xcache.var_size');
+
+ if(!($enabled && $var_size > 0))
+ throw new TConfigurationException('xcache_extension_not_enabled');
+
+ parent::init($config);
+ }
+
+ /**
+ * Retrieves a value from cache with a specified key.
+ * This is the implementation of the method declared in the parent class.
+ * @param string a unique key identifying the cached value
+ * @return string the value stored in cache, false if the value is not in the cache or expired.
+ */
+ protected function getValue($key)
+ {
+ return xcache_isset($key) ? xcache_get($key) : false;
+ }
+
+ /**
+ * Stores a value identified by a key in cache.
+ * This is the implementation of the method declared in the parent class.
+ *
+ * @param string the key identifying the value to be cached
+ * @param string the value to be cached
+ * @param integer the number of seconds in which the cached value will expire. 0 means never expire.
+ * @return boolean true if the value is successfully stored into cache, false otherwise
+ */
+ protected function setValue($key,$value,$expire)
+ {
+ return xcache_set($key,$value,$expire);
+ }
+
+ /**
+ * Stores a value identified by a key into cache if the cache does not contain this key.
+ * This is the implementation of the method declared in the parent class.
+ *
+ * @param string the key identifying the value to be cached
+ * @param string the value to be cached
+ * @param integer the number of seconds in which the cached value will expire. 0 means never expire.
+ * @return boolean true if the value is successfully stored into cache, false otherwise
+ */
+ protected function addValue($key,$value,$expire)
+ {
+ return !xcache_isset($key) ? $this->setValue($key,$value,$expire) : false;
+ }
+
+ /**
+ * Deletes a value with the specified key from cache
+ * This is the implementation of the method declared in the parent class.
+ * @param string the key of the value to be deleted
+ * @return boolean if no error happens during deletion
+ */
+ protected function deleteValue($key)
+ {
+ return xcache_unset($key);
+ }
+
+ /**
+ * Deletes all values from cache.
+ * Be careful of performing this operation if the cache is shared by multiple applications.
+ */
+ public function flush()
+ {
+ for($i=0, $max=xcache_count(XC_TYPE_VAR); $i<$max; $i++)
+ {
+ if(xcache_clear_cache(XC_TYPE_VAR, $i)===false)
+ return false;
+ }
+ return true;
+ }
+}
+
+?>