View difference between Paste ID: tRbJKt37 and BRU1BP2E
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);