Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
58 / 58
100.00% covered (success)
100.00%
6 / 6
CRAP
100.00% covered (success)
100.00%
1 / 1
db
100.00% covered (success)
100.00%
58 / 58
100.00% covered (success)
100.00%
6 / 6
19
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
1
 initialise
100.00% covered (success)
100.00%
19 / 19
100.00% covered (success)
100.00%
1 / 1
5
 delete
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
2
 set
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 set_atomic
100.00% covered (success)
100.00%
18 / 18
100.00% covered (success)
100.00%
1 / 1
7
 increment
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
3
1<?php
2/**
3*
4* This file is part of the phpBB Forum Software package.
5*
6* @copyright (c) phpBB Limited <https://www.phpbb.com>
7* @license GNU General Public License, version 2 (GPL-2.0)
8*
9* For full copyright and license information, please see
10* the docs/CREDITS.txt file.
11*
12*/
13
14namespace phpbb\config;
15
16use phpbb\cache\driver\driver_interface as cache_interface;
17use phpbb\db\driver\driver_interface as db_interface;
18
19/**
20* Configuration container class
21*/
22class db extends config
23{
24    /**
25    * Cache instance
26    * @var cache_interface
27    */
28    protected $cache;
29
30    /**
31    * Database connection
32    * @var db_interface
33    */
34    protected $db;
35
36    /**
37    * Name of the database table used for configuration.
38    * @var string
39    */
40    protected $table;
41
42    /**
43    * Creates a configuration container with a default set of values
44    *
45    * @param db_interface    $db    Database connection
46    * @param cache_interface $cache Cache instance
47    * @param string                       $table Configuration table name
48    */
49    public function __construct(db_interface $db, cache_interface $cache, $table)
50    {
51        $this->db = $db;
52        $this->cache = $cache;
53        $this->table = $table;
54
55        $this->initialise($cache);
56
57        parent::__construct($this->config);
58    }
59
60    /**
61     * Initialise config with database and/or cached entries
62     *
63     * @param cache_interface $cache
64     */
65    public function initialise(cache_interface $cache)
66    {
67        if (($config = $cache->get('config')) !== false)
68        {
69            $sql = 'SELECT config_name, config_value
70                FROM ' . $this->table . '
71                WHERE is_dynamic = 1';
72            $result = $this->db->sql_query($sql);
73
74            while ($row = $this->db->sql_fetchrow($result))
75            {
76                $config[$row['config_name']] = $row['config_value'];
77            }
78            $this->db->sql_freeresult($result);
79        }
80        else
81        {
82            $config = $cached_config = array();
83
84            $sql = 'SELECT config_name, config_value, is_dynamic
85                FROM ' . $this->table;
86            $result = $this->db->sql_query($sql);
87
88            while ($row = $this->db->sql_fetchrow($result))
89            {
90                if (!$row['is_dynamic'])
91                {
92                    $cached_config[$row['config_name']] = $row['config_value'];
93                }
94
95                $config[$row['config_name']] = $row['config_value'];
96            }
97            $this->db->sql_freeresult($result);
98
99            $cache->put('config', $cached_config);
100        }
101
102        $this->config = $config;
103    }
104
105    /**
106    * Removes a configuration option
107    *
108    * @param  String $key       The configuration option's name
109    * @param  bool   $use_cache Whether this variable should be cached or if it
110    *                           changes too frequently to be efficiently cached
111    * @return void
112    */
113    public function delete($key, $use_cache = true)
114    {
115        $sql = 'DELETE FROM ' . $this->table . "
116            WHERE config_name = '" . $this->db->sql_escape($key) . "'";
117        $this->db->sql_query($sql);
118
119        unset($this->config[$key]);
120
121        if ($use_cache)
122        {
123            $this->cache->destroy('config');
124        }
125    }
126
127    /**
128    * Sets a configuration option's value
129    *
130    * @param    string        $key        The configuration option's name
131    * @param    int|string    $value        New configuration value
132    * @param    bool        $use_cache    Whether this variable should be cached or if it
133    *                                    changes too frequently to be efficiently cached.
134    */
135    public function set($key, $value, $use_cache = true)
136    {
137        $this->set_atomic($key, false, $value, $use_cache);
138    }
139
140    /**
141    * Sets a configuration option's value only if the old_value matches the
142    * current configuration value or the configuration value does not exist yet.
143    *
144    * @param    string            $key        The configuration option's name
145    * @param    false|int|string    $old_value    Current configuration value or false to ignore
146    *                                        the old value
147    * @param    int|string        $new_value    New configuration value
148    * @param    bool            $use_cache    Whether this variable should be cached or if it
149    *                                        changes too frequently to be efficiently cached
150    * @return    bool                        True if the value was changed, false otherwise
151    */
152    public function set_atomic($key, $old_value, $new_value, $use_cache = true)
153    {
154        $sql = 'UPDATE ' . $this->table . "
155            SET config_value = '" . $this->db->sql_escape($new_value) . "'
156            WHERE config_name = '" . $this->db->sql_escape($key) . "'";
157
158        if ($old_value !== false)
159        {
160            $sql .= " AND config_value = '" . $this->db->sql_escape($old_value) . "'";
161        }
162
163        $this->db->sql_query($sql);
164
165        if (!$this->db->sql_affectedrows() && isset($this->config[$key]))
166        {
167            return false;
168        }
169
170        if (!isset($this->config[$key]))
171        {
172            $sql = 'INSERT INTO ' . $this->table . ' ' . $this->db->sql_build_array('INSERT', array(
173                'config_name'    => $key,
174                'config_value'    => $new_value,
175                'is_dynamic'    => $use_cache ? 0 : 1));
176            $this->db->sql_query($sql);
177        }
178
179        if ($use_cache)
180        {
181            $this->cache->destroy('config');
182        }
183
184        $this->config[$key] = $new_value;
185        return true;
186    }
187
188    /**
189    * Increments an integer config value directly in the database.
190    *
191    * Using this method instead of setting the new value directly avoids race
192    * conditions and unlike set_atomic it cannot fail.
193    *
194    * @param string $key       The configuration option's name
195    * @param int    $increment Amount to increment by
196    * @param bool   $use_cache Whether this variable should be cached or if it
197    *                          changes too frequently to be efficiently cached.
198    */
199    function increment($key, $increment, $use_cache = true)
200    {
201        if (!isset($this->config[$key]))
202        {
203            $this->set($key, '0', $use_cache);
204        }
205
206        $sql_update = $this->db->cast_expr_to_string($this->db->cast_expr_to_bigint('config_value') . ' + ' . (int) $increment);
207
208        $this->db->sql_query('UPDATE ' . $this->table . '
209            SET config_value = ' . $sql_update . "
210            WHERE config_name = '" . $this->db->sql_escape($key) . "'");
211
212        if ($use_cache)
213        {
214            $this->cache->destroy('config');
215        }
216
217        $this->config[$key] += $increment;
218    }
219}