/** * Restricts which products can be added to the cart at the same time. * Version for WooCommerce 3.x and later. * * HOW TO USE THIS CODE * 1. Add the code to the bottom of your theme's functions.php file (see https://www.skyverge.com/blog/add-custom-code-to-wordpress/). * 2. Set the IDs of the products that are allowed to be added to the cart at the same time. * 3. Amend the message displayed to customers when products are unavailable after the specified * products have been added to the cart (see function woocommerce_get_price_html(), below). * * GPL DISCLAIMER * Because this code program is free of charge, there is no warranty for it, to the extent permitted by applicable law. * Except when otherwise stated in writing the copyright holders and/or other parties provide the program "as is" * without warranty of any kind, either expressed or implied, including, but not limited to, the implied warranties of * merchantability and fitness for a particular purpose. The entire risk as to the quality and performance of the program * is with you. should the program prove defective, you assume the cost of all necessary servicing, repair or correction. * * Need a consultation, or assistance to customise this code? Find us on Codeable: https://aelia.co/hire_us */ /** * Retrieves the cart contents. We can't just call WC_Cart::get_cart(), because * such method runs multiple actions and filters, which we don't want to trigger * at this stage. * * @author Aelia */ function aelia_get_cart_contents() { $cart_contents = array(); /** * Load the cart object. This defaults to the persistant cart if null. */ $cart = WC()->session->get( 'cart', null ); if ( is_null( $cart ) && ( $saved_cart = get_user_meta( get_current_user_id(), '_woocommerce_persistent_cart_' . get_current_blog_id(), true ) ) ) { // @codingStandardsIgnoreLine $cart = $saved_cart['cart']; } elseif ( is_null( $cart ) ) { $cart = array(); } elseif ( is_array( $cart ) && ( $saved_cart = get_user_meta( get_current_user_id(), '_woocommerce_persistent_cart_' . get_current_blog_id(), true ) ) ) { // @codingStandardsIgnoreLine $cart = array_merge( $saved_cart['cart'], $cart ); } if ( is_array( $cart ) ) { foreach ( $cart as $key => $values ) { $_product = wc_get_product( $values['variation_id'] ? $values['variation_id'] : $values['product_id'] ); if ( ! empty( $_product ) && $_product->exists() && $values['quantity'] > 0 ) { if ( $_product->is_purchasable() ) { // Put session data into array. Run through filter so other plugins can load their own session data $session_data = array_merge( $values, array( 'data' => $_product ) ); $cart_contents[ $key ] = apply_filters( 'woocommerce_get_cart_item_from_session', $session_data, $values, $key ); } } } } return $cart_contents; } // Step 1 - Keep track of cart contents add_action('wp_loaded', function() { // If there is no session, then we don't have a cart and we should not take // any action if(!is_object(WC()->session)) { return; } // This variable must be global, we will need it later. If this code were // packaged as a plugin, a property could be used instead global $allowed_cart_items; // We decided that products with ID 737 and 832 can go together. If any of them // is in the cart, all other products cannot be added to it global $restricted_cart_items; $restricted_cart_items = array( // Set the IDs of the products that can be added to the cart at the same time 1, 2, 3, ); // "Snoop" into the cart contents, without actually loading the whole cart foreach(aelia_get_cart_contents() as $item) { if(in_array($item['data']->get_id(), $restricted_cart_items)) { $allowed_cart_items[] = $item['data']->get_id(); // If you need to allow MULTIPLE restricted items in the cart, comment // the line below break; } } // Step 2 - Make disallowed products "not purchasable" add_filter('woocommerce_is_purchasable', function($is_purchasable, $product) { global $restricted_cart_items; global $allowed_cart_items; // If any of the restricted products is in the cart, any other must be made // "not purchasable" if(!empty($allowed_cart_items)) { // To allow MULTIPLE products from the restricted ones, use the line below //$is_purchasable = in_array($product->id, $allowed_cart_items) || in_array($product->id, $restricted_cart_items); // To allow a SINGLE products from the restricted ones, use the line below $is_purchasable = in_array($product->get_id(), $allowed_cart_items); } return $is_purchasable; }, 10, 2); }, 10); // Step 3 - Explain customers why they can't add some products to the cart add_filter('woocommerce_get_price_html', function($price_html, $product) { if(!$product->is_purchasable() && is_product()) { $price_html .= '

' . __('This product cannot be purchased together with "Product X" or "Product Y". If you wish to buy this product, please remove the other products from the cart.', 'woocommerce') . '

'; } return $price_html; }, 10, 2);