source: trunk/lib/Prefs.inc.php

Last change on this file was 784, checked in by anonymous, 14 months ago

Allow setting cookie_path

File size: 26.5 KB
Line 
1<?php
2/**
3 * The Strangecode Codebase - a general application development framework for PHP
4 * For details visit the project site: <http://trac.strangecode.com/codebase/>
5 * Copyright 2001-2012 Strangecode, LLC
6 *
7 * This file is part of The Strangecode Codebase.
8 *
9 * The Strangecode Codebase is free software: you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as published by the
11 * Free Software Foundation, either version 3 of the License, or (at your option)
12 * any later version.
13 *
14 * The Strangecode Codebase is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
17 * details.
18 *
19 * You should have received a copy of the GNU General Public License along with
20 * The Strangecode Codebase. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23/**
24 * Prefs.inc.php
25 *
26 * Prefs provides an API for saving arbitrary values in a user's session, in cookies, and in the database.
27 * Prefs can be stored into a database with the optional save() and load() methods.
28 *
29 * @author  Quinn Comendant <quinn@strangecode.com>
30 * @version 3.0
31 * @todo This class could really benefit from being refactored using the factory pattern, with backend storage mechanisms.
32 *
33 * Example of use (database storagetype):
34---------------------------------------------------------------------
35// Load preferences for the user's session.
36require_once 'codebase/lib/Prefs.inc.php';
37$prefs = new Prefs('my-namespace');
38$prefs->setParam(array(
39    'storagetype' => ($auth->isLoggedIn() ? 'database' : 'session'),
40    'user_id' => $auth->get('user_id'),
41));
42$prefs->setDefaults(array(
43    'search_num_results' => 25,
44    'datalog_num_entries' => 25,
45));
46$prefs->load();
47
48// Update preferences. Make sure to validate this input first!
49$prefs->set('search_num_results', getFormData('search_num_results'));
50$prefs->set('datalog_num_entries', getFormData('datalog_num_entries'));
51$prefs->save();
52---------------------------------------------------------------------
53 */
54class Prefs
55{
56
57    // Namespace of this instance of Prefs.
58    protected $_ns;
59
60    // Configuration parameters for this object.
61    protected $_params = array(
62
63        // Store preferences in one of the available storage mechanisms: session, cookie, database
64        // This default should remain set to 'session' for legacy support.
65        'storagetype' => 'session',
66
67        // This parameter is only used for legacy support, superseded by the 'storagetype' setting.
68        // Enable database storage. If this is false, all prefs will live only as long as the session.
69        'persistent' => null,
70
71        // ----------------------------------------------------------
72        // Cookie-type settings.
73
74        // 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).
75        'cookie_expire' => '+10 years',
76
77        // The path on the server in which the cookie will be available on.
78        'cookie_path' => '/',
79
80        // The domain that the cookie is available to.
81        'cookie_domain' => null,
82
83        // ----------------------------------------------------------
84        // Database-type settings.
85
86        // The current user_id for which to load/save database-backed preferences.
87        'user_id' => null,
88
89        // How long before we force a reload of the persistent prefs data?
90        'load_timeout' => 60,
91
92        // Name of database table to store prefs.
93        'db_table' => 'pref_tbl',
94
95        // Automatically create table and verify columns. Better set to false after site launch.
96        // This value is overwritten by the $app->getParam('db_create_tables') setting if it is available.
97        'create_table' => true,
98
99        // Original namespace set during __construct().
100        // 'namespace' => '',
101    );
102
103    /**
104     * Prefs constructor.
105     */
106    public function __construct($namespace='', array $params=null)
107    {
108        $app =& App::getInstance();
109
110        $this->_ns = $namespace;
111
112        // Save the original namespace for the DB pref_namespace column. $this->_ns, used in the SESSION variable, will change based on the user_id.
113        $this->setParam(array('namespace' => $namespace));
114
115        // Get create tables config from global context.
116        if (!is_null($app->getParam('db_create_tables'))) {
117            $this->setParam(array('create_table' => $app->getParam('db_create_tables')));
118        }
119
120        // Optional initial params.
121        $this->setParam($params);
122
123        if (isset($params['save_on_shutdown']) && $params['save_on_shutdown']) {
124            // Run Prefs->save() upon script completion if we're using the database storagetype.
125            // This only works if:
126            // - 'storagetype' is provided as a parameter to the constructor rather than via setParam() later.
127            // - $app->stop() is not called at the end of the script (which would close the PDO connection before the shutdown function runs).
128            if ('database' == $this->getParam('storagetype')) {
129                register_shutdown_function(array($this, 'save'));
130            }
131        }
132    }
133
134    /**
135     * Setup the database table for this class.
136     *
137     * @access  public
138     * @author  Quinn Comendant <quinn@strangecode.com>
139     * @since   04 Jun 2006 16:41:42
140     */
141    public function initDB($recreate_db=false)
142    {
143        $app =& App::getInstance();
144        $pdo =& \Strangecode\Codebase\PDO::getInstance();
145
146        static $_db_tested = false;
147
148        if ($recreate_db || !$_db_tested && $this->getParam('create_table')) {
149            if ($recreate_db) {
150                $pdo->query(sprintf("DROP TABLE IF EXISTS `%s`", $pdo->sanitizeIdentifier($this->getParam('db_table'))));
151                $app->logMsg(sprintf('Dropping and recreating table %s.', $this->getParam('db_table')), LOG_INFO, __FILE__, __LINE__);
152            }
153            $stmt = $pdo->query(sprintf("
154                CREATE TABLE IF NOT EXISTS `%s` (
155                    `user_id` VARCHAR(32) NOT NULL DEFAULT '',
156                    `pref_namespace` VARCHAR(32) NOT NULL DEFAULT '',
157                    `pref_key` VARCHAR(64) NOT NULL DEFAULT '',
158                    `pref_value` TEXT,
159                    PRIMARY KEY (`user_id`, `pref_namespace`, `pref_key`)
160                )
161            ", $pdo->sanitizeIdentifier($this->getParam('db_table'))));
162
163            if (!$pdo->columnExists($this->getParam('db_table'), array(
164                'user_id',
165                'pref_namespace',
166                'pref_key',
167                'pref_value',
168            ), false, false)) {
169                $app->logMsg(sprintf('Database table %s has invalid columns. Please update this table manually.', $this->getParam('db_table')), LOG_ALERT, __FILE__, __LINE__);
170                trigger_error(sprintf('Database table %s has invalid columns. Please update this table manually.', $this->getParam('db_table')), E_USER_ERROR);
171            }
172        }
173        $_db_tested = true;
174    }
175
176    /**
177     * Set the params of this object.
178     *
179     * @param  array $params   Array of param keys and values to set.
180     */
181    public function setParam(array $params=null)
182    {
183        $app =& App::getInstance();
184
185        // CLI scripts can't use prefs stored in HTTP-based protocols.
186        if ($app->isCLI()
187        && isset($params['storagetype'])
188        && in_array($params['storagetype'], array('cookie', 'session'))) {
189            $app->logMsg(sprintf('Storage type %s not available for CLI', $params['storagetype']), LOG_DEBUG, __FILE__, __LINE__);
190        }
191
192        // Convert the legacy param 'persistent' to 'storagetype=database'.
193        // Old sites would set 'persistent' to true (use database) or false (use sessions).
194        // If it is true, we set storagetype=database here.
195        // If false, we rely on the default, sessions (which is assigned in the params).
196        if (isset($params['persistent']) && $params['persistent'] && !isset($params['storagetype'])) {
197            $params['storagetype'] = 'database';
198        }
199
200        // Append the user_id to the namespace to keep separate collections for different users.
201        if (isset($params['user_id']) && $params['user_id']) {
202            // $this->getParam('namespace') should always be available since it is set in __construct().
203            $this->_ns = sprintf('%s-%s', $this->getParam('namespace'), $params['user_id']);
204        }
205
206        // Check max DB string lengths.
207        if ((isset($params['storagetype']) && $params['storagetype'] == 'database') || $this->getParam('storagetype') == 'database') {
208            if (isset($params['user_id']) && mb_strlen($params['user_id']) > 32) {
209                $app->logMsg(sprintf('Prefs user_id param longer than 32 characters: %s', $params['user_id']), LOG_ERR, __FILE__, __LINE__);
210            }
211            if (isset($params['namespace']) && mb_strlen($params['namespace']) > 32) {
212                $app->logMsg(sprintf('Prefs namespace longer than 32 characters: %s', $this->_ns), LOG_ERR, __FILE__, __LINE__);
213            }
214            if (isset($params['pref_key']) && mb_strlen($params['pref_key']) > 64) {
215                $app->logMsg(sprintf('Prefs pref_key param longer than 64 characters: %s', $params['pref_key']), LOG_ERR, __FILE__, __LINE__);
216            }
217        }
218
219        if (isset($params) && is_array($params)) {
220            // Merge new parameters with old overriding only those passed.
221            $this->_params = array_merge($this->_params, $params);
222        }
223    }
224
225    /**
226     * Return the value of a parameter, if it exists.
227     *
228     * @access public
229     * @param string $param        Which parameter to return.
230     * @return mixed               Configured parameter value.
231     */
232    public function getParam($param)
233    {
234        $app =& App::getInstance();
235
236        if (array_key_exists($param, $this->_params)) {
237            return $this->_params[$param];
238        } else {
239            $app->logMsg(sprintf('Parameter is not set: %s', $param), LOG_DEBUG, __FILE__, __LINE__);
240            return null;
241        }
242    }
243
244    /*
245    * Setup the SESSION storage array. This method is called at the beginning of each method that accesses $_SESSION['_prefs'].
246    *
247    * @access   public
248    * @param
249    * @return
250    * @author   Quinn Comendant <quinn@strangecode.com>
251    * @since    02 Oct 2018 15:35:09
252    */
253    private function _init()
254    {
255        if ('cookie' != $this->getParam('storagetype') && !isset($_SESSION['_prefs'][$this->_ns])) {
256            $this->clear();
257        }
258    }
259
260    /**
261     * Sets the default values for preferences. If a preference is not explicitly
262     * set, the value set here will be used. Can be called multiple times to merge additional
263     * defaults together. This is mostly only useful for the database storagetype, when you have
264     * values you want to use as default, and those are not stored to the database (so the defaults
265     * can be changed later and apply to all users who haven't make s specific setting).
266     * For the cookie storagetype, using setDefaults just sets cookies but only if a cookie with
267     * the same name is not already set.
268     *
269     * @param  array $defaults  Array of key-value pairs
270     */
271    public function setDefaults($defaults)
272    {
273        $app =& App::getInstance();
274
275        $this->_init();
276
277        if (isset($defaults) && is_array($defaults)) {
278            switch ($this->getParam('storagetype')) {
279            case 'session':
280            case 'database':
281                $_SESSION['_prefs'][$this->_ns]['defaults'] = array_merge($_SESSION['_prefs'][$this->_ns]['defaults'], $defaults);
282                break;
283
284            case 'cookie':
285                foreach ($defaults as $key => $val) {
286                    if (!$this->exists($key)) {
287                        $this->set($key, $val);
288                    }
289                }
290                unset($key, $val);
291                break;
292            }
293        } else {
294            $app->logMsg(sprintf('Wrong data-type passed to Prefs->setDefaults().', null), LOG_NOTICE, __FILE__, __LINE__);
295        }
296    }
297
298    /**
299     * Store a key-value pair.
300     * When using the database storagetype, if the value is different than what is set by setDefaults the value will be scheduled to be saved in the database.
301     *
302     * @param  string $key          The name of the preference to modify.
303     * @param  string $val          The new value for this preference.
304     */
305    public function set($key, $val)
306    {
307        $app =& App::getInstance();
308
309        if (!is_string($key)) {
310            $app->logMsg(sprintf('Key is not a string-compatible type (%s)', getDump($key)), LOG_NOTICE, __FILE__, __LINE__);
311            return false;
312        }
313        if ('' == trim($key)) {
314            $app->logMsg(sprintf('Key is empty (along with value: %s)', $val), LOG_NOTICE, __FILE__, __LINE__);
315            return false;
316        }
317        if (!is_scalar($val) && !is_array($val) && !is_object($val)) {
318            $app->logMsg(sprintf('Value is not a compatible data type (%s=%s)', $key, getDump($val)), LOG_WARNING, __FILE__, __LINE__);
319            return false;
320        }
321
322        $this->_init();
323
324        switch ($this->getParam('storagetype')) {
325        // Both session and database prefs are saved in the session (for database, only temporarily until they are saved).
326        case 'session':
327        case 'database':
328            // Set a saved preference if...
329            // - there isn't a default.
330            // - or the new value is different than the default
331            // - or there is a previously existing saved key.
332            if (!(isset($_SESSION['_prefs'][$this->_ns]['defaults']) && array_key_exists($key, $_SESSION['_prefs'][$this->_ns]['defaults']))
333            || $_SESSION['_prefs'][$this->_ns]['defaults'][$key] != $val
334            || $this->exists($key)) {
335                $_SESSION['_prefs'][$this->_ns]['saved'][$key] = $val;
336                $app->logMsg(sprintf('Setting session/database preference %s => %s', $key, getDump($val, true)), LOG_DEBUG, __FILE__, __LINE__);
337            } else {
338                $app->logMsg(sprintf('Not setting session/database preference %s => %s', $key, getDump($val, true)), LOG_DEBUG, __FILE__, __LINE__);
339            }
340            break;
341
342        case 'cookie':
343            $name = $this->_getCookieName($key);
344            $val = json_encode($val);
345            $app->setCookie($name, $val, $this->getParam('cookie_expire'), $this->getParam('cookie_path'), $this->getParam('cookie_domain'));
346            $_COOKIE[$name] = $val;
347            $app->logMsg(sprintf('Setting cookie preference %s => %s', $key, $val), LOG_DEBUG, __FILE__, __LINE__);
348            break;
349        }
350
351    }
352
353    /**
354     * Returns the value of the requested preference. Saved values take precedence, but if none is set
355     * a default value is returned, or if not that, null.
356     *
357     * @param string $key       The name of the preference to retrieve (or null to retrieve all keys).
358     * @return string           The value of the preference.
359     */
360    public function get($key=null)
361    {
362        $app =& App::getInstance();
363
364        $this->_init();
365
366        switch ($this->getParam('storagetype')) {
367        case 'session':
368        case 'database':
369            if (is_null($key) && isset($_SESSION['_prefs'][$this->_ns]['saved'])) {
370                return $_SESSION['_prefs'][$this->_ns]['saved'];
371            }
372            if ($this->exists($key)) {
373                $app->logMsg(sprintf('Found %s in saved', $key), LOG_DEBUG, __FILE__, __LINE__);
374                return $_SESSION['_prefs'][$this->_ns]['saved'][$key];
375            }
376            if (isset($_SESSION['_prefs'][$this->_ns]['defaults']) && array_key_exists($key, $_SESSION['_prefs'][$this->_ns]['defaults'])) {
377                $app->logMsg(sprintf('Found %s in defaults', $key), LOG_DEBUG, __FILE__, __LINE__);
378                return $_SESSION['_prefs'][$this->_ns]['defaults'][$key];
379            }
380            $app->logMsg(sprintf('Key not found in prefs cache: %s', $key), LOG_DEBUG, __FILE__, __LINE__);
381            return null;
382
383        case 'cookie':
384            if (is_null($key)) {
385                $app->logMsg(sprintf('Unable to get(null) when using cookie storagetype.', null), LOG_WARNING, __FILE__, __LINE__);
386                return null;
387            }
388            $name = $this->_getCookieName($key);
389            if ($this->exists($key) && '' != $_COOKIE[$name]) {
390                $val = json_decode($_COOKIE[$name], true);
391                $app->logMsg(sprintf('Found %s in cookie: %s', $key, getDump($val)), LOG_DEBUG, __FILE__, __LINE__);
392                return $val;
393            }
394            $app->logMsg(sprintf('Did not find %s in cookie', $key), LOG_DEBUG, __FILE__, __LINE__);
395            return null;
396        }
397    }
398
399    /**
400     * To see if a preference has been set.
401     *
402     * @param string $key       The name of the preference to check.
403     * @return boolean          True if the preference isset and not empty false otherwise.
404     */
405    public function exists($key)
406    {
407        $this->_init();
408
409        switch ($this->getParam('storagetype')) {
410        case 'session':
411        case 'database':
412            // isset() does not return TRUE for array keys that correspond to a NULL value, while array_key_exists() does.
413            return (isset($_SESSION['_prefs'][$this->_ns]['saved']) && array_key_exists($key, $_SESSION['_prefs'][$this->_ns]['saved']));
414
415        case 'cookie':
416            $name = $this->_getCookieName($key);
417            return (isset($_COOKIE) && array_key_exists($name, $_COOKIE));
418        }
419
420    }
421
422    /**
423     * Delete an existing preference value. This will also remove the value from the database, once save() is called.
424     *
425     * @param string $key       The name of the preference to delete.
426     */
427    public function delete($key)
428    {
429        $app =& App::getInstance();
430
431        $this->_init();
432
433        switch ($this->getParam('storagetype')) {
434        case 'session':
435        case 'database':
436            unset($_SESSION['_prefs'][$this->_ns]['saved'][$key]);
437            break;
438
439        case 'cookie':
440            if ($this->exists($key)) {
441                // Just set the existing value to an empty string, which expires in the past.
442                $name = $this->_getCookieName($key);
443                $app->setCookie($name, '', time() - 86400);
444                // Also unset the received cookie value, so it is unavailable.
445                unset($_COOKIE[$name]);
446            }
447            break;
448        }
449
450    }
451
452    /**
453     * Resets all existing values under this namespace. This should be executed with the same consideration as $auth->clear(), such as when logging out.
454     * Set $save true to persist the clear action to the storage (i.e., erase all stored prefs for this user).
455     */
456    public function clear($scope='all', $save=false)
457    {
458        $app =& App::getInstance();
459
460        switch ($scope) {
461        case 'all' :
462            switch ($this->getParam('storagetype')) {
463            case 'session':
464            case 'database':
465                $_SESSION['_prefs'][$this->_ns] = array(
466                    'loaded' => false,
467                    'load_datetime' => '1970-01-01',
468                    'defaults' => array(),
469                    'saved' => array(),
470                );
471                break;
472            case 'cookie':
473                foreach ($_COOKIE as $key => $value) {
474                    // All cookie keys with our internal prefix. Use only the last part as the key.
475                    if (preg_match('/^' . preg_quote(sprintf('_prefs-%s-', $this->_ns)) . '(.+)$/i', $key, $match)) {
476                        $this->delete($match[1]);
477                    }
478                }
479                break;
480            }
481            break;
482
483        case 'defaults' :
484            $_SESSION['_prefs'][$this->_ns]['defaults'] = array();
485            break;
486
487        case 'saved' :
488            $_SESSION['_prefs'][$this->_ns]['saved'] = array();
489            break;
490        }
491
492        if ($save) {
493            $this->save(true);
494            $app->logMsg(sprintf('Deleted all %s %s prefs for user_id %s', $this->getParam('storagetype'), $this->_ns, $this->getParam('user_id')), LOG_INFO, __FILE__, __LINE__);
495        } else {
496            $app->logMsg(sprintf('Cleared %s %s prefs', $scope, $this->_ns), LOG_DEBUG, __FILE__, __LINE__);
497        }
498    }
499
500    /*
501    * Retrieves all prefs from the database and stores them in the $_SESSION.
502    *
503    * @access   public
504    * @param    bool    $force  Set to always load from database, regardless if _isLoaded() or not.
505    * @return   bool    True if loading succeeded.
506    * @author   Quinn Comendant <quinn@strangecode.com>
507    * @version  1.0
508    * @since    04 Jun 2006 16:56:53
509    */
510    public function load($force=false)
511    {
512        $app =& App::getInstance();
513        $pdo =& \Strangecode\Codebase\PDO::getInstance();
514
515        // Skip this method if not using the db.
516        if ('database' != $this->getParam('storagetype')) {
517            $app->logMsg('Prefs->load() does nothing unless using a database storagetype.', LOG_DEBUG, __FILE__, __LINE__);
518            return true;
519        }
520
521        $this->initDB();
522
523        $this->_init();
524
525        // Prefs already loaded for this session.
526        if (!$force && $this->_isLoaded()) {
527            return true;
528        }
529
530        // User_id must not be empty.
531        if ('' == $this->getParam('user_id')) {
532            $app->logMsg(sprintf('Cannot load prefs because user_id not set.', null), LOG_WARNING, __FILE__, __LINE__);
533            return false;
534        }
535
536        // Clear existing cache.
537        $this->clear('saved');
538
539        // Retrieve all prefs for this user and namespace.
540        $stmt = $pdo->prepare(sprintf("SELECT `pref_key`, `pref_value` FROM `%s` WHERE `user_id` = ? AND `pref_namespace` = ? LIMIT 100000", $pdo->sanitizeIdentifier($this->getParam('db_table'))));
541        $stmt->execute([$this->getParam('user_id'), $this->getParam('namespace')]);
542        while (list($key, $val) = $stmt->fetch(\PDO::FETCH_NUM)) {
543            $_SESSION['_prefs'][$this->_ns]['saved'][$key] = unserialize($val);
544        }
545
546        $app->logMsg(sprintf('Loaded %s prefs from database.', sizeof($_SESSION['_prefs'][$this->_ns]['saved'])), LOG_DEBUG, __FILE__, __LINE__);
547
548        // Data loaded only once per session.
549        $_SESSION['_prefs'][$this->_ns]['loaded'] = true;
550        $_SESSION['_prefs'][$this->_ns]['load_datetime'] = date('Y-m-d H:i:s');
551
552        return true;
553    }
554
555    /*
556    * Returns true if the prefs had been loaded from the database into the $_SESSION recently.
557    * This function is simply a check so the database isn't access every page load.
558    *
559    * @access   private
560    * @return   bool    True if prefs are loaded.
561    * @author   Quinn Comendant <quinn@strangecode.com>
562    * @version  1.0
563    * @since    04 Jun 2006 17:12:44
564    */
565    protected function _isLoaded()
566    {
567        if ('database' != $this->getParam('storagetype')) {
568            $app->logMsg('Prefs->_isLoaded() does nothing unless using a database storagetype.', LOG_DEBUG, __FILE__, __LINE__);
569            return true;
570        }
571
572        $this->_init();
573
574        if (isset($_SESSION['_prefs'][$this->_ns]['load_datetime'])
575        && strtotime($_SESSION['_prefs'][$this->_ns]['load_datetime']) > time() - $this->getParam('load_timeout')
576        && isset($_SESSION['_prefs'][$this->_ns]['loaded'])
577        && true === $_SESSION['_prefs'][$this->_ns]['loaded']) {
578            return true;
579        } else {
580            return false;
581        }
582    }
583
584    /*
585    * Saves all prefs stored in the $_SESSION into the database.
586    *
587    * @access   public
588    * @return   bool    True if prefs exist and were saved.
589    * @author   Quinn Comendant <quinn@strangecode.com>
590    * @version  1.0
591    * @since    04 Jun 2006 17:19:56
592    */
593    public function save($allow_empty=false)
594    {
595        $app =& App::getInstance();
596        $pdo =& \Strangecode\Codebase\PDO::getInstance();
597
598        // Skip this method if not using the db.
599        if ('database' != $this->getParam('storagetype')) {
600            $app->logMsg('Prefs->save() does nothing unless using a database storagetype.', LOG_DEBUG, __FILE__, __LINE__);
601            return true;
602        }
603
604        // User_id must not be empty.
605        if ('' == $this->getParam('user_id')) {
606            $app->logMsg(sprintf('Cannot save prefs because user_id not set.', null), LOG_DEBUG, __FILE__, __LINE__);
607            return false;
608        }
609
610        $this->initDB();
611
612        $this->_init();
613
614        if (isset($_SESSION['_prefs'][$this->_ns]['saved']) && is_array($_SESSION['_prefs'][$this->_ns]['saved']) && ($allow_empty || !empty($_SESSION['_prefs'][$this->_ns]['saved']))) {
615            // Delete old prefs from database.
616            $stmt = $pdo->prepare(sprintf("DELETE FROM `%s` WHERE `user_id` = ? AND `pref_namespace` = ?", $pdo->sanitizeIdentifier($this->getParam('db_table'))));
617            $stmt->execute([$this->getParam('user_id'), $this->getParam('namespace')]);
618
619            // Insert new prefs.
620            $insert_values = array();
621            foreach ($_SESSION['_prefs'][$this->_ns]['saved'] as $key => $val) {
622                $insert_values[] = sprintf("(%s, %s, %s, %s)",
623                    $pdo->quote($this->getParam('user_id')),
624                    $pdo->quote($this->getParam('namespace')),
625                    $pdo->quote($key),
626                    $pdo->quote(serialize($val))
627                );
628            }
629            if (!empty($insert_values)) {
630                $stmt = $pdo->query(sprintf("
631                    INSERT INTO `%s`
632                    (`user_id`, `pref_namespace`, `pref_key`, `pref_value`)
633                    VALUES
634                    %s
635                ", $pdo->sanitizeIdentifier($this->getParam('db_table')), join(', ', $insert_values)));
636                $app->logMsg(sprintf('Saved %s prefs to database for user_id %s.', sizeof($insert_values), $this->getParam('user_id')), LOG_DEBUG, __FILE__, __LINE__);
637            }
638
639            return true;
640        }
641
642        return false;
643    }
644
645    /*
646    *
647    *
648    * @access   public
649    * @param
650    * @return
651    * @author   Quinn Comendant <quinn@strangecode.com>
652    * @version  1.0
653    * @since    02 May 2014 18:17:04
654    */
655    protected function _getCookieName($key)
656    {
657        $app =& App::getInstance();
658
659        if (mb_strpos($key, sprintf('_prefs-%s', $this->_ns)) === 0) {
660            $app->logMsg(sprintf('Invalid key name (%s). Leave off "_prefs-%s-" and it should work.', $key, $this->_ns), LOG_NOTICE, __FILE__, __LINE__);
661        }
662        // Use standardized class data names: _ + classname + namespace + variablekey
663        // (namespace = namespace + user_id)
664        return sprintf('_prefs-%s-%s', $this->_ns, $key);
665    }
666}
667
Note: See TracBrowser for help on using the repository browser.