Change cart items subscription properties values before checkout

≡放荡痞女 提交于 2020-03-23 06:24:06

问题


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.


回答1:


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 );




回答2:


Updated (work for simple subscriptions and subscription variations (of a variable subscription)

The hook woocommerce_before_calculate_totals allow to change product properties on cart items. Since woocommerce 3 and CRUD Objects, Object properties can't be accessed directly and you will have to use available getters and setters methods instead… Here we:

  1. get an array of length for all Subscriptions cart items only.
  2. get the max length value
  3. set the max length value for all Subscriptions cart items only.

The required code:

add_action( 'woocommerce_before_calculate_totals', 'before_calculate_totals_action_callback', 10, 1 );
function before_calculate_totals_action_callback( $cart ) {
    if ( ( is_admin() && ! defined( 'DOING_AJAX' ) )  )
        return;

    if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
        return;

    $maxlength = []; // Initializing

    // First loop (get)
    foreach ( $cart->get_cart() as $cart_item ){
        if ( in_array( $cart_item['data']->get_type(), array('subscription', 'subscription_variation') ) ) {
            $maxlength[] = (float) $cart_item['data']->get_length();
        }
    }

    // Get the highest value
    $maxlength = max($maxlength);

    // Second loop (set)
    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' ) ) {
            $cart_item['data']->set_length( $maxlength );
        }
    }
}

Code goes in function.php file of your active child theme (or active theme). Tested and works.

Note: When submitting the order, you will certainly need to set the cart item (custom) length as custom order item meta data.



来源:https://stackoverflow.com/questions/55924998/change-cart-items-subscription-properties-values-before-checkout

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!