Skip to content

REST API: Reject note replies and changes to a deleted note - #14560

Open
yyppsk wants to merge 1 commit into
WordPress:trunkfrom
yyppsk:66351-notes-deleted-note
Open

yyppsk wants to merge 1 commit into
WordPress:trunkfrom
yyppsk:66351-notes-deleted-note

Conversation

@yyppsk

@yyppsk yyppsk commented Oct 20, 2026 •

Copy link
Copy Markdown

Another editor session can delete a note while it is still open. The REST API then accepts changes to the deleted note that the editor can no longer show:

  • A reply submitted after the delete returns 201, and the editor announces "Reply added.", but the reply is stored under the trashed note and is not shown anywhere.
  • Reopen & Reply on a resolved note first sets the note's status, which moves it out of the trash without the replies trashed along with it, then adds the reply. The thread comes back with only the new reply.
  • Resolving or editing a deleted note is accepted the same way.

This PR changes WP_REST_Comments_Controller:

  • create_item() rejects a note reply whose parent is trashed, spam, or no longer exists, with 400 rest_comment_invalid_parent. Reactions are already rejected on a trashed or spam note.
  • update_item() rejects any change to a trashed or spam note other than restoring it (status of untrash or unspam), with 400 rest_comment_invalid_status. Undo in the editor sends untrash, so it keeps working.

The editor already shows REST error messages in a snackbar, and keeps the note form's text when a save fails, so no client changes are needed. The same change is in the Gutenberg plugin's 7.2 compat controller: WordPress/gutenberg#85202. Originally reported in WordPress/gutenberg#80678.

Testing Instructions

  1. Sign the same administrator into two browser sessions, A and B (for example a normal and a private window).
  2. In A, create a post, add a Paragraph, add a note to it, and save the draft.
  3. Open the same post in B and open All notes.
  4. In A, select the note and type a reply, but don't submit it.
  5. In B, delete the note from its Actions menu and wait for "Note deleted.".
  6. In A, without reloading, click Reply.
    • Before: "Reply added." The reply is not shown after a reload, but it is stored under the deleted note.
    • After: "This note was deleted, so your reply could not be added." The reply text stays in the form.

For Reopen & Reply, resolve the note in A before step 4. Clicking Reopen & Reply after the delete:

  • Before: brings the deleted note back as open, with only the new reply. Its earlier replies stay in the trash.
  • After: "This note was deleted, so it could not be updated." The note stays deleted.

The console snippet in the Trac ticket reproduces both in a single session. With this PR, its first request fails with 400.

Unit tests: npm run test:php -- --group 66351

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

Use of AI Tools

AI assistance: Yes
Tool(s): Claude Code
Model(s): Claude Opus 5.5
Used for: In-depth reproduction of both issues, verifying the fix, and assisting with a valid patch and PHPUnit tests.


This Pull Request is for code review only. Please keep all other discussion in the Trac ticket. Do not merge this Pull Request. See GitHub Pull Requests for Code Review in the Core Handbook for more details.

Another editor session can delete a note while it is still open. A
reply submitted afterwards was stored under the trashed note and no
longer shown anywhere in the editor. Reopening a resolved note with a
reply set the note's status, which moved it out of the trash without
the replies trashed along with it. Resolving or editing a deleted note
was accepted the same way.

Reject a note reply whose parent is trashed, spam or no longer exists,
as reactions already are, and reject any change to a trashed or spam
note other than restoring it. The editor then shows an error and keeps
the typed text, and Undo still restores a deleted note.

See #66351.
@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 pranjalpratapsingh.

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