Skip to content

GH#935: fix email verification gate — hold site publish until customer verifies email#937

Merged
superdav42 merged 1 commit intomainfrom
feature/auto-20260424-230838-gh935
Apr 25, 2026
Merged

GH#935: fix email verification gate — hold site publish until customer verifies email#937
superdav42 merged 1 commit intomainfrom
feature/auto-20260424-230838-gh935

Conversation

@superdav42
Copy link
Copy Markdown
Collaborator

Summary

When enable_email_verification=always, the payment gateway (e.g. Stripe) can activate a membership via webhook before the customer has verified their email. The wu_transition_membership_status hook was unconditionally publishing the pending site on activation, completely bypassing the email-verification gate.

Root cause

Membership_Manager::transition_membership_status() called publish_pending_site_async() without checking the customer's email_verification status.

Changes

inc/managers/class-membership-manager.php

Return early from transition_membership_status() when the customer's email_verification === 'pending'. The site is deferred until email verification completes.

inc/managers/class-customer-manager.php

Add an ACTIVE branch to the post-verification publish block in maybe_verify_email_address(). Previously, the code only handled PENDING and TRIALING memberships. With this fix, if the gateway already activated the membership before email was verified, the pending site is published once the customer clicks their verification link.

inc/checkout/class-checkout-pages.php

Remove the $payment->get_total() === 0.0 guard from add_verify_email_notice(). With always, paid customers also need to see the "verify your email" banner on the thank-you page.

tests/WP_Ultimo/Managers/Membership_Manager_Test.php

Two regression tests covering the email-gate behaviour.

Verification

vendor/bin/phpunit --filter test_transition_status_skips_publish_when_customer_email_pending
vendor/bin/phpunit --filter test_transition_status_publishes_when_customer_email_not_pending

Resolves #935


aidevops.sh v3.11.0 plugin for OpenCode v1.3.17 with claude-sonnet-4-6 spent 10m and 23,862 tokens on this as a headless worker.

…935)

When enable_email_verification=always, Stripe (or any payment gateway)
can mark a membership active before the customer verifies their email.
The transition_membership_status hook was unconditionally publishing the
pending site, bypassing the email-verification gate.

Changes:
- Membership_Manager::transition_membership_status() — return early if
  the customer's email_verification is 'pending'; the site is published
  later by Customer_Manager once the email is verified.
- Customer_Manager::maybe_verify_email_address() — add ACTIVE branch to
  the post-verification publish logic so sites held during a Stripe
  activation are published when the customer completes email verification.
- Checkout_Pages::add_verify_email_notice() — remove the
  payment->get_total() === 0.0 guard so paid customers with 'always'
  verification also see the 'verify your email' notice on the thank-you
  page.
- Tests — two focused regression tests for the email-gate behaviour in
  Membership_Manager_Test.

Fixes #935
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 25, 2026

Warning

Rate limit exceeded

@superdav42 has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 55 minutes and 49 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 55 minutes and 49 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 89bfd5c9-b5ea-4b65-ba93-f63a79bc4610

📥 Commits

Reviewing files that changed from the base of the PR and between 3fd1267 and 9fce88b.

📒 Files selected for processing (4)
  • inc/checkout/class-checkout-pages.php
  • inc/managers/class-customer-manager.php
  • inc/managers/class-membership-manager.php
  • tests/WP_Ultimo/Managers/Membership_Manager_Test.php
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/auto-20260424-230838-gh935

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.

@superdav42
Copy link
Copy Markdown
Collaborator Author

What was done

Fixed enable_email_verification=always not working for paid memberships (GH#935).

Root cause: Membership_Manager::transition_membership_status() called publish_pending_site_async() unconditionally when a membership moved from PENDING/ON_HOLDACTIVE/TRIALING. When Stripe (or another gateway) sends an activation webhook, the membership becomes ACTIVE before the customer has verified their email, so the pending site was published immediately — bypassing the verification gate.

Fixes applied:

  1. inc/managers/class-membership-manager.php — Added early-return in transition_membership_status() when customer->get_email_verification() === 'pending'. The site publish is deferred.
  2. inc/managers/class-customer-manager.php — Added ACTIVE branch in maybe_verify_email_address() post-verification block. If the gateway already activated the membership, the held site is published when the customer clicks the verification link.
  3. inc/checkout/class-checkout-pages.php — Removed $payment->get_total() === 0.0 guard from add_verify_email_notice(). Paid customers using always now see the verification banner on the thank-you page.
  4. tests/WP_Ultimo/Managers/Membership_Manager_Test.php — Two regression tests covering the gate (skips publish when pending, publishes when not pending).

How to verify:

vendor/bin/phpunit --filter test_transition_status_skips_publish_when_customer_email_pending
vendor/bin/phpunit --filter test_transition_status_publishes_when_customer_email_not_pending

aidevops.sh v3.11.0 plugin for OpenCode v1.3.17 with claude-sonnet-4-6 spent 10m and 24,663 tokens on this as a headless worker.

@github-actions
Copy link
Copy Markdown

🔨 Build Complete - Ready for Testing!

📦 Download Build Artifact (Recommended)

Download the zip build, upload to WordPress and test:

🌐 Test in WordPress Playground (Very Experimental)

Click the link below to instantly test this PR in your browser - no installation needed!
Playground support for multisite is very limitied, hopefully it will get better in the future.

🚀 Launch in Playground

Login credentials: admin / password

@github-actions
Copy link
Copy Markdown

Performance Test Results

Performance test results for 2aaa648 are in 🛎️!

Note: the numbers in parentheses show the difference to the previous (baseline) test run. Differences below 2% or 0.5 in absolute values are not shown.

URL: /

Run DB Queries Memory Before Template Template WP Total LCP TTFB LCP - TTFB
0 40 (-1 / -3% ) 37.73 MB 802.50 ms (-101.50 ms / -13% ) 172.50 ms (+14.50 ms / +8% ) 1031.00 ms (-77.50 ms / -8% ) 1940.00 ms (-132.00 ms / -7% ) 1839.95 ms (-133.70 ms / -7% ) 90.30 ms (-3.35 ms / -4% )
1 56 49.03 MB 943.00 ms 149.00 ms 1092.50 ms 2052.00 ms (-52.00 ms / -3% ) 1969.90 ms (-51.75 ms / -3% ) 82.75 ms

@superdav42 superdav42 merged commit 97fd08b into main Apr 25, 2026
11 checks passed
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.

enable_email_verification=always not working as intended

1 participant