Search code examples
phpmethodswoocommercecartwoocommerce-subscriptions

Change cart items subscription properties values before checkout


This may be a noob question so apologies in advance.

I have variable subscription products whose price varies by subscription length. I also have simple subscriptions that have a subscription_length = 0. When the cart contains both types, Woocommerce subscriptions creates two subscriptions.

I am trying to modify the subscription_length metadata of all the items in the cart to match the longest length in the cart so only one subscription will be created.

I just can't seem to find right way to update the cart. It might just be stupid human PHP tricks.

This is the latest variation of the statement that is not working right now:

$cart[$item_key]['data']->subscription_length = $maxlength;

I've tried a dozen or more variations on the theme to update the $cart data. some failed and some succeeded but the data in $cart did not change.

function csi_align_subscription_length() {
    $maxlength = 0;
    $cart = WC()->cart->get_cart();

    //find the longest length
    foreach ( $cart as $item_key => $item ){
        if ( WC_Subscriptions_Product::is_subscription( $item['data'] ) ) {
            $length = WC_Subscriptions_Product::get_length( $item['data'] );
            $maxlength = ($length > $maxlength) ?  $length : $maxlength ;   //get the longest length
        }
    }   

    //set all subscription lengths to the longest lengths
    foreach ( $cart as $item_key => $item ){
        if ( WC_Subscriptions_Product::is_subscription( $item['data'] ) ) {
            echo '<pre>';
            echo "cart-item before: ". var_dump($cart[$item_key]);
            $cart[$item_key]['data']->subscription_length = $maxlength;
            echo "cart-item after:  ".var_dump($cart[$item_key]);
            echo '</pre>';
        }
    }   
    WC()->cart->set_cart_contents($cart);
}
add_filter( 'woocommerce_subscription_cart_before_grouping', 'csi_align_subscription_length', 10, 1 );

I just need to get the subscriptions in the cart to align to a common group so I only have 1 order and 1 subscription per checkout. I am open to a different approach if I've gotten lost off on a tangent.


Solution

  • Finally resolved the issue. No setter for 'subscription_length'. Had to use update_meta_data method. The meta key is '_subscription_length'. the following code works.

    function csi_align_subscription_length( $cart ) {
        if ( ( is_admin() && ! defined( 'DOING_AJAX' ) )  )
            return;
    
        if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
            return;
    
        $maxlength = (float) 0;
    
        // Find the longest subscription length
        foreach ( $cart->get_cart() as $cart_item ){
            if ( is_a( $cart_item['data'], 'WC_Product_Subscription' ) || is_a( $cart_item['data'], 'WC_Product_Subscription_Variation' ) ) {
                $length = (float) WC_Subscriptions_Product::get_length( $cart_item['data'] );
                $maxlength = ($length > $maxlength) ?  $length : $maxlength ;   //get the longest length
            }
        } 
    
        // set the subscription length for everything in the cart
        foreach ( $cart->get_cart() as $item_key => $cart_item ){
            if ( is_a( $cart_item['data'], 'WC_Product_Subscription' ) || is_a( $cart_item['data'], 'WC_Product_Subscription_Variation' )) {
                $cart_item['data']->update_meta_data( '_subscription_length', $maxlength );
            }
        }
    }
    
    add_action( 'woocommerce_before_calculate_totals', 'csi_align_subscription_length', 5, 1 );