Completed
Push — add/eta-to-sync-status ( d17f42...551096 )
by
unknown
06:17
created

Posts::get_sync_speed()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * Posts sync module.
4
 *
5
 * @package automattic/jetpack-sync
6
 */
7
8
namespace Automattic\Jetpack\Sync\Modules;
9
10
use Automattic\Jetpack\Constants as Jetpack_Constants;
11
use Automattic\Jetpack\Roles;
12
use Automattic\Jetpack\Sync\Settings;
13
14
/**
15
 * Class to handle sync for posts.
16
 */
17
class Posts extends Module {
18
	/**
19
	 *  An estimate of how many rows per second can be synced during a full sync.
20
	 *
21
	 * @access static
22
	 *
23
	 * @var int|null Null if speed is not important in a full sync.
24
	 */
25
	static $sync_speed = 7;
26
	/**
27
	 * The post IDs of posts that were just published but not synced yet.
28
	 *
29
	 * @access private
30
	 *
31
	 * @var array
32
	 */
33
	private $just_published = array();
34
35
	/**
36
	 * The previous status of posts that we use for calculating post status transitions.
37
	 *
38
	 * @access private
39
	 *
40
	 * @var array
41
	 */
42
	private $previous_status = array();
43
44
	/**
45
	 * Action handler callable.
46
	 *
47
	 * @access private
48
	 *
49
	 * @var callable
50
	 */
51
	private $action_handler;
52
53
	/**
54
	 * Import end.
55
	 *
56
	 * @access private
57
	 *
58
	 * @todo This appears to be unused - let's remove it.
59
	 *
60
	 * @var boolean
61
	 */
62
	private $import_end = false;
63
64
	/**
65
	 * Default previous post state.
66
	 * Used for default previous post status.
67
	 *
68
	 * @access public
69
	 *
70
	 * @var string
71
	 */
72
	const DEFAULT_PREVIOUS_STATE = 'new';
73
74
	/**
75
	 * Sync module name.
76
	 *
77
	 * @access public
78
	 *
79
	 * @return string
80
	 */
81
	public function name() {
82
		return 'posts';
83
	}
84
85
	/**
86
	 * The table in the database.
87
	 *
88
	 * @access public
89
	 *
90
	 * @return string
91
	 */
92
	public function table_name() {
93
		return 'posts';
94
	}
95
96
	/**
97
	 * Retrieve a post by its ID.
98
	 *
99
	 * @access public
100
	 *
101
	 * @param string $object_type Type of the sync object.
102
	 * @param int    $id          ID of the sync object.
103
	 * @return \WP_Post|bool Filtered \WP_Post object, or false if the object is not a post.
104
	 */
105
	public function get_object_by_id( $object_type, $id ) {
106
		if ( 'post' === $object_type ) {
107
			$post = get_post( intval( $id ) );
108
			if ( $post ) {
109
				return $this->filter_post_content_and_add_links( $post );
110
			}
111
		}
112
113
		return false;
114
	}
115
116
	/**
117
	 * Initialize posts action listeners.
118
	 *
119
	 * @access public
120
	 *
121
	 * @param callable $callable Action handler callable.
122
	 */
123
	public function init_listeners( $callable ) {
124
		$this->action_handler = $callable;
125
126
		add_action( 'wp_insert_post', array( $this, 'wp_insert_post' ), 11, 3 );
127
		add_action( 'jetpack_sync_save_post', $callable, 10, 4 );
128
129
		add_action( 'deleted_post', $callable, 10 );
130
		add_action( 'jetpack_published_post', $callable, 10, 2 );
131
132
		add_action( 'transition_post_status', array( $this, 'save_published' ), 10, 3 );
133
		add_filter( 'jetpack_sync_before_enqueue_jetpack_sync_save_post', array( $this, 'filter_blacklisted_post_types' ) );
134
135
		// Listen for meta changes.
136
		$this->init_listeners_for_meta_type( 'post', $callable );
137
		$this->init_meta_whitelist_handler( 'post', array( $this, 'filter_meta' ) );
138
139
		add_action( 'jetpack_daily_akismet_meta_cleanup_before', array( $this, 'daily_akismet_meta_cleanup_before' ) );
140
		add_action( 'jetpack_daily_akismet_meta_cleanup_after', array( $this, 'daily_akismet_meta_cleanup_after' ) );
141
		add_action( 'jetpack_post_meta_batch_delete', $callable, 10, 2 );
142
	}
143
144
	/**
145
	 * Before Akismet's daily cleanup of spam detection metadata.
146
	 *
147
	 * @access public
148
	 *
149
	 * @param array $feedback_ids IDs of feedback posts.
150
	 */
151
	public function daily_akismet_meta_cleanup_before( $feedback_ids ) {
152
		remove_action( 'deleted_post_meta', $this->action_handler );
153
		/**
154
		 * Used for syncing deletion of batch post meta
155
		 *
156
		 * @since 6.1.0
157
		 *
158
		 * @module sync
159
		 *
160
		 * @param array $feedback_ids feedback post IDs
161
		 * @param string $meta_key to be deleted
162
		 */
163
		do_action( 'jetpack_post_meta_batch_delete', $feedback_ids, '_feedback_akismet_values' );
164
	}
165
166
	/**
167
	 * After Akismet's daily cleanup of spam detection metadata.
168
	 *
169
	 * @access public
170
	 *
171
	 * @param array $feedback_ids IDs of feedback posts.
172
	 */
173
	public function daily_akismet_meta_cleanup_after( $feedback_ids ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
174
		add_action( 'deleted_post_meta', $this->action_handler );
175
	}
176
177
	/**
178
	 * Initialize posts action listeners for full sync.
179
	 *
180
	 * @access public
181
	 *
182
	 * @param callable $callable Action handler callable.
183
	 */
184
	public function init_full_sync_listeners( $callable ) {
185
		add_action( 'jetpack_full_sync_posts', $callable ); // Also sends post meta.
186
	}
187
188
	/**
189
	 * Initialize the module in the sender.
190
	 *
191
	 * @access public
192
	 */
193
	public function init_before_send() {
194
		add_filter( 'jetpack_sync_before_send_jetpack_sync_save_post', array( $this, 'expand_jetpack_sync_save_post' ) );
195
196
		// Full sync.
197
		add_filter( 'jetpack_sync_before_send_jetpack_full_sync_posts', array( $this, 'expand_post_ids' ) );
198
	}
199
200
	/**
201
	 * Enqueue the posts actions for full sync.
202
	 *
203
	 * @access public
204
	 *
205
	 * @param array   $config               Full sync configuration for this sync module.
206
	 * @param int     $max_items_to_enqueue Maximum number of items to enqueue.
207
	 * @param boolean $state                True if full sync has finished enqueueing this module, false otherwise.
208
	 * @return array Number of actions enqueued, and next module state.
209
	 */
210
	public function enqueue_full_sync_actions( $config, $max_items_to_enqueue, $state ) {
211
		global $wpdb;
212
213
		return $this->enqueue_all_ids_as_action( 'jetpack_full_sync_posts', $wpdb->posts, 'ID', $this->get_where_sql( $config ), $max_items_to_enqueue, $state );
214
	}
215
216
	/**
217
	 * Retrieve an estimated number of actions that will be enqueued.
218
	 *
219
	 * @access public
220
	 *
221
	 * @todo Use $wpdb->prepare for the SQL query.
222
	 *
223
	 * @param array $config Full sync configuration for this sync module.
224
	 * @return array Number of items yet to be enqueued.
225
	 */
226 View Code Duplication
	public function estimate_full_sync_actions( $config ) {
227
		global $wpdb;
228
229
		$query = "SELECT count(*) FROM $wpdb->posts WHERE " . $this->get_where_sql( $config );
230
		// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
231
		$count = $wpdb->get_var( $query );
232
233
		return (int) ceil( $count / self::ARRAY_CHUNK_SIZE );
234
	}
235
236
	/**
237
	 * Retrieve the WHERE SQL clause based on the module config.
238
	 *
239
	 * @access public
240
	 *
241
	 * @param array $config Full sync configuration for this sync module.
242
	 * @return string WHERE SQL clause, or `null` if no comments are specified in the module config.
243
	 */
244 View Code Duplication
	public function get_where_sql( $config ) {
245
		$where_sql = Settings::get_blacklisted_post_types_sql();
246
247
		// Config is a list of post IDs to sync.
248
		if ( is_array( $config ) ) {
249
			$where_sql .= ' AND ID IN (' . implode( ',', array_map( 'intval', $config ) ) . ')';
250
		}
251
252
		return $where_sql;
253
	}
254
255
	/**
256
	 * Retrieve the actions that will be sent for this module during a full sync.
257
	 *
258
	 * @access public
259
	 *
260
	 * @return array Full sync actions of this module.
261
	 */
262
	public function get_full_sync_actions() {
263
		return array( 'jetpack_full_sync_posts' );
264
	}
265
266
	/**
267
	 * Process content before send.
268
	 *
269
	 * @param array $args Arguments of the `wp_insert_post` hook.
270
	 *
271
	 * @return array
272
	 */
273
	public function expand_jetpack_sync_save_post( $args ) {
274
		list( $post_id, $post, $update, $previous_state ) = $args;
275
		return array( $post_id, $this->filter_post_content_and_add_links( $post ), $update, $previous_state );
276
	}
277
278
	/**
279
	 * Filter all blacklisted post types.
280
	 *
281
	 * @param array $args Hook arguments.
282
	 * @return array|false Hook arguments, or false if the post type is a blacklisted one.
283
	 */
284
	public function filter_blacklisted_post_types( $args ) {
285
		$post = $args[1];
286
287
		if ( in_array( $post->post_type, Settings::get_setting( 'post_types_blacklist' ), true ) ) {
288
			return false;
289
		}
290
291
		return $args;
292
	}
293
294
	/**
295
	 * Filter all meta that is not blacklisted, or is stored for a disallowed post type.
296
	 *
297
	 * @param array $args Hook arguments.
298
	 * @return array|false Hook arguments, or false if meta was filtered.
299
	 */
300
	public function filter_meta( $args ) {
301
		if ( $this->is_post_type_allowed( $args[1] ) && $this->is_whitelisted_post_meta( $args[2] ) ) {
302
			return $args;
303
		}
304
305
		return false;
306
	}
307
308
	/**
309
	 * Whether a post meta key is whitelisted.
310
	 *
311
	 * @param string $meta_key Meta key.
312
	 * @return boolean Whether the post meta key is whitelisted.
313
	 */
314
	public function is_whitelisted_post_meta( $meta_key ) {
315
		// The _wpas_skip_ meta key is used by Publicize.
316
		return in_array( $meta_key, Settings::get_setting( 'post_meta_whitelist' ), true ) || wp_startswith( $meta_key, '_wpas_skip_' );
317
	}
318
319
	/**
320
	 * Whether a post type is allowed.
321
	 * A post type will be disallowed if it's present in the post type blacklist.
322
	 *
323
	 * @param int $post_id ID of the post.
324
	 * @return boolean Whether the post type is allowed.
325
	 */
326
	public function is_post_type_allowed( $post_id ) {
327
		$post = get_post( intval( $post_id ) );
328
329
		if ( isset( $post->post_type ) ) {
330
			return ! in_array( $post->post_type, Settings::get_setting( 'post_types_blacklist' ), true );
331
		}
332
		return false;
333
	}
334
335
	/**
336
	 * Remove the embed shortcode.
337
	 *
338
	 * @global $wp_embed
339
	 */
340 View Code Duplication
	public function remove_embed() {
341
		global $wp_embed;
342
		remove_filter( 'the_content', array( $wp_embed, 'run_shortcode' ), 8 );
343
		// remove the embed shortcode since we would do the part later.
344
		remove_shortcode( 'embed' );
345
		// Attempts to embed all URLs in a post.
346
		remove_filter( 'the_content', array( $wp_embed, 'autoembed' ), 8 );
347
	}
348
349
	/**
350
	 * Add the embed shortcode.
351
	 *
352
	 * @global $wp_embed
353
	 */
354 View Code Duplication
	public function add_embed() {
355
		global $wp_embed;
356
		add_filter( 'the_content', array( $wp_embed, 'run_shortcode' ), 8 );
357
		// Shortcode placeholder for strip_shortcodes().
358
		add_shortcode( 'embed', '__return_false' );
359
		// Attempts to embed all URLs in a post.
360
		add_filter( 'the_content', array( $wp_embed, 'autoembed' ), 8 );
361
	}
362
363
	/**
364
	 * Expands wp_insert_post to include filtered content
365
	 *
366
	 * @param \WP_Post $post_object Post object.
367
	 */
368
	public function filter_post_content_and_add_links( $post_object ) {
369
		global $post;
370
		// phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
371
		$post = $post_object;
372
373
		// Return non existant post.
374
		$post_type = get_post_type_object( $post->post_type );
375 View Code Duplication
		if ( empty( $post_type ) || ! is_object( $post_type ) ) {
376
			$non_existant_post                    = new \stdClass();
377
			$non_existant_post->ID                = $post->ID;
378
			$non_existant_post->post_modified     = $post->post_modified;
379
			$non_existant_post->post_modified_gmt = $post->post_modified_gmt;
380
			$non_existant_post->post_status       = 'jetpack_sync_non_registered_post_type';
381
			$non_existant_post->post_type         = $post->post_type;
382
383
			return $non_existant_post;
384
		}
385
		/**
386
		 * Filters whether to prevent sending post data to .com
387
		 *
388
		 * Passing true to the filter will prevent the post data from being sent
389
		 * to the WordPress.com.
390
		 * Instead we pass data that will still enable us to do a checksum against the
391
		 * Jetpacks data but will prevent us from displaying the data on in the API as well as
392
		 * other services.
393
		 *
394
		 * @since 4.2.0
395
		 *
396
		 * @param boolean false prevent post data from being synced to WordPress.com
397
		 * @param mixed $post \WP_Post object
398
		 */
399 View Code Duplication
		if ( apply_filters( 'jetpack_sync_prevent_sending_post_data', false, $post ) ) {
400
			// We only send the bare necessary object to be able to create a checksum.
401
			$blocked_post                    = new \stdClass();
402
			$blocked_post->ID                = $post->ID;
403
			$blocked_post->post_modified     = $post->post_modified;
404
			$blocked_post->post_modified_gmt = $post->post_modified_gmt;
405
			$blocked_post->post_status       = 'jetpack_sync_blocked';
406
			$blocked_post->post_type         = $post->post_type;
407
408
			return $blocked_post;
409
		}
410
411
		// lets not do oembed just yet.
412
		$this->remove_embed();
413
414
		if ( 0 < strlen( $post->post_password ) ) {
415
			$post->post_password = 'auto-' . wp_generate_password( 10, false );
416
		}
417
418
		/** This filter is already documented in core. wp-includes/post-template.php */
419
		if ( Settings::get_setting( 'render_filtered_content' ) && $post_type->public ) {
420
			global $shortcode_tags;
421
			/**
422
			 * Filter prevents some shortcodes from expanding.
423
			 *
424
			 * Since we can can expand some type of shortcode better on the .com side and make the
425
			 * expansion more relevant to contexts. For example [galleries] and subscription emails
426
			 *
427
			 * @since 4.5.0
428
			 *
429
			 * @param array of shortcode tags to remove.
430
			 */
431
			$shortcodes_to_remove        = apply_filters(
432
				'jetpack_sync_do_not_expand_shortcodes',
433
				array(
434
					'gallery',
435
					'slideshow',
436
				)
437
			);
438
			$removed_shortcode_callbacks = array();
439
			foreach ( $shortcodes_to_remove as $shortcode ) {
440
				if ( isset( $shortcode_tags[ $shortcode ] ) ) {
441
					$removed_shortcode_callbacks[ $shortcode ] = $shortcode_tags[ $shortcode ];
442
				}
443
			}
444
445
			array_map( 'remove_shortcode', array_keys( $removed_shortcode_callbacks ) );
446
447
			$post->post_content_filtered = apply_filters( 'the_content', $post->post_content );
448
			$post->post_excerpt_filtered = apply_filters( 'the_excerpt', $post->post_excerpt );
449
450
			foreach ( $removed_shortcode_callbacks as $shortcode => $callback ) {
451
				add_shortcode( $shortcode, $callback );
452
			}
453
		}
454
455
		$this->add_embed();
456
457
		if ( has_post_thumbnail( $post->ID ) ) {
458
			$image_attributes = wp_get_attachment_image_src( get_post_thumbnail_id( $post->ID ), 'full' );
459
			if ( is_array( $image_attributes ) && isset( $image_attributes[0] ) ) {
460
				$post->featured_image = $image_attributes[0];
461
			}
462
		}
463
464
		$post->permalink = get_permalink( $post->ID );
465
		$post->shortlink = wp_get_shortlink( $post->ID );
466
467
		if ( function_exists( 'amp_get_permalink' ) ) {
468
			$post->amp_permalink = amp_get_permalink( $post->ID );
469
		}
470
471
		return $post;
472
	}
473
474
	/**
475
	 * Handle transition from another post status to a published one.
476
	 *
477
	 * @param string   $new_status New post status.
478
	 * @param string   $old_status Old post status.
479
	 * @param \WP_Post $post       Post object.
480
	 */
481
	public function save_published( $new_status, $old_status, $post ) {
482
		if ( 'publish' === $new_status && 'publish' !== $old_status ) {
483
			$this->just_published[ $post->ID ] = true;
484
		}
485
486
		$this->previous_status[ $post->ID ] = $old_status;
487
	}
488
489
	/**
490
	 * When publishing or updating a post, the Gutenberg editor sends two requests:
491
	 * 1. sent to WP REST API endpoint `wp-json/wp/v2/posts/$id`
492
	 * 2. sent to wp-admin/post.php `?post=$id&action=edit&classic-editor=1&meta_box=1`
493
	 *
494
	 * The 2nd request is to update post meta, which is not supported on WP REST API.
495
	 * When syncing post data, we will include if this was a meta box update.
496
	 *
497
	 * @todo Implement nonce verification.
498
	 *
499
	 * @return boolean Whether this is a Gutenberg meta box update.
500
	 */
501
	public function is_gutenberg_meta_box_update() {
502
		// phpcs:disable WordPress.Security.NonceVerification.Missing, WordPress.Security.NonceVerification.Recommended
503
		return (
504
			isset( $_POST['action'], $_GET['classic-editor'], $_GET['meta_box'] ) &&
505
			'editpost' === $_POST['action'] &&
506
			'1' === $_GET['classic-editor'] &&
507
			'1' === $_GET['meta_box']
508
			// phpcs:enable WordPress.Security.NonceVerification.Missing, WordPress.Security.NonceVerification.Recommended
509
		);
510
	}
511
512
	/**
513
	 * Handler for the wp_insert_post hook.
514
	 * Called upon creation of a new post.
515
	 *
516
	 * @param int      $post_ID Post ID.
0 ignored issues
show
Documentation introduced by
Should the type for parameter $post not be \WP_Post|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...
517
	 * @param \WP_Post $post    Post object.
518
	 * @param boolean  $update  Whether this is an existing post being updated or not.
0 ignored issues
show
Documentation introduced by
Should the type for parameter $update not be boolean|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...
519
	 */
520
	public function wp_insert_post( $post_ID, $post = null, $update = null ) {
521
		if ( ! is_numeric( $post_ID ) || is_null( $post ) ) {
522
			return;
523
		}
524
525
		// Workaround for https://github.com/woocommerce/woocommerce/issues/18007.
526
		if ( $post && 'shop_order' === $post->post_type ) {
527
			$post = get_post( $post_ID );
528
		}
529
530
		$previous_status = isset( $this->previous_status[ $post_ID ] ) ?
531
			$this->previous_status[ $post_ID ] :
532
			self::DEFAULT_PREVIOUS_STATE;
533
534
		$just_published = isset( $this->just_published[ $post_ID ] ) ?
535
			$this->just_published[ $post_ID ] :
536
			false;
537
538
		$state = array(
539
			'is_auto_save'                 => (bool) Jetpack_Constants::get_constant( 'DOING_AUTOSAVE' ),
540
			'previous_status'              => $previous_status,
541
			'just_published'               => $just_published,
542
			'is_gutenberg_meta_box_update' => $this->is_gutenberg_meta_box_update(),
543
		);
544
		/**
545
		 * Filter that is used to add to the post flags ( meta data ) when a post gets published
546
		 *
547
		 * @since 5.8.0
548
		 *
549
		 * @param int $post_ID the post ID
550
		 * @param mixed $post \WP_Post object
551
		 * @param bool  $update Whether this is an existing post being updated or not.
552
		 * @param mixed $state state
553
		 *
554
		 * @module sync
555
		 */
556
		do_action( 'jetpack_sync_save_post', $post_ID, $post, $update, $state );
557
		unset( $this->previous_status[ $post_ID ] );
558
		$this->send_published( $post_ID, $post );
559
	}
560
561
	/**
562
	 * Send a published post for sync.
563
	 *
564
	 * @param int      $post_ID Post ID.
565
	 * @param \WP_Post $post    Post object.
566
	 */
567
	public function send_published( $post_ID, $post ) {
568
		if ( ! isset( $this->just_published[ $post_ID ] ) ) {
569
			return;
570
		}
571
572
		// Post revisions cause race conditions where this send_published add the action before the actual post gets synced.
573
		if ( wp_is_post_autosave( $post ) || wp_is_post_revision( $post ) ) {
574
			return;
575
		}
576
577
		$post_flags = array(
578
			'post_type' => $post->post_type,
579
		);
580
581
		$author_user_object = get_user_by( 'id', $post->post_author );
582
		if ( $author_user_object ) {
583
			$roles = new Roles();
584
585
			$post_flags['author'] = array(
586
				'id'              => $post->post_author,
587
				'wpcom_user_id'   => get_user_meta( $post->post_author, 'wpcom_user_id', true ),
588
				'display_name'    => $author_user_object->display_name,
589
				'email'           => $author_user_object->user_email,
590
				'translated_role' => $roles->translate_user_to_role( $author_user_object ),
591
			);
592
		}
593
594
		/**
595
		 * Filter that is used to add to the post flags ( meta data ) when a post gets published
596
		 *
597
		 * @since 4.4.0
598
		 *
599
		 * @param mixed array post flags that are added to the post
600
		 * @param mixed $post \WP_Post object
601
		 */
602
		$flags = apply_filters( 'jetpack_published_post_flags', $post_flags, $post );
603
604
		/**
605
		 * Action that gets synced when a post type gets published.
606
		 *
607
		 * @since 4.4.0
608
		 *
609
		 * @param int $post_ID
610
		 * @param mixed array $flags post flags that are added to the post
611
		 */
612
		do_action( 'jetpack_published_post', $post_ID, $flags );
613
		unset( $this->just_published[ $post_ID ] );
614
615
		/**
616
		 * Send additional sync action for Activity Log when post is a Customizer publish
617
		 */
618
		if ( 'customize_changeset' === $post->post_type ) {
619
			$post_content = json_decode( $post->post_content, true );
620
			foreach ( $post_content as $key => $value ) {
621
				// Skip if it isn't a widget.
622
				if ( 'widget_' !== substr( $key, 0, strlen( 'widget_' ) ) ) {
623
					continue;
624
				}
625
				// Change key from "widget_archives[2]" to "archives-2".
626
				$key = str_replace( 'widget_', '', $key );
627
				$key = str_replace( '[', '-', $key );
628
				$key = str_replace( ']', '', $key );
629
630
				global $wp_registered_widgets;
631
				if ( isset( $wp_registered_widgets[ $key ] ) ) {
632
					$widget_data = array(
633
						'name'  => $wp_registered_widgets[ $key ]['name'],
634
						'id'    => $key,
635
						'title' => $value['value']['title'],
636
					);
637
					do_action( 'jetpack_widget_edited', $widget_data );
638
				}
639
			}
640
		}
641
	}
642
643
	/**
644
	 * Expand post IDs to post objects within a hook before they are serialized and sent to the server.
645
	 *
646
	 * @access public
647
	 *
648
	 * @param array $args The hook parameters.
649
	 * @return array $args The expanded hook parameters.
650
	 */
651
	public function expand_post_ids( $args ) {
652
		list( $post_ids, $previous_interval_end) = $args;
653
654
		$posts = array_filter( array_map( array( 'WP_Post', 'get_instance' ), $post_ids ) );
655
		$posts = array_map( array( $this, 'filter_post_content_and_add_links' ), $posts );
656
		$posts = array_values( $posts ); // Reindex in case posts were deleted.
657
658
		return array(
659
			$posts,
660
			$this->get_metadata( $post_ids, 'post', Settings::get_setting( 'post_meta_whitelist' ) ),
661
			$this->get_term_relationships( $post_ids ),
662
			$previous_interval_end,
663
		);
664
	}
665
666
	/**
667
	 * Gets a list of minimum and maximum object ids for each batch based on the given batch size.
668
	 *
669
	 * @access public
670
	 *
671
	 * @param int         $batch_size The batch size for objects.
672
	 * @param string|bool $where_sql  The sql where clause minus 'WHERE', or false if no where clause is needed.
673
	 *
674
	 * @return array|bool An array of min and max ids for each batch. FALSE if no table can be found.
675
	 */
676
	public function get_min_max_object_ids_for_batches( $batch_size, $where_sql = false ) {
677
		return parent::get_min_max_object_ids_for_batches( $batch_size, $this->get_where_sql( $where_sql ) );
0 ignored issues
show
Documentation introduced by
$where_sql is of type string|boolean, but the function expects a array.

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...
678
	}
679
680
	/**
681
	 * Gets the sync speed of a module.
682
	 *
683
	 * @access public
684
	 *
685
	 * @return int
686
	 */
687
	public function get_sync_speed() {
688
		return self::$sync_speed;
689
	}
690
}
691