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 Registry 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 Registry, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
23 | class Registry |
||
24 | { |
||
25 | |||
26 | /** |
||
27 | * @var EE_Template_Config $template_config |
||
28 | */ |
||
29 | protected $template_config; |
||
30 | |||
31 | /** |
||
32 | * @var EE_Currency_Config $currency_config |
||
33 | */ |
||
34 | protected $currency_config; |
||
35 | |||
36 | /** |
||
37 | * This holds the jsdata data object that will be exposed on pages that enqueue the `eejs-core` script. |
||
38 | * |
||
39 | * @var array |
||
40 | */ |
||
41 | protected $jsdata = array(); |
||
42 | |||
43 | |||
44 | /** |
||
45 | * This keeps track of all scripts with registered data. It is used to prevent duplicate data objects setup in the |
||
46 | * page source. |
||
47 | * @var array |
||
48 | */ |
||
49 | protected $script_handles_with_data = array(); |
||
50 | |||
51 | |||
52 | |||
53 | /** |
||
54 | * Registry constructor. |
||
55 | * Hooking into WP actions for script registry. |
||
56 | * |
||
57 | * @param EE_Template_Config $template_config |
||
58 | * @param EE_Currency_Config $currency_config |
||
59 | */ |
||
60 | public function __construct(EE_Template_Config $template_config, EE_Currency_Config $currency_config) |
||
71 | |||
72 | |||
73 | |||
74 | /** |
||
75 | * Callback for the WP script actions. |
||
76 | * Used to register globally accessible core scripts. |
||
77 | * Also used to add the eejs.data object to the source for any js having eejs-core as a dependency. |
||
78 | */ |
||
79 | public function scripts() |
||
110 | |||
111 | |||
112 | |||
113 | /** |
||
114 | * Call back for the script print in frontend and backend. |
||
115 | * Used to call wp_localize_scripts so that data can be added throughout the runtime until this later hook point. |
||
116 | * |
||
117 | * @since 4.9.31.rc.015 |
||
118 | */ |
||
119 | public function enqueueData() |
||
120 | { |
||
121 | $this->removeAlreadyRegisteredDataForScriptHandles(); |
||
122 | wp_localize_script('eejs-core', 'eejs', array('data' => $this->jsdata)); |
||
123 | wp_localize_script('espresso_core', 'eei18n', EE_Registry::$i18n_js_strings); |
||
124 | $this->localizeAccountingJs(); |
||
125 | $this->addRegisteredScriptHandlesWithData('eejs-core'); |
||
126 | $this->addRegisteredScriptHandlesWithData('espresso_core'); |
||
127 | } |
||
128 | |||
129 | |||
130 | |||
131 | /** |
||
132 | * Used to add data to eejs.data object. |
||
133 | * Note: Overriding existing data is not allowed. |
||
134 | * Data will be accessible as a javascript object when you list `eejs-core` as a dependency for your javascript. |
||
135 | * If the data you add is something like this: |
||
136 | * $this->addData( 'my_plugin_data', array( 'foo' => 'gar' ) ); |
||
137 | * It will be exposed in the page source as: |
||
138 | * eejs.data.my_plugin_data.foo == gar |
||
139 | * |
||
140 | * @param string $key Key used to access your data |
||
141 | * @param string|array $value Value to attach to key |
||
142 | * @throws InvalidArgumentException |
||
143 | */ |
||
144 | public function addData($key, $value) |
||
150 | |||
151 | |||
152 | |||
153 | /** |
||
154 | * Similar to addData except this allows for users to push values to an existing key where the values on key are |
||
155 | * elements in an array. |
||
156 | * When you use this method, the value you include will be appended to the end of an array on $key. |
||
157 | * So if the $key was 'test' and you added a value of 'my_data' then it would be represented in the javascript |
||
158 | * object like this, eejs.data.test = [ my_data, |
||
159 | * ] |
||
160 | * If there has already been a scalar value attached to the data object given key, then |
||
161 | * this will throw an exception. |
||
162 | * |
||
163 | * @param string $key Key to attach data to. |
||
164 | * @param string|array $value Value being registered. |
||
165 | * @throws InvalidArgumentException |
||
166 | */ |
||
167 | public function pushData($key, $value) |
||
186 | |||
187 | |||
188 | |||
189 | /** |
||
190 | * Used to set content used by javascript for a template. |
||
191 | * Note: Overrides of existing registered templates are not allowed. |
||
192 | * |
||
193 | * @param string $template_reference |
||
194 | * @param string $template_content |
||
195 | * @throws InvalidArgumentException |
||
196 | */ |
||
197 | public function addTemplate($template_reference, $template_content) |
||
216 | |||
217 | |||
218 | |||
219 | /** |
||
220 | * Retrieve the template content already registered for the given reference. |
||
221 | * |
||
222 | * @param string $template_reference |
||
223 | * @return string |
||
224 | */ |
||
225 | public function getTemplate($template_reference) |
||
231 | |||
232 | |||
233 | |||
234 | /** |
||
235 | * Retrieve registered data. |
||
236 | * |
||
237 | * @param string $key Name of key to attach data to. |
||
238 | * @return mixed If there is no for the given key, then false is returned. |
||
239 | */ |
||
240 | public function getData($key) |
||
246 | |||
247 | |||
248 | |||
249 | /** |
||
250 | * Verifies whether the given data exists already on the jsdata array. |
||
251 | * Overriding data is not allowed. |
||
252 | * |
||
253 | * @param string $key Index for data. |
||
254 | * @return bool If valid then return true. |
||
255 | * @throws InvalidArgumentException if data already exists. |
||
256 | */ |
||
257 | protected function verifyDataNotExisting($key) |
||
287 | |||
288 | |||
289 | |||
290 | /** |
||
291 | * registers core default stylesheets |
||
292 | */ |
||
293 | private function loadCoreCss() |
||
316 | |||
317 | |||
318 | |||
319 | /** |
||
320 | * registers core default javascript |
||
321 | */ |
||
322 | private function loadCoreJs() |
||
333 | |||
334 | |||
335 | |||
336 | /** |
||
337 | * registers jQuery Validate for form validation |
||
338 | */ |
||
339 | private function loadJqueryValidate() |
||
357 | |||
358 | |||
359 | |||
360 | /** |
||
361 | * registers accounting.js for performing client-side calculations |
||
362 | */ |
||
363 | private function loadAccountingJs() |
||
364 | { |
||
365 | //accounting.js library |
||
366 | // @link http://josscrowcroft.github.io/accounting.js/ |
||
367 | wp_register_script( |
||
368 | 'ee-accounting-core', |
||
369 | EE_THIRD_PARTY_URL . 'accounting/accounting.js', |
||
370 | array('underscore'), |
||
371 | '0.3.2', |
||
372 | true |
||
373 | ); |
||
374 | wp_register_script( |
||
375 | 'ee-accounting', |
||
376 | EE_GLOBAL_ASSETS_URL . 'scripts/ee-accounting-config.js', |
||
377 | array('ee-accounting-core'), |
||
378 | EVENT_ESPRESSO_VERSION, |
||
379 | true |
||
380 | ); |
||
381 | } |
||
382 | |||
383 | |||
384 | |||
385 | /** |
||
386 | * registers accounting.js for performing client-side calculations |
||
387 | */ |
||
388 | private function localizeAccountingJs() |
||
414 | |||
415 | |||
416 | |||
417 | /** |
||
418 | * registers assets for cleaning your ears |
||
419 | */ |
||
420 | private function loadQtipJs() |
||
428 | |||
429 | |||
430 | /** |
||
431 | * This is used to set registered script handles that have data. |
||
432 | * @param string $script_handle |
||
433 | */ |
||
434 | private function addRegisteredScriptHandlesWithData($script_handle) |
||
438 | |||
439 | |||
440 | /** |
||
441 | * Checks WP_Scripts for all of each script handle registered internally as having data and unsets from the |
||
442 | * Dependency stored in WP_Scripts if its set. |
||
443 | */ |
||
444 | private function removeAlreadyRegisteredDataForScriptHandles() |
||
453 | |||
454 | |||
455 | /** |
||
456 | * Removes any data dependency registered in WP_Scripts if its set. |
||
457 | * @param string $script_handle |
||
458 | */ |
||
459 | private function removeAlreadyRegisteredDataForScriptHandle($script_handle) |
||
469 | |||
470 | |||
471 | } |
||
472 |