Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like Configure often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use Configure, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
33 | class Configure |
||
34 | { |
||
35 | |||
36 | /** |
||
37 | * Array of values currently stored in Configure. |
||
38 | * |
||
39 | * @var array |
||
40 | */ |
||
41 | protected static $_values = [ |
||
42 | 'debug' => false |
||
43 | ]; |
||
44 | |||
45 | /** |
||
46 | * Configured engine classes, used to load config files from resources |
||
47 | * |
||
48 | * @see \Cake\Core\Configure::load() |
||
49 | * @var \Cake\Core\Configure\ConfigEngineInterface[] |
||
50 | */ |
||
51 | protected static $_engines = []; |
||
52 | |||
53 | /** |
||
54 | * Flag to track whether or not ini_set exists. |
||
55 | * |
||
56 | * @var bool|null |
||
57 | */ |
||
58 | protected static $_hasIniSet; |
||
59 | |||
60 | /** |
||
61 | * Used to store a dynamic variable in Configure. |
||
62 | * |
||
63 | * Usage: |
||
64 | * ``` |
||
65 | * Configure::write('One.key1', 'value of the Configure::One[key1]'); |
||
66 | * Configure::write(['One.key1' => 'value of the Configure::One[key1]']); |
||
67 | * Configure::write('One', [ |
||
68 | * 'key1' => 'value of the Configure::One[key1]', |
||
69 | * 'key2' => 'value of the Configure::One[key2]' |
||
70 | * ]); |
||
71 | * |
||
72 | * Configure::write([ |
||
73 | * 'One.key1' => 'value of the Configure::One[key1]', |
||
74 | * 'One.key2' => 'value of the Configure::One[key2]' |
||
75 | * ]); |
||
76 | * ``` |
||
77 | * |
||
78 | * @param string|array $config The key to write, can be a dot notation value. |
||
79 | * Alternatively can be an array containing key(s) and value(s). |
||
80 | * @param mixed $value Value to set for var |
||
81 | * @return bool True if write was successful |
||
82 | * @link https://book.cakephp.org/3.0/en/development/configuration.html#writing-configuration-data |
||
83 | */ |
||
84 | public static function write($config, $value = null) |
||
105 | |||
106 | /** |
||
107 | * Used to read information stored in Configure. It's not |
||
108 | * possible to store `null` values in Configure. |
||
109 | * |
||
110 | * Usage: |
||
111 | * ``` |
||
112 | * Configure::read('Name'); will return all values for Name |
||
113 | * Configure::read('Name.key'); will return only the value of Configure::Name[key] |
||
114 | * ``` |
||
115 | * |
||
116 | * @param string|null $var Variable to obtain. Use '.' to access array elements. |
||
117 | * @param mixed $default The return value when the configure does not exist |
||
118 | * @return mixed Value stored in configure, or null. |
||
119 | * @link https://book.cakephp.org/3.0/en/development/configuration.html#reading-configuration-data |
||
120 | */ |
||
121 | public static function read($var = null, $default = null) |
||
129 | |||
130 | /** |
||
131 | * Returns true if given variable is set in Configure. |
||
132 | * |
||
133 | * @param string $var Variable name to check for |
||
134 | * @return bool True if variable is there |
||
135 | */ |
||
136 | public static function check($var) |
||
144 | |||
145 | /** |
||
146 | * Used to get information stored in Configure. It's not |
||
147 | * possible to store `null` values in Configure. |
||
148 | * |
||
149 | * Acts as a wrapper around Configure::read() and Configure::check(). |
||
150 | * The configure key/value pair fetched via this method is expected to exist. |
||
151 | * In case it does not an exception will be thrown. |
||
152 | * |
||
153 | * Usage: |
||
154 | * ``` |
||
155 | * Configure::readOrFail('Name'); will return all values for Name |
||
156 | * Configure::readOrFail('Name.key'); will return only the value of Configure::Name[key] |
||
157 | * ``` |
||
158 | * |
||
159 | * @param string $var Variable to obtain. Use '.' to access array elements. |
||
160 | * @return mixed Value stored in configure. |
||
161 | * @throws \RuntimeException if the requested configuration is not set. |
||
162 | * @link https://book.cakephp.org/3.0/en/development/configuration.html#reading-configuration-data |
||
163 | */ |
||
164 | View Code Duplication | public static function readOrFail($var) |
|
172 | |||
173 | /** |
||
174 | * Used to delete a variable from Configure. |
||
175 | * |
||
176 | * Usage: |
||
177 | * ``` |
||
178 | * Configure::delete('Name'); will delete the entire Configure::Name |
||
179 | * Configure::delete('Name.key'); will delete only the Configure::Name[key] |
||
180 | * ``` |
||
181 | * |
||
182 | * @param string $var the var to be deleted |
||
183 | * @return void |
||
184 | * @link https://book.cakephp.org/3.0/en/development/configuration.html#deleting-configuration-data |
||
185 | */ |
||
186 | public static function delete($var) |
||
190 | |||
191 | /** |
||
192 | * Used to consume information stored in Configure. It's not |
||
193 | * possible to store `null` values in Configure. |
||
194 | * |
||
195 | * Acts as a wrapper around Configure::consume() and Configure::check(). |
||
196 | * The configure key/value pair consumed via this method is expected to exist. |
||
197 | * In case it does not an exception will be thrown. |
||
198 | * |
||
199 | * @param string $var Variable to consume. Use '.' to access array elements. |
||
200 | * @return mixed Value stored in configure. |
||
201 | * @throws \RuntimeException if the requested configuration is not set. |
||
202 | * @since 3.6.0 |
||
203 | */ |
||
204 | View Code Duplication | public static function consumeOrFail($var) |
|
212 | |||
213 | /** |
||
214 | * Used to read and delete a variable from Configure. |
||
215 | * |
||
216 | * This is primarily used during bootstrapping to move configuration data |
||
217 | * out of configure into the various other classes in CakePHP. |
||
218 | * |
||
219 | * @param string $var The key to read and remove. |
||
220 | * @return array|string|null |
||
221 | */ |
||
222 | public static function consume($var) |
||
238 | |||
239 | /** |
||
240 | * Add a new engine to Configure. Engines allow you to read configuration |
||
241 | * files in various formats/storage locations. CakePHP comes with two built-in engines |
||
242 | * PhpConfig and IniConfig. You can also implement your own engine classes in your application. |
||
243 | * |
||
244 | * To add a new engine to Configure: |
||
245 | * |
||
246 | * ``` |
||
247 | * Configure::config('ini', new IniConfig()); |
||
248 | * ``` |
||
249 | * |
||
250 | * @param string $name The name of the engine being configured. This alias is used later to |
||
251 | * read values from a specific engine. |
||
252 | * @param \Cake\Core\Configure\ConfigEngineInterface $engine The engine to append. |
||
253 | * @return void |
||
254 | */ |
||
255 | public static function config($name, ConfigEngineInterface $engine) |
||
259 | |||
260 | /** |
||
261 | * Gets the names of the configured Engine objects. |
||
262 | * |
||
263 | * Checking if a specific engine has been configured with this method is deprecated. |
||
264 | * Use Configure::isConfigured() instead. |
||
265 | * |
||
266 | * @param string|null $name Engine name. |
||
267 | * @return array|bool Array of the configured Engine objects, bool for specific name. |
||
268 | */ |
||
269 | public static function configured($name = null) |
||
282 | |||
283 | /** |
||
284 | * Returns true if the Engine objects is configured. |
||
285 | * |
||
286 | * @param string $name Engine name. |
||
287 | * @return bool |
||
288 | */ |
||
289 | public static function isConfigured($name) |
||
293 | |||
294 | /** |
||
295 | * Remove a configured engine. This will unset the engine |
||
296 | * and make any future attempts to use it cause an Exception. |
||
297 | * |
||
298 | * @param string $name Name of the engine to drop. |
||
299 | * @return bool Success |
||
300 | */ |
||
301 | public static function drop($name) |
||
310 | |||
311 | /** |
||
312 | * Loads stored configuration information from a resource. You can add |
||
313 | * config file resource engines with `Configure::config()`. |
||
314 | * |
||
315 | * Loaded configuration information will be merged with the current |
||
316 | * runtime configuration. You can load configuration files from plugins |
||
317 | * by preceding the filename with the plugin name. |
||
318 | * |
||
319 | * `Configure::load('Users.user', 'default')` |
||
320 | * |
||
321 | * Would load the 'user' config file using the default config engine. You can load |
||
322 | * app config files by giving the name of the resource you want loaded. |
||
323 | * |
||
324 | * ``` |
||
325 | * Configure::load('setup', 'default'); |
||
326 | * ``` |
||
327 | * |
||
328 | * If using `default` config and no engine has been configured for it yet, |
||
329 | * one will be automatically created using PhpConfig |
||
330 | * |
||
331 | * @param string $key name of configuration resource to load. |
||
332 | * @param string $config Name of the configured engine to use to read the resource identified by $key. |
||
333 | * @param bool $merge if config files should be merged instead of simply overridden |
||
334 | * @return bool False if file not found, true if load successful. |
||
335 | * @link https://book.cakephp.org/3.0/en/development/configuration.html#reading-and-writing-configuration-files |
||
336 | */ |
||
337 | public static function load($key, $config = 'default', $merge = true) |
||
351 | |||
352 | /** |
||
353 | * Dump data currently in Configure into $key. The serialization format |
||
354 | * is decided by the config engine attached as $config. For example, if the |
||
355 | * 'default' adapter is a PhpConfig, the generated file will be a PHP |
||
356 | * configuration file loadable by the PhpConfig. |
||
357 | * |
||
358 | * ### Usage |
||
359 | * |
||
360 | * Given that the 'default' engine is an instance of PhpConfig. |
||
361 | * Save all data in Configure to the file `my_config.php`: |
||
362 | * |
||
363 | * ``` |
||
364 | * Configure::dump('my_config', 'default'); |
||
365 | * ``` |
||
366 | * |
||
367 | * Save only the error handling configuration: |
||
368 | * |
||
369 | * ``` |
||
370 | * Configure::dump('error', 'default', ['Error', 'Exception']; |
||
371 | * ``` |
||
372 | * |
||
373 | * @param string $key The identifier to create in the config adapter. |
||
374 | * This could be a filename or a cache key depending on the adapter being used. |
||
375 | * @param string $config The name of the configured adapter to dump data with. |
||
376 | * @param array $keys The name of the top-level keys you want to dump. |
||
377 | * This allows you save only some data stored in Configure. |
||
378 | * @return bool Success |
||
379 | * @throws \Cake\Core\Exception\Exception if the adapter does not implement a `dump` method. |
||
380 | */ |
||
381 | public static function dump($key, $config = 'default', $keys = []) |
||
394 | |||
395 | /** |
||
396 | * Get the configured engine. Internally used by `Configure::load()` and `Configure::dump()` |
||
397 | * Will create new PhpConfig for default if not configured yet. |
||
398 | * |
||
399 | * @param string $config The name of the configured adapter |
||
400 | * @return \Cake\Core\Configure\ConfigEngineInterface|false Engine instance or false |
||
401 | */ |
||
402 | protected static function _getEngine($config) |
||
413 | |||
414 | /** |
||
415 | * Used to determine the current version of CakePHP. |
||
416 | * |
||
417 | * Usage |
||
418 | * ``` |
||
419 | * Configure::version(); |
||
420 | * ``` |
||
421 | * |
||
422 | * @return string Current version of CakePHP |
||
423 | */ |
||
424 | public static function version() |
||
433 | |||
434 | /** |
||
435 | * Used to write runtime configuration into Cache. Stored runtime configuration can be |
||
436 | * restored using `Configure::restore()`. These methods can be used to enable configuration managers |
||
437 | * frontends, or other GUI type interfaces for configuration. |
||
438 | * |
||
439 | * @param string $name The storage name for the saved configuration. |
||
440 | * @param string $cacheConfig The cache configuration to save into. Defaults to 'default' |
||
441 | * @param array|null $data Either an array of data to store, or leave empty to store all values. |
||
442 | * @return bool Success |
||
443 | */ |
||
444 | View Code Duplication | public static function store($name, $cacheConfig = 'default', $data = null) |
|
455 | |||
456 | /** |
||
457 | * Restores configuration data stored in the Cache into configure. Restored |
||
458 | * values will overwrite existing ones. |
||
459 | * |
||
460 | * @param string $name Name of the stored config file to load. |
||
461 | * @param string $cacheConfig Name of the Cache configuration to read from. |
||
462 | * @return bool Success. |
||
463 | */ |
||
464 | View Code Duplication | public static function restore($name, $cacheConfig = 'default') |
|
476 | |||
477 | /** |
||
478 | * Clear all values stored in Configure. |
||
479 | * |
||
480 | * @return bool success. |
||
481 | */ |
||
482 | public static function clear() |
||
488 | } |
||
489 |
If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:
If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.