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 EE_Addon 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 EE_Addon, and based on these observations, apply Extract Interface, too.
1 | <?php if ( !defined( 'EVENT_ESPRESSO_VERSION' ) ) { |
||
30 | abstract class EE_Addon extends EE_Configurable { |
||
31 | |||
32 | |||
33 | /** |
||
34 | * prefix to be added onto an addon's plugin slug to make a wp option name |
||
35 | * which will be used to store the plugin's activation history |
||
36 | */ |
||
37 | const ee_addon_version_history_option_prefix = 'ee_version_history_'; |
||
38 | |||
39 | /** |
||
40 | * @var $_version |
||
41 | * @type string |
||
42 | */ |
||
43 | protected $_version = ''; |
||
44 | |||
45 | /** |
||
46 | * @var $_min_core_version |
||
47 | * @type string |
||
48 | */ |
||
49 | protected $_min_core_version = ''; |
||
50 | |||
51 | /** |
||
52 | * derived from plugin 'main_file_path using plugin_basename() |
||
53 | * |
||
54 | * @type string $_plugin_basename |
||
55 | */ |
||
56 | protected $_plugin_basename = ''; |
||
57 | |||
58 | /** |
||
59 | * A non-internationalized name to identify this addon for use in URLs, etc |
||
60 | * |
||
61 | * @type string $_plugin_slug |
||
62 | */ |
||
63 | protected $_plugin_slug = ''; |
||
64 | |||
65 | /** |
||
66 | * A non-internationalized name to identify this addon. Eg 'Calendar','MailChimp',etc/ |
||
67 | * @type string _addon_name |
||
68 | */ |
||
69 | protected $_addon_name = ''; |
||
70 | |||
71 | /** |
||
72 | * one of the EE_System::req_type_* constants |
||
73 | * @type int $_req_type |
||
74 | */ |
||
75 | protected $_req_type; |
||
76 | |||
77 | /** |
||
78 | * page slug to be used when generating the "Settings" link on the WP plugin page |
||
79 | * |
||
80 | * @type string $_plugin_action_slug |
||
81 | */ |
||
82 | protected $_plugin_action_slug = ''; |
||
83 | |||
84 | /** |
||
85 | * if not empty, inserts a new table row after this plugin's row on the WP Plugins page |
||
86 | * that can be used for adding upgrading/marketing info |
||
87 | * |
||
88 | * @type array $_plugins_page_row |
||
89 | */ |
||
90 | protected $_plugins_page_row = array(); |
||
91 | |||
92 | |||
93 | |||
94 | /** |
||
95 | * class constructor |
||
96 | */ |
||
97 | public function __construct() { |
||
100 | |||
101 | |||
102 | |||
103 | /** |
||
104 | * @param mixed $version |
||
105 | */ |
||
106 | public function set_version( $version = NULL ) { |
||
109 | |||
110 | |||
111 | /** |
||
112 | * get__version |
||
113 | * @return string |
||
114 | */ |
||
115 | public function version() { |
||
118 | |||
119 | |||
120 | |||
121 | /** |
||
122 | * @param mixed $min_core_version |
||
123 | */ |
||
124 | public function set_min_core_version( $min_core_version = NULL ) { |
||
127 | |||
128 | |||
129 | |||
130 | /** |
||
131 | * get__min_core_version |
||
132 | * @return string |
||
133 | */ |
||
134 | public function min_core_version() { |
||
137 | |||
138 | |||
139 | |||
140 | /** |
||
141 | * Sets addon_name |
||
142 | * @param string $addon_name |
||
143 | * @return boolean |
||
144 | */ |
||
145 | public function set_name( $addon_name ) { |
||
148 | |||
149 | |||
150 | /** |
||
151 | * Gets addon_name |
||
152 | * @return string |
||
153 | */ |
||
154 | public function name() { |
||
157 | |||
158 | |||
159 | |||
160 | /** |
||
161 | * @return string |
||
162 | */ |
||
163 | public function plugin_basename() { |
||
167 | |||
168 | |||
169 | |||
170 | /** |
||
171 | * @param string $plugin_basename |
||
172 | */ |
||
173 | public function set_plugin_basename( $plugin_basename ) { |
||
177 | |||
178 | |||
179 | |||
180 | /** |
||
181 | * @return string |
||
182 | */ |
||
183 | public function plugin_slug() { |
||
187 | |||
188 | |||
189 | |||
190 | /** |
||
191 | * @param string $plugin_slug |
||
192 | */ |
||
193 | public function set_plugin_slug( $plugin_slug ) { |
||
197 | |||
198 | |||
199 | |||
200 | /** |
||
201 | * @return string |
||
202 | */ |
||
203 | public function plugin_action_slug() { |
||
207 | |||
208 | |||
209 | |||
210 | /** |
||
211 | * @param string $plugin_action_slug |
||
212 | */ |
||
213 | public function set_plugin_action_slug( $plugin_action_slug ) { |
||
217 | |||
218 | |||
219 | |||
220 | /** |
||
221 | * @return array |
||
222 | */ |
||
223 | public function get_plugins_page_row() { |
||
227 | |||
228 | |||
229 | |||
230 | /** |
||
231 | * @param array $plugins_page_row |
||
232 | */ |
||
233 | public function set_plugins_page_row( $plugins_page_row = array() ) { |
||
240 | |||
241 | |||
242 | |||
243 | /** |
||
244 | * Called when EE core detects this addon has been activated for the first time. |
||
245 | * If the site isn't in maintenance mode, should setup the addon's database |
||
246 | * @return void |
||
247 | */ |
||
248 | View Code Duplication | public function new_install() { |
|
255 | |||
256 | |||
257 | |||
258 | /** |
||
259 | * Called when EE core detects this addon has been reactivated. When this happens, |
||
260 | * it's good to just check that your data is still intact |
||
261 | * @return void |
||
262 | */ |
||
263 | View Code Duplication | public function reactivation() { |
|
270 | |||
271 | |||
272 | |||
273 | public function deactivation(){ |
||
282 | |||
283 | |||
284 | |||
285 | /** |
||
286 | * Takes care of double-checking that we're not in maintenance mode, and then |
||
287 | * initializing this addon's necessary initial data. This is called by default on new activations |
||
288 | * and reactivations |
||
289 | * |
||
290 | * @param boolean $verify_schema whether to verify the database's schema for this addon, or just its data. |
||
291 | * This is a resource-intensive job so we prefer to only do it when necessary |
||
292 | * @return void |
||
293 | * @throws \EE_Error |
||
294 | */ |
||
295 | public function initialize_db_if_no_migrations_required( $verify_schema = true ) { |
||
333 | |||
334 | |||
335 | |||
336 | /** |
||
337 | * Used to setup this addon's database tables, but not necessarily any default |
||
338 | * data in them. The default is to actually use the most up-to-date data migration script |
||
339 | * for this addon, and just use its schema_changes_before_migration() and schema_changes_after_migration() |
||
340 | * methods to setup the db. |
||
341 | */ |
||
342 | public function initialize_db() { |
||
364 | |||
365 | |||
366 | |||
367 | /** |
||
368 | * If you want to setup default data for the addon, override this method, and call |
||
369 | * parent::initialize_default_data() from within it. This is normally called |
||
370 | * from EE_Addon::initialize_db_if_no_migrations_required(), just after EE_Addon::initialize_db() |
||
371 | * and should verify default data is present (but this is also called |
||
372 | * on reactivations and just after migrations, so please verify you actually want |
||
373 | * to ADD default data, because it may already be present). |
||
374 | * However, please call this parent (currently it just fires a hook which other |
||
375 | * addons may be depending on) |
||
376 | */ |
||
377 | public function initialize_default_data() { |
||
388 | |||
389 | |||
390 | |||
391 | /** |
||
392 | * EE Core detected that this addon has been upgraded. We should check if there |
||
393 | * are any new migration scripts, and if so put the site into maintenance mode until |
||
394 | * they're ran |
||
395 | * @return void |
||
396 | */ |
||
397 | View Code Duplication | public function upgrade() { |
|
407 | |||
408 | |||
409 | |||
410 | /** |
||
411 | * If Core detects this addon has been downgraded, you may want to invoke some special logic here. |
||
412 | */ |
||
413 | public function downgrade() { |
||
420 | |||
421 | |||
422 | |||
423 | /** |
||
424 | * set_db_update_option_name |
||
425 | * Until we do something better, we'll just check for migration scripts upon |
||
426 | * plugin activation only. In the future, we'll want to do it on plugin updates too |
||
427 | * @return bool |
||
428 | */ |
||
429 | public function set_db_update_option_name(){ |
||
434 | |||
435 | |||
436 | /** |
||
437 | * |
||
438 | * Returns the name of the activation indicator option |
||
439 | * (an option which is set temporarily to indicate that this addon was just activated) |
||
440 | * @deprecated since version 4.3.0.alpha.016 |
||
441 | * @return string |
||
442 | */ |
||
443 | public function get_db_update_option_name() { |
||
447 | |||
448 | |||
449 | |||
450 | /** |
||
451 | * When the addon is activated, this should be called to set a wordpress option that |
||
452 | * indicates it was activated. This is especially useful for detecting reactivations. |
||
453 | * @return bool |
||
454 | */ |
||
455 | public function set_activation_indicator_option() { |
||
459 | |||
460 | |||
461 | /** |
||
462 | * Gets the name of the wp option which is used to temporarily indicate that this addon was activated |
||
463 | * @return string |
||
464 | */ |
||
465 | public function get_activation_indicator_option_name(){ |
||
468 | |||
469 | |||
470 | |||
471 | |||
472 | /** |
||
473 | * Used by EE_System to set the request type of this addon. Should not be used by addon developers |
||
474 | * @param int $req_type |
||
475 | */ |
||
476 | public function set_req_type( $req_type ) { |
||
479 | |||
480 | |||
481 | |||
482 | /** |
||
483 | * Returns the request type of this addon (ie, EE_System::req_type_normal, EE_System::req_type_new_activation, EE_System::req_type_reactivation, EE_System::req_type_upgrade, or EE_System::req_type_downgrade). This is set by EE_System when it is checking for new install or upgrades |
||
484 | * of addons |
||
485 | */ |
||
486 | public function detect_req_type() { |
||
492 | |||
493 | |||
494 | |||
495 | /** |
||
496 | * Detects the request type for this addon (whether it was just activated, upgrades, a normal request, etc.) |
||
497 | * Should only be called once per request |
||
498 | * @return void |
||
499 | */ |
||
500 | public function detect_activation_or_upgrade(){ |
||
539 | |||
540 | /** |
||
541 | * Updates the version history for this addon |
||
542 | * @param array $version_history |
||
543 | * @param string $current_version_to_add |
||
544 | * @return boolean success |
||
545 | */ |
||
546 | public function update_list_of_installed_versions($version_history = NULL,$current_version_to_add = NULL) { |
||
558 | |||
559 | /** |
||
560 | * Gets the name of the wp option that stores the activation history |
||
561 | * of this addon |
||
562 | * @return string |
||
563 | */ |
||
564 | public function get_activation_history_option_name(){ |
||
567 | |||
568 | |||
569 | |||
570 | /** |
||
571 | * Gets the wp option which stores the activation history for this addon |
||
572 | * @return array |
||
573 | */ |
||
574 | public function get_activation_history(){ |
||
577 | |||
578 | |||
579 | |||
580 | /** |
||
581 | * @param string $config_section |
||
582 | */ |
||
583 | public function set_config_section( $config_section = '' ) { |
||
586 | /** |
||
587 | * filepath to the main file, which can be used for register_activation_hook, register_deactivation_hook, etc. |
||
588 | * @type string |
||
589 | */ |
||
590 | protected $_main_plugin_file; |
||
591 | |||
592 | /** |
||
593 | * |
||
594 | * Sets the filepath to the main plugin file |
||
595 | * @param string $filepath |
||
596 | */ |
||
597 | public function set_main_plugin_file( $filepath ) { |
||
600 | /** |
||
601 | * gets the filepath to teh main file |
||
602 | * @return string |
||
603 | */ |
||
604 | public function get_main_plugin_file(){ |
||
607 | |||
608 | /** |
||
609 | * Gets the filename (no path) of the main file (the main file loaded |
||
610 | * by WP) |
||
611 | * @return string |
||
612 | */ |
||
613 | public function get_main_plugin_file_basename() { |
||
616 | |||
617 | /** |
||
618 | * Gets the folder name which contains the main plugin file |
||
619 | * @return string |
||
620 | */ |
||
621 | public function get_main_plugin_file_dirname(){ |
||
624 | |||
625 | |||
626 | /** |
||
627 | * sets hooks used in the admin |
||
628 | * |
||
629 | * @return void |
||
630 | */ |
||
631 | public function admin_init(){ |
||
638 | |||
639 | |||
640 | |||
641 | /** |
||
642 | * plugin_actions |
||
643 | * |
||
644 | * Add a settings link to the Plugins page, so people can go straight from the plugin page to the settings page. |
||
645 | * |
||
646 | * @param $links |
||
647 | * @param $file |
||
648 | * @return array |
||
649 | */ |
||
650 | public function plugin_action_links( $links, $file ) { |
||
657 | |||
658 | |||
659 | |||
660 | /** |
||
661 | * after_plugin_row |
||
662 | * |
||
663 | * Add additional content to the plugins page plugin row |
||
664 | * Inserts another row |
||
665 | * |
||
666 | * @param $plugin_file |
||
667 | * @param $plugin_data |
||
668 | * @param $status |
||
669 | * @return void |
||
670 | */ |
||
671 | public function after_plugin_row( $plugin_file, $plugin_data, $status ) { |
||
737 | |||
738 | |||
739 | |||
740 | /** |
||
741 | * a safe space for addons to add additional logic like setting hooks |
||
742 | * that will run immediately after addon registration |
||
743 | * making this a great place for code that needs to be "omnipresent" |
||
744 | * |
||
745 | * @since 4.9.26 |
||
746 | */ |
||
747 | public function after_registration() |
||
751 | |||
752 | |||
753 | } |
||
754 | // End of file EE_Addon.core.php |
||
756 |
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.
For example, imagine you have a variable
$accountId
that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to theid
property of an instance of theAccount
class. This class holds a proper account, so the id value must no longer be false.Either this assignment is in error or a type check should be added for that assignment.