Skip to content

Fix paypal commerce test mode checkbox not working when paypal addon is active#3156

Merged
Crabcyborg merged 4 commits into
masterfrom
fix_paypal_commerce_test_mode_checkbox_not_working_when_paypal_addon_is_active
Jun 18, 2026
Merged

Fix paypal commerce test mode checkbox not working when paypal addon is active#3156
Crabcyborg merged 4 commits into
masterfrom
fix_paypal_commerce_test_mode_checkbox_not_working_when_paypal_addon_is_active

Conversation

@Crabcyborg

@Crabcyborg Crabcyborg commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Related ticket https://secure.helpscout.net/conversation/3359590190/253804

Pre-release
formidable-6.32.1b.zip

Summary by CodeRabbit

  • Bug Fixes
    • Fixed an issue where the PayPal add-on's test mode setting could be lost when updating PayPal configuration. Test mode preference is now properly preserved during settings updates.

@coderabbitai

coderabbitai Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Fixes PayPal test_mode being lost on settings save. A hidden form field ensures frm_paypal_test_mode=0 is always submitted when unchecked. The model's update() caches $this->param(). A new static method preserve_test_mode_on_update copies test_mode from the old option object to the new one when missing, triggered via a newly registered WordPress action hook.

Changes

PayPal test_mode preservation fix

Layer / File(s) Summary
Form hidden input and model param caching
paypal/views/settings/connect-settings-container.php, paypal/models/FrmPayPalLiteSettings.php
A hidden frm_paypal_test_mode=0 field is inserted before the checkbox so the value is always present in the POST data when unchecked. FrmPayPalLiteSettings::update() caches $this->param() in a local variable and uses it consistently for both per-setting and test_mode key construction.
preserve_test_mode_on_update method and hook wiring
paypal/controllers/FrmPayPalLiteSettingsController.php, paypal/controllers/FrmPayPalLiteHooksController.php
Adds FrmPayPalLiteSettingsController::preserve_test_mode_on_update($old_value, $new_value) which guards against non-objects, copies test_mode from the old option to the new one if absent, and re-persists via update_option. load_admin_hooks() registers this on the update_option_frm_paypal_options action with priority 10 and 2 args.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Suggested reviewers

  • garretlaxton

Poem

🐰 A checkbox unchecked, a value lost in the wind,
A hidden field added, let saving begin!
Old options and new, we copy with care,
test_mode preserved — no more pulling of hair.
Hop hop, little bug, you shall bother no more! 🥕

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title directly and clearly describes the main bug being fixed: the PayPal Commerce test mode checkbox not working when the PayPal addon is active, which matches the core problem addressed across all file changes in this PR.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix_paypal_commerce_test_mode_checkbox_not_working_when_paypal_addon_is_active

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 and usage tips.

@Crabcyborg Crabcyborg modified the milestones: 6.33, 6.32.1 Jun 18, 2026
@deepsource-io

deepsource-io Bot commented Jun 18, 2026

Copy link
Copy Markdown

DeepSource Code Review

We reviewed changes in 45f8d02...a8c7af5 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 ↗

PR Report Card

Overall Grade   Security  

Reliability  

Complexity  

Hygiene  

Code Review Summary

Analyzer Status Updated (UTC) Details
PHP Jun 18, 2026 1:52p.m. Review ↗
JavaScript Jun 18, 2026 1:52p.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.

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@paypal/controllers/FrmPayPalLiteSettingsController.php`:
- Around line 68-78: The preserve_test_mode_on_update function is currently
hooked to the update_option_frm_paypal_options action and calls update_option
inside the callback, which causes the hook to fire again and creates duplicate
writes. Move this logic to use the pre_update_option_frm_paypal_options filter
instead, which executes before the option is written. Remove the update_option
call since the filter can directly modify and return the new_value parameter,
allowing the preservation to happen in a single update operation without
re-triggering the hook.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 7b106f8d-5138-4b32-979b-cdef354e51fd

📥 Commits

Reviewing files that changed from the base of the PR and between 45f8d02 and 83a81ca.

📒 Files selected for processing (4)
  • paypal/controllers/FrmPayPalLiteHooksController.php
  • paypal/controllers/FrmPayPalLiteSettingsController.php
  • paypal/models/FrmPayPalLiteSettings.php
  • paypal/views/settings/connect-settings-container.php

Comment on lines +68 to +78
public static function preserve_test_mode_on_update( $old_value, $new_value ) {
if ( ! is_object( $old_value ) || ! is_object( $new_value ) ) {
return;
}

// If old value had test_mode but new value doesn't, preserve it
if ( isset( $old_value->test_mode ) && ! isset( $new_value->test_mode ) ) {
$new_value->test_mode = $old_value->test_mode;
// Update the option with the preserved test_mode
update_option( 'frm_paypal_options', $new_value );
}

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.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify current re-entrant pattern:
# 1) Callback is attached to update_option_frm_paypal_options
# 2) Callback itself calls update_option('frm_paypal_options', ...)
rg -n --type=php -C3 "update_option_frm_paypal_options|preserve_test_mode_on_update|update_option\s*\(\s*'frm_paypal_options'" paypal/controllers

Repository: Strategy11/formidable-forms

Length of output: 1961


Avoid re-writing the same option inside its update_option_* callback.

Line 80 triggers a second update_option() from inside the update_option_frm_paypal_options action. This causes an extra write and re-fires option-update hooks, which can duplicate downstream side effects.

🔧 Suggested fix (move preservation to pre-update filter)
diff --git a/paypal/controllers/FrmPayPalLiteSettingsController.php b/paypal/controllers/FrmPayPalLiteSettingsController.php
@@
-	/**
-	 * Preserve test_mode when the PayPal add-on updates frm_paypal_options.
-	 * This hooks into update_option to ensure test_mode isn't lost.
-	 *
-	 * `@param` mixed $old_value The old option value.
-	 * `@param` mixed $new_value The new option value.
-	 *
-	 * `@return` void
-	 */
-	public static function preserve_test_mode_on_update( $old_value, $new_value ) {
-		if ( ! is_object( $old_value ) || ! is_object( $new_value ) ) {
-			return;
-		}
-
-		// If old value had test_mode but new value doesn't, preserve it
-		if ( isset( $old_value->test_mode ) && ! isset( $new_value->test_mode ) ) {
-			$new_value->test_mode = $old_value->test_mode;
-			// Update the option with the preserved test_mode
-			update_option( 'frm_paypal_options', $new_value );
-		}
-	}
+	/**
+	 * Preserve test_mode before frm_paypal_options is persisted.
+	 *
+	 * `@param` mixed $new_value The incoming option value.
+	 * `@param` mixed $old_value The currently stored option value.
+	 *
+	 * `@return` mixed
+	 */
+	public static function preserve_test_mode_on_update( $new_value, $old_value ) {
+		if ( is_object( $old_value ) && is_object( $new_value ) && isset( $old_value->test_mode ) && ! isset( $new_value->test_mode ) ) {
+			$new_value->test_mode = $old_value->test_mode;
+		}
+
+		return $new_value;
+	}
diff --git a/paypal/controllers/FrmPayPalLiteHooksController.php b/paypal/controllers/FrmPayPalLiteHooksController.php
@@
-		add_action( 'update_option_frm_paypal_options', 'FrmPayPalLiteSettingsController::preserve_test_mode_on_update', 10, 2 );
+		add_filter( 'pre_update_option_frm_paypal_options', 'FrmPayPalLiteSettingsController::preserve_test_mode_on_update', 10, 2 );
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@paypal/controllers/FrmPayPalLiteSettingsController.php` around lines 68 - 78,
The preserve_test_mode_on_update function is currently hooked to the
update_option_frm_paypal_options action and calls update_option inside the
callback, which causes the hook to fire again and creates duplicate writes. Move
this logic to use the pre_update_option_frm_paypal_options filter instead, which
executes before the option is written. Remove the update_option call since the
filter can directly modify and return the new_value parameter, allowing the
preservation to happen in a single update operation without re-triggering the
hook.

@Crabcyborg
Crabcyborg merged commit bec0f1d into master Jun 18, 2026
21 of 22 checks passed
@Crabcyborg
Crabcyborg deleted the fix_paypal_commerce_test_mode_checkbox_not_working_when_paypal_addon_is_active branch June 18, 2026 13:56
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.

1 participant