Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions src/wp-includes/class-walker-comment.php
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,8 @@ public function display_element( $element, &$children_elements, $max_depth, $dep
* @since 5.9.0 Renamed `$comment` to `$data_object` and `$id` to `$current_object_id`
* to match parent class for PHP 8 named parameter support.
* @since 7.1.0 Comments of a registered comment type with a `render_callback`
* are rendered via that callback.
* are rendered via that callback, and short-ping rendering is
* driven by the comment type's `is_ping` property.
*
* @see Walker::start_el()
* @see wp_list_comments()
Expand Down Expand Up @@ -204,7 +205,9 @@ public function start_el( &$output, $data_object, $depth = 0, $args = array(), $
add_filter( 'comment_text', array( $this, 'filter_comment_text' ), 40, 2 );
}

if ( ( 'pingback' === $comment->comment_type || 'trackback' === $comment->comment_type ) && $args['short_ping'] ) {
$is_ping = $comment_type_object && $comment_type_object->is_ping;

if ( $is_ping && $args['short_ping'] ) {
ob_start();
$this->ping( $comment, $depth, $args );
$output .= ob_get_clean();
Expand Down
17 changes: 17 additions & 0 deletions src/wp-includes/class-wp-comment-type.php
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,22 @@ final class WP_Comment_Type {
*/
public $render_callback = null;

/**
* Whether the comment type represents a ping (a notification from another site)
* rather than a human-authored comment.
*
* Ping types (such as `pingback` and `trackback`) are grouped together by
* {@see separate_comments()} and, when the `short_ping` argument of
* wp_list_comments() is true, rendered with the compact ping markup by
* {@see Walker_Comment}. A registered `render_callback` takes precedence over
* the ping markup. Like `render_callback`, the rendering effects apply only to
* classic themes; block themes do not use Walker_Comment. Default false.
*
* @since 7.1.0
* @var bool
*/
public $is_ping = false;

/**
* Whether the comment type is hierarchical.
*
Expand Down Expand Up @@ -216,6 +232,7 @@ public function set_props( $args ) {
'public' => true,
'internal' => false,
'render_callback' => null,
'is_ping' => false,
'_builtin' => false,
);

Expand Down
6 changes: 4 additions & 2 deletions src/wp-includes/comment-template.php
Original file line number Diff line number Diff line change
Expand Up @@ -2230,8 +2230,10 @@ function _get_comment_reply_id( $post = null ) {
* 'div' will result in no additional list markup. Default 'ul'.
* @type callable $callback Callback function to use. Default null.
* @type callable $end-callback Callback function to use at the end. Default null.
* @type string $type Type of comments to list. Accepts 'all', 'comment',
* 'pingback', 'trackback', 'pings'. Default 'all'.
* @type string $type Type of comments to list. Accepts 'all', any comment type
* slug, or 'pings' (the comments of every registered comment
* type with the 'is_ping' property, which includes pingbacks
* and trackbacks). Default 'all'.
* @type int $page Page ID to list comments for. Default empty.
* @type int $per_page Number of comments to list per page. Default empty.
* @type int $avatar_size Height and width dimensions of the avatar size. Default 32.
Expand Down
16 changes: 15 additions & 1 deletion src/wp-includes/comment.php
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,7 @@ function create_initial_comment_types() {
'singular_name' => __( 'Pingback' ),
),
'public' => true,
'is_ping' => true,
'_builtin' => true,
)
);
Expand All @@ -320,6 +321,7 @@ function create_initial_comment_types() {
'singular_name' => __( 'Trackback' ),
),
'public' => true,
'is_ping' => true,
'_builtin' => true,
)
);
Expand Down Expand Up @@ -374,6 +376,13 @@ function create_initial_comment_types() {
* @type bool $internal Whether the comment type is for internal use only. Core does
* not currently consult this flag; it is intended to drive
* default query exclusions in the future. Default false.
* @type bool $is_ping Whether the comment type represents a ping (a notification
* from another site) rather than a human-authored comment.
* Ping types are grouped together by separate_comments() and,
* when wp_list_comments() is called with 'short_ping', rendered
* with compact ping markup by Walker_Comment. A registered
* 'render_callback' takes precedence over the ping markup.
* Default false.
* @type callable $render_callback Callback used to render a comment of this type in comment
* lists. Receives the same arguments as the `callback` argument
* of wp_list_comments() (the comment, the arguments, and the
Expand Down Expand Up @@ -1281,6 +1290,9 @@ function wp_check_comment_flood( $is_flood, $ip, $email, $date, $avoid_die = fal
* Separates an array of comments into an array keyed by comment_type.
*
* @since 2.7.0
* @since 7.1.0 The 'pings' group contains the comments of every registered
* comment type with the `is_ping` property, rather than only
* pingbacks and trackbacks.
*
* @param WP_Comment[] $comments Array of comments.
* @return array<string, WP_Comment[]> Array of comments keyed by comment type.
Expand All @@ -1304,7 +1316,9 @@ function separate_comments( &$comments ) {

$comments_by_type[ $type ][] = &$comments[ $i ];

if ( 'trackback' === $type || 'pingback' === $type ) {
$comment_type_object = get_comment_type_object( $type );

if ( $comment_type_object && $comment_type_object->is_ping ) {
$comments_by_type['pings'][] = &$comments[ $i ];
}
}
Expand Down
133 changes: 133 additions & 0 deletions tests/phpunit/tests/comment/separateComments.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
<?php

/**
* @group comment
*
* @covers ::separate_comments
*/
class Tests_Comment_SeparateComments extends WP_UnitTestCase {

/**
* Comment post ID.
*
* @var int
*/
private static $post_id;

public static function wpSetUpBeforeClass( WP_UnitTest_Factory $factory ) {
self::$post_id = $factory->post->create();
}

/**
* Builds a comment of the given type on the shared post.
*
* @param string $comment_type Comment type slug.
* @return WP_Comment The created comment object.
*/
private function make_comment( $comment_type ) {
return get_comment(
self::factory()->comment->create(
array(
'comment_post_ID' => self::$post_id,
'comment_type' => $comment_type,
)
)
);
}

/**
* The standard buckets are always present, even when empty.
*
* @ticket 35214
*/
public function test_default_buckets_are_always_present() {
$comments = array();
$separated = separate_comments( $comments );

$this->assertArrayHasKey( 'comment', $separated );
$this->assertArrayHasKey( 'trackback', $separated );
$this->assertArrayHasKey( 'pingback', $separated );
$this->assertArrayHasKey( 'pings', $separated );
}

/**
* Built-in pingbacks and trackbacks are grouped into the 'pings' bucket.
*
* @ticket 35214
*/
public function test_built_in_pings_are_grouped_into_pings_bucket() {
$comments = array(
$this->make_comment( 'comment' ),
$this->make_comment( 'pingback' ),
$this->make_comment( 'trackback' ),
);

$separated = separate_comments( $comments );

$this->assertCount( 1, $separated['comment'] );
$this->assertCount( 1, $separated['pingback'] );
$this->assertCount( 1, $separated['trackback'] );
$this->assertCount( 2, $separated['pings'] );
}

/**
* A registered comment type marked as a ping is grouped into 'pings'.
*
* @ticket 35214
*/
public function test_registered_ping_type_is_grouped_into_pings_bucket() {
register_comment_type( 'webmention', array( 'is_ping' => true ) );

$comments = array( $this->make_comment( 'webmention' ) );

$separated = separate_comments( $comments );

$this->assertCount( 1, $separated['webmention'] );
$this->assertCount( 1, $separated['pings'] );
}

/**
* A registered comment type that is not a ping stays out of the 'pings' bucket.
*
* @ticket 35214
*/
public function test_non_ping_type_is_not_grouped_into_pings_bucket() {
register_comment_type( 'review' );

$comments = array( $this->make_comment( 'review' ) );

$separated = separate_comments( $comments );

$this->assertCount( 1, $separated['review'] );
$this->assertCount( 0, $separated['pings'] );
}

/**
* An unregistered comment type gets its own bucket and stays out of 'pings',
* matching the previous hard-coded behavior.
*
* @ticket 35214
*/
public function test_unregistered_type_gets_own_bucket_and_is_not_a_ping() {
$comments = array( $this->make_comment( 'webmention' ) );

$separated = separate_comments( $comments );

$this->assertCount( 1, $separated['webmention'] );
$this->assertCount( 0, $separated['pings'] );
}

/**
* A comment stored with the legacy empty string type lands in the 'comment' bucket.
*
* @ticket 35214
*/
public function test_legacy_empty_type_lands_in_comment_bucket() {
$comments = array( $this->make_comment( '' ) );

$separated = separate_comments( $comments );

$this->assertCount( 1, $separated['comment'] );
$this->assertCount( 0, $separated['pings'] );
}
}
16 changes: 16 additions & 0 deletions tests/phpunit/tests/comment/types.php
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,22 @@ public function test_built_in_note_type_is_internal_and_non_public() {
*
* @covers ::comment_type_exists
*/
public function test_built_in_ping_types_are_marked_as_pings() {
$this->assertTrue( get_comment_type_object( 'pingback' )->is_ping );
$this->assertTrue( get_comment_type_object( 'trackback' )->is_ping );
}

/**
* @ticket 35214
*/
public function test_built_in_non_ping_types_are_not_marked_as_pings() {
$this->assertFalse( get_comment_type_object( 'comment' )->is_ping );
$this->assertFalse( get_comment_type_object( 'note' )->is_ping );
}

/**
* @ticket 35214
*/
public function test_comment_type_exists() {
$this->assertFalse( comment_type_exists( 'foo' ) );

Expand Down
Loading
Loading