Search code examples
phpwordpresswoocommercecheckoutwoocommerce-subscriptions

Display a notice in WooCommerce checkout if a subscription item is in cart for an active subscriber


I have subscriptions on my WooCommerce site. I created a functionality that, if there is an active subscription, rewrites it to a new one upon purchase:

add_action( 'woocommerce_thankyou', 'cancel_previous_active_subscription' );
function cancel_previous_active_subscription() {
    $no_of_loops = 0;
    $user_id = get_current_user_id();

    $args = array(
        'subscription_status'       => 'active', 
        'subscriptions_per_page'    => -1,
        'customer_id'               => $user_id, 
        'orderby'                   => 'ID', 
        'order'                     => 'DESC'
    );
    $subscriptions = wcs_get_subscriptions($args);

    foreach ( $subscriptions as $subscription ) {
        $no_of_loops = $no_of_loops + 1;

        if ($no_of_loops > 1){
            $subscription->update_status( 'cancelled' );
        } 
    }
}

Now we need to make sure that in the checkout, if there is a subscription, a notice is displayed. But only when the subscription is in checkout, not for other products. Right now, my code is not working. How to fix it?

add_action( 'woocommerce_before_cart', 'display_subscription_notice' );
function display_subscription_notice() {
    $user_id = get_current_user_id();

    $args = array(
        'subscription_status'       => 'active', 
        'subscriptions_per_page'    => 1,
        'customer_id'               => $user_id, 
    );
    $subscriptions = wcs_get_subscriptions($args);

    $has_subscription = false;
    foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
        if ( wcs_order_contains_subscription( $cart_item['data']->get_id() ) ) {
            $has_subscription = true;
            break;
        }
    }


    if ( !empty($subscriptions) && $has_subscription ) {
        wc_add_notice( 'By purchasing a new subscription you will cancel your current one', 'notice' );
    }
}

I have a version of the working code, but it works for absolutely all products, and I only need it when purchasing a new subscription:

add_action('woocommerce_before_cart', 'display_subscription_notice');
function display_subscription_notice()
{
    $user_id = get_current_user_id();
    $args = array(
        'subscription_status' => 'active',
        'subscriptions_per_page' => 1,
        'customer_id' => $user_id,
    );
    $subscriptions = wcs_get_subscriptions($args);


    if (!empty($subscriptions)) {
        wc_add_notice('By purchasing a new subscription you will cancel your current one', 'notice');
    }
}

Solution

  • You can use the following to display a notice in checkout page when a subscription product is in cart and if the customer has already an active subscription:

    // Conditional function: Check if a user has active subscriptions
    function has_active_subscriptions( $user_id = 0 ) {
        return wcs_user_has_subscription( $user_id > 0?:get_current_user_id(), '', 'active' );
    }
    
    // Conditional function: Check if a user has a subscription product in cart
    function has_subscription_in_cart( $cart_contents = null ) {
        foreach ( $cart_contents?:WC()->cart->get_cart() as $item ) {
            if ( $item['data']->is_type( array('subscription', 'subscription_variation') ) ) {
                return true;
            }
        }
        return false;
    }
    
    // Display a notice in checkout conditionally
    add_action( 'template_redirect', 'display_checkout_subscription_notice' );
    function display_checkout_subscription_notice() {
        if ( is_checkout() && ! is_wc_endpoint_url() && has_active_subscriptions() && has_subscription_in_cart() ) {
            wc_add_notice( __('By purchasing a new subscription you will cancel your current active one.'), 'notice' );
        }
    }
    

    Code goes in functions.php file of your child theme (or in a plugin). Tested and works.

    In checkout page (if the user has an active subscription and a subscription product in cart):

    enter image description here


    Addition

    For your first function, you could try to use the following instead, that will cancel all previous user "active" subscriptions, when a new subscription get "active" status:

    add_action( 'woocommerce_subscription_status_active', 'cancel_previous_active_subscriptions', 10, 1 );
    function cancel_previous_active_subscriptions( $subscription ) {
        $user_subscriptions  = wcs_get_subscriptions( array(
            'subscription_status'       => 'active',
            'customer_id'               => absint( $subscription->get_user_id() ),
        ) );
    
        // Loop through user subscriptions
        foreach ( $user_subscriptions as $subscription_id => $user_subscription ) {
            if ( $subscription->get_id() != $subscription_id ) {
                $user_subscription->update_status( 'cancelled' ); // Cancel previous subscriptions
            }
        }
    }
    

    Code goes in functions.php file of your child theme (or in a plugin). It should work.


    Related: