Ignore:
Timestamp:
May 3, 2014 3:13:19 PM (10 years ago)
Author:
anonymous
Message:

Added cookie storage to Prefs(). Created App->addCookie method. Improved PHP version checks.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/lib/Prefs.inc.php

    r468 r477  
    3030 * @version 2.1
    3131 *
    32  * Example of use:
     32 * Example of use (database storagetype):
    3333---------------------------------------------------------------------
    3434// Load preferences for the user's session.
     
    3636$prefs = new Prefs('my-namespace');
    3737$prefs->setParam(array(
    38     'persistent' => $auth->isLoggedIn(),
     38    'storagetype' => ($auth->isLoggedIn() ? 'database' : 'session'),
    3939    'user_id' => $auth->get('user_id'),
    4040));
     
    4949$prefs->set('datalog_num_entries', getFormData('datalog_num_entries'));
    5050$prefs->save();
    51 
    5251---------------------------------------------------------------------
    5352 */
     
    6059    private $_params = array(
    6160
     61        // Legacy parameter, superceeded by the 'storagetype' setting.
    6262        // Enable database storage. If this is false, all prefs will live only as long as the session.
    63         'persistent' => false,
    64 
    65         // The current user_id for which to load/save persistent preferences.
     63        'persistent' => null,
     64
     65        // Store preferences in one of the available storage mechanisms: session, cookie, database
     66        'storagetype' => 'session',
     67
     68        // ----------------------------------------------------------
     69        // Cookie-type settings.
     70
     71        // Lifespan of the cookie. If set to an integer, interpreted as a timestamp (0 for 'when user closes browser'), otherwise as a strtotime-compatible value ('tomorrow', etc).
     72        'cookie_expire' => '+10 years',
     73
     74        // The path on the server in which the cookie will be available on.
     75        'cookie_path' => null,
     76
     77        // The domain that the cookie is available to.
     78        'cookie_domain' => null,
     79
     80        // ----------------------------------------------------------
     81        // Database-type settings.
     82
     83        // The current user_id for which to load/save database-backed preferences.
    6684        'user_id' => null,
    6785
     
    82100    public function __construct($namespace='')
    83101    {
    84         $app =& App::getInstance();
     102        $app =& App::getInstance();
    85103
    86104        $this->_ns = $namespace;
     
    106124    public function initDB($recreate_db=false)
    107125    {
    108         $app =& App::getInstance();
    109         $db =& DB::getInstance();
     126        $app =& App::getInstance();
     127        $db =& DB::getInstance();
    110128
    111129        static $_db_tested = false;
     
    144162    public function setParam($params=null)
    145163    {
     164        // CLI scripts can't use prefs stored in HTTP-based protocols.
     165        if (defined('_CLI')
     166        && isset($params['storagetype'])
     167        && in_array($params['storagetype'], array('cookie', 'session'))) {
     168            $app->logMsg(sprintf('Storage type %s not available for CLI', $params['storagetype']), LOG_NOTICE, __FILE__, __LINE__);
     169        }
     170
     171        // Convert the legacy param 'persistent' to 'storagetype=database'.
     172        if (isset($params['persistent']) && $params['persistent'] && !isset($params['storagetype'])) {
     173            $params['storagetype'] = 'database';
     174        }
     175
    146176        if (isset($params) && is_array($params)) {
    147177            // Merge new parameters with old overriding only those passed.
     
    159189    public function getParam($param)
    160190    {
    161         $app =& App::getInstance();
     191        $app =& App::getInstance();
    162192
    163193        if (isset($this->_params[$param])) {
     
    190220     * @param  string $key          The name of the preference to modify.
    191221     * @param  string $val          The new value for this preference.
    192      * @param  bool   $persistent   Save this value forever? Set to false and value will exist as long as the session is in use.
    193222     */
    194223    public function set($key, $val)
     
    196225        $app =& App::getInstance();
    197226
    198         if ('' == $key) {
    199             $app->logMsg(sprintf('Key is empty (provided with value: %s)', $val), LOG_NOTICE, __FILE__, __LINE__);
     227        if (!is_string($key)) {
     228            $app->logMsg(sprintf('Key is not a string-compatible type (%s)', getDump($key)), LOG_NOTICE, __FILE__, __LINE__);
     229            return false;
     230        }
     231        if ('' == trim($key)) {
     232            $app->logMsg(sprintf('Key is empty (along with value: %s)', $val), LOG_NOTICE, __FILE__, __LINE__);
     233            return false;
     234        }
     235        if (!is_scalar($val) && !is_array($val) && !is_object($val)) {
     236            $app->logMsg(sprintf('Value is not a string-compatible type (%s=%s)', $key, getDump($val)), LOG_WARNING, __FILE__, __LINE__);
    200237            return false;
    201238        }
     
    205242        // - or the new value is different than the default
    206243        // - or there is a previously existing saved key.
    207         if (!isset($_SESSION['_prefs'][$this->_ns]['defaults'][$key])
    208         || $_SESSION['_prefs'][$this->_ns]['defaults'][$key] != $val
    209         || isset($_SESSION['_prefs'][$this->_ns]['saved'][$key])) {
    210             $_SESSION['_prefs'][$this->_ns]['saved'][$key] = $val;
    211             $app->logMsg(sprintf('Setting preference %s => %s', $key, truncate(getDump($val, true), 128, 'end')), LOG_DEBUG, __FILE__, __LINE__);
    212         } else {
    213             $app->logMsg(sprintf('Not setting preference %s => %s', $key, truncate(getDump($val, true), 128, 'end')), LOG_DEBUG, __FILE__, __LINE__);
    214         }
     244        switch ($this->getParam('storagetype')) {
     245        case 'session':
     246        case 'database': // DB prefs are saved in the session temporarily until they are saved.
     247            if (!isset($_SESSION['_prefs'][$this->_ns]['defaults'][$key])
     248            || $_SESSION['_prefs'][$this->_ns]['defaults'][$key] != $val
     249            || isset($_SESSION['_prefs'][$this->_ns]['saved'][$key])) {
     250                $_SESSION['_prefs'][$this->_ns]['saved'][$key] = $val;
     251                $app->logMsg(sprintf('Setting session preference %s => %s', $key, getDump($val, true)), LOG_DEBUG, __FILE__, __LINE__);
     252            } else {
     253                $app->logMsg(sprintf('Not setting session preference %s => %s', $key, getDump($val, true)), LOG_DEBUG, __FILE__, __LINE__);
     254            }
     255            break;
     256
     257        case 'cookie':
     258            $name = $this->_getCookieName($key);
     259            $val = json_encode($val);
     260            $app->setCookie($name, $val, $this->getParam('cookie_expire'), $this->getParam('cookie_path'), $this->getParam('cookie_domain'));
     261            $app->logMsg(sprintf('Setting cookie preference %s => %s', $key, $val), LOG_DEBUG, __FILE__, __LINE__);
     262            break;
     263        }
     264
    215265    }
    216266
     
    226276    {
    227277        $app =& App::getInstance();
    228         if (isset($_SESSION['_prefs'][$this->_ns]['saved']) && array_key_exists($key, $_SESSION['_prefs'][$this->_ns]['saved'])) {
    229             $app->logMsg(sprintf('Found %s in saved', $key), LOG_DEBUG, __FILE__, __LINE__);
    230             return $_SESSION['_prefs'][$this->_ns]['saved'][$key];
    231         } else if (isset($_SESSION['_prefs'][$this->_ns]['defaults']) && array_key_exists($key, $_SESSION['_prefs'][$this->_ns]['defaults'])) {
    232             $app->logMsg(sprintf('Found %s in defaults', $key), LOG_DEBUG, __FILE__, __LINE__);
    233             return $_SESSION['_prefs'][$this->_ns]['defaults'][$key];
    234         } else {
    235             $app->logMsg(sprintf('Key not found in prefs cache: %s', $key), LOG_DEBUG, __FILE__, __LINE__);
    236             return null;
     278
     279        switch ($this->getParam('storagetype')) {
     280        case 'session':
     281        case 'database':
     282            if (isset($_SESSION['_prefs'][$this->_ns]['saved']) && array_key_exists($key, $_SESSION['_prefs'][$this->_ns]['saved'])) {
     283                $app->logMsg(sprintf('Found %s in saved', $key), LOG_DEBUG, __FILE__, __LINE__);
     284                return $_SESSION['_prefs'][$this->_ns]['saved'][$key];
     285            } else if (isset($_SESSION['_prefs'][$this->_ns]['defaults']) && array_key_exists($key, $_SESSION['_prefs'][$this->_ns]['defaults'])) {
     286                $app->logMsg(sprintf('Found %s in defaults', $key), LOG_DEBUG, __FILE__, __LINE__);
     287                return $_SESSION['_prefs'][$this->_ns]['defaults'][$key];
     288            } else {
     289                $app->logMsg(sprintf('Key not found in prefs cache: %s', $key), LOG_DEBUG, __FILE__, __LINE__);
     290                return null;
     291            }
     292            break;
     293
     294        case 'cookie':
     295            $name = $this->_getCookieName($key);
     296            if ($this->exists($key)) {
     297                $val = json_decode($_COOKIE[$name]);
     298                $app->logMsg(sprintf('Found %s in cookie: %s', $key, getDump($val)), LOG_DEBUG, __FILE__, __LINE__);
     299                return $val;
     300            } else {
     301                $app->logMsg(sprintf('Key not found in cookie: %s', $key), LOG_DEBUG, __FILE__, __LINE__);
     302                return null;
     303            }
     304            break;
    237305        }
    238306    }
     
    246314    public function exists($key)
    247315    {
    248         return array_key_exists($key, $_SESSION['_prefs'][$this->_ns]['saved']);
     316        switch ($this->getParam('storagetype')) {
     317        case 'session':
     318        case 'database':
     319            return array_key_exists($key, $_SESSION['_prefs'][$this->_ns]['saved']);
     320
     321        case 'cookie':
     322            $name = $this->_getCookieName($key);
     323            return isset($_COOKIE[$name]);
     324        }
     325
    249326    }
    250327
     
    256333    public function delete($key)
    257334    {
    258         unset($_SESSION['_prefs'][$this->_ns]['saved'][$key]);
     335        $app =& App::getInstance();
     336
     337        switch ($this->getParam('storagetype')) {
     338        case 'session':
     339        case 'database':
     340            unset($_SESSION['_prefs'][$this->_ns]['saved'][$key]);
     341            break;
     342
     343        case 'cookie':
     344            if ($this->exists($key)) {
     345                // Just set the existing value to an empty string, which expires in the past.
     346                $name = $this->_getCookieName($key);
     347                $app->setCookie($name, '', time() - 86400);
     348                // Also unset the received cookie value, so it is unavailable.
     349                unset($_COOKIE[$name]);
     350            }
     351            break;
     352        }
     353
    259354    }
    260355
     
    265360    public function clear($focus='all')
    266361    {
     362
    267363        switch ($focus) {
    268364        case 'all' :
    269             $_SESSION['_prefs'][$this->_ns] = array(
    270                 'loaded' => false,
    271                 'load_datetime' => '1970-01-01',
    272                 'defaults' => array(),
    273                 'saved' => array(),
    274             );
    275             break;
    276 
     365            switch ($this->getParam('storagetype')) {
     366            case 'session':
     367            case 'database':
     368                $_SESSION['_prefs'][$this->_ns] = array(
     369                    'loaded' => false,
     370                    'load_datetime' => '1970-01-01',
     371                    'defaults' => array(),
     372                    'saved' => array(),
     373                );
     374                break;
     375            case 'cookie':
     376                foreach ($_COOKIE as $key => $value) {
     377                    // All cookie keys with our internal prefix. Use only the last part as the key.
     378                    if (preg_match('/^' . preg_quote(sprintf('strangecode-%s-', $this->_ns)) . '(.+)$/i', $key, $match)) {
     379                        $this->delete($match[1]);
     380                    }
     381                }
     382                break;
     383            }
     384            break;
    277385        case 'defaults' :
    278386            $_SESSION['_prefs'][$this->_ns]['defaults'] = array();
    279387            break;
    280 
    281388        case 'saved' :
    282389            $_SESSION['_prefs'][$this->_ns]['saved'] = array();
     
    298405    {
    299406        $app =& App::getInstance();
    300         $db =& DB::getInstance();
    301 
    302         // Skip this method if not using the db.
    303         if (true !== $this->getParam('persistent')) {
    304             return true;
    305         }
     407        $db =& DB::getInstance();
     408
     409        // Skip this method if not using the db.
     410        if ('database' != $this->getParam('storagetype')) {
     411            return true;
     412        }
    306413
    307414        $this->initDB();
    308415
    309416        // Prefs already loaded for this session.
    310         if (!$force && $this->_isLoaded()) {
    311             return true;
    312         }
     417        if (!$force && $this->_isLoaded()) {
     418            return true;
     419        }
    313420
    314421        // User_id must not be empty.
     
    322429
    323430        // Retrieve all prefs for this user and namespace.
    324         $qid = $db->query("
    325             SELECT pref_key, pref_value
    326             FROM " . $db->escapeString($this->getParam('db_table')) . "
    327             WHERE user_id = '" . $db->escapeString($this->getParam('user_id')) . "'
    328             AND pref_namespace = '" . $db->escapeString($this->_ns) . "'
    329             LIMIT 10000
    330         ");
    331         while (list($key, $val) = mysql_fetch_row($qid)) {
     431        $qid = $db->query("
     432            SELECT pref_key, pref_value
     433            FROM " . $db->escapeString($this->getParam('db_table')) . "
     434            WHERE user_id = '" . $db->escapeString($this->getParam('user_id')) . "'
     435            AND pref_namespace = '" . $db->escapeString($this->_ns) . "'
     436            LIMIT 10000
     437        ");
     438        while (list($key, $val) = mysql_fetch_row($qid)) {
    332439            $_SESSION['_prefs'][$this->_ns]['saved'][$key] = unserialize($val);
    333         }
    334 
    335         $app->logMsg(sprintf('Loaded %s prefs from database.', mysql_num_rows($qid)), LOG_DEBUG, __FILE__, __LINE__);
    336 
    337         // Data loaded only once per session.
    338         $_SESSION['_prefs'][$this->_ns]['loaded'] = true;
     440        }
     441
     442        $app->logMsg(sprintf('Loaded %s prefs from database.', mysql_num_rows($qid)), LOG_DEBUG, __FILE__, __LINE__);
     443
     444        // Data loaded only once per session.
     445        $_SESSION['_prefs'][$this->_ns]['loaded'] = true;
    339446        $_SESSION['_prefs'][$this->_ns]['load_datetime'] = date('Y-m-d H:i:s');
    340447
    341         return true;
     448        return true;
    342449    }
    343450
     
    354461    private function _isLoaded()
    355462    {
     463        if ('database' != $this->getParam('storagetype')) {
     464            return true;
     465        }
     466
    356467        if (isset($_SESSION['_prefs'][$this->_ns]['load_datetime'])
    357468        && strtotime($_SESSION['_prefs'][$this->_ns]['load_datetime']) > time() - $this->getParam('load_timeout')
     
    376487    {
    377488        $app =& App::getInstance();
    378         $db =& DB::getInstance();
    379 
    380         // Skip this method if not using the db.
    381         if (true !== $this->getParam('persistent')) {
    382             return true;
    383         }
     489        $db =& DB::getInstance();
     490
     491        // Skip this method if not using the db.
     492        if ('database' != $this->getParam('storagetype')) {
     493            return true;
     494        }
    384495
    385496        // User_id must not be empty.
     
    395506            $db->query("
    396507                DELETE FROM " . $db->escapeString($this->getParam('db_table')) . "
    397                 WHERE user_id = '" . $db->escapeString($this->getParam('user_id')) . "'
    398                 AND pref_namespace = '" . $db->escapeString($this->_ns) . "'
     508                WHERE user_id = '" . $db->escapeString($this->getParam('user_id')) . "'
     509                AND pref_namespace = '" . $db->escapeString($this->_ns) . "'
    399510            ");
    400511
     
    422533        return false;
    423534    }
     535
     536    /*
     537    *
     538    *
     539    * @access   public
     540    * @param
     541    * @return
     542    * @author   Quinn Comendant <quinn@strangecode.com>
     543    * @version  1.0
     544    * @since    02 May 2014 18:17:04
     545    */
     546    private function _getCookieName($key)
     547    {
     548        $app =& App::getInstance();
     549
     550        if (mb_strpos($key, sprintf('strangecode-%s', $this->_ns)) === 0) {
     551            $app->logMsg(sprintf('Invalid key name (%s). Leave off "strangecode-%s-" and it should work.', $key, $this->_ns), LOG_NOTICE, __FILE__, __LINE__);
     552        }
     553        return sprintf('strangecode-%s-%s', $this->_ns, $key);
     554    }
    424555}
    425556
Note: See TracChangeset for help on using the changeset viewer.