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
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,18 @@

All notable changes to this project will be documented in this file, per [the Keep a Changelog standard](http://keepachangelog.com/).

## [Unreleased]

### Added

- WordPress 6.9+ Block Notes compatibility with disable comments feature.
- New filter `tenup_experience_disable_comments_allowed_types` to allow specific comment types when comments are disabled.

### Fixed

- Block Notes now work correctly when traditional comments are disabled.
- Comment query filters now properly check comment type before short-circuiting.

## [1.17.0] - 2025-12-18
* Make sure user roles are unindexed arrays by @felipeelia in https://github.com/10up/10up-experience/pull/186
* Bump express from 4.19.2 to 4.22.1 in the npm_and_yarn group across 1 directory by @dependabot[bot] in https://github.com/10up/10up-experience/pull/188
Expand Down
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,17 @@ On top of disabling the comment form, this feature removes the following:
- Comment blocks from the post editor.
- Comments from the admin bar.

#### WordPress 6.9+ Block Notes Compatibility

As of version 1.17.0, the disable comments feature is fully compatible with Block Notes introduced in WordPress 6.9. Block Notes are a collaborative feedback feature that allows teams to leave contextual comments on blocks within the editor.
Copy link

Copilot AI Dec 17, 2025

Choose a reason for hiding this comment

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

The version number mentioned here (1.17.0) is inconsistent with the @SInCE tags in the code which reference 1.12.0. Please ensure the version number is accurate and consistent across all documentation.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This version will actually be 1.18.0 following semver 🙂

Suggested change
As of version 1.17.0, the disable comments feature is fully compatible with Block Notes introduced in WordPress 6.9. Block Notes are a collaborative feedback feature that allows teams to leave contextual comments on blocks within the editor.
As of version 1.18.0, the disable comments feature is fully compatible with Block Notes introduced in WordPress 6.9. Block Notes are a collaborative feedback feature that allows teams to leave contextual comments on blocks within the editor.


When comments are disabled, Block Notes will continue to function normally because they:
- Use a different comment type (`note` instead of `comment`)
- Rely on `edit_post` capability rather than comment capabilities
- Are only visible within the block editor, not on the frontend

This means you can safely disable traditional comments while still using Block Notes for editorial collaboration.

#### Constants

- `TENUP_DISABLE_COMMENTS`
Expand All @@ -216,6 +227,19 @@ Setting this constant will disable the UI for enabling/disabling comments in the
Filters whether to disable comments. Default is `false`.
Defining this filter will disable the UI for enabling/disabling comments in the admin.

- `tenup_experience_disable_comments_allowed_types`

Filters the list of comment types that should bypass the disable comments feature. By default, this includes `note` for WordPress 6.9+ Block Notes. This allows plugins to extend the list of comment types that should continue to function when traditional comments are disabled.

Example:

```php
add_filter( 'tenup_experience_disable_comments_allowed_types', function( $allowed_types ) {
$allowed_types[] = 'custom_comment_type';
return $allowed_types;
} );
```

- `tenup_experience_disable_comments_disallowed_blocks`

Filters the list of blocks that should be disallowed when comments are disabled. This is useful when core adds new blocks that aren't covered by the default list.
Expand Down
101 changes: 91 additions & 10 deletions includes/classes/Comments/Comments.php
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,37 @@ protected function is_ui_disabled() {
return defined( 'TENUP_DISABLE_COMMENTS' ) || has_filter( 'tenup_experience_disable_comments' );
}

/**
* Get the list of comment types that should bypass disable comments filters.
*
* This allows certain comment types (like Block Notes introduced in WordPress 6.9)
* to continue functioning even when traditional comments are disabled.
*
* Block Notes are stored as WP_Comments with a comment_type of 'note' and are used
* for collaborative feedback within the block editor. They rely on edit_post capability
* rather than comment capabilities.
*
* @since 1.12.0
* @see https://make.wordpress.org/core/2025/11/15/notes-feature-in-wordpress-6-9/
*
* @return array Array of comment types that should be allowed.
*/
protected function get_allowed_comment_types() {
$allowed_types = array( 'note' );

/**
* Filter the list of comment types that bypass the disable comments feature.
*
* This allows plugins to extend the list of comment types that should continue
* to function when traditional comments are disabled.
*
* @since 1.12.0
*
* @param array $allowed_types Array of comment type strings.
*/
return apply_filters( 'tenup_experience_disable_comments_allowed_types', $allowed_types );
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

My preference here is to ensure an array is always returned for better type safety.

Suggested change
return apply_filters( 'tenup_experience_disable_comments_allowed_types', $allowed_types );
$allowed_types = apply_filters( 'tenup_experience_disable_comments_allowed_types', $allowed_types );
return is_array( $allowed_types ) ? $allowed_types : array();

}

/**
* Register restrict REST API setting.
*
Expand Down Expand Up @@ -258,35 +289,85 @@ public function remove_comments_admin_bar_links() {
/**
* Hide any existing comments on front end
*
* @return array
* This filter preserves certain comment types (like Block Notes) while hiding
* traditional comments from the frontend.
*
* @since 1.11.2
*
* @param array $comments Array of comments.
* @param int $post_id Post ID.
*
* @return array Filtered array of comments.
*/
public function disable_comments_hide_existing_comments() {
return [];
public function disable_comments_hide_existing_comments( $comments, $post_id ) {
$allowed_types = $this->get_allowed_comment_types();

// If no allowed types, return empty array (original behavior).
if ( empty( $allowed_types ) ) {
return array();
}

// Filter to only include allowed comment types (e.g., Block Notes).
return array_filter(
$comments,
function ( $comment ) use ( $allowed_types ) {
return in_array( $comment->comment_type, $allowed_types, true );
}
);
}

/**
* Disable commenting
*
* @return boolean
* Block Notes do not rely on the comments_open or pings_open filters,
* so this can safely return false for all contexts.
*
* @since 1.11.2
*
* @param bool $open Whether comments are open.
* @param int $post_id Post ID.
*
* @return bool Always returns false to disable commenting.
*/
public function disable_comments_status() {
public function disable_comments_status( $open, $post_id ) {
return false;
}

/**
* Short-circuit WP_Comment_Query
*
* @param array $comment_data Comment data.
* @param array $query Query data.
* This filter prevents traditional comment queries from executing, but allows
* certain comment types (like Block Notes) to pass through by checking the
* query's 'type' parameter.
*
* Block Notes (WordPress 6.9+) are stored as WP_Comments with comment_type='note'
* and must be able to query the database for the Notes feature to work.
*
* @since 1.11.2
* @see https://make.wordpress.org/core/2025/11/15/notes-feature-in-wordpress-6-9/
*
* @param array|int|null $comment_data Comment data (null to allow query to proceed).
* @param \WP_Comment_Query $query The WP_Comment_Query instance.
*
* @return array|int|null
* @return array|int|null Returns null to allow query, or array/int to short-circuit.
*/
public function filter_comments_pre_query( $comment_data, $query ) {

if ( is_a( $query, '\WP_Comment_Query' ) && $query->query_vars['count'] ) {
return 0;
if ( is_a( $query, '\WP_Comment_Query' ) ) {
$comment_type = $query->query_vars['type'] ?? '';

// Allow certain comment types (like Block Notes) to pass through.
if ( in_array( $comment_type, $this->get_allowed_comment_types(), true ) ) {
return $comment_data; // Return null to allow the query to proceed.
}

// Short-circuit count queries for traditional comments.
if ( $query->query_vars['count'] ) {
return 0;
}
}
Comment on lines +356 to 368
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot made a valid point here, the type param can be an array, so we should handle it in a way that allows that. This should update your code to handle it gracefully.

I guess one question I have is; if we have a query with the type of ['note', 'comment'] this will let it work as-is. Should we instead clobber any non-allowlisted comment types? So ['note', 'comment'] would become ['note']?

That would ensure that we don't accidentally leak other comment types in queries, but also since I'm not close to this feature, I don't know if it will break anything.

Suggested change
if ( is_a( $query, '\WP_Comment_Query' ) ) {
$comment_type = $query->query_vars['type'] ?? '';
// Allow certain comment types (like Block Notes) to pass through.
if ( in_array( $comment_type, $this->get_allowed_comment_types(), true ) ) {
return $comment_data; // Return null to allow the query to proceed.
}
// Short-circuit count queries for traditional comments.
if ( $query->query_vars['count'] ) {
return 0;
}
}
// Only handle WP_Comment_Query instances.
if ( ! is_a( $query, '\WP_Comment_Query' ) ) {
return array();
}
$allowed_types = $this->get_allowed_comment_types();
$requested_types = $query->query_vars['type'] ?? '';
// Normalise "type" to an array.
if ( '' === $requested_types || null === $requested_types ) {
$requested_types = array();
} elseif ( ! is_array( $requested_types ) ) {
$requested_types = array( $requested_types );
}
// Does this query include any allowed comment types?
$has_allowed_type = ! empty( array_intersect( $requested_types, $allowed_types ) );
// Allow queries that involve any of the allowed types to run as normal.
if ( $has_allowed_type ) {
return $comment_data;
}
// If this is a count query, return 0 instead of letting WP run the full query.
if ( ! empty( $query->query_vars['count'] ) ) {
return 0;
}


// Short-circuit all other comment queries.
return array();
}

Expand Down
Loading