PluginProbe
ActivityPub / 9.2.1
ActivityPub v9.2.1
9.3.1 9.3.0 9.2.2 9.2.1 9.2.0 9.1.0 9.0.2 9.0.1 9.0.0 8.3.0 8.2.1 8.2.0 8.1.1 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.2.0 1.3.0 2.0.0 2.0.1 2.1.0 2.1.1 All 160 releases
← All changes | includes/class-comment.php +68 -47 8.2.19.2.1 View file →
@@ -112,9 +112,9 @@
112 112 // Logged-in user without ActivityPub capability - show warning instead of reply link.
113 113 if ( \is_user_logged_in() ) {
114 114 $author = \esc_html( $comment->comment_author );
115 115
116 - $message = sprintf(
116 + $message = \sprintf(
117 117 /* translators: %s: comment author name */
118 118 \__( '%s is on the Fediverse. To reply to them, ask your administrator to enable ActivityPub for your account.', 'activitypub' ),
119 119 $author
120 120 );
@@ -120,9 +120,9 @@
120 120 );
121 121
122 122 // Add link to users page if current user can edit users.
123 123 if ( \current_user_can( 'edit_users' ) ) {
124 - $message = sprintf(
124 + $message = \sprintf(
125 125 /* translators: 1: comment author name, 2: URL to the users management page */
126 126 \__( '%1$s is on the Fediverse. To reply to them, <a href="%2$s">enable ActivityPub for your account</a>.', 'activitypub' ),
127 127 $author,
128 128 \esc_url( \admin_url( 'users.php' ) )
@@ -128,9 +128,9 @@
128 128 \esc_url( \admin_url( 'users.php' ) )
129 129 );
130 130 }
131 131
132 - $warning = sprintf(
132 + $warning = \sprintf(
133 133 '<p class="activitypub-reply-warning"><em>%s</em></p>',
134 134 \wp_kses( $message, array( 'a' => array( 'href' => array() ) ) )
135 135 );
136 136
@@ -177,9 +177,9 @@
177 177 if ( ! self::was_received( $comment ) ) {
178 178 return true;
179 179 }
180 180
181 - $current_user = get_current_user_id();
181 + $current_user = \get_current_user_id();
182 182
183 183 if ( ! $current_user ) {
184 184 return false;
185 185 }
@@ -298,8 +298,19 @@
298 298 if ( ! user_can_activitypub( $user_id ) ) {
299 299 return false;
300 300 }
301 301
302 + /*
303 + * Do not federate brand-new comments on a post that is not federated itself
304 + * (e.g. a private post, a post switched to local visibility, or a non-ActivityPub
305 + * post type). This prevents leaking replies on content the post type's read rules
306 + * would otherwise protect. Comments that were already sent are allowed through so
307 + * their Update and Delete activities can still federate (and tear down remote copies).
308 + */
309 + if ( ! self::was_sent( $comment ) && ! is_post_federated( $comment->comment_post_ID ) ) {
310 + return false;
311 + }
312 +
302 313 // It is a comment to the post and can be federated.
303 314 if ( empty( $comment->comment_parent ) ) {
304 315 return true;
305 316 }
@@ -312,22 +323,33 @@
312 323
313 324 /**
314 325 * Examine a comment ID and look up an existing comment it represents.
315 326 *
316 - * @param string $id ActivityPub object ID (usually a URL) to check.
327 + * @since 9.1.0 Added the `$args` parameter.
317 328 *
329 + * @param string $id ActivityPub object ID (usually a URL) to check.
330 + * @param array $args Optional. Additional WP_Comment_Query arguments. Pass `array( 'status' => 'any' )`
331 + * to also match comments in spam or trash, which the default status excludes.
332 + *
318 333 * @return \WP_Comment|false Comment object, or false on failure.
319 334 */
320 - public static function object_id_to_comment( $id ) {
321 - $comment_query = new \WP_Comment_Query(
335 + public static function object_id_to_comment( $id, $args = array() ) {
336 + $args = \wp_parse_args(
337 + $args,
322 338 array(
323 - 'meta_key' => 'source_id', // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key
324 - 'meta_value' => $id, // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value
325 - 'orderby' => 'comment_date',
326 - 'order' => 'DESC',
339 + 'number' => 1,
340 + 'orderby' => 'comment_date',
341 + 'order' => 'DESC',
327 342 )
328 343 );
329 344
345 + // Force the lookup key and full comment objects, so callers cannot break the return contract.
346 + $args['fields'] = 'all';
347 + $args['meta_key'] = 'source_id'; // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key
348 + $args['meta_value'] = $id; // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value
349 +
350 + $comment_query = new \WP_Comment_Query( $args );
351 +
330 352 if ( ! $comment_query->comments ) {
331 353 return false;
332 354 }
333 355
@@ -381,9 +403,9 @@
381 403
382 404 $query = new \WP_Comment_Query();
383 405 $comments = $query->query( $args );
384 406
385 - if ( $comments && is_array( $comments ) ) {
407 + if ( $comments && \is_array( $comments ) ) {
386 408 return $comments[0]->comment_ID;
387 409 }
388 410
389 411 return null;
@@ -399,9 +421,9 @@
399 421 * @return string[] An array of classes.
400 422 */
401 423 public static function comment_class( $classes, $css_class, $comment_id ) {
402 424 // Check if ActivityPub comment.
403 - if ( 'activitypub' === get_comment_meta( $comment_id, 'protocol', true ) ) {
425 + if ( 'activitypub' === \get_comment_meta( $comment_id, 'protocol', true ) ) {
404 426 $classes[] = 'activitypub-comment';
405 427 }
406 428
407 429 return $classes;
@@ -429,12 +451,11 @@
429 451
430 452 if ( \in_array( $comment_type, $comment_types, true ) ) {
431 453 $where .= $wpdb->prepare( ' AND comment_type = %s', $comment_type );
432 454 } else {
433 - $comment_types = \array_map( 'esc_sql', $comment_types );
434 - $placeholders = implode( ', ', array_fill( 0, count( $comment_types ), '%s' ) );
455 + $placeholders = \implode( ', ', \array_fill( 0, \count( $comment_types ), '%s' ) );
435 456 // phpcs:ignore WordPress.DB.PreparedSQLPlaceholders.ReplacementsWrongNumber, WordPress.DB.PreparedSQL.NotPrepared
436 - $where .= $wpdb->prepare( sprintf( ' AND comment_type NOT IN (%s)', $placeholders ), ...$comment_types );
457 + $where .= $wpdb->prepare( \sprintf( ' AND comment_type NOT IN (%s)', $placeholders ), ...$comment_types );
437 458 }
438 459
439 460 return $where;
440 461 }
@@ -564,9 +585,9 @@
564 585 $activity_type = \sanitize_key( $activity_type );
565 586 $comment_types = self::get_comment_types();
566 587
567 588 foreach ( $comment_types as $comment_type ) {
568 - if ( in_array( $activity_type, $comment_type['activity_types'], true ) ) {
589 + if ( \in_array( $activity_type, $comment_type['activity_types'], true ) ) {
569 590 return $comment_type;
570 591 }
571 592 }
572 593
@@ -605,15 +626,15 @@
605 626 *
606 627 * @return array The registered custom comment type slugs.
607 628 */
608 629 public static function get_comment_type_slugs() {
609 - if ( ! did_action( 'init' ) ) {
610 - _doing_it_wrong( __METHOD__, 'This function should not be called before the init action has run. Comment types are only available after init.', '7.5.0' );
630 + if ( ! \did_action( 'init' ) ) {
631 + \_doing_it_wrong( __METHOD__, 'This function should not be called before the init action has run. Comment types are only available after init.', '7.5.0' );
611 632
612 633 return array();
613 634 }
614 635
615 - return array_keys( self::get_comment_types() );
636 + return \array_keys( self::get_comment_types() );
616 637 }
617 638
618 639 /**
619 640 * Get the custom comment type.
@@ -627,16 +648,16 @@
627 648 *
628 649 * @return array The comment type.
629 650 */
630 651 public static function get_comment_type( $type ) {
631 - $type = strtolower( $type );
632 - $type = sanitize_key( $type );
652 + $type = \strtolower( $type );
653 + $type = \sanitize_key( $type );
633 654
634 655 $comment_types = self::get_comment_types();
635 656 $type_array = array();
636 657
637 658 // Check array keys.
638 - if ( in_array( $type, array_keys( $comment_types ), true ) ) {
659 + if ( \in_array( $type, \array_keys( $comment_types ), true ) ) {
639 660 $type_array = $comment_types[ $type ];
640 661 }
641 662
642 663 /**
@@ -643,9 +664,9 @@
643 664 * Filter the comment type.
644 665 *
645 666 * @param array $type_array The comment type.
646 667 */
647 - return apply_filters( "activitypub_comment_type_{$type}", $type_array );
668 + return \apply_filters( "activitypub_comment_type_{$type}", $type_array );
648 669 }
649 670
650 671 /**
651 672 * Get a comment type attribute.
@@ -669,9 +690,9 @@
669 690 *
670 691 * @param mixed $value The value of the attribute.
671 692 * @param string $type The comment type.
672 693 */
673 - return apply_filters( "activitypub_comment_type_{$attr}", $value, $type );
694 + return \apply_filters( "activitypub_comment_type_{$attr}", $value, $type );
674 695 }
675 696
676 697 /**
677 698 * Register the comment types used by the ActivityPub plugin.
@@ -679,10 +700,10 @@
679 700 public static function register_comment_types() {
680 701 register_comment_type(
681 702 'repost',
682 703 array(
683 - 'label' => __( 'Reposts', 'activitypub' ),
684 - 'singular' => __( 'Repost', 'activitypub' ),
704 + 'label' => \__( 'Reposts', 'activitypub' ),
705 + 'singular' => \__( 'Repost', 'activitypub' ),
685 706 'description' => 'A repost (or Announce) is when a post appears in the timeline because someone else shared it, while still showing the original author as the source.',
686 707 'icon' => '♻️',
687 708 'class' => 'p-repost',
688 709 'type' => 'repost',
@@ -687,13 +708,13 @@
687 708 'class' => 'p-repost',
688 709 'type' => 'repost',
689 710 'collection' => 'reposts',
690 711 'activity_types' => array( 'announce' ),
691 - 'excerpt' => html_entity_decode( \__( '&hellip; reposted this!', 'activitypub' ) ),
712 + 'excerpt' => \html_entity_decode( \__( '&hellip; reposted this!', 'activitypub' ) ),
692 713 /* translators: %d: Number of reposts */
693 - 'count_single' => _x( '%d repost', 'number of reposts', 'activitypub' ),
714 + 'count_single' => \_x( '%d repost', 'number of reposts', 'activitypub' ),
694 715 /* translators: %d: Number of reposts */
695 - 'count_plural' => _x( '%d reposts', 'number of reposts', 'activitypub' ),
716 + 'count_plural' => \_x( '%d reposts', 'number of reposts', 'activitypub' ),
696 717 )
697 718 );
698 719
699 720 register_comment_type(
@@ -698,10 +719,10 @@
698 719
699 720 register_comment_type(
700 721 'like',
701 722 array(
702 - 'label' => __( 'Likes', 'activitypub' ),
703 - 'singular' => __( 'Like', 'activitypub' ),
723 + 'label' => \__( 'Likes', 'activitypub' ),
724 + 'singular' => \__( 'Like', 'activitypub' ),
704 725 'description' => 'A like is a small positive reaction that shows appreciation for a post without sharing it further.',
705 726 'icon' => '👍',
706 727 'class' => 'p-like',
707 728 'type' => 'like',
@@ -706,13 +727,13 @@
706 727 'class' => 'p-like',
707 728 'type' => 'like',
708 729 'collection' => 'likes',
709 730 'activity_types' => array( 'like' ),
710 - 'excerpt' => html_entity_decode( \__( '&hellip; liked this!', 'activitypub' ) ),
731 + 'excerpt' => \html_entity_decode( \__( '&hellip; liked this!', 'activitypub' ) ),
711 732 /* translators: %d: Number of likes */
712 - 'count_single' => _x( '%d like', 'number of likes', 'activitypub' ),
733 + 'count_single' => \_x( '%d like', 'number of likes', 'activitypub' ),
713 734 /* translators: %d: Number of likes */
714 - 'count_plural' => _x( '%d likes', 'number of likes', 'activitypub' ),
735 + 'count_plural' => \_x( '%d likes', 'number of likes', 'activitypub' ),
715 736 )
716 737 );
717 738
718 739 register_comment_type(
@@ -717,10 +738,10 @@
717 738
718 739 register_comment_type(
719 740 'quote',
720 741 array(
721 - 'label' => __( 'Quotes', 'activitypub' ),
722 - 'singular' => __( 'Quote', 'activitypub' ),
742 + 'label' => \__( 'Quotes', 'activitypub' ),
743 + 'singular' => \__( 'Quote', 'activitypub' ),
723 744 'description' => 'A quote is when a post is shared along with an added comment, so the original post appears together with the sharer&#8217;s own words.',
724 745 'icon' => '❞',
725 746 'class' => 'p-quote',
726 747 'type' => 'quote',
@@ -725,13 +746,13 @@
725 746 'class' => 'p-quote',
726 747 'type' => 'quote',
727 748 'collection' => 'quotes',
728 749 'activity_types' => array( 'quote' ),
729 - 'excerpt' => html_entity_decode( \__( '&hellip; quoted this!', 'activitypub' ) ),
750 + 'excerpt' => \html_entity_decode( \__( '&hellip; quoted this!', 'activitypub' ) ),
730 751 /* translators: %d: Number of quotes */
731 - 'count_single' => _x( '%d quote', 'number of quotes', 'activitypub' ),
752 + 'count_single' => \_x( '%d quote', 'number of quotes', 'activitypub' ),
732 753 /* translators: %d: Number of quotes */
733 - 'count_plural' => _x( '%d quotes', 'number of quotes', 'activitypub' ),
754 + 'count_plural' => \_x( '%d quotes', 'number of quotes', 'activitypub' ),
734 755 )
735 756 );
736 757 }
737 758
@@ -743,11 +764,11 @@
743 764 * @return array show avatars on Activities
744 765 */
745 766 public static function get_avatar_comment_types( $types ) {
746 767 $comment_types = self::get_comment_type_slugs();
747 - $types = array_merge( $types, $comment_types );
768 + $types = \array_merge( $types, $comment_types );
748 769
749 - return array_unique( $types );
770 + return \array_unique( $types );
750 771 }
751 772
752 773 /**
753 774 * Excludes likes and reposts from comment queries.
@@ -763,9 +784,9 @@
763 784 return;
764 785 }
765 786
766 787 // Do not exclude likes and reposts on ActivityPub requests.
767 - if ( defined( 'ACTIVITYPUB_REQUEST' ) && ACTIVITYPUB_REQUEST ) {
788 + if ( \defined( 'ACTIVITYPUB_REQUEST' ) && ACTIVITYPUB_REQUEST ) {
768 789 return;
769 790 }
770 791
771 792 // Do not exclude likes and reposts on REST requests (handled by rest_comment_query).
@@ -921,9 +942,9 @@
921 942 * @return int|null The updated comment count, or null to use the default query.
922 943 */
923 944 public static function pre_wp_update_comment_count_now( $new_count, $old_count, $post_id ) {
924 945 if ( null === $new_count ) {
925 - $excluded_types = array_filter( self::get_comment_type_slugs(), array( self::class, 'is_comment_type_enabled' ) );
946 + $excluded_types = \array_filter( self::get_comment_type_slugs(), array( self::class, 'is_comment_type_enabled' ) );
926 947
927 948 if ( ! empty( $excluded_types ) ) {
928 949 /*
929 950 * Include 'note' type when Gutenberg's filter is registered, so a
@@ -945,14 +966,14 @@
945 966 * @param string[] $excluded_types The comment type slugs to exclude.
946 967 * @param int $post_id The post ID.
947 968 */
948 969 $excluded_types = \apply_filters( 'activitypub_excluded_comment_types', $excluded_types, $post_id );
949 - $excluded_types = array_unique( array_filter( $excluded_types ) );
970 + $excluded_types = \array_unique( \array_filter( $excluded_types ) );
950 971
951 972 global $wpdb;
952 973
953 974 // phpcs:ignore WordPress.DB
954 - $new_count = (int) $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM $wpdb->comments WHERE comment_post_ID = %d AND comment_approved = '1' AND comment_type NOT IN ('" . implode( "','", $excluded_types ) . "')", $post_id ) );
975 + $new_count = (int) $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM $wpdb->comments WHERE comment_post_ID = %d AND comment_approved = '1' AND comment_type NOT IN ('" . \implode( "','", $excluded_types ) . "')", $post_id ) );
955 976 }
956 977 }
957 978
958 979 return $new_count;
@@ -964,9 +985,9 @@
964 985 * @param string $comment_type The comment type.
965 986 * @return bool True if the comment type is enabled.
966 987 */
967 988 public static function is_comment_type_enabled( $comment_type ) {
968 - return '1' === get_option( "activitypub_allow_{$comment_type}s", '1' );
989 + return '1' === \get_option( "activitypub_allow_{$comment_type}s", '1' );
969 990 }
970 991
971 992 /**
972 993 * Get post types to hide comments for in admin.