Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions includes/plugins/wc-memberships/class-membership-expiry.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,18 @@ public static function init() {
/**
* Prevent membership expiration if there are other active subscriptions.
*
* @param bool $cancel_membership Whether to cancel the membership when the subscription is cancelled (default true).
* @param \WC_Memberships_Integration_Subscriptions_User_Membership $user_membership The subscription-tied membership.
* @param bool $cancel_membership Whether to cancel the membership when the subscription is cancelled (default true).
* @param \WC_Memberships_User_Membership $user_membership The membership. Only subscription-tied memberships (\WC_Memberships_Integration_Subscriptions_User_Membership) expose get_subscription_id()/set_subscription_id().
*/
public static function prevent_membership_expiration( $cancel_membership, $user_membership ) {
if ( ! function_exists( 'wcs_get_subscription' ) ) {
return $cancel_membership;
}
// `wc_memberships_expire_user_membership` fires for every membership, but only the
// Subscriptions integration class exposes get_subscription_id()/set_subscription_id().
if ( ! method_exists( $user_membership, 'get_subscription_id' ) ) {
return $cancel_membership;
}
$membership_product_id = $user_membership->get_product_id();
$cancelling_subscription_id = $user_membership->get_subscription_id();
$active_subscription_ids = WooCommerce_Connection::get_active_subscriptions_for_user( $user_membership->get_user_id() );
Expand Down
54 changes: 54 additions & 0 deletions tests/unit-tests/plugins/wc-memberships/membership-expiry.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php
/**
* Tests for the WC Memberships expiry handler.
*
* @package Newspack\Tests
*/

use Newspack\Membership_Expiry;

require_once dirname( __DIR__, 3 ) . '/mocks/wc-mocks.php';

/**
* Test Membership_Expiry::prevent_membership_expiration().
*
* @group membership-expiry
*/
class Test_Membership_Expiry extends WP_UnitTestCase {

/**
* The wc_memberships_expire_user_membership filter fires for every user membership,
* not just subscription-tied ones. Plain WC_Memberships_User_Membership objects do
* not expose get_subscription_id(); calling it must not fatal.
*
* Reproduces the production fatal observed at v6.39.3 of newspack-plugin:
* Uncaught Error: Call to undefined method WC_Memberships_User_Membership::get_subscription_id()
* in includes/plugins/wc-memberships/class-membership-expiry.php:39
*/
public function test_passes_through_non_subscription_membership() {
$non_subscription_membership = new class() {
/**
* Return a product id.
*
* @return int
*/
public function get_product_id() {
return 123;
}

/**
* Return a user id.
*
* @return int
*/
public function get_user_id() {
return 456;
}

// Deliberately no get_subscription_id() — only the Subscriptions integration class has it.
};

$result = Membership_Expiry::prevent_membership_expiration( true, $non_subscription_membership );
$this->assertTrue( $result, 'Filter should return the incoming $cancel_membership unchanged when the membership is not subscription-tied.' );
}
}
Loading