Example #1
0
 /**
  * Bulk action - Set Price
  * @access private
  * @param  array $variations
  * @param string $operator + or -
  * @param string $field price being adjusted
  * @param string $value Price or Percent
  */
 private static function variation_bulk_adjust_price($variations, $field, $operator, $value)
 {
     foreach ($variations as $variation_id) {
         // Get existing data
         $_regular_price = get_post_meta($variation_id, '_regular_price', true);
         $_sale_price = get_post_meta($variation_id, '_sale_price', true);
         $date_from = get_post_meta($variation_id, '_sale_price_dates_from', true);
         $date_to = get_post_meta($variation_id, '_sale_price_dates_to', true);
         $date_from = !empty($date_from) ? date('Y-m-d', $date_from) : '';
         $date_to = !empty($date_to) ? date('Y-m-d', $date_to) : '';
         if ('%' === substr($value, -1)) {
             $percent = wc_format_decimal(substr($value, 0, -1));
             ${$field} += ${$field} / 100 * $percent * "{$operator}1";
         } else {
             ${$field} += $value * "{$operator}1";
         }
         _wc_save_product_price($variation_id, $_regular_price, $_sale_price, $date_from, $date_to);
     }
 }
 /**
  * Save variations
  *
  * @since  2.2
  * @param  int $id
  * @param  array $data
  * @return bool
  * @throws WC_API_Exception
  */
 protected function save_variations($id, $data)
 {
     global $wpdb;
     $variations = $data['variations'];
     $attributes = (array) maybe_unserialize(get_post_meta($id, '_product_attributes', true));
     foreach ($variations as $menu_order => $variation) {
         $variation_id = isset($variation['id']) ? absint($variation['id']) : 0;
         if (!$variation_id && isset($variation['sku'])) {
             $variation_sku = wc_clean($variation['sku']);
             $variation_id = wc_get_product_id_by_sku($variation_sku);
         }
         // Generate a useful post title
         $variation_post_title = sprintf(__('Variation #%1$s of %2$s', 'woocommerce'), $variation_id, esc_html(get_the_title($id)));
         // Update or Add post
         if (!$variation_id) {
             $post_status = isset($variation['visible']) && false === $variation['visible'] ? 'private' : 'publish';
             $new_variation = array('post_title' => $variation_post_title, 'post_content' => '', 'post_status' => $post_status, 'post_author' => get_current_user_id(), 'post_parent' => $id, 'post_type' => 'product_variation', 'menu_order' => $menu_order);
             $variation_id = wp_insert_post($new_variation);
             do_action('woocommerce_create_product_variation', $variation_id);
         } else {
             $update_variation = array('post_title' => $variation_post_title, 'menu_order' => $menu_order);
             if (isset($variation['visible'])) {
                 $post_status = false === $variation['visible'] ? 'private' : 'publish';
                 $update_variation['post_status'] = $post_status;
             }
             $wpdb->update($wpdb->posts, $update_variation, array('ID' => $variation_id));
             do_action('woocommerce_update_product_variation', $variation_id);
         }
         // Stop with we don't have a variation ID
         if (is_wp_error($variation_id)) {
             throw new WC_API_Exception('woocommerce_api_cannot_save_product_variation', $variation_id->get_error_message(), 400);
         }
         // SKU
         if (isset($variation['sku'])) {
             $sku = get_post_meta($variation_id, '_sku', true);
             $new_sku = wc_clean($variation['sku']);
             if ('' == $new_sku) {
                 update_post_meta($variation_id, '_sku', '');
             } elseif ($new_sku !== $sku) {
                 if (!empty($new_sku)) {
                     $unique_sku = wc_product_has_unique_sku($variation_id, $new_sku);
                     if (!$unique_sku) {
                         throw new WC_API_Exception('woocommerce_api_product_sku_already_exists', __('The SKU already exists on another product.', 'woocommerce'), 400);
                     } else {
                         update_post_meta($variation_id, '_sku', $new_sku);
                     }
                 } else {
                     update_post_meta($variation_id, '_sku', '');
                 }
             }
         }
         // Thumbnail.
         if (isset($variation['image']) && is_array($variation['image'])) {
             $image = current($variation['image']);
             if ($image && is_array($image)) {
                 if (isset($image['position']) && 0 == $image['position']) {
                     if (isset($image['src'])) {
                         $upload = $this->upload_product_image(wc_clean($image['src']));
                         if (is_wp_error($upload)) {
                             throw new WC_API_Exception('woocommerce_api_cannot_upload_product_image', $upload->get_error_message(), 400);
                         }
                         $attachment_id = $this->set_product_image_as_attachment($upload, $id);
                     } else {
                         if (isset($image['id'])) {
                             $attachment_id = $image['id'];
                         }
                     }
                     // Set the image alt if present.
                     if (!empty($image['alt'])) {
                         update_post_meta($attachment_id, '_wp_attachment_image_alt', wc_clean($image['alt']));
                     }
                     // Set the image title if present.
                     if (!empty($image['title'])) {
                         wp_update_post(array('ID' => $attachment_id, 'post_title' => $image['title']));
                     }
                     update_post_meta($variation_id, '_thumbnail_id', $attachment_id);
                 }
             } else {
                 delete_post_meta($variation_id, '_thumbnail_id');
             }
         }
         // Virtual variation
         if (isset($variation['virtual'])) {
             $is_virtual = true === $variation['virtual'] ? 'yes' : 'no';
             update_post_meta($variation_id, '_virtual', $is_virtual);
         }
         // Downloadable variation
         if (isset($variation['downloadable'])) {
             $is_downloadable = true === $variation['downloadable'] ? 'yes' : 'no';
             update_post_meta($variation_id, '_downloadable', $is_downloadable);
         } else {
             $is_downloadable = get_post_meta($variation_id, '_downloadable', true);
         }
         // Shipping data
         $this->save_product_shipping_data($variation_id, $variation);
         // Stock handling
         if (isset($variation['managing_stock'])) {
             $managing_stock = true === $variation['managing_stock'] ? 'yes' : 'no';
         } else {
             $managing_stock = get_post_meta($variation_id, '_manage_stock', true);
         }
         update_post_meta($variation_id, '_manage_stock', '' === $managing_stock ? 'no' : $managing_stock);
         if (isset($variation['in_stock'])) {
             $stock_status = true === $variation['in_stock'] ? 'instock' : 'outofstock';
         } else {
             $stock_status = get_post_meta($variation_id, '_stock_status', true);
         }
         wc_update_product_stock_status($variation_id, '' === $stock_status ? 'instock' : $stock_status);
         if ('yes' === $managing_stock) {
             $backorders = get_post_meta($variation_id, '_backorders', true);
             if (isset($variation['backorders'])) {
                 if ('notify' === $variation['backorders']) {
                     $backorders = 'notify';
                 } else {
                     $backorders = true === $variation['backorders'] ? 'yes' : 'no';
                 }
             }
             update_post_meta($variation_id, '_backorders', '' === $backorders ? 'no' : $backorders);
             if (isset($variation['stock_quantity'])) {
                 wc_update_product_stock($variation_id, wc_stock_amount($variation['stock_quantity']));
             } else {
                 if (isset($data['inventory_delta'])) {
                     $stock_quantity = wc_stock_amount(get_post_meta($variation_id, '_stock', true));
                     $stock_quantity += wc_stock_amount($data['inventory_delta']);
                     wc_update_product_stock($variation_id, wc_stock_amount($stock_quantity));
                 }
             }
         } else {
             delete_post_meta($variation_id, '_backorders');
             delete_post_meta($variation_id, '_stock');
         }
         // Regular Price
         if (isset($variation['regular_price'])) {
             $regular_price = '' === $variation['regular_price'] ? '' : $variation['regular_price'];
         } else {
             $regular_price = get_post_meta($variation_id, '_regular_price', true);
         }
         // Sale Price
         if (isset($variation['sale_price'])) {
             $sale_price = '' === $variation['sale_price'] ? '' : $variation['sale_price'];
         } else {
             $sale_price = get_post_meta($variation_id, '_sale_price', true);
         }
         if (isset($variation['sale_price_dates_from'])) {
             $date_from = $variation['sale_price_dates_from'];
         } else {
             $date_from = get_post_meta($variation_id, '_sale_price_dates_from', true);
             $date_from = '' === $date_from ? '' : date('Y-m-d', $date_from);
         }
         if (isset($variation['sale_price_dates_to'])) {
             $date_to = $variation['sale_price_dates_to'];
         } else {
             $date_to = get_post_meta($variation_id, '_sale_price_dates_to', true);
             $date_to = '' === $date_to ? '' : date('Y-m-d', $date_to);
         }
         _wc_save_product_price($variation_id, $regular_price, $sale_price, $date_from, $date_to);
         // Tax class
         if (isset($variation['tax_class'])) {
             if ('parent' !== $variation['tax_class']) {
                 update_post_meta($variation_id, '_tax_class', wc_clean($variation['tax_class']));
             } else {
                 delete_post_meta($variation_id, '_tax_class');
             }
         }
         // Downloads
         if ('yes' == $is_downloadable) {
             // Downloadable files
             if (isset($variation['downloads']) && is_array($variation['downloads'])) {
                 $this->save_downloadable_files($id, $variation['downloads'], $variation_id);
             }
             // Download limit
             if (isset($variation['download_limit'])) {
                 $download_limit = absint($variation['download_limit']);
                 update_post_meta($variation_id, '_download_limit', !$download_limit ? '' : $download_limit);
             }
             // Download expiry
             if (isset($variation['download_expiry'])) {
                 $download_expiry = absint($variation['download_expiry']);
                 update_post_meta($variation_id, '_download_expiry', !$download_expiry ? '' : $download_expiry);
             }
         } else {
             update_post_meta($variation_id, '_download_limit', '');
             update_post_meta($variation_id, '_download_expiry', '');
             update_post_meta($variation_id, '_downloadable_files', '');
         }
         // Description.
         if (isset($variation['description'])) {
             update_post_meta($variation_id, '_variation_description', wp_kses_post($variation['description']));
         }
         // Update taxonomies
         if (isset($variation['attributes'])) {
             $updated_attribute_keys = array();
             foreach ($variation['attributes'] as $attribute_key => $attribute) {
                 if (!isset($attribute['name'])) {
                     continue;
                 }
                 $taxonomy = 0;
                 $_attribute = array();
                 if (isset($attribute['slug'])) {
                     $taxonomy = $this->get_attribute_taxonomy_by_slug($attribute['slug']);
                 }
                 if (!$taxonomy) {
                     $taxonomy = sanitize_title($attribute['name']);
                 }
                 if (isset($attributes[$taxonomy])) {
                     $_attribute = $attributes[$taxonomy];
                 }
                 if (isset($_attribute['is_variation']) && $_attribute['is_variation']) {
                     $_attribute_key = 'attribute_' . sanitize_title($_attribute['name']);
                     $updated_attribute_keys[] = $_attribute_key;
                     if (isset($_attribute['is_taxonomy']) && $_attribute['is_taxonomy']) {
                         // Don't use wc_clean as it destroys sanitized characters
                         $_attribute_value = isset($attribute['option']) ? sanitize_title(stripslashes($attribute['option'])) : '';
                     } else {
                         $_attribute_value = isset($attribute['option']) ? wc_clean(stripslashes($attribute['option'])) : '';
                     }
                     update_post_meta($variation_id, $_attribute_key, $_attribute_value);
                 }
             }
             // Remove old taxonomies attributes so data is kept up to date - first get attribute key names
             $delete_attribute_keys = $wpdb->get_col($wpdb->prepare("SELECT meta_key FROM {$wpdb->postmeta} WHERE meta_key LIKE 'attribute_%%' AND meta_key NOT IN ( '" . implode("','", $updated_attribute_keys) . "' ) AND post_id = %d;", $variation_id));
             foreach ($delete_attribute_keys as $key) {
                 delete_post_meta($variation_id, $key);
             }
         }
         do_action('woocommerce_api_save_product_variation', $variation_id, $menu_order, $variation);
     }
     // Update parent if variable so price sorting works and stays in sync with the cheapest child
     WC_Product_Variable::sync($id);
     // Update default attributes options setting
     if (isset($data['default_attribute'])) {
         $data['default_attributes'] = $data['default_attribute'];
     }
     if (isset($data['default_attributes']) && is_array($data['default_attributes'])) {
         $default_attributes = array();
         foreach ($data['default_attributes'] as $default_attr_key => $default_attr) {
             if (!isset($default_attr['name'])) {
                 continue;
             }
             $taxonomy = sanitize_title($default_attr['name']);
             if (isset($default_attr['slug'])) {
                 $taxonomy = $this->get_attribute_taxonomy_by_slug($default_attr['slug']);
             }
             if (isset($attributes[$taxonomy])) {
                 $_attribute = $attributes[$taxonomy];
                 if ($_attribute['is_variation']) {
                     $value = '';
                     if (isset($default_attr['option'])) {
                         if ($_attribute['is_taxonomy']) {
                             // Don't use wc_clean as it destroys sanitized characters
                             $value = sanitize_title(trim(stripslashes($default_attr['option'])));
                         } else {
                             $value = wc_clean(trim(stripslashes($default_attr['option'])));
                         }
                     }
                     if ($value) {
                         $default_attributes[$taxonomy] = $value;
                     }
                 }
             }
         }
         update_post_meta($id, '_default_attributes', $default_attributes);
     }
     return true;
 }
 /**
  * Save variations.
  *
  * @param WC_Product $product
  * @param WP_REST_Request $request
  * @return bool
  * @throws WC_REST_Exception
  */
 protected function save_variations_data($product, $request, $single_variation = false)
 {
     global $wpdb;
     if ($single_variation) {
         $variations = array($request);
     } else {
         $variations = $request['variations'];
     }
     $attributes = $product->get_attributes();
     foreach ($variations as $menu_order => $variation) {
         $variation_id = isset($variation['id']) ? absint($variation['id']) : 0;
         // Generate a useful post title.
         $variation_post_title = sprintf(__('Variation #%1$s of %2$s', 'woocommerce'), $variation_id, esc_html(get_the_title($product->id)));
         // Update or Add post.
         if (!$variation_id) {
             $post_status = isset($variation['visible']) && false === $variation['visible'] ? 'private' : 'publish';
             $new_variation = array('post_title' => $variation_post_title, 'post_content' => '', 'post_status' => $post_status, 'post_author' => get_current_user_id(), 'post_parent' => $product->id, 'post_type' => 'product_variation', 'menu_order' => $menu_order);
             $variation_id = wp_insert_post($new_variation);
             do_action('woocommerce_create_product_variation', $variation_id);
         } else {
             $update_variation = array('post_title' => $variation_post_title, 'menu_order' => $menu_order);
             if (isset($variation['visible'])) {
                 $post_status = false === $variation['visible'] ? 'private' : 'publish';
                 $update_variation['post_status'] = $post_status;
             }
             $wpdb->update($wpdb->posts, $update_variation, array('ID' => $variation_id));
             do_action('woocommerce_update_product_variation', $variation_id);
         }
         // Stop with we don't have a variation ID.
         if (is_wp_error($variation_id)) {
             throw new WC_REST_Exception('woocommerce_rest_cannot_save_product_variation', $variation_id->get_error_message(), 400);
         }
         // SKU.
         if (isset($variation['sku'])) {
             $sku = get_post_meta($variation_id, '_sku', true);
             $new_sku = wc_clean($variation['sku']);
             if ('' === $new_sku) {
                 update_post_meta($variation_id, '_sku', '');
             } elseif ($new_sku !== $sku) {
                 if (!empty($new_sku)) {
                     $unique_sku = wc_product_has_unique_sku($variation_id, $new_sku);
                     if (!$unique_sku) {
                         throw new WC_REST_Exception('woocommerce_rest_product_sku_already_exists', __('The SKU already exists on another product.', 'woocommerce'), 400);
                     } else {
                         update_post_meta($variation_id, '_sku', $new_sku);
                     }
                 } else {
                     update_post_meta($variation_id, '_sku', '');
                 }
             }
         }
         // Thumbnail.
         if (isset($variation['image']) && is_array($variation['image'])) {
             $image = $variation['image'];
             $image = current($image);
             if ($image && is_array($image)) {
                 if (isset($image['position']) && 0 === $image['position']) {
                     $attachment_id = isset($image['id']) ? absint($image['id']) : 0;
                     $skip_image = false;
                     if (0 === $attachment_id && isset($image['src'])) {
                         $upload = wc_rest_upload_image_from_url(wc_clean($image['src']));
                         if (is_wp_error($upload)) {
                             if (!apply_filters('woocommerce_rest_suppress_variation_image_upload_error', false, $upload, $product)) {
                                 throw new WC_REST_Exception('woocommerce_product_image_upload_error', $upload->get_error_message(), 400);
                             } else {
                                 $skip_image = true;
                             }
                         } else {
                             $attachment_id = wc_rest_set_uploaded_image_as_attachment($upload, $product->id);
                         }
                     }
                     if (!$skip_image) {
                         // Set the image alt if present.
                         if (!empty($image['alt'])) {
                             update_post_meta($attachment_id, '_wp_attachment_image_alt', wc_clean($image['alt']));
                         }
                         // Set the image name if present.
                         if (!empty($image['name'])) {
                             wp_update_post(array('ID' => $attachment_id, 'post_title' => $image['name']));
                         }
                         update_post_meta($variation_id, '_thumbnail_id', $attachment_id);
                     }
                 }
             } else {
                 delete_post_meta($variation_id, '_thumbnail_id');
             }
         }
         // Virtual variation.
         if (isset($variation['virtual'])) {
             $is_virtual = true === $variation['virtual'] ? 'yes' : 'no';
             update_post_meta($variation_id, '_virtual', $is_virtual);
         }
         // Downloadable variation.
         if (isset($variation['downloadable'])) {
             $is_downloadable = true === $variation['downloadable'] ? 'yes' : 'no';
             update_post_meta($variation_id, '_downloadable', $is_downloadable);
         } else {
             $is_downloadable = get_post_meta($variation_id, '_downloadable', true);
         }
         // Shipping data.
         $this->save_product_shipping_data($variation_id, $variation);
         // Stock handling.
         if (isset($variation['manage_stock'])) {
             $manage_stock = true === $variation['manage_stock'] ? 'yes' : 'no';
         } else {
             $manage_stock = get_post_meta($variation_id, '_manage_stock', true);
         }
         update_post_meta($variation_id, '_manage_stock', '' === $manage_stock ? 'no' : $manage_stock);
         if (isset($variation['in_stock'])) {
             $stock_status = true === $variation['in_stock'] ? 'instock' : 'outofstock';
         } else {
             $stock_status = get_post_meta($variation_id, '_stock_status', true);
         }
         wc_update_product_stock_status($variation_id, '' === $stock_status ? 'instock' : $stock_status);
         if ('yes' === $manage_stock) {
             $backorders = get_post_meta($variation_id, '_backorders', true);
             if (isset($variation['backorders'])) {
                 $backorders = $variation['backorders'];
             }
             update_post_meta($variation_id, '_backorders', '' === $backorders ? 'no' : $backorders);
             if (isset($variation['stock_quantity'])) {
                 wc_update_product_stock($variation_id, wc_stock_amount($variation['stock_quantity']));
             } elseif (isset($request['inventory_delta'])) {
                 $stock_quantity = wc_stock_amount(get_post_meta($variation_id, '_stock', true));
                 $stock_quantity += wc_stock_amount($request['inventory_delta']);
                 wc_update_product_stock($variation_id, wc_stock_amount($stock_quantity));
             }
         } else {
             delete_post_meta($variation_id, '_backorders');
             wc_update_product_stock($variation_id, '');
         }
         // Regular Price.
         if (isset($variation['regular_price'])) {
             $regular_price = '' === $variation['regular_price'] ? '' : $variation['regular_price'];
         } else {
             $regular_price = get_post_meta($variation_id, '_regular_price', true);
         }
         // Sale Price.
         if (isset($variation['sale_price'])) {
             $sale_price = '' === $variation['sale_price'] ? '' : $variation['sale_price'];
         } else {
             $sale_price = get_post_meta($variation_id, '_sale_price', true);
         }
         if (isset($variation['date_on_sale_from'])) {
             $date_from = $variation['date_on_sale_from'];
         } else {
             $date_from = get_post_meta($variation_id, '_sale_price_dates_from', true);
             $date_from = '' === $date_from ? '' : date('Y-m-d', $date_from);
         }
         if (isset($variation['date_on_sale_to'])) {
             $date_to = $variation['date_on_sale_to'];
         } else {
             $date_to = get_post_meta($variation_id, '_sale_price_dates_to', true);
             $date_to = '' === $date_to ? '' : date('Y-m-d', $date_to);
         }
         _wc_save_product_price($variation_id, $regular_price, $sale_price, $date_from, $date_to);
         // Tax class.
         if (isset($variation['tax_class'])) {
             if ('parent' !== $variation['tax_class']) {
                 update_post_meta($variation_id, '_tax_class', wc_clean($variation['tax_class']));
             } else {
                 delete_post_meta($variation_id, '_tax_class');
             }
         }
         // Downloads.
         if ('yes' === $is_downloadable) {
             // Downloadable files.
             if (isset($variation['downloads']) && is_array($variation['downloads'])) {
                 $this->save_downloadable_files($product->id, $variation['downloads'], $variation_id);
             }
             // Download limit.
             if (isset($variation['download_limit'])) {
                 update_post_meta($variation_id, '_download_limit', -1 === $variation['download_limit'] ? '' : absint($variation['download_limit']));
             }
             // Download expiry.
             if (isset($variation['download_expiry'])) {
                 update_post_meta($variation_id, '_download_expiry', -1 === $variation['download_expiry'] ? '' : absint($variation['download_expiry']));
             }
         } else {
             update_post_meta($variation_id, '_download_limit', '');
             update_post_meta($variation_id, '_download_expiry', '');
             update_post_meta($variation_id, '_downloadable_files', '');
         }
         // Description.
         if (isset($variation['description'])) {
             update_post_meta($variation_id, '_variation_description', wp_kses_post($variation['description']));
         }
         // Update taxonomies.
         if (isset($variation['attributes'])) {
             $updated_attribute_keys = array();
             foreach ($variation['attributes'] as $attribute) {
                 $attribute_id = 0;
                 $attribute_name = '';
                 // Check ID for global attributes or name for product attributes.
                 if (!empty($attribute['id'])) {
                     $attribute_id = absint($attribute['id']);
                     $attribute_name = wc_attribute_taxonomy_name_by_id($attribute_id);
                 } elseif (!empty($attribute['name'])) {
                     $attribute_name = sanitize_title($attribute['name']);
                 }
                 if (!$attribute_id && !$attribute_name) {
                     continue;
                 }
                 if (isset($attributes[$attribute_name])) {
                     $_attribute = $attributes[$attribute_name];
                 }
                 if (isset($_attribute['is_variation']) && $_attribute['is_variation']) {
                     $_attribute_key = 'attribute_' . sanitize_title($_attribute['name']);
                     $updated_attribute_keys[] = $_attribute_key;
                     $attribute_value = isset($attribute['option']) ? wc_clean(stripslashes($attribute['option'])) : '';
                     if (!empty($_attribute['is_taxonomy'])) {
                         // If dealing with a taxonomy, we need to get the slug from the name posted to the API.
                         $term = get_term_by('name', $attribute_value, $attribute_name);
                         if ($term && !is_wp_error($term)) {
                             $attribute_value = $term->slug;
                         } else {
                             $attribute_value = sanitize_title($attribute_value);
                         }
                     }
                     update_post_meta($variation_id, $_attribute_key, $attribute_value);
                 }
             }
             // Remove old taxonomies attributes so data is kept up to date - first get attribute key names.
             $delete_attribute_keys = $wpdb->get_col($wpdb->prepare("SELECT meta_key FROM {$wpdb->postmeta} WHERE meta_key LIKE 'attribute_%%' AND meta_key NOT IN ( '" . implode("','", $updated_attribute_keys) . "' ) AND post_id = %d;", $variation_id));
             foreach ($delete_attribute_keys as $key) {
                 delete_post_meta($variation_id, $key);
             }
         }
         do_action('woocommerce_rest_save_product_variation', $variation_id, $menu_order, $variation);
     }
     // Update parent if variable so price sorting works and stays in sync with the cheapest child.
     WC_Product_Variable::sync($product->id);
     // Update default attributes options setting.
     if (isset($request['default_attribute'])) {
         $request['default_attributes'] = $request['default_attribute'];
     }
     if (isset($request['default_attributes']) && is_array($request['default_attributes'])) {
         $default_attributes = array();
         foreach ($request['default_attributes'] as $attribute) {
             $attribute_id = 0;
             $attribute_name = '';
             // Check ID for global attributes or name for product attributes.
             if (!empty($attribute['id'])) {
                 $attribute_id = absint($attribute['id']);
                 $attribute_name = wc_attribute_taxonomy_name_by_id($attribute_id);
             } elseif (!empty($attribute['name'])) {
                 $attribute_name = sanitize_title($attribute['name']);
             }
             if (!$attribute_id && !$attribute_name) {
                 continue;
             }
             if (isset($attributes[$attribute_name])) {
                 $_attribute = $attributes[$attribute_name];
                 if ($_attribute['is_variation']) {
                     $value = isset($attribute['option']) ? wc_clean(stripslashes($attribute['option'])) : '';
                     if (!empty($_attribute['is_taxonomy'])) {
                         // If dealing with a taxonomy, we need to get the slug from the name posted to the API.
                         $term = get_term_by('name', $attribute_value, $attribute_name);
                         if ($term && !is_wp_error($term)) {
                             $value = $term->slug;
                         } else {
                             $value = sanitize_title($attribute_value);
                         }
                     }
                     if ($value) {
                         $default_attributes[$attribute_name] = $value;
                     }
                 }
             }
         }
         update_post_meta($product->id, '_default_attributes', $default_attributes);
     }
     return true;
 }
/**
 *
 *
 */
function wsm_save_price($product_id, $regular_price, $sale_price = null)
{
    //$sale_price =  get_post_meta( $product_id, '_sale_price', true );
    $date_from = get_post_meta($product_id, '_sale_price_dates_from', true);
    $date_from = '' === $date_from ? '' : date('Y-m-d', $date_from);
    $date_to = get_post_meta($product_id, '_sale_price_dates_to', true);
    $date_to = '' === $date_to ? '' : date('Y-m-d', $date_to);
    if ($sale_price === null) {
        $sale_price = get_post_meta($product_id, '_sale_price', true);
    }
    _wc_save_product_price($product_id, $regular_price, $sale_price, $date_from, $date_to);
}
 /**
  * Save meta box data.
  *
  * @param int $post_id
  * @param WP_Post $post
  */
 public static function save_variations($post_id, $post)
 {
     global $wpdb;
     $attributes = (array) maybe_unserialize(get_post_meta($post_id, '_product_attributes', true));
     if (isset($_POST['variable_sku'])) {
         $variable_post_id = $_POST['variable_post_id'];
         $variable_sku = $_POST['variable_sku'];
         $variable_regular_price = $_POST['variable_regular_price'];
         $variable_sale_price = $_POST['variable_sale_price'];
         $upload_image_id = $_POST['upload_image_id'];
         $variable_download_limit = $_POST['variable_download_limit'];
         $variable_download_expiry = $_POST['variable_download_expiry'];
         $variable_shipping_class = $_POST['variable_shipping_class'];
         $variable_tax_class = isset($_POST['variable_tax_class']) ? $_POST['variable_tax_class'] : array();
         $variable_menu_order = $_POST['variation_menu_order'];
         $variable_sale_price_dates_from = $_POST['variable_sale_price_dates_from'];
         $variable_sale_price_dates_to = $_POST['variable_sale_price_dates_to'];
         $variable_weight = isset($_POST['variable_weight']) ? $_POST['variable_weight'] : array();
         $variable_length = isset($_POST['variable_length']) ? $_POST['variable_length'] : array();
         $variable_width = isset($_POST['variable_width']) ? $_POST['variable_width'] : array();
         $variable_height = isset($_POST['variable_height']) ? $_POST['variable_height'] : array();
         $variable_enabled = isset($_POST['variable_enabled']) ? $_POST['variable_enabled'] : array();
         $variable_is_virtual = isset($_POST['variable_is_virtual']) ? $_POST['variable_is_virtual'] : array();
         $variable_is_downloadable = isset($_POST['variable_is_downloadable']) ? $_POST['variable_is_downloadable'] : array();
         $variable_manage_stock = isset($_POST['variable_manage_stock']) ? $_POST['variable_manage_stock'] : array();
         $variable_stock = isset($_POST['variable_stock']) ? $_POST['variable_stock'] : array();
         $variable_backorders = isset($_POST['variable_backorders']) ? $_POST['variable_backorders'] : array();
         $variable_stock_status = isset($_POST['variable_stock_status']) ? $_POST['variable_stock_status'] : array();
         $variable_description = isset($_POST['variable_description']) ? $_POST['variable_description'] : array();
         $max_loop = max(array_keys($_POST['variable_post_id']));
         for ($i = 0; $i <= $max_loop; $i++) {
             if (!isset($variable_post_id[$i])) {
                 continue;
             }
             $variation_id = absint($variable_post_id[$i]);
             // Checkboxes
             $is_virtual = isset($variable_is_virtual[$i]) ? 'yes' : 'no';
             $is_downloadable = isset($variable_is_downloadable[$i]) ? 'yes' : 'no';
             $post_status = isset($variable_enabled[$i]) ? 'publish' : 'private';
             $manage_stock = isset($variable_manage_stock[$i]) ? 'yes' : 'no';
             // Generate a useful post title
             $variation_post_title = sprintf(__('Variation #%1$s of %2$s', 'woocommerce'), absint($variation_id), esc_html(get_the_title($post_id)));
             // Update or Add post
             if (!$variation_id) {
                 $variation = array('post_title' => $variation_post_title, 'post_content' => '', 'post_status' => $post_status, 'post_author' => get_current_user_id(), 'post_parent' => $post_id, 'post_type' => 'product_variation', 'menu_order' => $variable_menu_order[$i]);
                 $variation_id = wp_insert_post($variation);
                 do_action('woocommerce_create_product_variation', $variation_id);
             } else {
                 $modified_date = date_i18n('Y-m-d H:i:s', current_time('timestamp'));
                 $wpdb->update($wpdb->posts, array('post_status' => $post_status, 'post_title' => $variation_post_title, 'menu_order' => $variable_menu_order[$i], 'post_modified' => $modified_date, 'post_modified_gmt' => get_gmt_from_date($modified_date)), array('ID' => $variation_id));
                 clean_post_cache($variation_id);
                 do_action('woocommerce_update_product_variation', $variation_id);
             }
             // Only continue if we have a variation ID
             if (!$variation_id) {
                 continue;
             }
             // Unique SKU
             $sku = get_post_meta($variation_id, '_sku', true);
             $new_sku = wc_clean($variable_sku[$i]);
             if ('' == $new_sku) {
                 update_post_meta($variation_id, '_sku', '');
             } elseif ($new_sku !== $sku) {
                 if (!empty($new_sku)) {
                     $unique_sku = wc_product_has_unique_sku($variation_id, $new_sku);
                     if (!$unique_sku) {
                         WC_Admin_Meta_Boxes::add_error(sprintf(__('#%s &ndash; Variation SKU must be unique.', 'woocommerce'), $variation_id));
                     } else {
                         update_post_meta($variation_id, '_sku', $new_sku);
                     }
                 } else {
                     update_post_meta($variation_id, '_sku', '');
                 }
             }
             // Update post meta
             update_post_meta($variation_id, '_thumbnail_id', absint($upload_image_id[$i]));
             update_post_meta($variation_id, '_virtual', wc_clean($is_virtual));
             update_post_meta($variation_id, '_downloadable', wc_clean($is_downloadable));
             if (isset($variable_weight[$i])) {
                 update_post_meta($variation_id, '_weight', '' === $variable_weight[$i] ? '' : wc_format_decimal($variable_weight[$i]));
             }
             if (isset($variable_length[$i])) {
                 update_post_meta($variation_id, '_length', '' === $variable_length[$i] ? '' : wc_format_decimal($variable_length[$i]));
             }
             if (isset($variable_width[$i])) {
                 update_post_meta($variation_id, '_width', '' === $variable_width[$i] ? '' : wc_format_decimal($variable_width[$i]));
             }
             if (isset($variable_height[$i])) {
                 update_post_meta($variation_id, '_height', '' === $variable_height[$i] ? '' : wc_format_decimal($variable_height[$i]));
             }
             // Stock handling
             update_post_meta($variation_id, '_manage_stock', $manage_stock);
             if ('yes' === $manage_stock) {
                 update_post_meta($variation_id, '_backorders', wc_clean($variable_backorders[$i]));
                 wc_update_product_stock($variation_id, wc_stock_amount($variable_stock[$i]));
             } else {
                 delete_post_meta($variation_id, '_backorders');
                 delete_post_meta($variation_id, '_stock');
             }
             // Only update stock status to user setting if changed by the user, but do so before looking at stock levels at variation level
             if (!empty($variable_stock_status[$i])) {
                 wc_update_product_stock_status($variation_id, $variable_stock_status[$i]);
             }
             // Price handling
             _wc_save_product_price($variation_id, $variable_regular_price[$i], $variable_sale_price[$i], $variable_sale_price_dates_from[$i], $variable_sale_price_dates_to[$i]);
             if (isset($variable_tax_class[$i]) && $variable_tax_class[$i] !== 'parent') {
                 update_post_meta($variation_id, '_tax_class', wc_clean($variable_tax_class[$i]));
             } else {
                 delete_post_meta($variation_id, '_tax_class');
             }
             if ('yes' == $is_downloadable) {
                 update_post_meta($variation_id, '_download_limit', wc_clean($variable_download_limit[$i]));
                 update_post_meta($variation_id, '_download_expiry', wc_clean($variable_download_expiry[$i]));
                 $files = array();
                 $file_names = isset($_POST['_wc_variation_file_names'][$variation_id]) ? array_map('wc_clean', $_POST['_wc_variation_file_names'][$variation_id]) : array();
                 $file_urls = isset($_POST['_wc_variation_file_urls'][$variation_id]) ? array_map('wc_clean', $_POST['_wc_variation_file_urls'][$variation_id]) : array();
                 $file_url_size = sizeof($file_urls);
                 $allowed_file_types = get_allowed_mime_types();
                 for ($ii = 0; $ii < $file_url_size; $ii++) {
                     if (!empty($file_urls[$ii])) {
                         // Find type and file URL
                         if (0 === strpos($file_urls[$ii], 'http')) {
                             $file_is = 'absolute';
                             $file_url = esc_url_raw($file_urls[$ii]);
                         } elseif ('[' === substr($file_urls[$ii], 0, 1) && ']' === substr($file_urls[$ii], -1)) {
                             $file_is = 'shortcode';
                             $file_url = wc_clean($file_urls[$ii]);
                         } else {
                             $file_is = 'relative';
                             $file_url = wc_clean($file_urls[$ii]);
                         }
                         $file_name = wc_clean($file_names[$ii]);
                         $file_hash = md5($file_url);
                         // Validate the file extension
                         if (in_array($file_is, array('absolute', 'relative'))) {
                             $file_type = wp_check_filetype(strtok($file_url, '?'), $allowed_file_types);
                             $parsed_url = parse_url($file_url, PHP_URL_PATH);
                             $extension = pathinfo($parsed_url, PATHINFO_EXTENSION);
                             if (!empty($extension) && !in_array($file_type['type'], $allowed_file_types)) {
                                 WC_Admin_Meta_Boxes::add_error(sprintf(__('#%1$s &ndash; The downloadable file %2$s cannot be used as it does not have an allowed file type. Allowed types include: %3$s', 'woocommerce'), $variation_id, '<code>' . basename($file_url) . '</code>', '<code>' . implode(', ', array_keys($allowed_file_types)) . '</code>'));
                                 continue;
                             }
                         }
                         // Validate the file exists
                         if ('relative' === $file_is && !apply_filters('woocommerce_downloadable_file_exists', file_exists($file_url), $file_url)) {
                             WC_Admin_Meta_Boxes::add_error(sprintf(__('#%1$s &ndash; The downloadable file %2$s cannot be used as it does not exist on the server.', 'woocommerce'), $variation_id, '<code>' . $file_url . '</code>'));
                             continue;
                         }
                         $files[$file_hash] = array('name' => $file_name, 'file' => $file_url);
                     }
                 }
                 // grant permission to any newly added files on any existing orders for this product prior to saving
                 do_action('woocommerce_process_product_file_download_paths', $post_id, $variation_id, $files);
                 update_post_meta($variation_id, '_downloadable_files', $files);
             } else {
                 update_post_meta($variation_id, '_download_limit', '');
                 update_post_meta($variation_id, '_download_expiry', '');
                 update_post_meta($variation_id, '_downloadable_files', '');
             }
             update_post_meta($variation_id, '_variation_description', wp_kses_post($variable_description[$i]));
             // Save shipping class
             $variable_shipping_class[$i] = !empty($variable_shipping_class[$i]) ? (int) $variable_shipping_class[$i] : '';
             wp_set_object_terms($variation_id, $variable_shipping_class[$i], 'product_shipping_class');
             // Update Attributes
             $updated_attribute_keys = array();
             foreach ($attributes as $attribute) {
                 if ($attribute['is_variation']) {
                     $attribute_key = 'attribute_' . sanitize_title($attribute['name']);
                     $updated_attribute_keys[] = $attribute_key;
                     if ($attribute['is_taxonomy']) {
                         // Don't use wc_clean as it destroys sanitized characters
                         $value = isset($_POST[$attribute_key][$i]) ? sanitize_title(stripslashes($_POST[$attribute_key][$i])) : '';
                     } else {
                         $value = isset($_POST[$attribute_key][$i]) ? wc_clean(stripslashes($_POST[$attribute_key][$i])) : '';
                     }
                     update_post_meta($variation_id, $attribute_key, $value);
                 }
             }
             // Remove old taxonomies attributes so data is kept up to date - first get attribute key names
             $delete_attribute_keys = $wpdb->get_col($wpdb->prepare("SELECT meta_key FROM {$wpdb->postmeta} WHERE meta_key LIKE 'attribute_%%' AND meta_key NOT IN ( '" . implode("','", $updated_attribute_keys) . "' ) AND post_id = %d;", $variation_id));
             foreach ($delete_attribute_keys as $key) {
                 delete_post_meta($variation_id, $key);
             }
             do_action('woocommerce_save_product_variation', $variation_id, $i);
         }
     }
     // Update parent if variable so price sorting works and stays in sync with the cheapest child
     WC_Product_Variable::sync($post_id);
     // Update default attribute options setting
     $default_attributes = array();
     foreach ($attributes as $attribute) {
         if ($attribute['is_variation']) {
             $value = '';
             if (isset($_POST['default_attribute_' . sanitize_title($attribute['name'])])) {
                 if ($attribute['is_taxonomy']) {
                     // Don't use wc_clean as it destroys sanitized characters
                     $value = sanitize_title(trim(stripslashes($_POST['default_attribute_' . sanitize_title($attribute['name'])])));
                 } else {
                     $value = wc_clean(trim(stripslashes($_POST['default_attribute_' . sanitize_title($attribute['name'])])));
                 }
             }
             if ($value) {
                 $default_attributes[sanitize_title($attribute['name'])] = $value;
             }
         }
     }
     update_post_meta($post_id, '_default_attributes', $default_attributes);
 }
Example #6
0
 /**
  * Bulk edit variations via AJAX
  */
 public static function bulk_edit_variations()
 {
     ob_start();
     check_ajax_referer('bulk-edit-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['bulk_action'])) {
         die(-1);
     }
     global $wpdb;
     $product_id = absint($_POST['product_id']);
     $bulk_action = wc_clean($_POST['bulk_action']);
     $data = !empty($_POST['data']) ? array_map('wc_clean', $_POST['data']) : array();
     $variations = array();
     if (apply_filters('woocommerce_bulk_edit_variations_need_children', !in_array($bulk_action, array('variable_weight', 'variable_length', 'variable_width', 'variable_height')))) {
         $variations = get_posts(array('post_parent' => $product_id, 'posts_per_page' => -1, 'post_type' => 'product_variation', 'fields' => 'ids', 'post_status' => array('publish', 'private')));
     }
     switch ($bulk_action) {
         case 'toggle_enabled':
             foreach ($variations as $variation_id) {
                 $post_status = get_post_status($variation_id);
                 $new_status = 'private' === $post_status ? 'publish' : 'private';
                 $wpdb->update($wpdb->posts, array('post_status' => $new_status), array('ID' => $variation_id));
             }
             break;
         case 'toggle_downloadable':
             foreach ($variations as $variation_id) {
                 $_downloadable = get_post_meta($variation_id, '_downloadable', true);
                 $is_downloadable = 'no' === $_downloadable ? 'yes' : 'no';
                 update_post_meta($variation_id, '_downloadable', wc_clean($is_downloadable));
             }
             break;
         case 'toggle_virtual':
             foreach ($variations as $variation_id) {
                 $_virtual = get_post_meta($variation_id, '_virtual', true);
                 $is_virtual = 'no' === $_virtual ? 'yes' : 'no';
                 update_post_meta($variation_id, '_virtual', wc_clean($is_virtual));
             }
             break;
         case 'toggle_manage_stock':
             foreach ($variations as $variation_id) {
                 $_manage_stock = get_post_meta($variation_id, '_manage_stock', true);
                 $is_manage_stock = 'no' === $_manage_stock ? 'yes' : 'no';
                 update_post_meta($variation_id, '_manage_stock', wc_clean($is_manage_stock));
             }
             break;
         case 'variable_regular_price':
         case 'variable_sale_price':
             if (empty($data['value'])) {
                 break;
             }
             $field = str_replace('variable', '', $bulk_action);
             foreach ($variations as $variation_id) {
                 // Price fields
                 $regular_price = '_regular_price' === $field ? $data['value'] : get_post_meta($variation_id, '_regular_price', true);
                 $sale_price = '_sale_price' === $field ? $data['value'] : get_post_meta($variation_id, '_sale_price', true);
                 // Date fields
                 $date_from = get_post_meta($variation_id, '_sale_price_dates_from', true);
                 $date_to = get_post_meta($variation_id, '_sale_price_dates_to', true);
                 $date_from = !empty($date_from) ? date('Y-m-d', $date_from) : '';
                 $date_to = !empty($date_to) ? date('Y-m-d', $date_to) : '';
                 _wc_save_product_price($variation_id, $regular_price, $sale_price, $date_from, $date_to);
             }
             break;
         case 'variable_stock':
             if (empty($data['value'])) {
                 break;
             }
             $value = wc_clean($data['value']);
             foreach ($variations as $variation_id) {
                 if ('yes' === get_post_meta($variation_id, '_manage_stock', true)) {
                     wc_update_product_stock($variation_id, wc_stock_amount($value));
                 } else {
                     delete_post_meta($variation_id, '_stock');
                 }
             }
             break;
         case 'variable_weight':
         case 'variable_length':
         case 'variable_width':
         case 'variable_height':
             if (empty($data['value'])) {
                 break;
             }
             $value = wc_clean($data['value']);
             $field = str_replace('variable', '', $bulk_action);
             $wpdb->query($wpdb->prepare("\n\t\t\t\t\tUPDATE {$wpdb->postmeta} AS postmeta\n\t\t\t\t\tINNER JOIN {$wpdb->posts} AS posts ON posts.post_parent = %d\n\t\t\t\t\tSET postmeta.meta_value = %s\n\t\t\t\t\tWHERE postmeta.meta_key = '%s'\n\t\t\t\t\tAND postmeta.post_id = posts.ID\n\t\t\t\t ", $product_id, $value, $field));
             break;
         case 'variable_download_limit':
         case 'variable_download_expiry':
             if (empty($data['value'])) {
                 break;
             }
             $value = wc_clean($data['value']);
             $field = str_replace('variable', '', $bulk_action);
             foreach ($variations as $variation_id) {
                 if ('yes' === get_post_meta($variation_id, '_downloadable', true)) {
                     update_post_meta($variation_id, $field, $value);
                 } else {
                     update_post_meta($variation_id, $field, '');
                 }
             }
             break;
         case 'delete_all':
             if (isset($data['allowed']) && 'true' === $data['allowed']) {
                 foreach ($variations as $variation_id) {
                     wp_delete_post($variation_id);
                 }
             }
             break;
         case 'variable_regular_price_increase':
         case 'variable_regular_price_decrease':
         case 'variable_sale_price_increase':
         case 'variable_sale_price_decrease':
             if (empty($data['value'])) {
                 break;
             }
             $field = str_replace(array('variable', '_increase', '_decrease'), '', $bulk_action);
             $operator = 'increase' === substr($bulk_action, -8) ? +1 : -1;
             foreach ($variations as $variation_id) {
                 // Price fields
                 $regular_price = get_post_meta($variation_id, '_regular_price', true);
                 $sale_price = get_post_meta($variation_id, '_sale_price', true);
                 // Date fields
                 $date_from = get_post_meta($variation_id, '_sale_price_dates_from', true);
                 $date_to = get_post_meta($variation_id, '_sale_price_dates_to', true);
                 $date_from = !empty($date_from) ? date('Y-m-d', $date_from) : '';
                 $date_to = !empty($date_to) ? date('Y-m-d', $date_to) : '';
                 if ('%' === substr($data['value'], -1)) {
                     $percent = wc_format_decimal(substr($data['value'], 0, -1));
                     if ('_regular_price' === $field) {
                         $regular_price += $regular_price / 100 * $percent * $operator;
                     } else {
                         $sale_price += $sale_price / 100 * $percent * $operator;
                     }
                 } else {
                     if ('_regular_price' === $field) {
                         $regular_price += $data['value'];
                     } else {
                         $sale_price += $data['value'];
                     }
                 }
                 _wc_save_product_price($variation_id, $regular_price, $sale_price, $date_from, $date_to);
             }
             break;
         case 'variable_sale_schedule':
             if (!isset($data['date_from']) && !isset($data['date_to'])) {
                 break;
             }
             foreach ($variations as $variation_id) {
                 // Price fields
                 $regular_price = get_post_meta($variation_id, '_regular_price', true);
                 $sale_price = get_post_meta($variation_id, '_sale_price', true);
                 // Date fields
                 $date_from = get_post_meta($variation_id, '_sale_price_dates_from', true);
                 $date_to = get_post_meta($variation_id, '_sale_price_dates_to', true);
                 if ('false' === $data['date_from']) {
                     $date_from = !empty($date_from) ? date('Y-m-d', $date_from) : '';
                 } else {
                     $date_from = $data['date_from'];
                 }
                 if ('false' === $data['date_to']) {
                     $date_to = !empty($date_to) ? date('Y-m-d', $date_to) : '';
                 } else {
                     $date_to = $data['date_to'];
                 }
                 _wc_save_product_price($variation_id, $regular_price, $sale_price, $date_from, $date_to);
             }
             break;
         default:
             do_action('woocommerce_bulk_edit_variations_default', $bulk_action, $data, $product_id, $variations);
             break;
     }
     do_action('woocommerce_bulk_edit_variations', $bulk_action, $data, $product_id, $variations);
     // Sync and update transients
     WC_Product_Variable::sync($product_id);
     wc_delete_product_transients($product_id);
     die;
 }