1
votes

I'm doing work for a non-profit where people can order informational pamphlets from them. The pamphlets can be ordered individually or as a pack. The pack is set up as one product with id 1076.

When a customer orders the pack, they can only order the pack on its own.

The code I have clears the cart of any other products and leaves just the pack when the pack is added to the cart. It then disables the Add to Cart button for all products when the pack is in the cart. And finally it changes the popup error message when people click on the greyed out Add to Cart button.

How do I ensure that wc_print_notice() only outputs a notice in cart page just once?

Here's the code I have so far (it's been cobbled together from several sources so it's probably inefficient)

// Remove conditionally cart items based on a specific product (item)
    function remove_cart_items_conditionally( $cart ) {
    // HERE define your specific product ID
    $specific_product_id = 1076; 

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

    $cart_items  = $cart->get_cart(); // Cart items array
    $items_count = count($cart_items); // Different cart items count

    // Continue if cart has at least 2 different cart items
    if ( $items_count < 2 )
        return;

    $last_item    = end($cart_items); // Last cart item data array
    $is_last_item = false; // Initializing

    // Check if the specific product is the last added item
    if ( in_array($specific_product_id, array( $last_item['product_id'], $last_item['variation_id'] ) ) ) {
        $is_last_item = true;
    }

    // Loop through cart items
    foreach ( $cart_items as $cart_item_key => $cart_item ) {
        // Remove all others cart items when specific product ID is the last added to cart
        if ( ! in_array($specific_product_id, array( $cart_item['product_id'], $cart_item['variation_id'] ) ) && $is_last_item ) {
            $cart->remove_cart_item( $cart_item_key );
            wc_print_notice( 'Individual resources have been removed as the full pack already contains all the resources', 'notice' );
        }
    }
}
add_action( 'woocommerce_before_calculate_totals', 'remove_cart_items_conditionally', 10, 1 );

// Disable the add to cart button if specified product is in the cart
function disable_add_to_cart_if_product_is_in_cart ( $is_purchasable, $product ){

    $specific_product_id = 1076;

    // Loop through cart items checking if the product is already in cart
    foreach ( WC()->cart->get_cart() as $cart_item ){
        if ( in_array($specific_product_id, array( $cart_item['product_id'], $cart_item['variation_id'] ) ) ) {
            return false;

        }
    }
    return $is_purchasable;
}
add_filter( 'woocommerce_is_purchasable', 'disable_add_to_cart_if_product_is_in_cart', 10, 2 );

// Change disabled add to cart button popup message to something relevant
function customizing_product_variation_message( $translated_text, $untranslated_text, $domain )
{
    if ( in_array($specific_product_id, array( $cart_item['product_id'], $cart_item['variation_id'] ) ) ) {
        if ($untranslated_text == 'Sorry, this product is unavailable. Please choose a different combination.') {
        $translated_text = __( 'The full pack in the cart already contains this resource', $domain );
        }
    }
    return $translated_text;
}
add_filter( 'gettext', 'customizing_product_variation_message', 10, 3 );

my code is made from this answer threads:

Remove conditionally Woocommerce cart items based on a specific product

Disable Woocommerce add to cart button if the product is already in cart

Customizing product variations message on single product pages

1
Sorry, I'm stressed out of my mind at the moment with trying to get this finished and losing our home. I will edit and break it into two questions when I next have a moment to breathe.Rose Thorn
Sorry, I'm in the middle of a house move and will be coming back to this after the move is complete. (Really appreciate the help in the meantime)Rose Thorn

1 Answers

0
votes

You are using the wc_print_notice in a loop so it will display as many time as loop count. To overcome this please give a try with following code.

Replace this section of code . This code will default disable notice call. It will enable notice call only when there execute a loop and remove the cart item.

// Loop through cart items
    foreach ( $cart_items as $cart_item_key => $cart_item ) {
        // Remove all others cart items when specific product ID is the last added to cart
        if ( ! in_array($specific_product_id, array( $cart_item['product_id'], $cart_item['variation_id'] ) ) && $is_last_item ) {
            $cart->remove_cart_item( $cart_item_key );
            wc_print_notice( 'Individual resources have been removed as the full pack already contains all the resources', 'notice' );
        }
    }

by this code and let me know the result.

// Loop through cart items
    $enable_notice = false;
    foreach ( $cart_items as $cart_item_key => $cart_item ) {
        // Remove all others cart items when specific product ID is the last added to cart
        if ( ! in_array($specific_product_id, array( $cart_item['product_id'], $cart_item['variation_id'] ) ) && $is_last_item ) {
            $cart->remove_cart_item( $cart_item_key );
            $enable_notice = true;
        }
    }
    if($enable_notice){
        wc_print_notice( 'Individual resources have been removed as the full pack already contains all the resources', 'notice' );    
    }