Completed
Push — renovate/octokit-rest-18.x ( fdf192...f7756d )
by
unknown
42:56 queued 32:41
created

REST_Endpoints::checkout()   A

Complexity

Conditions 5
Paths 4

Size

Total Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
nc 4
nop 1
dl 0
loc 22
rs 9.2568
c 0
b 0
f 0
1
<?php
2
/**
3
 * Sync package.
4
 *
5
 * @package  automattic/jetpack-sync
6
 */
7
8
namespace Automattic\Jetpack\Sync;
9
10
use Automattic\Jetpack\Connection\Rest_Authentication;
11
use WP_Error;
12
use WP_REST_Server;
13
14
/**
15
 * This class will handle Sync v4 REST Endpoints.
16
 *
17
 * @since 9.9.0
18
 */
19
class REST_Endpoints {
20
21
	/**
22
	 *  Items pending send.
23
	 *
24
	 * @var array
25
	 */
26
	public $items = array();
27
28
	/**
29
	 * Initialize REST routes.
30
	 */
31
	public static function initialize_rest_api() {
32
33
		// Request a Full Sync.
34
		register_rest_route(
35
			'jetpack/v4',
36
			'/sync/full-sync',
37
			array(
38
				'methods'             => WP_REST_Server::EDITABLE,
39
				'callback'            => __CLASS__ . '::full_sync_start',
40
				'permission_callback' => __CLASS__ . '::verify_default_permissions',
41
				'args'                => array(
42
					'modules'  => array(
43
						'description' => __( 'Data Modules that should be included in Full Sync', 'jetpack' ),
44
						'type'        => 'array',
45
						'required'    => false,
46
					),
47
					'users'    => array(
48
						'description' => __( 'User IDs to include in Full Sync or "initial"', 'jetpack' ),
49
						'required'    => false,
50
					),
51
					'posts'    => array(
52
						'description' => __( 'Post IDs to include in Full Sync', 'jetpack' ),
53
						'type'        => 'array',
54
						'required'    => false,
55
					),
56
					'comments' => array(
57
						'description' => __( 'Comment IDs to include in Full Sync', 'jetpack' ),
58
						'type'        => 'array',
59
						'required'    => false,
60
					),
61
				),
62
			)
63
		);
64
65
		// Obtain Sync status.
66
		register_rest_route(
67
			'jetpack/v4',
68
			'/sync/status',
69
			array(
70
				'methods'             => WP_REST_Server::READABLE,
71
				'callback'            => __CLASS__ . '::sync_status',
72
				'permission_callback' => __CLASS__ . '::verify_default_permissions',
73
				'args'                => array(
74
					'fields' => array(
75
						'description' => __( 'Comma seperated list of additional fields that should be included in status.', 'jetpack' ),
76
						'type'        => 'string',
77
						'required'    => false,
78
					),
79
				),
80
			)
81
		);
82
83
		// Update Sync health status.
84
		register_rest_route(
85
			'jetpack/v4',
86
			'/sync/health',
87
			array(
88
				'methods'             => WP_REST_Server::EDITABLE,
89
				'callback'            => __CLASS__ . '::sync_health',
90
				'permission_callback' => __CLASS__ . '::verify_default_permissions',
91
				'args'                => array(
92
					'status' => array(
93
						'description' => __( 'New Sync health status', 'jetpack' ),
94
						'type'        => 'string',
95
						'required'    => true,
96
					),
97
				),
98
			)
99
		);
100
101
		// Obtain Sync settings.
102
		register_rest_route(
103
			'jetpack/v4',
104
			'/sync/settings',
105
			array(
106
				array(
107
					'methods'             => WP_REST_Server::READABLE,
108
					'callback'            => __CLASS__ . '::get_sync_settings',
109
					'permission_callback' => __CLASS__ . '::verify_default_permissions',
110
				),
111
				array(
112
					'methods'             => WP_REST_Server::EDITABLE,
113
					'callback'            => __CLASS__ . '::update_sync_settings',
114
					'permission_callback' => __CLASS__ . '::verify_default_permissions',
115
				),
116
			)
117
		);
118
119
		// Retrieve Sync Object(s).
120
		register_rest_route(
121
			'jetpack/v4',
122
			'/sync/object',
123
			array(
124
				'methods'             => WP_REST_Server::READABLE,
125
				'callback'            => __CLASS__ . '::get_sync_objects',
126
				'permission_callback' => __CLASS__ . '::verify_default_permissions',
127
				'args'                => array(
128
					'module_name' => array(
129
						'description' => __( 'Name of Sync module', 'jetpack' ),
130
						'type'        => 'string',
131
						'required'    => false,
132
					),
133
					'object_type' => array(
134
						'description' => __( 'Object Type', 'jetpack' ),
135
						'type'        => 'string',
136
						'required'    => false,
137
					),
138
					'object_ids'  => array(
139
						'description' => __( 'Objects Identifiers', 'jetpack' ),
140
						'type'        => 'array',
141
						'required'    => false,
142
					),
143
				),
144
			)
145
		);
146
147
		// Retrieve Sync Object(s).
148
		register_rest_route(
149
			'jetpack/v4',
150
			'/sync/now',
151
			array(
152
				'methods'             => WP_REST_Server::EDITABLE,
153
				'callback'            => __CLASS__ . '::do_sync',
154
				'permission_callback' => __CLASS__ . '::verify_default_permissions',
155
				'args'                => array(
156
					'queue' => array(
157
						'description' => __( 'Name of Sync queue.', 'jetpack' ),
158
						'type'        => 'string',
159
						'required'    => true,
160
					),
161
				),
162
			)
163
		);
164
165
		// Checkout Sync Objects.
166
		register_rest_route(
167
			'jetpack/v4',
168
			'/sync/checkout',
169
			array(
170
				'methods'             => WP_REST_Server::EDITABLE,
171
				'callback'            => __CLASS__ . '::checkout',
172
				'permission_callback' => __CLASS__ . '::verify_default_permissions',
173
			)
174
		);
175
176
		// Checkin Sync Objects.
177
		register_rest_route(
178
			'jetpack/v4',
179
			'/sync/close',
180
			array(
181
				'methods'             => WP_REST_Server::EDITABLE,
182
				'callback'            => __CLASS__ . '::close',
183
				'permission_callback' => __CLASS__ . '::verify_default_permissions',
184
			)
185
		);
186
187
		// Unlock Sync Queue.
188
		register_rest_route(
189
			'jetpack/v4',
190
			'/sync/unlock',
191
			array(
192
				'methods'             => WP_REST_Server::EDITABLE,
193
				'callback'            => __CLASS__ . '::unlock_queue',
194
				'permission_callback' => __CLASS__ . '::verify_default_permissions',
195
				'args'                => array(
196
					'queue' => array(
197
						'description' => __( 'Name of Sync queue.', 'jetpack' ),
198
						'type'        => 'string',
199
						'required'    => true,
200
					),
201
				),
202
			)
203
		);
204
205
		// Retrieve range of Object Ids.
206
		register_rest_route(
207
			'jetpack/v4',
208
			'/sync/object-id-range',
209
			array(
210
				'methods'             => WP_REST_Server::READABLE,
211
				'callback'            => __CLASS__ . '::get_object_id_range',
212
				'permission_callback' => __CLASS__ . '::verify_default_permissions',
213
				'args'                => array(
214
					'sync_module' => array(
215
						'description' => __( 'Name of Sync module.', 'jetpack' ),
216
						'type'        => 'string',
217
						'required'    => true,
218
					),
219
					'batch_size'  => array(
220
						'description' => __( 'Size of batches', 'jetpack' ),
221
						'type'        => 'int',
222
						'required'    => true,
223
					),
224
				),
225
			)
226
		);
227
228
		// Obtain table checksums.
229
		register_rest_route(
230
			'jetpack/v4',
231
			'/sync/data-check',
232
			array(
233
				'methods'             => WP_REST_Server::READABLE,
234
				'callback'            => __CLASS__ . '::data_check',
235
				'permission_callback' => __CLASS__ . '::verify_default_permissions',
236
			)
237
		);
238
239
		// Obtain histogram.
240
		register_rest_route(
241
			'jetpack/v4',
242
			'/sync/data-histogram',
243
			array(
244
				'methods'             => WP_REST_Server::EDITABLE,
245
				'callback'            => __CLASS__ . '::data_histogram',
246
				'permission_callback' => __CLASS__ . '::verify_default_permissions',
247
				'args'                => array(
248
					'columns'            => array(
249
						'description' => __( 'Column mappings', 'jetpack' ),
250
						'type'        => 'array',
251
						'required'    => false,
252
					),
253
					'object_type'        => array(
254
						'description' => __( 'Object Type', 'jetpack' ),
255
						'type'        => 'string',
256
						'required'    => false,
257
					),
258
					'buckets'            => array(
259
						'description' => __( 'Number of histogram buckets.', 'jetpack' ),
260
						'type'        => 'int',
261
						'required'    => false,
262
					),
263
					'start_id'           => array(
264
						'description' => __( 'Start ID for the histogram', 'jetpack' ),
265
						'type'        => 'int',
266
						'required'    => false,
267
					),
268
					'end_id'             => array(
269
						'description' => __( 'End ID for the histogram', 'jetpack' ),
270
						'type'        => 'int',
271
						'required'    => false,
272
					),
273
					'strip_non_ascii'    => array(
274
						'description' => __( 'Strip non-ascii characters?', 'jetpack' ),
275
						'type'        => 'boolean',
276
						'required'    => false,
277
					),
278
					'shared_salt'        => array(
279
						'description' => __( 'Shared Salt to use when generating checksum', 'jetpack' ),
280
						'type'        => 'string',
281
						'required'    => false,
282
					),
283
					'only_range_edges'   => array(
284
						'description' => __( 'Should only range endges be returned', 'jetpack' ),
285
						'type'        => 'boolean',
286
						'required'    => false,
287
					),
288
					'detailed_drilldown' => array(
289
						'description' => __( 'Do we want the checksum or object ids.', 'jetpack' ),
290
						'type'        => 'boolean',
291
						'required'    => false,
292
					),
293
				),
294
			)
295
		);
296
297
	}
298
299
	/**
300
	 * Trigger a Full Sync of specified modules.
301
	 *
302
	 * @since 9.9.0
303
	 *
304
	 * @param \WP_REST_Request $request The request sent to the WP REST API.
305
	 *
306
	 * @return \WP_REST_Response|WP_Error
307
	 */
308
	public static function full_sync_start( $request ) {
309
310
		$modules = $request->get_param( 'modules' );
311
312
		// convert list of modules into array format of "$modulename => true".
313
		if ( ! empty( $modules ) ) {
314
			$modules = array_map( '__return_true', array_flip( $modules ) );
315
		}
316
317
		// Process additional options.
318
		foreach ( array( 'posts', 'comments', 'users' ) as $module_name ) {
319
			if ( 'users' === $module_name && 'initial' === $request->get_param( 'users' ) ) {
320
				$modules['users'] = 'initial';
321
			} elseif ( is_array( $request->get_param( $module_name ) ) ) {
322
				$ids = $request->get_param( $module_name );
323
				if ( count( $ids ) > 0 ) {
324
					$modules[ $module_name ] = $ids;
325
				}
326
			}
327
		}
328
329
		if ( empty( $modules ) ) {
330
			$modules = null;
331
		}
332
333
		return rest_ensure_response(
334
			array(
335
				'scheduled' => Actions::do_full_sync( $modules ),
336
			)
337
		);
338
	}
339
340
	/**
341
	 * Return Sync's status.
342
	 *
343
	 * @since 9.9.0
344
	 *
345
	 * @param \WP_REST_Request $request The request sent to the WP REST API.
346
	 *
347
	 * @return \WP_REST_Response
348
	 */
349
	public static function sync_status( $request ) {
350
		$fields = $request->get_param( 'fields' );
351
		return rest_ensure_response( Actions::get_sync_status( $fields ) );
352
	}
353
354
	/**
355
	 * Return table checksums.
356
	 *
357
	 * @since 9.9.0
358
	 *
359
	 * @return \WP_REST_Response
360
	 */
361
	public static function data_check() {
362
		// Disable Sync during this call, so we can resolve faster.
363
		Actions::mark_sync_read_only();
364
		$store = new Replicastore();
365
		return rest_ensure_response( $store->checksum_all() );
366
	}
367
368
	/**
369
	 * Return Histogram.
370
	 *
371
	 * @since 9.9.0
372
	 *
373
	 * @param \WP_REST_Request $request The request sent to the WP REST API.
374
	 *
375
	 * @return \WP_REST_Response
376
	 */
377
	public static function data_histogram( $request ) {
378
379
		// Disable Sync during this call, so we can resolve faster.
380
		Actions::mark_sync_read_only();
381
382
		$args = $request->get_params();
383
384
		if ( empty( $args['columns'] ) ) {
385
			$args['columns'] = null; // go with defaults.
386
		}
387
388
		if ( false !== $args['strip_non_ascii'] ) {
389
			$args['strip_non_ascii'] = true;
390
		}
391
392
		/**
393
		 * Hack: nullify the values of `start_id` and `end_id` if we're only requesting ranges.
394
		 *
395
		 * The endpoint doesn't support nullable values :(
396
		 */
397 View Code Duplication
		if ( true === $args['only_range_edges'] ) {
398
			if ( 0 === $args['start_id'] ) {
399
				$args['start_id'] = null;
400
			}
401
402
			if ( 0 === $args['end_id'] ) {
403
				$args['end_id'] = null;
404
			}
405
		}
406
407
		$store     = new Replicastore();
408
		$histogram = $store->checksum_histogram( $args['object_type'], $args['buckets'], $args['start_id'], $args['end_id'], $args['columns'], $args['strip_non_ascii'], $args['shared_salt'], $args['only_range_edges'], $args['detailed_drilldown'] );
409
410
		return rest_ensure_response(
411
			array(
412
				'histogram' => $histogram,
413
				'type'      => $store->get_checksum_type(),
414
			)
415
		);
416
	}
417
418
	/**
419
	 * Update Sync health.
420
	 *
421
	 * @since 9.9.0
422
	 *
423
	 * @param \WP_REST_Request $request The request sent to the WP REST API.
424
	 *
425
	 * @return \WP_REST_Response
426
	 */
427
	public static function sync_health( $request ) {
428
429 View Code Duplication
		switch ( $request->get_param( 'status' ) ) {
430
			case Health::STATUS_IN_SYNC:
431
			case Health::STATUS_OUT_OF_SYNC:
432
				Health::update_status( $request->get_param( 'status' ) );
433
				break;
434
			default:
435
				return new WP_Error( 'invalid_status', 'Invalid Sync Status Provided.' );
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'invalid_status'.

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...
436
		}
437
438
		// re-fetch so we see what's really being stored.
439
		return rest_ensure_response(
440
			array(
441
				'success' => Health::get_status(),
442
			)
443
		);
444
	}
445
446
	/**
447
	 * Obtain Sync settings.
448
	 *
449
	 * @since 9.9.0
450
	 *
451
	 * @return \WP_REST_Response
452
	 */
453
	public static function get_sync_settings() {
454
		return rest_ensure_response( Settings::get_settings() );
455
	}
456
457
	/**
458
	 * Update Sync settings.
459
	 *
460
	 * @since 9.9.0
461
	 *
462
	 * @param \WP_REST_Request $request The request sent to the WP REST API.
463
	 *
464
	 * @return \WP_REST_Response
465
	 */
466 View Code Duplication
	public static function update_sync_settings( $request ) {
467
		$args          = $request->get_params();
468
		$sync_settings = Settings::get_settings();
469
470
		foreach ( $args as $key => $value ) {
471
			if ( false !== $value ) {
472
				if ( is_numeric( $value ) ) {
473
					$value = (int) $value;
474
				}
475
476
				// special case for sending empty arrays - a string with value 'empty'.
477
				if ( 'empty' === $value ) {
478
					$value = array();
479
				}
480
481
				$sync_settings[ $key ] = $value;
482
			}
483
		}
484
485
		Settings::update_settings( $sync_settings );
486
487
		// re-fetch so we see what's really being stored.
488
		return rest_ensure_response( Settings::get_settings() );
489
	}
490
491
	/**
492
	 * Retrieve Sync Objects.
493
	 *
494
	 * @since 9.9.0
495
	 *
496
	 * @param \WP_REST_Request $request The request sent to the WP REST API.
497
	 *
498
	 * @return \WP_REST_Response
499
	 */
500
	public static function get_sync_objects( $request ) {
501
		$args = $request->get_params();
502
503
		$module_name = $args['module_name'];
504
		// Verify valid Sync Module.
505
		$sync_module = Modules::get_module( $module_name );
506
		if ( ! $sync_module ) {
507
			return new WP_Error( 'invalid_module', 'You specified an invalid sync module' );
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'invalid_module'.

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...
508
		}
509
510
		Actions::mark_sync_read_only();
511
512
		$codec = Sender::get_instance()->get_codec();
513
		Settings::set_is_syncing( true );
514
		$objects = $codec->encode( $sync_module->get_objects_by_id( $args['object_type'], $args['object_ids'] ) );
515
		Settings::set_is_syncing( false );
516
517
		return rest_ensure_response(
518
			array(
519
				'objects' => $objects,
520
				'codec'   => $codec->name(),
521
			)
522
		);
523
	}
524
525
	/**
526
	 * Request Sync processing.
527
	 *
528
	 * @since 9.9.0
529
	 *
530
	 * @param \WP_REST_Request $request The request sent to the WP REST API.
531
	 *
532
	 * @return \WP_REST_Response
533
	 */
534
	public static function do_sync( $request ) {
535
536
		$queue_name = self::validate_queue( $request->get_param( 'queue' ) );
537
		if ( is_wp_error( $queue_name ) ) {
538
			return $queue_name;
539
		}
540
541
		$sender   = Sender::get_instance();
542
		$response = $sender->do_sync_for_queue( new Queue( $queue_name ) );
0 ignored issues
show
Documentation introduced by
$queue_name is of type object<WP_Error>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
Documentation introduced by
new \Automattic\Jetpack\Sync\Queue($queue_name) is of type object<Automattic\Jetpack\Sync\Queue>, but the function expects a object<Automattic\Jetpac...tic\Jetpack\Sync\Queue>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
543
544
		return rest_ensure_response(
545
			array(
546
				'response' => $response,
547
			)
548
		);
549
	}
550
551
	/**
552
	 * Request sync data from specified queue.
553
	 *
554
	 * @since 9.9.0
555
	 *
556
	 * @param \WP_REST_Request $request The request sent to the WP REST API.
557
	 *
558
	 * @return \WP_REST_Response
559
	 */
560
	public static function checkout( $request ) {
561
		$args       = $request->get_params();
562
		$queue_name = self::validate_queue( $args['queue'] );
563
564
		if ( is_wp_error( $queue_name ) ) {
565
			return $queue_name;
566
		}
567
568
		$number_of_items = $args['number_of_items'];
569
		if ( $number_of_items < 1 || $number_of_items > 100 ) {
570
			return new WP_Error( 'invalid_number_of_items', 'Number of items needs to be an integer that is larger than 0 and less then 100', 400 );
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'invalid_number_of_items'.

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...
571
		}
572
573
		// REST Sender.
574
		$sender = new REST_Sender();
575
576
		if ( 'immediate' === $queue_name ) {
577
			return rest_ensure_response( $sender->immediate_full_sync_pull( $number_of_items ) );
0 ignored issues
show
Unused Code introduced by
The call to REST_Sender::immediate_full_sync_pull() has too many arguments starting with $number_of_items.

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...
578
		}
579
580
		return rest_ensure_response( $sender->queue_pull( $queue_name, $number_of_items, $args ) );
0 ignored issues
show
Documentation introduced by
$queue_name is of type object<WP_Error>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
581
	}
582
583
	/**
584
	 * Unlock a Sync queue.
585
	 *
586
	 * @since 9.9.0
587
	 *
588
	 * @param \WP_REST_Request $request The request sent to the WP REST API.
589
	 *
590
	 * @return \WP_REST_Response
591
	 */
592
	public static function unlock_queue( $request ) {
593
594
		$queue_name = $request->get_param( 'queue' );
595
596
		if ( ! in_array( $queue_name, array( 'sync', 'full_sync' ), true ) ) {
597
			return new WP_Error( 'invalid_queue', 'Queue name should be sync or full_sync', 400 );
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'invalid_queue'.

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...
598
		}
599
		$queue = new Queue( $queue_name );
600
601
		// False means that there was no lock to delete.
602
		$response = $queue->unlock();
603
		return rest_ensure_response(
604
			array(
605
				'success' => $response,
606
			)
607
		);
608
	}
609
610
	/**
611
	 * Checkin Sync actions.
612
	 *
613
	 * @since 9.9.0
614
	 *
615
	 * @param \WP_REST_Request $request The request sent to the WP REST API.
616
	 *
617
	 * @return \WP_REST_Response
618
	 */
619
	public static function close( $request ) {
620
621
		$request_body = $request->get_params();
622
		$queue_name   = self::validate_queue( $request_body['queue'] );
623
624
		if ( is_wp_error( $queue_name ) ) {
625
			return $queue_name;
626
		}
627
628
		if ( empty( $request_body['buffer_id'] ) ) {
629
			return new WP_Error( 'missing_buffer_id', 'Please provide a buffer id', 400 );
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'missing_buffer_id'.

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...
630
		}
631
632
		if ( ! is_array( $request_body['item_ids'] ) ) {
633
			return new WP_Error( 'missing_item_ids', 'Please provide a list of item ids in the item_ids argument', 400 );
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'missing_item_ids'.

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...
634
		}
635
636
		// Limit to A-Z,a-z,0-9,_,- .
637
		$request_body['buffer_id'] = preg_replace( '/[^A-Za-z0-9]/', '', $request_body['buffer_id'] );
638
		$request_body['item_ids']  = array_filter( array_map( array( 'Automattic\Jetpack\Sync\REST_Endpoints', 'sanitize_item_ids' ), $request_body['item_ids'] ) );
639
640
		$queue = new Queue( $queue_name );
0 ignored issues
show
Documentation introduced by
$queue_name is of type object<WP_Error>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
641
642
		$items = $queue->peek_by_id( $request_body['item_ids'] );
643
644
		// Update Full Sync Status if queue is "full_sync".
645
		if ( 'full_sync' === $queue_name ) {
646
			$full_sync_module = Modules::get_module( 'full-sync' );
647
			$full_sync_module->update_sent_progress_action( $items );
648
		}
649
650
		$buffer   = new Queue_Buffer( $request_body['buffer_id'], $request_body['item_ids'] );
651
		$response = $queue->close( $buffer, $request_body['item_ids'] );
0 ignored issues
show
Documentation introduced by
$buffer is of type object<Automattic\Jetpack\Sync\Queue_Buffer>, but the function expects a object<Automattic\Jetpac...pack\Sync\Queue_Buffer>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
652
653
		// Perform another checkout?
654 View Code Duplication
		if ( isset( $request_body['continue'] ) && $request_body['continue'] ) {
655
			if ( in_array( $queue_name, array( 'full_sync', 'immediate' ), true ) ) {
656
				// Send Full Sync Actions.
657
				Sender::get_instance()->do_full_sync();
658
			} else {
659
				// Send Incremental Sync Actions.
660
				if ( $queue->has_any_items() ) {
661
					Sender::get_instance()->do_sync();
662
				}
663
			}
664
		}
665
666
		if ( is_wp_error( $response ) ) {
667
			return $response;
668
		}
669
670
		return rest_ensure_response(
671
			array(
672
				'success' => $response,
673
				'status'  => Actions::get_sync_status(),
674
			)
675
		);
676
	}
677
678
	/**
679
	 * Retrieve range of Object Ids for a specified Sync module.
680
	 *
681
	 * @since 9.9.0
682
	 *
683
	 * @param \WP_REST_Request $request The request sent to the WP REST API.
684
	 *
685
	 * @return \WP_REST_Response
686
	 */
687
	public static function get_object_id_range( $request ) {
688
689
		$module_name = $request->get_param( 'sync_module' );
690
		$batch_size  = $request->get_param( 'batch_size' );
691
692
		if ( ! self::is_valid_sync_module( $module_name ) ) {
693
			return new WP_Error( 'invalid_module', 'This sync module cannot be used to calculate a range.', 400 );
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'invalid_module'.

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...
694
		}
695
		$module = Modules::get_module( $module_name );
696
697
		return rest_ensure_response(
698
			array(
699
				'ranges' => $module->get_min_max_object_ids_for_batches( $batch_size ),
700
			)
701
		);
702
	}
703
704
	/**
705
	 * Verify that request has default permissions to perform sync actions.
706
	 *
707
	 * @since 9.9.0
708
	 *
709
	 * @return bool Whether user has capability 'manage_options' or a blog token is used.
710
	 */
711
	public static function verify_default_permissions() {
712
		if ( current_user_can( 'manage_options' ) || Rest_Authentication::is_signed_with_blog_token() ) {
713
			return true;
714
		}
715
716
		$error_msg = esc_html__(
717
			'You do not have the correct user permissions to perform this action.
718
			Please contact your site admin if you think this is a mistake.',
719
			'jetpack'
720
		);
721
722
		return new WP_Error( 'invalid_user_permission_sync', $error_msg, array( 'status' => rest_authorization_required_code() ) );
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'invalid_user_permission_sync'.

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...
723
	}
724
725
	/**
726
	 * Validate Queue name.
727
	 *
728
	 * @param string $value Queue Name.
729
	 *
730
	 * @return WP_Error
731
	 */
732 View Code Duplication
	protected static function validate_queue( $value ) {
733
		if ( ! isset( $value ) ) {
734
			return new WP_Error( 'invalid_queue', 'Queue name is required', 400 );
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'invalid_queue'.

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...
735
		}
736
737
		if ( ! in_array( $value, array( 'sync', 'full_sync', 'immediate' ), true ) ) {
738
			return new WP_Error( 'invalid_queue', 'Queue name should be sync, full_sync or immediate', 400 );
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'invalid_queue'.

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...
739
		}
740
		return $value;
741
	}
742
743
	/**
744
	 * Validate name is a valid Sync module.
745
	 *
746
	 * @param string $module_name Name of Sync Module.
747
	 *
748
	 * @return bool
749
	 */
750 View Code Duplication
	protected static function is_valid_sync_module( $module_name ) {
751
		return in_array(
752
			$module_name,
753
			array(
754
				'comments',
755
				'posts',
756
				'terms',
757
				'term_relationships',
758
				'users',
759
			),
760
			true
761
		);
762
	}
763
764
	/**
765
	 * Sanitize Item Ids.
766
	 *
767
	 * @param string $item Sync item identifier.
768
	 *
769
	 * @return string|string[]|null
770
	 */
771 View Code Duplication
	protected static function sanitize_item_ids( $item ) {
772
		// lets not delete any options that don't start with jpsq_sync- .
773
		if ( ! is_string( $item ) || substr( $item, 0, 5 ) !== 'jpsq_' ) {
774
			return null;
775
		}
776
		// Limit to A-Z,a-z,0-9,_,-,. .
777
		return preg_replace( '/[^A-Za-z0-9-_.]/', '', $item );
778
	}
779
780
}
781