计算 WooCommerce 购物车中的购物车内容 VS 术语计数,并使用 AJAX(片段)显示差异

Count cart content VS term count in WooCommerce cart and show the difference using AJAX (Fragments)

我得到了四个礼盒。客户只能将带有fits-in-giftbox标签的产品放入其中。这些盒子有 space 表示 4、9、16 或 24 件。所有其他产品将单独包装。

我需要计算每个盒子被添加到购物车的次数,并计算它们可以放入的总件数。

然后我需要计算客户将多少 fits-in-giftbox 标记的产品添加到他们的购物车并将该数字与所有礼品盒可以容纳的数量相匹配。

示例: 客户将一盒 4(可容纳 4 件产品)和一盒 24(可容纳 24 件产品)放入购物车。客户现在总共可以添加 28 件标有适合礼品盒的产品。

客户添加了 18 件标有 fits-in-giftbox 的产品。现在还剩10件。

预期输出: “您已将三 (3) 个礼盒添加到您的购物车。请添加额外的 XX 产品以填充您的礼盒。”

或: “您已经添加了两 (2) 个可容纳 8 件的礼盒。您已将 12 件产品添加到您的购物车。超过四 (4) 件产品将单独包装,除非您将另一个礼盒添加到您的购物车。”

或: "您已将一个礼盒添加到您的购物车,但没有礼盒产品。除非您这样做,否则这些产品将单独包装。"

我希望这是有道理的。感觉自己在兜圈子..

这是我需要帮助的代码:

function product_tag_count( $term ) {
    $tag_count = 0;
    foreach( WC()->cart->get_cart() as $cart_item ) {
        if ( has_term( $term, 'product_tag', $cart_item['product_id'] ) )
            $tag_count += $cart_item['quantity'];
    }
    return $tag_count == 0 ? false : $tag_count;
}

function display_cart_counters() {

    ob_start();

    $link  = wc_get_checkout_url();
    $title = __( 'Checkout and Pay', 'woocommerce' );
    $tag_count = __( '0 products', 'woocommerce');

    echo '<a class="product-cart-count" href="' . $link . '" title="' . $title . '">' . $tag_count . '</a>';

    return ob_get_clean();

}

add_filter( 'woocommerce_add_to_cart_fragments', 'counters_add_to_cart_fragment', 30, 1 );
function counters_add_to_cart_fragment( $fragments ) {
    
    ob_start();

    // count the number of giftboxes
    $giftbox4 = 'giftbox-4';
    $fits_in_giftbox4 = '4';
    $count_giftbox4 = product_tag_count( $giftbox4 );

    $giftbox9 = 'giftbox-9';
    $fits_in_giftbox9 = '9';
    $count_giftbox9 = product_tag_count( $giftbox9 );

    $giftbox16 = 'giftbox-16';
    $fits_in_giftbox16 = '16';
    $count_giftbox16 = product_tag_count( $giftbox16 );

    $giftbox24 = 'giftbox-24';
    $fits_in_giftbox24 = '24';
    $count_giftbox24 = product_tag_count( $giftbox24 );
    
    // get the total number of giftboxes
    $count_giftboxes_total = ( $count_giftbox4 + $count_giftbox9 + $count_giftbox16 + $count_giftbox24 );

    // count how many products that fits into giftboxes
    $fits_in_giftbox = 'goes-into-box';
    $count_fits_in_giftbox = product_tag_count( $fits_in_giftbox );

    // count the cart as a whole
    $cart_count = WC()->cart->get_cart_contents_count();

    // calculate the difference between cart as a whole and giftbox products
    $difference_between_cart_and_giftbox_products = ( $cart_count - $count_fits_in_giftbox );

    // calculate boxes VS giftbox products
    $fits_into_boxes_vs_giftbox_products = ( $count_giftboxes_total - $count_fits_in_giftbox );


    // this is what I need help with.. how do I get the total pieces of all boxes added to cart?
    
    // first check, is there space left or not?
    if ( $count_giftboxes_total < $count_fits_in_giftbox ) {
    $output = sprintf (_n( 'You have %d product to much. This will be packed separately unless you add another giftbox.', 'You have %d products to many. These will be packed separately unless you add another giftbox.' ), 'woocommerce');
    } elseif () {
        $output = sprintf (_n( 'You have %d product to much. This will be packed separately unless you add another giftbox.', 'You have %d products to many. These will be packed separately unless you add another giftbox.' ), 'woocommerce');
    } elseif () {
        $output = sprintf (_n( 'You have %d product to much. This will be packed separately unless you add another giftbox.', 'You have %d products to many. These will be packed separately unless you add another giftbox.' ), 'woocommerce');
    } else {
        $output = sprintf (_n( 'You have %d product to much. This will be packed separately unless you add another giftbox.', 'You have %d products to many. These will be packed separately unless you add another giftbox.' ), 'woocommerce');
    }
    
    $checkout_link = wc_get_checkout_url();
    $link_title = __( 'Go to Checkout', 'woocommerce' );

    ?>
    <div class="product-wrapper">
    <?php echo $output; ?>
    <br>
    <a class="product-cart-count" href="<?php echo $link; ?>"
    title="<?php echo $title ?>">Go to Checkout &amp; Pay</a>
    </div>
    
    <?php 
    
        $fragments['a.product-cart-count'] = ob_get_clean();

        return $fragments;
}

add_action( 'woocommerce_before_shop_loop', 'count_products_and_boxes');
add_action( 'woocommerce_before_add_to_cart_form', 'count_products_and_boxes');
function count_products_and_boxes() {
    echo display_cart_counters();
}

这将根据购物车中礼品盒的数量和它们可以包含的产品数量来调整消息。消息已更改:

  • 当购物车包含产品但没有礼盒时
  • 当购物车包含礼品盒但没有产品时
  • 当购物车中的产品多于礼品盒所能容纳的数量时
  • 当购物车中的产品数量少于礼品盒所能容纳的数量时

请注意,我使用了 4 个礼盒的产品 ID,否则你会把它弄得不必要的复杂。

function display_cart_counters() {
    // Settings
    $term = 'fits-in-giftbox';
    $taxonomy = 'product_tag';
    
    // Giftbox IDs. Important, these should not contain the term 'fits-in-giftbox' !!
    // Contents => Product ID
    $giftbox_ids = array( 
        4  => 218,
        9  => 220,
        16 => 813,
        24 => 815 
    );
    
    // Initialize
    $count_fits_in_giftbox = 0;
    $count_giftboxes = 0;
    $count_giftboxes_total = 0;
    $count_not_term = 0;
    $message = '';
    
    // True
    if ( WC()->cart ) { 
        // Loop trough cart items quantities
        foreach( WC()->cart->get_cart_item_quantities() as $product_id => $cart_item_quantity ) {
            // Contains the definite term
            if ( has_term( $term, $taxonomy, $product_id ) ) {
                // Add the cart item quantity from this certain product to the counter
                $count_fits_in_giftbox += $cart_item_quantity;
            // The box ID is in the cart
            } elseif( in_array( $product_id, $giftbox_ids ) ) {
                // Add 1 * cart item quantity to counter
                $count_giftboxes += 1 * $cart_item_quantity;
                
                // Add contens * the cart item quantity to the counter
                $count_giftboxes_total  += ( array_search ( $product_id, $giftbox_ids ) * $cart_item_quantity );
            // Does not contain the particular term and is not a gift box
            } else {
                // Add the cart item quantity from this certain product to the counter
                $count_not_term += $cart_item_quantity;
            }
        }
    }
    
    // Singular or plural
    $s_o_p_giftbox = _n( '%d giftbox', '%d giftboxes', $count_giftboxes, 'woocommerce' );
    $s_o_p_product = _n( '%d product', '%d products', $count_fits_in_giftbox, 'woocommerce' );
    
    // Additional message for untagged products
    if ( $count_not_term >= 1 ) { 
        $untagged_product_message = ' You also added %s untagged products, these will be packaged separately.';
    } else {
        $untagged_product_message = '';
        $count_not_term = '';
    }
    
    // When the cart contains products, but no giftbox(es)
    if ( $count_giftboxes == 0 && $count_fits_in_giftbox >= 1 ) {
        $message = sprintf( 
            __( 'You have added ' . $s_o_p_giftbox . ' to your cart but ' . $s_o_p_product . '. Unless you do, these products will be packed separately.' . $untagged_product_message . '', 'woocommerce' ), 
            $count_giftboxes, 
            $count_fits_in_giftbox,
            $count_not_term
        );      
    // When the cart contains giftbox(es), but no products
    } elseif ( $count_giftboxes >= 1 && $count_fits_in_giftbox == 0 ) {
        $message = sprintf( 
            __( 'You have added ' . $s_o_p_giftbox . ' to your cart but no giftbox products. Unless you do, these products will be packed separately.' . $untagged_product_message . '', 'woocommerce' ), 
            $count_giftboxes,
            $count_not_term
        );
    // When there are more products in cart than giftboxes can contain
    } elseif( $count_giftboxes_total < $count_fits_in_giftbox ) {
        $message = sprintf( 
            __( 'You have added ' . $s_o_p_giftbox . ' which can hold %d pieces. You have added ' . $s_o_p_product . ' to your cart. The exceeding %d products will be packed separately unless you add another giftbox to your cart.' . $untagged_product_message . '', 'woocommerce' ),
            $count_giftboxes, 
            $count_giftboxes_total, 
            $count_fits_in_giftbox, 
            $count_fits_in_giftbox - $count_giftboxes_total,
            $count_not_term
        );
    // When there are less products in cart than giftboxes can contain
    } elseif( $count_giftboxes_total > $count_fits_in_giftbox ) {
        $message = sprintf( 
            __( 'You have added ' . $s_o_p_giftbox . ' which can hold %d pieces. You have added ' . $s_o_p_product . ' to your cart. Please add an additional %d products to fill your boxes.' . $untagged_product_message . '', 'woocommerce' ), 
            $count_giftboxes, 
            $count_giftboxes_total, 
            $count_fits_in_giftbox, 
            $count_giftboxes_total - $count_fits_in_giftbox,
            $count_not_term
        );
    }
    
    return $message;
}

// Refreshing on cart ajax events
function filter_woocommerce_add_to_cart_fragments( $fragments ) {    
    $fragments['div.display-cart-counters'] = '<div class="display-cart-counters">' . display_cart_counters() . '</div>';
    
    return $fragments;        
}
add_filter( 'woocommerce_add_to_cart_fragments', 'filter_woocommerce_add_to_cart_fragments', 10, 1 );

// Display message via the desired hooks
function display_message() {
    echo '<div class="display-cart-counters">' . display_cart_counters() . '</div>';
}
add_action( 'woocommerce_before_shop_loop', 'display_message', 10, 0 );
add_action( 'woocommerce_before_add_to_cart_form', 'display_message', 10, 0 );