Completed
Push — add/sync-action ( 5f576a...56b581 )
by
unknown
18:38 queued 09:42
created

Jetpack_Sync_Client   D

Complexity

Total Complexity 105

Size/Duplication

Total Lines 587
Duplicated Lines 6.47 %

Coupling/Cohesion

Components 3
Dependencies 7

Importance

Changes 6
Bugs 0 Features 5
Metric Value
c 6
b 0
f 5
dl 38
loc 587
rs 4.8717
wmc 105
lcom 3
cbo 7

49 Methods

Rating   Name   Duplication   Size   Complexity  
A getInstance() 0 7 2
A __construct() 0 4 1
B init() 0 127 6
A set_options_whitelist() 0 3 1
A set_constants_whitelist() 0 3 1
A get_callable_whitelist() 0 3 1
A set_callable_whitelist() 0 3 1
A set_network_options_whitelist() 0 3 1
A set_send_buffer_size() 0 6 2
A set_taxonomy_whitelist() 0 3 1
A is_whitelisted_option() 0 3 1
A is_whitelisted_network_option() 0 3 2
A set_codec() 0 3 1
A set_full_sync_client() 0 12 2
A get_full_sync_client() 0 3 1
C action_handler() 0 42 12
A send_theme_info() 0 14 3
A send_wp_version() 0 6 3
A save_term_handler() 0 9 2
A send_attachment_info() 0 4 1
A save_user_handler() 0 18 4
A save_user_role_handler() 0 4 1
A save_user_cap_handler() 0 6 2
A sanitize_user() 0 4 1
C do_sync() 0 72 12
A filter_items_before_send() 0 6 1
A buffer_includes_action() 0 9 3
A expand_wp_insert_post() 0 4 1
A expand_transition_post_status() 0 3 1
A filter_post_content() 0 7 2
A schedule_sync() 0 3 1
A force_sync_constants() 0 4 1
A force_sync_options() 0 3 1
A force_sync_network_options() 0 3 1
A maybe_sync_constants() 11 11 3
A get_all_constants() 0 6 1
A get_constant() 0 7 2
A force_sync_callables() 0 4 1
A maybe_sync_callables() 11 11 3
A get_all_callables() 0 6 1
A get_callable() 0 3 1
A get_all_options() 0 7 2
A get_all_network_options() 0 7 2
A get_check_sum() 0 3 1
B jetpack_sync_core_icon() 16 16 6
A get_sync_queue() 0 3 1
A reset_sync_queue() 0 3 1
A set_defaults() 0 18 2
A reset_data() 0 4 1

How to fix   Duplicated Code    Complexity   

Duplicated Code

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 Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like Jetpack_Sync_Client 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_Client, and based on these observations, apply Extract Interface, too.

1
<?php
2
require_once dirname( __FILE__ ) . '/class.jetpack-sync-deflate-codec.php';
3
require_once dirname( __FILE__ ) . '/class.jetpack-sync-queue.php';
4
require_once dirname( __FILE__ ) . '/class.jetpack-sync-functions.php';
5
require_once dirname( __FILE__ ) . '/class.jetpack-sync-full.php';
6
require_once dirname( __FILE__ ) . '/class.jetpack-sync-defaults.php';
7
8
class Jetpack_Sync_Client {
9
	
10
	static $constants_checksum_option_name = 'jetpack_constants_sync_checksum';
0 ignored issues
show
Coding Style introduced by
The visibility should be declared for property $constants_checksum_option_name.

The PSR-2 coding standard requires that all properties in a class have their visibility explicitly declared. If you declare a property using

class A {
    var $property;
}

the property is implicitly global.

To learn more about the PSR-2, please see the PHP-FIG site on the PSR-2.

Loading history...
11
	static $functions_checksum_option_name = 'jetpack_functions_sync_checksum';
0 ignored issues
show
Coding Style introduced by
The visibility should be declared for property $functions_checksum_option_name.

The PSR-2 coding standard requires that all properties in a class have their visibility explicitly declared. If you declare a property using

class A {
    var $property;
}

the property is implicitly global.

To learn more about the PSR-2, please see the PHP-FIG site on the PSR-2.

Loading history...
12
13
	private $sync_queue;
14
	private $full_sync_client;
15
	private $codec;
16
	private $options_whitelist;
17
	private $constants_whitelist;
18
	private $meta_types = array( 'post', 'comment' );
19
	private $callable_whitelist;
20
	private $network_options_whitelist;
21
	private $taxonomy_whitelist;
22
23
	// singleton functions
24
	private static $instance;
25
26
	public static function getInstance() {
27
		if ( null === self::$instance ) {
28
			self::$instance = new self();
29
		}
30
31
		return self::$instance;
32
	}
33
34
	// this is necessary because you can't use "new" when you declare instance properties >:(
35
	protected function __construct() {
36
		$this->set_defaults();
37
		$this->init();
38
	}
39
40
	private function init() {
41
42
		$handler = array( $this, 'action_handler' );
43
44
		/**
45
		 * Most of the following hooks are sent to the same $handler 
46
		 * for immediate serialization and queuing be sent to the server.
47
		 * The only exceptions are actions which need additional processing.
48
		 */
49
50
		// constants
51
		add_action( 'jetpack_sync_current_constants', $handler, 10 );
52
53
		// functions
54
		add_action( 'jetpack_sync_current_callables', $handler, 10 );
55
56
		// posts
57
		add_action( 'wp_insert_post', $handler, 10, 3 );
58
		add_action( 'deleted_post', $handler, 10 );
59
		add_filter( 'jetpack_sync_before_send_wp_insert_post', array( $this, 'expand_wp_insert_post' ) );
60
		add_action( 'transition_post_status', $handler, 10, 3 ); // $new_status, $old_status, $post)
61
		add_filter( 'jetpack_sync_before_send_transition_post_status', array( $this, 'expand_transition_post_status' ) );
62
63
		// attachments
64
65
		add_action( 'edit_attachment', array( $this, 'send_attachment_info' ) );
66
		// Once we don't have to support 4.3 we can start using add_action( 'attachment_updated', $handler, 10, 3 ); instead
67
		add_action( 'add_attachment', array( $this, 'send_attachment_info' ) );
68
		add_action( 'jetpack_sync_save_add_attachment', $handler, 10, 2 );
69
70
		// comments
71
		add_action( 'wp_insert_comment', $handler, 10, 2 );
72
		add_action( 'deleted_comment', $handler, 10 );
73
		add_action( 'trashed_comment', $handler, 10 );
74
		add_action( 'spammed_comment', $handler, 10 );
75
76
		// even though it's messy, we implement these hooks because 
77
		// the edit_comment hook doesn't include the data
78
		// so this saves us a DB read for every comment event
79
		foreach ( array( '', 'trackback', 'pingback' ) as $comment_type ) {
80
			foreach ( array( 'unapproved', 'approved' ) as $comment_status ) {
81
				add_action( "comment_{$comment_status}_{$comment_type}", $handler, 10, 2 );
82
			}
83
		}
84
85
		// options
86
		add_action( 'added_option', $handler, 10, 2 );
87
		add_action( 'updated_option', $handler, 10, 3 );
88
		add_action( 'deleted_option', $handler, 10, 1 );
89
90
		// Sync Core Icon: Detect changes in Core's Site Icon and make it syncable.
91
		add_action( 'add_option_site_icon', array( $this, 'jetpack_sync_core_icon' ) );
92
		add_action( 'update_option_site_icon', array( $this, 'jetpack_sync_core_icon' ) );
93
		add_action( 'delete_option_site_icon', array( $this, 'jetpack_sync_core_icon' ) );
94
95
		// wordpress version
96
		add_action( 'upgrader_process_complete', array( $this, 'send_wp_version' ), 10, 2 );
97
		add_action( 'jetpack_sync_wp_version', $handler );
98
99
		// themes
100
		add_action( 'switch_theme', array( $this, 'send_theme_info' ) );
101
		add_action( 'jetpack_sync_current_theme_support', $handler, 10 ); // custom hook, see meta-hooks below
102
103
		// post-meta, and in the future - other meta?
104
		foreach ( $this->meta_types as $meta_type ) {
105
			add_action( "added_{$meta_type}_meta", $handler, 10, 4 );
106
			add_action( "updated_{$meta_type}_meta", $handler, 10, 4 );
107
			add_action( "deleted_{$meta_type}_meta", $handler, 10, 4 );
108
		}
109
110
		// terms
111
		add_action( 'created_term', array( $this, 'save_term_handler' ), 10, 3 );
112
		add_action( 'edited_term', array( $this, 'save_term_handler' ), 10, 3 );
113
		add_action( 'jetpack_sync_save_term', $handler, 10, 4 );
114
		add_action( 'delete_term', $handler, 10, 4 );
115
		add_action( 'set_object_terms', $handler, 10, 5 );
116
		add_action( 'deleted_term_relationships', $handler, 10 , 2 );
117
118
		// users
119
		add_action( 'user_register', array( $this, 'save_user_handler' ) );
120
		add_action( 'profile_update', array( $this, 'save_user_handler' ), 10, 2 );
121
		add_action( 'jetpack_sync_save_user', $handler, 10, 2 );
122
		add_action( 'deleted_user', $handler, 10, 2 );
123
124
		// user roles
125
		add_action( 'add_user_role', array( $this,'save_user_role_handler' ), 10, 2 );
126
		add_action( 'set_user_role', array( $this,'save_user_role_handler' ), 10, 3 );
127
		add_action( 'remove_user_role', array( $this,'save_user_role_handler' ), 10, 2 );
128
129
130
		// user capabilities
131
		add_action( 'added_user_meta', array( $this, 'save_user_cap_handler' ), 10, 4 );
132
		add_action( 'updated_user_meta', array( $this, 'save_user_cap_handler' ), 10, 4 );
133
		add_action( 'deleted_user_meta', array( $this, 'save_user_cap_handler' ), 10, 4 );
134
135
		// themes
136
		add_action( 'set_site_transient_update_plugins', $handler, 10, 1 );
137
		add_action( 'set_site_transient_update_themes', $handler, 10, 1 );
138
		add_action( 'set_site_transient_update_core', $handler, 10, 1 );
139
140
		// multi site network options
141
		if ( $this->is_multisite ) {
0 ignored issues
show
Bug introduced by
The property is_multisite does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
142
			add_action( 'add_site_option', $handler, 10, 2 );
143
			add_action( 'update_site_option', $handler, 10, 3 );
144
			add_action( 'delete_site_option', $handler, 10, 1 );
145
		}
146
147
		// synthetic actions for full sync
148
		add_action( 'jetpack_full_sync_start', $handler );
149
		add_action( 'jetpack_full_sync_end', $handler );
150
		add_action( 'jetpack_full_sync_options', $handler );
151
		add_action( 'jetpack_full_sync_posts', $handler ); // also sends post meta
152
		add_action( 'jetpack_full_sync_comments', $handler ); // also send comments meta
153
		add_action( 'jetpack_full_sync_users', $handler );
154
		add_action( 'jetpack_full_sync_terms', $handler, 10, 2 );
155
		if ( is_multisite() ) {
156
			add_action( 'jetpack_full_sync_network_options', $handler );
157
		}
158
159
160
		// TODO: Callables, Constanst, Network Options, Users, Terms
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
161
162
		/**
163
		 * Sync all pending actions with server
164
		 */
165
		add_action( 'jetpack_sync_actions', array( $this, 'do_sync' ) );
166
	}
167
168
	// TODO: Refactor to use one set whitelist function, with one is_whitelisted.
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
169
	function set_options_whitelist( $options ) {
170
		$this->options_whitelist = $options;
171
	}
172
173
	function set_constants_whitelist( $constants ) {
174
		$this->constants_whitelist = $constants;
175
	}
176
177
	function get_callable_whitelist( $functions ) {
0 ignored issues
show
Unused Code introduced by
The parameter $functions is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
178
		return $this->callable_whitelist;
179
	}
180
181
	function set_callable_whitelist( $functions ) {
182
		$this->callable_whitelist = $functions;
183
	}
184
185
	function set_network_options_whitelist( $options ) {
186
		$this->network_options_whitelist = $options;
187
	}
188
189
	function set_send_buffer_size( $size, $memory_limit = null ) {
190
		$this->sync_queue->set_checkout_size( $size );
191
		if ( $memory_limit ) {
192
			$this->sync_queue->set_memory_limit(  $memory_limit );
193
		}
194
	}
195
196
	function set_taxonomy_whitelist( $taxonomies ) {
197
		$this->taxonomy_whitelist = $taxonomies;
198
	}
199
200
	function is_whitelisted_option( $option ) {
201
		return in_array( $option, $this->options_whitelist );
202
	}
203
204
	function is_whitelisted_network_option( $option ) {
205
		return $this->is_multisite && in_array( $option, $this->network_options_whitelist );
206
	}
207
208
	function set_codec( iJetpack_Sync_Codec $codec ) {
209
		$this->codec = $codec;
210
	}
211
212
	function set_full_sync_client( $full_sync_client ) {
213
		if ( $this->full_sync_client ) {
214
			remove_action( 'jetpack_sync_full', array( $this->full_sync_client, 'start' ) );
215
		}
216
217
		$this->full_sync_client = $full_sync_client;
218
219
		/**
220
		 * Sync all objects in the database with the server
221
		 */
222
		add_action( 'jetpack_sync_full', array( $this->full_sync_client, 'start' ) );
223
	}
224
225
	function get_full_sync_client() {
226
		return $this->full_sync_client;
227
	}
228
229
	function action_handler() {
230
		// TODO: it's really silly to have this function here - it should be
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
231
		// wherever we initialize the action listeners or we're just wasting cycles
232
		if ( Jetpack::is_development_mode() || Jetpack::is_staging_site() ) {
233
			return false;
234
		}
235
236
		$current_filter = current_filter();
237
		$args           = func_get_args();
238
239
		if ( $current_filter === 'wp_insert_post' && $args[1]->post_type === 'revision' ) {
240
			return;
241
		}
242
243
		if ( in_array( $current_filter, array( 'deleted_option', 'added_option', 'updated_option' ) )
244
		     &&
245
		     ! $this->is_whitelisted_option( $args[0] )
246
		) {
247
			return;
248
		}
249
250
		if ( in_array( $current_filter, array( 'delete_site_option', 'add_site_option', 'update_site_option' ) )
251
		     &&
252
		     ! $this->is_whitelisted_network_option( $args[0] )
253
		) {
254
			return;
255
		}
256
257
		// don't sync private meta
258
		if ( preg_match( '/^(added|updated|deleted)_.*_meta$/', $current_filter )
259
		     && $args[2][0] === '_'
260
		     && ! in_array( $args[2], Jetpack_Sync_Defaults::$default_whitelist_meta_keys ) ) {
0 ignored issues
show
Bug introduced by
The property default_whitelist_meta_keys cannot be accessed from this context as it is declared private in class Jetpack_Sync_Defaults.

This check looks for access to properties that are not accessible from the current context.

If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.

Loading history...
261
			return;
262
		}
263
264
		$this->sync_queue->add( array(
265
			$current_filter,
266
			$args,
267
			get_current_user_id(),
268
			microtime(true)
269
		) );
270
	}
271
272
	function send_theme_info() {
273
		global $_wp_theme_features;
274
275
		$theme_support = array();
276
277
		foreach( Jetpack_Sync_Defaults::$default_theme_support_whitelist as $theme_feature ) {
0 ignored issues
show
Bug introduced by
The property default_theme_support_whitelist cannot be accessed from this context as it is declared private in class Jetpack_Sync_Defaults.

This check looks for access to properties that are not accessible from the current context.

If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.

Loading history...
278
			$has_support = current_theme_supports( $theme_feature );
279
			if ( $has_support ) {
280
				$theme_support[ $theme_feature ] = $_wp_theme_features[ $theme_feature ];
281
			}
282
283
		}
284
		do_action( 'jetpack_sync_current_theme_support', $theme_support );
285
	}
286
287
	function send_wp_version( $update, $meta_data ) {
288
		if ( 'update' === $meta_data['action'] && 'core' === $meta_data['type'] ) {
289
			global $wp_version;
290
			do_action( 'jetpack_sync_wp_version', $wp_version );
291
		}
292
	}
293
294
	function save_term_handler( $term_id, $tt_id, $taxonomy ) {
295
		if ( class_exists('WP_Term') ) {
296
			$term_object = WP_Term::get_instance( $term_id, $taxonomy );
297
		} else {
298
			$term_object = get_term_by( 'id', $term_id, $taxonomy );
299
		}
300
301
		do_action( 'jetpack_sync_save_term', $term_object );
302
	}
303
304
	function send_attachment_info( $attachment_id ) {
305
		$attachment = get_post( $attachment_id );
306
		do_action( 'jetpack_sync_save_add_attachment', $attachment_id, $attachment );
307
	}
308
309
	function save_user_handler( $user_id, $old_user_data = null ) {
310
		$user = $this->sanitize_user( get_user_by( 'id', $user_id ) );
311
312
		// Older versions of WP don't pass the old_user_data in ->data
313
		if ( isset( $old_user_data->data ) ) {
314
			$old_user = $old_user_data->data;
315
		} else {
316
			$old_user = $old_user_data;
317
		}
318
319
		if ( $old_user !== null ) {
320
			unset( $old_user->user_pass );
321
			if ( serialize( $old_user ) === serialize( $user->data ) ) {
322
				return;
323
			}
324
		}
325
		do_action( 'jetpack_sync_save_user', $user );
326
	}
327
328
	function save_user_role_handler( $user_id, $role, $old_roles = null ) {
0 ignored issues
show
Unused Code introduced by
The parameter $role is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $old_roles is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
329
		$user = $this->sanitize_user( get_user_by( 'id', $user_id ) );
330
		do_action( 'jetpack_sync_save_user', $user );
331
	}
332
333
	function save_user_cap_handler( $meta_id, $user_id, $meta_key, $capabilities ) {
0 ignored issues
show
Unused Code introduced by
The parameter $capabilities is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
334
		$user = $this->sanitize_user( get_user_by( 'id', $user_id ) );
335
		if ( $meta_key === $user->cap_key ) {
336
			do_action( 'jetpack_sync_save_user', $user );
337
		}
338
	}
339
340
	public function sanitize_user( $user ) {
341
		unset( $user->data->user_pass );
342
		return $user;
343
	}
344
345
346
	function do_sync() {
347
		if ( defined( 'WP_IMPORTING' ) && WP_IMPORTING ) {
348
			$this->schedule_sync( "+1 minute" );
349
			return false;
350
		}
351
352
		$this->maybe_sync_constants();
353
		$this->maybe_sync_callables();
354
355
		if ( $this->sync_queue->size() === 0 ) {
356
			return false;
357
		}
358
359
		$buffer = $this->sync_queue->checkout();
360
361
		if ( ! $buffer ) {
362
			// buffer has no items
363
			return;
364
		}
365
366
		if ( is_wp_error( $buffer ) ) {
367
			// another buffer is currently sending
368
			return;
369
		}
370
371
		$items = array_map( array( $this, 'filter_items_before_send' ), $buffer->get_items() );
372
373
		$data = $this->codec->encode( $items );
374
375
		/**
376
		 * Fires when data is ready to send to the server.
377
		 * Return false or WP_Error to abort the sync (e.g. if there's an error)
378
		 * The items will be automatically re-sent later
379
		 *
380
		 * @since 4.1
381
		 *
382
		 * @param array $data The action buffer
383
		 */
384
		$result = apply_filters( 'jetpack_sync_client_send_data', $data );
385
386
		if ( ! $result || is_wp_error( $result ) ) {
387
			// error_log("There was an error sending data:");
388
			// error_log(print_r($result, 1));
389
			$result = $this->sync_queue->checkin( $buffer );
390
391
			if ( is_wp_error( $result ) ) {
392
				error_log("Error checking in buffer: ".$result->get_error_message());
393
				$this->sync_queue->force_checkin();
394
			}
395
			// try again in 1 minute
396
			$this->schedule_sync( "+1 minute" );
397
		} else {
398
399
			// scan the sent data to see if a full sync started or finished
400
			if ( $this->buffer_includes_action( $buffer, 'jetpack_full_sync_start' ) ) {
401
				do_action( 'jetpack_full_sync_start_sent' );
402
				$this->full_sync_client->set_status_sending_started();
403
			}
404
405
			if ( $this->buffer_includes_action( $buffer, 'jetpack_full_sync_end' ) ) {
406
				do_action( 'jetpack_full_sync_end_sent' );
407
				$this->full_sync_client->set_status_sending_finished();
408
			}
409
410
			$this->sync_queue->close( $buffer );
411
			// check if there are any more events in the buffer
412
			// if so, schedule a cron job to happen soon
413
			if ( $this->sync_queue->has_any_items() ) {
414
				$this->schedule_sync( "+1 minute" );
415
			}
416
		}
417
	}
418
419
	private function filter_items_before_send( $item ) {
420
		$current_filter = $item[0];
421
		$item[1]        = apply_filters( "jetpack_sync_before_send_$current_filter", $item[1] );
422
423
		return $item;
424
	}
425
426
	private function buffer_includes_action( $buffer, $action_name ) {
427
		foreach ( $buffer->get_items() as $item ) {
428
			if ( $item[0] === $action_name ) {
429
				return true;
430
			}
431
		}
432
433
		return false;
434
	}
435
	
436
	function expand_wp_insert_post( $args ) {
437
		// list( $post_ID, $post, $update ) = $args;
438
		return array( $args[0], $this->filter_post_content( $args[1] ), $args[2] );
439
	}
440
441
	function expand_transition_post_status( $args ) {
442
		return array( $args[0], $args[1], $this->filter_post_content( $args[2] ) );
443
	}
444
	// Expands wp_insert_post to include filteredpl
445
	function filter_post_content( $post ) {
446
		if ( 0 < strlen( $post->post_password ) ) {
447
			$post->post_password = 'auto-' . wp_generate_password( 10, false );
448
		}
449
		$post->post_content_filtered = apply_filters( 'the_content', $post->post_content );
450
		return $post;
451
	}
452
453
	private function schedule_sync( $when ) {
454
		wp_schedule_single_event( strtotime( $when ), 'jetpack_sync_actions' );
455
	}
456
457
	function force_sync_constants() {
458
		delete_option( self::$constants_checksum_option_name );
459
		$this->maybe_sync_constants();
460
	}
461
462
	function force_sync_options() {
463
		do_action( 'jetpack_full_sync_options', true );
464
	}
465
466
	function force_sync_network_options() {
467
		do_action( 'jetpack_full_sync_network_options', true );
468
	}
469
470 View Code Duplication
	private function maybe_sync_constants() {
471
		$constants = $this->get_all_constants();
472
		if ( empty( $constants ) ) {
473
			return;
474
		}
475
		$constants_check_sum = $this->get_check_sum( $constants );
476
		if ( $constants_check_sum !== (int) get_option( self::$constants_checksum_option_name ) ) {
477
			do_action( 'jetpack_sync_current_constants', $constants );
478
			update_option( self::$constants_checksum_option_name, $constants_check_sum );
479
		}
480
	}
481
482
	private function get_all_constants() {
483
		return array_combine(
484
			$this->constants_whitelist,
485
			array_map( array( $this, 'get_constant' ), $this->constants_whitelist )
486
		);
487
	}
488
489
	private function get_constant( $constant ) {
490
		if ( defined( $constant ) ) {
491
			return constant( $constant );
492
		}
493
494
		return null;
495
	}
496
497
	public function force_sync_callables() {
498
		delete_option( self::$functions_checksum_option_name );
499
		$this->maybe_sync_callables();
500
	}
501
502 View Code Duplication
	private function maybe_sync_callables() {
503
		$callables = $this->get_all_callables();
504
		if ( empty( $callables ) ) {
505
			return;
506
		}
507
		$callables_check_sum = $this->get_check_sum( $callables );
508
		if ( $callables_check_sum !== (int) get_option( self::$functions_checksum_option_name ) ) {
509
			do_action( 'jetpack_sync_current_callables', $callables );
510
			update_option( self::$functions_checksum_option_name, $callables_check_sum );
511
		}
512
	}
513
514
	private function get_all_callables() {
515
		return array_combine(
516
			array_keys( $this->callable_whitelist ),
517
			array_map( array( $this, 'get_callable' ), array_values( $this->callable_whitelist ) )
518
		);
519
	}
520
521
	private function get_callable( $callable ) {
522
		return call_user_func( $callable );
523
	}
524
525
	// Is public so that we don't have to store so much data all the options twice.
526
	function get_all_options() {
527
		$options = array();
528
		foreach( $this->options_whitelist as $option ) {
529
			$options[ $option ] = get_option( $option );
530
		}
531
		return $options;
532
	}
533
534
	function get_all_network_options() {
535
		$options = array();
536
		foreach( $this->network_options_whitelist as $option ) {
537
			$options[ $option ] = get_site_option( $option );
538
		}
539
		return $options;
540
	}
541
542
	private function get_check_sum( $values ) {
543
		return crc32( serialize( $values ) );
544
	}
545
546 View Code Duplication
	function jetpack_sync_core_icon() {
547
		if ( function_exists( 'get_site_icon_url' ) ) {
548
			$url = get_site_icon_url();
549
		} else {
550
			return;
551
		}
552
553
		require_once( JETPACK__PLUGIN_DIR . 'modules/site-icon/site-icon-functions.php' );
554
		// If there's a core icon, maybe update the option.  If not, fall back to Jetpack's.
555
		if ( ! empty( $url ) && $url !== jetpack_site_icon_url() ) {
556
			// This is the option that is synced with dotcom
557
			Jetpack_Options::update_option( 'site_icon_url', $url );
558
		} else if ( empty( $url ) && did_action( 'delete_option_site_icon' ) ) {
559
			Jetpack_Options::delete_option( 'site_icon_url' );
560
		}
561
	}
562
563
	function get_sync_queue() {
564
		return $this->sync_queue;
565
	}
566
567
	function reset_sync_queue() {
568
		$this->sync_queue->reset();
569
	}
570
571
	function set_defaults() {
572
		$this->sync_queue = new Jetpack_Sync_Queue( 'sync', Jetpack_Sync_Defaults::$default_send_buffer_size );
0 ignored issues
show
Bug introduced by
The property default_send_buffer_size cannot be accessed from this context as it is declared private in class Jetpack_Sync_Defaults.

This check looks for access to properties that are not accessible from the current context.

If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.

Loading history...
573
		$this->set_full_sync_client( Jetpack_Sync_Full::getInstance() );
574
		$this->codec                     = new Jetpack_Sync_Deflate_Codec();
575
		$this->constants_whitelist       = Jetpack_Sync_Defaults::$default_constants_whitelist;
0 ignored issues
show
Bug introduced by
The property default_constants_whitelist cannot be accessed from this context as it is declared private in class Jetpack_Sync_Defaults.

This check looks for access to properties that are not accessible from the current context.

If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.

Loading history...
576
		$this->options_whitelist         = Jetpack_Sync_Defaults::$default_options_whitelist;
0 ignored issues
show
Bug introduced by
The property default_options_whitelist cannot be accessed from this context as it is declared private in class Jetpack_Sync_Defaults.

This check looks for access to properties that are not accessible from the current context.

If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.

Loading history...
577
		$this->network_options_whitelist = Jetpack_Sync_Defaults::$default_network_options_whitelist;
0 ignored issues
show
Bug introduced by
The property default_network_options_whitelist cannot be accessed from this context as it is declared private in class Jetpack_Sync_Defaults.

This check looks for access to properties that are not accessible from the current context.

If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.

Loading history...
578
		$this->taxonomy_whitelist        = Jetpack_Sync_Defaults::$default_taxonomy_whitelist;
0 ignored issues
show
Bug introduced by
The property default_taxonomy_whitelist cannot be accessed from this context as it is declared private in class Jetpack_Sync_Defaults.

This check looks for access to properties that are not accessible from the current context.

If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.

Loading history...
579
		$this->is_multisite              = is_multisite();
580
		
581
		// theme mod varies from theme to theme.
582
		$this->options_whitelist[] =  'theme_mods_' . get_option( 'stylesheet' );
583
		if ( $this->is_multisite ) {
584
			$this->callable_whitelist = array_merge( Jetpack_Sync_Defaults::$default_callable_whitelist, Jetpack_Sync_Defaults::$default_multisite_callable_whitelist );
0 ignored issues
show
Bug introduced by
The property default_callable_whitelist cannot be accessed from this context as it is declared private in class Jetpack_Sync_Defaults.

This check looks for access to properties that are not accessible from the current context.

If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.

Loading history...
Bug introduced by
The property default_multisite_callable_whitelist cannot be accessed from this context as it is declared private in class Jetpack_Sync_Defaults.

This check looks for access to properties that are not accessible from the current context.

If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.

Loading history...
585
		} else {
586
			$this->callable_whitelist = Jetpack_Sync_Defaults::$default_callable_whitelist;
0 ignored issues
show
Bug introduced by
The property default_callable_whitelist cannot be accessed from this context as it is declared private in class Jetpack_Sync_Defaults.

This check looks for access to properties that are not accessible from the current context.

If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.

Loading history...
587
		}
588
	}
589
590
	function reset_data() {
591
		delete_option( self::$constants_checksum_option_name );
592
		$this->reset_sync_queue();
593
	}
594
}
595