source: trunk/lib/Prefs.inc.php @ 150

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

Q - okay now finished with Prefs.inc.php; it is sweeeet!

File size: 11.3 KB
Line 
1<?php
2/**
3 * Prefs.inc.php
4 * code by strangecode :: www.strangecode.com :: this document contains copyrighted information
5 *
6 * Prefs provides an API for saving arbitrary values in a user's session.
7 * Session prefs can be stored into a database with the optional save() and load() methods.
8 *
9 * @author  Quinn Comendant <quinn@strangecode.com>
10 * @version 2.1
11 *
12 * Example of use:
13---------------------------------------------------------------------
14// Load preferences for the user.
15require_once 'codebase/lib/Prefs.inc.php';
16$prefs = new Prefs('bURB');
17$prefs->setParam(array(
18    'enable_db' => $auth->isLoggedIn(),
19    'user_id' => $auth->get('user_id'),
20));
21$prefs->setDefaults(array(
22    'search_num_results' => 25,
23    'datalog_num_entries' => 25,
24));
25$prefs->load();
26---------------------------------------------------------------------
27 */
28class Prefs {
29
30    // Namespace of this instance of Prefs.
31    var $_ns;
32
33    // Configuration of this object.
34    var $_params = array(
35       
36        // The current user_id for which to load/save preferences.
37        'user_id' => null,
38       
39        // How long before we force a reload of the prefs data? 3600 = once every hour.
40        'load_timeout' => 3600,
41       
42        // Enable database storage.
43        'enable_db' => true,
44       
45        // Name of database table to store prefs.
46        'db_table' => 'pref_tbl',
47
48        // Automatically create table and verify columns. Better set to false after site launch.
49        'create_table' => true,
50    );
51
52    /**
53     * Prefs constructor.
54     */
55    function Prefs($namespace='')
56    {
57        $app =& App::getInstance();
58
59        $this->_ns = '_prefs_' . $namespace;
60       
61        // Initialized the prefs array.
62        if (!isset($_SESSION[$this->_ns]['data'])) {
63            $this->clear();
64        }
65
66        // Get create tables config from global context.
67        if (!is_null($app->getParam('db_create_tables'))) {
68            $this->setParam(array('create_table' => $app->getParam('db_create_tables')));
69        }
70    }
71
72    /**
73     * Setup the database table for this class.
74     *
75     * @access  public
76     * @author  Quinn Comendant <quinn@strangecode.com>
77     * @since   04 Jun 2006 16:41:42
78     */
79    function initDB($recreate_db=false)
80    {
81        $app =& App::getInstance();
82        $db =& DB::getInstance();
83
84        static $_db_tested = false;
85
86        if ($recreate_db || !$_db_tested && $this->getParam('create_table')) {
87            if ($recreate_db) {
88                $db->query("DROP TABLE IF EXISTS " . $this->getParam('db_table'));
89                $app->logMsg(sprintf('Dropping and recreating table %s.', $this->getParam('db_table')), LOG_DEBUG, __FILE__, __LINE__);
90            }
91            $db->query("CREATE TABLE IF NOT EXISTS " . $db->escapeString($this->getParam('db_table')) . " (
92                user_id VARCHAR(32) NOT NULL DEFAULT '',
93                pref_namespace VARCHAR(32) NOT NULL DEFAULT '',
94                pref_key VARCHAR(64) NOT NULL DEFAULT '',
95                pref_value TEXT,
96                PRIMARY KEY (user_id, pref_namespace, pref_key)
97            )");
98
99            if (!$db->columnExists($this->getParam('db_table'), array(
100                'user_id',
101                'pref_namespace',
102                'pref_key',
103                'pref_value',
104            ), false, false)) {
105                $app->logMsg(sprintf('Database table %s has invalid columns. Please update this table manually.', $this->getParam('db_table')), LOG_ALERT, __FILE__, __LINE__);
106                trigger_error(sprintf('Database table %s has invalid columns. Please update this table manually.', $this->getParam('db_table')), E_USER_ERROR);
107            }
108        }
109        $_db_tested = true;
110    }
111
112    /**
113     * Set the params of this object.
114     *
115     * @param  array $params   Array of param keys and values to set.
116     */
117    function setParam($params=null)
118    {
119        if (isset($params) && is_array($params)) {
120            // Merge new parameters with old overriding only those passed.
121            $this->_params = array_merge($this->_params, $params);
122        }
123    }
124
125    /**
126     * Return the value of a parameter, if it exists.
127     *
128     * @access public
129     * @param string $param        Which parameter to return.
130     * @return mixed               Configured parameter value.
131     */
132    function getParam($param)
133    {
134        $app =& App::getInstance();
135   
136        if (isset($this->_params[$param])) {
137            return $this->_params[$param];
138        } else {
139            $app->logMsg(sprintf('Parameter is not set: %s', $param), LOG_DEBUG, __FILE__, __LINE__);
140            return null;
141        }
142    }
143
144    /**
145     * Sets the default value of a preference. The pref will be set only if
146     * is not set already.
147     *
148     * @param  string $key       The name of the preference to modify.
149     * @param  string $val       The new value for this preference.
150     */
151    function setDefaults($defaults)
152    {
153        if (isset($defaults) && is_array($defaults)) {
154            // Apply defaults to the session, setting only non-existing values.
155            $_SESSION[$this->_ns]['data'] = array_merge($defaults, $_SESSION[$this->_ns]['data']);
156        }
157    }
158
159    /**
160     * Sets the given preferences to the specific value,
161     *
162     * @param  string $key       The name of the preference to modify.
163     * @param  string $val       The new value for this preference.
164     */
165    function set($key, $val)
166    {
167        if ('' != $key && '' != $val) {
168            $_SESSION[$this->_ns]['data'][$key] = $val;
169        }
170    }
171
172    /**
173     * Returns the value of the requested preference.
174     *
175     * @param string $key       The name of the preference to retrieve.
176     *
177     * @return string           The value of the preference.
178     */
179    function get($key)
180    {
181        return (isset($_SESSION[$this->_ns]['data'][$key])) ? $_SESSION[$this->_ns]['data'][$key] : null;
182    }
183
184    /**
185     * To see if a preference has been set.
186     *
187     * @param string $key       The name of the preference to check.
188     *
189     * @return boolean          True if the preference isset and not empty
190     *                          false otherwise.
191     */
192    function exists($key)
193    {
194        return isset($_SESSION[$this->_ns]['data'][$key]);
195    }
196
197    /**
198     * Clear a set preference value.
199     *
200     * @param string $key       The name of the preference to delete.
201     */
202    function delete($key)
203    {
204        unset($_SESSION[$this->_ns]['data'][$key]);
205    }
206
207    /**
208     * Empty the $_SESSION cache. This should be executed with the same consideration as $auth->clear()
209     */
210    function clear()
211    {
212        $_SESSION[$this->_ns] = array(
213            'loaded' => false,
214            'load_datetime' => '1970-01-01',
215            'data' => array()
216        );
217    }
218   
219    /*
220    * Retreives all prefs from the database and stores them in the $_SESSION.
221    *
222    * @access   public
223    * @param    bool    $force  Set to always load from database, regardless if _isLoaded() or not.
224    * @return   bool    True if loading succeeded.
225    * @author   Quinn Comendant <quinn@strangecode.com>
226    * @version  1.0
227    * @since    04 Jun 2006 16:56:53
228    */
229    function load($force=false)
230    {
231        $app =& App::getInstance();
232        $db =& DB::getInstance();
233       
234        // Skip this method if not using the db.
235        if (true !== $this->getParam('enable_db')) {
236            return true;
237        }
238
239        $this->initDB();
240
241        // Prefs already loaded for this session.
242        if (!$force && $this->_isLoaded()) {
243            return true;
244        }
245
246        // User_id must not be empty.
247        if ('' == $this->getParam('user_id')) {
248            $app->logMsg(sprintf('Cannot save prefs because user_id not set.', null), LOG_ERR, __FILE__, __LINE__);
249            return false;
250        }
251       
252        // Clear existing cache.
253        $this->clear();
254       
255        // Retreive all prefs for this user and namespace.
256        $qid = $db->query("
257            SELECT pref_key, pref_value
258            FROM " . $db->escapeString($this->getParam('db_table')) . "
259            WHERE user_id = '" . $db->escapeString($this->getParam('user_id')) . "'
260            AND pref_namespace = '" . $db->escapeString($this->_ns) . "'
261            LIMIT 10000
262        ");
263        while (list($key, $val) = mysql_fetch_row($qid)) {
264            $_SESSION[$this->_ns]['data'][$key] = $val;
265        }
266       
267        $app->logMsg(sprintf('%s prefs loaded from database.', sizeof($_SESSION[$this->_ns]['data'])), LOG_DEBUG, __FILE__, __LINE__);
268       
269        // Data loaded only once per session.
270        $_SESSION[$this->_ns]['loaded'] = true;
271        $_SESSION[$this->_ns]['load_datetime'] = date('Y-m-d H:i:s');
272       
273        return true;
274    }
275   
276    /*
277    * Returns true if the prefs had been loaded from the database into the $_SESSION recently.
278    * This function is simply a check so the database isn't access every page load.
279    *
280    * @access   private
281    * @return   bool    True if prefs are loaded.
282    * @author   Quinn Comendant <quinn@strangecode.com>
283    * @version  1.0
284    * @since    04 Jun 2006 17:12:44
285    */
286    function _isLoaded()
287    {
288        if (isset($_SESSION[$this->_ns]['load_datetime'])
289        && strtotime($_SESSION[$this->_ns]['load_datetime']) > time() - $this->getParam('load_timeout')
290        && isset($_SESSION[$this->_ns]['loaded']) 
291        && true === $_SESSION[$this->_ns]['loaded']) {
292            return true;
293        } else {
294            return false;
295        }
296    }
297   
298    /*
299    * Saves all prefs stored in the $_SESSION into the database.
300    *
301    * @access   public
302    * @return   bool    True if prefs exist and were saved.
303    * @author   Quinn Comendant <quinn@strangecode.com>
304    * @version  1.0
305    * @since    04 Jun 2006 17:19:56
306    */
307    function save()
308    {
309        $app =& App::getInstance();
310        $db =& DB::getInstance();
311       
312        // Skip this method if not using the db.
313        if (true !== $this->getParam('enable_db')) {
314            return true;
315        }
316       
317        // User_id must not be empty.
318        if ('' == $this->getParam('user_id')) {
319            $app->logMsg(sprintf('Cannot save prefs because user_id not set.', null), LOG_ERR, __FILE__, __LINE__);
320            return false;
321        }
322
323        $this->initDB();
324
325        if (isset($_SESSION[$this->_ns]['data']) && is_array($_SESSION[$this->_ns]['data'])) {
326            // Delete old prefs from database.
327            $db->query("
328                DELETE FROM " . $db->escapeString($this->getParam('db_table')) . "
329                WHERE user_id = '" . $db->escapeString($this->getParam('user_id')) . "'
330                AND pref_namespace = '" . $db->escapeString($this->_ns) . "'
331            ");
332           
333            // Insert new prefs.
334            $insert_values = array();
335            foreach ($_SESSION[$this->_ns]['data'] as $key => $val) {
336                if ('' != trim($key) && '' != trim($val)) {
337                    $insert_values[] = sprintf("('%s', '%s', '%s', '%s')", $db->escapeString($this->getParam('user_id')), $db->escapeString($this->_ns), $db->escapeString($key), $db->escapeString($val));
338                }
339            }
340            $db->query("
341                INSERT LOW_PRIORITY INTO " . $db->escapeString($this->getParam('db_table')) . "
342                (user_id, pref_namespace, pref_key, pref_value)
343                VALUES " . join(', ', $insert_values) . "
344            ");
345           
346            $app->logMsg(sprintf('Saved %s preferences to database.', sizeof($insert_values)), LOG_DEBUG, __FILE__, __LINE__);
347            return true;
348        }
349       
350        return false;
351    }
352}
353
354
355?>
Note: See TracBrowser for help on using the repository browser.