connection Database connection object
protected $table; ///< string Settings table name
protected $blog_id; ///< string Blog ID
protected $namespaces = array(); ///< array Associative namespaces array
protected $ns; ///< string Current namespace
/**
Object constructor. Retrieves blog settings and puts them in $namespaces
array. Local (blog) settings have a highest priority than global settings.
@param core dcCore dcCore object
@param blog_id string Blog ID
*/
public function __construct($core,$blog_id)
{
$this->core = &$core;
$this->con = &$core->con;
$this->table = $core->prefix.'setting';
$this->blog_id = &$blog_id;
$this->loadSettings();
}
/**
Retrieves all namespaces (and their settings) from database, with one query.
*/
private function loadSettings()
{
$strReq = 'SELECT blog_id, setting_id, setting_value, '.
'setting_type, setting_label, setting_ns '.
'FROM '.$this->table.' '.
"WHERE blog_id = '".$this->con->escape($this->blog_id)."' ".
'OR blog_id IS NULL '.
'ORDER BY setting_ns ASC, setting_id DESC';
try {
$rs = $this->con->select($strReq);
} catch (Exception $e) {
trigger_error(__('Unable to retrieve namespaces:').' '.$this->con->error(), E_USER_ERROR);
}
/* Prevent empty tables (install phase, for instance) */
if ($rs->isEmpty()) {
return;
}
do {
$ns = trim($rs->f('setting_ns'));
if (!$rs->isStart()) {
// we have to go up 1 step, since namespaces construction performs a fetch()
// at very first time
$rs->movePrev();
}
$this->namespaces[$ns] = new dcNamespace($this->core, $this->blog_id, $ns,$rs);
} while(!$rs->isStart());
}
/**
Create a new namespace. If the namespace already exists, return it without modification.
@param ns string Namespace name
@return dcNamespace The namespace created
*/
public function addNamespace($ns)
{
if (!array_key_exists($ns, $this->namespaces)) {
$this->namespaces[$ns] = new dcNamespace($this->core, $this->blog_id, $ns);
}
return $this->namespaces[$ns];
}
/**
Rename a namespace.
@param oldNs string Old namespace name
@param newNs string New namespace name
@return boolean
*/
public function renNamespace($oldNs,$newNs)
{
if (!array_key_exists($oldNs, $this->namespaces) || array_key_exists($newNs, $this->namespaces)) {
return false;
}
// Rename the namespace in the namespace array
$this->namespaces[$newNs] = $this->namespaces[$oldNs];
unset($this->namespaces[$oldNs]);
// Rename the namespace in the database
$strReq = 'UPDATE '.$this->table.
" SET setting_ns = '".$this->con->escape($newNs)."' ".
" WHERE setting_ns = '".$this->con->escape($oldNs)."' ";
$this->con->execute($strReq);
return true;
}
/**
Delete a whole namespace with all settings pertaining to it.
@param ns string Namespace name
@return boolean
*/
public function delNamespace($ns)
{
if (!array_key_exists($ns, $this->namespaces)) {
return false;
}
// Remove the namespace from the namespace array
unset($this->namespaces[$ns]);
// Delete all settings from the namespace in the database
$strReq = 'DELETE FROM '.$this->table.
" WHERE setting_ns = '".$this->con->escape($ns)."' ";
$this->con->execute($strReq);
return true;
}
/**
Returns full namespace with all settings pertaining to it.
@param ns string Namespace name
@return dcNamespace
*/
public function get($ns)
{
return $this->namespaces[$ns];
}
/**
Magic __get method.
@copydoc ::get
*/
public function __get($n)
{
if (!array_key_exists($n, $this->namespaces)) {
// For backward compatibility only: the developer tried to access
// a setting directly, without passing via a namespace.
$this->raiseDeprecated('old_style_get');
return $this->getSetting($n);
}
return $this->get($n);
}
/**
Magic __set method.
@copydoc ::set
*/
public function __set($n,$v)
{
$this->set($n,$v);
}
/**
Returns $namespaces property content.
@return array
*/
public function dumpNamespaces()
{
return $this->namespaces;
}
/**
Raises a E_USER_NOTICE errror for deprecated functions.
This allows the developer to know he's been using deprecated functions.
@param name string Name of the deprecated function that was called.
*/
private function raiseDeprecated($name)
{
if (DC_DEBUG) {
$trace = debug_backtrace();
array_shift($trace);
$grand = array_shift($trace);
$msg = 'Deprecated function called. (';
$msg .= 'dcSettings::'.$name . ' was called from '.$grand['file'].' ['.$grand['line'].'])';
trigger_error($msg, E_USER_NOTICE);
}
}
/**
@deprecated Please set your settings via $core->blog->settings->{namespace}->{setting}
Sets a setting in $settings property. This sets the setting for script
execution time only and if setting exists.
@param n string Setting name
@param v mixed Setting value
*/
public function set($n,$v)
{
// For backward compatibility only: the developer tried to access
// a setting directly, without passing via a namespace.
$this->raiseDeprecated('old_style_set');
if (!$this->ns) {
throw new Exception(__('No namespace specified'));
}
if (isset($this->namespaces[$this->ns]->$n)) {
$this->namespaces[$this->ns]->$n['value'] = $v;
} else {
$this->namespaces[$this->ns]->$n = array(
'ns' => $this->ns,
'value' => $v,
'type' => gettype($n),
'label' => '',
'global' => false
);
}
}
/**
@deprecated Please access your settings via $core->blog->settings->{namespace}->...
Sets a working namespace. You should do this before accessing any setting.
@param ns string Namespace name
*/
public function setNamespace($ns)
{
$this->raiseDeprecated('setNamespace');
if (preg_match('/^[a-zA-Z][a-zA-Z0-9]+$/',$ns)) {
$this->ns = $ns;
} else {
throw new Exception(sprintf(__('Invalid setting namespace: %s'),$ns));
}
}
/**
@deprecated Please set your settings via $core->blog->settings->{namespace}->put()
Creates or updates a setting.
$type could be 'string', 'integer', 'float', 'boolean' or null. If $type is
null and setting exists, it will keep current setting type.
$value_change allow you to not change setting. Useful if you need to change
a setting label or type and don't want to change its value.
Don't forget to set namespace before calling this method.
@param id string Setting ID
@param value mixed Setting value
@param type string Setting type
@param label string Setting label
@param value_change boolean Change setting value or not
@param global boolean Setting is global
*/
public function put($id,$value,$type=null,$label=null,$value_change=true,$global=false)
{
$this->raiseDeprecated('put');
if (!$this->ns) {
throw new Exception(__('No namespace specified'));
}
if (!isset($this->namespaces[$this->ns])) {
// Create namespace if needed
$this->namespaces[$this->ns] = new dcNamespace($this->core, $this->blog_id, $this->ns);
}
$this->namespaces[$this->ns]->put($id, $value, $type, $label, $value_change, $global);
}
/**
@deprecated Please get your settings via $core->blog->settings->{namespace}->{setting}
Returns setting value if exists.
@param n string Setting name
@return mixed
*/
public function getSetting($n)
{
if ($this->namespaces['system']->get($n) != null) {
// Give preference to system settings
return $this->namespaces['system']->get($n);
} else {
// Parse all the namespaces
foreach (array_keys($this->namespaces) as $id => $ns) {
if ($this->namespaces[$ns]->get($n) != null) {
// Return the first setting with matching name
return $this->namespaces[$ns]->get($n);
}
}
}
return null;
}
/**
@deprecated Please get your settings via $core->blog->settings->{namespace}->dumpSettings
Returns all settings content.
@return array
*/
public function dumpSettings()
{
// For backward compatibility only: the developer tried to access
// the settings directly, without passing via a namespace.
$this->raiseDeprecated('dumpSettings');
$settings = array();
// Parse all the namespaces
foreach (array_keys($this->namespaces) as $id => $ns) {
$settings = array_merge($settings, $this->namespaces[$ns]->dumpSettings());
}
return $settings;
}
/**
@deprecated Please get your settings via $core->blog->settings->{namespace}->dumpGlobalSettings
Returns all global settings content.
@return array
*/
public function dumpGlobalSettings()
{
// For backward compatibility only: the developer tried to access
// the settings directly, without passing via a namespace.
$this->raiseDeprecated('dumpGlobalSettings');
$settings = array();
// Parse all the namespaces
foreach (array_keys($this->namespaces) as $id => $ns) {
$settings = array_merge($settings, $this->namespaces[$ns]->dumpGlobalSettings());
}
return $settings;
}
/**
Returns a list of settings matching given criteria, for any blog.
$params is an array taking the following
optionnal parameters:
- ns : retrieve setting from given namespace
- id : retrieve only settings corresponding to the given id
@param params array Parameters
@return record A record
*/
public function getGlobalSettings($params=array())
{
$strReq = "SELECT * from ".$this->table." ";
$where = array();
if (!empty($params['ns'])) {
$where[] = "setting_ns = '".$this->con->escape($params['ns'])."'";
}
if (!empty($params['id'])) {
$where[] = "setting_id = '".$this->con->escape($params['id'])."'";
}
if (isset($params['blog_id'])) {
if (!empty($params['blog_id'])) {
$where[] = "blog_id = '".$this->con->escape($params['blog_id'])."'";
} else {
$where[] = "blog_id IS NULL";
}
}
if (count($where) != 0) {
$strReq .= " WHERE ".join(" AND ", $where);
}
$strReq .= " ORDER by blog_id";
return $this->con->select($strReq);
}
/**
Updates a setting from a given record
@param rs record the setting to update
*/
public function updateSetting($rs)
{
$cur = $this->con->openCursor($this->table);
$cur->setting_id = $rs->setting_id;
$cur->setting_value = $rs->setting_value;
$cur->setting_type = $rs->setting_type;
$cur->setting_label = $rs->setting_label;
$cur->blog_id = $rs->blog_id;
$cur->setting_ns = $rs->setting_ns;
if ($cur->blog_id == null) {
$where = 'WHERE blog_id IS NULL ';
} else {
$where = "WHERE blog_id = '".$this->con->escape($cur->blog_id)."' ";
}
$cur->update($where."AND setting_id = '".$this->con->escape($cur->setting_id)."' AND setting_ns = '".$this->con->escape($cur->setting_ns)."' ");
}
/**
Drops a setting from a given record
@param rs record the setting to drop
@return int number of deleted records (0 if setting does not exist)
*/
public function dropSetting($rs) {
$strReq = "DELETE FROM ".$this->table.' ';
if ($rs->blog_id == null) {
$strReq .= 'WHERE blog_id IS NULL ';
} else {
$strReq .= "WHERE blog_id = '".$this->con->escape($rs->blog_id)."' ";
}
$strReq .= "AND setting_id = '".$this->con->escape($rs->setting_id)."' AND setting_ns = '".$this->con->escape($rs->setting_ns)."' ";
return $this->con->execute($strReq);
}
}