You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Broken: no ability could mark an entry as spam. Lite had list-entries, get-entry and delete-entry only.
Changed
New ability formidable-forms/mark-entry-spam. Input: id (entry ID or item_key). It calls FrmSpamEntriesHelper::mark_as_spam(), the same method the Entries screen uses, so the entry is flagged as manual spam and its child entries move with it.
Returns the entry in the get-entry shape, with is_draft 4.
Permission: FrmSpamEntriesController::current_user_can_moderate() (frm_delete_entries), or an administrator, like delete-entry.
Annotations: not read-only, not destructive, idempotent. An entry that is already spam returns success, as reloading the Entries screen does.
A draft, or a site where spam can't be stored, returns a frm_entry_not_markable 400 error. A missing entry returns the usual 404.
Verified: Lite's local PHPUnit can't run here, so CI is the red/green. Test-only commit: all 4 PHPUnit jobs failed (The mark-entry-spam ability should be registered). With the fix, all 4 pass, plus PHPCS, PHPStan, Psalm, Mago, Rector and PHP CS Fixer. Tests cover the result and get-entry match, item_key lookup, repeat calls, draft and unknown IDs, the permission check, and the contract list.
Not checked: that the entry then shows in list-entries with is_draft: 4. That needs #3599. Not run through a live MCP client.
We reviewed changes in 1927ae3...700aa12 on this pull request. Below is the summary for the review, and you can see the individual issues we found as inline review comments.
AI Review is run only on demand for your team. We're only showing results of static analysis review right now. To trigger AI Review, comment @deepsourcebot review on this thread.
Moves a submitted entry to spam through FrmSpamEntriesHelper::mark_as_spam(),
gated on the same capability as the Entries screen.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The reason will be displayed to describe this comment to others. Learn more.
The ability works for normal entries, but it can mark a child entry as spam on its own. That one needs a fix before this merges.
Checked: I ran the PR's tests (FrmAbilitiesEntriesController and FrmAbilitiesContract, plus the MCP tests) on PHP 8.2 with Lite only: 35 pass. A probe confirmed: mark by item_key, result matches get-entry, is_draft 4, recorded as manual spam, repeat call succeeds, a draft returns 400, unknown id returns 404, subscriber is denied, parent plus child move together, and frm_entry_marked_spam fires once.
Blocking
A child entry (repeater or embedded form row) can be marked as spam by itself. See the inline comment.
Not blocking
execute_mark_entry_spam() treats any mark_as_spam() failure as a 400 "only a submitted entry" error. If another request marks the same entry first, this call fails even though the entry is spam. The Entries screen avoids this with mark_as_spam( $id ) || is_spam( getOne( $id ) ) (FrmSpamEntriesController::mark_spam()). Re-read the entry after a failure and return success if it is now spam.
The draft test passes the message as the second argument of assertWPError(), which does not check the message. Assert get_error_code() is frm_entry_not_markable and the status is 400. No test covers the parent-and-child move or the can_store_spam() false branch.
Not run: a live MCP client, Pro or Views loaded (Pro's own spam support), the full Lite suite.
The reason will be displayed to describe this comment to others. Learn more.
A child entry (a row where parent_item_id is not 0, from a repeater or embedded form) is accepted here. mark_as_spam() then sets only that row to is_draft 4. The parent stays submitted. I ran this: parent marked, child follows (good); child marked alone, parent stays is_draft 0 and the child becomes spam. The Entries screen only offers "Mark as spam" on top-level entries, and the PR body says child entries move with their parent, so this breaks that rule. The Spam tab does not list child rows, so the caller has no way to undo it.
Fix: refuse a child entry before marking it.
Suggested change
if ( ! $entry ) {
returnself::get_invalid_entry_error();
}
if ( ! $entry ) {
returnself::get_invalid_entry_error();
}
// A repeater or embedded form row moves to spam with its parent, never on its own.
if ( (int) $entry->parent_item_id > 0 ) {
returnnewWP_Error( 'frm_entry_not_markable', __( 'A child entry cannot be marked as spam on its own. Mark its parent entry instead.', 'formidable' ), array( 'status' => 400 ) );
}
Also add a test that marks a child entry and expects frm_entry_not_markable, and that the parent keeps is_draft 0.
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 194ac54 and 700aa12: a child entry now gets a 400 frm_entry_not_markable. A failed mark re-reads the entry after clearing the cache and returns success if it is now spam. Tests added for the child refusal, the parent moving its child, and the concurrent mark; the draft test asserts the error code and status. All PHPUnit jobs and PHPCS pass. The can_store_spam() false branch is not tested (needs a separate-process fixture), and neither a live MCP client nor Pro/Views was run.
The reason will be displayed to describe this comment to others. Learn more.
Approve at 700aa12. This is a re-review of the whole PR; what changed since my last pass at 5b7b278 is the controller guard and three tests.
Blocking item from last time: fixed.execute_mark_entry_spam() now returns a frm_entry_not_markable 400 when parent_item_id > 0, so a repeater or embedded-form row can no longer go to spam on its own. The parent still takes its children with it.
Non-blocking items from last time: also fixed.
After a failed mark_as_spam() it clears the cache, re-reads the entry and returns success if it is now spam. A racing request no longer turns into a false 400.
The draft test now asserts the error code and the 400 status.
New tests cover the child refusal, the parent-moves-its-children case and the race.
Verified by running it:
FrmAbilitiesEntriesController, FrmAbilitiesContract and the MCP tests: 38 pass on PHP 8.4, Lite only.
Mutation check: the old controller (5b7b278) fails the child test and the race test. Removing only the child guard fails the child test. Removing only the re-read fails the race test.
The can_store_spam() false branch has no test in the PR, so I probed it: with a FrmProAppHelper stub that lacks SPAM_ENTRIES_SUPPORTED, the call returns frm_entry_not_markable / "Spam entries cannot be stored while an active add-on does not support them." / status 400, and the entry stays is_draft 0.
Not run: a live MCP client, real Pro or Views loaded, the full Lite suite. DeepSource PHP is red only on PHPUnit assert methods it can't resolve; the other checks are green.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes Strategy11/formidable-pro#6863
Broken: no ability could mark an entry as spam. Lite had
list-entries,get-entryanddelete-entryonly.Changed
formidable-forms/mark-entry-spam. Input:id(entry ID or item_key). It callsFrmSpamEntriesHelper::mark_as_spam(), the same method the Entries screen uses, so the entry is flagged as manual spam and its child entries move with it.get-entryshape, withis_draft4.FrmSpamEntriesController::current_user_can_moderate()(frm_delete_entries), or an administrator, likedelete-entry.frm_entry_not_markable400 error. A missing entry returns the usual 404.Verified: Lite's local PHPUnit can't run here, so CI is the red/green. Test-only commit: all 4 PHPUnit jobs failed (
The mark-entry-spam ability should be registered). With the fix, all 4 pass, plus PHPCS, PHPStan, Psalm, Mago, Rector and PHP CS Fixer. Tests cover the result andget-entrymatch, item_key lookup, repeat calls, draft and unknown IDs, the permission check, and the contract list.Not checked: that the entry then shows in
list-entrieswithis_draft: 4. That needs #3599. Not run through a live MCP client.🤖 Generated with Claude Code