source: trunk/lib/Cache.inc.php @ 172

Last change on this file since 172 was 172, checked in by scdev, 18 years ago

Q - added caching to ACL, and flush command to acl.cli.php

File size: 8.2 KB
Line 
1<?php
2/**
3 * Cache.inc.php
4 * code by strangecode :: www.strangecode.com :: this document contains copyrighted information
5 *
6 * Provides an API for storing a limited amount of data
7 * intended to have a short lifetime in a user's session.
8 *
9 * @author  Quinn Comendant <quinn@strangecode.com>
10 * @version 2.1
11 * @since   2001
12 */
13 
14// Flags.
15define('CACHE_ALLOW_OVERSIZED', 1);
16
17class Cache {
18
19    // Namespace of this instance of Prefs.
20    var $_ns;
21
22    // Configuration parameters for this object.
23    var $_params = array(
24       
25        // If false nothing will be cached or retreived. Useful for testing realtime data requests.
26        'enabled' => true,
27
28        // The maximum size in bytes of any one variable.
29        'item_size_limit' => 4194304, // 4 MB
30       
31        // The maximum size in bytes before the cache will begin flushing out old items.
32        'stack_size_limit' => 4194304, // 4 MB
33       
34        // The minimum items to keep in the cache regardless of item or cache size.
35        'min_items' => 5,
36    );
37   
38    /*
39    * Constructor
40    *
41    * @access   public
42    * @param    string  $namespace  This object will store data under this realm.
43    * @author   Quinn Comendant <quinn@strangecode.com>
44    * @version  1.0
45    * @since    05 Jun 2006 23:14:21
46    */
47    function Cache($namespace='')
48    {
49        $app =& App::getInstance();
50       
51        $this->_ns = $namespace;
52
53        if (true !== $app->getParam('enable_session')) {
54            $app->logMsg('Cache disabled, enable_session is false.', LOG_DEBUG, __FILE__, __LINE__);
55            $this->setParam(array('enabled' => false));
56        }
57       
58        if (!isset($_SESSION['_cache'][$this->_ns])) {
59            $this->clear();
60        }
61    }
62
63    /**
64     * This method enforces the singleton pattern for this class.
65     *
66     * @return  object  Reference to the global Cache object.
67     * @access  public
68     * @static
69     */
70    function &getInstance($namespace='')
71    {
72        static $instances = array();
73
74        if (!array_key_exists($namespace, $instances)) {
75            $instances[$namespace] = new Cache($namespace);
76        }
77
78        return $instances[$namespace];
79    }
80
81    /**
82     * Set (or overwrite existing) parameters by passing an array of new parameters.
83     *
84     * @access public
85     * @param  array    $params     Array of parameters (key => val pairs).
86     */
87    function setParam($params)
88    {
89        $app =& App::getInstance();
90
91        if (isset($params) && is_array($params)) {
92            // Merge new parameters with old overriding only those passed.
93            $this->_params = array_merge($this->_params, $params);
94        } else {
95            $app->logMsg(sprintf('Parameters are not an array: %s', $params), LOG_ERR, __FILE__, __LINE__);
96        }
97    }
98
99    /**
100     * Return the value of a parameter, if it exists.
101     *
102     * @access public
103     * @param string $param        Which parameter to return.
104     * @return mixed               Configured parameter value.
105     */
106    function getParam($param)
107    {
108        $app =& App::getInstance();
109   
110        if (isset($this->_params[$param])) {
111            return $this->_params[$param];
112        } else {
113            $app->logMsg(sprintf('Parameter is not set: %s', $param), LOG_DEBUG, __FILE__, __LINE__);
114            return null;
115        }
116    }
117
118    /**
119     * Stores a new variable in the session cache. The $key is is md5'ed
120     * because if a key is numeric, the array_shift function
121     * will reset the key to the next largest int key. Weird behavior I can't
122     * understand. For example $cache["123"] will become $cache[0]
123     *
124     * @param str   $key        An identifier for the cached object.
125     * @param mixed $var        The var to store in the session cache.
126     * @param bool  $flags      If we have something really big that we
127     *                          still want to cache, setting this to
128     *                          CACHE_ALLOW_OVERSIZED allows this.
129     * @return bool             True on success, false otherwise.
130     */
131    function set($key, $var, $flags=0)
132    {
133        $app =& App::getInstance();
134
135        if (true !== $this->getParam('enabled')) {
136            $app->logMsg(sprintf('Cache not enabled, not saving data.', null), LOG_DEBUG, __FILE__, __LINE__);
137            return false;
138        }
139
140        $keyhash = md5($key);
141        $var = serialize($var);
142        $var_len = strlen($var);
143
144        if ($var_len >= $this->getParam('item_size_limit')) {
145            $app->logMsg(sprintf('Serialized variable (%s bytes) more than item_size_limit (%s bytes).', $var_len, $this->getParam('item_size_limit')), LOG_NOTICE, __FILE__, __LINE__);
146            return false;
147        }
148
149        if ($flags & CACHE_ALLOW_OVERSIZED == 0 && $var_len >= $this->getParam('stack_size_limit')) {
150            $app->logMsg(sprintf('Serialized variable (%s bytes) more than stack_size_limit (%s bytes).', $var_len, $this->getParam('stack_size_limit')), LOG_NOTICE, __FILE__, __LINE__);
151            return false;
152        }       
153
154        // Remove any value already stored under this key.
155        unset($_SESSION['_cache'][$this->_ns][$keyhash]);
156
157        // Continue to prune the cache if its size is greater than stack_size_limit, but keep at least min_items.
158        while (strlen(serialize($_SESSION['_cache'][$this->_ns])) + $var_len >= $this->getParam('stack_size_limit') && sizeof($_SESSION['_cache'][$this->_ns]) >= $this->getParam('min_items')) {
159            array_shift($_SESSION['_cache'][$this->_ns]);
160        }
161
162        // Save this value under the specified key.
163        $_SESSION['_cache'][$this->_ns][$keyhash] =& $var;
164
165        if ($var_len >= 1024000) {
166            $app->logMsg(sprintf('Successfully cached oversized variable (%s bytes).', $var_len), LOG_DEBUG, __FILE__, __LINE__);
167        }
168
169        return true;
170    }
171
172    /**
173     * Retrives an object from the session cache and returns it unserialized.
174     * It also moves it to the top of the stack, which makes it such that the
175     * cache flushing mechanism of putCache deletes the oldest referenced items
176     * first.
177     *
178     * @param string $key  The key for the datum to retrieve.
179     * @return mixed          The requested datum, or false on failure.
180     */
181    function get($key)
182    {
183        $app =& App::getInstance();
184
185        if (true !== $this->getParam('enabled')) {
186            $app->logMsg(sprintf('Cache not enabled, not getting data.', null), LOG_DEBUG, __FILE__, __LINE__);
187            return false;
188        }
189
190        $keyhash = md5($key);
191        if (isset($_SESSION['_cache'][$this->_ns][$keyhash])) {
192            $app->logMsg(sprintf('Retreiving %s from cache.', $key), LOG_DEBUG, __FILE__, __LINE__);
193            // Move the accessed cached datum to the top of the stack. Maybe somebody knows a better way to do this?
194            $tmp =& $_SESSION['_cache'][$this->_ns][$keyhash];
195            unset($_SESSION['_cache'][$this->_ns][$keyhash]);
196            $_SESSION['_cache'][$this->_ns][$keyhash] =& $tmp;
197            // Return the unserialized datum.
198            return unserialize($_SESSION['_cache'][$this->_ns][$keyhash]);
199        } else {
200            $app->logMsg(sprintf('Missing %s from cache.', $key), LOG_DEBUG, __FILE__, __LINE__);
201            return false;
202        }
203    }
204
205    /**
206     * Tells you if the object is cached.
207     *
208     * @param string $key  The key of the object to check.
209     * @return bool           The return from isset().
210     */
211    function exists($key)
212    {
213        if (true !== $this->getParam('enabled')) {
214            return false;
215        }
216
217        $keyhash = md5($key);
218        return array_key_exists($keyhash, $_SESSION['_cache'][$this->_ns]);
219    }
220
221    /**
222     * Tells you if the object is cached.
223     *
224     * @param string $key  The key of the object to check.
225     * @return bool           The return from isset().
226     */
227    function delete($key)
228    {
229        $keyhash = md5($key);
230        unset($_SESSION['_cache'][$this->_ns][$keyhash]);
231    }
232   
233    /*
234    * Delete all existing items from the cache.
235    *
236    * @access   public
237    * @author   Quinn Comendant <quinn@strangecode.com>
238    * @version  1.0
239    * @since    05 Jun 2006 23:51:34
240    */
241    function clear()
242    {
243        $_SESSION['_cache'][$this->_ns] = array();
244    }
245
246// END Cache
247}
248
249?>
Note: See TracBrowser for help on using the repository browser.