]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/pear/Cache.php
private --> protected
[SourceForge/phpwiki.git] / lib / pear / Cache.php
1 <?php
2 // +----------------------------------------------------------------------+
3 // | PHP Version 4                                                        |
4 // +----------------------------------------------------------------------+
5 // | Copyright (c) 1997, 1998, 1999, 2000, 2001 The PHP Group             |
6 // +----------------------------------------------------------------------+
7 // | This source file is subject to version 2.0 of the PHP license,       |
8 // | that is bundled with this package in the file LICENSE, and is        |
9 // | available at through the world-wide-web at                           |
10 // | http://www.php.net/license/2_02.txt.                                 |
11 // | If you did not receive a copy of the PHP license and are unable to   |
12 // | obtain it through the world-wide-web, please send a note to          |
13 // | license@php.net so we can mail you a copy immediately.               |
14 // +----------------------------------------------------------------------+
15 // | Authors: Ulf Wendel <ulf.wendel@phpdoc.de>                           |
16 // |          Sebastian Bergmann <sb@sebastian-bergmann.de>               |
17 // +----------------------------------------------------------------------+
18 //
19
20 require_once 'PEAR.php';
21 require_once 'Cache/Error.php';
22
23 /**
24 * Cache is a base class for cache implementations.
25 *
26 * The pear cache module is a generic data cache which can be used to
27 * cache script runs. The idea behind the cache is quite simple. If you have
28 * the same input parameters for whatever tasks/algorithm you use you'll
29 * usually get the same output. So why not caching templates, functions calls,
30 * graphic generation etc. Caching certain actions e.g. XSLT tranformations
31 * saves you lots of time.
32 *
33 * The design of the cache reminds of PHPLibs session implementation. A
34 * (PHPLib: session) controller uses storage container (PHPLib: ct_*.inc) to save
35 * certain data (PHPLib: session data). In contrast to the session stuff it's up to
36 * you to generate an ID for the data to cache. If you're using the output cache
37 * you might use the script name as a seed for cache::generateID(), if your using the
38 * function cache you'd use an array with all function parameters.
39 *
40 * Usage example of the generic data cache:
41 *
42 * require_once('Cache.php');
43 *
44 * $cache = new Cache('file', array('cache_dir' => 'cache/') );
45 * $id = $cache->generateID('testentry');
46 *
47 * if ($data = $cache->get($id)) {
48 *    print "Cache hit.<br>Data: $data";
49 *
50 * } else {
51 *   $data = 'data of any kind';
52 *   $cache->save($id, $data);
53 *   print 'Cache miss.<br>';
54 * }
55 *
56 * WARNING: No File/DB-Table-Row locking is implemented yet,
57 *          it's possible, that you get corrupted data-entries under
58 *          bad circumstances  (especially with the file container)
59 *
60 * @author   Ulf Wendel <ulf.wendel@phpdoc.de>
61 * @version
62 * @package  Cache
63 * @access   public
64 */
65 class Cache extends PEAR {
66
67     /**
68     * Enables / disables caching.
69     *
70     * TODO: Add explanation what this is good for.
71     *
72     * @var      boolean
73     * @access   private
74     */
75     var $caching = true;
76
77     /**
78     * Garbage collection: probability in seconds
79     *
80     * If set to a value above 0 a garbage collection will
81     * flush all cache entries older than the specified number
82     * of seconds.
83     *
84     * @var      integer
85     * @see      $gc_probability, $gc_maxlifetime
86     * @access   public
87     */
88     var $gc_time  = 1;
89
90     /**
91     * Garbage collection: probability in percent
92     *
93     * TODO: Add an explanation.
94     *
95     * @var      integer     0 => never
96     * @see      $gc_time, $gc_maxlifetime
97     * @access   public
98     */
99     var $gc_probability = 1;
100
101     /**
102     * Garbage collection: delete all entries not use for n seconds.
103     *
104     * Default is one day, 60 * 60 * 24 = 86400 seconds.
105     *
106     * @var  integer
107     * @see  $gc_probability, $gc_time
108     */
109     var $gc_maxlifetime = 86400;
110
111     /**
112     * Storage container object.
113     *
114     * @var  object Cache_Container
115     */
116     var $container;
117
118     //
119     // public methods
120     //
121
122     /**
123     *
124     * @param    string  Name of container class
125     * @param    array   Array with container class options
126     */
127     function Cache($container, $container_options = '')
128     {
129         $this->PEAR();
130         $container = strtolower($container);
131         $container_class = 'Cache_Container_' . $container;
132         $container_classfile = 'Cache/Container/' . $container . '.php';
133
134         include_once $container_classfile;
135         $this->container = new $container_class($container_options);
136     }
137
138     //deconstructor
139     function _Cache()
140     {
141         $this->garbageCollection();
142     }
143
144     /**
145      * Returns the current caching state.
146      *
147      * @return boolean The current caching state.
148      * @access  public
149      */
150     function getCaching()
151     {
152         return ($this->caching);
153     }
154
155     /**
156      * Enables or disables caching.
157      *
158      * @param   boolean     The new caching state.
159      * @access  public
160      */
161     function setCaching($state)
162     {
163         $this->caching = $state;
164     }
165
166     /**
167     * Returns the requested dataset it if exists and is not expired
168     *
169     * @param    string  dataset ID
170     * @param    string  cache group
171     * @return   mixed   cached data or NULL on failure
172     * @access   public
173     */
174     function get($id, $group = 'default') {
175         if (!$this->caching)
176             return '';
177
178         if ($this->isCached($id, $group) && !$this->isExpired($id, $group))
179             return $this->load($id, $group);
180
181         return NULL;
182     } // end func get
183
184     /**
185     * Stores the given data in the cache.
186     *
187     * @param    string  dataset ID used as cache identifier
188     * @param    mixed   data to cache
189     * @param    integer lifetime of the cached data in seconds - 0 for endless
190     * @param    string  cache group
191     * @return   boolean
192     * @access   public
193     */
194     function save($id, $data, $expires = 0, $group = 'default') {
195         if (!$this->caching)
196             return true;
197
198         return $this->extSave($id, $data, '',$expires, $group);
199     } // end func save
200
201     /**
202     * Stores a dataset without additional userdefined data.
203     *
204     * @param    string  dataset ID
205     * @param    mixed   data to store
206     * @param    string  additional userdefined data
207     * @param    mixed   userdefined expire date
208     * @param    string  cache group
209     * @return   boolean
210     * @throws   Cache_Error
211     * @access   public
212     * @see      getUserdata()
213     */
214     function extSave($id, $cachedata, $userdata, $expires = 0, $group = 'default') {
215         if (!$this->caching)
216             return true;
217
218         return $this->container->save($id, $cachedata, $expires, $group, $userdata);
219     } // end func extSave
220
221     /**
222     * Loads the given ID from the cache.
223     *
224     * @param    string  dataset ID
225     * @param    string  cache group
226     * @return   mixed   cached data or NULL on failure
227     * @access   public
228     */
229     function load($id, $group = 'default') {
230         if (!$this->caching)
231             return '';
232
233         return $this->container->load($id, $group);
234     } // end func load
235
236     /**
237     * Returns the userdata field of a cached data set.
238     *
239     * @param    string  dataset ID
240     * @param    string  cache group
241     * @return   string  userdata
242     * @access   public
243     * @see      extSave()
244     */
245     function getUserdata($id, $group = 'default') {
246         if (!$this->caching)
247             return '';
248
249         return $this->container->getUserdata($id, $group);
250     } // end func getUserdata
251
252     /**
253     * Removes the specified dataset from the cache.
254     *
255     * @param    string  dataset ID
256     * @param    string  cache group
257     * @return   boolean
258     * @access   public
259     */
260     function remove($id, $group = 'default') {
261         if (!$this->caching)
262             return true;
263
264         return $this->container->remove($id, $group);
265     } // end func remove
266
267     /**
268     * Flushes the cache - removes all data from it
269     *
270     * @param    string  cache group, if empty all groups will be flashed
271     * @return   integer number of removed datasets
272     */
273     function flush($group = 'default') {
274         if (!$this->caching)
275             return true;
276
277         return $this->container->flush($group);
278     } // end func flush
279
280     /**
281     * Checks if a dataset exists.
282     *
283     * Note: this does not say that the cached data is not expired!
284     *
285     * @param    string  dataset ID
286     * @param    string  cache group
287     * @return   boolean
288     * @access   public
289     */
290     function isCached($id, $group = 'default') {
291         if (!$this->caching)
292             return false;
293
294         return $this->container->isCached($id, $group);
295     } // end func isCached
296
297     /**
298     * Checks if a dataset is expired
299     *
300     * @param    string  dataset ID
301     * @param    string  cache group
302     * @param    integer maximum age for the cached data in seconds - 0 for endless
303     *                   If the cached data is older but the given lifetime it will
304     *                   be removed from the cache. You don't have to provide this
305     *                   argument if you call isExpired(). Every dataset knows
306     *                   it's expire date and will be removed automatically. Use
307     *                   this only if you know what you're doing...
308     * @return   boolean
309     * @access   public
310     */
311     function isExpired($id, $group = 'default', $max_age = 0) {
312         if (!$this->caching)
313             return true;
314
315         return $this->container->isExpired($id, $group, $max_age);
316     } // end func isExpired
317
318     /**
319     * Generates a "unique" ID for the given value
320     *
321     * This is a quick but dirty hack to get a "unique" ID for a any kind of variable.
322     * ID clashes might occur from time to time although they are extreme unlikely!
323     *
324     * @param    mixed   variable to generate a ID for
325     * @return   string  "unique" ID
326     * @access   public
327     */
328     function generateID($variable) {
329         // WARNING: ID clashes are possible although unlikely
330         return md5(serialize($variable));
331     }
332
333     /**
334     * Calls the garbage collector of the storage object with a certain probability
335     *
336     * @param    boolean Force a garbage collection run?
337     * @see  $gc_probability, $gc_time
338     */
339     function garbageCollection($force = false) {
340         static $last_run = 0;
341
342         if (!$this->caching)
343             return;
344
345         srand((double) microtime() * 1000000);
346
347         // time and probability based
348         if (($force) || ($last_run && $last_run < time() + $this->gc_time) || (rand(1, 100) < $this->gc_probability)) {
349             $this->container->garbageCollection($this->gc_maxlifetime);
350             $last_run = time();
351         }
352     } // end func garbageCollection
353
354 } // end class cache