Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
14 commits
Select commit Hold shift + click to select a range
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
32 changes: 29 additions & 3 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.2.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 Expand Up @@ -260,6 +263,7 @@ public function end_el( &$output, $data_object, $depth = 0, $args = array() ) {
* Outputs a pingback comment.
*
* @since 3.6.0
* @since 7.2.0 A registered, non-built-in ping type is labeled with its singular name.
*
* @see wp_list_comments()
*
Expand All @@ -269,10 +273,32 @@ public function end_el( &$output, $data_object, $depth = 0, $args = array() ) {
*/
protected function ping( $comment, $depth, $args ) {
$tag = ( 'div' === $args['style'] ) ? 'div' : 'li';

/*
* The built-in ping types share the 'Pingback:' label - trackbacks have carried it
* since 3.6 - so their markup is unchanged. A registered ping type would be
* mislabeled by it, so use its own singular name instead, matching comment_type().
* A ping type registered without labels inherits the default 'Comment' singular
* name, which is even more wrong for a ping, so such types keep 'Pingback:' too.
*/
$comment_type_object = get_comment_type_object( $comment->comment_type );
$default_labels = WP_Comment_Type::get_default_labels();

if (
$comment_type_object
&& ! $comment_type_object->_builtin
&& isset( $comment_type_object->labels->singular_name )
&& $default_labels['singular_name'][0] !== $comment_type_object->labels->singular_name
) {
/* translators: %s: Singular name of a registered comment type, e.g. "Webmention". */
$label = sprintf( _x( '%s:', 'comment type label' ), esc_html( $comment_type_object->labels->singular_name ) );
} else {
$label = __( 'Pingback:' );
}
?>
<<?php echo $tag; ?> id="comment-<?php comment_ID(); ?>" <?php comment_class( '', $comment ); ?>>
<div class="comment-body">
<?php _e( 'Pingback:' ); ?> <?php comment_author_link( $comment ); ?> <?php edit_comment_link( __( 'Edit' ), '<span class="edit-link">', '</span>' ); ?>
<?php echo $label; ?> <?php comment_author_link( $comment ); ?> <?php edit_comment_link( __( 'Edit' ), '<span class="edit-link">', '</span>' ); ?>
</div>
<?php
}
Expand Down
97 changes: 85 additions & 12 deletions src/wp-includes/class-wp-comment-query.php
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,18 @@ class WP_Comment_Query {
*/
public $max_num_pages = 0;

/**
* Comment types a 'pings' type token expands to.
*
* Resolved lazily, once per parsed query, so that the set folded into the cache
* keys is the same one get_comment_ids() builds the SQL from. Reset by
* parse_query(); null until resolved.
*
* @since 7.2.0
* @var string[]|null
*/
protected $ping_comment_types = null;

/**
* Make private/protected methods readable for backward compatibility.
*
Expand Down Expand Up @@ -149,6 +161,7 @@ public function __call( $name, $arguments ) {
* @since 4.9.0 Introduced the `$paged` argument.
* @since 5.1.0 Introduced the `$meta_compare_key` argument.
* @since 5.3.0 Introduced the `$meta_type_key` argument.
* @since 7.2.0 A `$type` of 'pings' expands to every comment type registered with `is_ping`.
*
* @param string|array $query {
* Optional. Array or query string of comment query parameters. Default empty.
Expand Down Expand Up @@ -251,7 +264,8 @@ public function __call( $name, $arguments ) {
* 'approve' (`comment_status=1`), 'all', or a custom
* comment status. Default 'all'.
* @type string|string[] $type Include comments of a given type, or array of types.
* Accepts 'comment', 'pings' (includes 'pingback' and
* Accepts 'comment', 'pings' (every comment type registered
* with `is_ping`, which includes 'pingback' and
* 'trackback'), or any custom type string. Default empty.
* @type string[] $type__in Include comments from a given array of comment types.
* Default empty.
Expand Down Expand Up @@ -343,6 +357,9 @@ public function parse_query( $query = '' ) {

$this->query_vars = wp_parse_args( $query, $this->query_var_defaults );

// Re-resolve the ping types per query, in case the registry changed in between.
$this->ping_comment_types = null;

/**
* Fires after the comment query vars have been parsed.
*
Expand Down Expand Up @@ -448,14 +465,7 @@ public function get_comments() {
return $comment_data;
}

/*
* Only use the args defined in the query_var_defaults to compute the key,
* but ignore 'fields', 'update_comment_meta_cache', 'update_comment_post_cache' which does not affect query results.
*/
$_args = wp_array_slice_assoc( $this->query_vars, array_keys( $this->query_var_defaults ) );
unset( $_args['fields'], $_args['update_comment_meta_cache'], $_args['update_comment_post_cache'] );

$key = md5( serialize( $_args ) );
$key = md5( serialize( $this->get_cache_key_args() ) );
$last_changed = wp_cache_get_last_changed( 'comment' );

$cache_key = "get_comments:$key";
Expand Down Expand Up @@ -806,8 +816,9 @@ protected function get_comment_ids() {
break;

case 'pings':
$comment_types[ $operator ][] = "'pingback'";
$comment_types[ $operator ][] = "'trackback'";
foreach ( $this->get_ping_comment_types() as $ping_type ) {
$comment_types[ $operator ][] = $wpdb->prepare( '%s', $ping_type );
}
break;

default:
Expand Down Expand Up @@ -1006,6 +1017,68 @@ protected function get_comment_ids() {
}
}

/**
* Builds the normalized set of query vars that comment query cache keys hash.
*
* Only uses the args defined in the query_var_defaults, ignoring 'fields',
* 'update_comment_meta_cache', and 'update_comment_post_cache', which do not
* affect query results.
*
* A 'pings' token expands to the registered ping types, which a plugin can change
* from one request to the next, so the resolved set belongs in the cache key. The
* comment last_changed salt only moves when a comment does, and would not catch
* it. Both the main query cache in get_comments() and the per-parent descendant
* caches in fill_descendants() hash these args, so the two cannot disagree.
*
* @since 7.2.0
*
* @return array Query vars to hash into a cache key.
*/
protected function get_cache_key_args() {
$_args = wp_array_slice_assoc( $this->query_vars, array_keys( $this->query_var_defaults ) );
unset( $_args['fields'], $_args['update_comment_meta_cache'], $_args['update_comment_post_cache'] );

$type_query_vars = array_merge(
(array) $this->query_vars['type'],
(array) $this->query_vars['type__in'],
(array) $this->query_vars['type__not_in']
);

if ( in_array( 'pings', $type_query_vars, true ) ) {
$_args['ping_comment_types'] = $this->get_ping_comment_types();
}

return $_args;
}

/**
* Resolves the comment types a 'pings' type token expands to.
*
* Matches how separate_comments() and wp_list_comments() group pings, so that a
* query for 'pings' returns the comments a theme would list under that heading.
*
* @since 7.2.0
*
* @return string[] Comment type names.
*/
protected function get_ping_comment_types() {
if ( null === $this->ping_comment_types ) {
$ping_types = get_comment_types( array( 'is_ping' => true ), 'names' );

/*
* The built-in ping types, for queries that run before create_initial_comment_types()
* in a partial bootstrap and for any install running without the registry.
*/
if ( ! $ping_types ) {
$ping_types = array( 'pingback', 'trackback' );
}

$this->ping_comment_types = array_values( $ping_types );
}

return $this->ping_comment_types;
}

/**
* Populates found_comments and max_num_pages properties for the current
* query if the limit clause was used.
Expand Down Expand Up @@ -1048,7 +1121,7 @@ protected function fill_descendants( $comments ) {
0 => wp_list_pluck( $comments, 'comment_ID' ),
);

$key = md5( serialize( wp_array_slice_assoc( $this->query_vars, array_keys( $this->query_var_defaults ) ) ) );
$key = md5( serialize( $this->get_cache_key_args() ) );
$last_changed = wp_cache_get_last_changed( 'comment' );

// Fetch an entire level of the descendant tree at a time.
Expand Down
25 changes: 25 additions & 0 deletions src/wp-includes/class-wp-comment-type.php
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,30 @@ 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 returned by a `'pings'` type query in
* {@see WP_Comment_Query}. When the `short_ping` argument of wp_list_comments()
* is true, they are rendered with the compact ping markup by
* {@see Walker_Comment}, which labels the comment with the type's
* `singular_name`, so a ping type should register one. 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.
*
* The flag drives grouping and display only. It does not change how a comment of
* this type is validated, moderated, or notified about: the pingback and trackback
* paths in {@see check_comment()}, {@see get_default_comment_status()}, and the
* notification emails are still keyed to those two type names. Default false.
*
* @since 7.2.0
* @var bool
*/
public $is_ping = false;

/**
* Whether the comment type is hierarchical.
*
Expand Down Expand Up @@ -230,6 +254,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
26 changes: 23 additions & 3 deletions src/wp-includes/comment.php
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,7 @@ function create_initial_comment_types() {
'singular_name' => __( 'Pingback' ),
),
'public' => true,
'is_ping' => true,
'_builtin' => true,
)
);
Expand All @@ -377,6 +378,7 @@ function create_initial_comment_types() {
'singular_name' => __( 'Trackback' ),
),
'public' => true,
'is_ping' => true,
'_builtin' => true,
)
);
Expand Down Expand Up @@ -450,6 +452,17 @@ function create_initial_comment_types() {
* counts by default. Core does not currently act on this
* argument.
* 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(),
* returned by a 'pings' type query, and, when
* wp_list_comments() is called with 'short_ping', rendered
* with compact ping markup by Walker_Comment, labeled with the
* type's singular name. A registered 'render_callback' takes
* precedence over the ping markup. The flag drives grouping
* and display only; validation, moderation, and notification
* still key on the 'pingback' and 'trackback' type names.
* 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 @@ -1387,6 +1400,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.2.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 @@ -1410,7 +1426,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 Expand Up @@ -1490,7 +1508,8 @@ function get_comment_pages_count( $comments = null, $per_page = null, $threaded
*
* @type string $type Limit paginated comments to those matching a given type.
* Accepts 'comment', 'trackback', 'pingback', 'pings'
* (trackbacks and pingbacks), or 'all'. Default 'all'.
* (the comments of every registered comment type with
* `is_ping`), or 'all'. Default 'all'.
* @type int $per_page Per-page count to use when calculating pagination.
* Defaults to the value of the 'comments_per_page' option.
* @type int|string $max_depth If greater than 1, comment page will be determined
Expand Down Expand Up @@ -1590,7 +1609,8 @@ function get_page_of_comment( $comment_id, $args = array() ) {
*
* @type string $type Limit paginated comments to those matching a given type.
* Accepts 'comment', 'trackback', 'pingback', 'pings'
* (trackbacks and pingbacks), or 'all'. Default 'all'.
* (the comments of every registered comment type with
* `is_ping`), or 'all'. Default 'all'.
* @type int $post_id ID of the post.
* @type string $fields Comment fields to return.
* @type bool $count Whether to return a comment count (true) or array
Expand Down
Loading
Loading