From b558f2c60e97540415464719149b773e51f79abc Mon Sep 17 00:00:00 2001
From: xue <>
Date: Mon, 17 Sep 2007 18:18:17 +0000
Subject: Added TCachePageStatePersister
---
.gitattributes | 1 +
HISTORY | 1 +
.../pages/GettingStarted/NewFeatures.page | 1 +
framework/Exceptions/messages/messages.txt | 7 +-
framework/Web/TCacheHttpSession.php | 2 +-
framework/Web/UI/TCachePageStatePersister.php | 202 +++++++++++++++++++++
framework/Web/UI/TSessionPageStatePersister.php | 4 +-
7 files changed, 214 insertions(+), 4 deletions(-)
create mode 100644 framework/Web/UI/TCachePageStatePersister.php
diff --git a/.gitattributes b/.gitattributes
index 6b7bd75a..27c86adf 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -2498,6 +2498,7 @@ framework/Web/UI/ActiveControls/TEventTriggeredCallback.php -text
framework/Web/UI/ActiveControls/TInPlaceTextBox.php -text
framework/Web/UI/ActiveControls/TTriggeredCallback.php -text
framework/Web/UI/ActiveControls/TValueTriggeredCallback.php -text
+framework/Web/UI/TCachePageStatePersister.php -text
framework/Web/UI/TClientScriptManager.php -text
framework/Web/UI/TCompositeControl.php -text
framework/Web/UI/TControl.php -text
diff --git a/HISTORY b/HISTORY
index 07ab61fa..b2c53067 100644
--- a/HISTORY
+++ b/HISTORY
@@ -29,6 +29,7 @@ NEW: Ticket#680 - Added TCacheHttpSession (Carl, Qiang)
NEW: Added TTabPanel (Qiang)
NEW: Added TKeyboard (Qiang)
NEW: Added TCaptcha and TCaptchaValidator (Qiang)
+NEW: Added TCachePageStatePersister (Qiang)
NEW: Added TSlider (Christophe)
NEW: Added Indonesian translation to QuickStart, requirements and error messages (Zaenal Mutaqin)
NEW: Added French translation to the blog tutorial (Eric Marchetti)
diff --git a/demos/quickstart/protected/pages/GettingStarted/NewFeatures.page b/demos/quickstart/protected/pages/GettingStarted/NewFeatures.page
index e3e5c0e4..939dd139 100644
--- a/demos/quickstart/protected/pages/GettingStarted/NewFeatures.page
+++ b/demos/quickstart/protected/pages/GettingStarted/NewFeatures.page
@@ -15,6 +15,7 @@ This page summarizes the main new features that are introduced in each PRADO rel
Added Oracle DB support to Active Record.
Added support to TDataGrid to allow grouping consecutive cells with the same content.
Added support to allow configuring page properties and authorization rules using relative page paths in application and page configurations. Added support to allow authorization based on remote host address.
+Added a new page state persister TCachePageStatePersister. It allows page state to be stored using a cache module (e.g. TMemCache, TDbCache, etc.)
Version 3.1.0
diff --git a/framework/Exceptions/messages/messages.txt b/framework/Exceptions/messages/messages.txt
index 484d23e5..a105f359 100644
--- a/framework/Exceptions/messages/messages.txt
+++ b/framework/Exceptions/messages/messages.txt
@@ -444,4 +444,9 @@ captcha_gd2_required = TCaptcha requires PHP GD2 extension.
captcha_imagettftext_required = TCaptcha requires PHP GD2 extension with TrueType font support.
captcha_imagepng_required = TCaptcha requires PHP GD2 extension with PNG image format support.
-slider_handle_class_invalid = TSlider.HandleClass '{0}' is not a valid user class. The class must extends TSliderHandle.
\ No newline at end of file
+slider_handle_class_invalid = TSlider.HandleClass '{0}' is not a valid user class. The class must extends TSliderHandle.
+
+cachepagestatepersister_cachemoduleid_invalid = TCachePageStatePersister.CacheModuleID '{0}' does not point to a valid cache module.
+cachepagestatepersister_cache_required = TCachePageStatePersister requires a cache module to be loaded.
+cachepagestatepersister_timeout_invalid = TCachePageStatePersister.Timeout must be an integer no less than zero.
+cachepagestatepersister_pagestate_corrupted = Page state is corrupted.
\ No newline at end of file
diff --git a/framework/Web/TCacheHttpSession.php b/framework/Web/TCacheHttpSession.php
index edc79935..21638131 100644
--- a/framework/Web/TCacheHttpSession.php
+++ b/framework/Web/TCacheHttpSession.php
@@ -67,7 +67,7 @@ class TCacheHttpSession extends THttpSession
}
/**
- * @return string host name of the memcache server
+ * @return string the ID of the cache module.
*/
public function getCacheModuleID()
{
diff --git a/framework/Web/UI/TCachePageStatePersister.php b/framework/Web/UI/TCachePageStatePersister.php
new file mode 100644
index 00000000..3e793195
--- /dev/null
+++ b/framework/Web/UI/TCachePageStatePersister.php
@@ -0,0 +1,202 @@
+
+ * @link http://www.pradosoft.com/
+ * @copyright Copyright © 2005-2007 PradoSoft
+ * @license http://www.pradosoft.com/license/
+ * @version $Id$
+ * @package System.Web.UI
+ */
+
+/**
+ * TCachePageStatePersister class
+ *
+ * TCachePageStatePersister implements a page state persistent method based on cache.
+ * Page state are stored in cache (e.g. memcache, DB cache, etc.), and only a small token
+ * is passed to the client side to identify the state. This greatly reduces the size of
+ * the page state that needs to be transmitted between the server and the client. Of course,
+ * this is at the cost of using server side resource.
+ *
+ * A cache module has to be loaded in order to use TCachePageStatePersister.
+ * By default, TCachePageStatePersister will use the primary cache module.
+ * A non-primary cache module can be used by setting {@link setCacheModuleID CacheModuleID}.
+ * Any cache module, as long as it implements the interface {@link ICache}, may be used.
+ * For example, one can use {@link TDbCache}, {@link TMemCache}, {@link TAPCCache}, etc.
+ *
+ * TCachePageStatePersister uses {@link setCacheTimeout CacheTimeout} to limit the data
+ * that stores in cache.
+ *
+ * Since server resource is often limited, be cautious if you plan to use TCachePageStatePersister
+ * for high-traffic Web pages. You may consider using a small {@link setCacheTimeout CacheTimeout}.
+ *
+ * There are a couple of ways to use TCachePageStatePersister.
+ * One can override the page's {@link TPage::getStatePersister()} method and
+ * create a TCachePageStatePersister instance there.
+ * Or one can configure the pages to use TCachePageStatePersister in page configurations
+ * as follows,
+ *
+ *
+ *
+ * Note in the above, we use StatePersister.CacheModuleID to configure the cache module ID
+ * for the TCachePageStatePersister instance.
+ *
+ * The above configuration will affect the pages under the directory containing
+ * this configuration and all its subdirectories.
+ * To configure individual pages to use TCachePageStatePersister, use
+ *
+ *
+ *
+ *
+ *
+ *
+ * @author Qiang Xue
+ * @version $Id$
+ * @package System.Web.UI
+ * @since 3.1.1
+ */
+class TCachePageStatePersister extends TComponent implements IPageStatePersister
+{
+ private $_prefix='statepersister';
+ private $_page;
+ private $_cache=null;
+ private $_cacheModuleID='';
+ private $_timeout=1800;
+
+ /**
+ * @param TPage the page that this persister works for
+ */
+ public function getPage()
+ {
+ return $this->_page;
+ }
+
+ /**
+ * @param TPage the page that this persister works for.
+ */
+ public function setPage(TPage $page)
+ {
+ $this->_page=$page;
+ }
+
+ /**
+ * @return string the ID of the cache module.
+ */
+ public function getCacheModuleID()
+ {
+ return $this->_cacheModuleID;
+ }
+
+ /**
+ * @param string the ID of the cache module. If not set, the primary cache module will be used.
+ */
+ public function setCacheModuleID($value)
+ {
+ $this->_cacheModuleID=$value;
+ }
+
+ /**
+ * @return ICache the cache module being used for data storage
+ */
+ public function getCache()
+ {
+ if($this->_cache===null)
+ {
+ if($this->_cacheModuleID!=='')
+ $cache=Prado::getApplication()->getModule($this->_cacheModuleID);
+ else
+ $cache=Prado::getApplication()->getCache();
+ if($cache===null || !($cache instanceof ICache))
+ {
+ if($this->_cacheModule!=='')
+ throw new TConfigurationException('cachepagestatepersister_cachemoduleid_invalid',$this->_cacheModuleID);
+ else
+ throw new TConfigurationException('cachepagestatepersister_cache_required');
+ }
+ $this->_cache=$cache;
+ }
+ return $this->_cache;
+ }
+
+ /**
+ * @return integer the number of seconds in which the cached state will expire. Defaults to 1800.
+ */
+ public function getCacheTimeout()
+ {
+ return $this->_timeout;
+ }
+
+ /**
+ * @param integer the number of seconds in which the cached state will expire. 0 means never expire.
+ * @throws TInvalidDataValueException if the number is smaller than 0.
+ */
+ public function setCacheTimeout($value)
+ {
+ if(($value=TPropertyValue::ensureInteger($value))>=0)
+ $this->_timeout=$value;
+ else
+ throw new TInvalidDataValueException('cachepagestatepersister_timeout_invalid');
+ }
+
+ /**
+ * @return string prefix of cache variable name to avoid conflict with other cache data. Defaults to 'statepersister'.
+ */
+ public function getKeyPrefix()
+ {
+ return $this->_prefix;
+ }
+
+ /**
+ * @param string prefix of cache variable name to avoid conflict with other cache data
+ */
+ public function setKeyPrefix($value)
+ {
+ $this->_prefix=$value;
+ }
+
+ /**
+ * @param string micro timestamp when saving state occurs
+ * @return string a key that is unique per user request
+ */
+ protected function calculateKey($timestamp)
+ {
+ return $this->getKeyPrefix().':'
+ . $this->_page->getRequest()->getUserHostAddress()
+ . $this->_page->getPagePath()
+ . $timestamp;
+ }
+
+ /**
+ * Saves state in cache.
+ * @param mixed state to be stored
+ */
+ public function save($state)
+ {
+ $data=serialize($state);
+ $timestamp=(string)microtime(true);
+ $key=$this->calculateKey($timestamp);
+ $this->getCache()->add($key,$data,$this->_timeout);
+ $this->_page->setClientState(TPageStateFormatter::serialize($this->_page,$timestamp));
+ }
+
+ /**
+ * Loads page state from cache.
+ * @return mixed the restored state
+ * @throws THttpException if page state is corrupted
+ */
+ public function load()
+ {
+ if(($timestamp=TPageStateFormatter::unserialize($this->_page,$this->_page->getRequestClientState()))!==null)
+ {
+ $key=$this->calculateKey($timestamp);
+ if(($data=$this->getCache()->get($key))!==false)
+ return unserialize($data);
+ }
+ throw new THttpException(400,'cachepagestatepersister_pagestate_corrupted');
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/framework/Web/UI/TSessionPageStatePersister.php b/framework/Web/UI/TSessionPageStatePersister.php
index 964ad366..6c7d9669 100644
--- a/framework/Web/UI/TSessionPageStatePersister.php
+++ b/framework/Web/UI/TSessionPageStatePersister.php
@@ -87,7 +87,7 @@ class TSessionPageStatePersister extends TComponent implements IPageStatePersist
throw new TInvalidDataValueException('sessionpagestatepersister_historysize_invalid');
}
/**
- * Saves state in hidden fields.
+ * Saves state in session.
* @param mixed state to be stored
*/
public function save($state)
@@ -111,7 +111,7 @@ class TSessionPageStatePersister extends TComponent implements IPageStatePersist
}
/**
- * Loads page state from hidden fields.
+ * Loads page state from session.
* @return mixed the restored state
* @throws THttpException if page state is corrupted
*/
--
cgit v1.2.3