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); } }