Source for file _abstractsettings.class.php
Documentation is available at _abstractsettings.class.php
* This file implements the AbstractSettings class designed to handle any kind of settings.
* This file is part of the evoCore framework - {@link http://evocore.net/}
* See also {@link http://sourceforge.net/projects/evocms/}.
* @copyright (c)2003-2006 by Francois PLANQUE - {@link http://fplanque.net/}
* Parts of this file are copyright (c)2004-2006 by Daniel HAHLER - {@link http://thequod.de/contact}.
* {@internal License choice
* - If you have received this file as part of a package, please find the license.txt file in
* the same folder or the closest folder above for complete license terms.
* - If you have received this file individually (e-g: from http://cvs.sourceforge.net/viewcvs.py/evocms/)
* then you must choose one of the following licenses before using the file:
* - GNU General Public License 2 (GPL) - http://www.opensource.org/licenses/gpl-license.php
* - Mozilla Public License 1.1 (MPL) - http://www.opensource.org/licenses/mozilla1.1.php
* {@internal Open Source relicensing agreement:
* Daniel HAHLER grants Francois PLANQUE the right to license
* Daniel HAHLER's contributions to this file and the b2evolution project
* under any OSI approved OSS license (http://www.opensource.org/licenses/).
* {@internal Below is a list of authors who have contributed to design/coding of this file: }}
* @author blueyed: Daniel HAHLER
* @author fplanque: Francois PLANQUE
* @version $Id: _abstractsettings.class.php,v 1.12.2.6 2006/11/15 21:05:24 blueyed Exp $
if( !defined('EVO_MAIN_INIT') ) die( 'Please, do not access this page directly.' );
* Class to handle settings in an abstract manner (to get used with either 1, 2 or 3 DB column keys).
* Arrays and Objects automatically get serialized and unserialized
* (in {@link AbstractSettings::get()} and {@link AbstractSettings::dbupdate()}).
* Note: I've evaluated splitting this into single classes for performance reasons, but only
* get() is relevant performance-wise and we could now only get rid of the switch() therein,
* which is not sufficient to split it into *_base + _X classes. (blueyed, 2006-08)
* @see UserSettings, GeneralSettings, PluginSettings, CollectionSettings
* The DB table which stores the settings.
* Array with DB column key names.
* DB column name for the value.
* The number of column keys to cache by. This are the first x keys of
* {@link $col_key_names}. 0 means 'load all'.
* @var array|NULL|falseContains the loaded settings or false, if settings
* could not be loaded or NULL if not initialized.
* Do we have loaded everything?
* Maps last colkeyname to some default setting that will be used by
* {@link get()} if no value was defined (and it is set as a default).
* @param string The name of the DB table with the settings stored.
* @param array List of names for the DB columns keys that reference a value.
* @param string The name of the DB column that holds the value.
* @param integer The number of column keys to cache by. This are the first x keys of {@link $col_key_names}. 0 means 'load all'.
function AbstractSettings( $db_table_name, $col_key_names, $col_value_name, $cache_by_col_keys =
0 )
* @var integer internal counter for the number of column keys
if( $this->count_col_key_names >
3 ||
$this->count_col_key_names <
1 )
* Load all settings, disregarding the derived classes setting of
* {@link $cache_by_col_keys} - useful if you know that you want to get
* all user settings for example.
* Loads the settings. Not meant to be called directly, but gets called
* @param string First column key
* @param string Second column key
* @param string Third column key
* @return boolean always true
function _load( $arg1 =
NULL, $arg2 =
NULL, $arg3 =
NULL )
* The where clause - gets filled when {@link $cache_by_col_keys} is used.
$testCache =
$this->cache;
$args =
array( $arg1, $arg2, $arg3 );
||
! isset
( $testCache[$args[$i]] )
||
! ($testCache =
& $testCache[$args[$i]]) )
{ // we're about to load everything
$result =
$DB->get_results( '
?
' WHERE '.
implode( ' AND ', $whereList )
switch( $this->count_col_key_names )
{ // Remember that we've tried it
$this->cache[ $arg1 ] =
NULL;
else foreach( $result as $loop_row )
{ // Remember that we've tried it
$this->cache[ $arg1 ][ $arg2 ] =
NULL;
else foreach( $result as $loop_row )
{ // Remember that we've tried it
$this->cache[ $arg1 ][ $arg2 ][ $arg3 ] =
NULL;
else foreach( $result as $loop_row )
* Get a setting from the DB settings table.
* @param string First column key
* @param string Second column key
* @param string Third column key
* @return string|false|NULLvalue as string on success; NULL if not found; false in case of error
function get( $col_key1, $col_key2 =
NULL, $col_key3 =
NULL )
$Timer->resume('abstractsettings_'.
$this_class.
'_get');
switch( $this->count_col_key_names )
$this->_load( $col_key1 );
if( isset
($this->cache[ $col_key1 ]->unserialized) )
{ // The value has been unserialized before:
$r =
$this->cache[ $col_key1 ]->value;
elseif( isset
($this->cache[ $col_key1 ]->value) )
{ // First attempt to access the value, we need to unserialize it:
// Try to unserialize setting (once) - this is as fast as checking an array of values that should get unserialized
$this->cache[ $col_key1 ]->value =
$r;
$r =
$this->cache[ $col_key1 ]->value;
$this->cache[ $col_key1 ]->unserialized =
true;
{ // The value is not in the cache, we use the default:
$this->cache[ $col_key1 ]->value =
$r; // remember in cache
$this->cache[ $col_key1 ]->dbUptodate =
true;
$this->cache[ $col_key1 ]->unserialized =
true;
$from_default =
true; // for debug
$this->_load( $col_key1, $col_key2 );
if( isset
($this->cache[ $col_key1 ][ $col_key2 ]->unserialized) )
$r =
$this->cache[ $col_key1 ][ $col_key2 ]->value;
elseif( isset
($this->cache[ $col_key1 ][ $col_key2 ]->value) )
// Try to unserialize setting (once) - this is as fast as checking an array of values that should get unserialized
if( ($r =
@unserialize($this->cache[ $col_key1 ][ $col_key2 ]->value)) !==
false )
$this->cache[ $col_key1 ][ $col_key2 ]->value =
$r;
$r =
$this->cache[ $col_key1 ][ $col_key2 ]->value;
$this->cache[ $col_key1 ][ $col_key2 ]->unserialized =
true;
$this->cache[ $col_key1 ][ $col_key2 ]->value =
$r; // remember in cache
$this->cache[ $col_key1 ][ $col_key2 ]->dbUptodate =
true;
$this->cache[ $col_key1 ][ $col_key2 ]->unserialized =
true;
$from_default =
true; // for debug
$this->_load( $col_key1, $col_key2, $col_key3 );
if( isset
($this->cache[ $col_key1 ][ $col_key2 ][ $col_key3 ]->unserialized) )
$r =
$this->cache[ $col_key1 ][ $col_key2 ][ $col_key3 ]->value;
elseif( isset
($this->cache[ $col_key1 ][ $col_key2 ][ $col_key3 ]->value) )
// Try to unserialize setting (once) - this is as fast as checking an array of values that should get unserialized
if( ($r =
@unserialize($this->cache[ $col_key1 ][ $col_key2 ][ $col_key3 ]->value)) !==
false )
$this->cache[ $col_key1 ][ $col_key2 ][ $col_key3 ]->value =
$r;
$r =
$this->cache[ $col_key1 ][ $col_key2 ][ $col_key3 ]->value;
$this->cache[ $col_key1 ][ $col_key2 ][ $col_key3 ]->unserialized =
true;
$this->cache[ $col_key1 ][ $col_key2 ][ $col_key3 ]->value =
$r; // remember in cache
$this->cache[ $col_key1 ][ $col_key2 ][ $col_key3 ]->dbUptodate =
true;
$this->cache[ $col_key1 ][ $col_key2 ][ $col_key3 ]->unserialized =
true;
$from_default =
true; // for debug
$Debuglog->add( $this_class.
'::get( '.
$col_key1.
'/'.
$col_key2.
'/'.
$col_key3.
' ): '
.
( isset
($from_default) ?
'[DEFAULT]: ' :
'' )
$Timer->pause('abstractsettings_'.
$this_class.
'_get');
* Get the default for the last key of {@link $col_key_names}
* @param string The last column key
* @return NULL|mixedNULL if no default is set, otherwise the value (should be string).
* Only set the first variable (passed by reference) if we could retrieve a
* @param mixed variable to set maybe (by reference)
* @param string the values for the column keys (depends on $this->col_key_names
* and must match its count and order)
* @return boolean true on success (variable was set), false if not
if( $result !==
NULL &&
$result !==
false )
{ // No error and value retrieved
* Temporarily sets a setting ({@link dbupdate()} writes it to DB).
* @param string $args,... the values for the {@link $col_key_names column keys}
* and {@link $col_value_name column value}. Must match order and count!
* @return boolean true, if the value has been set, false if it has not changed.
switch( $this->count_col_key_names )
$atCache =
& $this->cache[ $args[0] ];
$atCache =
& $this->cache[ $args[0] ][ $args[1] ];
$atCache =
& $this->cache[ $args[0] ][ $args[1] ][ $args[2] ];
$atCache->dbRemove =
false;
if( isset
($atCache->value) )
if( $atCache->value ==
$value )
$Debuglog->add( $debugMsg.
' Already set to the same value.', 'settings' );
$atCache->value =
$value;
$atCache->dbUptodate =
false;
$atCache->unserialized =
true;
$Debuglog->add( $debugMsg.
' SET!', 'settings' );
* Set an array of values.
* @param array Array of parameters for {@link set()}
foreach( $array as $lSet )
* @param array List of {@link $col_key_names}
switch( $this->count_col_key_names )
$atCache =
& $this->cache[ $args[0] ];
$atCache =
& $this->cache[ $args[0] ][ $args[1] ];
$atCache =
& $this->cache[ $args[0] ][ $args[1] ][ $args[2] ];
$atCache->dbRemove =
true;
unset
($atCache->unserialized);
* Delete an array of values.
* @param array Array of parameters for {@link delete()}
foreach( $array as $lDel )
* Delete values for {@link $_defaults default settings} in DB.
* This will use the default settings on the next {@link get()}
* @return boolean true, if settings have been updated; false otherwise
* Commit changed settings to DB.
* @return boolean true, if settings have been updated; false otherwise
if( empty($this->cache) )
$query_where_delete =
array();
switch( $this->count_col_key_names )
foreach( $this->cache as $key =>
$value )
{ // Remembered as not existing
if( ! empty($value->dbRemove) )
$query_where_delete[] =
"{
$this->col_key_names[0]} = '$key'";
unset
( $this->cache[$key] );
elseif( isset
($value->dbUptodate) &&
!$value->dbUptodate )
$query_insert[] =
"('$key', '".
$DB->escape( $value ).
"')";
$this->cache[$key]->dbUptodate =
true;
foreach( $this->cache as $key =>
$value )
foreach( $value as $key2 =>
$value2 )
{ // Remembered as not existing
if( ! empty($value2->dbRemove) )
$query_where_delete[] =
"{
$this->col_key_names[0]} = '
$key' AND {
$this->col_key_names[1]} = '
$key2'
";
unset
( $this->cache[$key][$key2] );
elseif( isset
($value2->dbUptodate) &&
!$value2->dbUptodate )
$value2 =
$value2->value;
$query_insert[] =
"('$key', '$key2', '".
$DB->escape( $value2 ).
"')";
$this->cache[$key][$key2]->dbUptodate =
true;
foreach( $this->cache as $key =>
$value )
foreach( $value as $key2 =>
$value2 )
foreach( $value2 as $key3 =>
$value3 )
{ // Remembered as not existing
if( ! empty($value3->dbRemove) )
$query_where_delete[] =
"{
$this->col_key_names[0]} = '
$key' AND {
$this->col_key_names[1]} = '
$key2' AND {
$this->col_key_names[2]} = '
$key3'
";
unset
( $this->cache[$key][$key2][$key3] );
elseif( isset
($value3->dbUptodate) &&
!$value3->dbUptodate )
$value3 =
$value3->value;
$query_insert[] =
"('$key', '$key2', '$key3', '".
$DB->escape( $value3 ).
"')";
$this->cache[$key][$key2][$key3]->dbUptodate =
true;
if( ! empty($query_where_delete) )
$query =
'DELETE FROM '.
$this->db_table_name.
" WHERE\n(".
implode( ")\nOR (", $query_where_delete ).
')';
$r = (boolean)
$DB->query( $query );
if( ! empty($query_insert) )
.
') VALUES '.
implode(', ', $query_insert);
$r =
$DB->query( $query ) ||
$r;
* Reset cache (includes settings to be written to DB).
* This is useful, to rollback settings that have been made, e.g. when a Plugin
* decides that his settings should not get updated.
* $Log: _abstractsettings.class.php,v $
* Revision 1.12.2.6 2006/11/15 21:05:24 blueyed
* MFH: - Fixed removing setting after delete() and get() (from defaults) (When getting value from default do not reset $dbRemove property)
* - Opt: default settings are already unserialized
* Revision 1.12.2.5 2006/11/15 20:19:35 blueyed
* MFH: Fixed AbstractSettings::delete(): unset properties in cache
* Revision 1.12.2.4 2006/11/04 19:54:54 fplanque
* Reinjected old Log blocks. Removing them from CVS was a bad idea -- especially since Daniel has decided branch 1.9 was his HEAD...
* Revision 1.12 2006/08/04 23:27:03 blueyed
* Fixed getting default values.
* Revision 1.11 2006/08/02 22:05:37 blueyed
* Optimized performance of (Abstract)Settings, especially get().
* Revision 1.10 2006/05/19 18:15:05 blueyed
* Merged from v-1-8 branch
* Revision 1.9.2.1 2006/05/19 15:06:24 fplanque
* Revision 1.9 2006/05/12 21:53:38 blueyed
* Fixes, cleanup, translation for plugins
* Revision 1.8 2006/05/02 22:17:10 blueyed
* use global DB object instead of property, so it does not get serialized with the object
* Revision 1.7 2006/04/20 17:30:53 blueyed
* Revision 1.6 2006/04/20 16:31:30 fplanque
* comment moderation (finished for 1.8)
* Revision 1.5 2006/04/19 20:13:50 fplanque
* do not restrict to :// (does not catch subdomains, not even www.)
* Revision 1.4 2006/03/12 23:08:59 fplanque
* Revision 1.3 2006/03/11 15:49:48 blueyed
* Allow a plugin to not update his settings at all.
* Revision 1.2 2006/02/24 15:09:31 blueyed
* Decent support for serialized settings through get() and dbupdate().
* Revision 1.1 2006/02/23 21:11:58 fplanque
* File reorganization to MVC (Model View Controller) architecture.
* See index.hml files in folders.
* (Sorry for all the remaining bugs induced by the reorg... :/)
* Revision 1.30 2006/01/26 20:27:45 blueyed
* Revision 1.28 2006/01/22 22:41:12 blueyed
* Added get_unserialized().
* Revision 1.27 2005/12/30 04:34:04 blueyed
* Small performance enhancements.
* Revision 1.26 2005/12/19 17:39:56 fplanque
* Remember prefered browing tab for each user.
* Revision 1.25 2005/12/12 19:21:21 fplanque
* big merge; lots of small mods; hope I didn't make to many mistakes :]
* Revision 1.24 2005/12/08 22:26:31 blueyed
* added restore_defaults(), use debug_die()
* Revision 1.23 2005/12/07 18:04:17 blueyed
* Revision 1.19 2005/11/01 23:03:22 blueyed
* Fix notice on rare occasion (a setting was remembered as not existing [set to NULL in cache], not changed/set and dbupdate()) called
* Revision 1.18 2005/10/28 02:37:37 blueyed
* Normalized AbstractSettings API
* Revision 1.17 2005/09/06 17:13:54 fplanque
* stop processing early if referer spam has been detected
* Revision 1.16 2005/07/12 22:54:14 blueyed
* Fixed get_cond(): respect NULL and false return value of get()
* Revision 1.15 2005/06/06 17:59:39 fplanque
* user dialog enhancements
* Revision 1.14 2005/05/04 19:40:41 fplanque
* cleaned up file settings a little bit
* Revision 1.13 2005/04/28 20:44:19 fplanque
* Revision 1.12 2005/02/28 09:06:31 blueyed
* removed constants for DB config (allows to override it from _config_TEST.php), introduced EVO_CONFIG_LOADED
* Revision 1.11 2005/01/10 20:29:26 blueyed
* Defaults / Refactored AbstractSettings
* Revision 1.10 2005/01/06 11:35:00 blueyed
* Revision 1.9 2005/01/06 05:20:14 blueyed
* refactored (constructor), getDefaults()
* Revision 1.8 2005/01/03 06:23:47 blueyed
* Revision 1.7 2004/12/30 14:29:42 fplanque
* Revision 1.5 2004/11/08 02:48:26 blueyed
* Revision 1.4 2004/11/08 02:23:44 blueyed
* allow caching by column keys (e.g. user ID)
* Revision 1.3 2004/10/23 21:32:42 blueyed
* documentation, return value
* Revision 1.2 2004/10/16 01:31:22 blueyed
* Revision 1.1 2004/10/13 22:46:32 fplanque
* Revision 1.13 2004/10/11 19:02:04 fplanque
* Edited code documentation.