* @link http://domain.tld * @license GPL 2.0+ * @copyright 2022 WebAppick */ // Ensure the file is not accessed directly. if (!defined('ABSPATH')) { exit; } use Disco\App\Disco; use Disco\App\Utility\Helper; use Disco\App\Utility\Settings; if ( ! function_exists( 'disco_cart_apply_free_items' ) ) { function disco_cart_apply_free_items( $cart ) { if ( is_admin() && ! defined( 'DOING_AJAX' ) ) { return; } if( Settings::get( 'discount_priority_type' ) === 'woocommerce_coupon' ) { return $cart; } if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 ) { return; } if ( $cart->is_empty() ) { return; } // Clone cart to avoid free products when calculating discount $cart_copy = new WC_Cart; foreach ( $cart->get_cart() as $cart_item ) { if ( ! empty( $cart_item['is_free_product'] ) ) { continue; } $cart_copy->add_to_cart( $cart_item['product_id'], $cart_item['quantity'], $cart_item['variation_id'] ?? 0, $cart_item['variation'] ?? array(), $cart_item['cart_item_data'] ?? array() ); } foreach ( $cart->get_applied_coupons() as $coupon_code ) { $cart_copy->apply_coupon( $coupon_code ); } $discounts = ( new Disco )->get_cart_items_discount_for_bogo( $cart_copy ); $free_ids = $discounts['get_ids'] ?? array(); $free_qty = $discounts['get_qty'] ?? 0; $bogo_type = $discounts['bogo_type'] ?? 'products'; // Remove invalid free items from cart foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) { if ( ! isset( $cart_item['is_free_product'] ) || ! $cart_item['is_free_product'] ) { continue; } $product_id = $cart_item['product_id']; if ( ( $bogo_type === 'categories' && ! Helper::is_in_category( $product_id, $free_ids ) ) || ( $bogo_type !== 'categories' && ! in_array( $product_id, $free_ids, true ) ) ) { $cart->remove_cart_item( $cart_item_key ); } } if ( empty( $free_qty ) || empty( $free_ids ) ) { return; } if ( $bogo_type === 'categories' ) { $free_count = 0; foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) { if ( $free_count >= $free_qty ) { break; } if ( ! empty( $cart_item['is_free_product'] ) ) { continue; } $product_id = $cart_item['product_id']; if ( Helper::is_in_category( $product_id, $free_ids ) ) { $remaining_qty = $free_qty - $free_count; // Only mark item free if the full quantity fits if ( $cart_item['quantity'] <= $remaining_qty ) { $cart->cart_contents[ $cart_item_key ]['is_free_product'] = true; $free_count += $cart_item['quantity']; } else { continue; } } } } else { // Product-based free items foreach ( $free_ids as $product_id ) { $found = false; foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) { if ( intval( $cart_item['product_id'] ) === intval( $product_id ) && ! empty( $cart_item['is_free_product'] ) ) { $current_qty = $cart_item['quantity']; if ( $current_qty !== $free_qty ) { $cart->set_quantity( $cart_item_key, $free_qty ); } $found = true; break; } } if ( ! $found ) { $cart->add_to_cart( $product_id, $free_qty, 0, array(), array( 'is_free_product' => true ) ); } } } } add_action( 'woocommerce_before_calculate_totals', 'disco_cart_apply_free_items', 5 ); } if ( ! function_exists( 'disco_set_free_product_price' ) ) { /** * Set the price of free products to zero. * * @param \WC_Cart $cart Cart Object. */ function disco_set_free_product_price( $cart ) { if ( is_admin() && ! defined( 'DOING_AJAX' ) ) { return; } foreach ( $cart->get_cart() as $cart_item_key => $cart_item ) { if ( empty( $cart_item['is_free_product'] ) ) { continue; } // Only process if not already handled if ( empty( $cart_item['free_product_processed'] ) ) { $cart_item['data']->set_price( 0 ); $cart_item['data']->set_regular_price( 0 ); $cart->cart_contents[ $cart_item_key ]['free_product_note'] = __( 'This item is added as free!', 'disco' ); // Mark as processed to avoid duplicate changes $cart->cart_contents[ $cart_item_key ]['free_product_processed'] = true; } } } add_action( 'woocommerce_before_calculate_totals', 'disco_set_free_product_price', 10 ); } if ( ! function_exists( 'disco_free_product_label' ) ) { function disco_free_product_label( $item_data, $cart_item ) { if ( ! empty( $cart_item['free_product_note'] ) ) { $item_data[] = array( 'key' => __( 'Note', 'disco' ), 'value' => $cart_item['free_product_note'], ); } return $item_data; } add_filter( 'woocommerce_get_item_data', 'disco_free_product_label', 10, 2 ); }