Dotclear

source: inc/core/class.dc.namespace.php @ 3158:568e0d0e0991

Revision 3158:568e0d0e0991, 9.8 KB checked in by franck <carnet.franck.paul@…>, 10 years ago (diff)

Add new array type for settings and prefs, closes #1833 (thank's Dsls for code)

Line 
1<?php
2# -- BEGIN LICENSE BLOCK ---------------------------------------
3#
4# This file is part of Dotclear 2.
5#
6# Copyright (c) 2003-2013 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 namespace for settings handler
17
18*/
19class dcNamespace
20{
21     protected $con;          ///< <b>connection</b> Database connection object
22     protected $table;        ///< <b>string</b> Settings table name
23     protected $blog_id;      ///< <b>string</b> Blog ID
24
25     protected $global_settings = array();   ///< <b>array</b> Global settings array
26     protected $local_settings = array();    ///< <b>array</b> Local settings array
27     protected $settings = array();          ///< <b>array</b> Associative settings array
28     protected $ns;           ///< <b>string</b> Current namespace
29
30     /**
31     Object constructor. Retrieves blog settings and puts them in $settings
32     array. Local (blog) settings have a highest priority than global settings.
33
34     @param    name      <b>string</b>       ID for this namespace
35     */
36     public function __construct(&$core, $blog_id, $name, $rs=null)
37     {
38          if (preg_match('/^[a-zA-Z][a-zA-Z0-9]+$/',$name)) {
39               $this->ns = $name;
40          } else {
41               throw new Exception(sprintf(__('Invalid setting dcNamespace: %s'),$name));
42          }
43
44          $this->con =& $core->con;
45          $this->table = $core->prefix.'setting';
46          $this->blog_id =& $blog_id;
47
48          $this->getSettings($rs);
49     }
50
51     private function getSettings($rs=null)
52     {
53          if ($rs == null) {
54               $strReq = 'SELECT blog_id, setting_id, setting_value, '.
55                         'setting_type, setting_label, setting_ns '.
56                         'FROM '.$this->table.' '.
57                         "WHERE (blog_id = '".$this->con->escape($this->blog_id)."' ".
58                         'OR blog_id IS NULL) '.
59                         "AND setting_ns = '".$this->con->escape($this->ns)."' ".
60                         'ORDER BY setting_id DESC ';
61
62               try {
63                    $rs = $this->con->select($strReq);
64               } catch (Exception $e) {
65                    trigger_error(__('Unable to retrieve settings:').' '.$this->con->error(), E_USER_ERROR);
66               }
67          }
68          while ($rs->fetch())
69          {
70               if ($rs->f('setting_ns') != $this->ns){
71                    break;
72               }
73               $id = trim($rs->f('setting_id'));
74               $value = $rs->f('setting_value');
75               $type = $rs->f('setting_type');
76
77               if ($type == 'array') {
78                    $value = @json_decode($value);
79               } else {
80                    if ($type == 'float' || $type == 'double') {
81                         $type = 'float';
82                    } elseif ($type != 'boolean' && $type != 'integer') {
83                         $type = 'string';
84                    }
85               }
86
87               settype($value,$type);
88
89               $array = $rs->blog_id ? 'local' : 'global';
90
91               $this->{$array.'_settings'}[$id] = array(
92                    'ns' => $this->ns,
93                    'value' => $value,
94                    'type' => $type,
95                    'label' => (string) $rs->f('setting_label'),
96                    'global' => $rs->blog_id == ''
97               );
98          }
99
100          $this->settings = $this->global_settings;
101
102          foreach ($this->local_settings as $id => $v) {
103               $this->settings[$id] = $v;
104          }
105
106          return true;
107     }
108
109     private function settingExists($id,$global=false)
110     {
111          $array = $global ? 'global' : 'local';
112          return isset($this->{$array.'_settings'}[$id]);
113     }
114
115     /**
116     Returns setting value if exists.
117
118     @param    n         <b>string</b>       Setting name
119     @return   <b>mixed</b>
120     */
121     public function get($n)
122     {
123          if (isset($this->settings[$n]['value'])) {
124               return $this->settings[$n]['value'];
125          }
126
127          return null;
128     }
129
130     /**
131     Returns global setting value if exists.
132
133     @param    n         <b>string</b>       setting name
134     @return   <b>mixed</b>
135     */
136     public function getGlobal($n)
137     {
138          if (isset($this->global_settings[$n]['value'])) {
139               return $this->global_settings[$n]['value'];
140          }
141
142          return null;
143     }
144
145     /**
146     Returns local setting value if exists.
147
148     @param    n         <b>string</b>       setting name
149     @return   <b>mixed</b>
150     */
151     public function getLocal($n)
152     {
153          if (isset($this->local_settings[$n]['value'])) {
154               return $this->local_settings[$n]['value'];
155          }
156
157          return null;
158     }
159
160     /**
161     Magic __get method.
162     @copydoc ::get
163     */
164     public function __get($n)
165     {
166          return $this->get($n);
167     }
168
169     /**
170     Sets a setting in $settings property. This sets the setting for script
171     execution time only and if setting exists.
172
173     @param    n         <b>string</b>       Setting name
174     @param    v         <b>mixed</b>        Setting value
175     */
176     public function set($n,$v)
177     {
178          if (isset($this->settings[$n])) {
179               $this->settings[$n]['value'] = $v;
180          }
181     }
182
183     /**
184     Magic __set method.
185     @copydoc ::set
186     */
187     public function __set($n,$v)
188     {
189          $this->set($n,$v);
190     }
191
192     /**
193     Creates or updates a setting.
194
195     $type could be 'string', 'integer', 'float', 'boolean' or null. If $type is
196     null and setting exists, it will keep current setting type.
197
198     $value_change allow you to not change setting. Useful if you need to change
199     a setting label or type and don't want to change its value.
200
201     @param    id             <b>string</b>       Setting ID
202     @param    value          <b>mixed</b>        Setting value
203     @param    type           <b>string</b>       Setting type
204     @param    label          <b>string</b>       Setting label
205     @param    value_change   <b>boolean</b>      Change setting value or not
206     @param    global         <b>boolean</b>      Setting is global
207     */
208     public function put($id,$value,$type=null,$label=null,$value_change=true,$global=false)
209     {
210          if (!preg_match('/^[a-zA-Z][a-zA-Z0-9_]+$/',$id)) {
211               throw new Exception(sprintf(__('%s is not a valid setting id'),$id));
212          }
213
214          # We don't want to change setting value
215          if (!$value_change)
216          {
217               if (!$global && $this->settingExists($id,false)) {
218                    $value = $this->local_settings[$id]['value'];
219               } elseif ($this->settingExists($id,true)) {
220                    $value = $this->global_settings[$id]['value'];
221               }
222          }
223
224          # Setting type
225          if ($type == 'double')
226          {
227               $type = 'float';
228          }
229          elseif ($type === null)
230          {
231               if (!$global && $this->settingExists($id,false)) {
232                    $type = $this->local_settings[$id]['type'];
233               } elseif ($this->settingExists($id,true)) {
234                    $type = $this->global_settings[$id]['type'];
235               } else {
236                    $type = 'string';
237               }
238          }
239          elseif ($type != 'boolean' && $type != 'integer' && $type != 'float' && $type != 'array')
240          {
241               $type = 'string';
242          }
243
244          # We don't change label
245          if ($label == null)
246          {
247               if (!$global && $this->settingExists($id,false)) {
248                    $label = $this->local_settings[$id]['label'];
249               } elseif ($this->settingExists($id,true)) {
250                    $label = $this->global_settings[$id]['label'];
251               }
252          }
253
254          if ($type != 'array') {
255               settype($value,$type);
256          } else {
257               $value = json_encode($value);
258          }
259
260          $cur = $this->con->openCursor($this->table);
261          $cur->setting_value = ($type == 'boolean') ? (string) (integer) $value : (string) $value;
262          $cur->setting_type = $type;
263          $cur->setting_label = $label;
264
265          #If we are local, compare to global value
266          if (!$global && $this->settingExists($id,true))
267          {
268               $g = $this->global_settings[$id];
269               $same_setting = $g['ns'] == $this->ns && $g['value'] == $value
270               && $g['type'] == $type && $g['label'] == $label;
271
272               # Drop setting if same value as global
273               if ($same_setting && $this->settingExists($id,false)) {
274                    $this->drop($id);
275               } elseif ($same_setting) {
276                    return;
277               }
278          }
279
280          if ($this->settingExists($id,$global) && $this->ns == $this->settings[$id]['ns'])
281          {
282               if ($global) {
283                    $where = 'WHERE blog_id IS NULL ';
284               } else {
285                    $where = "WHERE blog_id = '".$this->con->escape($this->blog_id)."' ";
286               }
287
288               $cur->update($where."AND setting_id = '".$this->con->escape($id)."' AND setting_ns = '".$this->con->escape($this->ns)."' ");
289          }
290          else
291          {
292               $cur->setting_id = $id;
293               $cur->blog_id = $global ? null : $this->blog_id;
294               $cur->setting_ns = $this->ns;
295
296               $cur->insert();
297          }
298     }
299
300     /**
301     Rename an existing setting in a Namespace
302
303     @param    $oldId    <b>string</b>  Current setting name
304     @param    $newId    <b>string</b>  New setting name
305     @return   <b>boolean</b>
306     */
307     public function rename($oldId,$newId)
308     {
309          if (!$this->ns) {
310               throw new Exception(__('No namespace specified'));
311          }
312
313          if (!array_key_exists($oldId,$this->settings) || array_key_exists($newId,$this->settings)) {
314               return false;
315          }
316
317          // Rename the setting in the settings array
318          $this->settings[$newId] = $this->settings[$oldId];
319          unset($this->settings[$oldId]);
320
321          // Rename the setting in the database
322          $strReq = 'UPDATE '.$this->table.
323               " SET setting_id = '".$this->con->escape($newId)."' ".
324               " WHERE setting_ns = '".$this->con->escape($this->ns)."' ".
325               " AND setting_id = '".$this->con->escape($oldId)."' ";
326          $this->con->execute($strReq);
327          return true;
328     }
329
330     /**
331     Removes an existing setting in a Namespace
332
333     @param    id        <b>string</b>       Setting ID
334     */
335     public function drop($id)
336     {
337          if (!$this->ns) {
338               throw new Exception(__('No namespace specified'));
339          }
340
341          $strReq = 'DELETE FROM '.$this->table.' ';
342
343          if ($this->blog_id === null) {
344               $strReq .= 'WHERE blog_id IS NULL ';
345          } else {
346               $strReq .= "WHERE blog_id = '".$this->con->escape($this->blog_id)."' ";
347          }
348
349          $strReq .= "AND setting_id = '".$this->con->escape($id)."' ";
350          $strReq .= "AND setting_ns = '".$this->con->escape($this->ns)."' ";
351
352          $this->con->execute($strReq);
353     }
354
355     /**
356     Removes all existing settings in a Namespace
357
358     @param    force_global   <b>boolean</b> Force global pref drop
359     */
360     public function dropAll($force_global=false)
361     {
362          if (!$this->ns) {
363               throw new Exception(__('No namespace specified'));
364          }
365
366          $strReq = 'DELETE FROM '.$this->table.' ';
367
368          if (($force_global) || ($this->blog_id === null)) {
369               $strReq .= 'WHERE blog_id IS NULL ';
370               $global = true;
371          } else {
372               $strReq .= "WHERE blog_id = '".$this->con->escape($this->blog_id)."' ";
373               $global = false;
374          }
375
376          $strReq .= "AND setting_ns = '".$this->con->escape($this->ns)."' ";
377
378          $this->con->execute($strReq);
379
380          $array = $global ? 'global' : 'local';
381          unset($this->{$array.'_settings'});
382          $this->{$array.'_settings'} = array();
383
384          $array = $global ? 'local' : 'global';
385          $this->settings = $this->{$array.'_settings'};
386     }
387
388     /**
389     Returns $settings property content.
390
391     @return   <b>array</b>
392     */
393     public function dumpSettings()
394     {
395          return $this->settings;
396     }
397
398     /**
399     Returns $global_settings property content.
400
401     @return   <b>array</b>
402     */
403     public function dumpGlobalSettings()
404     {
405          return $this->global_settings;
406     }
407
408}
Note: See TracBrowser for help on using the repository browser.

Sites map