| 1 |
lars |
1 |
<?php
|
|
|
2 |
/**
|
|
|
3 |
* TCache and cache dependency classes.
|
|
|
4 |
*
|
|
|
5 |
* @author Qiang Xue <qiang.xue@gmail.com>
|
|
|
6 |
* @link http://www.pradosoft.com/
|
|
|
7 |
* @copyright Copyright © 2005-2008 PradoSoft
|
|
|
8 |
* @license http://www.pradosoft.com/license/
|
|
|
9 |
* @version $Id: TCache.php 2513 2008-10-13 10:46:23Z carl $
|
|
|
10 |
* @package System.Caching
|
|
|
11 |
*/
|
|
|
12 |
|
|
|
13 |
Prado::using('System.Collections.TList');
|
|
|
14 |
|
|
|
15 |
/**
|
|
|
16 |
* TCache class
|
|
|
17 |
*
|
|
|
18 |
* TCache is the base class for cache classes with different cache storage implementation.
|
|
|
19 |
*
|
|
|
20 |
* TCache implements the interface {@link ICache} with the following methods,
|
|
|
21 |
* - {@link get} : retrieve the value with a key (if any) from cache
|
|
|
22 |
* - {@link set} : store the value with a key into cache
|
|
|
23 |
* - {@link add} : store the value only if cache does not have this key
|
|
|
24 |
* - {@link delete} : delete the value with the specified key from cache
|
|
|
25 |
* - {@link flush} : delete all values from cache
|
|
|
26 |
*
|
|
|
27 |
* Each value is associated with an expiration time. The {@link get} operation
|
|
|
28 |
* ensures that any expired value will not be returned. The expiration time by
|
|
|
29 |
* the number of seconds. A expiration time 0 represents never expire.
|
|
|
30 |
*
|
|
|
31 |
* By definition, cache does not ensure the existence of a value
|
|
|
32 |
* even if it never expires. Cache is not meant to be an persistent storage.
|
|
|
33 |
*
|
|
|
34 |
* Child classes must implement the following methods:
|
|
|
35 |
* - {@link getValue}
|
|
|
36 |
* - {@link setValue}
|
|
|
37 |
* - {@link addValue}
|
|
|
38 |
* - {@link deleteValue}
|
|
|
39 |
* and optionally {@link flush}
|
|
|
40 |
*
|
|
|
41 |
* Since version 3.1.2, TCache implements the ArrayAccess interface such that
|
|
|
42 |
* the cache acts as an array.
|
|
|
43 |
*
|
|
|
44 |
* @author Qiang Xue <qiang.xue@gmail.com>
|
|
|
45 |
* @version $Id: TCache.php 2513 2008-10-13 10:46:23Z carl $
|
|
|
46 |
* @package System.Caching
|
|
|
47 |
* @since 3.0
|
|
|
48 |
*/
|
|
|
49 |
abstract class TCache extends TModule implements ICache, ArrayAccess
|
|
|
50 |
{
|
|
|
51 |
private $_prefix=null;
|
|
|
52 |
private $_primary=true;
|
|
|
53 |
|
|
|
54 |
/**
|
|
|
55 |
* Initializes the cache module.
|
|
|
56 |
* This method initializes the cache key prefix and registers the cache module
|
|
|
57 |
* with the application if the cache is primary.
|
|
|
58 |
* @param TXmlElement the module configuration
|
|
|
59 |
*/
|
|
|
60 |
public function init($config)
|
|
|
61 |
{
|
|
|
62 |
if($this->_prefix===null)
|
|
|
63 |
$this->_prefix=$this->getApplication()->getUniqueID();
|
|
|
64 |
if($this->_primary)
|
|
|
65 |
{
|
|
|
66 |
if($this->getApplication()->getCache()===null)
|
|
|
67 |
$this->getApplication()->setCache($this);
|
|
|
68 |
else
|
|
|
69 |
throw new TConfigurationException('cache_primary_duplicated',get_class($this));
|
|
|
70 |
}
|
|
|
71 |
}
|
|
|
72 |
|
|
|
73 |
/**
|
|
|
74 |
* @return boolean whether this cache module is used as primary/system cache.
|
|
|
75 |
* A primary cache is used by PRADO core framework to cache data such as
|
|
|
76 |
* parsed templates, themes, etc.
|
|
|
77 |
*/
|
|
|
78 |
public function getPrimaryCache()
|
|
|
79 |
{
|
|
|
80 |
return $this->_primary;
|
|
|
81 |
}
|
|
|
82 |
|
|
|
83 |
/**
|
|
|
84 |
* @param boolean whether this cache module is used as primary/system cache. Defaults to false.
|
|
|
85 |
* @see getPrimaryCache
|
|
|
86 |
*/
|
|
|
87 |
public function setPrimaryCache($value)
|
|
|
88 |
{
|
|
|
89 |
$this->_primary=TPropertyValue::ensureBoolean($value);
|
|
|
90 |
}
|
|
|
91 |
|
|
|
92 |
/**
|
|
|
93 |
* @return string a unique prefix for the keys of cached values.
|
|
|
94 |
* If it is not explicitly set, it will take the value of {@link TApplication::getUniqueID}.
|
|
|
95 |
*/
|
|
|
96 |
public function getKeyPrefix()
|
|
|
97 |
{
|
|
|
98 |
return $this->_prefix;
|
|
|
99 |
}
|
|
|
100 |
|
|
|
101 |
/**
|
|
|
102 |
* @param string a unique prefix for the keys of cached values
|
|
|
103 |
*/
|
|
|
104 |
public function setKeyPrefix($value)
|
|
|
105 |
{
|
|
|
106 |
$this->_prefix=$value;
|
|
|
107 |
}
|
|
|
108 |
|
|
|
109 |
/**
|
|
|
110 |
* @param string a key identifying a value to be cached
|
|
|
111 |
* @return sring a key generated from the provided key which ensures the uniqueness across applications
|
|
|
112 |
*/
|
|
|
113 |
protected function generateUniqueKey($key)
|
|
|
114 |
{
|
|
|
115 |
return md5($this->_prefix.$key);
|
|
|
116 |
}
|
|
|
117 |
|
|
|
118 |
/**
|
|
|
119 |
* Retrieves a value from cache with a specified key.
|
|
|
120 |
* @param string a key identifying the cached value
|
|
|
121 |
* @return mixed the value stored in cache, false if the value is not in the cache or expired.
|
|
|
122 |
*/
|
|
|
123 |
public function get($id)
|
|
|
124 |
{
|
|
|
125 |
if(($value=$this->getValue($this->generateUniqueKey($id)))!==false)
|
|
|
126 |
{
|
|
|
127 |
$data=unserialize($value);
|
|
|
128 |
if(!is_array($data))
|
|
|
129 |
return false;
|
|
|
130 |
if(!($data[1] instanceof ICacheDependency) || !$data[1]->getHasChanged())
|
|
|
131 |
return $data[0];
|
|
|
132 |
}
|
|
|
133 |
return false;
|
|
|
134 |
}
|
|
|
135 |
|
|
|
136 |
/**
|
|
|
137 |
* Stores a value identified by a key into cache.
|
|
|
138 |
* If the cache already contains such a key, the existing value and
|
|
|
139 |
* expiration time will be replaced with the new ones. If the value is
|
|
|
140 |
* empty, the cache key will be deleted.
|
|
|
141 |
*
|
|
|
142 |
* @param string the key identifying the value to be cached
|
|
|
143 |
* @param mixed the value to be cached
|
|
|
144 |
* @param integer the number of seconds in which the cached value will expire. 0 means never expire.
|
|
|
145 |
* @param ICacheDependency dependency of the cached item. If the dependency changes, the item is labeled invalid.
|
|
|
146 |
* @return boolean true if the value is successfully stored into cache, false otherwise
|
|
|
147 |
*/
|
|
|
148 |
public function set($id,$value,$expire=0,$dependency=null)
|
|
|
149 |
{
|
|
|
150 |
if(empty($value) && $expire === 0)
|
|
|
151 |
$this->delete($id);
|
|
|
152 |
else
|
|
|
153 |
{
|
|
|
154 |
$data=array($value,$dependency);
|
|
|
155 |
return $this->setValue($this->generateUniqueKey($id),serialize($data),$expire);
|
|
|
156 |
}
|
|
|
157 |
}
|
|
|
158 |
|
|
|
159 |
/**
|
|
|
160 |
* Stores a value identified by a key into cache if the cache does not contain this key.
|
|
|
161 |
* Nothing will be done if the cache already contains the key or if value is empty.
|
|
|
162 |
* @param string the key identifying the value to be cached
|
|
|
163 |
* @param mixed the value to be cached
|
|
|
164 |
* @param integer the number of seconds in which the cached value will expire. 0 means never expire.
|
|
|
165 |
* @param ICacheDependency dependency of the cached item. If the dependency changes, the item is labeled invalid.
|
|
|
166 |
* @return boolean true if the value is successfully stored into cache, false otherwise
|
|
|
167 |
*/
|
|
|
168 |
public function add($id,$value,$expire=0,$dependency=null)
|
|
|
169 |
{
|
|
|
170 |
if(empty($value) && $expire === 0)
|
|
|
171 |
return false;
|
|
|
172 |
$data=array($value,$dependency);
|
|
|
173 |
return $this->addValue($this->generateUniqueKey($id),serialize($data),$expire);
|
|
|
174 |
}
|
|
|
175 |
|
|
|
176 |
/**
|
|
|
177 |
* Deletes a value with the specified key from cache
|
|
|
178 |
* @param string the key of the value to be deleted
|
|
|
179 |
* @return boolean if no error happens during deletion
|
|
|
180 |
*/
|
|
|
181 |
public function delete($id)
|
|
|
182 |
{
|
|
|
183 |
return $this->deleteValue($this->generateUniqueKey($id));
|
|
|
184 |
}
|
|
|
185 |
|
|
|
186 |
/**
|
|
|
187 |
* Deletes all values from cache.
|
|
|
188 |
* Be careful of performing this operation if the cache is shared by multiple applications.
|
|
|
189 |
* Child classes may implement this method to realize the flush operation.
|
|
|
190 |
* @throws TNotSupportedException if this method is not overridden by child classes
|
|
|
191 |
*/
|
|
|
192 |
public function flush()
|
|
|
193 |
{
|
|
|
194 |
throw new TNotSupportedException('cache_flush_unsupported');
|
|
|
195 |
}
|
|
|
196 |
|
|
|
197 |
/**
|
|
|
198 |
* Retrieves a value from cache with a specified key.
|
|
|
199 |
* This method should be implemented by child classes to store the data
|
|
|
200 |
* in specific cache storage. The uniqueness and dependency are handled
|
|
|
201 |
* in {@link get()} already. So only the implementation of data retrieval
|
|
|
202 |
* is needed.
|
|
|
203 |
* @param string a unique key identifying the cached value
|
|
|
204 |
* @return string the value stored in cache, false if the value is not in the cache or expired.
|
|
|
205 |
*/
|
|
|
206 |
abstract protected function getValue($key);
|
|
|
207 |
|
|
|
208 |
/**
|
|
|
209 |
* Stores a value identified by a key in cache.
|
|
|
210 |
* This method should be implemented by child classes to store the data
|
|
|
211 |
* in specific cache storage. The uniqueness and dependency are handled
|
|
|
212 |
* in {@link set()} already. So only the implementation of data storage
|
|
|
213 |
* is needed.
|
|
|
214 |
*
|
|
|
215 |
* @param string the key identifying the value to be cached
|
|
|
216 |
* @param string the value to be cached
|
|
|
217 |
* @param integer the number of seconds in which the cached value will expire. 0 means never expire.
|
|
|
218 |
* @return boolean true if the value is successfully stored into cache, false otherwise
|
|
|
219 |
*/
|
|
|
220 |
abstract protected function setValue($key,$value,$expire);
|
|
|
221 |
|
|
|
222 |
/**
|
|
|
223 |
* Stores a value identified by a key into cache if the cache does not contain this key.
|
|
|
224 |
* This method should be implemented by child classes to store the data
|
|
|
225 |
* in specific cache storage. The uniqueness and dependency are handled
|
|
|
226 |
* in {@link add()} already. So only the implementation of data storage
|
|
|
227 |
* is needed.
|
|
|
228 |
*
|
|
|
229 |
* @param string the key identifying the value to be cached
|
|
|
230 |
* @param string the value to be cached
|
|
|
231 |
* @param integer the number of seconds in which the cached value will expire. 0 means never expire.
|
|
|
232 |
* @return boolean true if the value is successfully stored into cache, false otherwise
|
|
|
233 |
*/
|
|
|
234 |
abstract protected function addValue($key,$value,$expire);
|
|
|
235 |
|
|
|
236 |
/**
|
|
|
237 |
* Deletes a value with the specified key from cache
|
|
|
238 |
* This method should be implemented by child classes to delete the data from actual cache storage.
|
|
|
239 |
* @param string the key of the value to be deleted
|
|
|
240 |
* @return boolean if no error happens during deletion
|
|
|
241 |
*/
|
|
|
242 |
abstract protected function deleteValue($key);
|
|
|
243 |
|
|
|
244 |
/**
|
|
|
245 |
* Returns whether there is a cache entry with a specified key.
|
|
|
246 |
* This method is required by the interface ArrayAccess.
|
|
|
247 |
* @param string a key identifying the cached value
|
|
|
248 |
* @return boolean
|
|
|
249 |
*/
|
|
|
250 |
public function offsetExists($id)
|
|
|
251 |
{
|
|
|
252 |
return $this->get($id) !== false;
|
|
|
253 |
}
|
|
|
254 |
|
|
|
255 |
/*
|
|
|
256 |
* Retrieves the value from cache with a specified key.
|
|
|
257 |
* This method is required by the interface ArrayAccess.
|
|
|
258 |
* @param string a key identifying the cached value
|
|
|
259 |
* @return mixed the value stored in cache, false if the value is not in the cache or expired.
|
|
|
260 |
*/
|
|
|
261 |
public function offsetGet($id)
|
|
|
262 |
{
|
|
|
263 |
return $this->get($id);
|
|
|
264 |
}
|
|
|
265 |
|
|
|
266 |
/*
|
|
|
267 |
* Stores the value identified by a key into cache.
|
|
|
268 |
* If the cache already contains such a key, the existing value will be
|
|
|
269 |
* replaced with the new ones. To add expiration and dependencies, use the set() method.
|
|
|
270 |
* This method is required by the interface ArrayAccess.
|
|
|
271 |
* @param string the key identifying the value to be cached
|
|
|
272 |
* @param mixed the value to be cached
|
|
|
273 |
*/
|
|
|
274 |
public function offsetSet($id, $value)
|
|
|
275 |
{
|
|
|
276 |
$this->set($id, $value);
|
|
|
277 |
}
|
|
|
278 |
|
|
|
279 |
/*
|
|
|
280 |
* Deletes the value with the specified key from cache
|
|
|
281 |
* This method is required by the interface ArrayAccess.
|
|
|
282 |
* @param string the key of the value to be deleted
|
|
|
283 |
* @return boolean if no error happens during deletion
|
|
|
284 |
*/
|
|
|
285 |
public function offsetUnset($id)
|
|
|
286 |
{
|
|
|
287 |
$this->delete($id);
|
|
|
288 |
}
|
|
|
289 |
}
|
|
|
290 |
|
|
|
291 |
|
|
|
292 |
/**
|
|
|
293 |
* TCacheDependency class.
|
|
|
294 |
*
|
|
|
295 |
* TCacheDependency is the base class implementing {@link ICacheDependency} interface.
|
|
|
296 |
* Descendant classes must implement {@link getHasChanged()} to provide
|
|
|
297 |
* actual dependency checking logic.
|
|
|
298 |
*
|
|
|
299 |
* The property value of {@link getHasChanged HasChanged} tells whether
|
|
|
300 |
* the dependency is changed or not.
|
|
|
301 |
*
|
|
|
302 |
* You may disable the dependency checking by setting {@link setEnabled Enabled}
|
|
|
303 |
* to false.
|
|
|
304 |
*
|
|
|
305 |
* Note, since the dependency objects often need to be serialized so that
|
|
|
306 |
* they can persist across requests, you may need to implement __sleep() and
|
|
|
307 |
* __wakeup() if the dependency objects contain resource handles which are
|
|
|
308 |
* not serializable.
|
|
|
309 |
*
|
|
|
310 |
* Currently, the following dependency classes are provided in the PRADO release:
|
|
|
311 |
* - {@link TFileCacheDependency}: checks whether a file is changed or not
|
|
|
312 |
* - {@link TDirectoryCacheDependency}: checks whether a directory is changed or not
|
|
|
313 |
* - {@link TGlobalStateCacheDependency}: checks whether a global state is changed or not
|
|
|
314 |
* - {@link TChainedCacheDependency}: checks whether any of a list of dependencies is changed or not
|
|
|
315 |
*
|
|
|
316 |
* @author Qiang Xue <qiang.xue@gmail.com>
|
|
|
317 |
* @version $Id: TCache.php 2513 2008-10-13 10:46:23Z carl $
|
|
|
318 |
* @package System.Caching
|
|
|
319 |
* @since 3.1.0
|
|
|
320 |
*/
|
|
|
321 |
abstract class TCacheDependency extends TComponent implements ICacheDependency
|
|
|
322 |
{
|
|
|
323 |
}
|
|
|
324 |
|
|
|
325 |
|
|
|
326 |
/**
|
|
|
327 |
* TFileCacheDependency class.
|
|
|
328 |
*
|
|
|
329 |
* TFileCacheDependency performs dependency checking based on the
|
|
|
330 |
* last modification time of the file specified via {@link setFileName FileName}.
|
|
|
331 |
* The dependency is reported as unchanged if and only if the file's
|
|
|
332 |
* last modification time remains unchanged.
|
|
|
333 |
*
|
|
|
334 |
* @author Qiang Xue <qiang.xue@gmail.com>
|
|
|
335 |
* @version $Id: TCache.php 2513 2008-10-13 10:46:23Z carl $
|
|
|
336 |
* @package System.Caching
|
|
|
337 |
* @since 3.1.0
|
|
|
338 |
*/
|
|
|
339 |
class TFileCacheDependency extends TCacheDependency
|
|
|
340 |
{
|
|
|
341 |
private $_fileName;
|
|
|
342 |
private $_timestamp;
|
|
|
343 |
|
|
|
344 |
/**
|
|
|
345 |
* Constructor.
|
|
|
346 |
* @param string name of the file whose change is to be checked.
|
|
|
347 |
*/
|
|
|
348 |
public function __construct($fileName)
|
|
|
349 |
{
|
|
|
350 |
$this->setFileName($fileName);
|
|
|
351 |
}
|
|
|
352 |
|
|
|
353 |
/**
|
|
|
354 |
* @return string the name of the file whose change is to be checked
|
|
|
355 |
*/
|
|
|
356 |
public function getFileName()
|
|
|
357 |
{
|
|
|
358 |
return $this->_fileName;
|
|
|
359 |
}
|
|
|
360 |
|
|
|
361 |
/**
|
|
|
362 |
* @param string the name of the file whose change is to be checked
|
|
|
363 |
*/
|
|
|
364 |
public function setFileName($value)
|
|
|
365 |
{
|
|
|
366 |
$this->_fileName=$value;
|
|
|
367 |
$this->_timestamp=@filemtime($value);
|
|
|
368 |
}
|
|
|
369 |
|
|
|
370 |
/**
|
|
|
371 |
* @return int the last modification time of the file
|
|
|
372 |
*/
|
|
|
373 |
public function getTimestamp()
|
|
|
374 |
{
|
|
|
375 |
return $this->_timestamp;
|
|
|
376 |
}
|
|
|
377 |
|
|
|
378 |
/**
|
|
|
379 |
* Performs the actual dependency checking.
|
|
|
380 |
* This method returns true if the last modification time of the file is changed.
|
|
|
381 |
* @return boolean whether the dependency is changed or not.
|
|
|
382 |
*/
|
|
|
383 |
public function getHasChanged()
|
|
|
384 |
{
|
|
|
385 |
return @filemtime($this->_fileName)!==$this->_timestamp;
|
|
|
386 |
}
|
|
|
387 |
}
|
|
|
388 |
|
|
|
389 |
/**
|
|
|
390 |
* TDirectoryCacheDependency class.
|
|
|
391 |
*
|
|
|
392 |
* TDirectoryCacheDependency performs dependency checking based on the
|
|
|
393 |
* modification time of the files contained in the specified directory.
|
|
|
394 |
* The directory being checked is specified via {@link setDirectory Directory}.
|
|
|
395 |
*
|
|
|
396 |
* By default, all files under the specified directory and subdirectories
|
|
|
397 |
* will be checked. If the last modification time of any of them is changed
|
|
|
398 |
* or if different number of files are contained in a directory, the dependency
|
|
|
399 |
* is reported as changed. By specifying {@link setRecursiveCheck RecursiveCheck}
|
|
|
400 |
* and {@link setRecursiveLevel RecursiveLevel}, one can limit the checking
|
|
|
401 |
* to a certain depth of the subdirectories.
|
|
|
402 |
*
|
|
|
403 |
* @author Qiang Xue <qiang.xue@gmail.com>
|
|
|
404 |
* @version $Id: TCache.php 2513 2008-10-13 10:46:23Z carl $
|
|
|
405 |
* @package System.Caching
|
|
|
406 |
* @since 3.1.0
|
|
|
407 |
*/
|
|
|
408 |
class TDirectoryCacheDependency extends TCacheDependency
|
|
|
409 |
{
|
|
|
410 |
private $_recursiveCheck=true;
|
|
|
411 |
private $_recursiveLevel=-1;
|
|
|
412 |
private $_timestamps;
|
|
|
413 |
private $_directory;
|
|
|
414 |
|
|
|
415 |
/**
|
|
|
416 |
* Constructor.
|
|
|
417 |
* @param string the directory to be checked
|
|
|
418 |
*/
|
|
|
419 |
public function __construct($directory)
|
|
|
420 |
{
|
|
|
421 |
$this->setDirectory($directory);
|
|
|
422 |
}
|
|
|
423 |
|
|
|
424 |
/**
|
|
|
425 |
* @return string the directory to be checked
|
|
|
426 |
*/
|
|
|
427 |
public function getDirectory()
|
|
|
428 |
{
|
|
|
429 |
return $this->_directory;
|
|
|
430 |
}
|
|
|
431 |
|
|
|
432 |
/**
|
|
|
433 |
* @param string the directory to be checked
|
|
|
434 |
* @throws TInvalidDataValueException if the directory does not exist
|
|
|
435 |
*/
|
|
|
436 |
public function setDirectory($directory)
|
|
|
437 |
{
|
|
|
438 |
if(($path=realpath($directory))===false || !is_dir($path))
|
|
|
439 |
throw new TInvalidDataValueException('directorycachedependency_directory_invalid',$directory);
|
|
|
440 |
$this->_directory=$path;
|
|
|
441 |
$this->_timestamps=$this->generateTimestamps($path);
|
|
|
442 |
}
|
|
|
443 |
|
|
|
444 |
/**
|
|
|
445 |
* @return boolean whether the subdirectories of the directory will also be checked.
|
|
|
446 |
* It defaults to true.
|
|
|
447 |
*/
|
|
|
448 |
public function getRecursiveCheck()
|
|
|
449 |
{
|
|
|
450 |
return $this->_recursiveCheck;
|
|
|
451 |
}
|
|
|
452 |
|
|
|
453 |
/**
|
|
|
454 |
* @param boolean whether the subdirectories of the directory will also be checked.
|
|
|
455 |
*/
|
|
|
456 |
public function setRecursiveCheck($value)
|
|
|
457 |
{
|
|
|
458 |
$this->_recursiveCheck=TPropertyValue::ensureBoolean($value);
|
|
|
459 |
}
|
|
|
460 |
|
|
|
461 |
/**
|
|
|
462 |
* @return int the depth of the subdirectories to be checked.
|
|
|
463 |
* It defaults to -1, meaning unlimited depth.
|
|
|
464 |
*/
|
|
|
465 |
public function getRecursiveLevel()
|
|
|
466 |
{
|
|
|
467 |
return $this->_recursiveLevel;
|
|
|
468 |
}
|
|
|
469 |
|
|
|
470 |
/**
|
|
|
471 |
* Sets a value indicating the depth of the subdirectories to be checked.
|
|
|
472 |
* This is meaningful only when {@link getRecursiveCheck RecursiveCheck}
|
|
|
473 |
* is true.
|
|
|
474 |
* @param int the depth of the subdirectories to be checked.
|
|
|
475 |
* If the value is less than 0, it means unlimited depth.
|
|
|
476 |
* If the value is 0, it means checking the files directly under the specified directory.
|
|
|
477 |
*/
|
|
|
478 |
public function setRecursiveLevel($value)
|
|
|
479 |
{
|
|
|
480 |
$this->_recursiveLevel=TPropertyValue::ensureInteger($value);
|
|
|
481 |
}
|
|
|
482 |
|
|
|
483 |
/**
|
|
|
484 |
* Performs the actual dependency checking.
|
|
|
485 |
* This method returns true if the directory is changed.
|
|
|
486 |
* @return boolean whether the dependency is changed or not.
|
|
|
487 |
*/
|
|
|
488 |
public function getHasChanged()
|
|
|
489 |
{
|
|
|
490 |
return $this->generateTimestamps($this->_directory)!=$this->_timestamps;
|
|
|
491 |
}
|
|
|
492 |
|
|
|
493 |
/**
|
|
|
494 |
* Checks to see if the file should be checked for dependency.
|
|
|
495 |
* This method is invoked when dependency of the whole directory is being checked.
|
|
|
496 |
* By default, it always returns true, meaning the file should be checked.
|
|
|
497 |
* You may override this method to check only certain files.
|
|
|
498 |
* @param string the name of the file that may be checked for dependency.
|
|
|
499 |
* @return boolean whether this file should be checked.
|
|
|
500 |
*/
|
|
|
501 |
protected function validateFile($fileName)
|
|
|
502 |
{
|
|
|
503 |
return true;
|
|
|
504 |
}
|
|
|
505 |
|
|
|
506 |
/**
|
|
|
507 |
* Checks to see if the specified subdirectory should be checked for dependency.
|
|
|
508 |
* This method is invoked when dependency of the whole directory is being checked.
|
|
|
509 |
* By default, it always returns true, meaning the subdirectory should be checked.
|
|
|
510 |
* You may override this method to check only certain subdirectories.
|
|
|
511 |
* @param string the name of the subdirectory that may be checked for dependency.
|
|
|
512 |
* @return boolean whether this subdirectory should be checked.
|
|
|
513 |
*/
|
|
|
514 |
protected function validateDirectory($directory)
|
|
|
515 |
{
|
|
|
516 |
return true;
|
|
|
517 |
}
|
|
|
518 |
|
|
|
519 |
/**
|
|
|
520 |
* Determines the last modification time for files under the directory.
|
|
|
521 |
* This method may go recursively into subdirectories if
|
|
|
522 |
* {@link setRecursiveCheck RecursiveCheck} is set true.
|
|
|
523 |
* @param string the directory name
|
|
|
524 |
* @param int level of the recursion
|
|
|
525 |
* @return array list of file modification time indexed by the file path
|
|
|
526 |
*/
|
|
|
527 |
protected function generateTimestamps($directory,$level=0)
|
|
|
528 |
{
|
|
|
529 |
if(($dir=opendir($directory))===false)
|
|
|
530 |
throw new TIOException('directorycachedependency_directory_invalid',$directory);
|
|
|
531 |
$timestamps=array();
|
|
|
532 |
while(($file=readdir($dir))!==false)
|
|
|
533 |
{
|
|
|
534 |
$path=$directory.DIRECTORY_SEPARATOR.$file;
|
|
|
535 |
if($file==='.' || $file==='..')
|
|
|
536 |
continue;
|
|
|
537 |
else if(is_dir($path))
|
|
|
538 |
{
|
|
|
539 |
if(($this->_recursiveLevel<0 || $level<$this->_recursiveLevel) && $this->validateDirectory($path))
|
|
|
540 |
$timestamps=array_merge($this->generateTimestamps($path,$level+1));
|
|
|
541 |
}
|
|
|
542 |
else if($this->validateFile($path))
|
|
|
543 |
$timestamps[$path]=filemtime($path);
|
|
|
544 |
}
|
|
|
545 |
closedir($dir);
|
|
|
546 |
return $timestamps;
|
|
|
547 |
}
|
|
|
548 |
}
|
|
|
549 |
|
|
|
550 |
|
|
|
551 |
/**
|
|
|
552 |
* TGlobalStateCacheDependency class.
|
|
|
553 |
*
|
|
|
554 |
* TGlobalStateCacheDependency checks if a global state is changed or not.
|
|
|
555 |
* If the global state is changed, the dependency is reported as changed.
|
|
|
556 |
* To specify which global state this dependency should check with,
|
|
|
557 |
* set {@link setStateName StateName} to the name of the global state.
|
|
|
558 |
*
|
|
|
559 |
* @author Qiang Xue <qiang.xue@gmail.com>
|
|
|
560 |
* @version $Id: TCache.php 2513 2008-10-13 10:46:23Z carl $
|
|
|
561 |
* @package System.Caching
|
|
|
562 |
* @since 3.1.0
|
|
|
563 |
*/
|
|
|
564 |
class TGlobalStateCacheDependency extends TCacheDependency
|
|
|
565 |
{
|
|
|
566 |
private $_stateName;
|
|
|
567 |
private $_stateValue;
|
|
|
568 |
|
|
|
569 |
/**
|
|
|
570 |
* Constructor.
|
|
|
571 |
* @param string the name of the global state
|
|
|
572 |
*/
|
|
|
573 |
public function __construct($name)
|
|
|
574 |
{
|
|
|
575 |
$this->setStateName($name);
|
|
|
576 |
}
|
|
|
577 |
|
|
|
578 |
/**
|
|
|
579 |
* @return string the name of the global state
|
|
|
580 |
*/
|
|
|
581 |
public function getStateName()
|
|
|
582 |
{
|
|
|
583 |
return $this->_stateName;
|
|
|
584 |
}
|
|
|
585 |
|
|
|
586 |
/**
|
|
|
587 |
* @param string the name of the global state
|
|
|
588 |
* @see TApplication::setGlobalState
|
|
|
589 |
*/
|
|
|
590 |
public function setStateName($value)
|
|
|
591 |
{
|
|
|
592 |
$this->_stateName=$value;
|
|
|
593 |
$this->_stateValue=Prado::getApplication()->getGlobalState($value);
|
|
|
594 |
}
|
|
|
595 |
|
|
|
596 |
/**
|
|
|
597 |
* Performs the actual dependency checking.
|
|
|
598 |
* This method returns true if the specified global state is changed.
|
|
|
599 |
* @return boolean whether the dependency is changed or not.
|
|
|
600 |
*/
|
|
|
601 |
public function getHasChanged()
|
|
|
602 |
{
|
|
|
603 |
return $this->_stateValue!==Prado::getApplication()->getGlobalState($this->_stateName);
|
|
|
604 |
}
|
|
|
605 |
}
|
|
|
606 |
|
|
|
607 |
|
|
|
608 |
/**
|
|
|
609 |
* TChainedCacheDependency class.
|
|
|
610 |
*
|
|
|
611 |
* TChainedCacheDependency represents a list of cache dependency objects
|
|
|
612 |
* and performs the dependency checking based on the checking results of
|
|
|
613 |
* these objects. If any of them reports a dependency change, TChainedCacheDependency
|
|
|
614 |
* will return true for the checking.
|
|
|
615 |
*
|
|
|
616 |
* To add dependencies to TChainedCacheDependency, use {@link getDependencies Dependencies}
|
|
|
617 |
* which gives a {@link TCacheDependencyList} instance and can be used like an array
|
|
|
618 |
* (see {@link TList} for more details}).
|
|
|
619 |
*
|
|
|
620 |
* @author Qiang Xue <qiang.xue@gmail.com>
|
|
|
621 |
* @version $Id: TCache.php 2513 2008-10-13 10:46:23Z carl $
|
|
|
622 |
* @package System.Caching
|
|
|
623 |
* @since 3.1.0
|
|
|
624 |
*/
|
|
|
625 |
class TChainedCacheDependency extends TCacheDependency
|
|
|
626 |
{
|
|
|
627 |
private $_dependencies=null;
|
|
|
628 |
|
|
|
629 |
/**
|
|
|
630 |
* @return TCacheDependencyList list of dependency objects
|
|
|
631 |
*/
|
|
|
632 |
public function getDependencies()
|
|
|
633 |
{
|
|
|
634 |
if($this->_dependencies===null)
|
|
|
635 |
$this->_dependencies=new TCacheDependencyList;
|
|
|
636 |
return $this->_dependencies;
|
|
|
637 |
}
|
|
|
638 |
|
|
|
639 |
/**
|
|
|
640 |
* Performs the actual dependency checking.
|
|
|
641 |
* This method returns true if any of the dependency objects
|
|
|
642 |
* reports a dependency change.
|
|
|
643 |
* @return boolean whether the dependency is changed or not.
|
|
|
644 |
*/
|
|
|
645 |
public function getHasChanged()
|
|
|
646 |
{
|
|
|
647 |
if($this->_dependencies!==null)
|
|
|
648 |
{
|
|
|
649 |
foreach($this->_dependencies as $dependency)
|
|
|
650 |
if($dependency->getHasChanged())
|
|
|
651 |
return true;
|
|
|
652 |
}
|
|
|
653 |
return false;
|
|
|
654 |
}
|
|
|
655 |
}
|
|
|
656 |
|
|
|
657 |
|
|
|
658 |
/**
|
|
|
659 |
* TApplicationStateCacheDependency class.
|
|
|
660 |
*
|
|
|
661 |
* TApplicationStateCacheDependency performs dependency checking based on
|
|
|
662 |
* the mode of the currently running PRADO application.
|
|
|
663 |
* The dependency is reportedly as unchanged if and only if the application
|
|
|
664 |
* is running in performance mode.
|
|
|
665 |
*
|
|
|
666 |
* You may chain this dependency together with other dependencies
|
|
|
667 |
* so that only when the application is not in performance mode the other dependencies
|
|
|
668 |
* will be checked.
|
|
|
669 |
*
|
|
|
670 |
* @author Qiang Xue <qiang.xue@gmail.com>
|
|
|
671 |
* @version $Id: TCache.php 2513 2008-10-13 10:46:23Z carl $
|
|
|
672 |
* @package System.Caching
|
|
|
673 |
* @since 3.1.0
|
|
|
674 |
*/
|
|
|
675 |
class TApplicationStateCacheDependency extends TCacheDependency
|
|
|
676 |
{
|
|
|
677 |
/**
|
|
|
678 |
* Performs the actual dependency checking.
|
|
|
679 |
* This method returns true if the currently running application is not in performance mode.
|
|
|
680 |
* @return boolean whether the dependency is changed or not.
|
|
|
681 |
*/
|
|
|
682 |
public function getHasChanged()
|
|
|
683 |
{
|
|
|
684 |
return Prado::getApplication()->getMode()!==TApplicationMode::Performance;
|
|
|
685 |
}
|
|
|
686 |
}
|
|
|
687 |
|
|
|
688 |
/**
|
|
|
689 |
* TCacheDependencyList class.
|
|
|
690 |
*
|
|
|
691 |
* TCacheDependencyList represents a list of cache dependency objects.
|
|
|
692 |
* Only objects implementing {@link ICacheDependency} can be added into this list.
|
|
|
693 |
*
|
|
|
694 |
* TCacheDependencyList can be used like an array. See {@link TList}
|
|
|
695 |
* for more details.
|
|
|
696 |
*
|
|
|
697 |
* @author Qiang Xue <qiang.xue@gmail.com>
|
|
|
698 |
* @version $Id: TCache.php 2513 2008-10-13 10:46:23Z carl $
|
|
|
699 |
* @package System.Caching
|
|
|
700 |
* @since 3.1.0
|
|
|
701 |
*/
|
|
|
702 |
class TCacheDependencyList extends TList
|
|
|
703 |
{
|
|
|
704 |
/**
|
|
|
705 |
* Inserts an item at the specified position.
|
|
|
706 |
* This overrides the parent implementation by performing additional type checking
|
|
|
707 |
* for each newly added item.
|
|
|
708 |
* @param integer the specified position.
|
|
|
709 |
* @param mixed new item
|
|
|
710 |
* @throws TInvalidDataTypeException if the item to be inserted is not a dependency instance
|
|
|
711 |
*/
|
|
|
712 |
public function insertAt($index,$item)
|
|
|
713 |
{
|
|
|
714 |
if($item instanceof ICacheDependency)
|
|
|
715 |
parent::insertAt($index,$item);
|
|
|
716 |
else
|
|
|
717 |
throw new TInvalidDataTypeException('cachedependencylist_cachedependency_required');
|
|
|
718 |
}
|
|
|
719 |
}
|
|
|
720 |
|
|
|
721 |
?>
|