Skip to content

Sync master from upstream#112

Closed
vanshk141999 wants to merge 50 commits into
masterfrom
sync/master-20260625
Closed

Sync master from upstream#112
vanshk141999 wants to merge 50 commits into
masterfrom
sync/master-20260625

Conversation

@vanshk141999

Copy link
Copy Markdown
Collaborator

Syncs master from upstream private repo.

Upstream range: 10103ca50..4556b2f83363 commits

The branch 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-file deletions are shown. All commits carry verified signatures.

Highlights

  • Merge pull request #2903 from brainstormforce/next-release
  • Merge pull request #2905 from brainstormforce/i18n/next-release
  • Merge pull request #2902 from brainstormforce/version-bump-2.12.0
  • Merge pull request #2901 from brainstormforce/fix/page-break-settings-shared-component
  • Merge pull request #2899 from brainstormforce/dev-nr-2.12.0
  • Merge pull request #2854 from brainstormforce/feat/show-entries-preview-banner
  • Merge pull request #2849 from brainstormforce/fix/2848-conditional-logic-custom-button-hidden-submit
  • Merge pull request #2892 from brainstormforce/fix/admin-paypal-subscription-cancel-routing
  • Merge pull request #2877 from brainstormforce/fix/payment-unresolved-hidden-floor-master
  • Merge pull request #2884 from brainstormforce/fix/stripe-live-card-field-manual-capture
  • Merge pull request #2897 from brainstormforce/chore/plugin-check-fixes
  • Merge pull request #2890 from brainstormforce/feat/suremembers-payment-lifecycle-hooks
  • Merge pull request #2896 from brainstormforce/chore/update-bsf-analytics-1.1.28
  • Merge pull request #2889 from brainstormforce/fix/plugin-check-findings-dev
  • Merge pull request #2878 from brainstormforce/fix/iframe-compat-wp6
  • Merge pull request #2888 from brainstormforce/dev-nr-2.11.1-post
  • Merge pull request #2887 from brainstormforce/master-dev-2.11.1-post
  • Merge pull request #2870 from brainstormforce/fix/turnstile-multi-widget-getresponse
  • Merge pull request #2875 from brainstormforce/readme-light-trim
  • Merge pull request #2871 from brainstormforce/seo/readme-keyword-optimization
  • Merge pull request #2867 from brainstormforce/next-release
  • Merge pull request #2866 from brainstormforce/version-bump-2.11.1
  • Merge pull request #2865 from brainstormforce/dev-nr-2.11.1-pre
  • Merge pull request #2864 from brainstormforce/master-dev-2.11.1-pre
  • Merge pull request #2858 from brainstormforce/ci/harden-i18n-workflow

avi1080p and others added 30 commits June 11, 2026 17:32
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.
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
vanshk141999 and others added 20 commits June 23, 2026 14:55
…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.
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
Auto-generated by /i18n command on PR #2903
@vanshk141999

Copy link
Copy Markdown
Collaborator Author

Superseded by re-synced branch — the previous strip missed nested CLAUDE.md files and the docs/ tree. Closing and replacing with a clean sync.

@vanshk141999 vanshk141999 deleted the sync/master-20260625 branch June 25, 2026 15:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants