1 | <?php |
||||
2 | /** |
||||
3 | * Bright Nucleus Config Component. |
||||
4 | * |
||||
5 | * @package BrightNucleus\Config |
||||
6 | * @author Alain Schlesser <[email protected]> |
||||
7 | * @license MIT |
||||
8 | * @link http://www.brightnucleus.com/ |
||||
9 | * @copyright 2016-2017 Alain Schlesser, Bright Nucleus |
||||
10 | */ |
||||
11 | |||||
12 | namespace BrightNucleus\Config; |
||||
13 | |||||
14 | use BrightNucleus\Config\ConfigSchemaInterface as Schema; |
||||
15 | use BrightNucleus\Config\ConfigValidatorInterface as Validator; |
||||
16 | use BrightNucleus\Config\Exception\FailedToInstantiateParentException; |
||||
17 | use BrightNucleus\Config\Exception\FailedToLoadConfigException; |
||||
18 | use BrightNucleus\Config\Exception\FailedToResolveConfigException; |
||||
19 | use BrightNucleus\Config\Exception\InvalidConfigException; |
||||
20 | use BrightNucleus\Config\Exception\InvalidConfigurationSourceException; |
||||
21 | use Exception; |
||||
22 | use Symfony\Component\OptionsResolver\OptionsResolver; |
||||
23 | |||||
24 | /** |
||||
25 | * Generic implementation of a Config object. |
||||
26 | * |
||||
27 | * @since 0.1.0 |
||||
28 | * |
||||
29 | * @package BrightNucleus\Config |
||||
30 | * @author Alain Schlesser <[email protected]> |
||||
31 | */ |
||||
32 | class Config extends AbstractConfig |
||||
33 | { |
||||
34 | |||||
35 | /** |
||||
36 | * The schema of the Config file. |
||||
37 | * |
||||
38 | * @var Schema |
||||
39 | */ |
||||
40 | protected $schema; |
||||
41 | |||||
42 | /** |
||||
43 | * The Validator class that gets asked to do the validation of the config. |
||||
44 | * |
||||
45 | * @since 0.1.0 |
||||
46 | * |
||||
47 | * @var Validator |
||||
48 | */ |
||||
49 | protected $validator; |
||||
50 | |||||
51 | /** |
||||
52 | * Instantiate the Config object. |
||||
53 | * |
||||
54 | * It accepts either an array with the configuration settings, or a |
||||
55 | * filename pointing to a PHP file it can include. |
||||
56 | * |
||||
57 | * @since 0.1.0 |
||||
58 | * @since 0.1.6 Accepts a delimiter to parse configuration keys. |
||||
59 | * |
||||
60 | * @param array|string $config Array with settings or filename for the |
||||
61 | * settings file. |
||||
62 | * @param Schema|null $schema Optional. Config that contains default |
||||
63 | * values that can get overwritten. |
||||
64 | * @param Validator|null $validator Optional. Validator class that does the |
||||
65 | * actual validation. |
||||
66 | * @param string[]|string|null $delimiter A string or array of strings that are used as delimiters to parse |
||||
67 | * configuration keys. Defaults to "\", "/" & ".". |
||||
68 | * |
||||
69 | * @throws InvalidConfigurationSourceException If the config source is not a string or array. |
||||
70 | * @throws FailedToInstantiateParentException If the parent class could not be instantiated. |
||||
71 | * @throws FailedToLoadConfigException If loading of the config source failed. |
||||
72 | * @throws FailedToResolveConfigException If the config file could not be resolved. |
||||
73 | * @throws InvalidConfigException If the config file is not valid. |
||||
74 | */ |
||||
75 | 11 | public function __construct( |
|||
76 | $config, |
||||
77 | ?Schema $schema = null, |
||||
78 | ?Validator $validator = null, |
||||
79 | $delimiter = null |
||||
80 | ) { |
||||
81 | 11 | $this->schema = $schema; |
|||
82 | 11 | $this->validator = $validator; |
|||
83 | |||||
84 | // Make sure $config is either a string or array. |
||||
85 | 11 | if (! (is_string($config) || is_array($config))) { |
|||
0 ignored issues
–
show
introduced
by
![]() |
|||||
86 | 1 | throw new InvalidConfigurationSourceException( |
|||
87 | sprintf( |
||||
88 | 1 | _('Invalid configuration source: %1$s'), |
|||
89 | 1 | print_r($config, true) |
|||
90 | ) |
||||
91 | ); |
||||
92 | } |
||||
93 | |||||
94 | 10 | if (is_string($config)) { |
|||
95 | 6 | $config = Loader::load($config); |
|||
96 | } |
||||
97 | |||||
98 | // Run the $config through the OptionsResolver. |
||||
99 | 8 | $config = $this->resolveOptions($config); |
|||
100 | |||||
101 | // Instantiate the parent class. |
||||
102 | try { |
||||
103 | 8 | parent::__construct($config, $delimiter); |
|||
104 | } catch (Exception $exception) { |
||||
105 | throw new FailedToInstantiateParentException( |
||||
106 | sprintf( |
||||
107 | _('Could not instantiate the configuration through its parent. Reason: %1$s'), |
||||
108 | $exception->getMessage() |
||||
109 | ) |
||||
110 | ); |
||||
111 | } |
||||
112 | |||||
113 | // Finally, validate the resulting config. |
||||
114 | 8 | if (! $this->isValid()) { |
|||
115 | 1 | throw new InvalidConfigException( |
|||
116 | sprintf( |
||||
117 | 1 | _('ConfigInterface file is not valid: %1$s'), |
|||
118 | 1 | print_r($config, true) |
|||
0 ignored issues
–
show
It seems like
print_r($config, true) can also be of type true ; however, parameter $values of sprintf() does only seem to accept double|integer|string , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
119 | ) |
||||
120 | ); |
||||
121 | } |
||||
122 | 8 | } |
|||
123 | |||||
124 | /** |
||||
125 | * Validate the Config file. |
||||
126 | * |
||||
127 | * @since 0.1.0 |
||||
128 | * |
||||
129 | * @return boolean |
||||
130 | */ |
||||
131 | 4 | public function isValid() |
|||
132 | { |
||||
133 | 4 | if ($this->validator) { |
|||
134 | 1 | return $this->validator->isValid($this); |
|||
135 | } |
||||
136 | |||||
137 | 4 | return true; |
|||
138 | } |
||||
139 | |||||
140 | /** |
||||
141 | * Process the passed-in defaults and merge them with the new values, while |
||||
142 | * checking that all required options are set. |
||||
143 | * |
||||
144 | * @since 0.1.0 |
||||
145 | * |
||||
146 | * @param array $config Configuration settings to resolve. |
||||
147 | * |
||||
148 | * @return array Resolved configuration settings. |
||||
149 | * @throws FailedToResolveConfigException If there are errors while resolving the options. |
||||
150 | */ |
||||
151 | 6 | protected function resolveOptions($config) |
|||
152 | { |
||||
153 | 6 | if (! $this->schema) { |
|||
154 | 6 | return $config; |
|||
155 | } |
||||
156 | |||||
157 | try { |
||||
158 | 2 | $resolver = new OptionsResolver(); |
|||
159 | 2 | if ($this->configureOptions($resolver)) { |
|||
160 | 2 | $config = $resolver->resolve($config); |
|||
161 | } |
||||
162 | 1 | } catch (Exception $exception) { |
|||
163 | 1 | throw new FailedToResolveConfigException( |
|||
164 | sprintf( |
||||
165 | 1 | _('Error while resolving config options: %1$s'), |
|||
166 | 1 | $exception->getMessage() |
|||
167 | ) |
||||
168 | ); |
||||
169 | } |
||||
170 | |||||
171 | 1 | return $config; |
|||
172 | } |
||||
173 | |||||
174 | /** |
||||
175 | * Configure the possible and required options for the Config. |
||||
176 | * |
||||
177 | * This should return a bool to let the resolve_options() know whether the |
||||
178 | * actual resolving needs to be done or not. |
||||
179 | * |
||||
180 | * @since 0.1.0 |
||||
181 | * |
||||
182 | * @param OptionsResolver $resolver Reference to the OptionsResolver |
||||
183 | * instance. |
||||
184 | * |
||||
185 | * @return bool Whether to do the resolving. |
||||
186 | * @throws FailedToResolveConfigException If there are errors while processing. |
||||
187 | */ |
||||
188 | 2 | protected function configureOptions(OptionsResolver $resolver) |
|||
189 | { |
||||
190 | 2 | $defined = $this->schema->getDefinedOptions(); |
|||
191 | 2 | $defaults = $this->schema->getDefaultOptions(); |
|||
192 | 2 | $required = $this->schema->getRequiredOptions(); |
|||
193 | |||||
194 | 2 | if (! $defined && ! $defaults && ! $required) { |
|||
195 | return false; |
||||
196 | } |
||||
197 | |||||
198 | try { |
||||
199 | 2 | if ($defined) { |
|||
200 | 2 | $resolver->setDefined($defined); |
|||
201 | } |
||||
202 | 2 | if ($defaults) { |
|||
203 | 2 | $resolver->setDefaults($defaults); |
|||
204 | } |
||||
205 | 2 | if ($required) { |
|||
206 | 2 | $resolver->setRequired($required); |
|||
207 | } |
||||
208 | } catch (Exception $exception) { |
||||
209 | throw new FailedToResolveConfigException( |
||||
210 | sprintf( |
||||
211 | _('Error while processing config options: %1$s'), |
||||
212 | $exception->getMessage() |
||||
213 | ) |
||||
214 | ); |
||||
215 | } |
||||
216 | |||||
217 | 2 | return true; |
|||
218 | } |
||||
219 | } |
||||
220 |