Subversion-Projekte lars-tiefland.prado

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
/**
3
 * TCachePageStatePersister class file
4
 *
5
 * @author Qiang Xue <qiang.xue@gmail.com>
6
 * @link http://www.pradosoft.com/
7
 * @copyright Copyright &copy; 2005-2008 PradoSoft
8
 * @license http://www.pradosoft.com/license/
9
 * @version $Id: TCachePageStatePersister.php 2541 2008-10-21 15:05:13Z qiang.xue $
10
 * @package System.Web.UI
11
 */
12
 
13
/**
14
 * TCachePageStatePersister class
15
 *
16
 * TCachePageStatePersister implements a page state persistent method based on cache.
17
 * Page state are stored in cache (e.g. memcache, DB cache, etc.), and only a small token
18
 * is passed to the client side to identify the state. This greatly reduces the size of
19
 * the page state that needs to be transmitted between the server and the client. Of course,
20
 * this is at the cost of using server side resource.
21
 *
22
 * A cache module has to be loaded in order to use TCachePageStatePersister.
23
 * By default, TCachePageStatePersister will use the primary cache module.
24
 * A non-primary cache module can be used by setting {@link setCacheModuleID CacheModuleID}.
25
 * Any cache module, as long as it implements the interface {@link ICache}, may be used.
26
 * For example, one can use {@link TDbCache}, {@link TMemCache}, {@link TAPCCache}, etc.
27
 *
28
 * TCachePageStatePersister uses {@link setCacheTimeout CacheTimeout} to limit the data
29
 * that stores in cache.
30
 *
31
 * Since server resource is often limited, be cautious if you plan to use TCachePageStatePersister
32
 * for high-traffic Web pages. You may consider using a small {@link setCacheTimeout CacheTimeout}.
33
 *
34
 * There are a couple of ways to use TCachePageStatePersister.
35
 * One can override the page's {@link TPage::getStatePersister()} method and
36
 * create a TCachePageStatePersister instance there.
37
 * Or one can configure the pages to use TCachePageStatePersister in page configurations
38
 * as follows,
39
 * <code>
40
 *   <pages StatePersisterClass="System.Web.UI.TCachePageStatePersister"
41
 *          StatePersister.CacheModuleID="mycache"
42
 *          StatePersister.CacheTimeout="3600" />
43
 * </code>
44
 * Note in the above, we use StatePersister.CacheModuleID to configure the cache module ID
45
 * for the TCachePageStatePersister instance.
46
 *
47
 * The above configuration will affect the pages under the directory containing
48
 * this configuration and all its subdirectories.
49
 * To configure individual pages to use TCachePageStatePersister, use
50
 * <code>
51
 *   <pages>
52
 *     <page id="PageID" StatePersisterClass="System.Web.UI.TCachePageStatePersister" />
53
 *   </pages>
54
 * </code>
55
 *
56
 * @author Qiang Xue <qiang.xue@gmail.com>
57
 * @version $Id: TCachePageStatePersister.php 2541 2008-10-21 15:05:13Z qiang.xue $
58
 * @package System.Web.UI
59
 * @since 3.1.1
60
 */
61
class TCachePageStatePersister extends TComponent implements IPageStatePersister
62
{
63
	private $_prefix='statepersister';
64
	private $_page;
65
	private $_cache=null;
66
	private $_cacheModuleID='';
67
	private $_timeout=1800;
68
 
69
	/**
70
	 * @param TPage the page that this persister works for
71
	 */
72
	public function getPage()
73
	{
74
		return $this->_page;
75
	}
76
 
77
	/**
78
	 * @param TPage the page that this persister works for.
79
	 */
80
	public function setPage(TPage $page)
81
	{
82
		$this->_page=$page;
83
	}
84
 
85
	/**
86
	 * @return string the ID of the cache module.
87
	 */
88
	public function getCacheModuleID()
89
	{
90
		return $this->_cacheModuleID;
91
	}
92
 
93
	/**
94
	 * @param string the ID of the cache module. If not set, the primary cache module will be used.
95
	 */
96
	public function setCacheModuleID($value)
97
	{
98
		$this->_cacheModuleID=$value;
99
	}
100
 
101
	/**
102
	 * @return ICache the cache module being used for data storage
103
	 */
104
	public function getCache()
105
	{
106
		if($this->_cache===null)
107
		{
108
			if($this->_cacheModuleID!=='')
109
				$cache=Prado::getApplication()->getModule($this->_cacheModuleID);
110
			else
111
				$cache=Prado::getApplication()->getCache();
112
			if($cache===null || !($cache instanceof ICache))
113
			{
114
				if($this->_cacheModule!=='')
115
					throw new TConfigurationException('cachepagestatepersister_cachemoduleid_invalid',$this->_cacheModuleID);
116
				else
117
					throw new TConfigurationException('cachepagestatepersister_cache_required');
118
			}
119
			$this->_cache=$cache;
120
		}
121
		return $this->_cache;
122
	}
123
 
124
	/**
125
	 * @return integer the number of seconds in which the cached state will expire. Defaults to 1800.
126
	 */
127
	public function getCacheTimeout()
128
	{
129
		return $this->_timeout;
130
	}
131
 
132
	/**
133
	 * @param integer the number of seconds in which the cached state will expire. 0 means never expire.
134
	 * @throws TInvalidDataValueException if the number is smaller than 0.
135
	 */
136
	public function setCacheTimeout($value)
137
	{
138
		if(($value=TPropertyValue::ensureInteger($value))>=0)
139
			$this->_timeout=$value;
140
		else
141
			throw new TInvalidDataValueException('cachepagestatepersister_timeout_invalid');
142
	}
143
 
144
	/**
145
	 * @return string prefix of cache variable name to avoid conflict with other cache data. Defaults to 'statepersister'.
146
	 */
147
	public function getKeyPrefix()
148
	{
149
	    return $this->_prefix;
150
	}
151
 
152
	/**
153
     * @param string prefix of cache variable name to avoid conflict with other cache data
154
     */
155
	public function setKeyPrefix($value)
156
	{
157
	    $this->_prefix=$value;
158
	}
159
 
160
	/**
161
	 * @param string micro timestamp when saving state occurs
162
	 * @return string a key that is unique per user request
163
	 */
164
	protected function calculateKey($timestamp)
165
	{
166
		return $this->getKeyPrefix().':'
167
			. $this->_page->getRequest()->getUserHostAddress()
168
			. $this->_page->getPagePath()
169
			. $timestamp;
170
	}
171
 
172
	/**
173
	 * Saves state in cache.
174
	 * @param mixed state to be stored
175
	 */
176
	public function save($state)
177
	{
178
		$data=serialize($state);
179
		$timestamp=(string)microtime(true);
180
		$key=$this->calculateKey($timestamp);
181
		$this->getCache()->add($key,$data,$this->_timeout);
182
		$this->_page->setClientState(TPageStateFormatter::serialize($this->_page,$timestamp));
183
	}
184
 
185
	/**
186
	 * Loads page state from cache.
187
	 * @return mixed the restored state
188
	 * @throws THttpException if page state is corrupted
189
	 */
190
	public function load()
191
	{
192
		if(($timestamp=TPageStateFormatter::unserialize($this->_page,$this->_page->getRequestClientState()))!==null)
193
		{
194
			$key=$this->calculateKey($timestamp);
195
			if(($data=$this->getCache()->get($key))!==false)
196
				return unserialize($data);
197
		}
198
		throw new THttpException(400,'cachepagestatepersister_pagestate_corrupted');
199
	}
200
}
201