Dotclear

source: inc/core/class.dc.settings.php @ 934:1ab99955f080

Revision 934:1ab99955f080, 11.9 KB checked in by franck <carnet.franck.paul@…>, 11 years ago (diff)

Add some methods to namespaces (settings) and workspaces (prefs), conservative way, partially fixes #794. Thanks zeiram for patches

Line 
1<?php
2# -- BEGIN LICENSE BLOCK ---------------------------------------
3#
4# This file is part of Dotclear 2.
5#
6# Copyright (c) 2003-2011 Olivier Meunier & Association Dotclear
7# Licensed under the GPL version 2.0 license.
8# See LICENSE file or
9# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
10#
11# -- END LICENSE BLOCK -----------------------------------------
12if (!defined('DC_RC_PATH')) { return; }
13
14/**
15@ingroup DC_CORE
16@brief Blog settings handler
17
18dcSettings provides blog settings management. This class instance exists as
19dcBlog $settings property. You should create a new settings instance when
20updating another blog settings.
21*/
22class dcSettings
23{
24     protected $con;          ///< <b>connection</b> Database connection object
25     protected $table;        ///< <b>string</b> Settings table name
26     protected $blog_id;      ///< <b>string</b> Blog ID
27     
28     protected $namespaces = array();        ///< <b>array</b> Associative namespaces array
29     
30     protected $ns;           ///< <b>string</b> Current namespace
31     
32     /**
33     Object constructor. Retrieves blog settings and puts them in $namespaces
34     array. Local (blog) settings have a highest priority than global settings.
35     
36     @param    core      <b>dcCore</b>       dcCore object
37     @param    blog_id   <b>string</b>       Blog ID
38     */
39     public function __construct($core,$blog_id)
40     {
41          $this->con =& $core->con;
42          $this->table = $core->prefix.'setting';
43          $this->blog_id =& $blog_id;
44          $this->loadSettings();
45     }
46     
47     /**
48     Retrieves all namespaces (and their settings) from database, with one query.
49     */
50     private function loadSettings()
51     {
52          $strReq = 'SELECT blog_id, setting_id, setting_value, '.
53                    'setting_type, setting_label, setting_ns '.
54                    'FROM '.$this->table.' '.
55                    "WHERE blog_id = '".$this->con->escape($this->blog_id)."' ".
56                    'OR blog_id IS NULL '.
57                    'ORDER BY setting_ns ASC, setting_id DESC';
58          try {
59               $rs = $this->con->select($strReq);
60          } catch (Exception $e) {
61               trigger_error(__('Unable to retrieve namespaces:').' '.$this->con->error(), E_USER_ERROR);
62          }
63         
64          /* Prevent empty tables (install phase, for instance) */
65          if ($rs->isEmpty()) {
66               return;
67          }
68         
69          do {
70               $ns = trim($rs->f('setting_ns'));
71               if (!$rs->isStart()) {
72                    // we have to go up 1 step, since namespaces construction performs a fetch()
73                    // at very first time
74                    $rs->movePrev();
75               }
76               $this->namespaces[$ns] = new dcNamespace($GLOBALS['core'], $this->blog_id, $ns,$rs);
77          } while(!$rs->isStart());
78     }
79         
80     
81     /**
82     Create a new namespace. If the namespace already exists, return it without modification.
83     
84     @param    ns   <b>string</b>       Namespace name
85     @return   <b>dcNamespace</b>  The namespace created
86     */
87     public function addNamespace($ns)
88     {
89          if (!array_key_exists($ns, $this->namespaces)) {
90               $this->namespaces[$ns] = new dcNamespace($GLOBALS['core'], $this->blog_id, $ns);
91          }
92          return $this->namespaces[$ns];
93     }
94
95     /**
96     Rename a namespace.
97
98     @param    oldNs     <b>string</b>  Old namespace name
99     @param    newNs     <b>string</b>  New namespace name
100     @return   <b>boolean</b>
101     */
102     public function renNamespace($oldNs,$newNs)
103     {
104          if (!array_key_exists($oldNs, $this->namespaces) || array_key_exists($newNs, $this->namespaces)) {
105               return false;
106          }
107
108          // Rename the namespace in the namespace array
109          $this->namespaces[$newNs] = $this->namespaces[$oldNs];
110          unset($this->namespaces[$oldNs]);
111
112          // Rename the namespace in the database
113          $strReq = 'UPDATE '.$this->table.
114               " SET setting_ns = '".$this->con->escape($newNs)."' ".
115               " WHERE setting_ns = '".$this->con->escape($oldNs)."' ";
116          $this->con->execute($strReq);
117          return true;
118     }
119
120     /**
121     Delete a whole namespace with all settings pertaining to it.
122
123     @param    ns   <b>string</b>  Namespace name
124     @return   <b>boolean</b>
125     */
126     public function delNamespace($ns)
127     {
128          if (!array_key_exists($ns, $this->namespaces)) {
129               return false;
130          }
131
132          // Remove the namespace from the namespace array
133          unset($this->namespaces[$ns]);
134
135          // Delete all settings from the namespace in the database
136          $strReq = 'DELETE FROM '.$this->table.
137               " WHERE setting_ns = '".$this->con->escape($ns)."' ";
138          $this->con->execute($strReq);
139          return true;
140     }
141     
142     /**
143     Returns full namespace with all settings pertaining to it.
144     
145     @param    ns   <b>string</b>       Namespace name
146     @return   <b>dcNamespace</b>
147     */
148     public function get($ns)
149     {
150          return $this->namespaces[$ns];
151     }
152     
153     /**
154     Magic __get method.
155     @copydoc ::get
156     */
157     public function __get($n)
158     {
159          if (!array_key_exists($n, $this->namespaces)) {
160               // For backward compatibility only: the developer tried to access
161               // a setting directly, without passing via a namespace.
162               $this->raiseDeprecated('old_style_get');
163               return $this->getSetting($n);
164          }
165          return $this->get($n);
166     }
167     
168     /**
169     Magic __set method.
170     @copydoc ::set
171     */
172     public function __set($n,$v)
173     {
174          $this->set($n,$v);
175     }
176     
177     /**
178     Returns $namespaces property content.
179     
180     @return   <b>array</b>
181     */
182     public function dumpNamespaces()
183     {
184          return $this->namespaces;
185     }
186     
187     /**
188     Raises a E_USER_NOTICE errror for deprecated functions.
189     This allows the developer to know he's been using deprecated functions.
190     
191     @param    name <b>string</b>  Name of the deprecated function that was called.
192     */
193     private function raiseDeprecated($name)
194     {
195          if (DC_DEBUG) {
196               $trace = debug_backtrace();
197               array_shift($trace);
198               $grand = array_shift($trace);
199               $msg = 'Deprecated function called. (';
200               $msg .= 'dcSettings::'.$name . ' was called from '.$grand['file'].' ['.$grand['line'].'])';
201               trigger_error($msg, E_USER_NOTICE);
202          }
203     }
204     
205     /**
206     @deprecated Please set your settings via $core->blog->settings->{namespace}->{setting}
207     
208     Sets a setting in $settings property. This sets the setting for script
209     execution time only and if setting exists.
210     
211     @param    n         <b>string</b>       Setting name
212     @param    v         <b>mixed</b>        Setting value
213     */
214     public function set($n,$v)
215     {
216          // For backward compatibility only: the developer tried to access
217          // a setting directly, without passing via a namespace.
218          $this->raiseDeprecated('old_style_set');
219         
220          if (!$this->ns) {
221               throw new Exception(__('No namespace specified'));
222          }
223         
224          if (isset($this->namespaces[$this->ns]->$n)) {
225               $this->namespaces[$this->ns]->$n['value'] = $v;
226          } else {
227               $this->namespaces[$this->ns]->$n = array(
228                    'ns' => $this->ns,
229                    'value' => $v,
230                    'type' => gettype($n),
231                    'label' => '',
232                    'global' => false
233               );
234          }
235     }
236     
237     /**
238     @deprecated Please access your settings via $core->blog->settings->{namespace}->...
239     
240     Sets a working namespace. You should do this before accessing any setting.
241     
242     @param    ns        <b>string</b>       Namespace name
243     */
244     public function setNamespace($ns)
245     {
246          $this->raiseDeprecated('setNamespace');
247          if (preg_match('/^[a-zA-Z][a-zA-Z0-9]+$/',$ns)) {
248               $this->ns = $ns;
249          } else {
250               throw new Exception(sprintf(__('Invalid setting namespace: %s'),$ns));
251          }
252     }
253     
254     /**
255     @deprecated Please set your settings via $core->blog->settings->{namespace}->put()
256     
257     Creates or updates a setting.
258     
259     $type could be 'string', 'integer', 'float', 'boolean' or null. If $type is
260     null and setting exists, it will keep current setting type.
261     
262     $value_change allow you to not change setting. Useful if you need to change
263     a setting label or type and don't want to change its value.
264     
265     Don't forget to set namespace before calling this method.
266     
267     @param    id             <b>string</b>       Setting ID
268     @param    value          <b>mixed</b>        Setting value
269     @param    type           <b>string</b>       Setting type
270     @param    label          <b>string</b>       Setting label
271     @param    value_change   <b>boolean</b>      Change setting value or not
272     @param    global         <b>boolean</b>      Setting is global
273     */
274     public function put($id,$value,$type=null,$label=null,$value_change=true,$global=false)
275     {
276          $this->raiseDeprecated('put');
277          if (!$this->ns) {
278               throw new Exception(__('No namespace specified'));
279          }
280          if (!isset($this->namespaces[$this->ns])) {
281               // Create namespace if needed
282               $this->namespaces[$this->ns] = new dcNamespace($GLOBALS['core'], $this->blog_id, $this->ns);
283          }
284          $this->namespaces[$this->ns]->put($id, $value, $type, $label, $value_change, $global);
285     }
286     
287     /**
288     @deprecated Please get your settings via $core->blog->settings->{namespace}->{setting}
289     
290     Returns setting value if exists.
291     
292     @param    n         <b>string</b>       Setting name
293     @return   <b>mixed</b>
294     */
295     public function getSetting($n)
296     {
297          if ($this->namespaces['system']->get($n) != null) {
298               // Give preference to system settings
299               return $this->namespaces['system']->get($n);
300          } else {
301               // Parse all the namespaces
302               foreach (array_keys($this->namespaces) as $id => $ns) {
303                    if ($this->namespaces[$ns]->get($n) != null) {
304                         // Return the first setting with matching name
305                         return $this->namespaces[$ns]->get($n);
306                    }
307               }
308          }
309         
310          return null;
311     }
312     
313     /**
314     @deprecated Please get your settings via $core->blog->settings->{namespace}->dumpSettings
315     
316     Returns all settings content.
317     
318     @return   <b>array</b>
319     */
320     public function dumpSettings()
321     {
322          // For backward compatibility only: the developer tried to access
323          // the settings directly, without passing via a namespace.
324          $this->raiseDeprecated('dumpSettings');
325         
326          $settings = array();
327          // Parse all the namespaces
328          foreach (array_keys($this->namespaces) as $id => $ns) {
329               $settings = array_merge($settings, $this->namespaces[$ns]->dumpSettings());
330          }
331         
332          return $settings;
333     }
334     
335     /**
336     @deprecated Please get your settings via $core->blog->settings->{namespace}->dumpGlobalSettings
337     
338     Returns all global settings content.
339     
340     @return   <b>array</b>
341     */
342     public function dumpGlobalSettings()
343     {
344          // For backward compatibility only: the developer tried to access
345          // the settings directly, without passing via a namespace.
346          $this->raiseDeprecated('dumpGlobalSettings');
347         
348          $settings = array();
349          // Parse all the namespaces
350          foreach (array_keys($this->namespaces) as $id => $ns) {
351               $settings = array_merge($settings, $this->namespaces[$ns]->dumpGlobalSettings());
352          }
353         
354          return $settings;
355     }
356
357     /**
358     Returns a list of settings matching given criteria, for any blog.
359     <b>$params</b> is an array taking the following
360     optionnal parameters:
361     
362     - ns : retrieve setting from given namespace
363     - id : retrieve only settings corresponding to the given id
364     
365     @param    params         <b>array</b>        Parameters
366     @return   <b>record</b>  A record
367     */
368     public function getGlobalSettings($params=array())
369     {
370          $strReq = "SELECT * from ".$this->table." ";
371          $where = array();
372          if (!empty($params['ns'])) {
373               $where[] = "setting_ns = '".$this->con->escape($params['ns'])."'";
374          }
375          if (!empty($params['id'])) {
376               $where[] = "setting_id = '".$this->con->escape($params['id'])."'";
377          }
378          if (isset($params['blog_id'])) {
379               if (!empty($params['blog_id'])) {
380                    $where[] = "blog_id = '".$this->con->escape($params['blog_id'])."'";
381               } else {
382                    $where[] = "blog_id IS NULL";
383               }
384          }
385          if (count($where) != 0) {
386               $strReq .= " WHERE ".join(" AND ", $where);
387          }
388          $strReq .= " ORDER by blog_id";
389          return $this->con->select($strReq);
390     }
391
392     /**
393     Updates a setting from a given record
394     
395     @param    rs        <b>record</b>       the setting to update
396     */
397     public function updateSetting($rs) 
398     {
399          $cur = $this->con->openCursor($this->table);
400          $cur->setting_id = $rs->setting_id;
401          $cur->setting_value = $rs->setting_value;
402          $cur->setting_type = $rs->setting_type;
403          $cur->setting_label = $rs->setting_label;
404          $cur->blog_id = $rs->blog_id;
405          $cur->setting_ns = $rs->setting_ns;
406          if ($cur->blog_id == null) {
407                    $where = 'WHERE blog_id IS NULL ';
408          } else {
409               $where = "WHERE blog_id = '".$this->con->escape($cur->blog_id)."' ";
410          }
411          $cur->update($where."AND setting_id = '".$this->con->escape($cur->setting_id)."' AND setting_ns = '".$this->con->escape($cur->setting_ns)."' ");
412     }
413     
414     /**
415     Drops a setting from a given record
416     
417     @param    rs        <b>record</b>       the setting to drop
418     @return   int       number of deleted records (0 if setting does not exist)
419     */
420     public function dropSetting($rs) {
421          $strReq = "DELETE FROM ".$this->table.' ';
422          if ($rs->blog_id == null) {
423               $strReq .= 'WHERE blog_id IS NULL ';
424          } else {
425               $strReq .= "WHERE blog_id = '".$this->con->escape($rs->blog_id)."' ";
426          }
427          $strReq .= "AND setting_id = '".$this->con->escape($rs->setting_id)."' AND setting_ns = '".$this->con->escape($rs->setting_ns)."' ";
428          return $this->con->execute($strReq);
429     }
430}
431?>
Note: See TracBrowser for help on using the repository browser.

Sites map