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