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