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

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

Q - decided to use standard instantiation for Prefs and Cache instead of singleton methods.

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