Balázs Varga
Balázs Varga

Reputation: 1856

Conditionally remove specific cart items in Woocommerce

I'm developing a WooCommerce plugin for ordering foods for specific dates from a calendar like weekly list.

There is a time limit for orders, you can order for tomorrow on each day until 14:00. It works on the page where you can order the items (the add to cart buttons will not show up if the limit was reached), but if you already have an item in cart which will be unavailable, you CAN order it after 14:00.

I have read somewhere that there is an action hook for such actions, so I tried to figure it out myself but got stuck.

A little introduction on how it works. When you click on the add to cart button, the item will be created in the cart with a custom meta tag, which contains the infos i need in this format: MenuCode-Year-WeekOfYear-DayOfWeek.

The name of the function is wc_minimum_order_amount, because it also contains a piece of code to show a wc_notice if the order amount is less than a specified amount. This part was removed from the below code because it's irrelevant to the question, and it works.

And here is the hook and the code that I use:

add_action('woocommerce_checkout_process', 'wc_minimum_order_amount' );
add_action('woocommerce_before_cart' , 'wc_minimum_order_amount' );
function wc_minimum_order_amount() {
    $cart = WC()->cart->get_cart();
    foreach($cart as $item => $values) {
        $co   = explode('-', $values['_custom_options']);
        $year = $co[1];
        $week = $co[2];
        $day  = $co[3];
        $hour = date('H');

        if($year < date('Y')) {
            WC()->cart->remove_cart_item($item);
        }
        else if($year == date('Y') && $week < date('W')) {
            WC()->cart->remove_cart_item($item);
        }
        else if($year == date('Y') && $week == date('W') && $day < date('w')) {
            WC()->cart->remove_cart_item($item);
        }
        else if($year == date('Y') && $week == date('W') && $day == date('w') && $hour >= 14) {
            WC()->cart->remove_cart_item($item);
        }
    }
}

But it don't remove the items from the cart, as I was expecting.

How can I make it work?

Thanks

Upvotes: 2

Views: 1273

Answers (1)

LoicTheAztec
LoicTheAztec

Reputation: 253814

Here I am using only woocommerce_before_calculate_totals action hook, that should work everywhere.

I have made some little changes in your code:

add_action('woocommerce_before_calculate_totals', 'wc_minimum_order_amount', 10, 1 );
function wc_minimum_order_amount( $cart ) {

    if ( is_admin() && ! defined( 'DOING_AJAX' ) )
        return;

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

    // Set here the time offset (in hours)
    $hours_offset = 14;

    $now_year      = date('Y');
    $now_year_week = date('W');
    $now_day_week  = date('w');
    $now_hour      = date('H');

    foreach($cart->get_cart() as $cart_item_key => $cart_item ) {
       if( isset($cart_item['_custom_options']) && ! empty($cart_item['_custom_options']) ){
            $date = explode('-', $cart_item['_custom_options']);
            $date_year      = $date[1];
            $date_year_week = $date[2];
            $date_day_week  = $date[3];


            if( $date_year < $now_year ) {
                $remove_cart_item = true;
                wc_add_notice( __( 'CASE1', 'woocommerce' ), 'notice' ); // Just for testing (to be removed)
            }
            elseif( $date_year == $now_year && $date_year_week < $now_year_week ) {
                $remove_cart_item = true;
                wc_add_notice( __( 'CASE2', 'woocommerce' ), 'notice' ); // Just for testing (to be removed)
            }
            elseif( $date_year == $now_year && $date_year_week == $now_year_week && $date_day_week < $now_day_week ) {
                $remove_cart_item = true;
                wc_add_notice( __( 'CASE3', 'woocommerce' ), 'notice' ); // Just for testing (to be removed)
            }
            elseif( $date_year == $now_year && $date_year_week == $now_year_week && $date_day_week == $now_day_week && $now_hour >= $hours_offset ) {
                $remove_cart_item = true;
                wc_add_notice( __( 'CASE4', 'woocommerce' ), 'notice' ); // Just for testing (to be removed)
            }
            else {
                $remove_cart_item = false;
                wc_add_notice( __( 'CASE0', 'woocommerce' ), 'notice' ); // Just for testing (to be removed)
            }

            if($remove_cart_item) {
                $cart->remove_cart_item($cart_item_key);
            }
        }
    }
}

The Code goes in function.php file of your active child theme (or theme) or also in any plugin file.

I can't test it as this is very specific, but this should work.

Upvotes: 2

Related Questions