Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(memberships): ensure user membership is linked to the correct subscription #3768

Merged
merged 9 commits into from
Feb 24, 2025

Conversation

dkoo
Copy link
Contributor

@dkoo dkoo commented Feb 20, 2025

All Submissions:

Changes proposed in this Pull Request:

Yet another attempt to fix the WooCommerce Memberships bug addressed in #3050, #3060, #3268, #3338, #3380, and #3393. This bug exists in the WooCommerce Memberships plugin itself, but there's no indication that the issue will be addressed upstream, so we're applying a patch here as it continues to affect live sites.

The crux of the issue: if a user purchases more than one subscription for a product required by a user membership plan, and the first subscription has an Expired status, their user membership will remain linked to the expired subscription. Even if they subsequently purchase a new subscription for the same product, the membership will remain linked to the expired subscription, and will remain in expired status—so the user won't be able to access restricted content despite having purchased the required subscription.

This PR addresses the issue by checking the user's memberships upon login and subscription status change. If a user membership requires a subscription to specific products and the user has active subscriptions for those products, the membership will be relinked to the most recent active subscription, and the expiration date will be cleared. This should trigger the membership to automatically reactivate, granting the user access to any restricted content defined in the membership plan.

How to test the changes in this Pull Request:

  1. Publish a membership plan that requires a subscription product and is tied the subscription length. Optionally add content restrictions to test user access to the restricted content.
Screenshot 2025-02-20 at 4 45 57 PM
  1. On release, as a reader, purchase a subscription with the required product.
  2. As an admin, change the subscription's status to expired.
  3. As the reader, purchase a second subscription with the required product.
  4. As an admin, find the user's membership (in WooCommerce > Memberships).
  5. Observe that the user membership remains linked to the initial expired subscription, and remains in "Expired" status, meaning that the reader won't be able to access any content restricted by the membership plan.
  6. Check out this branch.
  7. As the reader, log out and then log back into the site again to trigger the reader_logged_in data event.
  8. Confirm that the user membership has been relinked to the active subscription, that the membership now has an "Active" status with no expiration date, and that the reader can now access restricted content.
Screenshot 2025-02-20 at 4 56 01 PM
  1. As an admin, set the active subscription to expired status and confirm that the membership also changes to expired status again.
  2. As the reader, purchase a subscription for the required product again. Confirm that the user membership has been once again relinked to the new active subscription, that the membership now has an "Active" status with no expiration date, and that the reader can now access restricted content.

Other information:

  • Have you added an explanation of what your changes do and why you'd like us to include them?
  • Have you written new tests for your changes, as applicable?
  • Have you successfully ran tests with your changes locally?

@dkoo dkoo added the [Status] Needs Review The issue or pull request needs to be reviewed label Feb 20, 2025
@dkoo dkoo self-assigned this Feb 20, 2025
@dkoo dkoo requested a review from a team as a code owner February 20, 2025 23:59
@dkoo
Copy link
Contributor Author

dkoo commented Feb 21, 2025

As discussed with @miguelpeixe, #3769 gets us close to a fix but doesn't solve the issue for user memberships linked to expired subscriptions.

Copy link
Member

@miguelpeixe miguelpeixe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I ran into a few issues that I commented inline.

Do we still need the handle_wc_memberships_expire_user_membership() logic here?

Comment on lines 1136 to 1142
$updated = $subscription_membership->set_subscription_id( $active_subscription_id );
$membership_plan = $subscription_membership->get_plan();

// Reset end date for plans with access set to subscription length.
if ( $membership_plan->is_access_length_type( 'subscription' ) && ! empty( $subscription_membership->get_end_date() ) ) {
$subscription_membership->set_end_date( '' );
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With the hook priority at the default (10), the set_subscription_id() works and the membership is relinked, but set_end_date() doesn't persist and the membership remains with the expired status.

After changing the hook priority to 11 the end date resets, but the status remains "expired". Maybe we should be running a $subscription_membership->update_status( 'active', $note ); here too?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for catching this! I can confirm this is the case. Maybe the data events approach was working because it happened after all other WC Memberships hooks had done their thing

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

f436f1a is now working for me. As for whether we still need handle_wc_memberships_expire_user_membership(), I repurposed it as another trigger to check and possibly relink the membership, which should prevent the "Expired" status from being set if the membership is linked to the wrong subscription. WDYT?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3fad077 updates handle_wc_memberships_expire_user_membership() to check_user_memberships_on_expire() and groups it with the other check_user_memberships_on_* methods, for clarity. It also only prevents the expiration if that specific membership should be relinked to an active subscription.

@dkoo dkoo requested a review from miguelpeixe February 21, 2025 21:25
@dkoo
Copy link
Contributor Author

dkoo commented Feb 21, 2025

I'm not sure why the unit test job is failing now—tests run fine locally 😕

@miguelpeixe
Copy link
Member

I'm not sure why the unit test job is failing now

Either CI or .org is unstable and unable to download WP. It's been doing that for me all day.

Copy link
Member

@miguelpeixe miguelpeixe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I repurposed it as another trigger to check and possibly relink the membership, which should prevent the "Expired" status from being set if the membership is linked to the wrong subscription. WDYT?

Good call!

It's working well for me now! 🎉

@@ -7,7 +7,10 @@

namespace Newspack;

use Newspack\Data_Events;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is unused now

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, removed in 835649b!

@github-actions github-actions bot added [Status] Approved The pull request has been reviewed and is ready to merge and removed [Status] Needs Review The issue or pull request needs to be reviewed labels Feb 21, 2025
@dkoo
Copy link
Contributor Author

dkoo commented Feb 21, 2025

Holding this until a non-Friday

@dkoo dkoo merged commit a942616 into release Feb 24, 2025
9 checks passed
@dkoo dkoo deleted the hotfix/check-membership-linked-subscription branch February 24, 2025 17:10
matticbot pushed a commit that referenced this pull request Feb 24, 2025
## [5.14.3](v5.14.2...v5.14.3) (2025-02-24)

### Bug Fixes

* **memberships:** ensure user membership is linked to the correct subscription ([#3768](#3768)) ([a942616](a942616))
@matticbot
Copy link
Contributor

🎉 This PR is included in version 5.14.3 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

matticbot pushed a commit that referenced this pull request Feb 27, 2025
# [6.0.0-alpha.2](v6.0.0-alpha.1...v6.0.0-alpha.2) (2025-02-27)

### Bug Fixes

* **memberships:** ensure user membership is linked to the correct subscription ([#3768](#3768)) ([a942616](a942616))
* undo forcing WC order attribution to off ([#3771](#3771)) ([c9cb52a](c9cb52a))
* **woo:** page template meta leaking to other types ([#3782](#3782)) ([325a21c](325a21c))

### Features

* add corrections customize settings ([#3751](#3751)) ([11dbc5e](11dbc5e))
* **corrections:** Unit tests for Corrections functionality ([#3776](#3776)) ([ae58933](ae58933))
* **my-account:** add change email template ([#3772](#3772)) ([32bef3c](32bef3c))
* **my-account:** add pending email change state ([#3763](#3763)) ([c9ba046](c9ba046))
* **my-account:** verify email change ([#3764](#3764)) ([b50c980](b50c980))
@matticbot
Copy link
Contributor

🎉 This PR is included in version 6.0.0-alpha.2 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
released on @alpha released [Status] Approved The pull request has been reviewed and is ready to merge
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants