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 Jetpack_Likes 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 Jetpack_Likes, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
25 | class Jetpack_Likes { |
||
26 | public static function init() { |
||
27 | static $instance = NULL; |
||
28 | |||
29 | if ( ! $instance ) { |
||
30 | $instance = new Jetpack_Likes; |
||
31 | } |
||
32 | |||
33 | return $instance; |
||
34 | } |
||
35 | |||
36 | function __construct() { |
||
37 | $this->in_jetpack = ( defined( 'IS_WPCOM' ) && IS_WPCOM ) ? false : true; |
||
|
|||
38 | $this->settings = new Jetpack_Likes_Settings(); |
||
39 | |||
40 | add_action( 'init', array( &$this, 'action_init' ) ); |
||
41 | add_action( 'admin_init', array( $this, 'admin_init' ) ); |
||
42 | |||
43 | if ( $this->in_jetpack ) { |
||
44 | add_action( 'jetpack_activate_module_likes', array( $this, 'set_social_notifications_like' ) ); |
||
45 | add_action( 'jetpack_deactivate_module_likes', array( $this, 'delete_social_notifications_like' ) ); |
||
46 | |||
47 | Jetpack::enable_module_configurable( __FILE__ ); |
||
48 | Jetpack::module_configuration_load( __FILE__, array( $this, 'configuration_redirect' ) ); |
||
49 | |||
50 | add_action( 'admin_print_scripts-settings_page_sharing', array( &$this, 'load_jp_css' ) ); |
||
51 | add_filter( 'sharing_show_buttons_on_row_start', array( $this, 'configuration_target_area' ) ); |
||
52 | |||
53 | $active = Jetpack::get_active_modules(); |
||
54 | |||
55 | View Code Duplication | if ( ! in_array( 'sharedaddy', $active ) && ! in_array( 'publicize', $active ) ) { |
|
56 | // we don't have a sharing page yet |
||
57 | add_action( 'admin_menu', array( $this->settings, 'sharing_menu' ) ); |
||
58 | } |
||
59 | |||
60 | View Code Duplication | if ( in_array( 'publicize', $active ) && ! in_array( 'sharedaddy', $active ) ) { |
|
61 | // we have a sharing page but not the global options area |
||
62 | add_action( 'pre_admin_screen_sharing', array( $this->settings, 'sharing_block' ), 20 ); |
||
63 | add_action( 'pre_admin_screen_sharing', array( $this->settings, 'updated_message' ), -10 ); |
||
64 | } |
||
65 | |||
66 | View Code Duplication | if( ! in_array( 'sharedaddy', $active ) ) { |
|
67 | add_action( 'admin_init', array( $this->settings, 'process_update_requests_if_sharedaddy_not_loaded' ) ); |
||
68 | add_action( 'sharing_global_options', array( $this->settings, 'admin_settings_showbuttonon_init' ), 19 ); |
||
69 | add_action( 'sharing_admin_update', array( $this->settings, 'admin_settings_showbuttonon_callback' ), 19 ); |
||
70 | add_action( 'admin_init', array( $this->settings, 'add_meta_box' ) ); |
||
71 | } else { |
||
72 | add_filter( 'sharing_meta_box_title', array( $this->settings, 'add_likes_to_sharing_meta_box_title' ) ); |
||
73 | add_action( 'start_sharing_meta_box_content', array( $this->settings, 'meta_box_content' ) ); |
||
74 | } |
||
75 | } else { // wpcom |
||
76 | add_action( 'wpmu_new_blog', array( $this, 'enable_comment_likes' ), 10, 1 ); |
||
77 | add_action( 'admin_init', array( $this->settings, 'add_meta_box' ) ); |
||
78 | add_action( 'end_likes_meta_box_content', array( $this->settings, 'sharing_meta_box_content' ) ); |
||
79 | add_filter( 'likes_meta_box_title', array( $this->settings, 'add_likes_to_sharing_meta_box_title' ) ); |
||
80 | } |
||
81 | |||
82 | add_action( 'admin_init', array( $this, 'admin_discussion_likes_settings_init' ) ); // Likes notifications |
||
83 | |||
84 | add_action( 'admin_bar_menu', array( $this, 'admin_bar_likes' ), 60 ); |
||
85 | |||
86 | add_action( 'wp_enqueue_scripts', array( $this, 'load_styles_register_scripts' ) ); |
||
87 | |||
88 | add_action( 'save_post', array( $this->settings, 'meta_box_save' ) ); |
||
89 | add_action( 'edit_attachment', array( $this->settings, 'meta_box_save' ) ); |
||
90 | add_action( 'sharing_global_options', array( $this->settings, 'admin_settings_init' ), 20 ); |
||
91 | add_action( 'sharing_admin_update', array( $this->settings, 'admin_settings_callback' ), 20 ); |
||
92 | } |
||
93 | |||
94 | /** |
||
95 | * Set the social_notifications_like option to `on` when the Likes module is activated. |
||
96 | * |
||
97 | * @since 3.7.0 |
||
98 | * |
||
99 | * @return null |
||
100 | */ |
||
101 | function set_social_notifications_like() { |
||
102 | update_option( 'social_notifications_like', 'on' ); |
||
103 | } |
||
104 | |||
105 | /** |
||
106 | * Delete the social_notifications_like option that was set to `on` on module activation. |
||
107 | * |
||
108 | * @since 3.7.0 |
||
109 | * |
||
110 | * @return null |
||
111 | */ |
||
112 | function delete_social_notifications_like() { |
||
113 | delete_option( 'social_notifications_like' ); |
||
114 | } |
||
115 | |||
116 | /** |
||
117 | * Redirects to the likes section of the sharing page. |
||
118 | */ |
||
119 | function configuration_redirect() { |
||
120 | wp_safe_redirect( admin_url( 'options-general.php?page=sharing#likes' ) ); |
||
121 | die(); |
||
122 | } |
||
123 | |||
124 | /** |
||
125 | * Loads Jetpack's CSS on the sharing page so we can use .jetpack-targetable |
||
126 | */ |
||
127 | function load_jp_css() { |
||
128 | // Do we really need `admin_styles`? With the new admin UI, it's breaking some bits. |
||
129 | // Jetpack::init()->admin_styles(); |
||
130 | } |
||
131 | |||
132 | /** |
||
133 | * Load scripts and styles for front end. |
||
134 | * @return null |
||
135 | */ |
||
136 | function load_styles_register_scripts() { |
||
137 | if ( $this->in_jetpack ) { |
||
138 | wp_enqueue_style( 'jetpack_likes', plugins_url( 'likes/style.css', __FILE__ ), array(), JETPACK__VERSION ); |
||
139 | $this->register_scripts(); |
||
140 | } |
||
141 | } |
||
142 | |||
143 | /** |
||
144 | * Stub for is_likes_visible, since some themes were calling it directly from this class |
||
145 | * |
||
146 | * @deprecated 5.4 |
||
147 | * @return bool |
||
148 | */ |
||
149 | function is_likes_visible() { |
||
150 | _deprecated_function( __METHOD__, 'jetpack-5.4', 'Jetpack_Likes_Settings()->is_likes_visible' ); |
||
151 | |||
152 | $settings = new Jetpack_Likes_Settings(); |
||
153 | return $settings->is_likes_visible(); |
||
154 | } |
||
155 | |||
156 | /** |
||
157 | * Adds in the jetpack-targetable class so when we visit sharing#likes our like settings get highlighted by a yellow box |
||
158 | * @param string $html row heading for the sharedaddy "which page" setting |
||
159 | * @return string html with the jetpack-targetable class and likes id. tbody gets closed after the like settings |
||
160 | */ |
||
161 | function configuration_target_area( $html = '' ) { |
||
165 | |||
166 | /** |
||
167 | * WordPress.com: Metabox option for sharing (sharedaddy will handle this on the JP blog) |
||
168 | */ |
||
169 | function sharing_meta_box_content( $post ) { |
||
170 | $post_id = ! empty( $post->ID ) ? (int) $post->ID : get_the_ID(); |
||
171 | $disabled = get_post_meta( $post_id, 'sharing_disabled', true ); ?> |
||
172 | <p> |
||
173 | <label for="wpl_enable_post_sharing"> |
||
180 | |||
181 | /** |
||
182 | * Options to be added to the discussion page (see also admin_settings_init, etc below for Sharing settings page) |
||
183 | */ |
||
184 | |||
185 | View Code Duplication | function admin_discussion_likes_settings_init() { |
|
192 | |||
193 | function admin_discussion_likes_settings_section() { |
||
213 | |||
214 | function admin_likes_get_option( $option ) { |
||
223 | |||
224 | function admin_discussion_likes_settings_field() { |
||
230 | |||
231 | function admin_discussion_likes_settings_validate( $input ) { |
||
239 | |||
240 | function admin_init() { |
||
248 | |||
249 | function action_init() { |
||
280 | |||
281 | /** |
||
282 | * Register scripts |
||
283 | */ |
||
284 | function register_scripts() { |
||
313 | |||
314 | /** |
||
315 | * Load the CSS needed for the wp-admin area. |
||
316 | */ |
||
317 | function load_admin_css() { |
||
356 | |||
357 | /** |
||
358 | * Load the JS required for loading the like counts. |
||
359 | */ |
||
360 | function enqueue_admin_scripts() { |
||
388 | |||
389 | /** |
||
390 | * Add "Likes" column data to the post edit table in wp-admin. |
||
391 | * |
||
392 | * @param string $column_name |
||
393 | * @param int $post_id |
||
394 | */ |
||
395 | function likes_edit_column( $column_name, $post_id ) { |
||
411 | |||
412 | /** |
||
413 | * Add a "Likes" column header to the post edit table in wp-admin. |
||
414 | * |
||
415 | * @param array $columns |
||
416 | * @return array |
||
417 | */ |
||
418 | function add_like_count_column( $columns ) { |
||
427 | |||
428 | function post_likes( $content ) { |
||
473 | |||
474 | function post_flair_service_enabled_like( $classes ) { |
||
478 | |||
479 | function is_admin_bar_button_visible() { |
||
505 | |||
506 | function admin_bar_likes() { |
||
545 | } |
||
546 | |||
548 |
In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:
Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion: