Search code examples
phpwordpresswoocommercehook-woocommercecart

Woocommerce duplicate product in cart item without increasing the product quantity


I am trying to do BOGO on my site the scenario is when some one add a product to the cart with the quantity of 5 or some one in cart page increase a specific cart item quantity grater than 5 than automatically on cart page the cart item will duplicated and add as a cart item with the subtotal of 0.00$. Here is the example

Product Quantity Subtotal
T-Shirt 5 10.00$
T-Shirt 1 FREE

Bellow i have try this on my plugin page..

add_filter('woocommerce_update_cart_action_cart_updated', 'on_action_cart_updated');

function on_action_cart_updated( $cart_updated ) {

    if ( WC()->cart ) {

        $cart_items = WC()->cart->get_cart();

        foreach ( $cart_items as $key => $cart_item ) {
            if ( $cart_item && 5 <= $cart_item['quantity'] ) {
                $unique_key = md5( microtime().rand() );
                $duplicate_item = $cart_item;
                $duplicate_item['key'] = $unique_key;
                $duplicate_item['quantity'] = 1;

                $item_object = $cart_item['data'];
                $item_object->add_meta_data('duplicated','yes');

                $_product = wc_get_product( $cart_item );
                error_log( $_product->get_type() );
//                $product =  new WC_Product_Simple();
//                $product->set_title('')
//                //$item_object->get_meta_data('duplicated');
//
//                WC()->cart->add_to_cart( $cart_item['product_id'], 1, 0, 0, [], $unique_key);
                WC()->cart->add_to_cart($cart_item['product_id'],1);
//                WC()->cart->cart_contents[$unique_key] = $duplicate_item;
            }
        }
    }

    return $cart_updated;
}

This Code will increase the old cart item quantity , not adding new cart item as the duplicate old cart item on the cart lists.


Solution

  • Try to use the following instead:

    // Duplicate cart item (separated)
    add_filter('woocommerce_update_cart_action_cart_updated', 'action_on_cart_updated');
    function action_on_cart_updated( $cart_updated ) {
        $cart = WC()->cart;
    
        if ( ! $cart->is_empty() ) {
            foreach ( $cart->get_cart() as $item_key => $item ) {
                if ( $item && 5 <= $item['quantity'] ) {
                    // Adjust cart item quantity
                    $cart->set_quantity( $item_key, ($item['quantity'] - 1), false );
                    $item_data = ['unique_key' => md5(microtime().rand()), 'free_item' => 'yes'];
                    // Add a separated product (free )
                    $cart->add_to_cart($item['product_id'], 1, $item['variation_id'], $item['variation'], $item_data);
                }
            }
        }
        return $cart_updated;
    }
    
    // Set cart item price
    add_filter('woocommerce_before_calculate_totals', 'action_before_calculate_totals');
    function action_before_calculate_totals( $cart ) {
        if ((is_admin() && !defined('DOING_AJAX')))
            return;
    
        foreach ( $cart->get_cart() as $item_key => $item ) {
            if ( isset($item['free_item']) ) {
                $item['data']->set_price(0);
            }
        }
    }
    
    // Display "Free" instead of "0" price
    add_action('woocommerce_cart_item_subtotal', 'filter_cart_item_displayed_price', 10, 2);
    add_action('woocommerce_cart_item_price', 'filter_cart_item_displayed_price', 10, 2);
    function filter_cart_item_displayed_price($price_html, $cart_item){
        if (isset($cart_item['free_item'])) {
            return 'FREE';
        }
        return $price_html;
    }
    

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