Completed
Push — update/connection-screen-desig... ( ad04a7...e52097 )
by
unknown
144:38 queued 133:55
created

Sender::maybe_set_user_from_token()   A

Complexity

Conditions 5
Paths 3

Size

Total Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
nc 3
nop 0
dl 0
loc 12
rs 9.5555
c 0
b 0
f 0
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();
0 ignored issues
show
Documentation Bug introduced by
It seems like new self() of type object<Automattic\Jetpack\Sync\Sender> is incompatible with the declared type object<Automattic\Jetpac...ic\Jetpack\Sync\Sender> of property $instance.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
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();
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Automattic\Jetpack\Sync\Modules\Module as the method continue_enqueuing() does only exist in the following sub-classes of Automattic\Jetpack\Sync\Modules\Module: Automattic\Jetpack\Sync\Modules\Full_Sync, Automattic\Jetpack\Sync\...s\Full_Sync_Immediately. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
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
		if ( ! Settings::is_sender_enabled( $queue->id ) ) {
331
			return new \WP_Error( 'sender_disabled_for_queue_' . $queue->id );
332
		}
333
334
		// Don't sync if we are throttled.
335
		if ( $this->get_next_sync_time( $queue->id ) > microtime( true ) ) {
336
			return new \WP_Error( 'sync_throttled' );
337
		}
338
339
		$start_time = microtime( true );
340
341
		Settings::set_is_syncing( true );
342
343
		$sync_result = $this->do_sync_for_queue( $queue );
344
345
		Settings::set_is_syncing( false );
346
347
		$exceeded_sync_wait_threshold = ( microtime( true ) - $start_time ) > (float) $this->get_sync_wait_threshold();
348
349
		if ( is_wp_error( $sync_result ) ) {
350
			if ( 'unclosed_buffer' === $sync_result->get_error_code() ) {
351
				$this->set_next_sync_time( time() + self::QUEUE_LOCKED_SYNC_DELAY, $queue->id );
352
			}
353
			if ( 'wpcom_error' === $sync_result->get_error_code() ) {
354
				$this->set_next_sync_time( time() + self::WPCOM_ERROR_SYNC_DELAY, $queue->id );
355
			}
356
		} elseif ( $exceeded_sync_wait_threshold ) {
357
			// If we actually sent data and it took a while, wait before sending again.
358
			$this->set_next_sync_time( time() + $this->get_sync_wait_time(), $queue->id );
359
		}
360
361
		return $sync_result;
362
	}
363
364
	/**
365
	 * Retrieve the next sync items to send.
366
	 *
367
	 * @access public
368
	 *
369
	 * @param (array|Automattic\Jetpack\Sync\Queue_Buffer) $buffer_or_items Queue buffer or array of objects.
370
	 * @param boolean                                      $encode Whether to encode the items.
371
	 * @return array Sync items to send.
372
	 */
373
	public function get_items_to_send( $buffer_or_items, $encode = true ) {
374
		// Track how long we've been processing so we can avoid request timeouts.
375
		$start_time    = microtime( true );
376
		$upload_size   = 0;
377
		$items_to_send = array();
378
		$items         = is_array( $buffer_or_items ) ? $buffer_or_items : $buffer_or_items->get_items();
379
		// Set up current screen to avoid errors rendering content.
380
		require_once ABSPATH . 'wp-admin/includes/class-wp-screen.php';
381
		require_once ABSPATH . 'wp-admin/includes/screen.php';
382
		set_current_screen( 'sync' );
383
		$skipped_items_ids = array();
384
		/**
385
		 * We estimate the total encoded size as we go by encoding each item individually.
386
		 * This is expensive, but the only way to really know :/
387
		 */
388
		foreach ( $items as $key => $item ) {
389
			// Suspending cache addition help prevent overloading in memory cache of large sites.
390
			wp_suspend_cache_addition( true );
391
			/**
392
			 * Modify the data within an action before it is serialized and sent to the server
393
			 * For example, during full sync this expands Post ID's into full Post objects,
394
			 * so that we don't have to serialize the whole object into the queue.
395
			 *
396
			 * @since 4.2.0
397
			 *
398
			 * @param array The action parameters
399
			 * @param int The ID of the user who triggered the action
400
			 */
401
			$item[1] = apply_filters( 'jetpack_sync_before_send_' . $item[0], $item[1], $item[2] );
402
			wp_suspend_cache_addition( false );
403
			if ( false === $item[1] ) {
404
				$skipped_items_ids[] = $key;
405
				continue;
406
			}
407
			$encoded_item = $encode ? $this->codec->encode( $item ) : $item;
408
			$upload_size += strlen( $encoded_item );
409
			if ( $upload_size > $this->upload_max_bytes && count( $items_to_send ) > 0 ) {
410
				break;
411
			}
412
			$items_to_send[ $key ] = $encoded_item;
413
			if ( microtime( true ) - $start_time > $this->max_dequeue_time ) {
414
				break;
415
			}
416
		}
417
418
		return array( $items_to_send, $skipped_items_ids, $items, microtime( true ) - $start_time );
419
	}
420
421
	/**
422
	 * If supported, flush all response data to the client and finish the request.
423
	 * This allows for time consuming tasks to be performed without leaving the connection open.
424
	 *
425
	 * @access private
426
	 */
427
	private function fastcgi_finish_request() {
428
		if ( function_exists( 'fastcgi_finish_request' ) && version_compare( phpversion(), '7.0.16', '>=' ) ) {
429
			fastcgi_finish_request();
430
		}
431
	}
432
433
	/**
434
	 * Perform sync for a certain sync queue.
435
	 *
436
	 * @access public
437
	 *
438
	 * @param Automattic\Jetpack\Sync\Queue $queue Queue object.
439
	 * @return boolean|\WP_Error True if this sync sending was successful, error object otherwise.
440
	 */
441
	public function do_sync_for_queue( $queue ) {
442
		do_action( 'jetpack_sync_before_send_queue_' . $queue->id );
443
		if ( $queue->size() === 0 ) {
444
			return new \WP_Error( 'empty_queue_' . $queue->id );
445
		}
446
447
		/**
448
		 * Now that we're sure we are about to sync, try to ignore user abort
449
		 * so we can avoid getting into a bad state.
450
		 */
451
		if ( function_exists( 'ignore_user_abort' ) ) {
452
			ignore_user_abort( true );
453
		}
454
455
		/* Don't make the request block till we finish, if possible. */
456
		if ( Constants::is_true( 'REST_REQUEST' ) || Constants::is_true( 'XMLRPC_REQUEST' ) ) {
457
			$this->fastcgi_finish_request();
458
		}
459
460
		$checkout_start_time = microtime( true );
461
462
		$buffer = $queue->checkout_with_memory_limit( $this->dequeue_max_bytes, $this->upload_max_rows );
463
464
		if ( ! $buffer ) {
465
			// Buffer has no items.
466
			return new \WP_Error( 'empty_buffer' );
467
		}
468
469
		if ( is_wp_error( $buffer ) ) {
470
			return $buffer;
471
		}
472
473
		$checkout_duration = microtime( true ) - $checkout_start_time;
474
475
		list( $items_to_send, $skipped_items_ids, $items, $preprocess_duration ) = $this->get_items_to_send( $buffer, true );
476
		if ( ! empty( $items_to_send ) ) {
477
			/**
478
			 * Fires when data is ready to send to the server.
479
			 * Return false or WP_Error to abort the sync (e.g. if there's an error)
480
			 * The items will be automatically re-sent later
481
			 *
482
			 * @since 4.2.0
483
			 *
484
			 * @param array  $data The action buffer
485
			 * @param string $codec The codec name used to encode the data
486
			 * @param double $time The current time
487
			 * @param string $queue The queue used to send ('sync' or 'full_sync')
488
			 * @param float  $checkout_duration The duration of the checkout operation.
489
			 * @param float  $preprocess_duration The duration of the pre-process operation.
490
			 * @param int    $queue_size The size of the sync queue at the time of processing.
491
			 */
492
			Settings::set_is_sending( true );
493
			$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 );
494
			Settings::set_is_sending( false );
495
		} else {
496
			$processed_item_ids = $skipped_items_ids;
497
			$skipped_items_ids  = array();
498
		}
499
500
		if ( 'non-blocking' !== $processed_item_ids ) {
501
			if ( ! $processed_item_ids || is_wp_error( $processed_item_ids ) ) {
502
				$checked_in_item_ids = $queue->checkin( $buffer );
503
				if ( is_wp_error( $checked_in_item_ids ) ) {
504
					// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
505
					error_log( 'Error checking in buffer: ' . $checked_in_item_ids->get_error_message() );
506
					$queue->force_checkin();
507
				}
508
				if ( is_wp_error( $processed_item_ids ) ) {
509
					return new \WP_Error( 'wpcom_error', $processed_item_ids->get_error_code() );
510
				}
511
512
				// Returning a wpcom_error is a sign to the caller that we should wait a while before syncing again.
513
				return new \WP_Error( 'wpcom_error', 'jetpack_sync_send_data_false' );
514
			} else {
515
				// Detect if the last item ID was an error.
516
				$had_wp_error = is_wp_error( end( $processed_item_ids ) );
517
				if ( $had_wp_error ) {
518
					$wp_error = array_pop( $processed_item_ids );
519
				}
520
				// Also checkin any items that were skipped.
521
				if ( count( $skipped_items_ids ) > 0 ) {
522
					$processed_item_ids = array_merge( $processed_item_ids, $skipped_items_ids );
523
				}
524
				$processed_items = array_intersect_key( $items, array_flip( $processed_item_ids ) );
525
				/**
526
				 * Allows us to keep track of all the actions that have been sent.
527
				 * Allows us to calculate the progress of specific actions.
528
				 *
529
				 * @since 4.2.0
530
				 *
531
				 * @param array $processed_actions The actions that we send successfully.
532
				 */
533
				do_action( 'jetpack_sync_processed_actions', $processed_items );
534
				$queue->close( $buffer, $processed_item_ids );
535
				// Returning a WP_Error is a sign to the caller that we should wait a while before syncing again.
536
				if ( $had_wp_error ) {
537
					return new \WP_Error( 'wpcom_error', $wp_error->get_error_code() );
0 ignored issues
show
Bug introduced by
The variable $wp_error does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
538
				}
539
			}
540
		}
541
542
		return true;
543
	}
544
545
	/**
546
	 * Immediately sends a single item without firing or enqueuing it
547
	 *
548
	 * @param string $action_name The action.
549
	 * @param array  $data The data associated with the action.
0 ignored issues
show
Documentation introduced by
Should the type for parameter $data not be array|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
550
	 *
551
	 * @return Items processed. TODO: this doesn't make much sense anymore, it should probably be just a bool.
552
	 */
553
	public function send_action( $action_name, $data = null ) {
554
		if ( ! Settings::is_sender_enabled( 'full_sync' ) ) {
555
			return array();
556
		}
557
558
		// Compose the data to be sent.
559
		$action_to_send = $this->create_action_to_send( $action_name, $data );
560
561
		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
0 ignored issues
show
Unused Code introduced by
The assignment to $skipped_items_ids is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
Unused Code introduced by
The assignment to $items is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
562
		Settings::set_is_sending( true );
563
		$processed_item_ids = apply_filters( 'jetpack_sync_send_data', $items_to_send, $this->get_codec()->name(), microtime( true ), 'immediate-send', 0, $preprocess_duration );
564
		Settings::set_is_sending( false );
565
566
		/**
567
		 * Allows us to keep track of all the actions that have been sent.
568
		 * Allows us to calculate the progress of specific actions.
569
		 *
570
		 * @param array $processed_actions The actions that we send successfully.
571
		 *
572
		 * @since 4.2.0
573
		 */
574
		do_action( 'jetpack_sync_processed_actions', $action_to_send );
575
576
		return $processed_item_ids;
577
	}
578
579
	/**
580
	 * Create an synthetic action for direct sending to WPCOM during full sync (for example)
581
	 *
582
	 * @access private
583
	 *
584
	 * @param string $action_name The action.
585
	 * @param array  $data The data associated with the action.
586
	 * @return array An array of synthetic sync actions keyed by current microtime(true)
587
	 */
588
	private function create_action_to_send( $action_name, $data ) {
589
		return array(
590
			(string) microtime( true ) => array(
591
				$action_name,
592
				$data,
593
				get_current_user_id(),
594
				microtime( true ),
595
				Settings::is_importing(),
596
			),
597
		);
598
	}
599
600
	/**
601
	 * Returns any object that is able to be synced.
602
	 *
603
	 * @access public
604
	 *
605
	 * @param array $args the synchronized object parameters.
606
	 * @return string Encoded sync object.
607
	 */
608
	public function sync_object( $args ) {
609
		// For example: posts, post, 5.
610
		list( $module_name, $object_type, $id ) = $args;
611
612
		$sync_module = Modules::get_module( $module_name );
613
		$codec       = $this->get_codec();
614
615
		return $codec->encode( $sync_module->get_object_by_id( $object_type, $id ) );
616
	}
617
618
	/**
619
	 * Register additional sync XML-RPC methods available to Jetpack for authenticated users.
620
	 *
621
	 * @access public
622
	 * @since 7.8
623
	 *
624
	 * @param array $jetpack_methods XML-RPC methods available to the Jetpack Server.
625
	 * @return array Filtered XML-RPC methods.
626
	 */
627
	public function register_jetpack_xmlrpc_methods( $jetpack_methods ) {
628
		$jetpack_methods['jetpack.syncObject'] = array( $this, 'sync_object' );
629
		return $jetpack_methods;
630
	}
631
632
	/**
633
	 * Get the incremental sync queue object.
634
	 *
635
	 * @access public
636
	 *
637
	 * @return Automattic\Jetpack\Sync\Queue Queue object.
638
	 */
639
	public function get_sync_queue() {
640
		return $this->sync_queue;
641
	}
642
643
	/**
644
	 * Get the full sync queue object.
645
	 *
646
	 * @access public
647
	 *
648
	 * @return Automattic\Jetpack\Sync\Queue Queue object.
649
	 */
650
	public function get_full_sync_queue() {
651
		return $this->full_sync_queue;
652
	}
653
654
	/**
655
	 * Get the codec object.
656
	 *
657
	 * @access public
658
	 *
659
	 * @return Automattic\Jetpack\Sync\Codec_Interface Codec object.
660
	 */
661
	public function get_codec() {
662
		return $this->codec;
663
	}
664
665
	/**
666
	 * Determine the codec object.
667
	 * Use gzip deflate if supported.
668
	 *
669
	 * @access public
670
	 */
671
	public function set_codec() {
672
		if ( function_exists( 'gzinflate' ) ) {
673
			$this->codec = new JSON_Deflate_Array_Codec();
0 ignored issues
show
Documentation Bug introduced by
It seems like new \Automattic\Jetpack\...N_Deflate_Array_Codec() of type object<Automattic\Jetpac...ON_Deflate_Array_Codec> is incompatible with the declared type object<Automattic\Jetpac...k\Sync\Codec_Interface> of property $codec.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
674
		} else {
675
			$this->codec = new Simple_Codec();
0 ignored issues
show
Documentation Bug introduced by
It seems like new \Automattic\Jetpack\Sync\Simple_Codec() of type object<Automattic\Jetpack\Sync\Simple_Codec> is incompatible with the declared type object<Automattic\Jetpac...k\Sync\Codec_Interface> of property $codec.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
676
		}
677
	}
678
679
	/**
680
	 * Compute and send all the checksums.
681
	 *
682
	 * @access public
683
	 */
684
	public function send_checksum() {
685
		$store = new Replicastore();
686
		do_action( 'jetpack_sync_checksum', $store->checksum_all() );
687
	}
688
689
	/**
690
	 * Reset the incremental sync queue.
691
	 *
692
	 * @access public
693
	 */
694
	public function reset_sync_queue() {
695
		$this->sync_queue->reset();
696
	}
697
698
	/**
699
	 * Reset the full sync queue.
700
	 *
701
	 * @access public
702
	 */
703
	public function reset_full_sync_queue() {
704
		$this->full_sync_queue->reset();
705
	}
706
707
	/**
708
	 * Set the maximum bytes to checkout without exceeding the memory limit.
709
	 *
710
	 * @access public
711
	 *
712
	 * @param int $size Maximum bytes to checkout.
713
	 */
714
	public function set_dequeue_max_bytes( $size ) {
715
		$this->dequeue_max_bytes = $size;
716
	}
717
718
	/**
719
	 * Set the maximum bytes in a single encoded item.
720
	 *
721
	 * @access public
722
	 *
723
	 * @param int $max_bytes Maximum bytes in a single encoded item.
724
	 */
725
	public function set_upload_max_bytes( $max_bytes ) {
726
		$this->upload_max_bytes = $max_bytes;
727
	}
728
729
	/**
730
	 * Set the maximum number of sync items in a single action.
731
	 *
732
	 * @access public
733
	 *
734
	 * @param int $max_rows Maximum number of sync items.
735
	 */
736
	public function set_upload_max_rows( $max_rows ) {
737
		$this->upload_max_rows = $max_rows;
738
	}
739
740
	/**
741
	 * Set the sync wait time (in seconds).
742
	 *
743
	 * @access public
744
	 *
745
	 * @param int $seconds Sync wait time.
746
	 */
747
	public function set_sync_wait_time( $seconds ) {
748
		$this->sync_wait_time = $seconds;
749
	}
750
751
	/**
752
	 * Get current sync wait time (in seconds).
753
	 *
754
	 * @access public
755
	 *
756
	 * @return int Sync wait time.
757
	 */
758
	public function get_sync_wait_time() {
759
		return $this->sync_wait_time;
760
	}
761
762
	/**
763
	 * Set the enqueue wait time (in seconds).
764
	 *
765
	 * @access public
766
	 *
767
	 * @param int $seconds Enqueue wait time.
768
	 */
769
	public function set_enqueue_wait_time( $seconds ) {
770
		$this->enqueue_wait_time = $seconds;
771
	}
772
773
	/**
774
	 * Get current enqueue wait time (in seconds).
775
	 *
776
	 * @access public
777
	 *
778
	 * @return int Enqueue wait time.
779
	 */
780
	public function get_enqueue_wait_time() {
781
		return $this->enqueue_wait_time;
782
	}
783
784
	/**
785
	 * Set the sync wait threshold (in seconds).
786
	 *
787
	 * @access public
788
	 *
789
	 * @param int $seconds Sync wait threshold.
790
	 */
791
	public function set_sync_wait_threshold( $seconds ) {
792
		$this->sync_wait_threshold = $seconds;
793
	}
794
795
	/**
796
	 * Get current sync wait threshold (in seconds).
797
	 *
798
	 * @access public
799
	 *
800
	 * @return int Sync wait threshold.
801
	 */
802
	public function get_sync_wait_threshold() {
803
		return $this->sync_wait_threshold;
804
	}
805
806
	/**
807
	 * Set the maximum time for perfirming a checkout of items from the queue (in seconds).
808
	 *
809
	 * @access public
810
	 *
811
	 * @param int $seconds Maximum dequeue time.
812
	 */
813
	public function set_max_dequeue_time( $seconds ) {
814
		$this->max_dequeue_time = $seconds;
815
	}
816
817
	/**
818
	 * Initialize the sync queues, codec and set the default settings.
819
	 *
820
	 * @access public
821
	 */
822
	public function set_defaults() {
823
		$this->sync_queue      = new Queue( 'sync' );
0 ignored issues
show
Documentation Bug introduced by
It seems like new \Automattic\Jetpack\Sync\Queue('sync') of type object<Automattic\Jetpack\Sync\Queue> is incompatible with the declared type object<Automattic\Jetpac...tic\Jetpack\Sync\Queue> of property $sync_queue.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
824
		$this->full_sync_queue = new Queue( 'full_sync' );
0 ignored issues
show
Documentation Bug introduced by
It seems like new \Automattic\Jetpack\Sync\Queue('full_sync') of type object<Automattic\Jetpack\Sync\Queue> is incompatible with the declared type object<Automattic\Jetpac...tic\Jetpack\Sync\Queue> of property $full_sync_queue.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
825
		$this->set_codec();
826
827
		// Saved settings.
828
		Settings::set_importing( null );
829
		$settings = Settings::get_settings();
830
		$this->set_dequeue_max_bytes( $settings['dequeue_max_bytes'] );
831
		$this->set_upload_max_bytes( $settings['upload_max_bytes'] );
832
		$this->set_upload_max_rows( $settings['upload_max_rows'] );
833
		$this->set_sync_wait_time( $settings['sync_wait_time'] );
834
		$this->set_enqueue_wait_time( $settings['enqueue_wait_time'] );
835
		$this->set_sync_wait_threshold( $settings['sync_wait_threshold'] );
836
		$this->set_max_dequeue_time( Defaults::get_max_sync_execution_time() );
837
	}
838
839
	/**
840
	 * Reset sync queues, modules and settings.
841
	 *
842
	 * @access public
843
	 */
844
	public function reset_data() {
845
		$this->reset_sync_queue();
846
		$this->reset_full_sync_queue();
847
848
		foreach ( Modules::get_modules() as $module ) {
849
			$module->reset_data();
850
		}
851
852
		foreach ( array( 'sync', 'full_sync', 'full-sync-enqueue' ) as $queue_name ) {
853
			delete_option( self::NEXT_SYNC_TIME_OPTION_NAME . '_' . $queue_name );
854
		}
855
856
		Settings::reset_data();
857
	}
858
859
	/**
860
	 * Perform cleanup at the event of plugin uninstallation.
861
	 *
862
	 * @access public
863
	 */
864
	public function uninstall() {
865
		// Lets delete all the other fun stuff like transient and option and the sync queue.
866
		$this->reset_data();
867
868
		// Delete the full sync status.
869
		delete_option( 'jetpack_full_sync_status' );
870
871
		// Clear the sync cron.
872
		wp_clear_scheduled_hook( 'jetpack_sync_cron' );
873
		wp_clear_scheduled_hook( 'jetpack_sync_full_cron' );
874
	}
875
}
876