Dotclear

source: inc/core/class.dc.settings.php @ 3874:ab8368569446

Revision 3874:ab8368569446, 13.9 KB checked in by franck <carnet.franck.paul@…>, 7 years ago (diff)

short notation for array (array() → [])

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

Sites map