Completed
Push — instant-search-master-without-... ( 38a5d0...b8a2f9 )
by
unknown
14:17 queued 08:07
created

Jetpack_JSON_API_Sync_Checkout_Endpoint::result()   B

Complexity

Conditions 10
Paths 15

Size

Total Lines 55

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 10
nc 15
nop 0
dl 0
loc 55
rs 7.1151
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
		if ( ! in_array( $query, array( 'sync', 'full_sync' ) ) ) {
52
			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...
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
		$queue = new Queue( $queue_name );
195
196
		if ( 0 === $queue->size() ) {
197
			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...
198
		}
199
200
		$sender = Sender::get_instance();
201
202
		// try to give ourselves as much time as possible.
203
		set_time_limit( 0 );
204
205
		if ( $args['pop'] ) {
206
			$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...
207
		} else {
208
			// let's delete the checkin state.
209
			if ( $args['force'] ) {
210
				$queue->unlock();
211
			}
212
			$buffer = $this->get_buffer( $queue, $number_of_items );
213
		}
214
		// Check that the $buffer is not checkout out already.
215
		if ( is_wp_error( $buffer ) ) {
216
			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...
217
		}
218
219
		if ( ! is_object( $buffer ) ) {
220
			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...
221
		}
222
223
		Settings::set_is_syncing( true );
224
		list( $items_to_send, $skipped_items_ids ) = $sender->get_items_to_send( $buffer, $args['encode'] );
225
		Settings::set_is_syncing( false );
226
227
		return array(
228
			'buffer_id'      => $buffer->id,
229
			'items'          => $items_to_send,
230
			'skipped_items'  => $skipped_items_ids,
231
			'codec'          => $args['encode'] ? $sender->get_codec()->name() : null,
232
			'sent_timestamp' => time(),
233
		);
234
	}
235
236
	protected function get_buffer( $queue, $number_of_items ) {
237
		$start = time();
238
		$max_duration = 5; // this will try to get the buffer
239
240
		$buffer = $queue->checkout( $number_of_items );
241
		$duration = time() - $start;
242
243
		while( is_wp_error( $buffer ) && $duration < $max_duration ) {
244
			sleep( 2 );
245
			$duration = time() - $start;
246
			$buffer = $queue->checkout( $number_of_items );
247
		}
248
249
		if ( $buffer === false ) {
250
			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...
251
		}
252
253
		return $buffer;
254
	}
255
}
256
257
class Jetpack_JSON_API_Sync_Close_Endpoint extends Jetpack_JSON_API_Sync_Endpoint {
258
	protected function result() {
259
		$request_body = $this->input();
260
		$queue_name = $this->validate_queue( $request_body['queue'] );
261
262
		if ( is_wp_error( $queue_name ) ) {
263
			return $queue_name;
264
		}
265
266
		if ( ! isset( $request_body['buffer_id'] ) ) {
267
			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...
268
		}
269
270
		if ( ! isset( $request_body['item_ids'] ) || ! is_array( $request_body['item_ids'] ) ) {
271
			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...
272
		}
273
274
		//Limit to A-Z,a-z,0-9,_,-
275
		$request_body ['buffer_id'] = preg_replace( '/[^A-Za-z0-9]/', '', $request_body['buffer_id'] );
276
		$request_body['item_ids'] = array_filter( array_map( array( 'Jetpack_JSON_API_Sync_Close_Endpoint', 'sanitize_item_ids' ), $request_body['item_ids'] ) );
277
278
		$queue = new Queue( $queue_name );
279
280
		$items = $queue->peek_by_id( $request_body['item_ids'] );
281
282
		/** This action is documented in packages/sync/src/modules/Full_Sync.php */
283
		$full_sync_module = Modules::get_module( 'full-sync' );
284
285
		$full_sync_module->update_sent_progress_action( $items );
286
287
		$buffer = new Queue_Buffer( $request_body['buffer_id'], $request_body['item_ids'] );
288
		$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...
289
290
		if ( is_wp_error( $response ) ) {
291
			return $response;
292
		}
293
294
		return array(
295
			'success' => $response,
296
			'status' => Actions::get_sync_status(),
297
		);
298
	}
299
300
	protected static function sanitize_item_ids( $item ) {
301
		// lets not delete any options that don't start with jpsq_sync-
302
		if ( substr( $item, 0, 5 ) !== 'jpsq_' ) {
303
			return null;
304
		}
305
		//Limit to A-Z,a-z,0-9,_,-,.
306
		return preg_replace( '/[^A-Za-z0-9-_.]/', '', $item );
307
	}
308
}
309
310
class Jetpack_JSON_API_Sync_Unlock_Endpoint extends Jetpack_JSON_API_Sync_Endpoint {
311
	protected function result() {
312
		$args = $this->input();
313
314
		if ( ! isset( $args['queue'] ) ) {
315
			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...
316
		}
317
318
		if ( ! in_array( $args['queue'], array( 'sync', 'full_sync' ) ) ) {
319
			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...
320
		}
321
322
		$queue = new Queue( $args['queue'] );
323
324
		// False means that there was no lock to delete.
325
		$response = $queue->unlock();
326
		return array(
327
			'success' => $response
328
		);
329
	}
330
}
331
332
class Jetpack_JSON_API_Sync_Object_Id_Range extends Jetpack_JSON_API_Sync_Endpoint {
333
	protected function result() {
334
		$args = $this->query_args();
335
336
		$module_name = $args['sync_module'];
337
		$batch_size  = $args['batch_size'];
338
339
		if ( ! $this->is_valid_sync_module( $module_name ) ) {
340
			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...
341
		}
342
343
		$module = Modules::get_module( $module_name );
344
345
		return array(
346
			'ranges' => $module->get_min_max_object_ids_for_batches( $batch_size ),
347
		);
348
	}
349
350
	protected function is_valid_sync_module( $module_name ) {
351
		return in_array(
352
			$module_name,
353
			array(
354
				'comments',
355
				'posts',
356
				'terms',
357
				'term_relationships',
358
				'users',
359
			),
360
			true
361
		);
362
	}
363
}
364