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

Last change on this file since 334 was 334, checked in by quinn, 16 years ago

Fixed lots of misplings. I'm so embarrassed! ;P

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 retrieved. 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 should not be numeric
120     * because the array_shift function will reset the key to the next largest
121     * int key. Weird behavior I can't understand. For example $cache["123"] will become $cache[0]
122     *
123     * @param str   $key        An identifier for the cached object.
124     * @param mixed $var        The var to store in the session cache.
125     * @param bool  $flags      If we have something really big that we
126     *                          still want to cache, setting this to
127     *                          CACHE_ALLOW_OVERSIZED allows this.
128     * @return bool             True on success, false otherwise.
129     */
130    function set($key, $var, $flags=0)
131    {
132        $app =& App::getInstance();
133
134        if (true !== $this->getParam('enabled')) {
135            $app->logMsg(sprintf('Cache disabled, not saving data.', null), LOG_DEBUG, __FILE__, __LINE__);
136            return false;
137        }
138
139        $var = serialize($var);
140        $var_len = mb_strlen($var);
141
142        if ($var_len >= $this->getParam('item_size_limit')) {
143            $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__);
144            return false;
145        }
146
147        if ($flags & CACHE_ALLOW_OVERSIZED == 0 && $var_len >= $this->getParam('stack_size_limit')) {
148            $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__);
149            return false;
150        }       
151
152        // Remove any value already stored under this key.
153        unset($_SESSION['_cache'][$this->_ns][$key]);
154
155        // Continue to prune the cache if its size is greater than stack_size_limit, but keep at least min_items.
156        while (mb_strlen(serialize($_SESSION['_cache'][$this->_ns])) + $var_len >= $this->getParam('stack_size_limit') && sizeof($_SESSION['_cache'][$this->_ns]) >= $this->getParam('min_items')) {
157            array_shift($_SESSION['_cache'][$this->_ns]);
158        }
159
160        // Save this value under the specified key.
161        $_SESSION['_cache'][$this->_ns][$key] =& $var;
162
163        if ($var_len >= 1024000) {
164            $app->logMsg(sprintf('Successfully cached oversized variable (%s bytes).', $var_len), LOG_DEBUG, __FILE__, __LINE__);
165        }
166
167        return true;
168    }
169
170    /**
171     * Retrieves an object from the session cache and returns it unserialized.
172     * It also moves it to the top of the stack, which makes it such that the
173     * cache flushing mechanism of putCache deletes the oldest referenced items
174     * first.
175     *
176     * @param string $key  The key for the datum to retrieve.
177     * @return mixed          The requested datum, or false on failure.
178     */
179    function get($key)
180    {
181        $app =& App::getInstance();
182
183        if (true !== $this->getParam('enabled')) {
184            $app->logMsg(sprintf('Cache disabled, not getting data.', null), LOG_DEBUG, __FILE__, __LINE__);
185            return false;
186        }
187
188        if (array_key_exists($key, $_SESSION['_cache'][$this->_ns])) {
189            $app->logMsg(sprintf('Retreiving %s from cache.', $key), LOG_DEBUG, __FILE__, __LINE__);
190            // Move the accessed cached datum to the top of the stack. Maybe somebody knows a better way to do this?
191            $tmp =& $_SESSION['_cache'][$this->_ns][$key];
192            unset($_SESSION['_cache'][$this->_ns][$key]);
193            $_SESSION['_cache'][$this->_ns][$key] =& $tmp;
194            // Return the unserialized datum.
195            return unserialize($_SESSION['_cache'][$this->_ns][$key]);
196        } else {
197            $app->logMsg(sprintf('Missing %s from cache.', $key), LOG_DEBUG, __FILE__, __LINE__);
198            return false;
199        }
200    }
201
202    /**
203     * Tells you if the object is cached.
204     *
205     * @param string $key  The key of the object to check.
206     * @return bool         True if a value exists for the given key.
207     */
208    function exists($key)
209    {
210        if (true !== $this->getParam('enabled')) {
211            return false;
212        }
213
214        return array_key_exists($key, $_SESSION['_cache'][$this->_ns]);
215    }
216
217    /**
218     * Removes a cached object.
219     *
220     * @param string $key  The key of the object to check.
221     * @return bool         True if the value existed before being unset.
222     */
223    function delete($key)
224    {
225        if (array_key_exists($key, $_SESSION['_cache'][$this->_ns])) {
226            unset($_SESSION['_cache'][$this->_ns][$key]);
227            return true;
228        } else {
229            return false;
230        }
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.