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_Sync_Module_Themes 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_Sync_Module_Themes, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
3 | class Jetpack_Sync_Module_Themes extends Jetpack_Sync_Module { |
||
4 | function name() { |
||
7 | |||
8 | public function init_listeners( $callable ) { |
||
33 | |||
34 | public function sync_widget_edit( $instance, $new_instance, $old_instance, $widget_object ) { |
||
54 | |||
55 | public function sync_network_allowed_themes_change( $option, $value, $old_value, $network_id ) { |
||
92 | |||
93 | private function get_theme_details_for_slugs( $theme_slugs ) { |
||
106 | |||
107 | public function detect_theme_edit( $redirect_url ) { |
||
144 | |||
145 | public function detect_theme_deletion() { |
||
146 | $delete_theme_call = $this->get_delete_theme_call(); |
||
147 | if ( empty( $delete_theme_call ) ) { |
||
148 | return; |
||
149 | } |
||
150 | |||
151 | $slug = $delete_theme_call['args'][0]; |
||
152 | $theme = wp_get_theme( $slug ); |
||
153 | $theme_data = array( |
||
154 | 'name' => $theme->get('Name'), |
||
155 | 'version' => $theme->get('Version'), |
||
156 | 'uri' => $theme->get( 'ThemeURI' ), |
||
157 | 'slug' => $slug, |
||
158 | ); |
||
159 | |||
160 | /** |
||
161 | * Signals to the sync listener that a theme was deleted and a sync action |
||
162 | * reflecting the deletion and theme slug should be sent |
||
163 | * |
||
164 | * @since 5.0.0 |
||
165 | * |
||
166 | * @param string $slug Theme slug |
||
167 | * @param array $theme_data Theme info Since 5.3 |
||
168 | */ |
||
169 | do_action( 'jetpack_deleted_theme', $slug, $theme_data ); |
||
170 | } |
||
171 | |||
172 | public function check_upgrader( $upgrader, $details) { |
||
173 | View Code Duplication | if ( ! isset( $details['type'] ) || |
|
174 | 'theme' !== $details['type'] || |
||
175 | is_wp_error( $upgrader->skin->result ) || |
||
176 | ! method_exists( $upgrader, 'theme_info' ) |
||
177 | ) { |
||
178 | return; |
||
179 | } |
||
180 | |||
181 | $theme = $upgrader->theme_info(); |
||
182 | if ( ! $theme instanceof WP_Theme ) { |
||
|
|||
183 | return; |
||
184 | } |
||
185 | $theme_info = array( |
||
186 | 'name' => $theme->get( 'Name' ), |
||
187 | 'version' => $theme->get( 'Version' ), |
||
188 | 'uri' => $theme->get( 'ThemeURI' ), |
||
189 | ); |
||
190 | |||
191 | if ( 'install' === $details['action'] ) { |
||
192 | /** |
||
193 | * Signals to the sync listener that a theme was installed and a sync action |
||
194 | * reflecting the installation and the theme info should be sent |
||
195 | * |
||
196 | * @since 4.9.0 |
||
197 | * |
||
198 | * @param string $theme->theme_root Text domain of the theme |
||
199 | * @param mixed $theme_info Array of abbreviated theme info |
||
200 | */ |
||
201 | do_action( 'jetpack_installed_theme', $theme->stylesheet, $theme_info ); |
||
202 | } |
||
203 | |||
204 | if ( 'update' === $details['action'] ) { |
||
205 | /** |
||
206 | * Signals to the sync listener that a theme was updated and a sync action |
||
207 | * reflecting the update and the theme info should be sent |
||
208 | * |
||
209 | * @since 4.9.0 |
||
210 | * |
||
211 | * @param string $theme->theme_root Text domain of the theme |
||
212 | * @param mixed $theme_info Array of abbreviated theme info |
||
213 | */ |
||
214 | do_action( 'jetpack_updated_theme', $theme->stylesheet, $theme_info ); |
||
215 | } |
||
216 | } |
||
217 | |||
218 | public function init_full_sync_listeners( $callable ) { |
||
219 | add_action( 'jetpack_full_sync_theme_data', $callable ); |
||
220 | } |
||
221 | |||
222 | public function sync_theme_support() { |
||
223 | /** |
||
224 | * Fires when the client needs to sync theme support info |
||
225 | * Only sends theme support attributes whitelisted in Jetpack_Sync_Defaults::$default_theme_support_whitelist |
||
226 | * |
||
227 | * @since 4.2.0 |
||
228 | * |
||
229 | * @param object the theme support hash |
||
230 | */ |
||
231 | do_action( 'jetpack_sync_current_theme_support' , $this->get_theme_support_info() ); |
||
232 | } |
||
233 | |||
234 | public function enqueue_full_sync_actions( $config, $max_items_to_enqueue, $state ) { |
||
235 | /** |
||
236 | * Tells the client to sync all theme data to the server |
||
237 | * |
||
238 | * @since 4.2.0 |
||
239 | * |
||
240 | * @param boolean Whether to expand theme data (should always be true) |
||
241 | */ |
||
242 | do_action( 'jetpack_full_sync_theme_data', true ); |
||
243 | |||
244 | // The number of actions enqueued, and next module state (true == done) |
||
245 | return array( 1, true ); |
||
246 | } |
||
247 | |||
248 | public function estimate_full_sync_actions( $config ) { |
||
249 | return 1; |
||
250 | } |
||
251 | |||
252 | public function init_before_send() { |
||
253 | add_filter( 'jetpack_sync_before_send_jetpack_full_sync_theme_data', array( $this, 'expand_theme_data' ) ); |
||
254 | } |
||
255 | |||
256 | function get_full_sync_actions() { |
||
257 | return array( 'jetpack_full_sync_theme_data' ); |
||
258 | } |
||
259 | |||
260 | function expand_theme_data() { |
||
261 | return array( $this->get_theme_support_info() ); |
||
262 | } |
||
263 | |||
264 | function get_widget_name( $widget_id ) { |
||
265 | global $wp_registered_widgets; |
||
266 | return ( isset( $wp_registered_widgets[ $widget_id ] ) ? $wp_registered_widgets[ $widget_id ]['name'] : null ); |
||
267 | } |
||
268 | |||
269 | function get_sidebar_name( $sidebar_id ) { |
||
270 | global $wp_registered_sidebars; |
||
271 | return ( isset( $wp_registered_sidebars[ $sidebar_id ] ) ? $wp_registered_sidebars[ $sidebar_id ]['name'] : null ); |
||
272 | } |
||
273 | |||
274 | function sync_add_widgets_to_sidebar( $new_widgets, $old_widgets, $sidebar ) { |
||
275 | $added_widgets = array_diff( $new_widgets, $old_widgets ); |
||
276 | if ( empty( $added_widgets ) ) { |
||
277 | return array(); |
||
278 | } |
||
279 | $moved_to_sidebar = array(); |
||
280 | $sidebar_name = $this->get_sidebar_name( $sidebar ); |
||
281 | |||
282 | //Don't sync jetpack_widget_added if theme was switched |
||
283 | if ( $this->is_theme_switch() ) { |
||
284 | return array(); |
||
285 | } |
||
286 | |||
287 | foreach ( $added_widgets as $added_widget ) { |
||
288 | $moved_to_sidebar[] = $added_widget; |
||
289 | $added_widget_name = $this->get_widget_name( $added_widget ); |
||
290 | /** |
||
291 | * Helps Sync log that a widget got added |
||
292 | * |
||
293 | * @since 4.9.0 |
||
294 | * |
||
295 | * @param string $sidebar, Sidebar id got changed |
||
296 | * @param string $added_widget, Widget id got added |
||
297 | * @param string $sidebar_name, Sidebar id got changed Since 5.0.0 |
||
298 | * @param string $added_widget_name, Widget id got added Since 5.0.0 |
||
299 | * |
||
300 | */ |
||
301 | do_action( 'jetpack_widget_added', $sidebar, $added_widget, $sidebar_name, $added_widget_name ); |
||
302 | } |
||
303 | return $moved_to_sidebar; |
||
304 | } |
||
305 | |||
306 | function sync_remove_widgets_from_sidebar( $new_widgets, $old_widgets, $sidebar, $inactive_widgets ) { |
||
338 | |||
339 | function sync_widgets_reordered( $new_widgets, $old_widgets, $sidebar ) { |
||
363 | |||
364 | function sync_sidebar_widgets_actions( $old_value, $new_value ) { |
||
365 | // Don't really know how to deal with different array_values yet. |
||
366 | if ( |
||
367 | ( isset( $old_value['array_version'] ) && $old_value['array_version'] !== 3 ) || |
||
368 | ( isset( $new_value['array_version'] ) && $new_value['array_version'] !== 3 ) |
||
369 | ) { |
||
370 | return; |
||
371 | } |
||
372 | |||
373 | $moved_to_inactive_ids = array(); |
||
374 | $moved_to_sidebar = array(); |
||
375 | |||
426 | |||
427 | private function get_theme_support_info() { |
||
448 | |||
449 | private function get_delete_theme_call() { |
||
460 | |||
461 | private function is_theme_switch() { |
||
464 | } |
This error could be the result of:
1. Missing dependencies
PHP Analyzer uses your
composer.json
file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects thecomposer.json
to be in the root folder of your repository.Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the
require
orrequire-dev
section?2. Missing use statement
PHP does not complain about undefined classes in
ìnstanceof
checks. For example, the following PHP code will work perfectly fine:If you have not tested against this specific condition, such errors might go unnoticed.