Sync master from upstream#113
Merged
Merged
Conversation
When a form uses the Custom Button block (srfm/inline-button) as the primary submit mechanism (default button disabled), and conditional logic hides the custom button, pressing Enter in a text field would still trigger form submission because the existing guard only checked for the button element's presence, not its visibility. Extend the check to also block submission when the custom button's container (.srfm-custom-button-ctn) has the 'hide-element' class, which is applied by the conditional logic frontend JS. Fixes #2848
`Array.isArray(children)` returns false when a block uses a single
InspectorTab (e.g. tabs={['advance']}), preventing Children.map from
running and leaving the panel blank. Remove the guard — React.Children.map
handles both single elements and arrays correctly.
Fixes the Conditional Logic panel not appearing on the Custom Button block.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Show Entries is a Pro feature but had no upsell preview in the single-form settings modal, unlike every other Pro feature (Quizzes, PDF Generation, Save & Progress, etc.). Add a "show-entries-preview" tab rendering the standard FeaturePreview upsell card so free users can discover it. When Pro is active, it replaces this preview with the real panel via replaceSingleFormTab (matching tab id "show-entries-preview").
…idgets handleCaptchaValidation() called turnstile.getResponse() without a widget id. When more than one Turnstile widget is rendered on the same page, that returns undefined, and reading .length on it threw a TypeError that was swallowed by the submit handler's catch and surfaced as the generic "An error occurred while submitting your form" — with no network request and no console log, making every such form un-submittable. - Read the token from the hidden cf-turnstile-response field scoped to the form's own widget (falling back to turnstile.getResponse()), so each form uses its own token instead of the first widget's. - Guard the .length check with (captchaResponse || '') so a missing token from any captcha provider shows the captcha error instead of crashing the submission. Closes #2869
…get-getresponse fix: form submission silently fails with multiple Cloudflare Turnstile widgets (#2869)
…o minimum floor WordPress.org's scanner flagged a residual edge of the #2857 variable-amount fix: when the amount source is a hidden field whose default is a non-numeric smart tag, resolve_server_side_variable_amount() returns null and the field is not a calculation number, so validation fell through to the minimum-amount floor only. With a zero/unset minimum, an unauthenticated visitor could underpay down to the gateway cent floor. Add an else branch (mirroring the existing 'amount source not identified' handling) that fail-safe rejects when the unresolved hidden source has no positive minimum_amount, while preserving the documented dynamic-prefill flow for forms that configure a positive minimum. Adds regression coverage in test-payment-helper.php.
PR #2791 restricted `useShouldIframe()` to srfm/+core/ blocks so third-party legacy registrations (ThirstyAffiliates, Ninja Forms, etc.) cannot flip the heuristic. That fix is correct for WP 7.0+, where core itself checks only *present* blocks and still iframes the form editor. On WP 6.x, however, core checks ALL registered block types — so a single apiVersion<3 block from any plugin causes WP 6.x to NOT create the `iframe[name="editor-canvas"]` element. The heuristic now returns true while the DOM has no iframe, leaving the 100ms polling loop spinning for the full 30s safety timeout before giving up. `documentBody` is never resolved and the editor is visually broken on every affected WP 6.x site. Fix: inside the polling loop, when `shouldIframe` is true but no iframe element is found, check whether the top-document block editor is already mounted (`.is-root-container` + `.block-editor-block-list__layout` both present). If so, WP rendered in non-iframe mode — wire up the top-document body immediately, exactly as the explicit `shouldIframe === false` branch does. On WP 7.0+ the iframe is always created so the guard is never hit. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ive card field In live mode the Stripe Payment Element failed to render (the deferred elements/sessions request returned HTTP 400) when the account had payment methods enabled that don't support manual capture (Bacs Direct Debit, Link, Cash App, BNPL). SureForms one-time payments use manual capture, so those methods are incompatible and Stripe rejected the whole session, leaving the card field missing. Test mode worked only because it had card-only enabled. Restrict the one-time element to card-based methods (paymentMethodTypes: ['card']). Apple Pay / Google Pay still appear (they ride on card); the dropped methods could never be used with manual capture anyway. Subscriptions (no manual capture) and the server intent are unchanged — backward compatible.
Master to Dev 2.11.1
…to dev-nr-2.11.1-post
Dev to Next Release 2.11.1
…to dev-nr-2.11.1-post
fix(editor): fall back to non-iframe path on WP 6.x with legacy blocks
- admin review link: drop ?filter=5 deep-link - entries.php / admin-ajax.php: unlink() -> wp_delete_file(); fix readfile ignore - stripe handler: esc_html__ in thrown exception - Bricks/Elementor widgets: scope escaping phpcs:ignore to the output line - plugin-loader: justified ignore for load_plugin_textdomain fallback - readme: reword short description to natural English (<=150 chars) - DirectDB: add PluginCheck.Security.DirectDB.UnescapedDBParameter to existing justified ignores (internal table names / esc_sql / int-cast IDs)
Emit generic srfm_* actions at key payment lifecycle points so third-party
plugins (SureMembers, LMS, etc.) can grant or revoke access in sync with
SureForms payments. Additive only - no change to existing behavior.
- Payment_Helper::resolve_payment_user(): entry user -> customer email -> 0
- Payment_Helper::build_payment_context(): resolved context array
{form_id, entry_id, user_id, customer_email, type, gateway, mode}
- srfm_payment_completed: one-time payment (link point, status-gated) and
initial subscription charge
- srfm_subscription_renewed: renewal charge succeeded
- srfm_subscription_canceled: terminal cancellation (subscription.deleted)
- srfm_payment_refunded: refund recorded (full/partial flagged)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018CYKxrgaxaDmZRnxVZsWp3
Follow the project convention of tagging new code with @SInCE x.x.x until the release version is finalized. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018CYKxrgaxaDmZRnxVZsWp3
…check Satisfies the check-test-coverage gate for is_transaction_present(). Asserts the boolean contract and that the result matches the payments table's actual row state (read-only, no mutation).
…gs-dev Resolve SureForms-own Plugin Check findings
Add unit tests for the two new Payment_Helper methods to satisfy the check-test-coverage CI gate.
…ic filter The admin Cancel Subscription action (srfm_stripe_cancel_subscription) called the Stripe API directly regardless of the payment's gateway, so cancelling a PayPal subscription from the admin failed (a PayPal subscription id was sent to Stripe) and the log hardcoded 'Payment Gateway: Stripe'. Route the admin cancellation through the existing srfm_process_subscription_cancellation filter (which both Stripe and PayPal hook), mirroring the frontend cancel path, so the payment's own gateway performs the cancellation. Also log the actual gateway. Action name and JS are unchanged (backward compatible); Pro's PayPal filter callback already exists. Closes #2891
Bumps the bundled bsf-analytics library from 1.1.26 to 1.1.28. Fixes the deactivation feedback survey not appearing in RTL locales: the survey registered a non-existent RTL stylesheet (feedback.min-rtl.css) which 404'd, so the popup never rendered and clicking Deactivate appeared to do nothing. 1.1.28 registers the style suffix via wp_style_add_data so the correct feedback-rtl.min.css is loaded. Also pulls in 1.1.27 (adds SureDonation slug to UTM analytics).
…ics-1.1.28 chore: update bsf-analytics to 1.1.28 (RTL deactivation survey fix)
…t-lifecycle-hooks Add payment lifecycle hooks for access/membership integrations
…ons) Adds justified phpcs:ignore/disable comments for Plugin Check findings in plugin-authored code (no logic changes): - CAPTCHA SDK enqueues (reCAPTCHA, Cloudflare Turnstile, hCaptcha): suppress EnqueuedResourceOffloading.OffloadedContent + MissingVersion. These must load from the vendor domain for token verification and cannot be bundled; the existing single-line ignores did not cover the reported arg lines. - Third-party integration hooks (wpml_*, suretriggers_*) and the shared spec_filesystem() helper: suppress NonPrefixedHookname/Function — names must match the other product exactly to integrate. - Dynamic-filter dispatcher in helper.php: suppress DynamicHooknameFound. - single-form.php template-scoped variables: file-level disable of NonPrefixedVariableFound (template locals, not true globals). Accepted false-positives left as-is (not phpcs-suppressible, documented in PR): Abilities API vs WP 6.4 (already function_exists-guarded), plugin-loader.php direct-access (guard present but undetected), readme.txt name mismatch. Excludes inc/lib/* (vendored) and intl-tel-input asset filenames (per request).
…-version false positives - plugin-loader.php: relocate the ABSPATH guard to immediately after the namespace declaration (before the use block). Plugin Check's direct-access check only scans the first 50 lines; the guard previously sat at line 57 behind the long use block, so it went undetected. No logic change. - inc/abilities/*: add justification comments above the 5 WP 6.9+ Abilities API calls (wp_register_ability, wp_get_abilities, wp_has_ability_category, wp_register_ability_category, wp_has_ability). Each is gated by function_exists()/wp_abilities_api_init and is inert on WP 6.4-6.8. The Plugin Check WP-version check is a token scanner with no inline-ignore support, so these remain documented false positives. readme.txt left unchanged (long SEO title is intentional).
fix: resolve Plugin Check findings in SureForms code (phpcs suppressions)
…gate #1: admin cancel no longer re-writes the DB / appends a second 'Subscription Canceled' log after the filter. The gateway callback already persists subscription_status + the log, so the handler now just reports success (mirrors the frontend cancel path). Also esc_html() the filter message in the JSON responses (#3). #2: process_stripe_subscription_cancellation() now treats an empty gateway as Stripe (gateway column defaults to ''), so legacy/imported Stripe rows can be cancelled again; only an explicitly different gateway is skipped.
…eld-manual-capture fix(payments): Stripe card field fails to load in live mode (manual capture vs incompatible methods)
…hidden-floor-master fix(payments): fail-safe reject unresolved hidden-field amount with no minimum floor
…eforms into feat/show-entries-preview-banner
…to fix/2848-conditional-logic-custom-button-hidden-submit
…iption-cancel-routing fix(payments): route admin subscription cancel through gateway-agnostic filter
…gic-custom-button-hidden-submit fix: block form submission when custom button is conditionally hidden
…ew-banner feat: add Show Entries feature-preview upsell tab
…to dev-nr-2.12.0 # Conflicts: # tests/unit/inc/payments/test-payment-helper.php
Adds unit tests for functions whose bodies were touched by the dev merge (phpcs-suppression edits) so the new/modified-function coverage check passes without the skip label: - get_google_captcha_script() / get_cf_turnstile_script() — assert rendered widget markup + enqueued handles per version, and the missing-sitekey error. - request_filesystem_credentials() — returns true (forces direct FS method). - generate_data_for_suretriggers_integration() — capability, nonce, and required-param guards reject via WPDieException. Test-only; no production code changed.
Dev to Next Release 2.12.0
Moves the page-break settings controls (Progress Indicator, Show Labels, First Page Label, Next/Back button text) out of the inline JSX in GeneralSettings.js and into a dedicated shared component at src/components/page-break-settings/index.js. This component owns the _srfm_page_break_settings post-meta read/write via the 'core/editor' store. GeneralSettings.js is updated to simply render <PageBreakSettings /> inside the existing panel body. The component is importable by sureforms-pro via the @components webpack alias, enabling the Page Break block inspector to surface the same controls without duplicating code. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…tion Fixes ESLint no-multiple-empty-lines failures left by the refactor.
…-shared-component refactor: extract PageBreakSettings into shared component
Version Bump 2.12.0
Auto-generated by /i18n command on PR #2903
chore: update i18n translations
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Syncs
masterfrom upstream private repo.Upstream range:
10103ca50..4556b2f83— 363 commitsBranch is capped with a merge commit whose first parent is
public/master, so this PR's diff is computed against the current mirror tip — only real upstream changes appear; no internal artifacts or deletions are shown. All commits carry verified signatures. README.md is the only markdown doc in the diff.Highlights