Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
b7cb7fc
Comments: Add filter for comment types excluded from queries by default
adamsilverstein Jun 24, 2026
4b57b1a
Apply suggestion from @adamsilverstein
adamsilverstein Jun 24, 2026
9e9fb0b
Apply suggestion from @adamsilverstein
adamsilverstein Jun 24, 2026
6e67226
Apply suggestion from @adamsilverstein
adamsilverstein Jun 24, 2026
237d916
Apply suggestion from @adamsilverstein
adamsilverstein Jun 24, 2026
bb238e9
Comments: Clarify the default_excluded_comment_types filter is not ac…
adamsilverstein Jun 25, 2026
1a4bf12
Comments: Feed default_excluded_comment_types into the comment counter.
adamsilverstein Jun 25, 2026
2f75e55
Comments: Honor default_excluded_comment_types in pending counts.
adamsilverstein Jun 25, 2026
e656cbd
Comments: Extract wp_get_default_excluded_comment_types().
adamsilverstein Jul 11, 2026
9355bd4
Merge branch 'trunk' into feature/65537-excluded-comment-types-filter
adamsilverstein Jul 17, 2026
e0d3cf9
Comments: Treat aliased type requests as explicit against excluded ty…
adamsilverstein Jul 17, 2026
4f69762
Comments: Keep a comment type named '0' in the excluded types list.
adamsilverstein Jul 17, 2026
0ded145
Comments: Drop the unsupported "feeds" claim from the filter docblock.
adamsilverstein Jul 17, 2026
c082ed3
Comments: Apply the excluded types filter in the comments list table.
adamsilverstein Jul 17, 2026
bebcf94
Merge branch 'trunk' into feature/65537-excluded-comment-types-filter
adamsilverstein Jul 23, 2026
91e2876
Merge branch 'trunk' into feature/65537-excluded-comment-types-filter
adamsilverstein Jul 24, 2026
b3fc3ef
Comments: Drop non-scalar values from the excluded comment types filter.
adamsilverstein Jul 24, 2026
e658376
Potential fix for pull request finding
adamsilverstein Jul 24, 2026
3e371d0
Merge branch 'trunk' into feature/65537-excluded-comment-types-filter
adamsilverstein Jul 24, 2026
3d507a5
Merge branch 'trunk' into feature/65537-excluded-comment-types-filter
adamsilverstein Jul 24, 2026
29af50b
Merge branch 'trunk' into feature/65537-excluded-comment-types-filter
adamsilverstein Jul 25, 2026
e0e1c5e
Comments: Let the list table show an explicitly requested excluded type.
adamsilverstein Jul 25, 2026
106def5
Merge branch 'trunk' into feature/65537-excluded-comment-types-filter
adamsilverstein Jul 26, 2026
0a788e4
Merge remote-tracking branch 'origin/trunk' into feature/65537-exclud…
adamsilverstein Aug 12, 2026
50e826e
Comments: Include the excluded comment types in the comment query cac…
adamsilverstein Aug 12, 2026
ef244ab
Comments: Exclude the default-excluded comment types from the comment…
adamsilverstein Aug 12, 2026
f1bc386
Comments: Default the excluded comment types to the registered intern…
adamsilverstein Aug 12, 2026
5aec019
Comments: Pin the visibility boundaries of the excluded comment types.
adamsilverstein Aug 12, 2026
05d3739
Comments: Filter empty excluded comment types with a boolean callback.
adamsilverstein Aug 12, 2026
eee634d
Comments: Apply the default comment type exclusions to comment page m…
adamsilverstein Aug 12, 2026
00576f0
Comments: Stamp the excluded-types filter work for 7.2.0.
adamsilverstein Aug 23, 2026
280fcd6
Comments: Use the block format for multi-line inline comments.
adamsilverstein Aug 27, 2026
8c5fea7
Comments: Ignore a non-string comment_type request in the list table.
adamsilverstein Aug 27, 2026
217a46c
Merge trunk into feature/65537-excluded-comment-types-filter
adamsilverstein Sep 30, 2026
a702772
Merge trunk into feature/65537-excluded-comment-types-filter
adamsilverstein Oct 12, 2026
9c7aef6
Merge remote-tracking branch 'origin/trunk' into feature/65537-exclud…
adamsilverstein Nov 8, 2026
94dc58f
Comments: Quote the excluded types column with %i and drop the unders…
adamsilverstein Nov 8, 2026
d4c6e2f
Comments: Keep 'all' as the comment page math default.
adamsilverstein Nov 8, 2026
14dc7d6
Tests: Tidy the excluded comment types tests per review.
adamsilverstein Nov 8, 2026
f057225
Tests: Update the excluded comment type tests for trunk's reaction type.
adamsilverstein Nov 8, 2026
fe9237a
Merge remote-tracking branch 'fork/feature/65537-excluded-comment-typ…
adamsilverstein Nov 8, 2026
fc67e40
Merge remote-tracking branch 'fork/feature/65537-excluded-comment-typ…
adamsilverstein Nov 8, 2026
7b3cf9f
Merge remote-tracking branch 'origin/trunk' into feature/65537-exclud…
adamsilverstein Nov 8, 2026
d13a613
Comments: Apply the excluded comment types to get_lastcommentmodified().
adamsilverstein Nov 8, 2026
c9ad985
Comments: Tighten the excluded comment types documentation.
adamsilverstein Nov 8, 2026
5dba100
Tests: Add native return types to the excluded comment types tests.
adamsilverstein Nov 8, 2026
c11b38b
Docs: Mark the new comment type APIs as @since 7.3.0.
adamsilverstein Nov 8, 2026
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
25 changes: 23 additions & 2 deletions src/wp-admin/includes/class-wp-comments-list-table.php
Original file line number Diff line number Diff line change
Expand Up @@ -105,12 +105,33 @@ public function prepare_items() {
$comment_status = 'all';
}

/*
* Notes and reactions cannot be requested as a type here, unlike other
* default-excluded types. A non-string request is ignored.
*/
$comment_type = '';

if ( ! empty( $_REQUEST['comment_type'] ) && ! in_array( $_REQUEST['comment_type'], array( 'note', 'reaction' ), true ) ) {
if ( ! empty( $_REQUEST['comment_type'] ) && is_string( $_REQUEST['comment_type'] ) && ! in_array( $_REQUEST['comment_type'], array( 'note', 'reaction' ), true ) ) {
$comment_type = $_REQUEST['comment_type'];
}

/*
* The default exclusions are passed explicitly so they still apply to an 'all'
* request. The requested type is kept, so a plugin can list its own excluded
* type via the 'admin_comment_types_dropdown' filter.
*/
switch ( $comment_type ) {
case 'pings':
$requested_types = array( 'pingback', 'trackback' );
break;

default:
$requested_types = array( $comment_type );
break;
}

$excluded_types = array_values( array_diff( wp_get_default_excluded_comment_types(), $requested_types ) );

$search = $_REQUEST['s'] ?? '';

$post_type = ( isset( $_REQUEST['post_type'] ) ) ? sanitize_key( $_REQUEST['post_type'] ) : '';
Expand Down Expand Up @@ -157,7 +178,7 @@ public function prepare_items() {
'number' => $number,
'post_id' => $post_id,
'type' => $comment_type,
'type__not_in' => array( 'note', 'reaction' ),
'type__not_in' => $excluded_types,
'orderby' => $orderby,
'order' => $order,
Comment on lines 179 to 183

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, fixed in e0e1c5e.

I didn't drop type__not_in entirely though - the list table still has to force the exclusions for a type=all request. WP_Comment_Query skips its default exclusions when 'all' is requested, and there is an existing test (test_comments_list_table_does_not_show_note_comment_type, added for #64198/#64474) asserting notes stay hidden on edit-comments.php?comment_type=all. Removing the arg outright regresses that.

Instead the requested type is now subtracted from the exclusion list before the query runs, with the 'comment'/'comments'/'pings' aliases expanded the same way WP_Comment_Query expands them:

$excluded_types = array_values( array_diff( wp_get_default_excluded_comment_types(), $requested_types ) );

The 'note' type is still stripped from the request a few lines above, so that one remains unlistable in the admin regardless.

Added two tests in tests/phpunit/tests/admin/wpCommentsListTable.php: a filtered-in 'private' type stays hidden for both an empty and an all request, and it is listed when explicitly selected. The second one fails against the old code (0 items) and passes now.

'post_type' => $post_type,
Expand Down
7 changes: 6 additions & 1 deletion src/wp-admin/includes/comment.php
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,8 @@ function get_comment_to_edit( $id ) {
* @since 2.3.0
* @since 6.9.0 Exclude the 'note' comment type from the count.
* @since 7.2.0 Exclude the 'reaction' comment type from the count.
* @since 7.3.0 The excluded comment types are derived from the
* {@see 'default_excluded_comment_types'} filter.
*
* @global wpdb $wpdb WordPress database abstraction object.
*
Expand All @@ -243,7 +245,10 @@ function get_pending_comments_num( $post_id ) {
$post_id_array = array_map( 'intval', $post_id_array );
$post_id_in = "'" . implode( "', '", $post_id_array ) . "'";

$pending = $wpdb->get_results( "SELECT comment_post_ID, COUNT(comment_ID) as num_comments FROM $wpdb->comments WHERE comment_post_ID IN ( $post_id_in ) AND comment_approved = '0' AND comment_type NOT IN ( 'note', 'reaction' ) GROUP BY comment_post_ID", ARRAY_A );
$type_not_in = wp_get_excluded_comment_types_clause();

// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- $post_id_in holds integers and $type_not_in is prepared.
$pending = $wpdb->get_results( "SELECT comment_post_ID, COUNT(comment_ID) as num_comments FROM $wpdb->comments WHERE comment_post_ID IN ( $post_id_in ) AND comment_approved = '0'$type_not_in GROUP BY comment_post_ID", ARRAY_A );

if ( $single ) {
if ( empty( $pending ) ) {
Expand Down
53 changes: 50 additions & 3 deletions src/wp-includes/class-wp-comment-query.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,14 @@ class WP_Comment_Query {
*/
protected $filtered_where_clause;

/**
* Comment types excluded from the results by default, or null until resolved.
*
* @since 7.3.0
* @var string[]|null
*/
protected $default_excluded_comment_types = null;

/**
* Date query container
*
Expand Down Expand Up @@ -460,6 +468,14 @@ public function get_comments() {
$_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'] );

/*
* The excluded set changes the results without bumping 'last_changed', so it is
* part of the key. get_comment_ids() reuses it.
*/
$this->default_excluded_comment_types = wp_get_default_excluded_comment_types( $this );

$_args['default_excluded_comment_types'] = $this->default_excluded_comment_types;

$key = md5( serialize( $_args ) );
$last_changed = wp_cache_get_last_changed( 'comment' );

Expand Down Expand Up @@ -550,6 +566,7 @@ public function get_comments() {
* @since 4.4.0
* @since 6.9.0 Excludes the 'note' comment type, unless 'all' or the 'note' types are requested.
* @since 7.2.0 Excludes the 'reaction' comment type, unless 'all' or the 'reaction' types are requested.
* @since 7.3.0 The default-excluded comment types are filterable via {@see 'default_excluded_comment_types'}.
*
* @global wpdb $wpdb WordPress database abstraction object.
*
Expand Down Expand Up @@ -781,11 +798,41 @@ protected function get_comment_ids() {
'NOT IN' => (array) $this->query_vars['type__not_in'],
);

// Exclude the 'note' and 'reaction' comment types, unless 'all' types or that type explicitly are requested.
// Resolved in get_comments() when the cache key is built; resolve here for direct calls.
if ( null === $this->default_excluded_comment_types ) {
$this->default_excluded_comment_types = wp_get_default_excluded_comment_types( $this );
}

$excluded_types = $this->default_excluded_comment_types;

/*
* Unless 'all' is requested, exclude each default-excluded type the query does not
* request. Aliases are expanded so a type requested via 'pings' stays included.
*/
if ( ! in_array( 'all', $raw_types['IN'], true ) ) {
foreach ( array( 'note', 'reaction' ) as $excluded_type ) {
$requested_types = array();
foreach ( $raw_types['IN'] as $requested_type ) {
switch ( $requested_type ) {
case 'comment':
case 'comments':
$requested_types[] = '';
$requested_types[] = 'comment';
break;

case 'pings':
$requested_types[] = 'pingback';
$requested_types[] = 'trackback';
break;

default:
$requested_types[] = $requested_type;
break;
}
}

foreach ( $excluded_types as $excluded_type ) {
if (
! in_array( $excluded_type, $raw_types['IN'], true ) &&
! in_array( $excluded_type, $requested_types, true ) &&
! in_array( $excluded_type, $raw_types['NOT IN'], true )
) {
$raw_types['NOT IN'][] = $excluded_type;
Expand Down
10 changes: 7 additions & 3 deletions src/wp-includes/class-wp-query.php
Original file line number Diff line number Diff line change
Expand Up @@ -2822,13 +2822,15 @@ public function get_posts() {

// Comments feeds.
if ( $this->is_comment_feed && ! $this->is_singular ) {
$ctype_not_in = wp_get_excluded_comment_types_clause( "{$wpdb->comments}.comment_type" );

if ( $this->is_archive || $this->is_search ) {
$cjoin = "JOIN {$wpdb->posts} ON ( {$wpdb->comments}.comment_post_ID = {$wpdb->posts}.ID ) $join ";
$cwhere = "WHERE comment_approved = '1' AND {$wpdb->comments}.comment_type NOT IN ( 'note', 'reaction' ) $where";
$cwhere = "WHERE comment_approved = '1'$ctype_not_in $where";
$cgroupby = "{$wpdb->comments}.comment_id";
} else { // Other non-singular, e.g. front.
$cjoin = "JOIN {$wpdb->posts} ON ( {$wpdb->comments}.comment_post_ID = {$wpdb->posts}.ID )";
$cwhere = "WHERE ( post_status = 'publish' OR ( post_status = 'inherit' AND post_type = 'attachment' ) ) AND comment_approved = '1' AND {$wpdb->comments}.comment_type NOT IN ( 'note', 'reaction' )";
$cwhere = "WHERE ( post_status = 'publish' OR ( post_status = 'inherit' AND post_type = 'attachment' ) ) AND comment_approved = '1'$ctype_not_in";
$cgroupby = '';
}

Expand Down Expand Up @@ -3541,11 +3543,13 @@ public function get_posts() {
}

if ( ! empty( $this->posts ) && $this->is_comment_feed && $this->is_singular ) {
$ctype_not_in = wp_get_excluded_comment_types_clause( "{$wpdb->comments}.comment_type" );

/** This filter is documented in wp-includes/class-wp-query.php */
$cjoin = apply_filters_ref_array( 'comment_feed_join', array( '', &$this ) );

/** This filter is documented in wp-includes/class-wp-query.php */
$cwhere = apply_filters_ref_array( 'comment_feed_where', array( "WHERE comment_post_ID = '{$this->posts[0]->ID}' AND comment_approved = '1' AND {$wpdb->comments}.comment_type NOT IN ( 'note', 'reaction' )", &$this ) );
$cwhere = apply_filters_ref_array( 'comment_feed_where', array( "WHERE comment_post_ID = '{$this->posts[0]->ID}' AND comment_approved = '1'$ctype_not_in", &$this ) );

/** This filter is documented in wp-includes/class-wp-query.php */
$cgroupby = apply_filters_ref_array( 'comment_feed_groupby', array( '', &$this ) );
Expand Down
Loading
Loading