PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 16.3-a.1
Jetpack – WP Security, Backup, Speed, & Growth v16.3-a.1
16.3-a.3 16.3-a.1 16.2 16.2-beta 12.0.3 12.1.3 12.2.3 12.3.2 12.4.2 12.5.2 12.6.4 12.7.3 12.8.3 12.9.5 13.0.2 13.1.5 13.2.4 13.3.3 13.4.5 13.5.2 13.6.2 13.7.2 13.8.3 13.9.2 14.0.1 All 504 releases
← All changes | jetpack_vendor/automattic/jetpack-sync/src/modules/class-comments.php +155 -40 12.0.3 → 16.3-a.1 View file →
@@ -6,15 +6,21 @@
6 6 */
7 7
8 8 namespace Automattic\Jetpack\Sync\Modules;
9 9
10 +use Automattic\Jetpack\Sync\Defaults;
10 11 use Automattic\Jetpack\Sync\Modules;
11 12 use Automattic\Jetpack\Sync\Settings;
12 13
14 +if ( ! defined( 'ABSPATH' ) ) {
15 + exit( 0 );
16 +}
17 +
13 18 /**
14 19 * Class to handle sync for comments.
15 20 */
16 21 class Comments extends Module {
22 +
17 23 /**
18 24 * Sync module name.
19 25 *
20 26 * @access public
@@ -36,19 +42,33 @@
36 42 return 'comment_ID';
37 43 }
38 44
39 45 /**
40 - * The table in the database.
46 + * The table name.
41 47 *
42 48 * @access public
43 49 *
44 50 * @return string
51 + * @deprecated since 3.11.0 Use table() instead.
45 52 */
46 53 public function table_name() {
54 + _deprecated_function( __METHOD__, '3.11.0', 'Automattic\\Jetpack\\Sync\\Comments->table' );
47 55 return 'comments';
48 56 }
49 57
50 58 /**
59 + * The table in the database with the prefix.
60 + *
61 + * @access public
62 + *
63 + * @return string|bool
64 + */
65 + public function table() {
66 + global $wpdb;
67 + return $wpdb->comments;
68 + }
69 +
70 + /**
51 71 * Retrieve a comment by its ID.
52 72 *
53 73 * @access public
54 74 *
@@ -90,9 +110,9 @@
90 110 add_action( 'unspammed_comment', $callable, 10, 2 );
91 111 add_filter( 'wp_update_comment_data', array( $this, 'handle_comment_contents_modification' ), 10, 3 );
92 112
93 113 // comment actions.
94 - add_filter( 'jetpack_sync_before_enqueue_wp_insert_comment', array( $this, 'only_allow_white_listed_comment_types' ) );
114 + add_filter( 'jetpack_sync_before_enqueue_wp_insert_comment', array( $this, 'filter_jetpack_sync_before_enqueue_wp_insert_comment' ) );
95 115 add_filter( 'jetpack_sync_before_enqueue_deleted_comment', array( $this, 'only_allow_white_listed_comment_types' ) );
96 116 add_filter( 'jetpack_sync_before_enqueue_trashed_comment', array( $this, 'only_allow_white_listed_comment_types' ) );
97 117 add_filter( 'jetpack_sync_before_enqueue_untrashed_comment', array( $this, 'only_allow_white_listed_comment_types' ) );
98 118 add_filter( 'jetpack_sync_before_enqueue_spammed_comment', array( $this, 'only_allow_white_listed_comment_types' ) );
@@ -114,8 +134,15 @@
114 134 foreach ( $this->get_whitelisted_comment_types() as $comment_type ) {
115 135 foreach ( array( 'unapproved', 'approved' ) as $comment_status ) {
116 136 $comment_action_name = "comment_{$comment_status}_{$comment_type}";
117 137 add_action( $comment_action_name, $callable, 10, 2 );
138 + add_filter(
139 + 'jetpack_sync_before_enqueue_' . $comment_action_name,
140 + array(
141 + $this,
142 + 'expand_wp_insert_comment',
143 + )
144 + );
118 145 }
119 146 }
120 147
121 148 // Listen for meta changes.
@@ -178,26 +205,27 @@
178 205 * Gets a filtered list of comment types that sync can hook into.
179 206 *
180 207 * @access public
181 208 *
182 - * @return array Defaults to [ '', 'trackback', 'pingback' ].
209 + * @return array Defaults to [ '', 'comment', 'trackback', 'pingback', 'review', 'note' ].
183 210 */
184 211 public function get_whitelisted_comment_types() {
185 - /**
186 - * Comment types present in this list will sync their status changes to WordPress.com.
187 - *
188 - * @since 1.6.3
189 - * @since-jetpack 7.6.0
190 - *
191 - * @param array A list of comment types.
192 - */
193 - return apply_filters(
194 - 'jetpack_sync_whitelisted_comment_types',
195 - array( '', 'comment', 'trackback', 'pingback', 'review' )
196 - );
212 + return Defaults::get_comment_types_whitelist();
197 213 }
198 214
199 215 /**
216 + * Returns escaped SQL for whitelisted comment types.
217 + * Can be injected directly into a WHERE clause.
218 + *
219 + * @access public
220 + *
221 + * @return string SQL WHERE clause.
222 + */
223 + public function get_whitelisted_comment_types_sql() {
224 + return 'comment_type IN (\'' . implode( '\', \'', array_map( 'esc_sql', $this->get_whitelisted_comment_types() ) ) . '\')';
225 + }
226 +
227 + /**
200 228 * Prevents any comment types that are not in the whitelist from being enqueued and sent to WordPress.com.
201 229 *
202 230 * @param array $args Arguments passed to wp_insert_comment, deleted_comment, spammed_comment, etc.
203 231 *
@@ -203,25 +231,30 @@
203 231 *
204 232 * @return bool or array $args Arguments passed to wp_insert_comment, deleted_comment, spammed_comment, etc.
205 233 */
206 234 public function only_allow_white_listed_comment_types( $args ) {
235 + if ( empty( $args ) ) {
236 + return false;
237 + }
238 +
207 239 $comment = false;
208 240
209 241 if ( isset( $args[1] ) ) {
210 242 // comment object is available.
211 243 $comment = $args[1];
212 - } elseif ( is_numeric( $args[0] ) ) {
244 + } elseif ( isset( $args[0] ) && is_numeric( $args[0] ) ) {
213 245 // comment_id is available.
214 246 $comment = get_comment( $args[0] );
215 247 }
216 248
217 - if (
218 - isset( $comment->comment_type )
219 - && ! in_array( $comment->comment_type, $this->get_whitelisted_comment_types(), true )
220 - ) {
249 + if ( ! $comment instanceof \WP_Comment ) {
221 250 return false;
222 251 }
223 252
253 + if ( ! in_array( $comment->comment_type, $this->get_whitelisted_comment_types(), true ) ) {
254 + return false;
255 + }
256 +
224 257 return $args;
225 258 }
226 259
227 260 /**
@@ -232,8 +265,9 @@
232 265 */
233 266 public function filter_blacklisted_post_types( $args ) {
234 267 $post_id = $args[0];
235 268 $posts_module = Modules::get_module( 'posts' );
269 + '@phan-var Posts $posts_module';
236 270
237 271 if ( false !== $posts_module && ! $posts_module->is_post_type_allowed( $post_id ) ) {
238 272 return false;
239 273 }
@@ -258,8 +292,24 @@
258 292 return $args;
259 293 }
260 294
261 295 /**
296 + * Prevents any comment types that are not in the whitelist from being enqueued and sent to WordPress.com.
297 + * Also expands comment data before being enqueued.
298 + *
299 + * @param array $args Arguments passed to wp_insert_comment.
300 + *
301 + * @return false or array $args Arguments passed to wp_insert_comment or false if the comment type is a blacklisted one.
302 + */
303 + public function filter_jetpack_sync_before_enqueue_wp_insert_comment( $args ) {
304 + if ( false === $this->only_allow_white_listed_comment_types( $args ) ) {
305 + return false;
306 + }
307 +
308 + return $this->expand_wp_insert_comment( $args );
309 + }
310 +
311 + /**
262 312 * Whether a comment type is allowed.
263 313 * A comment type is allowed if it's present in the comment type whitelist.
264 314 *
265 315 * @param int $comment_id ID of the comment.
@@ -279,25 +329,16 @@
279 329 *
280 330 * @access public
281 331 */
282 332 public function init_before_send() {
283 - add_filter( 'jetpack_sync_before_send_wp_insert_comment', array( $this, 'expand_wp_insert_comment' ) );
284 333
285 - foreach ( $this->get_whitelisted_comment_types() as $comment_type ) {
286 - foreach ( array( 'unapproved', 'approved' ) as $comment_status ) {
287 - $comment_action_name = "comment_{$comment_status}_{$comment_type}";
288 - add_filter(
289 - 'jetpack_sync_before_send_' . $comment_action_name,
290 - array(
291 - $this,
292 - 'expand_wp_insert_comment',
293 - )
294 - );
295 - }
334 + // Full sync.
335 + $sync_module = Modules::get_module( 'full-sync' );
336 + if ( $sync_module instanceof Full_Sync_Immediately ) {
337 + add_filter( 'jetpack_sync_before_send_jetpack_full_sync_comments', array( $this, 'extract_comments_and_meta' ) );
338 + } else {
339 + add_filter( 'jetpack_sync_before_send_jetpack_full_sync_comments', array( $this, 'expand_comment_ids' ) );
296 340 }
297 -
298 - // Full sync.
299 - add_filter( 'jetpack_sync_before_send_jetpack_full_sync_comments', array( $this, 'expand_comment_ids' ) );
300 341 }
301 342
302 343 /**
303 344 * Enqueue the comments actions for full sync.
@@ -332,10 +373,10 @@
332 373 $query .= ' WHERE ' . $where_sql;
333 374 }
334 375
335 376 // TODO: Call $wpdb->prepare on the following query.
336 - // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
337 - $count = $wpdb->get_var( $query );
377 + // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
378 + $count = (int) $wpdb->get_var( $query );
338 379
339 380 return (int) ceil( $count / self::ARRAY_CHUNK_SIZE );
340 381 }
341 382
@@ -347,13 +388,15 @@
347 388 * @param array $config Full sync configuration for this sync module.
348 389 * @return string WHERE SQL clause, or `null` if no comments are specified in the module config.
349 390 */
350 391 public function get_where_sql( $config ) {
351 - if ( is_array( $config ) ) {
392 + $where_sql = $this->get_whitelisted_comment_types_sql();
393 +
394 + if ( is_array( $config ) && ! empty( $config ) ) {
352 395 return 'comment_ID IN (' . implode( ',', array_map( 'intval', $config ) ) . ')';
353 396 }
354 397
355 - return '1=1';
398 + return $where_sql;
356 399 }
357 400
358 401 /**
359 402 * Retrieve the actions that will be sent for this module during a full sync.
@@ -391,9 +434,9 @@
391 434 return array( $args[0], $this->filter_comment( $args[1] ) );
392 435 }
393 436
394 437 /**
395 - * Expand the comment creation before the data is serialized and sent to the server.
438 + * Expand the comment creation before the data is added to the Sync queue.
396 439 *
397 440 * @access public
398 441 *
399 442 * @param array $args The hook parameters.
@@ -459,8 +502,11 @@
459 502 * @param array $args Hook args.
460 503 * @return array|boolean False if not whitelisted, the original hook args otherwise.
461 504 */
462 505 public function filter_meta( $args ) {
506 + if ( ! is_array( $args ) || count( $args ) < 3 ) {
507 + return false;
508 + }
463 509 if ( $this->is_comment_type_allowed( $args[1] ) && $this->is_whitelisted_comment_meta( $args[2] ) ) {
464 510 return $args;
465 511 }
466 512
@@ -489,7 +535,76 @@
489 535 return array(
490 536 $comments,
491 537 $this->get_metadata( $comment_ids, 'comment', Settings::get_setting( 'comment_meta_whitelist' ) ),
492 538 $previous_interval_end,
539 + );
540 + }
541 +
542 + /**
543 + * Expand the comment IDs to comment objects and meta before being serialized and sent to the server.
544 + *
545 + * @access public
546 + *
547 + * @param array $args The hook parameters.
548 + * @return array The expanded hook parameters.
549 + */
550 + public function extract_comments_and_meta( $args ) {
551 + list( $filtered_comments, $previous_end ) = $args;
552 + return array(
553 + $filtered_comments['objects'],
554 + $filtered_comments['meta'],
555 + $previous_end,
556 + );
557 + }
558 +
559 + /**
560 + * Given the Module Configuration and Status return the next chunk of items to send.
561 + * This function also expands the posts and metadata and filters them based on the maximum size constraints.
562 + *
563 + * @param array $config This module Full Sync configuration.
564 + * @param array $status This module Full Sync status.
565 + * @param int $chunk_size Chunk size.
566 + *
567 + * @return array
568 + */
569 + public function get_next_chunk( $config, $status, $chunk_size ) {
570 +
571 + $comment_ids = parent::get_next_chunk( $config, $status, $chunk_size );
572 + // If no comment IDs were fetched, return an empty array.
573 + if ( empty( $comment_ids ) ) {
574 + return array();
575 + }
576 + $comments = get_comments(
577 + array(
578 + 'comment__in' => $comment_ids,
579 + 'orderby' => 'comment_ID',
580 + 'order' => 'DESC',
581 + )
582 + );
583 + // If no comments were fetched, make sure to return the expected structure so that status is updated correctly.
584 + if ( empty( $comments ) ) {
585 + return array(
586 + 'object_ids' => $comment_ids,
587 + 'objects' => array(),
588 + 'meta' => array(),
589 + );
590 + }
591 + // Get the comment IDs from the comments that were fetched.
592 + $fetched_comment_ids = wp_list_pluck( $comments, 'comment_ID' );
593 + $metadata = $this->get_metadata( $fetched_comment_ids, 'comment', Settings::get_setting( 'comment_meta_whitelist' ) );
594 +
595 + // Filter the comments and metadata based on the maximum size constraints.
596 + list( $filtered_comment_ids, $filtered_comments, $filtered_comments_metadata ) = $this->filter_objects_and_metadata_by_size(
597 + 'comment',
598 + $comments,
599 + $metadata,
600 + self::MAX_META_LENGTH, // Replace with appropriate comment meta length constant.
601 + self::MAX_SIZE_FULL_SYNC
602 + );
603 +
604 + return array(
605 + 'object_ids' => $filtered_comment_ids,
606 + 'objects' => $filtered_comments,
607 + 'meta' => $filtered_comments_metadata,
493 608 );
494 609 }
495 610 }