Skip to content

Commit 253cfff

Browse files
authored
Improved comment-type handling (#1072)
1 parent cba6228 commit 253cfff

File tree

6 files changed

+197
-44
lines changed

6 files changed

+197
-44
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1919
* Email templates for Likes and Reposts
2020
* Improve Interactions moderation
2121
* Compatibility with Akismet
22+
* Comment type mapping for `Like` and `Announce`
2223

2324
### Fixed
2425

includes/class-admin.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -600,7 +600,7 @@ public static function comment_row_actions( $actions, $comment ) {
600600
unset( $actions['quickedit'] );
601601
}
602602

603-
if ( in_array( get_comment_type( $comment ), Comment::get_comment_type_names(), true ) ) {
603+
if ( in_array( get_comment_type( $comment ), Comment::get_comment_type_slugs(), true ) ) {
604604
unset( $actions['reply'] );
605605
}
606606

includes/class-comment.php

+70-38
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,27 @@ public static function enqueue_scripts() {
506506
}
507507
}
508508

509+
/**
510+
* Get the comment type by activity type.
511+
*
512+
* @param string $activity_type The activity type.
513+
*
514+
* @return array|null The comment type.
515+
*/
516+
public static function get_comment_type_by_activity_type( $activity_type ) {
517+
$activity_type = \strtolower( $activity_type );
518+
$activity_type = \sanitize_key( $activity_type );
519+
$comment_types = self::get_comment_types();
520+
521+
foreach ( $comment_types as $comment_type ) {
522+
if ( in_array( $activity_type, $comment_type['activity_types'], true ) ) {
523+
return $comment_type;
524+
}
525+
}
526+
527+
return null;
528+
}
529+
509530
/**
510531
* Return the registered custom comment types.
511532
*
@@ -520,23 +541,39 @@ public static function get_comment_types() {
520541
/**
521542
* Is this a registered comment type.
522543
*
523-
* @param string $slug The name of the type.
544+
* @param string $slug The slug of the type.
545+
*
524546
* @return boolean True if registered.
525547
*/
526548
public static function is_registered_comment_type( $slug ) {
527-
$slug = strtolower( $slug );
528-
$slug = sanitize_key( $slug );
549+
$slug = \strtolower( $slug );
550+
$slug = \sanitize_key( $slug );
529551

530-
return in_array( $slug, array_keys( self::get_comment_types() ), true );
552+
$comment_types = self::get_comment_types();
553+
554+
return isset( $comment_types[ $slug ] );
555+
}
556+
557+
/**
558+
* Return the registered custom comment type slugs.
559+
*
560+
* @return array The registered custom comment type slugs.
561+
*/
562+
public static function get_comment_type_slugs() {
563+
return array_keys( self::get_comment_types() );
531564
}
532565

533566
/**
534-
* Return the registered custom comment types names.
567+
* Return the registered custom comment type slugs.
568+
*
569+
* @deprecated 4.5.0 Use get_comment_type_slugs instead.
535570
*
536-
* @return array The registered custom comment type names.
571+
* @return array The registered custom comment type slugs.
537572
*/
538573
public static function get_comment_type_names() {
539-
return array_values( wp_list_pluck( self::get_comment_types(), 'type' ) );
574+
_deprecated_function( __METHOD__, '4.5.0', 'get_comment_type_slugs' );
575+
576+
return self::get_comment_type_slugs();
540577
}
541578

542579
/**
@@ -552,22 +589,15 @@ public static function get_comment_type_names() {
552589
* @return array The comment type.
553590
*/
554591
public static function get_comment_type( $type ) {
555-
$type = strtolower( $type );
556-
$type = sanitize_key( $type );
557-
$types = self::get_comment_types();
592+
$type = strtolower( $type );
593+
$type = sanitize_key( $type );
558594

559-
$type_array = array();
595+
$comment_types = self::get_comment_types();
596+
$type_array = array();
560597

561598
// Check array keys.
562-
if ( in_array( $type, array_keys( $types ), true ) ) {
563-
$type_array = $types[ $type ];
564-
} else { // Fall back to type attribute.
565-
foreach ( $types as $item ) {
566-
if ( $type === $item['type'] ) {
567-
$type_array = $item;
568-
break;
569-
}
570-
}
599+
if ( in_array( $type, array_keys( $comment_types ), true ) ) {
600+
$type_array = $comment_types[ $type ];
571601
}
572602

573603
/**
@@ -609,28 +639,30 @@ public static function get_comment_type_attr( $type, $attr ) {
609639
*/
610640
public static function register_comment_types() {
611641
register_comment_type(
612-
'announce',
642+
'repost',
613643
array(
614-
'label' => __( 'Reposts', 'activitypub' ),
615-
'singular' => __( 'Repost', 'activitypub' ),
616-
'description' => __( 'A repost on the indieweb is a post that is purely a 100% re-publication of another (typically someone else\'s) post.', 'activitypub' ),
617-
'icon' => '♻️',
618-
'class' => 'p-repost',
619-
'type' => 'repost',
620-
'excerpt' => __( '… reposted this!', 'activitypub' ),
644+
'label' => __( 'Reposts', 'activitypub' ),
645+
'singular' => __( 'Repost', 'activitypub' ),
646+
'description' => __( 'A repost on the indieweb is a post that is purely a 100% re-publication of another (typically someone else\'s) post.', 'activitypub' ),
647+
'icon' => '♻️',
648+
'class' => 'p-repost',
649+
'type' => 'repost',
650+
'activity_types' => array( 'announce' ),
651+
'excerpt' => __( '… reposted this!', 'activitypub' ),
621652
)
622653
);
623654

624655
register_comment_type(
625656
'like',
626657
array(
627-
'label' => __( 'Likes', 'activitypub' ),
628-
'singular' => __( 'Like', 'activitypub' ),
629-
'description' => __( 'A like is a popular webaction button and in some cases post type on various silos such as Facebook and Instagram.', 'activitypub' ),
630-
'icon' => '👍',
631-
'class' => 'p-like',
632-
'type' => 'like',
633-
'excerpt' => __( '… liked this!', 'activitypub' ),
658+
'label' => __( 'Likes', 'activitypub' ),
659+
'singular' => __( 'Like', 'activitypub' ),
660+
'description' => __( 'A like is a popular webaction button and in some cases post type on various silos such as Facebook and Instagram.', 'activitypub' ),
661+
'icon' => '👍',
662+
'class' => 'p-like',
663+
'type' => 'like',
664+
'activity_types' => array( 'like' ),
665+
'excerpt' => __( '… liked this!', 'activitypub' ),
634666
)
635667
);
636668
}
@@ -643,7 +675,7 @@ public static function register_comment_types() {
643675
* @return array show avatars on Activities
644676
*/
645677
public static function get_avatar_comment_types( $types ) {
646-
$comment_types = self::get_comment_type_names();
678+
$comment_types = self::get_comment_type_slugs();
647679
$types = array_merge( $types, $comment_types );
648680

649681
return array_unique( $types );
@@ -672,7 +704,7 @@ public static function comment_query( $query ) {
672704
}
673705

674706
// Exclude likes and reposts by the ActivityPub plugin.
675-
$query->query_vars['type__not_in'] = self::get_comment_type_names();
707+
$query->query_vars['type__not_in'] = self::get_comment_type_slugs();
676708
}
677709

678710
/**
@@ -726,7 +758,7 @@ public static function pre_wp_update_comment_count_now( $new_count, $old_count,
726758
if ( null === $new_count ) {
727759
global $wpdb;
728760

729-
$excluded_types = self::get_comment_type_names();
761+
$excluded_types = self::get_comment_type_slugs();
730762

731763
// phpcs:ignore WordPress.DB
732764
$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 ) );

includes/collection/class-interactions.php

+4-5
Original file line numberDiff line numberDiff line change
@@ -98,11 +98,11 @@ public static function add_reaction( $activity ) {
9898
}
9999

100100
$url = object_to_uri( $activity['object'] );
101-
$comment_post_id = url_to_postid( $url );
101+
$comment_post_id = \url_to_postid( $url );
102102
$parent_comment_id = url_to_commentid( $url );
103103

104104
if ( ! $comment_post_id && $parent_comment_id ) {
105-
$parent_comment = get_comment( $parent_comment_id );
105+
$parent_comment = \get_comment( $parent_comment_id );
106106
$comment_post_id = $parent_comment->comment_post_ID;
107107
}
108108

@@ -111,14 +111,13 @@ public static function add_reaction( $activity ) {
111111
return false;
112112
}
113113

114-
$type = $activity['type'];
114+
$comment_type = Comment::get_comment_type_by_activity_type( $activity['type'] );
115115

116-
if ( ! Comment::is_registered_comment_type( $type ) ) {
116+
if ( ! $comment_type ) {
117117
// Not a valid comment type.
118118
return false;
119119
}
120120

121-
$comment_type = Comment::get_comment_type( $type );
122121
$comment_content = $comment_type['excerpt'];
123122

124123
$commentdata['comment_post_ID'] = $comment_post_id;

readme.txt

+1
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ For reasons of data protection, it is not possible to see the followers of other
141141
* Improved: Email templates for Likes and Reposts
142142
* Improved: Interactions moderation
143143
* Improved: Compatibility with Akismet
144+
* Improved: Comment type mapping for `Like` and `Announce`
144145
* Fixed: Empty `url` attributes in the Reply block no longer cause PHP warnings
145146

146147
= 4.4.0 =

tests/includes/class-test-comment.php

+120
Original file line numberDiff line numberDiff line change
@@ -455,4 +455,124 @@ public function ability_to_federate_threaded_comment() {
455455
),
456456
);
457457
}
458+
459+
/**
460+
* Test get_comment_type_by_activity_type method.
461+
*
462+
* @covers ::get_comment_type_by_activity_type
463+
*/
464+
public function test_get_comment_type_by_activity_type() {
465+
// Test Like activity type.
466+
$comment_type = Comment::get_comment_type_by_activity_type( 'Like' );
467+
$this->assertIsArray( $comment_type );
468+
$this->assertEquals( 'like', $comment_type['type'] );
469+
$this->assertEquals( 'Like', $comment_type['singular'] );
470+
$this->assertEquals( 'Likes', $comment_type['label'] );
471+
$this->assertContains( 'like', $comment_type['activity_types'] );
472+
473+
// Test Announce activity type.
474+
$comment_type = Comment::get_comment_type_by_activity_type( 'Announce' );
475+
$this->assertIsArray( $comment_type );
476+
$this->assertEquals( 'repost', $comment_type['type'] );
477+
$this->assertEquals( 'Repost', $comment_type['singular'] );
478+
$this->assertEquals( 'Reposts', $comment_type['label'] );
479+
$this->assertContains( 'announce', $comment_type['activity_types'] );
480+
481+
// Test case insensitivity.
482+
$comment_type = Comment::get_comment_type_by_activity_type( 'like' );
483+
$this->assertIsArray( $comment_type );
484+
$this->assertEquals( 'like', $comment_type['type'] );
485+
486+
$comment_type = Comment::get_comment_type_by_activity_type( 'ANNOUNCE' );
487+
$this->assertIsArray( $comment_type );
488+
$this->assertEquals( 'repost', $comment_type['type'] );
489+
490+
// Test invalid activity type.
491+
$comment_type = Comment::get_comment_type_by_activity_type( 'InvalidType' );
492+
$this->assertNull( $comment_type );
493+
494+
// Test empty activity type.
495+
$comment_type = Comment::get_comment_type_by_activity_type( '' );
496+
$this->assertNull( $comment_type );
497+
}
498+
499+
/**
500+
* Test is_registered_comment_type.
501+
*
502+
* @covers ::is_registered_comment_type
503+
*/
504+
public function test_is_registered_comment_type() {
505+
// Test registered types (these are registered in Comment::register_comment_types()).
506+
$this->assertTrue( Comment::is_registered_comment_type( 'repost' ) );
507+
$this->assertTrue( Comment::is_registered_comment_type( 'like' ) );
508+
509+
// Test case insensitivity.
510+
$this->assertTrue( Comment::is_registered_comment_type( 'REPOST' ) );
511+
$this->assertTrue( Comment::is_registered_comment_type( 'Like' ) );
512+
513+
// Test with spaces and special characters (sanitize_key removes these).
514+
$this->assertTrue( Comment::is_registered_comment_type( ' repost ' ) );
515+
$this->assertTrue( Comment::is_registered_comment_type( 'like!' ) );
516+
517+
// Test unregistered types.
518+
$this->assertFalse( Comment::is_registered_comment_type( 'nonexistent' ) );
519+
$this->assertFalse( Comment::is_registered_comment_type( '' ) );
520+
$this->assertFalse( Comment::is_registered_comment_type( 'comment' ) );
521+
}
522+
523+
/**
524+
* Test get_comment_type_slugs.
525+
*
526+
* @covers ::get_comment_type_slugs
527+
*/
528+
public function test_get_comment_type_slugs() {
529+
// Get the registered slugs.
530+
$slugs = Comment::get_comment_type_slugs();
531+
532+
// Test that we get an array.
533+
$this->assertIsArray( $slugs );
534+
535+
// Test that the array is not empty.
536+
$this->assertNotEmpty( $slugs );
537+
538+
// Test that it contains the expected default types.
539+
$this->assertContains( 'repost', $slugs );
540+
$this->assertContains( 'like', $slugs );
541+
542+
// Test that the array only contains strings.
543+
foreach ( $slugs as $slug ) {
544+
$this->assertIsString( $slug );
545+
}
546+
547+
// Test that there are no duplicate slugs.
548+
$this->assertEquals( count( $slugs ), count( array_unique( $slugs ) ) );
549+
}
550+
551+
/**
552+
* Test get_comment_type_names to maintain backwards compatibility.
553+
*
554+
* @covers ::get_comment_type_names
555+
*/
556+
public function test_get_comment_type_names() {
557+
$this->setExpectedDeprecated( 'Activitypub\Comment::get_comment_type_names' );
558+
559+
// Get both types of results.
560+
$names = Comment::get_comment_type_names();
561+
$slugs = Comment::get_comment_type_slugs();
562+
563+
// Test that we get an array.
564+
$this->assertIsArray( $names );
565+
566+
// Test that the array is not empty.
567+
$this->assertNotEmpty( $names );
568+
569+
// Test that it returns exactly the same as get_comment_type_slugs().
570+
$this->assertEquals( $slugs, $names );
571+
572+
// Verify it returns slugs and not singular names.
573+
$this->assertContains( 'repost', $names );
574+
$this->assertContains( 'like', $names );
575+
$this->assertNotContains( 'Repost', $names );
576+
$this->assertNotContains( 'Like', $names );
577+
}
458578
}

0 commit comments

Comments
 (0)