* @version 2.1 */ class Prefs { // Namespace of this instance of Prefs. var $_ns; // Configuration of this object. var $_params = array( // The current user_id for which to load/save preferences. 'user_id' => null, // How long before we force a reload of the prefs data? 3600 = once every hour. 'load_timeout' => 3600, // Enable database storage. 'enable_db' => true, // Name of database table to store prefs. 'db_table' => 'pref_tbl', // Automatically create table and verify columns. Better set to false after site launch. 'create_table' => true, ); /** * Prefs constructor. */ function Prefs($namespace='') { $app =& App::getInstance(); $this->_ns = '_prefs_' . $namespace; // Initialized the prefs array. if (!isset($_SESSION[$this->_ns])) { $_SESSION[$this->_ns] = array('loaded' => false, 'data' => array()); } // Get create tables config from global context. if (!is_null($app->getParam('db_create_tables'))) { $this->setParam(array('create_table' => $app->getParam('db_create_tables'))); } } /** * Setup the database table for this class. * * @access public * @author Quinn Comendant * @since 04 Jun 2006 16:41:42 */ function initDB($recreate_db=false) { $app =& App::getInstance(); $db =& DB::getInstance(); static $_db_tested = false; if ($recreate_db || !$_db_tested && $this->getParam('create_table')) { if ($recreate_db) { $db->query("DROP TABLE IF EXISTS " . $this->getParam('db_table')); $app->logMsg(sprintf('Dropping and recreating table %s.', $this->getParam('db_table')), LOG_DEBUG, __FILE__, __LINE__); } $db->query("CREATE TABLE IF NOT EXISTS " . $db->escapeString($this->getParam('db_table')) . " ( user_id VARCHAR(32) NOT NULL DEFAULT '', pref_namespace VARCHAR(32) NOT NULL DEFAULT '', pref_key VARCHAR(64) NOT NULL DEFAULT '', pref_value TEXT, PRIMARY KEY (user_id, pref_namespace, pref_key) )"); if (!$db->columnExists($this->getParam('db_table'), array( 'user_id', 'pref_namespace', 'pref_key', 'pref_value', ), false, false)) { $app->logMsg(sprintf('Database table %s has invalid columns. Please update this table manually.', $this->getParam('db_table')), LOG_ALERT, __FILE__, __LINE__); trigger_error(sprintf('Database table %s has invalid columns. Please update this table manually.', $this->getParam('db_table')), E_USER_ERROR); } } $_db_tested = true; } /** * Set the params of this object. * * @param array $params Array of param keys and values to set. */ function setParam($params=null) { if (isset($params) && is_array($params)) { // Merge new parameters with old overriding only those passed. $this->_params = array_merge($this->_params, $params); } } /** * Return the value of a parameter, if it exists. * * @access public * @param string $param Which parameter to return. * @return mixed Configured parameter value. */ function getParam($param) { $app =& App::getInstance(); if (isset($this->_params[$param])) { return $this->_params[$param]; } else { $app->logMsg(sprintf('Parameter is not set: %s', $param), LOG_DEBUG, __FILE__, __LINE__); return null; } } /** * Sets the default value of a preference. The pref will be set only if * is not set already. * * @param string $key The name of the preference to modify. * @param string $val The new value for this preference. */ function setDefaults($defaults) { $app =& App::getInstance(); if (isset($defaults) && is_array($defaults)) { // Apply defaults to the session, setting only non-existing values. $app->logMsg(sprintf('Pre-defaulting: %s', getDump($_SESSION[$this->_ns]['data'])), LOG_DEBUG, __FILE__, __LINE__); $_SESSION[$this->_ns]['data'] = array_merge($defaults, $_SESSION[$this->_ns]['data']); $app->logMsg(sprintf('Post-defaulting: %s', getDump($_SESSION[$this->_ns]['data'])), LOG_DEBUG, __FILE__, __LINE__); } } /** * Sets the given preferences to the specific value, * * @param string $key The name of the preference to modify. * @param string $val The new value for this preference. */ function set($key, $val) { if ('' != $key && '' != $val) { $_SESSION[$this->_ns]['data'][$key] = $val; } } /** * Returns the value of the requested preference. * * @param string $key The name of the preference to retrieve. * * @return string The value of the preference. */ function get($key) { return (isset($_SESSION[$this->_ns]['data'][$key])) ? $_SESSION[$this->_ns]['data'][$key] : null; } /** * To see if a preference has been set. * * @param string $key The name of the preference to check. * * @return boolean True if the preference isset and not empty * false otherwise. */ function exists($key) { return isset($_SESSION[$this->_ns]['data'][$key]); } /** * Clear a set preference value. * * @param string $key The name of the preference to delete. */ function delete($key) { unset($_SESSION[$this->_ns]['data'][$key]); } /** * Empty the $_SESSION cache. This should be executed with the same consideration as $auth->clear() */ function clear() { $_SESSION[$this->_ns] = array(); } /* * Retreives all prefs from the database and stores them in the $_SESSION. * * @access public * @return bool True if loading succeeded. * @author Quinn Comendant * @version 1.0 * @since 04 Jun 2006 16:56:53 */ function load() { $app =& App::getInstance(); $db =& DB::getInstance(); // Skip this method if not using the db. if (true !== $this->getParam('enable_db')) { return true; } // Prefs already loaded for this session. if ($this->_isLoaded()) { return true; } // User_id must not be empty. if ('' == $this->getParam('user_id')) { $app->logMsg(sprintf('Cannot save prefs because user_id not set.', null), LOG_ERR, __FILE__, __LINE__); return false; } $this->initDB(); // Retreive all prefs for this user and namespace. $qid = $db->query(" SELECT pref_key, pref_value FROM " . $db->escapeString($this->getParam('db_table')) . " WHERE user_id = '" . $db->escapeString($this->getParam('user_id')) . "' AND pref_namespace = '" . $db->escapeString($this->_ns) . "' LIMIT 10000 "); while (list($key, $val) = mysql_fetch_row($qid)) { $_SESSION[$this->_ns]['data'][$key] = $val; } // Data loaded only once per session. $_SESSION[$this->_ns]['loaded'] = true; $_SESSION[$this->_ns]['load_datetime'] = date('Y-m-d H:i:s'); return true; } /* * Returns true if the prefs had been loaded from the database into the $_SESSION recently. * This function is simply a check so the database isn't access every page load. * * @access private * @return bool True if prefs are loaded. * @author Quinn Comendant * @version 1.0 * @since 04 Jun 2006 17:12:44 */ function _isLoaded() { if (isset($_SESSION[$this->_ns]['load_datetime']) && strtotime($_SESSION[$this->_ns]['load_datetime']) > time() - $this->getParam('load_timeout') && isset($_SESSION[$this->_ns]['loaded']) && true === $_SESSION[$this->_ns]['loaded']) { return true; } else { return false; } } /* * Saves all prefs stored in the $_SESSION into the database. * * @access public * @return bool True if prefs exist and were saved. * @author Quinn Comendant * @version 1.0 * @since 04 Jun 2006 17:19:56 */ function save() { $app =& App::getInstance(); $db =& DB::getInstance(); // Skip this method if not using the db. if (true !== $this->getParam('enable_db')) { return true; } // User_id must not be empty. if ('' == $this->getParam('user_id')) { $app->logMsg(sprintf('Cannot save prefs because user_id not set.', null), LOG_ERR, __FILE__, __LINE__); return false; } $this->initDB(); if (isset($_SESSION[$this->_ns]['data']) && is_array($_SESSION[$this->_ns]['data'])) { // Delete old prefs from database. $db->query(" DELETE FROM " . $db->escapeString($this->getParam('db_table')) . " WHERE user_id = '" . $db->escapeString($this->getParam('user_id')) . "' AND pref_namespace = '" . $db->escapeString($this->_ns) . "' "); // Insert new prefs. $insert_values = array(); foreach ($_SESSION[$this->_ns]['data'] as $key => $val) { if ('' != trim($key) && '' != trim($val)) { $insert_values[] = sprintf("('%s', '%s', '%s', '%s')", $db->escapeString($this->getParam('user_id')), $db->escapeString($this->_ns), $db->escapeString($key), $db->escapeString($val)); } } $db->query(" INSERT LOW_PRIORITY INTO " . $db->escapeString($this->getParam('db_table')) . " (user_id, pref_namespace, pref_key, pref_value) VALUES " . join(', ', $insert_values) . " "); $app->logMsg(sprintf('Saved %s preferences to database.', sizeof($insert_values)), LOG_DEBUG, __FILE__, __LINE__); return true; } return false; } } ?>