Example #1
0
 /**
  * Validates add-to-cart for bundles.
  * Basically ensures that stock for all bundled products exists before attempting to add them to cart.
  *
  * @param  boolean  $add                core validation add to cart flag
  * @param  int      $product_id         the product id
  * @param  int      $product_quantity   quantity
  * @param  mixed    $variation_id       variation id
  * @param  array    $variations         variation data
  * @param  array    $cart_item_data     cart item data
  * @return boolean                      modified add to cart validation flag
  */
 function woo_bundles_validation($add, $product_id, $product_quantity, $variation_id = '', $variations = array(), $cart_item_data = array())
 {
     global $woocommerce_bundles;
     // Get product type
     $terms = get_the_terms($product_id, 'product_type');
     $product_type = !empty($terms) && isset(current($terms)->name) ? sanitize_title(current($terms)->name) : 'simple';
     // Ordering again?
     $order_again = isset($_GET['order_again']) && isset($_GET['_wpnonce']) && wp_verify_nonce($_GET['_wpnonce'], 'woocommerce-order_again');
     // prevent bundled items from getting validated - they will be added by the container item
     if (isset($cart_item_data['is_bundled']) && $order_again) {
         return false;
     }
     if ($product_type === 'bundle') {
         $product = WC_PB_Core_Compatibility::wc_get_product($product_id);
         if (!$product) {
             return false;
         }
         if (!apply_filters('woocommerce_bundle_before_validation', true, $product)) {
             return false;
         }
         // If a stock-managed product / variation exists in the bundle multiple times, its stock will be checked only once for the sum of all bundled quantities.
         // The stock manager class keeps a record of stock-managed product / variation ids
         $bundled_stock = new WC_PB_Stock_Manager();
         // Grab bundled items
         $bundled_items = $product->get_bundled_items();
         if (!$bundled_items) {
             return $add;
         }
         foreach ($bundled_items as $bundled_item_id => $bundled_item) {
             $id = $bundled_item->product_id;
             $bundled_product_type = $bundled_item->product->product_type;
             // Optional
             $is_optional = $bundled_item->is_optional();
             if ($is_optional) {
                 if (isset($cart_item_data['stamp'][$bundled_item_id]['optional_selected']) && $order_again) {
                     $is_optional_selected = 'yes' === $cart_item_data['stamp'][$bundled_item_id]['optional_selected'] ? true : false;
                 } elseif (isset($_REQUEST[apply_filters('woocommerce_product_bundle_field_prefix', '', $product_id) . 'bundle_selected_optional_' . $bundled_item_id])) {
                     $is_optional_selected = isset($_REQUEST[apply_filters('woocommerce_product_bundle_field_prefix', '', $product_id) . 'bundle_selected_optional_' . $bundled_item_id]);
                 } else {
                     $is_optional_selected = false;
                 }
             }
             if ($is_optional && !$is_optional_selected) {
                 continue;
             }
             // Check quantity
             $item_quantity_min = $bundled_item->get_quantity();
             $item_quantity_max = $bundled_item->get_quantity('max');
             if (isset($_REQUEST[apply_filters('woocommerce_product_bundle_field_prefix', '', $product_id) . 'bundle_quantity_' . $bundled_item_id]) && is_numeric($_REQUEST[apply_filters('woocommerce_product_bundle_field_prefix', '', $product_id) . 'bundle_quantity_' . $bundled_item_id])) {
                 $item_quantity = absint($_REQUEST[apply_filters('woocommerce_product_bundle_field_prefix', '', $product_id) . 'bundle_quantity_' . $bundled_item_id]);
             } elseif (isset($cart_item_data['stamp'][$bundled_item_id]['quantity']) && $order_again) {
                 $item_quantity = $cart_item_data['stamp'][$bundled_item_id]['quantity'];
             } else {
                 $item_quantity = $item_quantity_min;
             }
             // Sold individually?
             $item_sold_individually = get_post_meta($id, '_sold_individually', true);
             if ($item_sold_individually === 'yes' && $item_quantity > 1) {
                 $item_quantity = $item_quantity_min;
             }
             if ($item_quantity < $item_quantity_min && $item_sold_individually !== 'yes') {
                 wc_add_notice(sprintf(__('&quot;%1$s&quot; cannot be added to the cart. The quantity of &quot;%2$s&quot; cannot be lower than %3$d.', 'woocommerce-product-bundles'), get_the_title($product_id), $bundled_item->get_raw_title(), $item_quantity_min), 'error');
                 return false;
             } elseif ($item_quantity > $item_quantity_max) {
                 wc_add_notice(sprintf(__('&quot;%1$s&quot; cannot be added to the cart. The quantity of &quot;%2$s&quot; cannot be higher than %3$d.', 'woocommerce-product-bundles'), get_the_title($product_id), $bundled_item->get_raw_title(), $item_quantity_max), 'error');
                 return false;
             }
             $quantity = $item_quantity * $product_quantity;
             // If quantity is zero, continue
             if ($quantity == 0) {
                 continue;
             }
             // Purchasable
             if (!$bundled_item->is_purchasable()) {
                 wc_add_notice(sprintf(__('&quot;%1$s&quot; cannot be added to the cart because &quot;%2$s&quot; cannot be purchased at the moment.', 'woocommerce-product-bundles'), get_the_title($product_id), $bundled_item->get_raw_title()), 'error');
                 return false;
             }
             // Validate variation id
             if ($bundled_product_type === 'variable') {
                 if (isset($cart_item_data['stamp'][$bundled_item_id]['variation_id']) && $order_again) {
                     $variation_id = $cart_item_data['stamp'][$bundled_item_id]['variation_id'];
                 } elseif (isset($_REQUEST[apply_filters('woocommerce_product_bundle_field_prefix', '', $product_id) . 'bundle_variation_id_' . $bundled_item_id])) {
                     $variation_id = $_REQUEST[apply_filters('woocommerce_product_bundle_field_prefix', '', $product_id) . 'bundle_variation_id_' . $bundled_item_id];
                 }
                 if (isset($variation_id) && is_numeric($variation_id) && $variation_id > 1) {
                     if (get_post_meta($variation_id, '_price', true) === '') {
                         wc_add_notice(sprintf(__('&quot;%1$s&quot; cannot be added to the cart. The selected variation of &quot;%2$s&quot; cannot be purchased.', 'woocommerce-product-bundles'), get_the_title($product_id), $bundled_item->product->get_title()), 'error');
                         return false;
                     }
                     // Add item for validation
                     $bundled_stock->add_item($id, $variation_id, $quantity);
                 } else {
                     wc_add_notice(sprintf(__('&quot;%1$s&quot; cannot be added to the cart. Please choose &quot;%2$s&quot; options&hellip;', 'woocommerce-product-bundles'), get_the_title($product_id), $bundled_item->product->get_title()), 'error');
                     return false;
                 }
                 // Verify all attributes for the variable product were set - TODO: verify with filters
                 $attributes = (array) maybe_unserialize(get_post_meta($id, '_product_attributes', true));
                 $variations = array();
                 $all_set = true;
                 $variation_data = array();
                 $custom_fields = get_post_meta($variation_id);
                 // Get the variation attributes from meta
                 foreach ($custom_fields as $name => $value) {
                     if (!strstr($name, 'attribute_')) {
                         continue;
                     }
                     $variation_data[$name] = sanitize_title($value[0]);
                 }
                 // Verify all attributes
                 foreach ($attributes as $attribute) {
                     if (!$attribute['is_variation']) {
                         continue;
                     }
                     $taxonomy = 'attribute_' . sanitize_title($attribute['name']);
                     if (!empty($_REQUEST[apply_filters('woocommerce_product_bundle_field_prefix', '', $product_id) . 'bundle_' . $taxonomy . '_' . $bundled_item_id])) {
                         // Get value from post data
                         // Don't use woocommerce_clean as it destroys sanitized characters
                         $value = sanitize_title(trim(stripslashes($_REQUEST[apply_filters('woocommerce_product_bundle_field_prefix', '', $product_id) . 'bundle_' . $taxonomy . '_' . $bundled_item_id])));
                         // Get valid value from variation
                         $valid_value = $variation_data[$taxonomy];
                         // Allow if valid
                         if ($valid_value == '' || $valid_value == $value) {
                             continue;
                         }
                     } elseif (isset($cart_item_data['stamp'][$bundled_item_id]['attributes']) && isset($cart_item_data['stamp'][$bundled_item_id]['variation_id']) && $order_again) {
                         $value = sanitize_title(trim(stripslashes($cart_item_data['stamp'][$bundled_item_id]['attributes'][$taxonomy])));
                         $valid_value = $variation_data[$taxonomy];
                         if ($valid_value == '' || $valid_value == $value) {
                             continue;
                         }
                     }
                     $all_set = false;
                 }
                 if (!$all_set) {
                     wc_add_notice(sprintf(__('&quot;%1$s&quot; cannot be added to the cart. Please choose &quot;%2$s&quot; options&hellip;', 'woocommerce-product-bundles'), get_the_title($product_id), $bundled_item->product->get_title()), 'error');
                     return false;
                 }
             } elseif ($bundled_product_type === 'simple' || $bundled_product_type === 'subscription') {
                 // Add item for validation
                 $bundled_stock->add_item($id, false, $quantity);
             }
             if (!apply_filters('woocommerce_bundled_item_add_to_cart_validation', true, $product, $bundled_item, $quantity, $variation_id)) {
                 return false;
             }
         }
         // Check stock for stock-managed bundled items
         // If out of stock, don't proceed
         if (false === apply_filters('woocommerce_add_to_cart_bundle_validation', $bundled_stock->validate_stock($product_id), $product_id, $bundled_stock)) {
             return false;
         }
         // Composite Products compatibility
         $woocommerce_bundles->compatibility->stock_data = $bundled_stock;
     }
     return $add;
 }
 /**
  * Validates add-to-cart for bundles.
  * Basically ensures that stock for all bundled products exists before attempting to add them to cart.
  *
  * @param  boolean  $add                core validation add to cart flag
  * @param  int      $product_id         the product id
  * @param  int      $product_quantity   quantity
  * @param  mixed    $variation_id       variation id
  * @param  array    $variations         variation data
  * @param  array    $cart_item_data     cart item data
  * @return boolean                      modified add to cart validation flag
  */
 public function woo_bundles_validation($add, $product_id, $product_quantity, $variation_id = '', $variations = array(), $cart_item_data = array())
 {
     // Get product type.
     $terms = get_the_terms($product_id, 'product_type');
     $product_type = !empty($terms) && isset(current($terms)->name) ? sanitize_title(current($terms)->name) : 'simple';
     // Ordering again?
     $order_again = isset($_GET['order_again']) && isset($_GET['_wpnonce']) && wp_verify_nonce($_GET['_wpnonce'], 'woocommerce-order_again');
     // prevent bundled items from getting validated - they will be added by the container item.
     if (isset($cart_item_data['is_bundled']) && $order_again) {
         return false;
     }
     if ($product_type === 'bundle') {
         $product = wc_get_product($product_id);
         if (!$product) {
             return false;
         }
         if (!apply_filters('woocommerce_bundle_before_validation', true, $product)) {
             return false;
         }
         // If a stock-managed product / variation exists in the bundle multiple times, its stock will be checked only once for the sum of all bundled quantities.
         // The stock manager class keeps a record of stock-managed product / variation ids.
         $bundled_stock = new WC_PB_Stock_Manager($product);
         // Grab bundled items.
         $bundled_items = $product->get_bundled_items();
         if (!$bundled_items) {
             return $add;
         }
         foreach ($bundled_items as $bundled_item_id => $bundled_item) {
             $id = $bundled_item->product_id;
             $bundled_product_type = $bundled_item->product->product_type;
             // Optional.
             $is_optional = $bundled_item->is_optional();
             if ($is_optional) {
                 if (isset($cart_item_data['stamp'][$bundled_item_id]['optional_selected']) && $order_again) {
                     $is_optional_selected = 'yes' === $cart_item_data['stamp'][$bundled_item_id]['optional_selected'] ? true : false;
                 } elseif (isset($_REQUEST[apply_filters('woocommerce_product_bundle_field_prefix', '', $product_id) . 'bundle_selected_optional_' . $bundled_item_id])) {
                     $is_optional_selected = isset($_REQUEST[apply_filters('woocommerce_product_bundle_field_prefix', '', $product_id) . 'bundle_selected_optional_' . $bundled_item_id]);
                 } else {
                     $is_optional_selected = false;
                 }
             }
             if ($is_optional && !$is_optional_selected) {
                 continue;
             }
             // Check quantity.
             $item_quantity_min = $bundled_item->get_quantity();
             $item_quantity_max = $bundled_item->get_quantity('max');
             if (isset($_REQUEST[apply_filters('woocommerce_product_bundle_field_prefix', '', $product_id) . 'bundle_quantity_' . $bundled_item_id]) && is_numeric($_REQUEST[apply_filters('woocommerce_product_bundle_field_prefix', '', $product_id) . 'bundle_quantity_' . $bundled_item_id])) {
                 $item_quantity = absint($_REQUEST[apply_filters('woocommerce_product_bundle_field_prefix', '', $product_id) . 'bundle_quantity_' . $bundled_item_id]);
             } elseif (isset($cart_item_data['stamp'][$bundled_item_id]['quantity']) && $order_again) {
                 $item_quantity = $cart_item_data['stamp'][$bundled_item_id]['quantity'];
             } else {
                 $item_quantity = $item_quantity_min;
             }
             if ($item_quantity < $item_quantity_min) {
                 wc_add_notice(sprintf(__('&quot;%1$s&quot; cannot be added to the cart. The quantity of &quot;%2$s&quot; cannot be lower than %3$d.', 'woocommerce-product-bundles'), get_the_title($product_id), $bundled_item->get_raw_title(), $item_quantity_min), 'error');
                 return false;
             } elseif ($item_quantity_max && $item_quantity > $item_quantity_max) {
                 wc_add_notice(sprintf(__('&quot;%1$s&quot; cannot be added to the cart. The quantity of &quot;%2$s&quot; cannot be higher than %3$d.', 'woocommerce-product-bundles'), get_the_title($product_id), $bundled_item->get_raw_title(), $item_quantity_max), 'error');
                 return false;
             }
             $quantity = $item_quantity * $product_quantity;
             // If quantity is zero, continue.
             if ($quantity == 0) {
                 continue;
             }
             // Purchasable
             if (!$bundled_item->is_purchasable()) {
                 wc_add_notice(sprintf(__('&quot;%1$s&quot; cannot be added to the cart because &quot;%2$s&quot; cannot be purchased at the moment.', 'woocommerce-product-bundles'), get_the_title($product_id), $bundled_item->get_raw_title()), 'error');
                 return false;
             }
             // Validate variation id.
             if ($bundled_product_type === 'variable' || $bundled_product_type === 'variable-subscription') {
                 $variation_id = '';
                 if (isset($cart_item_data['stamp'][$bundled_item_id]['variation_id']) && $order_again) {
                     $variation_id = $cart_item_data['stamp'][$bundled_item_id]['variation_id'];
                 } elseif (isset($_REQUEST[apply_filters('woocommerce_product_bundle_field_prefix', '', $product_id) . 'bundle_variation_id_' . $bundled_item_id])) {
                     $variation_id = $_REQUEST[apply_filters('woocommerce_product_bundle_field_prefix', '', $product_id) . 'bundle_variation_id_' . $bundled_item_id];
                 }
                 if ($variation_id && is_numeric($variation_id) && $variation_id > 1) {
                     if (get_post_meta($variation_id, '_price', true) === '') {
                         wc_add_notice(sprintf(__('&quot;%1$s&quot; cannot be added to the cart. The selected variation of &quot;%2$s&quot; cannot be purchased.', 'woocommerce-product-bundles'), get_the_title($product_id), $bundled_item->product->get_title()), 'error');
                         return false;
                     }
                     // Add item for validation.
                     $bundled_stock->add_item($id, $variation_id, $quantity);
                 }
                 // Verify all attributes for the variable product were set.
                 $bundled_variation = wc_get_product($variation_id);
                 $attributes = (array) maybe_unserialize(get_post_meta($id, '_product_attributes', true));
                 $variation_data = array();
                 $missing_attributes = array();
                 $all_set = true;
                 if ($bundled_variation) {
                     $variation_data = $bundled_variation->variation_data;
                     // Verify all attributes.
                     foreach ($attributes as $attribute) {
                         if (!$attribute['is_variation']) {
                             continue;
                         }
                         $taxonomy = 'attribute_' . sanitize_title($attribute['name']);
                         if (!empty($_REQUEST[apply_filters('woocommerce_product_bundle_field_prefix', '', $product_id) . 'bundle_' . $taxonomy . '_' . $bundled_item_id])) {
                             if (WC_PB_Core_Compatibility::is_wc_version_gte_2_4()) {
                                 // Get value from post data.
                                 if ($attribute['is_taxonomy']) {
                                     $value = sanitize_title(stripslashes($_REQUEST[apply_filters('woocommerce_product_bundle_field_prefix', '', $product_id) . 'bundle_' . $taxonomy . '_' . $bundled_item_id]));
                                 } else {
                                     $value = wc_clean(stripslashes($_REQUEST[apply_filters('woocommerce_product_bundle_field_prefix', '', $product_id) . 'bundle_' . $taxonomy . '_' . $bundled_item_id]));
                                 }
                             } else {
                                 // Get value from post data.
                                 $value = sanitize_title(trim(stripslashes($_REQUEST[apply_filters('woocommerce_product_bundle_field_prefix', '', $product_id) . 'bundle_' . $taxonomy . '_' . $bundled_item_id])));
                             }
                             // Get valid value from variation.
                             $valid_value = $variation_data[$taxonomy];
                             // Allow if valid
                             if ($valid_value === '' || $valid_value === $value) {
                                 continue;
                             }
                         } elseif (isset($cart_item_data['stamp'][$bundled_item_id]['attributes'][$taxonomy]) && isset($cart_item_data['stamp'][$bundled_item_id]['variation_id']) && $order_again) {
                             if (WC_PB_Core_Compatibility::is_wc_version_gte_2_4()) {
                                 // Get value from post data
                                 if ($attribute['is_taxonomy']) {
                                     $value = sanitize_title(stripslashes($cart_item_data['stamp'][$bundled_item_id]['attributes'][$taxonomy]));
                                 } else {
                                     $value = wc_clean(stripslashes($cart_item_data['stamp'][$bundled_item_id]['attributes'][$taxonomy]));
                                 }
                             } else {
                                 // Get value from post data
                                 $value = sanitize_title(trim(stripslashes($cart_item_data['stamp'][$bundled_item_id]['attributes'][$taxonomy])));
                             }
                             $valid_value = $variation_data[$taxonomy];
                             if ($valid_value === '' || $valid_value === $value) {
                                 continue;
                             }
                         } else {
                             $missing_attributes[] = wc_attribute_label($attribute['name']);
                         }
                         $all_set = false;
                     }
                 } else {
                     $all_set = false;
                 }
                 if (!$all_set) {
                     if ($missing_attributes && WC_PB_Core_Compatibility::is_wc_version_gte_2_3()) {
                         $required_fields_notice = sprintf(_n('%1$s is a required &quot;%2$s&quot; field', '%1$s are required &quot;%2$s&quot; fields', sizeof($missing_attributes), 'woocommerce-product-bundles'), wc_format_list_of_items($missing_attributes), $bundled_item->product->get_title());
                         wc_add_notice(sprintf(__('&quot;%1$s&quot; cannot be added to the cart. %2$s.', 'woocommerce-product-bundles'), get_the_title($product_id), $required_fields_notice), 'error');
                         return false;
                     } else {
                         wc_add_notice(sprintf(__('&quot;%1$s&quot; cannot be added to the cart. Please choose &quot;%2$s&quot; options&hellip;', 'woocommerce-product-bundles'), get_the_title($product_id), $bundled_item->product->get_title()), 'error');
                         return false;
                     }
                 }
             } elseif ($bundled_product_type === 'simple' || $bundled_product_type === 'subscription') {
                 // Add item for validation.
                 $bundled_stock->add_item($id, false, $quantity);
             }
             if (!apply_filters('woocommerce_bundled_item_add_to_cart_validation', true, $product, $bundled_item, $quantity, $variation_id)) {
                 return false;
             }
         }
         // Check stock for stock-managed bundled items.
         // If out of stock, don't proceed.
         if (false === apply_filters('woocommerce_add_to_cart_bundle_validation', $bundled_stock->validate_stock(), $product_id, $bundled_stock)) {
             return false;
         }
         // Composite Products compatibility.
         WC_PB_Compatibility::$stock_data = $bundled_stock;
     }
     return $add;
 }