Revamp/UI ux of payment page#1846
Conversation
WalkthroughRefactors checkout UI into a two-column gateway/order-summary layout with card-style gateways, moves coupon UI into the order summary, scopes and extends coupon/checkout JS (add remove + submit loading), normalizes billing data and order-summary rendering in PHP, and adds small gateway/default and subscription robustness tweaks. ChangesCheckout styling & layout
Checkout & coupon JavaScript
Payment rendering / Checkout PHP
Gateways & small robustness fixes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested labels
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 3❌ Failed checks (2 warnings, 1 inconclusive)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 PHPStan (2.1.51)PHPStan was skipped because the sandbox runner could not parse its output. 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. Review rate limit: 0/1 reviews remaining, refill in 60 minutes.Comment |
There was a problem hiding this comment.
Actionable comments posted: 5
🧹 Nitpick comments (4)
assets/js/subscriptions-old.js (2)
154-176:couponRemoveduplicatescouponCancellogic.The
couponRemovefunction is nearly identical tocouponCancel, with the only difference being thatcouponRemovedoesn't add/remove the spinner class. Consider extracting the shared logic into a helper function to reduce duplication.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@assets/js/subscriptions-old.js` around lines 154 - 176, The couponRemove function duplicates couponCancel logic; extract the shared AJAX/post and DOM-update logic into a new helper (e.g., handleCouponAjax or updateCouponUI) and have both couponRemove and couponCancel call it; move the common data construction (action, _wpnonce, pack_id, type) and the success callback that updates .wpuf-pack-inner, .wpuf-coupon-id-field, .wpuf-coupon-applied, and .wpuf-copon-show into that helper, while keeping only the spinner add/remove behavior inside couponCancel.
127-129: Potential whitespace issue with$('#wpuf_type').text().Using
.text()on a div may capture unintended whitespace. Since Payment.php renders these as<div id="wpuf_type" style="display: none"><?php echo 'pack'; ?></div>, this should work, but using.text().trim()would be safer. Alternatively, if the PHP is updated to use hidden inputs as suggested, change to.val().Safer approach
pack_id: self.data('pack_id'), - type: $( '#wpuf_type' ).text() || 'pack' + type: $( '#wpuf_type' ).text().trim() || 'pack'Apply the same change to lines 164 and 220.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@assets/js/subscriptions-old.js` around lines 127 - 129, The code uses $('#wpuf_type').text() when building the payload (type: $('#wpuf_type').text() || 'pack'), which can include stray whitespace; change it to $('#wpuf_type').text().trim() || 'pack' (or to $('#wpuf_type').val() || 'pack' if you switch the PHP to a hidden input) and apply the same .trim()/.val() change to the other occurrences of the '#wpuf_type' selector in this file (the other payload/assignment sites referenced in the review).includes/Frontend/Payment.php (1)
295-306: Use data attributes instead of hidden divs for JavaScript data passing.Using hidden
<div>elements with text content for passing data to JavaScript is unconventional. Consider usingdata-*attributes on a relevant element orwp_localize_script()for a more standard approach. This also avoids potential whitespace issues with.text()in JS.Suggested approach using data attributes
- <?php - if ( $pack_id ) { - ?> - <div id="wpuf_type" style="display: none"><?php echo 'pack'; ?></div> - <div id="wpuf_id" style="display: none"><?php echo esc_attr( $pack_id ); ?></div> - <?php - } elseif ( $post_id ) { - ?> - <div id="wpuf_type" style="display: none"><?php echo 'post'; ?></div> - <div id="wpuf_id" style="display: none"><?php echo esc_attr( $post_id ); ?></div> - <?php - } - ?> + <input type="hidden" id="wpuf_type" value="<?php echo esc_attr( $pack_id ? 'pack' : 'post' ); ?>"> + <input type="hidden" id="wpuf_id" value="<?php echo esc_attr( $pack_id ? $pack_id : $post_id ); ?>">Then update the JavaScript to use
.val()instead of.text().🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@includes/Frontend/Payment.php` around lines 295 - 306, The hidden <div>s with ids "wpuf_type" and "wpuf_id" in includes/Frontend/Payment.php should be replaced with data-* attributes (or use wp_localize_script()) on an existing container element so JS reads values via element.dataset or jQuery .data()/ .val() instead of using .text(); update the code that references wpuf_type/wpuf_id in your JavaScript to read the new data attributes (or the localized object) and remove the hidden div outputs in Payment.php (look for the blocks that echo 'pack'/'post' and esc_attr($pack_id)/esc_attr($post_id)).assets/css/frontend-forms.css (1)
962-974: Typo:wpuf-coponshould bewpuf-coupon.The class names
.wpuf-copon-show,.wpuf-copon-wrap, and.wpuf-copon-cancelcontain a typo ("copon" instead of "coupon"). While this is consistent with the JavaScript selectors insubscriptions-old.js, it creates an inconsistent naming convention alongside.wpuf-coupon-field,.wpuf-coupon-applied, etc.Consider renaming these to use the correct spelling for maintainability, updating both CSS/LESS and JS files together.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@assets/css/frontend-forms.css` around lines 962 - 974, Rename the misspelled CSS class names (.wpuf-copon-show, .wpuf-copon-wrap, .wpuf-copon-cancel) to the correct spelling (.wpuf-coupon-show, .wpuf-coupon-wrap, .wpuf-coupon-cancel) in assets/css/frontend-forms.css and update every corresponding usage in JS (e.g., subscriptions-old.js) and any templates that reference those selectors so they stay consistent with existing classes like .wpuf-coupon-field and .wpuf-coupon-applied; ensure you replace all occurrences (including event listeners and querySelector/querySelectorAll strings) and run a quick smoke test to confirm coupon show/hide and cancel behaviors still work.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@assets/css/frontend-forms.css`:
- Around line 894-897: The CSS rule using the selector body
li:has(input[type="radio"]:checked) .wpuf-gateway-card should use the lowercase
keyword currentcolor (replace currentColor with currentcolor) to satisfy
linting; also add a fallback rule for older browsers that don't support :has by
duplicating the styling using a more widely supported relationship such as
input[type="radio"]:checked ~ .wpuf-gateway-card or input[type="radio"]:checked
+ .wpuf-gateway-card (pick the sibling combinator that matches the markup) so
the same border-color/box-shadow styles apply when the radio is checked without
relying on :has.
In `@assets/js/subscriptions-old.js`:
- Around line 251-256: Replace the hardcoded "Coupon code applied" string in the
orderSummary.append call with a localized value provided by the wpuf_frontend
object; ensure PHP registers that text via wp_localize_script (e.g.,
'coupon_applied_text' => __( 'Coupon code applied', 'wp-user-frontend' )), then
in the JS change the HTML constructed in orderSummary.append (the block that
includes '<span class="wpuf-coupon-applied-label">...') to use
wpuf_frontend.coupon_applied_text while keeping the surrounding markup and the
existing data-pack_id usage on the .wpuf-coupon-remove button.
In `@assets/less/frontend-forms.less`:
- Around line 862-867: The .wpuf-order-summary rule in the LESS source is
missing the background property present in compiled CSS; update the
.wpuf-order-summary selector in assets/less/frontend-forms.less by adding
background: `#f9fafb`; to the rule (alongside border, border-radius, padding) and
recompile the LESS so the generated CSS remains in sync with the source.
In `@includes/Frontend/Payment.php`:
- Around line 168-169: Remove the two unused variable assignments $details_meta
and $currency in the Payment class code: eliminate the call to
wpuf()->subscription->get_details_meta_value() assigned to $details_meta and the
wpuf_get_currency('symbol') call assigned to $currency since neither variable is
used afterward; leaving no side-effectful calls and ensuring no references
remain to $details_meta or $currency elsewhere in the method (search for
$details_meta and $currency to confirm), then run static analysis to verify the
unused-variable warning is resolved.
- Around line 189-194: Remove the unused local variable $pay_per_post and stop
reassigning $current_user to wpuf_get_user(); instead, keep the original
$current_user (from earlier) and, if you need the subscription helper from
wpuf_get_user(), assign that to a new variable name (e.g., $wpuf_user or
$subscription_helper) or call $current_user->subscription()->current_pack()
directly; update references to use the new variable or the original
$current_user to avoid type confusion and redundant assignments (check the block
using get_subs_fallback_cost(), get_pay_per_post_cost(), and current_pack()).
---
Nitpick comments:
In `@assets/css/frontend-forms.css`:
- Around line 962-974: Rename the misspelled CSS class names (.wpuf-copon-show,
.wpuf-copon-wrap, .wpuf-copon-cancel) to the correct spelling
(.wpuf-coupon-show, .wpuf-coupon-wrap, .wpuf-coupon-cancel) in
assets/css/frontend-forms.css and update every corresponding usage in JS (e.g.,
subscriptions-old.js) and any templates that reference those selectors so they
stay consistent with existing classes like .wpuf-coupon-field and
.wpuf-coupon-applied; ensure you replace all occurrences (including event
listeners and querySelector/querySelectorAll strings) and run a quick smoke test
to confirm coupon show/hide and cancel behaviors still work.
In `@assets/js/subscriptions-old.js`:
- Around line 154-176: The couponRemove function duplicates couponCancel logic;
extract the shared AJAX/post and DOM-update logic into a new helper (e.g.,
handleCouponAjax or updateCouponUI) and have both couponRemove and couponCancel
call it; move the common data construction (action, _wpnonce, pack_id, type) and
the success callback that updates .wpuf-pack-inner, .wpuf-coupon-id-field,
.wpuf-coupon-applied, and .wpuf-copon-show into that helper, while keeping only
the spinner add/remove behavior inside couponCancel.
- Around line 127-129: The code uses $('#wpuf_type').text() when building the
payload (type: $('#wpuf_type').text() || 'pack'), which can include stray
whitespace; change it to $('#wpuf_type').text().trim() || 'pack' (or to
$('#wpuf_type').val() || 'pack' if you switch the PHP to a hidden input) and
apply the same .trim()/.val() change to the other occurrences of the
'#wpuf_type' selector in this file (the other payload/assignment sites
referenced in the review).
In `@includes/Frontend/Payment.php`:
- Around line 295-306: The hidden <div>s with ids "wpuf_type" and "wpuf_id" in
includes/Frontend/Payment.php should be replaced with data-* attributes (or use
wp_localize_script()) on an existing container element so JS reads values via
element.dataset or jQuery .data()/ .val() instead of using .text(); update the
code that references wpuf_type/wpuf_id in your JavaScript to read the new data
attributes (or the localized object) and remove the hidden div outputs in
Payment.php (look for the blocks that echo 'pack'/'post' and
esc_attr($pack_id)/esc_attr($post_id)).
🪄 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: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 5c39228e-bd56-4aae-9c0a-385a7e9c1280
📒 Files selected for processing (11)
assets/css/admin/form-builder.cssassets/css/admin/subscriptions.min.cssassets/css/ai-form-builder.cssassets/css/ai-form-builder.min.cssassets/css/forms-list.min.cssassets/css/frontend-forms.cssassets/css/frontend-subscriptions.min.cssassets/css/frontend/account.cssassets/js/subscriptions-old.jsassets/less/frontend-forms.lessincludes/Frontend/Payment.php
| body li:has(input[type="radio"]:checked) .wpuf-gateway-card { | ||
| border-color: currentColor; | ||
| box-shadow: 0 0 0 1px currentColor; | ||
| } |
There was a problem hiding this comment.
Fix currentColor casing per linting rules.
Static analysis indicates that currentColor should be currentcolor for consistency with CSS value keyword conventions.
Additionally, the li:has() selector has limited support in older browsers (Safari 15.3-, Firefox 120-). Consider whether fallback styling is needed for older browser support.
Proposed fix for casing
body li:has(input[type="radio"]:checked) .wpuf-gateway-card {
- border-color: currentColor;
- box-shadow: 0 0 0 1px currentColor;
+ border-color: currentcolor;
+ box-shadow: 0 0 0 1px currentcolor;
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| body li:has(input[type="radio"]:checked) .wpuf-gateway-card { | |
| border-color: currentColor; | |
| box-shadow: 0 0 0 1px currentColor; | |
| } | |
| body li:has(input[type="radio"]:checked) .wpuf-gateway-card { | |
| border-color: currentcolor; | |
| box-shadow: 0 0 0 1px currentcolor; | |
| } |
🧰 Tools
🪛 Stylelint (17.7.0)
[error] 895-895: Expected "currentColor" to be "currentcolor" (value-keyword-case)
(value-keyword-case)
[error] 896-896: Expected "currentColor" to be "currentcolor" (value-keyword-case)
(value-keyword-case)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@assets/css/frontend-forms.css` around lines 894 - 897, The CSS rule using the
selector body li:has(input[type="radio"]:checked) .wpuf-gateway-card should use
the lowercase keyword currentcolor (replace currentColor with currentcolor) to
satisfy linting; also add a fallback rule for older browsers that don't support
:has by duplicating the styling using a more widely supported relationship such
as input[type="radio"]:checked ~ .wpuf-gateway-card or
input[type="radio"]:checked + .wpuf-gateway-card (pick the sibling combinator
that matches the markup) so the same border-color/box-shadow styles apply when
the radio is checked without relying on :has.
| orderSummary.append( | ||
| '<div class="wpuf-coupon-applied">' + | ||
| '<span class="wpuf-coupon-applied-label">Coupon code applied</span>' + | ||
| '<button type="button" class="wpuf-coupon-remove" data-pack_id="' + self.data('pack_id') + '">×</button>' + | ||
| '</div>' | ||
| ); |
There was a problem hiding this comment.
Hardcoded English text should be internationalized.
The string "Coupon code applied" is hardcoded in JavaScript. For proper internationalization, this should come from a localized script variable (e.g., wpuf_frontend.coupon_applied_text).
Suggested fix
Ensure the string is localized in PHP via wp_localize_script():
'coupon_applied_text' => __( 'Coupon code applied', 'wp-user-frontend' ),Then use it in JS:
orderSummary.append(
'<div class="wpuf-coupon-applied">' +
- '<span class="wpuf-coupon-applied-label">Coupon code applied</span>' +
+ '<span class="wpuf-coupon-applied-label">' + wpuf_frontend.coupon_applied_text + '</span>' +
'<button type="button" class="wpuf-coupon-remove" data-pack_id="' + self.data('pack_id') + '">×</button>' +
'</div>'
);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| orderSummary.append( | |
| '<div class="wpuf-coupon-applied">' + | |
| '<span class="wpuf-coupon-applied-label">Coupon code applied</span>' + | |
| '<button type="button" class="wpuf-coupon-remove" data-pack_id="' + self.data('pack_id') + '">×</button>' + | |
| '</div>' | |
| ); | |
| orderSummary.append( | |
| '<div class="wpuf-coupon-applied">' + | |
| '<span class="wpuf-coupon-applied-label">' + wpuf_frontend.coupon_applied_text + '</span>' + | |
| '<button type="button" class="wpuf-coupon-remove" data-pack_id="' + self.data('pack_id') + '">×</button>' + | |
| '</div>' | |
| ); |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@assets/js/subscriptions-old.js` around lines 251 - 256, Replace the hardcoded
"Coupon code applied" string in the orderSummary.append call with a localized
value provided by the wpuf_frontend object; ensure PHP registers that text via
wp_localize_script (e.g., 'coupon_applied_text' => __( 'Coupon code applied',
'wp-user-frontend' )), then in the JS change the HTML constructed in
orderSummary.append (the block that includes '<span
class="wpuf-coupon-applied-label">...') to use wpuf_frontend.coupon_applied_text
while keeping the surrounding markup and the existing data-pack_id usage on the
.wpuf-coupon-remove button.
| // Order summary card | ||
| .wpuf-order-summary { | ||
| border: 1px solid #e5e7eb; | ||
| border-radius: 12px; | ||
| padding: 24px; | ||
| } |
There was a problem hiding this comment.
Missing background property in .wpuf-order-summary.
The compiled CSS at line 899 includes background: #f9fafb; for .wpuf-order-summary, but this property is missing in the LESS source. Either the CSS was manually edited (which would be overwritten on next compilation) or there's a sync issue. Add the background to the LESS source.
Proposed fix
// Order summary card
.wpuf-order-summary {
+ background: `#f9fafb`;
border: 1px solid `#e5e7eb`;
border-radius: 12px;
padding: 24px;
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // Order summary card | |
| .wpuf-order-summary { | |
| border: 1px solid #e5e7eb; | |
| border-radius: 12px; | |
| padding: 24px; | |
| } | |
| // Order summary card | |
| .wpuf-order-summary { | |
| background: `#f9fafb`; | |
| border: 1px solid `#e5e7eb`; | |
| border-radius: 12px; | |
| padding: 24px; | |
| } |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@assets/less/frontend-forms.less` around lines 862 - 867, The
.wpuf-order-summary rule in the LESS source is missing the background property
present in compiled CSS; update the .wpuf-order-summary selector in
assets/less/frontend-forms.less by adding background: `#f9fafb`; to the rule
(alongside border, border-radius, padding) and recompile the LESS so the
generated CSS remains in sync with the source.
| $details_meta = wpuf()->subscription->get_details_meta_value(); | ||
| $currency = wpuf_get_currency( 'symbol' ); |
There was a problem hiding this comment.
Remove unused variables $details_meta and $currency.
These variables are assigned but never used, as flagged by static analysis. They should be removed to improve code clarity.
Proposed fix
$pack = wpuf()->subscription->get_subscription( $pack_id );
- $details_meta = wpuf()->subscription->get_details_meta_value();
- $currency = wpuf_get_currency( 'symbol' );
$pack_cost = $pack->meta_value['billing_amount'];📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| $details_meta = wpuf()->subscription->get_details_meta_value(); | |
| $currency = wpuf_get_currency( 'symbol' ); |
🧰 Tools
🪛 PHPMD (2.15.0)
[warning] 168-168: Avoid unused local variables such as '$details_meta'. (undefined)
(UnusedLocalVariable)
[warning] 169-169: Avoid unused local variables such as '$currency'. (undefined)
(UnusedLocalVariable)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@includes/Frontend/Payment.php` around lines 168 - 169, Remove the two unused
variable assignments $details_meta and $currency in the Payment class code:
eliminate the call to wpuf()->subscription->get_details_meta_value() assigned to
$details_meta and the wpuf_get_currency('symbol') call assigned to $currency
since neither variable is used afterward; leaving no side-effectful calls and
ensuring no references remain to $details_meta or $currency elsewhere in the
method (search for $details_meta and $currency to confirm), then run static
analysis to verify the unused-variable warning is resolved.
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
includes/Frontend/Payment.php (1)
136-140:⚠️ Potential issue | 🟠 MajorDefault to the first enabled gateway instead of hard-coding PayPal.
If PayPal is disabled, the first render leaves every radio unchecked, and checkout can submit with an empty
wpuf_payment_method.Proposed fix
- if ( isset( $_REQUEST['wpuf_payment_submit'] ) ) { - $selected_gateway = isset( $_REQUEST['wpuf_payment_method'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['wpuf_payment_method'] ) ) : ''; - } else { - $selected_gateway = 'paypal'; - } + $selected_gateway = isset( $_REQUEST['wpuf_payment_method'] ) + ? sanitize_text_field( wp_unslash( $_REQUEST['wpuf_payment_method'] ) ) + : ''; + + if ( empty( $selected_gateway ) || ! isset( $gateways[ $selected_gateway ] ) ) { + $selected_gateway = array_key_first( $gateways ); + }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@includes/Frontend/Payment.php` around lines 136 - 140, The code currently hard-codes 'paypal' when no wpuf_payment_method is submitted which leaves radios unchecked if PayPal is disabled; change the fallback logic for $selected_gateway to instead detect the first enabled gateway and use its ID. In the else branch (near the wpuf_payment_submit check) call the existing payment gateway collection (the function or property that lists gateways in this class, e.g., the Payment class method that returns available/enabled gateways) and pick the first enabled gateway ID to assign to $selected_gateway (with a safe fallback to an empty string if none found); ensure you use sanitize_text_field/wp_unslash only for user input (the retrieved gateway ID can be validated against the gateway list).
♻️ Duplicate comments (1)
assets/less/frontend-forms.less (1)
857-861:⚠️ Potential issue | 🟡 MinorGive the order summary card an explicit background.
Right now this card inherits the page background, so it loses contrast on themed checkout pages.
Proposed fix
.wpuf-order-summary { + background: `#f9fafb`; border: 1px solid `#e5e7eb`; border-radius: 12px; padding: 24px; }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@assets/less/frontend-forms.less` around lines 857 - 861, The .wpuf-order-summary block lacks an explicit background so it can inherit page backgrounds; update the .wpuf-order-summary rule in assets/less/frontend-forms.less to add an explicit background-color (e.g. background-color: `#ffffff`; or use your theme variable like `@card-background` or --card-bg) so the card keeps contrast on themed checkout pages, keeping the existing border, border-radius and padding intact.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Outside diff comments:
In `@includes/Frontend/Payment.php`:
- Around line 136-140: The code currently hard-codes 'paypal' when no
wpuf_payment_method is submitted which leaves radios unchecked if PayPal is
disabled; change the fallback logic for $selected_gateway to instead detect the
first enabled gateway and use its ID. In the else branch (near the
wpuf_payment_submit check) call the existing payment gateway collection (the
function or property that lists gateways in this class, e.g., the Payment class
method that returns available/enabled gateways) and pick the first enabled
gateway ID to assign to $selected_gateway (with a safe fallback to an empty
string if none found); ensure you use sanitize_text_field/wp_unslash only for
user input (the retrieved gateway ID can be validated against the gateway list).
---
Duplicate comments:
In `@assets/less/frontend-forms.less`:
- Around line 857-861: The .wpuf-order-summary block lacks an explicit
background so it can inherit page backgrounds; update the .wpuf-order-summary
rule in assets/less/frontend-forms.less to add an explicit background-color
(e.g. background-color: `#ffffff`; or use your theme variable like
`@card-background` or --card-bg) so the card keeps contrast on themed checkout
pages, keeping the existing border, border-radius and padding intact.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: f96299e8-0184-47e8-a570-5c4db3c5892c
⛔ Files ignored due to path filters (2)
assets/images/bank.svgis excluded by!**/*.svgassets/images/credit-card.svgis excluded by!**/*.svg
📒 Files selected for processing (9)
Lib/Gateway/Bank_Gateway.phpLib/Gateway/Paypal.phpassets/css/frontend-forms.cssassets/js/billing-address.jsassets/js/subscriptions-old.jsassets/less/frontend-forms.lessincludes/Admin/Subscription.phpincludes/Free/Free_Loader.phpincludes/Frontend/Payment.php
✅ Files skipped from review due to trivial changes (2)
- Lib/Gateway/Bank_Gateway.php
- Lib/Gateway/Paypal.php
🚧 Files skipped from review as they are similar to previous changes (2)
- assets/js/subscriptions-old.js
- assets/css/frontend-forms.css
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@includes/Frontend/Payment.php`:
- Around line 175-223: The code can reach render_order_summary without
$billing_data set when neither $pack_id nor $post_id is truthy; add a guard that
either short-circuits (e.g., return/exit or show an error) before rendering the
form when both $pack_id and $post_id are empty, or initialize a safe default
$billing_data (with keys 'type','id','title','subtotal','billing_amount') before
the if/elseif so subsequent calls like
$this->render_order_summary($billing_data) and helper accesses
($billing_data['title'], ['type'], ['subtotal'], ['billing_amount']) never
trigger warnings; locate the logic around $pack_id/$post_id, the $billing_data
assignment blocks, and the render_order_summary call to implement the guard or
default.
🪄 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: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 0008cf3e-1530-4be9-9632-c4b897665253
📒 Files selected for processing (3)
includes/Admin/Subscription.phpincludes/Free/Free_Loader.phpincludes/Frontend/Payment.php
✅ Files skipped from review due to trivial changes (1)
- includes/Admin/Subscription.php
🚧 Files skipped from review as they are similar to previous changes (1)
- includes/Free/Free_Loader.php
| if ( $pack_id ) { | ||
| $pack = wpuf()->subscription->get_subscription( $pack_id ); | ||
| $details_meta = wpuf()->subscription->get_details_meta_value(); | ||
| $currency = wpuf_get_currency( 'symbol' ); | ||
|
|
||
| $pack_cost = $pack->meta_value['billing_amount']; | ||
| $billing_amount = apply_filters( 'wpuf_payment_amount', $pack->meta_value['billing_amount'] ); | ||
|
|
||
| $order_title = $pack->post_title; | ||
|
|
||
| $billing_data = apply_filters( 'wpuf_billing_data', [ | ||
| 'type' => 'pack', | ||
| 'id' => $pack_id, | ||
| 'title' => $order_title, | ||
| 'subtotal' => $pack_cost, | ||
| 'billing_amount' => $billing_amount, | ||
| 'recurring_pay' => isset( $pack->meta_value['recurring_pay'] ) ? $pack->meta_value['recurring_pay'] : 'no', | ||
| ] ); | ||
| } elseif ( $post_id ) { | ||
| $form = new Admin\Forms\Form( | ||
| get_post_meta( $post_id, '_wpuf_form_id', true ) | ||
| ); | ||
| $force_pack = $form->is_enabled_force_pack(); | ||
| $pay_per_post = $form->is_enabled_pay_per_post(); | ||
| $fallback_enabled = $form->is_enabled_fallback_cost(); | ||
| $fallback_cost = (float) $form->get_subs_fallback_cost(); | ||
| $pay_per_post_cost = (float) $form->get_pay_per_post_cost(); | ||
| $current_user = wpuf_get_user(); | ||
| $current_pack = $current_user->subscription()->current_pack(); | ||
|
|
||
| if ( $force_pack && ! is_wp_error( $current_pack ) && $fallback_enabled ) { | ||
| $post_cost = $fallback_cost; | ||
| $billing_amount = apply_filters( 'wpuf_payment_amount', $fallback_cost, $post_id ); | ||
| } else { | ||
| $post_cost = $pay_per_post_cost; | ||
| $billing_amount = apply_filters( 'wpuf_payment_amount', $pay_per_post_cost, $post_id ); | ||
| } | ||
|
|
||
| $post_obj = get_post( $post_id ); | ||
| $order_title = $post_obj ? $post_obj->post_title : __( 'Post Submission', 'wp-user-frontend' ); | ||
|
|
||
| $billing_data = apply_filters( 'wpuf_billing_data', [ | ||
| 'type' => 'post', | ||
| 'id' => $post_id, | ||
| 'title' => $order_title, | ||
| 'subtotal' => $post_cost, | ||
| 'billing_amount' => $billing_amount, | ||
| ] ); | ||
| } |
There was a problem hiding this comment.
$billing_data may be undefined when neither pack_id nor post_id is set.
If action=wpuf_pay is reached without a pack_id or post_id (both default to 0 at lines 111-112 and the >0 guard at lines 116-118 only catches the both-set case), neither the if ( $pack_id ) nor elseif ( $post_id ) branch executes, so $billing_data is never defined. It is then dereferenced at line 298 ($this->render_order_summary( $billing_data )) and inside the helpers ($billing_data['title'], ['type'], ['subtotal'], ['billing_amount']), producing PHP warnings and a broken summary render.
Either short-circuit before opening the form when both ids are 0, or initialize a safe default. For example:
🛡️ Suggested guard
if ( $post_id > 0 && $pack_id > 0 ) {
return $content;
}
+ if ( $post_id <= 0 && $pack_id <= 0 ) {
+ return $content;
+ }🧰 Tools
🪛 PHPMD (2.15.0)
[warning] 177-177: Avoid unused local variables such as '$details_meta'. (undefined)
(UnusedLocalVariable)
[warning] 178-178: Avoid unused local variables such as '$currency'. (undefined)
(UnusedLocalVariable)
[warning] 198-198: Avoid unused local variables such as '$pay_per_post'. (undefined)
(UnusedLocalVariable)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@includes/Frontend/Payment.php` around lines 175 - 223, The code can reach
render_order_summary without $billing_data set when neither $pack_id nor
$post_id is truthy; add a guard that either short-circuits (e.g., return/exit or
show an error) before rendering the form when both $pack_id and $post_id are
empty, or initialize a safe default $billing_data (with keys
'type','id','title','subtotal','billing_amount') before the if/elseif so
subsequent calls like $this->render_order_summary($billing_data) and helper
accesses ($billing_data['title'], ['type'], ['subtotal'], ['billing_amount'])
never trigger warnings; locate the logic around $pack_id/$post_id, the
$billing_data assignment blocks, and the render_order_summary call to implement
the guard or default.
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (1)
assets/js/subscriptions-old.js (1)
115-176: ⚡ Quick win
couponRemoveduplicatescouponCancel— extract a shared helper.Both functions POST to
wpuf_coupon_canceland perform identical DOM updates on four targets inside.wpuf-order-summary(.wpuf-pack-inner,.wpuf-coupon-id-field,.wpuf-coupon-applied,.wpuf-coupon-show). The only difference is thatcouponCancelanimates a spinner on the coupon input field whilecouponRemovehas no loading feedback at all — a secondary UX inconsistency that would be resolved by the refactor.♻️ Proposed refactor — shared `_doCouponCancel` helper
+ _doCouponCancel: function( packId, orderSummary, onDone ) { + var data = { + action: 'wpuf_coupon_cancel', + _wpnonce: wpuf_frontend.nonce, + pack_id: packId, + type: $( '#wpuf_type' ).text() || 'pack' + }; + $.post( wpuf_frontend.ajaxurl, data, function( res ) { + if ( res.success ) { + orderSummary.find( '.wpuf-pack-inner' ).html( res.data.append_data ); + orderSummary.find( '.wpuf-coupon-id-field' ).val( '' ); + orderSummary.find( '.wpuf-coupon-applied' ).remove(); + orderSummary.find( '.wpuf-coupon-show' ).show(); + } + if ( typeof onDone === 'function' ) { onDone( res ); } + } ); + }, couponCancel: function( e ) { e.preventDefault(); var self = $( this ), orderSummary = self.closest( '.wpuf-order-summary' ), couponField = orderSummary.find( 'input.wpuf-coupon-field' ); couponField.addClass( 'wpuf-coupon-field-spinner' ); - var data = { - action: 'wpuf_coupon_cancel', - _wpnonce: wpuf_frontend.nonce, - pack_id: self.data( 'pack_id' ), - type: $( '#wpuf_type' ).text() || 'pack' - }; - $.post( wpuf_frontend.ajaxurl, data, function( res ) { - couponField.removeClass( 'wpuf-coupon-field-spinner' ); - if ( res.success ) { - orderSummary.find( '.wpuf-pack-inner' ).html( res.data.append_data ); - orderSummary.find( '.wpuf-coupon-id-field' ).val( '' ); - orderSummary.find( '.wpuf-coupon-applied' ).remove(); - orderSummary.find( '.wpuf-coupon-show' ).show(); - } - } ); + subscription._doCouponCancel( self.data( 'pack_id' ), orderSummary, function() { + couponField.removeClass( 'wpuf-coupon-field-spinner' ); + } ); }, couponRemove: function( e ) { e.preventDefault(); var self = $( this ), orderSummary = self.closest( '.wpuf-order-summary' ); - var data = { - action: 'wpuf_coupon_cancel', - _wpnonce: wpuf_frontend.nonce, - pack_id: self.data( 'pack_id' ), - type: $( '#wpuf_type' ).text() || 'pack' - }; - $.post( wpuf_frontend.ajaxurl, data, function( res ) { - if ( res.success ) { - orderSummary.find( '.wpuf-pack-inner' ).html( res.data.append_data ); - orderSummary.find( '.wpuf-coupon-id-field' ).val( '' ); - orderSummary.find( '.wpuf-coupon-applied' ).remove(); - orderSummary.find( '.wpuf-coupon-show' ).show(); - } - } ); + subscription._doCouponCancel( self.data( 'pack_id' ), orderSummary ); },🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@assets/js/subscriptions-old.js` around lines 115 - 176, Both couponCancel and couponRemove duplicate the same AJAX call and DOM updates; extract a shared helper (e.g., _doCouponCancel) that accepts the prepared data and the orderSummary element (or pack_id) and performs the $.post to 'wpuf_coupon_cancel' and the four DOM updates (.wpuf-pack-inner, .wpuf-coupon-id-field, .wpuf-coupon-applied, .wpuf-coupon-show) on success; then refactor couponCancel to add/remove the spinner on the coupon input field before/after calling _doCouponCancel, and refactor couponRemove to call _doCouponCancel directly so both behaviors reuse the same update logic.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@assets/css/frontend-forms.css`:
- Around line 854-913: Restore the selected-card visual state by re-adding a
rule that targets the card when its radio is checked (e.g., use the selector
body li:has(input[type="radio"]:checked) .wpuf-gateway-card) and set the same
highlight styles as hover (border-color and optional box-shadow), ensuring you
use the lowercase currentcolor token (not currentColor) if used for color values
to satisfy the linter; if :has() support is a concern, add guidance to toggle an
.is-selected class from JS and target .is-selected .wpuf-gateway-card instead.
In `@assets/js/subscriptions-old.js`:
- Around line 353-356: Replace the hardcoded "Processing…" string in the HTML
snippet that sets the button content with a value from the localized script data
(the key you added via wp_localize_script, e.g. 'processing_text') instead of
the literal English text; update the JS in assets/js/subscriptions-old.js to use
that localized variable (e.g. a property on the global/localized object created
by wp_localize_script) when building the '<span class="wpuf-btn-text">…</span>'
so the label is translatable.
- Around line 376-390: The validation branches in checkoutSubmit do not call
e.preventDefault(), so the form may still submit despite validation errors;
modify the branches that check WP_User_Frontend.validateForm(form) === false and
!wpuf_validate_address() to call e.preventDefault() before calling resetBtn()
and returning, and ensure the handler uses the event parameter (e) passed into
checkoutSubmit; reference WP_User_Frontend.validateForm, wpuf_validate_address,
checkoutSubmit, and resetBtn when making the changes.
In `@Lib/Gateway/Paypal.php`:
- Around line 1595-1597: Guard against division-by-zero when computing
$tax_percentage: if $subtotal is zero (which can happen when
breakdown['item_total'] === 0) skip the division and set $tax_percentage = 0 (or
compute by another safe fallback) instead of performing ($tax_amount /
$subtotal) * 100; update the code around the $tax_amount, $subtotal and
$tax_percentage calculation in Paypal.php to check for $subtotal == 0 (or empty
numeric) and handle that branch before calling number_format()/building the
PayPal payload so you never pass INF/NAN strings to PayPal.
---
Nitpick comments:
In `@assets/js/subscriptions-old.js`:
- Around line 115-176: Both couponCancel and couponRemove duplicate the same
AJAX call and DOM updates; extract a shared helper (e.g., _doCouponCancel) that
accepts the prepared data and the orderSummary element (or pack_id) and performs
the $.post to 'wpuf_coupon_cancel' and the four DOM updates (.wpuf-pack-inner,
.wpuf-coupon-id-field, .wpuf-coupon-applied, .wpuf-coupon-show) on success; then
refactor couponCancel to add/remove the spinner on the coupon input field
before/after calling _doCouponCancel, and refactor couponRemove to call
_doCouponCancel directly so both behaviors reuse the same update logic.
🪄 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: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 6aa5f9ed-30b8-43fc-82b0-dfe0a100f026
⛔ Files ignored due to path filters (6)
assets/js/account.min.jsis excluded by!**/*.min.jsassets/js/ai-form-builder.min.jsis excluded by!**/*.min.jsassets/js/forms-list.min.jsis excluded by!**/*.min.jsassets/js/forms-list.min.js.mapis excluded by!**/*.map,!**/*.min.js.mapassets/js/frontend-subscriptions.min.jsis excluded by!**/*.min.jsassets/js/subscriptions.min.jsis excluded by!**/*.min.js
📒 Files selected for processing (12)
Lib/Gateway/Paypal.phpassets/css/admin/form-builder.cssassets/css/admin/subscriptions.min.cssassets/css/ai-form-builder.cssassets/css/ai-form-builder.min.cssassets/css/forms-list.min.cssassets/css/frontend-forms.cssassets/css/frontend-subscriptions.min.cssassets/css/frontend/account.cssassets/js/subscriptions-old.jsassets/less/frontend-forms.lesslanguages/wp-user-frontend.pot
✅ Files skipped from review due to trivial changes (1)
- languages/wp-user-frontend.pot
🚧 Files skipped from review as they are similar to previous changes (1)
- assets/less/frontend-forms.less
| body .wpuf-gateway-card { | ||
| display: block; | ||
| border: 2px solid #e5e7eb; | ||
| border-radius: 12px; | ||
| padding: 16px 20px; | ||
| cursor: pointer; | ||
| display: inline-block; | ||
| transition: border-color 0.2s ease, box-shadow 0.2s ease; | ||
| background: #fff; | ||
| } | ||
| body .wpuf-gateway-card:hover { | ||
| border-color: #c7d2fe; | ||
| } | ||
| body .wpuf-gateway-card .wpuf-gateway-card-main { | ||
| display: flex; | ||
| align-items: center; | ||
| gap: 14px; | ||
| } | ||
| body .wpuf-gateway-card .wpuf-gateway-icon { | ||
| flex-shrink: 0; | ||
| width: 40px; | ||
| height: 40px; | ||
| display: flex; | ||
| align-items: center; | ||
| justify-content: center; | ||
| } | ||
| body .wpuf-gateway-card .wpuf-gateway-icon img { | ||
| max-width: 36px; | ||
| max-height: 36px; | ||
| object-fit: contain; | ||
| } | ||
| body .wpuf-gateway-card .wpuf-gateway-info { | ||
| flex: 1; | ||
| min-width: 0; | ||
| } | ||
| body .wpuf-gateway-card .wpuf-gateway-label { | ||
| display: block; | ||
| font-size: 15px; | ||
| font-weight: 600; | ||
| color: #1a1a2e; | ||
| line-height: 1.3; | ||
| } | ||
| body .wpuf-gateway-card .wpuf-gateway-desc { | ||
| display: block; | ||
| font-size: 13px; | ||
| color: #6b7280; | ||
| line-height: 1.4; | ||
| margin-top: 2px; | ||
| } | ||
| body .wpuf-gateway-card input[type="radio"] { | ||
| flex-shrink: 0; | ||
| width: 20px; | ||
| height: 20px; | ||
| margin: 0; | ||
| cursor: pointer; | ||
| } | ||
| body .wpuf-gateway-card .wpuf-payment-instruction { | ||
| margin-top: 12px; | ||
| padding-top: 12px; | ||
| border-top: 1px solid #f3f4f6; | ||
| } |
There was a problem hiding this comment.
Gateway card has no visual selected state — add a :checked highlight rule.
.wpuf-gateway-card only defines a hover border (#c7d2fe) but never changes appearance when the radio inside it is selected. A user who picks a gateway gets zero card-level feedback beyond the tiny native radio dot.
The earlier iteration of this PR included a body li:has(input[type="radio"]:checked) .wpuf-gateway-card rule for this purpose. The rule is entirely absent here, likely removed to sidestep the currentColor linting error. It should be restored using currentcolor (lowercase) which satisfies the linter.
✅ Proposed fix — restore the selected-state rule with correct casing
body .wpuf-gateway-card:hover {
border-color: `#c7d2fe`;
}
+body li:has(input[type="radio"]:checked) .wpuf-gateway-card {
+ border-color: currentcolor;
+ box-shadow: 0 0 0 1px currentcolor;
+}Note on browser support:
:has()is unsupported in Firefox < 120 and Safari < 15.4. If support for those browser versions is required, consider toggling an.is-selectedclass via JS on theliwhen the radio changes, and targeting that class as a fallback.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@assets/css/frontend-forms.css` around lines 854 - 913, Restore the
selected-card visual state by re-adding a rule that targets the card when its
radio is checked (e.g., use the selector body
li:has(input[type="radio"]:checked) .wpuf-gateway-card) and set the same
highlight styles as hover (border-color and optional box-shadow), ensuring you
use the lowercase currentcolor token (not currentColor) if used for color values
to satisfy the linter; if :has() support is a concern, add guidance to toggle an
.is-selected class from JS and target .is-selected .wpuf-gateway-card instead.
| .html( | ||
| '<span class="wpuf-btn-spinner"></span>' + | ||
| '<span class="wpuf-btn-text">Processing…</span>' | ||
| ); |
There was a problem hiding this comment.
Hardcoded "Processing…" text needs to be localized.
The loading label is a hardcoded English string injected into the DOM. Like "Coupon code applied" (flagged separately), it should be provided via wp_localize_script.
🌐 Proposed fix
In PHP (wp_localize_script call):
'processing_text' => __( 'Processing...', 'wp-user-frontend' ),In JS:
- '<span class="wpuf-btn-text">Processing…</span>'
+ '<span class="wpuf-btn-text">' + ( wpuf_frontend.processing_text || 'Processing\u2026' ) + '</span>'📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| .html( | |
| '<span class="wpuf-btn-spinner"></span>' + | |
| '<span class="wpuf-btn-text">Processing…</span>' | |
| ); | |
| .html( | |
| '<span class="wpuf-btn-spinner"></span>' + | |
| '<span class="wpuf-btn-text">' + ( wpuf_frontend.processing_text || 'Processing\u2026' ) + '</span>' | |
| ); |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@assets/js/subscriptions-old.js` around lines 353 - 356, Replace the hardcoded
"Processing…" string in the HTML snippet that sets the button content with a
value from the localized script data (the key you added via wp_localize_script,
e.g. 'processing_text') instead of the literal English text; update the JS in
assets/js/subscriptions-old.js to use that localized variable (e.g. a property
on the global/localized object created by wp_localize_script) when building the
'<span class="wpuf-btn-text">…</span>' so the label is translatable.
| // validateForm() returns false on error, serialized string on success. | ||
| if ( typeof WP_User_Frontend !== 'undefined' ) { | ||
| if ( WP_User_Frontend.validateForm( form ) === false ) { | ||
| resetBtn(); | ||
| return; | ||
| } | ||
| } | ||
|
|
||
| // Billing address validation when the address form is present. | ||
| if ( $( '#wpuf-ajax-address-form' ).length && typeof wpuf_validate_address === 'function' ) { | ||
| if ( ! wpuf_validate_address() ) { | ||
| resetBtn(); | ||
| return; | ||
| } | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check full billing-address.js submit handler for e.preventDefault() position
fd -i 'billing-address.js' --exec grep -n 'preventDefault\|validateForm\|submit' {}Repository: weDevsOfficial/wp-user-frontend
Length of output: 385
🏁 Script executed:
#!/bin/bash
# Find subscriptions-old.js and examine context around lines 370-395
fd -i 'subscriptions-old.js' -type f | head -1 | xargs -I {} sh -c 'echo "File: {}" && sed -n "360,400p" {} | cat -n | sed "s/^/360: /"'Repository: weDevsOfficial/wp-user-frontend
Length of output: 246
🏁 Script executed:
#!/bin/bash
# Also search for the checkoutSubmit function definition and how it's attached
fd -i 'subscriptions-old.js' -type f | head -1 | xargs -I {} sh -c 'grep -n "checkoutSubmit\|\.submit(" {} | head -20'Repository: weDevsOfficial/wp-user-frontend
Length of output: 246
🏁 Script executed:
#!/bin/bash
# Find subscriptions-old.js and examine context around lines 370-395
fd -i 'subscriptions-old.js' -t f | head -1 | xargs -I {} sh -c 'sed -n "360,400p" {} | cat -n'Repository: weDevsOfficial/wp-user-frontend
Length of output: 1878
🏁 Script executed:
#!/bin/bash
# Search for the checkoutSubmit function definition and attachment
fd -i 'subscriptions-old.js' -t f | head -1 | xargs -I {} sh -c 'grep -n "checkoutSubmit\|\.submit(" {}'Repository: weDevsOfficial/wp-user-frontend
Length of output: 356
🏁 Script executed:
#!/bin/bash
# Find subscriptions-old.js and get the full checkoutSubmit function
fd -i 'subscriptions-old.js' -t f | head -1 | xargs -I {} sh -c 'sed -n "342,400p" {} | cat -n'Repository: weDevsOfficial/wp-user-frontend
Length of output: 3002
🏁 Script executed:
#!/bin/bash
# Also check if there are other submit handlers on the same form in subscriptions-old.js
fd -i 'subscriptions-old.js' -t f | head -1 | xargs -I {} sh -c 'grep -n "\.submit\|\.on.*submit" {}'Repository: weDevsOfficial/wp-user-frontend
Length of output: 312
🏁 Script executed:
#!/bin/bash
# Search for other handlers on wpuf-payment-gateway form and Stripe-related code
fd -i 'subscriptions-old.js' -t f | head -1 | xargs -I {} sh -c 'rg -n "wpuf-payment-gateway|stripe" {} | head -30'Repository: weDevsOfficial/wp-user-frontend
Length of output: 278
🏁 Script executed:
#!/bin/bash
# Check if there are other submit handlers or Stripe handlers in the entire assets/js directory
rg -l "wpuf-payment-gateway|stripe" assets/js/ | head -10Repository: weDevsOfficial/wp-user-frontend
Length of output: 301
🏁 Script executed:
#!/bin/bash
# Search for all submission paths to the payment gateway form in all JS files
rg -n "\.submit\(\)|\.trigger.*submit" assets/js/ -t jsRepository: weDevsOfficial/wp-user-frontend
Length of output: 50388
🏁 Script executed:
#!/bin/bash
# Check if there's a Stripe Pro handler or any other handler that might prevent submission
rg -l "stripe|Stripe" assets/js/ --type js | xargs -I {} sh -c 'echo "=== {} ===" && rg -n "preventDefault|submit" {}'Repository: weDevsOfficial/wp-user-frontend
Length of output: 40314
Add e.preventDefault() to validation failure branches in checkoutSubmit to prevent form submission after errors.
The function receives the event object but omits e.preventDefault() in both validation failure branches, allowing the form to POST despite displaying validation errors. In jQuery, return alone does not prevent the default form submission behavior.
🐛 Proposed fix
if ( typeof WP_User_Frontend !== 'undefined' ) {
if ( WP_User_Frontend.validateForm( form ) === false ) {
+ e.preventDefault();
resetBtn();
return;
}
}
if ( $( '#wpuf-ajax-address-form' ).length && typeof wpuf_validate_address === 'function' ) {
if ( ! wpuf_validate_address() ) {
+ e.preventDefault();
resetBtn();
return;
}
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // validateForm() returns false on error, serialized string on success. | |
| if ( typeof WP_User_Frontend !== 'undefined' ) { | |
| if ( WP_User_Frontend.validateForm( form ) === false ) { | |
| resetBtn(); | |
| return; | |
| } | |
| } | |
| // Billing address validation when the address form is present. | |
| if ( $( '#wpuf-ajax-address-form' ).length && typeof wpuf_validate_address === 'function' ) { | |
| if ( ! wpuf_validate_address() ) { | |
| resetBtn(); | |
| return; | |
| } | |
| } | |
| // validateForm() returns false on error, serialized string on success. | |
| if ( typeof WP_User_Frontend !== 'undefined' ) { | |
| if ( WP_User_Frontend.validateForm( form ) === false ) { | |
| e.preventDefault(); | |
| resetBtn(); | |
| return; | |
| } | |
| } | |
| // Billing address validation when the address form is present. | |
| if ( $( '#wpuf-ajax-address-form' ).length && typeof wpuf_validate_address === 'function' ) { | |
| if ( ! wpuf_validate_address() ) { | |
| e.preventDefault(); | |
| resetBtn(); | |
| return; | |
| } | |
| } |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@assets/js/subscriptions-old.js` around lines 376 - 390, The validation
branches in checkoutSubmit do not call e.preventDefault(), so the form may still
submit despite validation errors; modify the branches that check
WP_User_Frontend.validateForm(form) === false and !wpuf_validate_address() to
call e.preventDefault() before calling resetBtn() and returning, and ensure the
handler uses the event parameter (e) passed into checkoutSubmit; reference
WP_User_Frontend.validateForm, wpuf_validate_address, checkoutSubmit, and
resetBtn when making the changes.
|
|
||
| // Calculate tax percentage | ||
| $tax_percentage = ( $tax_amount / $subtotal ) * 100; |
There was a problem hiding this comment.
Division-by-zero when item_total is explicitly 0 — subscription creation silently fails.
?? (null-coalescing) only falls back to the right operand when the left is null or undefined. An extension that sets breakdown['item_total'] = 0 (e.g., fully-discounted item with a non-zero tax) will leave $subtotal = 0, making line 1597 a float-division-by-zero. PHP returns INF/NAN, number_format() turns that into a garbage string, and PayPal rejects the subscription payload.
🐛 Proposed fix
- $subtotal = $payment_data['breakdown']['item_total'] ?? $payment_data['amount'];
-
- // Calculate tax percentage
- $tax_percentage = ( $tax_amount / $subtotal ) * 100;
-
- // Add plan override with tax
- $subscription_data['plan'] = [
- 'taxes' => [
- 'percentage' => number_format( $tax_percentage, 2, '.', '' ),
- 'inclusive' => false,
- ],
- ];
+ $subtotal = ! empty( $payment_data['breakdown']['item_total'] )
+ ? (float) $payment_data['breakdown']['item_total']
+ : (float) $payment_data['amount'];
+
+ // Calculate tax percentage only when subtotal is non-zero.
+ if ( $subtotal > 0 ) {
+ $tax_percentage = ( $tax_amount / $subtotal ) * 100;
+
+ // Add plan override with tax
+ $subscription_data['plan'] = [
+ 'taxes' => [
+ 'percentage' => number_format( $tax_percentage, 2, '.', '' ),
+ 'inclusive' => false,
+ ],
+ ];
+ }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@Lib/Gateway/Paypal.php` around lines 1595 - 1597, Guard against
division-by-zero when computing $tax_percentage: if $subtotal is zero (which can
happen when breakdown['item_total'] === 0) skip the division and set
$tax_percentage = 0 (or compute by another safe fallback) instead of performing
($tax_amount / $subtotal) * 100; update the code around the $tax_amount,
$subtotal and $tax_percentage calculation in Paypal.php to check for $subtotal
== 0 (or empty numeric) and handle that branch before calling
number_format()/building the PayPal payload so you never pass INF/NAN strings to
PayPal.
Closes #935
Related PR #1488
Summary
Redesigns the payment/checkout page with a modern two-column layout: payment methods on the left and an order summary panel on the right. The page is now cleaner and easier to scan, with gateway cards replacing the old plain radio list and a dedicated order summary section showing item details, pricing, and coupon controls in context.
Technical Notes
wpuf_billing_datafilter — allows developers to modify the billing data array (type, title, subtotal, billing amount) before it's passed to the order summary.Summary by CodeRabbit
New Features
Bug Fixes / Tweaks