SHOW:
|
|
- or go back to the newest paste.
1 | /** | |
2 | - | * Restricts which products can be added to the cart at the same time. Tested |
2 | + | * Restricts which products can be added to the cart at the same time. |
3 | - | * with WooCommerce up to version 2.5. |
3 | + | * Version for WooCommerce 3.x and later. |
4 | - | * |
4 | + | |
5 | * HOW TO USE THIS CODE | |
6 | * 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/). | |
7 | * 2. Set the IDs of the products that are allowed to be added to the cart at the same time. | |
8 | * 3. Amend the message displayed to customers when products are unavailable after the specified | |
9 | * products have been added to the cart (see function woocommerce_get_price_html(), below). | |
10 | * | |
11 | * GPL DISCLAIMER | |
12 | * Because this code program is free of charge, there is no warranty for it, to the extent permitted by applicable law. | |
13 | * Except when otherwise stated in writing the copyright holders and/or other parties provide the program "as is" | |
14 | * without warranty of any kind, either expressed or implied, including, but not limited to, the implied warranties of | |
15 | * merchantability and fitness for a particular purpose. The entire risk as to the quality and performance of the program | |
16 | * is with you. should the program prove defective, you assume the cost of all necessary servicing, repair or correction. | |
17 | * | |
18 | * Need a consultation, or assistance to customise this code? Find us on Codeable: https://aelia.co/hire_us | |
19 | */ | |
20 | ||
21 | /** | |
22 | * Retrieves the cart contents. We can't just call WC_Cart::get_cart(), because | |
23 | * such method runs multiple actions and filters, which we don't want to trigger | |
24 | * at this stage. | |
25 | * | |
26 | * @author Aelia <support@aelia.co> | |
27 | */ | |
28 | function aelia_get_cart_contents() { | |
29 | $cart_contents = array(); | |
30 | /** | |
31 | * Load the cart object. This defaults to the persistant cart if null. | |
32 | */ | |
33 | $cart = WC()->session->get( 'cart', null ); | |
34 | ||
35 | - | if ( is_null( $cart ) && ( $saved_cart = get_user_meta( get_current_user_id(), '_woocommerce_persistent_cart', true ) ) ) { |
35 | + | if ( is_null( $cart ) && ( $saved_cart = get_user_meta( get_current_user_id(), '_woocommerce_persistent_cart_' . get_current_blog_id(), true ) ) ) { // @codingStandardsIgnoreLine |
36 | - | $cart = $saved_cart['cart']; |
36 | + | $cart = $saved_cart['cart']; |
37 | - | } elseif ( is_null( $cart ) ) { |
37 | + | } |
38 | - | $cart = array(); |
38 | + | elseif ( is_null( $cart ) ) { |
39 | $cart = array(); | |
40 | } | |
41 | elseif ( is_array( $cart ) && ( $saved_cart = get_user_meta( get_current_user_id(), '_woocommerce_persistent_cart_' . get_current_blog_id(), true ) ) ) { // @codingStandardsIgnoreLine | |
42 | $cart = array_merge( $saved_cart['cart'], $cart ); | |
43 | } | |
44 | ||
45 | if ( is_array( $cart ) ) { | |
46 | foreach ( $cart as $key => $values ) { | |
47 | $_product = wc_get_product( $values['variation_id'] ? $values['variation_id'] : $values['product_id'] ); | |
48 | ||
49 | if ( ! empty( $_product ) && $_product->exists() && $values['quantity'] > 0 ) { | |
50 | if ( $_product->is_purchasable() ) { | |
51 | // Put session data into array. Run through filter so other plugins can load their own session data | |
52 | $session_data = array_merge( $values, array( 'data' => $_product ) ); | |
53 | $cart_contents[ $key ] = apply_filters( 'woocommerce_get_cart_item_from_session', $session_data, $values, $key ); | |
54 | } | |
55 | } | |
56 | } | |
57 | } | |
58 | return $cart_contents; | |
59 | } | |
60 | ||
61 | // Step 1 - Keep track of cart contents | |
62 | add_action('wp_loaded', function() { | |
63 | // If there is no session, then we don't have a cart and we should not take | |
64 | // any action | |
65 | if(!is_object(WC()->session)) { | |
66 | return; | |
67 | } | |
68 | ||
69 | // This variable must be global, we will need it later. If this code were | |
70 | // packaged as a plugin, a property could be used instead | |
71 | global $allowed_cart_items; | |
72 | - | 737, |
72 | + | |
73 | - | 832, |
73 | + | |
74 | global $restricted_cart_items; | |
75 | $restricted_cart_items = array( | |
76 | // Set the IDs of the products that can be added to the cart at the same time | |
77 | 1, | |
78 | - | if(in_array($item['data']->id, $restricted_cart_items)) { |
78 | + | 2, |
79 | - | $allowed_cart_items[] = $item['data']->id; |
79 | + | 3, |
80 | ); | |
81 | ||
82 | // "Snoop" into the cart contents, without actually loading the whole cart | |
83 | foreach(aelia_get_cart_contents() as $item) { | |
84 | if(in_array($item['data']->get_id(), $restricted_cart_items)) { | |
85 | $allowed_cart_items[] = $item['data']->get_id(); | |
86 | ||
87 | // If you need to allow MULTIPLE restricted items in the cart, comment | |
88 | // the line below | |
89 | break; | |
90 | } | |
91 | - | |
91 | + | |
92 | ||
93 | // Step 2 - Make disallowed products "not purchasable" | |
94 | add_filter('woocommerce_is_purchasable', function($is_purchasable, $product) { | |
95 | global $restricted_cart_items; | |
96 | global $allowed_cart_items; | |
97 | - | |
97 | + | |
98 | // If any of the restricted products is in the cart, any other must be made | |
99 | - | $is_purchasable = in_array($product->id, $allowed_cart_items); |
99 | + | |
100 | if(!empty($allowed_cart_items)) { | |
101 | // To allow MULTIPLE products from the restricted ones, use the line below | |
102 | //$is_purchasable = in_array($product->id, $allowed_cart_items) || in_array($product->id, $restricted_cart_items); | |
103 | ||
104 | // To allow a SINGLE products from the restricted ones, use the line below | |
105 | $is_purchasable = in_array($product->get_id(), $allowed_cart_items); | |
106 | } | |
107 | return $is_purchasable; | |
108 | }, 10, 2); | |
109 | }, 10); | |
110 | ||
111 | // Step 3 - Explain customers why they can't add some products to the cart | |
112 | add_filter('woocommerce_get_price_html', function($price_html, $product) { | |
113 | if(!$product->is_purchasable() && is_product()) { | |
114 | $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>'; | |
115 | } | |
116 | return $price_html; | |
117 | }, 10, 2); |