Complex classes like Jetpack_Sync_Module_Callables 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_Callables, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
5 | class Jetpack_Sync_Module_Callables extends Jetpack_Sync_Module { |
||
6 | const CALLABLES_CHECKSUM_OPTION_NAME = 'jetpack_callables_sync_checksum'; |
||
7 | const CALLABLES_AWAIT_TRANSIENT_NAME = 'jetpack_sync_callables_await'; |
||
8 | |||
9 | private $callable_whitelist; |
||
10 | |||
11 | public function name() { |
||
14 | |||
15 | public function set_defaults() { |
||
22 | |||
23 | public function init_listeners( $callable ) { |
||
24 | add_action( 'jetpack_sync_callable', $callable, 10, 2 ); |
||
25 | add_action( 'admin_init', array( $this, 'set_plugin_action_links' ), 9999 ); // Should happen very late |
||
26 | |||
27 | // For some options, we should always send the change right away! |
||
28 | $always_send_updates_to_these_options = array( |
||
29 | 'jetpack_active_modules', |
||
30 | 'home', |
||
31 | 'siteurl', |
||
32 | 'jetpack_sync_error_idc' |
||
33 | ); |
||
34 | foreach( $always_send_updates_to_these_options as $option ) { |
||
35 | add_action( "update_option_{$option}", array( $this, 'unlock_sync_callable' ) ); |
||
36 | } |
||
37 | |||
38 | // Provide a hook so that hosts can send changes to certain callables right away. |
||
39 | // Especially useful when a host uses constants to change home and siteurl. |
||
40 | add_action( 'jetpack_sync_unlock_sync_callable', array( $this, 'unlock_sync_callable' ) ); |
||
41 | |||
42 | // get_plugins and wp_version |
||
43 | // gets fired when new code gets installed, updates etc. |
||
44 | add_action( 'upgrader_process_complete', array( $this, 'unlock_plugin_action_link_and_callables' ) ); |
||
45 | add_action( 'update_option_active_plugins', array( $this, 'unlock_plugin_action_link_and_callables' ) ); |
||
46 | } |
||
47 | |||
48 | public function init_full_sync_listeners( $callable ) { |
||
49 | add_action( 'jetpack_full_sync_callables', $callable ); |
||
50 | } |
||
51 | |||
52 | public function init_before_send() { |
||
53 | add_action( 'jetpack_sync_before_send_queue_sync', array( $this, 'maybe_sync_callables' ) ); |
||
54 | |||
55 | // full sync |
||
56 | add_filter( 'jetpack_sync_before_send_jetpack_full_sync_callables', array( $this, 'expand_callables' ) ); |
||
57 | } |
||
58 | |||
59 | public function reset_data() { |
||
60 | delete_option( self::CALLABLES_CHECKSUM_OPTION_NAME ); |
||
61 | delete_transient( self::CALLABLES_AWAIT_TRANSIENT_NAME ); |
||
62 | |||
63 | $url_callables = array( 'home_url', 'site_url', 'main_network_site_url' ); |
||
64 | foreach( $url_callables as $callable ) { |
||
65 | delete_option( Jetpack_Sync_Functions::HTTPS_CHECK_OPTION_PREFIX . $callable ); |
||
66 | } |
||
67 | } |
||
68 | |||
69 | function set_callable_whitelist( $callables ) { |
||
70 | $this->callable_whitelist = $callables; |
||
71 | } |
||
72 | |||
73 | function get_callable_whitelist() { |
||
74 | return $this->callable_whitelist; |
||
75 | } |
||
76 | |||
77 | public function get_all_callables() { |
||
78 | // get_all_callables should run as the master user always. |
||
79 | $current_user_id = get_current_user_id(); |
||
80 | wp_set_current_user( Jetpack_Options::get_option( 'master_user' ) ); |
||
81 | $callables = array_combine( |
||
82 | array_keys( $this->get_callable_whitelist() ), |
||
83 | array_map( array( $this, 'get_callable' ), array_values( $this->get_callable_whitelist() ) ) |
||
84 | ); |
||
85 | wp_set_current_user( $current_user_id ); |
||
86 | return $callables; |
||
87 | } |
||
88 | |||
89 | private function get_callable( $callable ) { |
||
92 | |||
93 | public function enqueue_full_sync_actions( $config, $max_items_to_enqueue, $state ) { |
||
106 | |||
107 | public function estimate_full_sync_actions( $config ) { |
||
110 | |||
111 | public function get_full_sync_actions() { |
||
114 | |||
115 | public function unlock_sync_callable() { |
||
118 | |||
119 | public function unlock_plugin_action_link_and_callables() { |
||
123 | |||
124 | public function set_plugin_action_links() { |
||
125 | if ( ! class_exists( 'DOMDocument' ) ) { |
||
126 | return; |
||
127 | } |
||
128 | |||
129 | // Is the transient lock in place? |
||
130 | $plugins_lock = get_transient( 'jetpack_plugin_api_action_links_refresh', false ); |
||
172 | |||
173 | public function should_send_callable( $callable_checksums, $name, $checksum ) { |
||
185 | |||
186 | public function maybe_sync_callables() { |
||
226 | |||
227 | public function expand_callables( $args ) { |
||
240 | } |
||
241 |
Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.
Let’s take a look at an example:
As you can see in this example, the array
$myArray
is initialized the first time when the foreach loop is entered. You can also see that the value of thebar
key is only written conditionally; thus, its value might result from a previous iteration.This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.