Subversion Repositories oidplus

Rev

Rev 1086 | Rev 1130 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 daniel-mar 1
<?php
2
 
3
/*
4
 * OIDplus 2.0
1086 daniel-mar 5
 * Copyright 2019 - 2023 Daniel Marschall, ViaThinkSoft
2 daniel-mar 6
 *
7
 * Licensed under the Apache License, Version 2.0 (the "License");
8
 * you may not use this file except in compliance with the License.
9
 * You may obtain a copy of the License at
10
 *
11
 *     http://www.apache.org/licenses/LICENSE-2.0
12
 *
13
 * Unless required by applicable law or agreed to in writing, software
14
 * distributed under the License is distributed on an "AS IS" BASIS,
15
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
 * See the License for the specific language governing permissions and
17
 * limitations under the License.
18
 */
19
 
1050 daniel-mar 20
namespace ViaThinkSoft\OIDplus;
511 daniel-mar 21
 
1086 daniel-mar 22
// phpcs:disable PSR1.Files.SideEffects
23
\defined('INSIDE_OIDPLUS') or die;
24
// phpcs:enable PSR1.Files.SideEffects
25
 
261 daniel-mar 26
// OIDplusConfig contains settings that are stored in the database.
294 daniel-mar 27
// Not to be confused with OIDplusBaseConfig which is the basic ("static")
28
// configuration stored in userdata/baseconfig/config.inc.php,
261 daniel-mar 29
// e.g. database access credentials.
730 daniel-mar 30
class OIDplusConfig extends OIDplusBaseClass implements OIDplusGetterSetterInterface {
2 daniel-mar 31
 
269 daniel-mar 32
        /*public*/ const PROTECTION_EDITABLE = 0;
33
        /*public*/ const PROTECTION_READONLY = 1;
34
        /*public*/ const PROTECTION_HIDDEN   = 2;
263 daniel-mar 35
 
326 daniel-mar 36
        protected $configTableReadOnce = false; // this ensures that all $values and $descriptions were read
37
 
75 daniel-mar 38
        protected $values = array();
295 daniel-mar 39
        protected $descriptions = array();
682 daniel-mar 40
        protected $protectSettings = array();
41
        protected $visibleSettings = array();
263 daniel-mar 42
        protected $validateCallbacks = array();
13 daniel-mar 43
 
1116 daniel-mar 44
        /**
45
         * @param string $name
46
         * @param string $description
47
         * @param string $init_value
48
         * @param int $protection
49
         * @param $validateCallback
50
         * @return void
51
         * @throws OIDplusException
52
         */
53
        public function prepareConfigKey(string $name, string $description, string $init_value, int $protection, $validateCallback) {
326 daniel-mar 54
                // Check if the protection flag is valid
263 daniel-mar 55
                switch ($protection) {
56
                        case OIDplusConfig::PROTECTION_EDITABLE:
57
                                $protected = 0;
58
                                $visible   = 1;
59
                                break;
60
                        case OIDplusConfig::PROTECTION_READONLY:
61
                                $protected = 1;
62
                                $visible   = 1;
63
                                break;
64
                        case OIDplusConfig::PROTECTION_HIDDEN:
65
                                $protected = 1;
66
                                $visible   = 0;
67
                                break;
68
                        default:
360 daniel-mar 69
                                throw new OIDplusException(_L('Invalid protection flag, use OIDplusConfig::PROTECTION_* constants'));
263 daniel-mar 70
                }
295 daniel-mar 71
 
326 daniel-mar 72
                // Check length limitations given by the database tables
166 daniel-mar 73
                if (strlen($name) > 50) {
360 daniel-mar 74
                        throw new OIDplusException(_L('Config key name "%1" is too long (max %2).',$name,50));
166 daniel-mar 75
                }
76
                if (strlen($description) > 255) {
360 daniel-mar 77
                        throw new OIDplusException(_L('Description for config key "%1" is too long (max %2).',$name,255));
166 daniel-mar 78
                }
326 daniel-mar 79
 
80
                // Read all values and descriptions from the database once.
150 daniel-mar 81
                $this->buildConfigArray();
326 daniel-mar 82
 
83
                // Figure out if we need to create/update something at database level
150 daniel-mar 84
                if (!isset($this->values[$name])) {
326 daniel-mar 85
                        // Case A: The config setting does not exist in the database. So we create it now.
614 daniel-mar 86
                        try {
87
                                OIDplus::db()->query("insert into ###config (name, description, value, protected, visible) values (?, ?, ?, ?, ?)", array($name, $description, $init_value, $protected, $visible));
1050 daniel-mar 88
                        } catch (\Exception $e) {
614 daniel-mar 89
                                // After a software update that introduced a new config setting,
90
                                // there will be a race-condition at this place, because
91
                                // jsTree and content are loading simultaneously!
92
                                // So we ignore the error here.
93
                        }
155 daniel-mar 94
                        $this->values[$name] = $init_value;
295 daniel-mar 95
                        $this->descriptions[$name] = $description;
682 daniel-mar 96
                        $this->protectSettings[$name] = $protected;
97
                        $this->visibleSettings[$name] = $visible;
326 daniel-mar 98
                } else {
99
                        // Case B: The config setting exists ...
100
                        if ($this->descriptions[$name] != $description) {
101
                                // ... but the human readable description is different.
102
                                // We want to give the plugin authors the possibility to automatically update the config descriptions for their plugins
103
                                // So we just edit the description
104
                                OIDplus::db()->query("update ###config set description = ? where name = ?", array($description, $name));
105
                                $this->descriptions[$name] = $description;
106
                        }
682 daniel-mar 107
                        if ($this->protectSettings[$name] != $protected) {
108
                                OIDplus::db()->query("update ###config set protected = ? where name = ?", array($protected, $name));
109
                                $this->protectSettings[$name] = $protected;
110
                        }
111
                        if ($this->visibleSettings[$name] != $visible) {
112
                                OIDplus::db()->query("update ###config set visible = ? where name = ?", array($visible, $name));
113
                                $this->visibleSettings[$name] = $visible;
114
                        }
150 daniel-mar 115
                }
326 daniel-mar 116
 
117
                // Register the validation callback
263 daniel-mar 118
                if (!is_null($validateCallback)) {
119
                        $this->validateCallbacks[$name] = $validateCallback;
120
                }
13 daniel-mar 121
        }
122
 
1116 daniel-mar 123
        /**
124
         * @return void
125
         * @throws OIDplusException
126
         */
326 daniel-mar 127
        public function clearCache() {
128
                $this->configTableReadOnce = false;
129
                $this->buildConfigArray();
130
        }
131
 
1116 daniel-mar 132
        /**
133
         * @return void
134
         * @throws OIDplusException
135
         */
150 daniel-mar 136
        protected function buildConfigArray() {
326 daniel-mar 137
                if ($this->configTableReadOnce) return;
138
 
139
                $this->values = array();
140
                $this->descriptions = array();
682 daniel-mar 141
                $this->protectSettings = array();
142
                $this->visibleSettings = array();
143
                $res = OIDplus::db()->query("select name, description, protected, visible, value from ###config");
326 daniel-mar 144
                while ($row = $res->fetch_object()) {
145
                        $this->values[$row->name] = $row->value;
146
                        $this->descriptions[$row->name] = $row->description;
682 daniel-mar 147
                        $this->protectSettings[$row->name] = $row->protected;
148
                        $this->visibleSettings[$row->name] = $row->visible;
75 daniel-mar 149
                }
326 daniel-mar 150
 
151
                $this->configTableReadOnce = true;
150 daniel-mar 152
        }
75 daniel-mar 153
 
1116 daniel-mar 154
        /**
155
         * @param string $name
156
         * @param mixed|null $default
157
         * @return mixed|null
158
         * @throws OIDplusException
159
         */
160
        public function getValue(string $name, $default=null) {
326 daniel-mar 161
                // Read all config settings once and write them in array $this->values
150 daniel-mar 162
                $this->buildConfigArray();
326 daniel-mar 163
 
164
                // Now we can see if our desired attribute is available
60 daniel-mar 165
                if (isset($this->values[$name])) {
166
                        return $this->values[$name];
167
                } else {
261 daniel-mar 168
                        return $default;
60 daniel-mar 169
                }
46 daniel-mar 170
        }
171
 
1116 daniel-mar 172
        /**
173
         * @param string $name
174
         * @return bool
175
         * @throws OIDplusException
176
         */
177
        public function exists(string $name): bool {
326 daniel-mar 178
                return !is_null($this->getValue($name, null));
74 daniel-mar 179
        }
180
 
1116 daniel-mar 181
        /**
182
         * @param string $name
183
         * @param mixed $value
184
         * @return void
185
         * @throws OIDplusException
186
         */
187
        public function setValue(string $name, $value) {
574 daniel-mar 188
                // Read all config settings once and write them in array $this->values
189
                $this->buildConfigArray();
190
 
326 daniel-mar 191
                if (isset($this->values[$name])) {
574 daniel-mar 192
                        // Avoid unnecessary database writes
326 daniel-mar 193
                        if ($this->values[$name] == $value) return;
574 daniel-mar 194
                } else {
195
                        throw new OIDplusException(_L('Config value "%1" cannot be written because it was not prepared!', $name));
326 daniel-mar 196
                }
197
 
263 daniel-mar 198
                // Give plugins the possibility to stop the process by throwing an Exception (e.g. if the value is invalid)
326 daniel-mar 199
                // Required is that the plugin previously prepared the config setting using prepareConfigKey()
263 daniel-mar 200
                if (isset($this->validateCallbacks[$name])) {
201
                        $this->validateCallbacks[$name]($value);
14 daniel-mar 202
                }
257 daniel-mar 203
 
14 daniel-mar 204
                // Now change the value in the database
261 daniel-mar 205
                OIDplus::db()->query("update ###config set value = ? where name = ?", array($value, $name));
66 daniel-mar 206
                $this->values[$name] = $value;
14 daniel-mar 207
        }
208
 
1116 daniel-mar 209
        /**
210
         * @param string $name
211
         * @param string $value
212
         * @return void
213
         * @throws OIDplusException
214
         */
215
        public function setValueNoCallback(string $name, string $value) {
672 daniel-mar 216
                // Read all config settings once and write them in array $this->values
217
                $this->buildConfigArray();
218
 
219
                if (isset($this->values[$name])) {
220
                        // Avoid unnecessary database writes
221
                        if ($this->values[$name] == $value) return;
222
                } else {
223
                        throw new OIDplusException(_L('Config value "%1" cannot be written because it was not prepared!', $name));
224
                }
225
 
226
                // Now change the value in the database
227
                OIDplus::db()->query("update ###config set value = ? where name = ?", array($value, $name));
228
                $this->values[$name] = $value;
229
        }
230
 
1116 daniel-mar 231
        /**
232
         * @param string $name
233
         * @return void
234
         * @throws OIDplusException
235
         */
236
        public function delete(string $name) {
326 daniel-mar 237
                if ($this->configTableReadOnce) {
238
                        if (isset($this->values[$name])) {
239
                                OIDplus::db()->query("delete from ###config where name = ?", array($name));
240
                        }
241
                } else {
242
                        // We do not know if the value exists.
243
                        // buildConfigArray() would do many reads which are unnecessary.
244
                        // So we just do a MySQL command to delete the stuff:
294 daniel-mar 245
                        OIDplus::db()->query("delete from ###config where name = ?", array($name));
246
                }
326 daniel-mar 247
 
248
                unset($this->values[$name]);
249
                unset($this->descriptions[$name]);
250
                unset($this->validateCallbacks[$name]);
682 daniel-mar 251
                unset($this->protectSettings[$name]);
252
                unset($this->visibleSettings[$name]);
294 daniel-mar 253
        }
254
 
569 daniel-mar 255
}