Skip to content

GH#904: fix: reclaim orphan pending_site on WC order completion#912

Merged
superdav42 merged 2 commits intomainfrom
feature/auto-20260422-131642-gh904
Apr 22, 2026
Merged

GH#904: fix: reclaim orphan pending_site on WC order completion#912
superdav42 merged 2 commits intomainfrom
feature/auto-20260422-131642-gh904

Conversation

@superdav42
Copy link
Copy Markdown
Collaborator

Summary

Implements the reclaim path for orphaned pending_site objects — the counterpart to the cancellation-preservation fix.

When a WU membership is cancelled, handle_pending_site_on_cancellation stores the pending_site in a 24-hour transient keyed by wu_transferable_pending_ + md5(email). Previously, nothing consumed that transient when the customer completed a new WooCommerce order. This PR closes that gap.

Changes

  • inc/managers/class-membership-manager.php

    • Hook woocommerce_order_status_completedreclaim_pending_site_on_wc_order_completion in init()
    • New method reclaim_pending_site_on_wc_order_completion($order_id): looks up the billing email → transient → WP user → WU customer → most-recent cancelled membership; reactivates it, attaches the pending_site, writes _wu_membership_id post meta on the WC order, deletes the transient, and triggers publish_pending_site_async()
    • Bails cleanly if WC is not active (wc_get_order not defined), order not found, no transient, no WP user, no WU customer, or no cancelled membership
  • tests/bootstrap.php

    • Adds a minimal wc_get_order() stub (if WC is not loaded) driven by $GLOBALS['_wu_test_wc_order_email']
  • tests/WP_Ultimo/Managers/Membership_Manager_Test.php

    • test_init_registers_wc_order_completion_hook — hook registration verified
    • test_reclaim_bails_when_order_not_found — stub returns false, membership stays cancelled
    • test_reclaim_pending_site_reactivates_membership_and_clears_transient — full flow: transient consumed, membership reactivated, pending_site re-attached
    • test_reclaim_skips_when_no_transient — no transient → membership unchanged
    • Adds unset($GLOBALS['_wu_test_wc_order_email']) to tearDown() to prevent test pollution

Acceptance Criteria

  1. ✅ When a WC order completes and a matching orphan transient exists, the pending_site is reclaimed
  2. ✅ A cancelled membership is reactivated with the pending_site attached
  3. ✅ The pending_site is published (async provisioning triggered)
  4. ✅ The transient is deleted after successful reclaim
  5. ✅ Unit tests confirm the full reclaim flow

Resolves #904


aidevops.sh v3.8.94 plugin for OpenCode v1.3.17 with claude-sonnet-4-6 spent 9m and 27,579 tokens on this as a headless worker.

Hook woocommerce_order_status_completed to check for a pending_site
transient keyed by the billing email hash. When found, reactivates the
customer's cancelled membership, attaches the pending_site, links the WC
order via _wu_membership_id post meta, deletes the transient, and
triggers async site provisioning.

Also adds a wc_get_order() stub to the test bootstrap and four unit
tests covering: hook registration, order-not-found bail, full reclaim
flow (membership reactivated + transient cleared + pending_site
re-attached), and no-transient skip.

Resolves #904
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 22, 2026

Warning

Rate limit exceeded

@superdav42 has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 44 minutes and 59 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 44 minutes and 59 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: da74e485-91de-4fa2-b175-eedb97a7f39b

📥 Commits

Reviewing files that changed from the base of the PR and between 0f16c7c and 621198c.

📒 Files selected for processing (3)
  • inc/managers/class-membership-manager.php
  • tests/WP_Ultimo/Managers/Membership_Manager_Test.php
  • tests/bootstrap.php
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/auto-20260422-131642-gh904

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

Merge Summary

What was implemented: Reclaim path for orphaned pending_site objects when a WooCommerce order completes.

Root cause: When a WU membership was cancelled, the pending_site was preserved in a transient (wu_transferable_pending_ + md5(email)) but nothing consumed it when the customer subsequently completed a WC order. The customer paid but received no site.

Fix: Hooked woocommerce_order_status_completedMembership_Manager::reclaim_pending_site_on_wc_order_completion(). On order completion, the method:

  1. Looks up the transient by billing email hash
  2. Resolves the WP user → WU customer → most-recent cancelled membership
  3. Reactivates the cancelled membership
  4. Re-attaches the pending_site to the membership
  5. Links the WC order via _wu_membership_id post meta
  6. Deletes the transient (idempotency)
  7. Triggers async site provisioning

Verification: 4 unit tests added covering hook registration, order-not-found bail, full reclaim flow, and no-transient skip. Bootstrap includes a wc_get_order() stub.

Resolves #904

@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

@superdav42 superdav42 merged commit cd31442 into main Apr 22, 2026
7 checks passed
@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

github-actions Bot commented Apr 22, 2026

Performance Test Results

Performance test results for f8f4b2f 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 818.00 ms (-23.00 ms / -3% ) 162.00 ms (-25.50 ms / -16% ) 1058.00 ms 2052.00 ms (+76.00 ms / +4% ) 1963.70 ms (+92.40 ms / +5% ) 86.60 ms (+2.60 ms / +3% )
1 56 49.03 MB 911.50 ms (-48.00 ms / -5% ) 147.00 ms (-3.50 ms / -2% ) 1062.00 ms (-48.50 ms / -5% ) 2014.00 ms (-82.00 ms / -4% ) 1939.50 ms (-82.65 ms / -4% ) 78.90 ms

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.

fix: reclaim orphan pending_site on WC order completion

1 participant