Continued:
[core.git] / framework / config / class_FrameworkConfiguration.php
1 <?php
2
3 // Own namespace
4 namespace Org\Mxchange\CoreFramework\Configuration;
5
6 // Import framework stuff
7 use Org\Mxchange\CoreFramework\Configuration\NoConfigEntryException;
8 use Org\Mxchange\CoreFramework\Generic\FrameworkInterface;
9 use Org\Mxchange\CoreFramework\Generic\UnsupportedOperationException;
10 use Org\Mxchange\CoreFramework\Registry\Registerable;
11 use Org\Mxchange\CoreFramework\Utils\Strings\StringUtils;
12
13 // Import SPL stuff
14 use \InvalidArgumentException;
15 use \UnexpectedValueException;
16
17 /**
18  * A class for the configuration stuff implemented in a singleton design pattern
19  *
20  * NOTE: We cannot put this in framework/main/ because it would be loaded (again) in
21  * class loader. See framework/loader/class_ClassLoader.php for instance
22  *
23  * @see                 ClassLoader
24  * @author              Roland Haeder <webmaster@shipsimu.org>
25  * @version             1.0.1
26  * @copyright   Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2023 Core Developer Team
27  * @license             GNU GPL 3.0 or any newer version
28  * @link                http://www.shipsimu.org
29  *
30  * This program is free software: you can redistribute it and/or modify
31  * it under the terms of the GNU General Public License as published by
32  * the Free Software Foundation, either version 3 of the License, or
33  * (at your option) any later version.
34  *
35  * This program is distributed in the hope that it will be useful,
36  * but WITHOUT ANY WARRANTY; without even the implied warranty of
37  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
38  * GNU General Public License for more details.
39  *
40  * You should have received a copy of the GNU General Public License
41  * along with this program. If not, see <http://www.gnu.org/licenses/>.
42  */
43 class FrameworkConfiguration implements Registerable {
44         // Some constants for the configuration system
45         const EXCEPTION_CONFIG_KEY_IS_EMPTY = 0x130;
46         const EXCEPTION_CONFIG_KEY_WAS_NOT_FOUND = 0x131;
47         const EXCEPTION_CONFIG_VALUE_TYPE_UNSUPPORTED = 0x132;
48
49         /**
50          * The framework's main configuration array which will be initialized with
51          * hard-coded configuration data and might be overwritten/extended by
52          * config data from the database.
53          */
54         private static $configData = [];
55
56         /**
57          * Call-back instance (unused)
58          */
59         private $callbackInstance = NULL;
60
61         /**
62          * Default constructor, the configuration entries are static, not the
63          * whole instance.
64          *
65          * @return      void
66          */
67         public function __construct () {
68                 // Empty for now
69         }
70
71         /**
72          * Compatiblity method to return this class' name
73          *
74          * @return      __CLASS__       This class' name
75          */
76         public function __toString () {
77                 return get_class($this);
78         }
79
80         /**
81          * Checks whether the given configuration key is set
82          *
83          * @param       $configKey      The configuration key we shall check
84          * @return      $isset  Whether the given configuration key is set
85          * @throws      InvalidArgumentException        If $configKey is empty
86          */
87         public function isConfigurationEntrySet (string $configKey) {
88                 // Is it null?
89                 //* NOISY-DEBUG: */ printf('[%s:%d]: configKey=%s - CALLED!' . PHP_EOL, __METHOD__, __LINE__, $configKey);
90                 if (empty($configKey)) {
91                         // Entry is empty
92                         throw new InvalidArgumentException('Parameter "configKey" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
93                 }
94
95                 // Is it set?
96                 $isset = ((isset(self::$configData[$configKey])) || (array_key_exists($configKey, self::$configData)));
97
98                 // Return the result
99                 //* NOISY-DEBUG: */ printf('[%s:%d]: isset=%s - EXIT!' . PHP_EOL, __METHOD__, __LINE__, intval($isset));
100                 return $isset;
101         }
102
103         /**
104          * Read a configuration element.
105          *
106          * @param       $configKey              The configuration element
107          * @return      $configValue    The fetched configuration value
108          * @throws      InvalidArgumentException        If $configKey is empty
109          * @throws      NoConfigEntryException          If a configuration element was not found
110          */
111         public function getConfigEntry (string $configKey) {
112                 // Is it null?
113                 //* NOISY-DEBUG: */ printf('[%s:%d]: configKey=%s - CALLED!' . PHP_EOL, __METHOD__, __LINE__, $configKey);
114                 if (empty($configKey)) {
115                         // Entry is empty
116                         throw new InvalidArgumentException('Parameter "configKey" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
117                 }
118
119                 // Convert dashes to underscore
120                 $configKey = str_replace('-', '_', $configKey);
121
122                 // Is a valid configuration key provided?
123                 //* NOISY-DEBUG: */ printf('[%s:%d]: configKey=%s - AFTER!' . PHP_EOL, __METHOD__, __LINE__, $configKey);
124                 if (!$this->isConfigurationEntrySet($configKey)) {
125                         // Entry was not found!
126                         throw new NoConfigEntryException(array(__CLASS__, $configKey), self::EXCEPTION_CONFIG_KEY_WAS_NOT_FOUND);
127                 }
128
129                 // Return the requested value
130                 //* NOISY-DEBUG: */ printf('[%s:%d]: Returning configData[%s]=[%s]:%s - EXIT!' . PHP_EOL, __METHOD__, __LINE__, $configKey, gettype(self::$configData[$configKey]), self::$configData[$configKey]);
131                 return self::$configData[$configKey];
132         }
133
134         /**
135          * Set a configuration key
136          *
137          * @param       $configKey      The configuration key we want to add/change
138          * @param       $configValue    The configuration value we want to set
139          * @return      void
140          * @throws      InvalidArgumentException        If $configKey is empty
141          * @throws      InvalidArgumentException        If $configValue has an unsupported variable type
142          */
143         public final function setConfigEntry (string $configKey, $configValue) {
144                 // Is a valid configuration key key provided?
145                 //* NOISY-DEBUG: */ printf('[%s:%d]: configKey=%s,configValue[]=%s - CALLED!' . PHP_EOL, __METHOD__, __LINE__, $configKey, gettype($configValue));
146                 if (empty($configKey)) {
147                         // Entry is empty
148                         throw new InvalidArgumentException('Parameter "configKey" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
149                 } elseif ((is_array($configValue)) || (is_object($configValue)) || (is_resource($configValue))) {
150                         // These cannot be set as this is not intended for configuration values, please use FrameworkArrayObject instead.
151                         throw new InvalidArgumentException(sprintf('configValue[]=%s for configKey=%s is not supported.', gettype($configValue), $configKey), self::EXCEPTION_CONFIG_VALUE_TYPE_UNSUPPORTED);
152                 }
153
154                 // Cast to string
155                 $configKey = str_replace('-', '_', $configKey);
156
157                 // Set the configuration value
158                 //* NOISY-DEBUG: */ printf('[%s:%d]: Setting configKey=%s,configValue[%s]=%s - EXIT!' . PHP_EOL, __METHOD__, __LINE__, $configKey, gettype($configValue), $configValue);
159                 self::$configData[$configKey] = $configValue;
160         }
161
162         /**
163          * Getter for whole configuration array
164          *
165          * @return      $config         Configuration array
166          */
167         public final function getConfigurationArray () {
168                 // Return it
169                 //* NOISY-DEBUG: */ printf('[%s:%d]: self::configData()=%d - EXIT!' . PHP_EOL, __METHOD__, __LINE__, count(self::$configData));
170                 return self::$configData;
171         }
172
173         /**
174          * Sorts the configuration array, saves A LOT calls if done after all configuration files have been loaded. You should NOT
175          * set any configuration entries by your own, means outside any configuration file. If you still do so, you HAVE to call
176          * this method afterwards
177          *
178          * @return      void
179          */
180         public final function sortConfigurationArray () {
181                 // Resort the array
182                 //* NOISY-DEBUG: */ printf('[%s:%d]: Sorting %d records - CALLED!' . PHP_EOL, __METHOD__, __LINE__, count(self::$configData));
183                 ksort(self::$configData);
184
185                 // Debug message
186                 //* NOISY-DEBUG: */ printf('[%s:%d]: EXIT!' . PHP_EOL, __METHOD__, __LINE__);
187         }
188
189         /**
190          * Unset a configuration key, the entry must be there or else an
191          * exception is thrown.
192          *
193          * @param       $configKey      Configuration key to unset
194          * @return      void
195          * @throws      InvalidArgumentException        If $configKey is empty
196          * @throws      NoConfigEntryException  If a configuration element was not found
197          */
198         public final function unsetConfigEntry (string $configKey) {
199                 // Validate parameters
200                 //* NOISY-DEBUG: */ printf('[%s:%d]: configKey=%s - CALLED!' . PHP_EOL, __METHOD__, __LINE__, $configKey);
201                 if (empty($configKey)) {
202                         // Entry is empty
203                         throw new InvalidArgumentException('Parameter "configKey" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
204                 }
205
206                 // Convert dashes to underscore
207                 $configKey = str_replace('-', '_', $configKey);
208
209                 // Is the configuration key there?
210                 //* NOISY-DEBUG: */ printf('[%s:%d]: configKey=%s - AFTER!' . PHP_EOL, __METHOD__, __LINE__, $configKey);
211                 if (!$this->isConfigurationEntrySet($configKey)) {
212                         // Entry was not found!
213                         throw new NoConfigEntryException(array(__CLASS__, $configKey), self::EXCEPTION_CONFIG_KEY_WAS_NOT_FOUND);
214                 }
215
216                 // Unset it
217                 //* NOISY-DEBUG: */ printf('[%s:%d]: Unsetting configKey=%s ...' . PHP_EOL, __METHOD__, __LINE__, $configKey);
218                 unset(self::$configData[$configKey]);
219
220                 // Debug message
221                 //* NOISY-DEBUG: */ printf('[%s:%d]: EXIT!' . PHP_EOL, __METHOD__, __LINE__);
222         }
223
224         /**
225          * Checks if a configuration entry is_*_enabled set to 'Y'
226          *
227          * @param       $keyPart        Configuration to expand with is_$keyPart_enabled
228          * @return      $enabled        Whether it has been set to Y or N
229          * @throws      InvalidArgumentException        If a parameter is invalid
230          * @throws      UnexpectedValueException        If a returned value is of an unexpected type or value
231          */
232         public function isEnabled (string $keyPart) {
233                 // Validate parameters
234                 //* NOISY-DEBUG: */ printf('[%s:%d]: keyPart=%s - CALLED!' . PHP_EOL, __METHOD__, __LINE__, $keyPart);
235                 if (empty($keyPart)) {
236                         // Entry is empty
237                         throw new InvalidArgumentException('Parameter "keyPart" is empty', FrameworkInterface::EXCEPTION_INVALID_ARGUMENT);
238                 }
239
240                 // Construct final config key
241                 $configKey = sprintf('is_%s_enabled', $keyPart);
242
243                 // Get value from it
244                 //* NOISY-DEBUG: */ printf('[%s:%d]: configKey=%s' . PHP_EOL, __METHOD__, __LINE__, $configKey);
245                 $isEnabled = $this->getConfigEntry($configKey);
246
247                 // Is it Y/N?
248                 //* NOISY-DEBUG: */ printf('[%s:%d]: isEnabled[]=%s' . PHP_EOL, __METHOD__, __LINE__, gettype($isEnabled));
249                 if (!is_bool($isEnabled)) {
250                         // Throw exception
251                         throw new UnexpectedValueException(sprintf('isEnabled[]=%s is unexpected', gettype($isEnabled)), FrameworkInterface::EXCEPTION_UNEXPECTED_VALUE);
252                 }
253
254                 // Return it
255                 //* NOISY-DEBUG: */ printf('[%s:%d]: isEnabled=%d - EXIT!' . PHP_EOL, __METHOD__, __LINE__, intval($isEnabled));
256                 return $isEnabled;
257         }
258
259         /**
260          * Generates a code for hashes from this class
261          *
262          * @return      $hashCode       The hash code respresenting this class
263          */
264         public function hashCode () {
265                 return crc32($this->__toString());
266         }
267
268         /**
269          * Checks whether an object equals this object. You should overwrite this
270          * method to implement own equality checks
271          *
272          * @param       $objectInstance         An instance of a FrameworkInterface object
273          * @return      $equals                         Whether both objects equals
274          */
275         public function equals (FrameworkInterface $objectInstance) {
276                 // Now test it
277                 $equals = ((
278                                 $this->__toString() === $objectInstance->__toString()
279                                 ) && (
280                                 $this->hashCode() === $objectInstance->hashCode()
281                                 ));
282
283                 // Return the result
284                 return $equals;
285         }
286
287         /**
288          * Setter for call-back instance
289          *
290          * @param       $callbackInstance       An instance of a FrameworkInterface class
291          * @return      void
292          */
293         public function setCallbackInstance (FrameworkInterface $callbackInstance) {
294                 $this->callbackInstance = $callbackInstance;
295         }
296
297         /**
298          * Getter for field name
299          *
300          * @param       $fieldName              Field name which we shall get
301          * @return      $fieldValue             Field value from the user
302          * @throws      NullPointerException    If the result instance is null
303          */
304         public final function getField (string $fieldName) {
305                 // The super interface "FrameworkInterface" requires this
306                 throw new UnsupportedOperationException([$this, __FUNCTION__], FrameworkInterface::EXCEPTION_UNSPPORTED_OPERATION);
307         }
308
309         /**
310          * Checks if given field is set
311          *
312          * @param       $fieldName      Field name to check
313          * @return      $isSet          Whether the given field name is set
314          * @throws      NullPointerException    If the result instance is null
315          */
316         public function isFieldSet (string $fieldName) {
317                 // The super interface "FrameworkInterface" requires this
318                 throw new UnsupportedOperationException([$this, __FUNCTION__], FrameworkInterface::EXCEPTION_UNSPPORTED_OPERATION);
319         }
320
321 }