/
configuration.php
295 lines (274 loc) · 10.3 KB
/
configuration.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
<?php
/**
* @package midcom.helper
* @author The Midgard Project, http://www.midgard-project.org
* @copyright The Midgard Project, http://www.midgard-project.org
* @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License
*/
/**
* This class is designed to ease MidCOM Configuration management.
*
* Basically it supports key/value pairs of data, which can be retrieved out of Midgard
* Parameters. In this case it would make the key/values a string/string pair with
* a length limit of 255 characters. Since the current implementation only supports
* read-access to the configuration data, this is a negligible fact, in reality it
* supports all valid PHP data types as key or data values, as long it is allowed
* to use the keys as array index elements.
*
* This class is designed to manage parameter like key/value configuration data.
* The class makes no assumption about the value type of keys or values, any valid
* PHP data type is allowed. Two different sets of configuration options are stored
* within the class, the "global" and the "local" configuration.
*
* The global configuration must include all possible configuration parameters with
* their default values. These data is fixed and cannot be changed after object
* instantiation. Aimed specifically at MidCOM is the second set of configuration
* data, the "local" parameters. It gives you a way of explicitly overwrite a part
* of the configuration data with localized values. This customization data can be
* overwritten at wish by deliberately resetting it to the defaults or by importing
* a new one over the existing local configuration.
*
* Configuration data can be delivered in two ways: The easiest way is using a
* associative array that will be used as configuration. Alternatively you can
* specify both a MidgardObject and a MidCOM Path which is used to fetch
* configuration data.
*
* Any configuration key in the local configuration, which is not present in the
* global "template", will be logged as a warning. This should normally not happen.
* Originally, this case threw a critical error, but that made upgrading
* configurations quite difficult.
*
* @package midcom.helper
*/
class midcom_helper_configuration
{
/**
* Globally assigned configuration data.
*
* @var Array
*/
public $_global = [];
/**
* Locally overridden configuration data.
*
* @var Array
*/
public $_local = [];
/**
* Merged, current configuration state.
*
* @var Array
*/
private $_merged = [];
/**
* Internal cache-related items
* @ignore
*/
private $_object_stored = false;
private $_object;
private $_path;
/**
* The constructor initializes the global configuration.
*
* Two sources can be specified:
*
* First, if passed a single associative array to the constructor,
* it will use its contents as global configuration.
*
* Alternatively you can specify any Midgard object and a parameter
* domain. It will then use the contents of this domain as global
* configuration.
*
* @param mixed $param1 Either an associative array or a Midgard object.
* @param mixed $param2 Either null or the name of a Parameter domain.
*/
public function __construct($param1, $param2 = null)
{
if (!is_null($param2)) {
$this->_object = $param1;
$this->_path = $param2;
$this->_store_from_object(true);
} elseif (!is_null($param1)) {
$this->_global = $param1;
$this->_merged = $param1;
}
}
/**
* Fetch the configuration data stored in the parameter domain _path of _object.
*
* The flag $global controls whether the global or the local configuration should
* be updated. No control whether an update of the global data is allowed is done
* here, the caller has to do this.
* This function will update the config data cache array. If it stores global
* configuration data it will automatically erase the local configuration data.
*
* Any error such as invalid configuration data will trigger a MidCOM error.
*
* @param boolean $global Set to true to replace the global configuration.
*/
private function _store_from_object($global = false, $merge = false)
{
// Cast to DBA type.
if (!midcom::get()->dbclassloader->is_midcom_db_object($this->_object)) {
$this->_object = midcom::get()->dbfactory->convert_midgard_to_midcom($this->_object);
}
$array = [];
$manifest = midcom::get()->componentloader->manifests[$this->_path];
if (!empty($manifest->extends)) {
$array = $this->_object->list_parameters($manifest->extends);
}
$array = array_merge($array, $this->_object->list_parameters($this->_path));
if ($global) {
$this->_global = ($merge) ? array_merge($this->_global, $array) : $array;
$this->_local = [];
$this->_merged = $array;
}
$this->_check_local_array($array);
$this->_local = ($merge) ? array_merge($this->_local, $array) : $array;
$this->_update_cache();
$this->_object_stored = true;
}
/**
* Merge the local and the global configuration arrays into the cache array.
*/
private function _update_cache()
{
$this->_merged = $this->_global;
if ( !empty($this->_local)
&& is_array($this->_local)) {
$this->_merged = array_merge($this->_merged, $this->_local);
}
}
/**
* Check local data array for validity
*
* Since the local array must only include configuration parameters that are
* included in the global configuration, this function is used to check a local
* array against the current global configuration. true/false is returned
* accordingly.
*/
private function _check_local_array(array $array)
{
if (!empty($array)) {
$diff = array_keys(array_diff_key($array, $this->_global));
foreach ($diff as $key) {
debug_add("The key {$key} is not present in the global configuration array.", MIDCOM_LOG_INFO);
}
}
}
/**
* Write the parameters in $params into the local configuration.
*
* If $reset is set, the local configuration will be cleared before
* the new set is imported, if not, the new data is merged with the old local
* configuration, overwriting duplicates. During import each configuration key will
* be checked against the global configuration values. If an unknown value is found,
* import will be aborted and no changes to the configuration is done.
*
* After import the cache array will be updated, reset is done by reset_local.
*
* @param array $params The new local parameters
* @param boolean $reset If set to true, the current local configuration will be discarded first.
* @see midcom_helper_configuration::reset_local()
*/
public function store(array $params, $reset = true)
{
if ( !$this->_object_stored
&& $this->_object) {
$this->_store_from_object();
}
$this->_check_local_array($params);
if ($reset == true) {
$this->reset_local();
}
$this->_local = array_merge($this->_local, $params);
$this->_update_cache();
}
/**
* Import data from a Midgard object.
*
* To import configuration data from a Midgard Object, use this method. As in the
* respective constructor it will retrieve the configuration data in the parameter
* domain $path of $object. Unlike the constructor this function will store the
* data in the local configuration.
*
* @param MidgardObject $object The object from which to import data.
* @param string $path The parameter domain to query.
* @param boolean $merge Should the existing local config be overridden or merged
*/
public function store_from_object($object, $path, $merge = false)
{
$this->_object = $object;
$this->_path = $path;
$this->_store_from_object(false, $merge);
}
/**
* Clear the local configuration data, effectively reverting to the global
* default.
*/
public function reset_local()
{
$this->_local = [];
$this->_merged = $this->_global;
}
/**
* Retrieve a configuration key
*
* If $key exists in the configuration data, its value is returned to the caller.
* If the value does not exist, the boolean value false will be returned. Be aware
* that this is not always good for error checking, since "false" is a perfectly good
* value in the configuration data. Do error checking with the function exists (see
* below).
*
* @param string $key The configuration key to query.
* @return mixed Its value or false, if the key doesn't exist.
* @see midcom_helper_configuration::exists()
*/
public function get($key)
{
if ($this->exists($key)) {
return $this->_merged[$key];
}
return false;
}
/**
* Set a value on the current instance, if the given key exists
*
* @param string $key The configuration key to set.
* @param mixed $value The value to set.
*/
public function set($key, $value)
{
if ($this->exists($key)) {
$this->_local[$key] = $value;
$this->_update_cache();
}
}
/**
* Retrieve a copy the complete configuration array.
*
* @return Array The complete current configuration.
*/
public function get_all()
{
if ( !$this->_object_stored
&& $this->_object) {
$this->_store_from_object();
}
return $this->_merged;
}
/**
* Checks for the existence of a configuration key.
*
* @param string $key The configuration key to check for.
* @return boolean True, if the key is available, false otherwise.
*/
public function exists($key)
{
if ( !$this->_object_stored
&& $this->_object) {
$this->_store_from_object();
}
return array_key_exists($key, $this->_merged);
}
}