Created
November 23, 2019 16:21
-
-
Save daigo75/35b69deaac23de1e5450c7ad1309bd0a to your computer and use it in GitHub Desktop.
WooCommerce - Allow specific products in cart (WC 3.x)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* 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 <support@aelia.co> | |
*/ | |
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 .= '<p>' . __('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') . '</p>'; | |
} | |
return $price_html; | |
}, 10, 2); |
Ok thank you. I'm going to ask Polylang if they can help me.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The message is passed to the
__()
localisation function. Polylang should be able to translate it using Polylang's string translation. I'm not familiar with that specific plugin, though, I would recommend to ask its team how to proceed.