Completed
Push — fix/resolve-security-vulnerabi... ( 372367...c122d8 )
by Yaroslav
197:31 queued 189:03
created

packages/sync/src/class-sender.php (1 issue)

Severity

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * Sync sender.
4
 *
5
 * @package automattic/jetpack-sync
6
 */
7
8
namespace Automattic\Jetpack\Sync;
9
10
use Automattic\Jetpack\Connection\Manager;
11
use Automattic\Jetpack\Constants;
12
13
/**
14
 * This class grabs pending actions from the queue and sends them
15
 */
16
class Sender {
17
	/**
18
	 * Name of the option that stores the time of the next sync.
19
	 *
20
	 * @access public
21
	 *
22
	 * @var string
23
	 */
24
	const NEXT_SYNC_TIME_OPTION_NAME = 'jetpack_next_sync_time';
25
26
	/**
27
	 * Sync timeout after a WPCOM error.
28
	 *
29
	 * @access public
30
	 *
31
	 * @var int
32
	 */
33
	const WPCOM_ERROR_SYNC_DELAY = 60;
34
35
	/**
36
	 * Sync timeout after a queue has been locked.
37
	 *
38
	 * @access public
39
	 *
40
	 * @var int
41
	 */
42
	const QUEUE_LOCKED_SYNC_DELAY = 10;
43
44
	/**
45
	 * Maximum bytes to checkout without exceeding the memory limit.
46
	 *
47
	 * @access private
48
	 *
49
	 * @var int
50
	 */
51
	private $dequeue_max_bytes;
52
53
	/**
54
	 * Maximum bytes in a single encoded item.
55
	 *
56
	 * @access private
57
	 *
58
	 * @var int
59
	 */
60
	private $upload_max_bytes;
61
62
	/**
63
	 * Maximum number of sync items in a single action.
64
	 *
65
	 * @access private
66
	 *
67
	 * @var int
68
	 */
69
	private $upload_max_rows;
70
71
	/**
72
	 * Maximum time for perfirming a checkout of items from the queue (in seconds).
73
	 *
74
	 * @access private
75
	 *
76
	 * @var int
77
	 */
78
	private $max_dequeue_time;
79
80
	/**
81
	 * How many seconds to wait after sending sync items after exceeding the sync wait threshold (in seconds).
82
	 *
83
	 * @access private
84
	 *
85
	 * @var int
86
	 */
87
	private $sync_wait_time;
88
89
	/**
90
	 * How much maximum time to wait for the checkout to finish (in seconds).
91
	 *
92
	 * @access private
93
	 *
94
	 * @var int
95
	 */
96
	private $sync_wait_threshold;
97
98
	/**
99
	 * How much maximum time to wait for the sync items to be queued for sending (in seconds).
100
	 *
101
	 * @access private
102
	 *
103
	 * @var int
104
	 */
105
	private $enqueue_wait_time;
106
107
	/**
108
	 * Incremental sync queue object.
109
	 *
110
	 * @access private
111
	 *
112
	 * @var Automattic\Jetpack\Sync\Queue
113
	 */
114
	private $sync_queue;
115
116
	/**
117
	 * Full sync queue object.
118
	 *
119
	 * @access private
120
	 *
121
	 * @var Automattic\Jetpack\Sync\Queue
122
	 */
123
	private $full_sync_queue;
124
125
	/**
126
	 * Codec object for encoding and decoding sync items.
127
	 *
128
	 * @access private
129
	 *
130
	 * @var Automattic\Jetpack\Sync\Codec_Interface
131
	 */
132
	private $codec;
133
134
	/**
135
	 * The current user before we change or clear it.
136
	 *
137
	 * @access private
138
	 *
139
	 * @var \WP_User
140
	 */
141
	private $old_user;
142
143
	/**
144
	 * Container for the singleton instance of this class.
145
	 *
146
	 * @access private
147
	 * @static
148
	 *
149
	 * @var Automattic\Jetpack\Sync\Sender
150
	 */
151
	private static $instance;
152
153
	/**
154
	 * Retrieve the singleton instance of this class.
155
	 *
156
	 * @access public
157
	 * @static
158
	 *
159
	 * @return Sender
160
	 */
161
	public static function get_instance() {
162
		if ( null === self::$instance ) {
163
			self::$instance = new self();
164
		}
165
166
		return self::$instance;
167
	}
168
169
	/**
170
	 * Constructor.
171
	 * This is necessary because you can't use "new" when you declare instance properties >:(
172
	 *
173
	 * @access protected
174
	 * @static
175
	 */
176
	protected function __construct() {
177
		$this->set_defaults();
178
		$this->init();
179
	}
180
181
	/**
182
	 * Initialize the sender.
183
	 * Prepares the current user and initializes all sync modules.
184
	 *
185
	 * @access private
186
	 */
187
	private function init() {
188
		add_action( 'jetpack_sync_before_send_queue_sync', array( $this, 'maybe_set_user_from_token' ), 1 );
189
		add_action( 'jetpack_sync_before_send_queue_sync', array( $this, 'maybe_clear_user_from_token' ), 20 );
190
		add_filter( 'jetpack_xmlrpc_methods', array( $this, 'register_jetpack_xmlrpc_methods' ) );
191
		foreach ( Modules::get_modules() as $module ) {
192
			$module->init_before_send();
193
		}
194
	}
195
196
	/**
197
	 * Detect if this is a XMLRPC request with a valid signature.
198
	 * If so, changes the user to the new one.
199
	 *
200
	 * @access public
201
	 */
202
	public function maybe_set_user_from_token() {
203
		$connection    = new Manager();
204
		$verified_user = $connection->verify_xml_rpc_signature();
205
		if ( Constants::is_true( 'XMLRPC_REQUEST' ) &&
206
			! is_wp_error( $verified_user )
207
			&& $verified_user
208
		) {
209
			$old_user       = wp_get_current_user();
210
			$this->old_user = isset( $old_user->ID ) ? $old_user->ID : 0;
211
			wp_set_current_user( $verified_user['user_id'] );
212
		}
213
	}
214
215
	/**
216
	 * If we used to have a previous current user, revert back to it.
217
	 *
218
	 * @access public
219
	 */
220
	public function maybe_clear_user_from_token() {
221
		if ( isset( $this->old_user ) ) {
222
			wp_set_current_user( $this->old_user );
223
		}
224
	}
225
226
	/**
227
	 * Retrieve the next sync time.
228
	 *
229
	 * @access public
230
	 *
231
	 * @param string $queue_name Name of the queue.
232
	 * @return float Timestamp of the next sync.
233
	 */
234
	public function get_next_sync_time( $queue_name ) {
235
		return (float) get_option( self::NEXT_SYNC_TIME_OPTION_NAME . '_' . $queue_name, 0 );
236
	}
237
238
	/**
239
	 * Set the next sync time.
240
	 *
241
	 * @access public
242
	 *
243
	 * @param int    $time       Timestamp of the next sync.
244
	 * @param string $queue_name Name of the queue.
245
	 * @return boolean True if update was successful, false otherwise.
246
	 */
247
	public function set_next_sync_time( $time, $queue_name ) {
248
		return update_option( self::NEXT_SYNC_TIME_OPTION_NAME . '_' . $queue_name, $time, true );
249
	}
250
251
	/**
252
	 * Trigger a full sync.
253
	 *
254
	 * @access public
255
	 *
256
	 * @return boolean|\WP_Error True if this sync sending was successful, error object otherwise.
257
	 */
258
	public function do_full_sync() {
259
		$sync_module = Modules::get_module( 'full-sync' );
260
		if ( ! $sync_module ) {
261
			return;
262
		}
263
		if ( ! Settings::get_setting( 'full_sync_sender_enabled' ) ) {
264
			return;
265
		}
266
		$this->continue_full_sync_enqueue();
267
		// immediate full sync sends data in continue_full_sync_enqueue.
268
		if ( false === strpos( get_class( $sync_module ), 'Full_Sync_Immediately' ) ) {
269
			return $this->do_sync_and_set_delays( $this->full_sync_queue );
270
		} else {
271
			$status = $sync_module->get_status();
272
			// Sync not started or Sync finished.
273
			if ( false === $status['started'] || ( ! empty( $status['started'] ) && ! empty( $status['finished'] ) ) ) {
274
				return false;
275
			} else {
276
				return true;
277
			}
278
		}
279
	}
280
281
	/**
282
	 * Enqueue the next sync items for sending.
283
	 * Will not be done if the current request is a WP import one.
284
	 * Will be delayed until the next sync time comes.
285
	 *
286
	 * @access private
287
	 */
288
	private function continue_full_sync_enqueue() {
289
		if ( defined( 'WP_IMPORTING' ) && WP_IMPORTING ) {
290
			return false;
291
		}
292
293
		if ( $this->get_next_sync_time( 'full-sync-enqueue' ) > microtime( true ) ) {
294
			return false;
295
		}
296
297
		Modules::get_module( 'full-sync' )->continue_enqueuing();
298
299
		$this->set_next_sync_time( time() + $this->get_enqueue_wait_time(), 'full-sync-enqueue' );
300
	}
301
302
	/**
303
	 * Trigger incremental sync.
304
	 *
305
	 * @access public
306
	 *
307
	 * @return boolean|\WP_Error True if this sync sending was successful, error object otherwise.
308
	 */
309
	public function do_sync() {
310
		return $this->do_sync_and_set_delays( $this->sync_queue );
311
	}
312
313
	/**
314
	 * Trigger sync for a certain sync queue.
315
	 * Responsible for setting next sync time.
316
	 * Will not be delayed if the current request is a WP import one.
317
	 * Will be delayed until the next sync time comes.
318
	 *
319
	 * @access public
320
	 *
321
	 * @param Automattic\Jetpack\Sync\Queue $queue Queue object.
322
	 * @return boolean|\WP_Error True if this sync sending was successful, error object otherwise.
323
	 */
324
	public function do_sync_and_set_delays( $queue ) {
325
		// Don't sync if importing.
326
		if ( defined( 'WP_IMPORTING' ) && WP_IMPORTING ) {
327
			return new \WP_Error( 'is_importing' );
328
		}
329
330
		// Don't sync if request is marked as read only.
331
		if ( Constants::is_true( 'JETPACK_SYNC_READ_ONLY' ) ) {
332
			return new \WP_Error( 'jetpack_sync_read_only' );
0 ignored issues
show
The call to WP_Error::__construct() has too many arguments starting with 'jetpack_sync_read_only'.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
333
		}
334
335
		if ( ! Settings::is_sender_enabled( $queue->id ) ) {
336
			return new \WP_Error( 'sender_disabled_for_queue_' . $queue->id );
337
		}
338
339
		// Don't sync if we are throttled.
340
		if ( $this->get_next_sync_time( $queue->id ) > microtime( true ) ) {
341
			return new \WP_Error( 'sync_throttled' );
342
		}
343
344
		$start_time = microtime( true );
345
346
		Settings::set_is_syncing( true );
347
348
		$sync_result = $this->do_sync_for_queue( $queue );
349
350
		Settings::set_is_syncing( false );
351
352
		$exceeded_sync_wait_threshold = ( microtime( true ) - $start_time ) > (float) $this->get_sync_wait_threshold();
353
354
		if ( is_wp_error( $sync_result ) ) {
355
			if ( 'unclosed_buffer' === $sync_result->get_error_code() ) {
356
				$this->set_next_sync_time( time() + self::QUEUE_LOCKED_SYNC_DELAY, $queue->id );
357
			}
358
			if ( 'wpcom_error' === $sync_result->get_error_code() ) {
359
				$this->set_next_sync_time( time() + self::WPCOM_ERROR_SYNC_DELAY, $queue->id );
360
			}
361
		} elseif ( $exceeded_sync_wait_threshold ) {
362
			// If we actually sent data and it took a while, wait before sending again.
363
			$this->set_next_sync_time( time() + $this->get_sync_wait_time(), $queue->id );
364
		}
365
366
		return $sync_result;
367
	}
368
369
	/**
370
	 * Retrieve the next sync items to send.
371
	 *
372
	 * @access public
373
	 *
374
	 * @param (array|Automattic\Jetpack\Sync\Queue_Buffer) $buffer_or_items Queue buffer or array of objects.
375
	 * @param boolean                                      $encode Whether to encode the items.
376
	 * @return array Sync items to send.
377
	 */
378
	public function get_items_to_send( $buffer_or_items, $encode = true ) {
379
		// Track how long we've been processing so we can avoid request timeouts.
380
		$start_time    = microtime( true );
381
		$upload_size   = 0;
382
		$items_to_send = array();
383
		$items         = is_array( $buffer_or_items ) ? $buffer_or_items : $buffer_or_items->get_items();
384
		// Set up current screen to avoid errors rendering content.
385
		require_once ABSPATH . 'wp-admin/includes/class-wp-screen.php';
386
		require_once ABSPATH . 'wp-admin/includes/screen.php';
387
		set_current_screen( 'sync' );
388
		$skipped_items_ids = array();
389
		/**
390
		 * We estimate the total encoded size as we go by encoding each item individually.
391
		 * This is expensive, but the only way to really know :/
392
		 */
393
		foreach ( $items as $key => $item ) {
394
			// Suspending cache addition help prevent overloading in memory cache of large sites.
395
			wp_suspend_cache_addition( true );
396
			/**
397
			 * Modify the data within an action before it is serialized and sent to the server
398
			 * For example, during full sync this expands Post ID's into full Post objects,
399
			 * so that we don't have to serialize the whole object into the queue.
400
			 *
401
			 * @since 4.2.0
402
			 *
403
			 * @param array The action parameters
404
			 * @param int The ID of the user who triggered the action
405
			 */
406
			$item[1] = apply_filters( 'jetpack_sync_before_send_' . $item[0], $item[1], $item[2] );
407
			wp_suspend_cache_addition( false );
408
			if ( false === $item[1] ) {
409
				$skipped_items_ids[] = $key;
410
				continue;
411
			}
412
			$encoded_item = $encode ? $this->codec->encode( $item ) : $item;
413
			$upload_size += strlen( $encoded_item );
414
			if ( $upload_size > $this->upload_max_bytes && count( $items_to_send ) > 0 ) {
415
				break;
416
			}
417
			$items_to_send[ $key ] = $encoded_item;
418
			if ( microtime( true ) - $start_time > $this->max_dequeue_time ) {
419
				break;
420
			}
421
		}
422
423
		return array( $items_to_send, $skipped_items_ids, $items, microtime( true ) - $start_time );
424
	}
425
426
	/**
427
	 * If supported, flush all response data to the client and finish the request.
428
	 * This allows for time consuming tasks to be performed without leaving the connection open.
429
	 *
430
	 * @access private
431
	 */
432
	private function fastcgi_finish_request() {
433
		if ( function_exists( 'fastcgi_finish_request' ) && version_compare( phpversion(), '7.0.16', '>=' ) ) {
434
			fastcgi_finish_request();
435
		}
436
	}
437
438
	/**
439
	 * Perform sync for a certain sync queue.
440
	 *
441
	 * @access public
442
	 *
443
	 * @param Automattic\Jetpack\Sync\Queue $queue Queue object.
444
	 * @return boolean|\WP_Error True if this sync sending was successful, error object otherwise.
445
	 */
446
	public function do_sync_for_queue( $queue ) {
447
		do_action( 'jetpack_sync_before_send_queue_' . $queue->id );
448
		if ( $queue->size() === 0 ) {
449
			return new \WP_Error( 'empty_queue_' . $queue->id );
450
		}
451
452
		/**
453
		 * Now that we're sure we are about to sync, try to ignore user abort
454
		 * so we can avoid getting into a bad state.
455
		 */
456
		if ( function_exists( 'ignore_user_abort' ) ) {
457
			ignore_user_abort( true );
458
		}
459
460
		/* Don't make the request block till we finish, if possible. */
461
		if ( Constants::is_true( 'REST_REQUEST' ) || Constants::is_true( 'XMLRPC_REQUEST' ) ) {
462
			$this->fastcgi_finish_request();
463
		}
464
465
		$checkout_start_time = microtime( true );
466
467
		$buffer = $queue->checkout_with_memory_limit( $this->dequeue_max_bytes, $this->upload_max_rows );
468
469
		if ( ! $buffer ) {
470
			// Buffer has no items.
471
			return new \WP_Error( 'empty_buffer' );
472
		}
473
474
		if ( is_wp_error( $buffer ) ) {
475
			return $buffer;
476
		}
477
478
		$checkout_duration = microtime( true ) - $checkout_start_time;
479
480
		list( $items_to_send, $skipped_items_ids, $items, $preprocess_duration ) = $this->get_items_to_send( $buffer, true );
481
		if ( ! empty( $items_to_send ) ) {
482
			/**
483
			 * Fires when data is ready to send to the server.
484
			 * Return false or WP_Error to abort the sync (e.g. if there's an error)
485
			 * The items will be automatically re-sent later
486
			 *
487
			 * @since 4.2.0
488
			 *
489
			 * @param array  $data The action buffer
490
			 * @param string $codec The codec name used to encode the data
491
			 * @param double $time The current time
492
			 * @param string $queue The queue used to send ('sync' or 'full_sync')
493
			 * @param float  $checkout_duration The duration of the checkout operation.
494
			 * @param float  $preprocess_duration The duration of the pre-process operation.
495
			 * @param int    $queue_size The size of the sync queue at the time of processing.
496
			 */
497
			Settings::set_is_sending( true );
498
			$processed_item_ids = apply_filters( 'jetpack_sync_send_data', $items_to_send, $this->codec->name(), microtime( true ), $queue->id, $checkout_duration, $preprocess_duration, $queue->size(), $buffer->id );
499
			Settings::set_is_sending( false );
500
		} else {
501
			$processed_item_ids = $skipped_items_ids;
502
			$skipped_items_ids  = array();
503
		}
504
505
		if ( 'non-blocking' !== $processed_item_ids ) {
506
			if ( ! $processed_item_ids || is_wp_error( $processed_item_ids ) ) {
507
				$checked_in_item_ids = $queue->checkin( $buffer );
508
				if ( is_wp_error( $checked_in_item_ids ) ) {
509
					// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
510
					error_log( 'Error checking in buffer: ' . $checked_in_item_ids->get_error_message() );
511
					$queue->force_checkin();
512
				}
513
				if ( is_wp_error( $processed_item_ids ) ) {
514
					return new \WP_Error( 'wpcom_error', $processed_item_ids->get_error_code() );
515
				}
516
517
				// Returning a wpcom_error is a sign to the caller that we should wait a while before syncing again.
518
				return new \WP_Error( 'wpcom_error', 'jetpack_sync_send_data_false' );
519
			} else {
520
				// Detect if the last item ID was an error.
521
				$had_wp_error = is_wp_error( end( $processed_item_ids ) );
522
				if ( $had_wp_error ) {
523
					$wp_error = array_pop( $processed_item_ids );
524
				}
525
				// Also checkin any items that were skipped.
526
				if ( count( $skipped_items_ids ) > 0 ) {
527
					$processed_item_ids = array_merge( $processed_item_ids, $skipped_items_ids );
528
				}
529
				$processed_items = array_intersect_key( $items, array_flip( $processed_item_ids ) );
530
				/**
531
				 * Allows us to keep track of all the actions that have been sent.
532
				 * Allows us to calculate the progress of specific actions.
533
				 *
534
				 * @since 4.2.0
535
				 *
536
				 * @param array $processed_actions The actions that we send successfully.
537
				 */
538
				do_action( 'jetpack_sync_processed_actions', $processed_items );
539
				$queue->close( $buffer, $processed_item_ids );
540
				// Returning a WP_Error is a sign to the caller that we should wait a while before syncing again.
541
				if ( $had_wp_error ) {
542
					return new \WP_Error( 'wpcom_error', $wp_error->get_error_code() );
543
				}
544
			}
545
		}
546
547
		return true;
548
	}
549
550
	/**
551
	 * Immediately sends a single item without firing or enqueuing it
552
	 *
553
	 * @param string $action_name The action.
554
	 * @param array  $data The data associated with the action.
555
	 *
556
	 * @return Items processed. TODO: this doesn't make much sense anymore, it should probably be just a bool.
557
	 */
558
	public function send_action( $action_name, $data = null ) {
559
		if ( ! Settings::is_sender_enabled( 'full_sync' ) ) {
560
			return array();
561
		}
562
563
		// Compose the data to be sent.
564
		$action_to_send = $this->create_action_to_send( $action_name, $data );
565
566
		list( $items_to_send, $skipped_items_ids, $items, $preprocess_duration ) = $this->get_items_to_send( $action_to_send, true ); // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
567
		Settings::set_is_sending( true );
568
		$processed_item_ids = apply_filters( 'jetpack_sync_send_data', $items_to_send, $this->get_codec()->name(), microtime( true ), 'immediate-send', 0, $preprocess_duration );
569
		Settings::set_is_sending( false );
570
571
		/**
572
		 * Allows us to keep track of all the actions that have been sent.
573
		 * Allows us to calculate the progress of specific actions.
574
		 *
575
		 * @param array $processed_actions The actions that we send successfully.
576
		 *
577
		 * @since 4.2.0
578
		 */
579
		do_action( 'jetpack_sync_processed_actions', $action_to_send );
580
581
		return $processed_item_ids;
582
	}
583
584
	/**
585
	 * Create an synthetic action for direct sending to WPCOM during full sync (for example)
586
	 *
587
	 * @access private
588
	 *
589
	 * @param string $action_name The action.
590
	 * @param array  $data The data associated with the action.
591
	 * @return array An array of synthetic sync actions keyed by current microtime(true)
592
	 */
593
	private function create_action_to_send( $action_name, $data ) {
594
		return array(
595
			(string) microtime( true ) => array(
596
				$action_name,
597
				$data,
598
				get_current_user_id(),
599
				microtime( true ),
600
				Settings::is_importing(),
601
			),
602
		);
603
	}
604
605
	/**
606
	 * Returns any object that is able to be synced.
607
	 *
608
	 * @access public
609
	 *
610
	 * @param array $args the synchronized object parameters.
611
	 * @return string Encoded sync object.
612
	 */
613
	public function sync_object( $args ) {
614
		// For example: posts, post, 5.
615
		list( $module_name, $object_type, $id ) = $args;
616
617
		$sync_module = Modules::get_module( $module_name );
618
		$codec       = $this->get_codec();
619
620
		return $codec->encode( $sync_module->get_object_by_id( $object_type, $id ) );
621
	}
622
623
	/**
624
	 * Register additional sync XML-RPC methods available to Jetpack for authenticated users.
625
	 *
626
	 * @access public
627
	 * @since 7.8
628
	 *
629
	 * @param array $jetpack_methods XML-RPC methods available to the Jetpack Server.
630
	 * @return array Filtered XML-RPC methods.
631
	 */
632
	public function register_jetpack_xmlrpc_methods( $jetpack_methods ) {
633
		$jetpack_methods['jetpack.syncObject'] = array( $this, 'sync_object' );
634
		return $jetpack_methods;
635
	}
636
637
	/**
638
	 * Get the incremental sync queue object.
639
	 *
640
	 * @access public
641
	 *
642
	 * @return Automattic\Jetpack\Sync\Queue Queue object.
643
	 */
644
	public function get_sync_queue() {
645
		return $this->sync_queue;
646
	}
647
648
	/**
649
	 * Get the full sync queue object.
650
	 *
651
	 * @access public
652
	 *
653
	 * @return Automattic\Jetpack\Sync\Queue Queue object.
654
	 */
655
	public function get_full_sync_queue() {
656
		return $this->full_sync_queue;
657
	}
658
659
	/**
660
	 * Get the codec object.
661
	 *
662
	 * @access public
663
	 *
664
	 * @return Automattic\Jetpack\Sync\Codec_Interface Codec object.
665
	 */
666
	public function get_codec() {
667
		return $this->codec;
668
	}
669
670
	/**
671
	 * Determine the codec object.
672
	 * Use gzip deflate if supported.
673
	 *
674
	 * @access public
675
	 */
676
	public function set_codec() {
677
		if ( function_exists( 'gzinflate' ) ) {
678
			$this->codec = new JSON_Deflate_Array_Codec();
679
		} else {
680
			$this->codec = new Simple_Codec();
681
		}
682
	}
683
684
	/**
685
	 * Compute and send all the checksums.
686
	 *
687
	 * @access public
688
	 */
689
	public function send_checksum() {
690
		$store = new Replicastore();
691
		do_action( 'jetpack_sync_checksum', $store->checksum_all() );
692
	}
693
694
	/**
695
	 * Reset the incremental sync queue.
696
	 *
697
	 * @access public
698
	 */
699
	public function reset_sync_queue() {
700
		$this->sync_queue->reset();
701
	}
702
703
	/**
704
	 * Reset the full sync queue.
705
	 *
706
	 * @access public
707
	 */
708
	public function reset_full_sync_queue() {
709
		$this->full_sync_queue->reset();
710
	}
711
712
	/**
713
	 * Set the maximum bytes to checkout without exceeding the memory limit.
714
	 *
715
	 * @access public
716
	 *
717
	 * @param int $size Maximum bytes to checkout.
718
	 */
719
	public function set_dequeue_max_bytes( $size ) {
720
		$this->dequeue_max_bytes = $size;
721
	}
722
723
	/**
724
	 * Set the maximum bytes in a single encoded item.
725
	 *
726
	 * @access public
727
	 *
728
	 * @param int $max_bytes Maximum bytes in a single encoded item.
729
	 */
730
	public function set_upload_max_bytes( $max_bytes ) {
731
		$this->upload_max_bytes = $max_bytes;
732
	}
733
734
	/**
735
	 * Set the maximum number of sync items in a single action.
736
	 *
737
	 * @access public
738
	 *
739
	 * @param int $max_rows Maximum number of sync items.
740
	 */
741
	public function set_upload_max_rows( $max_rows ) {
742
		$this->upload_max_rows = $max_rows;
743
	}
744
745
	/**
746
	 * Set the sync wait time (in seconds).
747
	 *
748
	 * @access public
749
	 *
750
	 * @param int $seconds Sync wait time.
751
	 */
752
	public function set_sync_wait_time( $seconds ) {
753
		$this->sync_wait_time = $seconds;
754
	}
755
756
	/**
757
	 * Get current sync wait time (in seconds).
758
	 *
759
	 * @access public
760
	 *
761
	 * @return int Sync wait time.
762
	 */
763
	public function get_sync_wait_time() {
764
		return $this->sync_wait_time;
765
	}
766
767
	/**
768
	 * Set the enqueue wait time (in seconds).
769
	 *
770
	 * @access public
771
	 *
772
	 * @param int $seconds Enqueue wait time.
773
	 */
774
	public function set_enqueue_wait_time( $seconds ) {
775
		$this->enqueue_wait_time = $seconds;
776
	}
777
778
	/**
779
	 * Get current enqueue wait time (in seconds).
780
	 *
781
	 * @access public
782
	 *
783
	 * @return int Enqueue wait time.
784
	 */
785
	public function get_enqueue_wait_time() {
786
		return $this->enqueue_wait_time;
787
	}
788
789
	/**
790
	 * Set the sync wait threshold (in seconds).
791
	 *
792
	 * @access public
793
	 *
794
	 * @param int $seconds Sync wait threshold.
795
	 */
796
	public function set_sync_wait_threshold( $seconds ) {
797
		$this->sync_wait_threshold = $seconds;
798
	}
799
800
	/**
801
	 * Get current sync wait threshold (in seconds).
802
	 *
803
	 * @access public
804
	 *
805
	 * @return int Sync wait threshold.
806
	 */
807
	public function get_sync_wait_threshold() {
808
		return $this->sync_wait_threshold;
809
	}
810
811
	/**
812
	 * Set the maximum time for perfirming a checkout of items from the queue (in seconds).
813
	 *
814
	 * @access public
815
	 *
816
	 * @param int $seconds Maximum dequeue time.
817
	 */
818
	public function set_max_dequeue_time( $seconds ) {
819
		$this->max_dequeue_time = $seconds;
820
	}
821
822
	/**
823
	 * Initialize the sync queues, codec and set the default settings.
824
	 *
825
	 * @access public
826
	 */
827
	public function set_defaults() {
828
		$this->sync_queue      = new Queue( 'sync' );
829
		$this->full_sync_queue = new Queue( 'full_sync' );
830
		$this->set_codec();
831
832
		// Saved settings.
833
		Settings::set_importing( null );
834
		$settings = Settings::get_settings();
835
		$this->set_dequeue_max_bytes( $settings['dequeue_max_bytes'] );
836
		$this->set_upload_max_bytes( $settings['upload_max_bytes'] );
837
		$this->set_upload_max_rows( $settings['upload_max_rows'] );
838
		$this->set_sync_wait_time( $settings['sync_wait_time'] );
839
		$this->set_enqueue_wait_time( $settings['enqueue_wait_time'] );
840
		$this->set_sync_wait_threshold( $settings['sync_wait_threshold'] );
841
		$this->set_max_dequeue_time( Defaults::get_max_sync_execution_time() );
842
	}
843
844
	/**
845
	 * Reset sync queues, modules and settings.
846
	 *
847
	 * @access public
848
	 */
849
	public function reset_data() {
850
		$this->reset_sync_queue();
851
		$this->reset_full_sync_queue();
852
853
		foreach ( Modules::get_modules() as $module ) {
854
			$module->reset_data();
855
		}
856
857
		foreach ( array( 'sync', 'full_sync', 'full-sync-enqueue' ) as $queue_name ) {
858
			delete_option( self::NEXT_SYNC_TIME_OPTION_NAME . '_' . $queue_name );
859
		}
860
861
		Settings::reset_data();
862
	}
863
864
	/**
865
	 * Perform cleanup at the event of plugin uninstallation.
866
	 *
867
	 * @access public
868
	 */
869
	public function uninstall() {
870
		// Lets delete all the other fun stuff like transient and option and the sync queue.
871
		$this->reset_data();
872
873
		// Delete the full sync status.
874
		delete_option( 'jetpack_full_sync_status' );
875
876
		// Clear the sync cron.
877
		wp_clear_scheduled_hook( 'jetpack_sync_cron' );
878
		wp_clear_scheduled_hook( 'jetpack_sync_full_cron' );
879
	}
880
}
881