/**
  * Handle adding variable products to the cart.
  * @since 2.4.6 Split from add_to_cart_action
  * @param int $product_id
  * @return bool success or not
  */
 private static function add_to_cart_handler_variable($product_id)
 {
     $adding_to_cart = wc_get_product($product_id);
     $variation_id = empty($_REQUEST['variation_id']) ? '' : absint($_REQUEST['variation_id']);
     $quantity = empty($_REQUEST['quantity']) ? 1 : wc_stock_amount($_REQUEST['quantity']);
     $missing_attributes = array();
     $variations = array();
     $attributes = $adding_to_cart->get_attributes();
     // If no variation ID is set, attempt to get a variation ID from posted attributes.
     if (empty($variation_id)) {
         $data_store = WC_Data_Store::load('product');
         $variation_id = $data_store->find_matching_product_variation($adding_to_cart, wp_unslash($_POST));
     }
     // Validate the attributes.
     try {
         if (empty($variation_id)) {
             throw new Exception(__('Please choose product options…', 'woocommerce'));
         }
         $variation_data = wc_get_product_variation_attributes($variation_id);
         foreach ($attributes as $attribute) {
             if (!$attribute['is_variation']) {
                 continue;
             }
             $taxonomy = 'attribute_' . sanitize_title($attribute['name']);
             if (isset($_REQUEST[$taxonomy])) {
                 // Get value from post data
                 if ($attribute['is_taxonomy']) {
                     // Don't use wc_clean as it destroys sanitized characters
                     $value = sanitize_title(stripslashes($_REQUEST[$taxonomy]));
                 } else {
                     $value = wc_clean(stripslashes($_REQUEST[$taxonomy]));
                 }
                 // Get valid value from variation
                 $valid_value = isset($variation_data[$taxonomy]) ? $variation_data[$taxonomy] : '';
                 // Allow if valid or show error.
                 if ('' === $valid_value || $valid_value === $value) {
                     $variations[$taxonomy] = $value;
                 } else {
                     throw new Exception(sprintf(__('Invalid value posted for %s', 'woocommerce'), wc_attribute_label($attribute['name'])));
                 }
             } else {
                 $missing_attributes[] = wc_attribute_label($attribute['name']);
             }
         }
         if (!empty($missing_attributes)) {
             throw new Exception(sprintf(_n('%s is a required field', '%s are required fields', sizeof($missing_attributes), 'woocommerce'), wc_format_list_of_items($missing_attributes)));
         }
     } catch (Exception $e) {
         wc_add_notice($e->getMessage(), 'error');
         return false;
     }
     // Add to cart validation
     $passed_validation = apply_filters('woocommerce_add_to_cart_validation', true, $product_id, $quantity, $variation_id, $variations);
     if ($passed_validation && WC()->cart->add_to_cart($product_id, $quantity, $variation_id, $variations) !== false) {
         wc_add_to_cart_message(array($product_id => $quantity), true);
         return true;
     }
     return false;
 }
 /**
  * Get method returns variation meta data if set, otherwise in most cases the data from the parent.
  *
  * @param string $key
  * @return mixed
  */
 public function __get($key)
 {
     if (in_array($key, array_keys($this->variation_level_meta_data))) {
         $value = get_post_meta($this->variation_id, '_' . $key, true);
         if ('' === $value) {
             $value = $this->variation_level_meta_data[$key];
         }
     } elseif (in_array($key, array_keys($this->variation_inherited_meta_data))) {
         $value = metadata_exists('post', $this->variation_id, '_' . $key) ? get_post_meta($this->variation_id, '_' . $key, true) : get_post_meta($this->id, '_' . $key, true);
         // Handle meta data keys which can be empty at variation level to cause inheritance
         if ('' === $value && in_array($key, array('sku', 'weight', 'length', 'width', 'height'))) {
             $value = get_post_meta($this->id, '_' . $key, true);
         }
         if ('' === $value) {
             $value = $this->variation_inherited_meta_data[$key];
         }
     } elseif ('variation_data' === $key) {
         return $this->variation_data = wc_get_product_variation_attributes($this->variation_id);
     } elseif ('variation_has_stock' === $key) {
         return $this->managing_stock();
     } else {
         $value = metadata_exists('post', $this->variation_id, '_' . $key) ? get_post_meta($this->variation_id, '_' . $key, true) : parent::__get($key);
     }
     return $value;
 }
 /**
  * Reads a product from the database and sets its data to the class.
  *
  * @since 2.7.0
  * @param WC_Product
  */
 public function read(&$product)
 {
     $product->set_defaults();
     if (!$product->get_id() || !($post_object = get_post($product->get_id()))) {
         return;
     }
     $id = $product->get_id();
     $product->set_parent_id($post_object->post_parent);
     $parent_id = $product->get_parent_id();
     // The post doesn't have a parent id, therefore its invalid and we should prevent this being created.
     if (empty($parent_id)) {
         throw new Exception(sprintf('No parent product set for variation #%d', $product->get_id()), 422);
     }
     // The post parent is not a valid variable product so we should prevent this being created.
     if ('product' !== get_post_type($product->get_parent_id())) {
         throw new Exception(sprintf('Invalid parent for variation #%d', $product->get_id()), 422);
     }
     $product->set_props(array('name' => get_the_title($post_object), 'slug' => $post_object->post_name, 'date_created' => $post_object->post_date, 'date_modified' => $post_object->post_modified, 'status' => $post_object->post_status, 'menu_order' => $post_object->menu_order, 'reviews_allowed' => 'open' === $post_object->comment_status));
     $this->read_product_data($product);
     $product->set_attributes(wc_get_product_variation_attributes($product->get_id()));
     // Set object_read true once all data is read.
     $product->set_object_read(true);
 }
Пример #4
0
 /**
  * Load variations via AJAX.
  */
 public static function load_variations()
 {
     ob_start();
     check_ajax_referer('load-variations', 'security');
     // Check permissions again and make sure we have what we need
     if (!current_user_can('edit_products') || empty($_POST['product_id']) || empty($_POST['attributes'])) {
         die(-1);
     }
     global $post;
     $product_id = absint($_POST['product_id']);
     $post = get_post($product_id);
     // Set $post global so its available like within the admin screens
     $per_page = !empty($_POST['per_page']) ? absint($_POST['per_page']) : 10;
     $page = !empty($_POST['page']) ? absint($_POST['page']) : 1;
     // Get attributes
     $attributes = array();
     $posted_attributes = wp_unslash($_POST['attributes']);
     foreach ($posted_attributes as $key => $value) {
         $attributes[$key] = array_map('wc_clean', $value);
     }
     // Get tax classes
     $tax_classes = WC_Tax::get_tax_classes();
     $tax_class_options = array();
     $tax_class_options[''] = __('Standard', 'woocommerce');
     if (!empty($tax_classes)) {
         foreach ($tax_classes as $class) {
             $tax_class_options[sanitize_title($class)] = esc_attr($class);
         }
     }
     // Set backorder options
     $backorder_options = array('no' => __('Do not allow', 'woocommerce'), 'notify' => __('Allow, but notify customer', 'woocommerce'), 'yes' => __('Allow', 'woocommerce'));
     // set stock status options
     $stock_status_options = array('instock' => __('In stock', 'woocommerce'), 'outofstock' => __('Out of stock', 'woocommerce'));
     $parent_data = array('id' => $product_id, 'attributes' => $attributes, 'tax_class_options' => $tax_class_options, 'sku' => get_post_meta($product_id, '_sku', true), 'weight' => wc_format_localized_decimal(get_post_meta($product_id, '_weight', true)), 'length' => wc_format_localized_decimal(get_post_meta($product_id, '_length', true)), 'width' => wc_format_localized_decimal(get_post_meta($product_id, '_width', true)), 'height' => wc_format_localized_decimal(get_post_meta($product_id, '_height', true)), 'tax_class' => get_post_meta($product_id, '_tax_class', true), 'backorder_options' => $backorder_options, 'stock_status_options' => $stock_status_options);
     if (!$parent_data['weight']) {
         $parent_data['weight'] = wc_format_localized_decimal(0);
     }
     if (!$parent_data['length']) {
         $parent_data['length'] = wc_format_localized_decimal(0);
     }
     if (!$parent_data['width']) {
         $parent_data['width'] = wc_format_localized_decimal(0);
     }
     if (!$parent_data['height']) {
         $parent_data['height'] = wc_format_localized_decimal(0);
     }
     // Get variations
     $args = apply_filters('woocommerce_ajax_admin_get_variations_args', array('post_type' => 'product_variation', 'post_status' => array('private', 'publish'), 'posts_per_page' => $per_page, 'paged' => $page, 'orderby' => array('menu_order' => 'ASC', 'ID' => 'DESC'), 'post_parent' => $product_id), $product_id);
     $variations = get_posts($args);
     $loop = 0;
     if ($variations) {
         foreach ($variations as $variation) {
             $variation_id = absint($variation->ID);
             $variation_meta = get_post_meta($variation_id);
             $variation_data = array();
             $shipping_classes = get_the_terms($variation_id, 'product_shipping_class');
             $variation_fields = array('_sku' => '', '_stock' => '', '_regular_price' => '', '_sale_price' => '', '_weight' => '', '_length' => '', '_width' => '', '_height' => '', '_download_limit' => '', '_download_expiry' => '', '_downloadable_files' => '', '_downloadable' => '', '_virtual' => '', '_thumbnail_id' => '', '_sale_price_dates_from' => '', '_sale_price_dates_to' => '', '_manage_stock' => '', '_stock_status' => '', '_backorders' => null, '_tax_class' => null, '_variation_description' => '');
             foreach ($variation_fields as $field => $value) {
                 $variation_data[$field] = isset($variation_meta[$field][0]) ? maybe_unserialize($variation_meta[$field][0]) : $value;
             }
             // Add the variation attributes
             $variation_data = array_merge($variation_data, wc_get_product_variation_attributes($variation_id));
             // Formatting
             $variation_data['_regular_price'] = wc_format_localized_price($variation_data['_regular_price']);
             $variation_data['_sale_price'] = wc_format_localized_price($variation_data['_sale_price']);
             $variation_data['_weight'] = wc_format_localized_decimal($variation_data['_weight']);
             $variation_data['_length'] = wc_format_localized_decimal($variation_data['_length']);
             $variation_data['_width'] = wc_format_localized_decimal($variation_data['_width']);
             $variation_data['_height'] = wc_format_localized_decimal($variation_data['_height']);
             $variation_data['_thumbnail_id'] = absint($variation_data['_thumbnail_id']);
             $variation_data['image'] = $variation_data['_thumbnail_id'] ? wp_get_attachment_thumb_url($variation_data['_thumbnail_id']) : '';
             $variation_data['shipping_class'] = $shipping_classes && !is_wp_error($shipping_classes) ? current($shipping_classes)->term_id : '';
             $variation_data['menu_order'] = $variation->menu_order;
             $variation_data['_stock'] = wc_stock_amount($variation_data['_stock']);
             include 'admin/meta-boxes/views/html-variation-admin.php';
             $loop++;
         }
     }
     die;
 }
 /**
  * Magic __get method for backwards compatibility. Maps legacy vars to new getters.
  *
  * @param  string $key Key name.
  * @return mixed
  */
 public function __get($key)
 {
     if ('post_type' === $key) {
         return $this->post_type;
     }
     wc_doing_it_wrong($key, __('Product properties should not be accessed directly.', 'woocommerce'), '2.7');
     switch ($key) {
         case 'id':
             $value = $this->is_type('variation') ? $this->get_parent_id() : $this->get_id();
             break;
         case 'variation_id':
             $value = $this->get_id();
             break;
         case 'product_attributes':
             $value = isset($this->data['attributes']) ? $this->data['attributes'] : '';
             break;
         case 'visibility':
             $value = $this->get_catalog_visibility();
             break;
         case 'sale_price_dates_from':
             $value = $this->get_date_on_sale_from();
             break;
         case 'sale_price_dates_to':
             $value = $this->get_date_on_sale_to();
             break;
         case 'post':
             $value = get_post($this->get_id());
             break;
         case 'download_type':
             return 'standard';
             break;
         case 'product_image_gallery':
             $value = $this->get_gallery_image_ids();
             break;
         case 'variation_shipping_class':
         case 'shipping_class':
             $value = $this->get_shipping_class();
             break;
         case 'total_stock':
             $value = $this->get_total_stock();
             break;
         case 'downloadable':
         case 'virtual':
         case 'manage_stock':
         case 'featured':
         case 'sold_individually':
             $value = $this->{"get_{$key}"}() ? 'yes' : 'no';
             break;
         case 'crosssell_ids':
             $value = $this->get_cross_sell_ids();
             break;
         case 'upsell_ids':
             $value = $this->get_upsell_ids();
             break;
         case 'parent':
             $value = wc_get_product($this->get_parent_id());
             break;
         case 'variation_data':
             $value = wc_get_product_variation_attributes($this->get_id());
             break;
         case 'variation_has_stock':
             $value = $this->managing_stock();
             break;
         case 'variation_shipping_class_id':
             $value = $this->get_shipping_class_id();
             break;
         default:
             if (in_array($key, array_keys($this->data))) {
                 $value = $this->{"get_{$key}"}();
             } else {
                 $value = get_post_meta($this->id, '_' . $key, true);
             }
             break;
     }
     return $value;
 }
Пример #6
0
 /**
  * Load variations via AJAX.
  */
 public static function load_variations()
 {
     ob_start();
     check_ajax_referer('load-variations', 'security');
     if (!current_user_can('edit_products') || empty($_POST['product_id'])) {
         die(-1);
     }
     // Set $post global so its available, like within the admin screens
     global $post;
     $loop = 0;
     $product_id = absint($_POST['product_id']);
     $post = get_post($product_id);
     $product_object = wc_get_product($product_id);
     $per_page = !empty($_POST['per_page']) ? absint($_POST['per_page']) : 10;
     $page = !empty($_POST['page']) ? absint($_POST['page']) : 1;
     $variations = wc_get_products(array('status' => array('private', 'publish'), 'type' => 'variation', 'parent' => $product_id, 'limit' => $per_page, 'page' => $page, 'orderby' => array('menu_order' => 'ASC', 'ID' => 'DESC'), 'return' => 'objects'));
     if ($variations) {
         foreach ($variations as $variation_object) {
             $variation_id = $variation_object->get_id();
             $variation = get_post($variation_id);
             $variation_data = array_merge(array_map('maybe_unserialize', get_post_custom($variation_id)), wc_get_product_variation_attributes($variation_id));
             // kept for BW compat.
             include 'admin/meta-boxes/views/html-variation-admin.php';
             $loop++;
         }
     }
     die;
 }
 /**
  * @param $product
  * @param array $item_data
  * @return array
  */
 private function get_item_datas($product, $item_data = array())
 {
     $attrs = $product->get_attributes();
     $variations = array();
     if (!empty($product->variation_id)) {
         $variations = wc_get_product_variation_attributes($product->variation_id);
     }
     if (count($attrs)) {
         foreach ($attrs as $name => $attribute) {
             $label = wc_attribute_label($attribute['name']);
             if (count($variations)) {
                 $term = get_term_by('slug', $variations['attribute_' . $name], $name);
                 $item_data[] = array('key' => $label, 'label' => $label, 'value' => wpautop(wptexturize($term->name)));
             } else {
                 $values = wc_get_product_terms($product->id, $attribute['name']);
                 $item_data[] = array('key' => $label, 'label' => $label, 'value' => wpautop(wptexturize(implode(', ', $values))));
             }
         }
     }
     return $item_data;
 }
 /**
  * Generate YML body with offers.
  *
  * @since     0.3.0
  * @param     $currency
  * @param     $query
  *
  * @return    string
  */
 private function yml_offers($currency, $query)
 {
     $yml = '';
     while ($query->have_posts()) {
         $query->the_post();
         $product = wc_get_product($query->post->ID);
         // We use a seperate variable for offer because we will be rewriting it for variable products.
         $offer = $product;
         /*
          * By default we set $variation_count to 1.
          * That means that there is at least one product available.
          * Variation products will have more than 1 count.
          */
         $variation_count = 1;
         if ($product->is_type('variable')) {
             $variation_count = count($offer->get_children());
             $variations = $product->get_available_variations();
         }
         while ($variation_count > 0) {
             $variation_count--;
             // If variable product, get product id from $variations array.
             $offerID = $product->is_type('variable') ? $variations[$variation_count]['variation_id'] : $product->id;
             // Prepare variation link.
             $var_link = '';
             if ($product->is_type('variable')) {
                 $variable_attribute = wc_get_product_variation_attributes($offerID);
                 $var_link = '?' . key($variable_attribute) . '=' . current($variable_attribute);
                 // This has to work but we need to think of a way to save the initial offer variable.
                 $offer = new WC_Product_Variation($offerID);
             }
             // NOTE: Below this point we start using $offer instead of $product.
             $yml .= '      <offer id="' . $offerID . '" available="' . ($offer->is_in_stock() ? "true" : "false") . '">' . PHP_EOL;
             $yml .= '        <url>' . get_permalink($offer->id) . $var_link . '</url>' . PHP_EOL;
             // Price.
             if ($offer->sale_price && $offer->sale_price < $offer->regular_price) {
                 $yml .= '        <price>' . $offer->sale_price . '</price>' . PHP_EOL;
                 $yml .= '        <oldprice>' . $offer->regular_price . '</oldprice>' . PHP_EOL;
             } else {
                 $yml .= '        <price>' . $offer->regular_price . '</price>' . PHP_EOL;
             }
             $yml .= '        <currencyId>' . $currency . '</currencyId>' . PHP_EOL;
             // Category.
             // Not using $offerID, because variable products inherit category from parent.
             $categories = get_the_terms($product->id, 'product_cat');
             $category = array_shift($categories);
             $yml .= '        <categoryId>' . $category->term_id . '</categoryId>' . PHP_EOL;
             // Market category.
             if (isset($this->settings['market_category']) && $this->settings['market_category'] != 'not_set') {
                 $market_category = wc_get_product_terms($offerID, 'pa_' . $this->settings['market_category'], array('fields' => 'names'));
                 if ($market_category) {
                     $yml .= '        <market_category>' . wp_strip_all_tags(array_shift($market_category)) . '</market_category>' . PHP_EOL;
                 }
             }
             // TODO: get all the images
             $image = get_the_post_thumbnail_url(null, 'full');
             //foreach ( $images as $image ):
             if (strlen(utf8_decode($image)) <= 512) {
                 $yml .= '        <picture>' . esc_url($image) . '</picture>' . PHP_EOL;
             }
             //endforeach;
             $yml .= '        <delivery>true</delivery>' . PHP_EOL;
             $yml .= '        <name>' . $offer->get_title() . '</name>' . PHP_EOL;
             // Vendor.
             if (isset($this->settings['vendor']) && $this->settings['vendor'] != 'not_set') {
                 $vendor = wc_get_product_terms($offer->ID, 'pa_' . $this->settings['vendor'], array('fields' => 'names'));
                 if ($vendor) {
                     $yml .= '        <vendor>' . wp_strip_all_tags(array_shift($vendor)) . '</vendor>' . PHP_EOL;
                 }
             }
             // Vendor code.
             if ($offer->sku) {
                 $yml .= '        <vendorCode>' . $offer->sku . '</vendorCode>' . PHP_EOL;
             }
             // Description.
             if ($offer->post->post_content) {
                 $yml .= '        <description><![CDATA[' . html_entity_decode($offer->post->post_content, ENT_COMPAT, "UTF-8") . ']]></description>' . PHP_EOL;
             }
             // Sales notes.
             if ($this->settings['sales_notes'] == 'yes' && $offer->post->post_excerpt) {
                 $yml .= '        <sales_notes>' . wp_strip_all_tags($offer->post->post_excerpt) . '</sales_notes>' . PHP_EOL;
             }
             $yml .= '      </offer>' . PHP_EOL;
         }
     }
     return $yml;
 }
 /**
  * Update bundle post_meta on save.
  *
  * @return 	mixed     bundle data array configuration or false if unsuccessful
  */
 public function build_bundle_config($post_id, $posted_bundle_data)
 {
     // Process Bundled Product Configuration.
     $bundle_data = array();
     $ordered_bundle_data = array();
     $bundle_data_old = get_post_meta($post_id, '_bundle_data', true);
     $bundled_subs = 0;
     // Now start saving new data.
     $times = array();
     $save_defaults = array();
     $ordering = array();
     if (!empty($posted_bundle_data)) {
         foreach ($posted_bundle_data as $val => $data) {
             $id = isset($data['product_id']) ? $data['product_id'] : false;
             if (!$id) {
                 continue;
             }
             $terms = get_the_terms($id, 'product_type');
             $product_type = !empty($terms) && isset(current($terms)->name) ? sanitize_title(current($terms)->name) : 'simple';
             $is_sub = class_exists('WC_Subscriptions') && WC_PB()->compatibility->is_subscription($id);
             if ($id && $id > 0 && ($product_type === 'simple' || $product_type === 'variable' || $is_sub) && $post_id != $id) {
                 // Only allow saving 1 sub.
                 if ($is_sub) {
                     if ($bundled_subs > 0 && version_compare(WC_Subscriptions::$version, '2.0.0', '<')) {
                         $this->add_admin_error(sprintf(__('&quot;%1$s&quot; (#%2$s) was not saved. Only one simple Subscription per Bundle is supported.', 'woocommerce-product-bundles'), get_the_title($id), $id));
                         continue;
                     } else {
                         $bundled_subs++;
                     }
                 }
                 // Allow bundling the same item id multiple times by adding a suffix.
                 if (!isset($times[$id])) {
                     $times[$id] = 1;
                     $val = $id;
                 } else {
                     // Only allow multiple instances of non-sold-individually items.
                     if (get_post_meta($id, '_sold_individually', true) == 'yes') {
                         $this->add_admin_error(sprintf(__('&quot;%1$s&quot; (#%2$s) is sold individually and cannot be bundled more than once.', 'woocommerce-product-bundles'), get_the_title($id), $id));
                         continue;
                     }
                     $times[$id] += 1;
                     $val = isset($data['item_id']) ? $data['item_id'] : $id . '_' . $times[$id];
                 }
                 $bundle_data[$val] = array();
                 $bundle_data[$val]['product_id'] = $id;
                 // Save thumbnail preferences first.
                 if (isset($data['hide_thumbnail'])) {
                     $bundle_data[$val]['hide_thumbnail'] = 'yes';
                 } else {
                     $bundle_data[$val]['hide_thumbnail'] = 'no';
                 }
                 // Save title preferences.
                 if (isset($data['override_title'])) {
                     $bundle_data[$val]['override_title'] = 'yes';
                     $bundle_data[$val]['product_title'] = isset($data['product_title']) ? $data['product_title'] : '';
                 } else {
                     $bundle_data[$val]['override_title'] = 'no';
                 }
                 // Save description preferences.
                 if (isset($data['override_description'])) {
                     $bundle_data[$val]['override_description'] = 'yes';
                     $bundle_data[$val]['product_description'] = isset($data['product_description']) ? wp_kses_post(stripslashes($data['product_description'])) : '';
                 } else {
                     $bundle_data[$val]['override_description'] = 'no';
                 }
                 // Save optional.
                 if (isset($data['optional'])) {
                     $bundle_data[$val]['optional'] = 'yes';
                 } else {
                     $bundle_data[$val]['optional'] = 'no';
                 }
                 // Save quantity data.
                 if (isset($data['bundle_quantity'])) {
                     if (is_numeric($data['bundle_quantity'])) {
                         $quantity = absint($data['bundle_quantity']);
                         if ($quantity >= 0 && $data['bundle_quantity'] - $quantity == 0) {
                             if ($quantity !== 1 && get_post_meta($id, '_sold_individually', true) === 'yes') {
                                 $this->add_admin_error(sprintf(__('&quot;%1$s&quot; (#%2$s) is sold individually and cannot be bundled with a minimum quantity higher than 1.', 'woocommerce-product-bundles'), get_the_title($id), $id));
                                 $bundle_data[$val]['bundle_quantity'] = 1;
                             } else {
                                 $bundle_data[$val]['bundle_quantity'] = $quantity;
                             }
                         } else {
                             $this->add_admin_error(sprintf(__('The quantity you entered for &quot;%1$s%2$s&quot; (#%3$s) was not valid and has been reset. Please enter a non-negative integer value.', 'woocommerce-product-bundles'), get_the_title($id), $id != $val ? ' #' . $times[$id] : '', $id));
                         }
                     }
                 } else {
                     $bundle_data[$val]['bundle_quantity'] = 1;
                 }
                 $quantity_min = $bundle_data[$val]['bundle_quantity'];
                 // Save max quantity data.
                 if (isset($data['bundle_quantity_max']) && (is_numeric($data['bundle_quantity_max']) || $data['bundle_quantity_max'] === '')) {
                     $quantity = $data['bundle_quantity_max'] !== '' ? absint($data['bundle_quantity_max']) : '';
                     if ($quantity === '' || $quantity > 0 && $quantity >= $quantity_min && $data['bundle_quantity_max'] - $quantity == 0) {
                         if ($quantity !== 1 && get_post_meta($id, '_sold_individually', true) === 'yes') {
                             $this->add_admin_error(sprintf(__('&quot;%1$s&quot; (#%2$s) is sold individually and cannot be bundled with a maximum quantity higher than 1.', 'woocommerce-product-bundles'), get_the_title($id), $id));
                             $bundle_data[$val]['bundle_quantity_max'] = 1;
                         } else {
                             $bundle_data[$val]['bundle_quantity_max'] = $quantity;
                         }
                     } else {
                         $this->add_admin_error(sprintf(__('The maximum product quantity that you entered for &quot;%1$s%2$s&quot; (#%3$s) was not valid and has been reset. Please enter a positive integer value, at least as high as the minimum quantity. Otherwise, leave the field empty for an unlimited maximum quantity.', 'woocommerce-product-bundles'), get_the_title($id), $id != $val ? ' #' . $times[$id] : '', $id));
                     }
                 } else {
                     $bundle_data[$val]['bundle_quantity_max'] = max($quantity_min, 1);
                 }
                 // Save sale price data.
                 if (isset($data['bundle_discount'])) {
                     if (is_numeric($data['bundle_discount'])) {
                         $discount = (double) wc_format_decimal($data['bundle_discount']);
                         if ($discount < 0 || $discount > 100) {
                             $this->add_admin_error(sprintf(__('The discount value you entered for &quot;%1$s%2$s&quot; (#%3$s) was not valid and has been reset. Please enter a positive number between 0-100.', 'woocommerce-product-bundles'), get_the_title($id), $id != $val ? ' #' . $times[$id] : '', $id));
                             $bundle_data[$val]['bundle_discount'] = '';
                         } else {
                             $bundle_data[$val]['bundle_discount'] = $discount;
                         }
                     } else {
                         $bundle_data[$val]['bundle_discount'] = '';
                     }
                 } else {
                     $bundle_data[$val]['bundle_discount'] = '';
                 }
                 // Save data related to variable items.
                 if ($product_type === 'variable') {
                     // Save variation filtering options.
                     if (isset($data['filter_variations'])) {
                         if (isset($data['allowed_variations']) && count($data['allowed_variations']) > 0) {
                             $bundle_data[$val]['filter_variations'] = 'yes';
                             $bundle_data[$val]['allowed_variations'] = $data['allowed_variations'];
                             if (isset($data['hide_filtered_variations'])) {
                                 $bundle_data[$val]['hide_filtered_variations'] = 'yes';
                             } else {
                                 $bundle_data[$val]['hide_filtered_variations'] = 'no';
                             }
                         } else {
                             $bundle_data[$val]['filter_variations'] = 'no';
                             $this->add_admin_error(__('Please select at least one variation for each bundled product you want to filter.', 'woocommerce-product-bundles'));
                         }
                     } else {
                         $bundle_data[$val]['filter_variations'] = 'no';
                     }
                     // Save defaults options.
                     if (isset($data['override_defaults'])) {
                         if (isset($data['default_attributes'])) {
                             // if filters are set, check that the selections are valid.
                             if (isset($data['filter_variations']) && !empty($data['allowed_variations'])) {
                                 $allowed_variations = $data['allowed_variations'];
                                 // the array to store all valid attribute options of the iterated product.
                                 $filtered_attributes = array();
                                 // populate array with valid attributes.
                                 foreach ($allowed_variations as $variation) {
                                     $variation_data = array();
                                     // sweep the post meta for attributes.
                                     if (WC_PB_Core_Compatibility::is_wc_version_gte_2_4()) {
                                         $variation_data = wc_get_product_variation_attributes($variation);
                                     } else {
                                         $post_meta = get_post_meta($variation);
                                         foreach ($post_meta as $field => $value) {
                                             if (!strstr($field, 'attribute_')) {
                                                 continue;
                                             }
                                             $variation_data[$field] = $value[0];
                                         }
                                     }
                                     foreach ($variation_data as $name => $value) {
                                         $attribute_name = substr($name, strlen('attribute_'));
                                         $attribute_value = sanitize_title($value);
                                         // Populate array.
                                         if (!isset($filtered_attributes[sanitize_title($attribute_name)])) {
                                             $filtered_attributes[sanitize_title($attribute_name)][] = $attribute_value;
                                         } elseif (!in_array($attribute_value, $filtered_attributes[sanitize_title($attribute_name)])) {
                                             $filtered_attributes[sanitize_title($attribute_name)][] = $attribute_value;
                                         }
                                     }
                                 }
                                 // Check validity.
                                 foreach ($data['default_attributes'] as $sanitized_name => $value) {
                                     if ($value === '') {
                                         continue;
                                     }
                                     if (!in_array(sanitize_title($value), $filtered_attributes[$sanitized_name]) && !in_array('', $filtered_attributes[$sanitized_name])) {
                                         // Set option to "Any".
                                         $data['default_attributes'][$sanitized_name] = '';
                                         // Throw an error.
                                         $this->add_admin_error(sprintf(__('The defaults that you selected for &quot;%1$s%2$s&quot; (#%3$s) are inconsistent with the set of active variations. Always double-check your preferences before saving, and always save any changes made to the variation filters before choosing new defaults.', 'woocommerce-product-bundles'), get_the_title($id), $id != $val ? ' #' . $times[$id] : '', $id));
                                         continue;
                                     }
                                 }
                             }
                             // Save.
                             foreach ($data['default_attributes'] as $sanitized_name => $value) {
                                 $bundle_data[$val]['bundle_defaults'][$sanitized_name] = $value;
                             }
                             $bundle_data[$val]['override_defaults'] = 'yes';
                         }
                     } else {
                         $bundle_data[$val]['override_defaults'] = 'no';
                     }
                 }
                 // Save visibility preferences.
                 $visibility = array('product' => 'visible', 'cart' => 'visible', 'order' => 'visible');
                 $visibility['product'] = isset($data['visibility']['product']) ? 'visible' : 'hidden';
                 $visibility['cart'] = isset($data['visibility']['cart']) ? 'visible' : 'hidden';
                 $visibility['order'] = isset($data['visibility']['order']) ? 'visible' : 'hidden';
                 if ($visibility['product'] === 'hidden') {
                     if ($product_type === 'variable') {
                         if ($bundle_data[$val]['override_defaults'] === 'yes') {
                             if (isset($data['default_attributes'])) {
                                 foreach ($data['default_attributes'] as $default_name => $default_value) {
                                     if (!$default_value) {
                                         $visibility['product'] = 'visible';
                                         $this->add_admin_error(sprintf(__('&quot;%1$s%2$s&quot; (#%s) cannot be hidden from the single-product template unless all default options of the bundled product are defined.', 'woocommerce-product-bundles'), get_the_title($id), $id != $val ? ' #' . $times[$id] : '', $id));
                                         break;
                                     }
                                 }
                             } else {
                                 $visibility['product'] = 'visible';
                             }
                         } else {
                             $this->add_admin_error(sprintf(__('&quot;%1$s%2$s&quot; (#%3$s) cannot be hidden from the single-product template unless all default options of the bundled product are defined.', 'woocommerce-product-bundles'), get_the_title($id), $id != $val ? ' #' . $times[$id] : '', $id));
                             $visibility['product'] = 'visible';
                         }
                     }
                 }
                 $bundle_data[$val]['visibility'] = $visibility;
                 // Save position data.
                 if (isset($data['bundle_order'])) {
                     $ordering[(int) $data['bundle_order']] = $val;
                 } else {
                     $ordering[count($ordering)] = $val;
                 }
                 $bundle_data[$val] = apply_filters('woocommerce_bundles_process_bundled_item_admin_data', $bundle_data[$val], $data, $val, $post_id);
             }
         }
         // Check empty.
         if (empty($bundle_data)) {
             return false;
         }
         // Sorting
         ksort($ordering);
         $ordered_bundle_data = array();
         foreach ($ordering as $item_id) {
             $ordered_bundle_data[$item_id] = $bundle_data[$item_id];
         }
         return $ordered_bundle_data;
     } else {
         return false;
     }
 }