Skip to content

Comments: Exclude notes from get_lastcommentmodified().#12573

Open
dhrupo wants to merge 1 commit into
WordPress:trunkfrom
dhrupo:notes-lastcommentmodified-exclude
Open

Comments: Exclude notes from get_lastcommentmodified().#12573
dhrupo wants to merge 1 commit into
WordPress:trunkfrom
dhrupo:notes-lastcommentmodified-exclude

Conversation

@dhrupo

@dhrupo dhrupo commented Jul 17, 2026

Copy link
Copy Markdown

Trac ticket: https://core.trac.wordpress.org/ticket/65657

Summary

get_lastcommentmodified() returns the date of the most recent approved comment, and WP::send_headers() uses it (max'd with get_lastpostmodified()) to build the Last-Modified and ETag headers for the comments feed.

Its three queries did not exclude the internal note comment type:

SELECT comment_date_gmt FROM wp_comments WHERE comment_approved = '1' ORDER BY comment_date_gmt DESC LIMIT 1

Notes are stored as approved comments (comment_type = 'note'), so adding or resolving a note makes it the most recent comment. The public comments feed's Last-Modified/ETag then change, even though the feed body already excludes notes (#64145 / #65613) and did not change.

Consequences:

  • Conditional GET (304 Not Modified) caching of the comments feed is defeated whenever notes are used — clients and CDNs re-fetch an identical feed.
  • The public Last-Modified header exposes the timing of internal editorial notes.

Reproduction

On a site using Notes:

curl -I '/?feed=comments-rss2'   # note Last-Modified + ETag
# add an internal note to any post
curl -I '/?feed=comments-rss2'   # Last-Modified + ETag have changed; feed body is unchanged

Verified live: adding one note moved Last-Modified from Fri, 01 Jan 2027 10:00:00 GMT to Sat, 02 Jan 2027 10:00:00 GMT and changed the ETag. See the before/after screenshots on the Trac ticket.

Fix

Add AND comment_type != 'note' to the three get_lastcommentmodified() queries, matching the exclusion already used by wp_update_comment_count_now() and the comment feed queries.

Testing

Added test_notes_are_excluded to Tests_Comment_GetLastCommentModified.

  • Before the fix, it fails: Failed asserting that <note timestamp> is identical to <regular-comment timestamp>.
  • After the fix, it passes.

Full comment group is green:

./vendor/bin/phpunit --group comment
OK (583 tests, 1428 assertions)

Use of AI Tools

AI assistance: Yes
Tool(s): Claude Code
Model(s): Claude Opus 4.8
Used for: Auditing the notes-exclusion surfaces, reproducing the feed-header change, implementing the fix, and writing the regression test. All changes were reviewed by me.

get_lastcommentmodified() returns the date of the most recent approved
comment, and WP::send_headers() uses it to build the Last-Modified and ETag
headers for the comments feed. The query did not exclude the internal
'note' comment type, so adding or resolving a note (approved, but never
part of the public feed) changed the feed's Last-Modified/ETag even though
the feed content -- which already excludes notes, see #64145 -- did not
change. This defeated conditional GET (304) caching of the comments feed
whenever notes are used, and exposed the timing of internal notes through
a public response header.

Add `comment_type != 'note'` to the three lastcommentmodified queries so
notes no longer affect the value, matching the exclusion already used by
wp_update_comment_count_now() and the comment feed queries.

Adds a regression test.

Fixes #65657.
@github-actions

Copy link
Copy Markdown

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

Core Committers: Use this line as a base for the props when committing in SVN:

Props dhrupo.

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@github-actions

Copy link
Copy Markdown

Test using WordPress Playground

The changes in this pull request can previewed and tested using a WordPress Playground instance.

WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser.

Some things to be aware of

  • All changes will be lost when closing a tab with a Playground instance.
  • All changes will be lost when refreshing the page.
  • A fresh instance is created each time the link below is clicked.
  • Every time this pull request is updated, a new ZIP file containing all changes is created. If changes are not reflected in the Playground instance,
    it's possible that the most recent build failed, or has not completed. Check the list of workflow runs to be sure.

For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation.

Test this pull request with WordPress Playground.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant