Skip to content

Keep the passed payment in trigger_payment_status_change - #3620

Open
vivi-the-going-merry[bot] wants to merge 3 commits into
masterfrom
fix/issue-6914-payment-status-hook-payment
Open

vivi-the-going-merry[bot] wants to merge 3 commits into
masterfrom
fix/issue-6914-payment-status-hook-payment

Conversation

@vivi-the-going-merry

@vivi-the-going-merry vivi-the-going-merry Bot commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

trigger_payment_status_change() rebuilt $atts before checking isset( $atts['payment'] ), so a payment passed in was always dropped and the entry's newest payment was loaded instead. frm_payment_status_* hooks and payment-triggered actions then ran against the wrong payment (for example, an older payment refunded while a newer one is pending: the actions never run, because the pending payment returns early).

The passed payment is now carried into the new $atts. The entry lookup still runs only when none was passed.

Two tests added in test_FrmTransLiteActionsController: one passes the older of two payments and checks the hook gets it (red before the fix: got the newer payment's ID; green after), one checks the entry lookup still works when only an entry is passed.

Verified locally: --group stripe 67/67 green. CI: all green on the head commit except Psalm (912 existing MissingPureAnnotation errors, also failing on other PRs) and DeepSource: PHP (no details exposed).

The bundled copy in formidable-payments (FrmTransActionsController.php) has the same code and needs the same change in its own repo.

Fixes Strategy11/formidable-pro#6914

🤖 Generated with Claude Code

@coderabbitai

coderabbitai Bot commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

Important

Review skipped

Bot user detected.

To trigger a single review, invoke the @coderabbitai review command.

Run configuration

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@deepsource-io

deepsource-io Bot commented Oct 26, 2026 •

Copy link
Copy Markdown

DeepSource Code Review

We reviewed changes in a0b9742...a934dc4 on this pull request. Below is the summary for the review, and you can see the individual issues we found as inline review comments.

See full review on DeepSource ↗

Important

Some issues found as part of this review are outside of the diff in this pull request and aren't shown in the inline review comments due to GitHub's API limitations. You can see those issues on the DeepSource dashboard.

PR Report Card

Overall Grade   Security  

Reliability  

Complexity  

Hygiene  

Code Review Summary

Analyzer Status Updated (UTC) Details
PHP Oct 26, 2026 4:14p.m. Review ↗
JavaScript Oct 26, 2026 4:14p.m. Review ↗

Important

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.

@@ -70,6 +70,94 @@ public function test_maybe_use_decimal() {
$this->assertSame( '111.500', $amount );

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Call to an undefined method test_FrmTransLiteActionsController::assertSame()


The method you are trying to call is not defined, which can result in a fatal error.

)
);

$this->assertNotNull( $atts );

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Call to an undefined method test_FrmTransLiteActionsController::assertNotNull()


The method you are trying to call is not defined, which can result in a fatal error.

);

$this->assertNotNull( $atts );
$this->assertEquals( $older_id, $atts['payment']->id );

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Call to an undefined method test_FrmTransLiteActionsController::assertEquals()


The method you are trying to call is not defined, which can result in a fatal error.


$this->assertNotNull( $atts );
$this->assertEquals( $older_id, $atts['payment']->id );
$this->assertEquals( $entry['id'], $atts['entry_id'] );

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Call to an undefined method test_FrmTransLiteActionsController::assertEquals()


The method you are trying to call is not defined, which can result in a fatal error.

)
);

$this->assertNotNull( $atts );

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Call to an undefined method test_FrmTransLiteActionsController::assertNotNull()


The method you are trying to call is not defined, which can result in a fatal error.

);

$this->assertNotNull( $atts );
$this->assertEquals( $entry['payment_ids'][0], $atts['payment']->id );

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Call to an undefined method test_FrmTransLiteActionsController::assertEquals()


The method you are trying to call is not defined, which can result in a fatal error.

@franky-the-going-merry franky-the-going-merry Bot added the franky-working Franky is actively reviewing this label Oct 26, 2026

@franky-the-going-merry franky-the-going-merry Bot left a comment

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.

Approve. The one-line fix is correct and the repro confirms it.

Live before/after (throwaway WordPress Playground, Lite only, PR copy vs. the same copy with the added line removed). Two payments on one entry, complete (id 1, older) and pending (id 2, newer), then trigger_payment_status_change( [ 'status' => 'refunded', 'payment' => <id 1> ] ):

frm_payment_status_refunded receives
base payment 2 (the newer, pending one)
PR payment 1 (the one passed in)

The entry-only call ('entry' => …, no payment) still loads the newest payment on both, so the lookup fallback is unchanged. All callers I grepped (Stripe, Square, PayPal events/actions, trigger_subscription_status_change) pass compact( 'status', 'payment' ), so they now get the payment they hand in, which is the intended behavior.

Notes (non-blocking):

  • formidable-payments has the same code in FrmTransActionsController.php and needs the same change in its own repo (already flagged in the description).
  • Psalm is red here, but it is also red on master (runs of 2026-10-22), so it is not from this PR. I did not look into the DeepSource PHP failure, which exposes no details.

Not run: the PR's PHPUnit tests locally (CI PHPUnit passed on 7.4/8.0/8.2/8.4, which includes them; my repro used an equivalent script, not the test file). The entry in my repro had id 0 because inserting an entry row under Playground's SQLite did not return an id, so item_id matched on 0 for both payments. That does not affect the older-vs-newer comparison. code-review/security-review/simplify were not run as separate passes; I read the whole diff by hand (one line of code plus tests).

@franky-the-going-merry franky-the-going-merry Bot removed franky-review franky-working Franky is actively reviewing this labels Oct 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants