Completed
Push — renovate/url-polyfill-1.x ( 5173f2...caead9 )
by
unknown
55:58 queued 48:53
created

Jetpack_JSON_API_Sync_Close_Endpoint::result()   C

Complexity

Conditions 11
Paths 19

Size

Total Lines 57

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 11
nc 19
nop 0
dl 0
loc 57
rs 6.7915
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
use Automattic\Jetpack\Sync\Actions;
4
use Automattic\Jetpack\Sync\Modules;
5
use Automattic\Jetpack\Sync\Queue;
6
use Automattic\Jetpack\Sync\Queue_Buffer;
7
use Automattic\Jetpack\Sync\Replicastore;
8
use Automattic\Jetpack\Sync\Sender;
9
use Automattic\Jetpack\Sync\Settings;
10
11
// POST /sites/%s/sync
12
class Jetpack_JSON_API_Sync_Endpoint extends Jetpack_JSON_API_Endpoint {
13
	protected $needed_capabilities = 'manage_options';
14
15
	protected function validate_call( $_blog_id, $capability, $check_manage_active = true ) {
16
		return parent::validate_call( $_blog_id, $capability, false );
17
	}
18
19
	protected function result() {
20
		$args = $this->input();
21
		$modules = null;
22
23
		// convert list of modules in comma-delimited format into an array
24
		// of "$modulename => true"
25 View Code Duplication
		if ( isset( $args['modules'] ) && ! empty( $args['modules'] ) ) {
26
			$modules = array_map( '__return_true', array_flip( array_map( 'trim', explode( ',', $args['modules'] ) ) ) );
27
		}
28
29 View Code Duplication
		foreach ( array( 'posts', 'comments', 'users' ) as $module_name ) {
30
			if ( 'users' === $module_name && isset( $args[ $module_name ] ) && 'initial' === $args[ $module_name ] ) {
31
				$modules[ 'users' ] = 'initial';
32
			} elseif ( isset( $args[ $module_name ] ) ) {
33
				$ids = explode( ',', $args[ $module_name ] );
34
				if ( count( $ids ) > 0 ) {
35
					$modules[ $module_name ] = $ids;
36
				}
37
			}
38
		}
39
40
		if ( empty( $modules ) ) {
41
			$modules = null;
42
		}
43
		return array( 'scheduled' => Actions::do_full_sync( $modules ) );
44
	}
45
46
	protected function validate_queue( $query ) {
47
		if ( ! isset( $query ) ) {
48
			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...
49
		}
50
51 View Code Duplication
		if ( ! in_array( $query, array( 'sync', 'full_sync', 'immediate' ) ) ) {
52
			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...
53
		}
54
		return $query;
55
	}
56
}
57
58
// GET /sites/%s/sync/status
59
class Jetpack_JSON_API_Sync_Status_Endpoint extends Jetpack_JSON_API_Sync_Endpoint {
60
	protected function result() {
61
		$args   = $this->query_args();
62
		$fields = isset( $args['fields'] ) ? $args['fields'] : array();
63
		return Actions::get_sync_status( $fields );
64
	}
65
}
66
67
// GET /sites/%s/data-check
68
class Jetpack_JSON_API_Sync_Check_Endpoint extends Jetpack_JSON_API_Sync_Endpoint {
69
	protected function result() {
70
		$store = new Replicastore();
71
		return $store->checksum_all();
72
	}
73
}
74
75
// GET /sites/%s/data-histogram
76
class Jetpack_JSON_API_Sync_Histogram_Endpoint extends Jetpack_JSON_API_Sync_Endpoint {
77
	protected function result() {
78
		$args = $this->query_args();
79
80
		if ( isset( $args['columns'] ) ) {
81
			$columns = array_map( 'trim', explode( ',', $args['columns'] ) );
82
		} else {
83
			$columns = null; // go with defaults
84
		}
85
86
		$store = new Replicastore();
87
88
		if ( ! isset( $args['strip_non_ascii'] ) ) {
89
			$args['strip_non_ascii'] = true;
90
		}
91
		$histogram = $store->checksum_histogram( $args['object_type'], $args['buckets'], $args['start_id'], $args['end_id'], $columns, $args['strip_non_ascii'], $args['shared_salt'] );
92
93
		return array( 'histogram' => $histogram, 'type' => $store->get_checksum_type() );
94
	}
95
}
96
97
// POST /sites/%s/sync/settings
98
class Jetpack_JSON_API_Sync_Modify_Settings_Endpoint extends Jetpack_JSON_API_Sync_Endpoint {
99
	protected function result() {
100
		$args = $this->input();
101
102
		$sync_settings = Settings::get_settings();
103
104
		foreach ( $args as $key => $value ) {
105
			if ( $value !== false ) {
106
				if ( is_numeric( $value ) ) {
107
					$value = (int) $value;
108
				}
109
110
				// special case for sending empty arrays - a string with value 'empty'
111
				if ( $value === 'empty' ) {
112
					$value = array();
113
				}
114
115
				$sync_settings[ $key ] = $value;
116
			}
117
		}
118
119
		Settings::update_settings( $sync_settings );
120
121
		// re-fetch so we see what's really being stored
122
		return Settings::get_settings();
123
	}
124
}
125
126
// GET /sites/%s/sync/settings
127
class Jetpack_JSON_API_Sync_Get_Settings_Endpoint extends Jetpack_JSON_API_Sync_Endpoint {
128
	protected function result() {
129
130
		return Settings::get_settings();
131
	}
132
}
133
134
// GET /sites/%s/sync/object
135
class Jetpack_JSON_API_Sync_Object extends Jetpack_JSON_API_Sync_Endpoint {
136
	protected function result() {
137
		$args = $this->query_args();
138
139
		$module_name = $args['module_name'];
140
141
		if ( ! $sync_module = Modules::get_module( $module_name ) ) {
142
			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...
143
		}
144
145
		$object_type = $args['object_type'];
146
		$object_ids  = $args['object_ids'];
147
148
		$codec = Sender::get_instance()->get_codec();
149
150
		Settings::set_is_syncing( true );
151
		$objects = $codec->encode( $sync_module->get_objects_by_id( $object_type, $object_ids ) );
152
		Settings::set_is_syncing( false );
153
154
		return array(
155
			'objects' => $objects,
156
			'codec' => $codec->name(),
157
		);
158
	}
159
}
160
161
class Jetpack_JSON_API_Sync_Now_Endpoint extends Jetpack_JSON_API_Sync_Endpoint {
162
	protected function result() {
163
		$args = $this->input();
164
		$queue_name = $this->validate_queue( $args['queue'] );
165
166
		if ( is_wp_error( $queue_name ) ){
167
			return $queue_name;
168
		}
169
170
		$sender = Sender::get_instance();
171
		$response = $sender->do_sync_for_queue( new Queue( $args['queue'] ) );
0 ignored issues
show
Documentation introduced by
new \Automattic\Jetpack\...c\Queue($args['queue']) 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...
172
173
		return array(
174
			'response' => $response
175
		);
176
	}
177
}
178
179
class Jetpack_JSON_API_Sync_Checkout_Endpoint extends Jetpack_JSON_API_Sync_Endpoint {
180
	protected function result() {
181
		$args       = $this->input();
182
		$queue_name = $this->validate_queue( $args['queue'] );
183
184
		if ( is_wp_error( $queue_name ) ) {
185
			return $queue_name;
186
		}
187
188
		if ( $args['number_of_items'] < 1 || $args['number_of_items'] > 100 ) {
189
			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...
190
		}
191
192
		$number_of_items = absint( $args['number_of_items'] );
193
194
		if ( 'immediate' === $queue_name ) {
195
			return $this->immediate_full_sync_pull( $number_of_items );
196
		}
197
198
		return $this->queue_pull( $queue_name, $number_of_items, $args );
199
	}
200
201
	function queue_pull( $queue_name, $number_of_items, $args ){
202
		$queue = new Queue( $queue_name );
203
204
		if ( 0 === $queue->size() ) {
205
			return new WP_Error( 'queue_size', 'The queue is empty and there is nothing to send', 400 );
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'queue_size'.

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...
206
		}
207
208
		$sender = Sender::get_instance();
209
210
		// try to give ourselves as much time as possible.
211
		set_time_limit( 0 );
212
213
		if ( $args['pop'] ) {
214
			$buffer = new Queue_Buffer( 'pop', $queue->pop( $number_of_items ) );
0 ignored issues
show
Bug introduced by
It seems like $queue->pop($number_of_items) targeting Automattic\Jetpack\Sync\Queue::pop() can also be of type null or object; however, Automattic\Jetpack\Sync\...e_Buffer::__construct() does only seem to accept array, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
215
		} else {
216
			// let's delete the checkin state.
217
			if ( $args['force'] ) {
218
				$queue->unlock();
219
			}
220
			$buffer = $this->get_buffer( $queue, $number_of_items );
221
		}
222
		// Check that the $buffer is not checkout out already.
223
		if ( is_wp_error( $buffer ) ) {
224
			return new WP_Error( 'buffer_open', "We couldn't get the buffer it is currently checked out", 400 );
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'buffer_open'.

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...
225
		}
226
227
		if ( ! is_object( $buffer ) ) {
228
			return new WP_Error( 'buffer_non-object', 'Buffer is not an object', 400 );
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'buffer_non-object'.

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...
229
		}
230
231
		Settings::set_is_syncing( true );
232
		list( $items_to_send, $skipped_items_ids ) = $sender->get_items_to_send( $buffer, $args['encode'] );
233
		Settings::set_is_syncing( false );
234
235
		return array(
236
			'buffer_id'      => $buffer->id,
237
			'items'          => $items_to_send,
238
			'skipped_items'  => $skipped_items_ids,
239
			'codec'          => $args['encode'] ? $sender->get_codec()->name() : null,
240
			'sent_timestamp' => time(),
241
		);
242
	}
243
244
	public $items = [];
245
246
	public function jetpack_sync_send_data_listener() {
247
		foreach ( func_get_args()[0] as $key => $item ) {
248
			$this->items[ $key ] = $item;
249
		}
250
	}
251
252
	/**
253
	 * Check out a buffer of full sync actions.
254
	 *
255
	 * @param null $number_of_items Number of Actions to check-out.
256
	 *
257
	 * @return array Sync Actions to be returned to requestor
258
	 */
259
	public function immediate_full_sync_pull( $number_of_items = null ) {
260
		// try to give ourselves as much time as possible.
261
		set_time_limit( 0 );
262
263
		$original_send_data_cb = array( 'Automattic\Jetpack\Sync\Actions', 'send_data' );
264
		$temp_send_data_cb     = array( $this, 'jetpack_sync_send_data_listener' );
265
266
		Sender::get_instance()->set_enqueue_wait_time( 0 );
267
		remove_filter( 'jetpack_sync_send_data', $original_send_data_cb );
268
		add_filter( 'jetpack_sync_send_data', $temp_send_data_cb, 10, 6 );
269
		Sender::get_instance()->do_full_sync();
270
		remove_filter( 'jetpack_sync_send_data', $temp_send_data_cb );
271
		add_filter( 'jetpack_sync_send_data', $original_send_data_cb, 10, 6 );
272
273
		return array(
274
			'items'          => $this->items,
275
			'codec'          => Sender::get_instance()->get_codec()->name(),
276
			'sent_timestamp' => time(),
277
			'status'         => Actions::get_sync_status(),
278
		);
279
	}
280
281
	protected function get_buffer( $queue, $number_of_items ) {
282
		$start = time();
283
		$max_duration = 5; // this will try to get the buffer
284
285
		$buffer = $queue->checkout( $number_of_items );
286
		$duration = time() - $start;
287
288
		while( is_wp_error( $buffer ) && $duration < $max_duration ) {
289
			sleep( 2 );
290
			$duration = time() - $start;
291
			$buffer = $queue->checkout( $number_of_items );
292
		}
293
294
		if ( $buffer === false ) {
295
			return new WP_Error( 'queue_size', 'The queue is empty and there is nothing to send', 400 );
0 ignored issues
show
Unused Code introduced by
The call to WP_Error::__construct() has too many arguments starting with 'queue_size'.

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...
296
		}
297
298
		return $buffer;
299
	}
300
}
301
302
class Jetpack_JSON_API_Sync_Close_Endpoint extends Jetpack_JSON_API_Sync_Endpoint {
303
	protected function result() {
304
305
		$request_body = $this->input();
306
		$queue_name = $this->validate_queue( $request_body['queue'] );
307
308
		if ( is_wp_error( $queue_name ) ) {
309
			return $queue_name;
310
		}
311
312
		if ( ! isset( $request_body['buffer_id'] ) ) {
313
			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...
314
		}
315
316
		if ( ! isset( $request_body['item_ids'] ) || ! is_array( $request_body['item_ids'] ) ) {
317
			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...
318
		}
319
320
		//Limit to A-Z,a-z,0-9,_,-
321
		$request_body ['buffer_id'] = preg_replace( '/[^A-Za-z0-9]/', '', $request_body['buffer_id'] );
322
		$request_body['item_ids'] = array_filter( array_map( array( 'Jetpack_JSON_API_Sync_Close_Endpoint', 'sanitize_item_ids' ), $request_body['item_ids'] ) );
323
324
		$queue = new Queue( $queue_name );
325
326
		$items = $queue->peek_by_id( $request_body['item_ids'] );
327
328
		// Update Full Sync Status if queue is "full_sync".
329
		if ( 'full_sync' === $queue_name ) {
330
			$full_sync_module = Modules::get_module( 'full-sync' );
331
332
			$full_sync_module->update_sent_progress_action( $items );
333
		}
334
335
		$buffer = new Queue_Buffer( $request_body['buffer_id'], $request_body['item_ids'] );
336
		$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...
337
338
		// Perform another checkout?
339
		if ( isset( $request_body['continue'] ) && $request_body['continue'] ) {
340
			if ( in_array( $queue_name, array( 'full_sync', 'immediate' ), true ) ) {
341
				// Send Full Sync Actions.
342
				Sender::get_instance()->do_full_sync();
343
			} else {
344
				// Send Incremental Sync Actions.
345
				if ( $queue->has_any_items() ) {
346
					Sender::get_instance()->do_sync();
347
				}
348
			}
349
		}
350
351
		if ( is_wp_error( $response ) ) {
352
			return $response;
353
		}
354
355
		return array(
356
			'success' => $response,
357
			'status' => Actions::get_sync_status(),
358
		);
359
	}
360
361
	protected static function sanitize_item_ids( $item ) {
362
		// lets not delete any options that don't start with jpsq_sync-
363
		if ( substr( $item, 0, 5 ) !== 'jpsq_' ) {
364
			return null;
365
		}
366
		//Limit to A-Z,a-z,0-9,_,-,.
367
		return preg_replace( '/[^A-Za-z0-9-_.]/', '', $item );
368
	}
369
}
370
371
class Jetpack_JSON_API_Sync_Unlock_Endpoint extends Jetpack_JSON_API_Sync_Endpoint {
372
	protected function result() {
373
		$args = $this->input();
374
375
		if ( ! isset( $args['queue'] ) ) {
376
			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...
377
		}
378
379 View Code Duplication
		if ( ! in_array( $args['queue'], array( 'sync', 'full_sync' ) ) ) {
380
			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...
381
		}
382
383
		$queue = new Queue( $args['queue'] );
384
385
		// False means that there was no lock to delete.
386
		$response = $queue->unlock();
387
		return array(
388
			'success' => $response
389
		);
390
	}
391
}
392
393
class Jetpack_JSON_API_Sync_Object_Id_Range extends Jetpack_JSON_API_Sync_Endpoint {
394
	protected function result() {
395
		$args = $this->query_args();
396
397
		$module_name = $args['sync_module'];
398
		$batch_size  = $args['batch_size'];
399
400
		if ( ! $this->is_valid_sync_module( $module_name ) ) {
401
			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...
402
		}
403
404
		$module = Modules::get_module( $module_name );
405
406
		return array(
407
			'ranges' => $module->get_min_max_object_ids_for_batches( $batch_size ),
408
		);
409
	}
410
411
	protected function is_valid_sync_module( $module_name ) {
412
		return in_array(
413
			$module_name,
414
			array(
415
				'comments',
416
				'posts',
417
				'terms',
418
				'term_relationships',
419
				'users',
420
			),
421
			true
422
		);
423
	}
424
}
425