Completed
Push — fix/14269 ( 73896b )
by
unknown
09:32 queued 03:22
created

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