/**
  * Sync grouped product prices with children.
  *
  * @since 2.7.0
  * @param WC_Product|int $product
  */
 public function sync_price(&$product)
 {
     global $wpdb;
     $children_ids = get_posts(array('post_parent' => $product->get_id(), 'post_type' => 'product', 'fields' => 'ids'));
     $prices = $children_ids ? array_unique($wpdb->get_col("SELECT meta_value FROM {$wpdb->postmeta} WHERE meta_key = '_price' AND post_id IN ( " . implode(',', array_map('absint', $children_ids)) . " )")) : array();
     delete_post_meta($product->get_id(), '_price');
     delete_transient('wc_var_prices_' . $product->get_id());
     if ($prices) {
         sort($prices);
         // To allow sorting and filtering by multiple values, we have no choice but to store child prices in this manner.
         foreach ($prices as $price) {
             add_post_meta($product->get_id(), '_price', $price, false);
         }
     }
 }
 /**
  * Backports WC_Product::get_id() method to 2.4.x
  *
  * @link https://github.com/woothemes/woocommerce/pull/9765
  *
  * @since 4.2.0
  * @param \WC_Product $product product object
  * @return string|int product ID
  */
 public static function product_get_id(WC_Product $product)
 {
     if (self::is_wc_version_gte_2_5()) {
         return $product->get_id();
     } else {
         return $product->is_type('variation') ? $product->variation_id : $product->id;
     }
 }
Example #3
0
 /**
  * Test updating a product.
  *
  * @since 2.7.0
  */
 function test_product_update()
 {
     $product = WC_Helper_Product::create_simple_product();
     $this->assertEquals('10', $product->get_regular_price());
     $product->set_regular_price(15);
     $product->save();
     // Reread from database
     $product = new WC_Product($product->get_id());
     $this->assertEquals('15', $product->get_regular_price());
 }
 /**
  * Add a product line item to the order. This is the only line item type with
  * it's own method because it saves looking up order amounts (costs are added up for you).
  * @param  \WC_Product $product
  * @param  int $qty
  * @param  array $args
  * @return int order item ID
  * @throws WC_Data_Exception
  */
 public function add_product($product, $qty = 1, $args = array())
 {
     if ($product) {
         $default_args = array('name' => $product->get_title(), 'tax_class' => $product->get_tax_class(), 'product_id' => $product->get_id(), 'variation_id' => isset($product->variation_id) ? $product->variation_id : 0, 'variation' => isset($product->variation_id) ? $product->get_variation_attributes() : array(), 'subtotal' => $product->get_price_excluding_tax($qty), 'total' => $product->get_price_excluding_tax($qty), 'quantity' => $qty);
     } else {
         $default_args = array('quantity' => $qty);
     }
     $args = wp_parse_args($args, $default_args);
     // BW compatibility with old args
     if (isset($args['totals'])) {
         foreach ($args['totals'] as $key => $value) {
             if ('tax' === $key) {
                 $args['total_tax'] = $value;
             } elseif ('tax_data' === $key) {
                 $args['taxes'] = $value;
             } else {
                 $args[$key] = $value;
             }
         }
     }
     $item = new WC_Order_Item_Product($args);
     $item->set_backorder_meta();
     $item->set_order_id($this->get_id());
     $item->save();
     $this->add_item($item);
     wc_do_deprecated_action('woocommerce_order_add_product', array($this->get_id(), $item->get_id(), $product, $qty, $args), '2.7', 'Use woocommerce_new_order_item action instead.');
     return $item->get_id();
 }
 /**
  * Sync variable product prices with children.
  *
  * @since 2.7.0
  * @param WC_Product|int $product
  */
 public function sync_price(&$product)
 {
     global $wpdb;
     $children = $product->get_visible_children('edit');
     $prices = $children ? array_unique($wpdb->get_col("SELECT meta_value FROM {$wpdb->postmeta} WHERE meta_key = '_price' AND post_id IN ( " . implode(',', array_map('absint', $children)) . " )")) : array();
     delete_post_meta($product->get_id(), '_price');
     if ($prices) {
         sort($prices);
         // To allow sorting and filtering by multiple values, we have no choice but to store child prices in this manner.
         foreach ($prices as $price) {
             add_post_meta($product->get_id(), '_price', $price, false);
         }
     }
 }
 /**
  * Get the attributes for a product or product variation
  *
  * @since 2.1
  * @param WC_Product|WC_Product_Variation $product
  * @return array
  */
 private function get_attributes($product)
 {
     $attributes = array();
     if ($product->is_type('variation')) {
         // variation attributes
         foreach ($product->get_variation_attributes() as $attribute_name => $attribute) {
             // taxonomy-based attributes are prefixed with `pa_`, otherwise simply `attribute_`
             $attributes[] = array('name' => ucwords(str_replace('attribute_', '', str_replace('pa_', '', $attribute_name))), 'option' => $attribute);
         }
     } else {
         foreach ($product->get_attributes() as $attribute) {
             $attributes[] = array('name' => ucwords(str_replace('pa_', '', $attribute['name'])), 'position' => $attribute['position'], 'visible' => (bool) $attribute['is_visible'], 'variation' => (bool) $attribute['is_variation'], 'options' => $this->get_attribute_options($product->get_id(), $attribute));
         }
     }
     return $attributes;
 }
 /**
  * Update a products rating counts.
  *
  * @since 2.7.0
  * @param WC_Product $product
  */
 public function update_rating_counts($product)
 {
     update_post_meta($product->get_id(), '_wc_rating_count', $product->get_rating_counts('edit'));
 }
 /**
  * Save variations.
  *
  * @throws WC_REST_Exception REST API exceptions.
  * @param WC_Product      $product          Product instance.
  * @param WP_REST_Request $request          Request data.
  * @param bool            $single_variation True if saving only a single variation.
  * @return bool
  */
 protected function save_variations_data($product, $request, $single_variation = false)
 {
     global $wpdb;
     if ($single_variation) {
         $variations = array($request);
     } else {
         $variations = $request['variations'];
     }
     foreach ($variations as $menu_order => $data) {
         $variation_id = isset($data['id']) ? absint($data['id']) : 0;
         $variation = new WC_Product_Variation($variation_id);
         // Create initial name and status.
         if (!$variation->get_slug()) {
             /* translators: 1: variation id 2: product name */
             $variation->set_name(sprintf(__('Variation #%1$s of %2$s', 'woocommerce'), $variation->get_id(), $product->get_name()));
             $variation->set_status(isset($data['visible']) && false === $data['visible'] ? 'private' : 'publish');
         }
         // Parent ID.
         $variation->set_parent_id($product->get_id());
         // Menu order.
         $variation->set_menu_order($menu_order);
         // Status.
         if (isset($data['visible'])) {
             $variation->set_status(false === $data['visible'] ? 'private' : 'publish');
         }
         // SKU.
         if (isset($data['sku'])) {
             $variation->set_sku(wc_clean($data['sku']));
         }
         // Thumbnail.
         if (isset($data['image']) && is_array($data['image'])) {
             $image = $data['image'];
             $image = current($image);
             if (is_array($image)) {
                 $image['position'] = 0;
             }
             $variation = $this->save_product_images($variation, array($image));
         }
         // Virtual variation.
         if (isset($data['virtual'])) {
             $variation->set_virtual($data['virtual']);
         }
         // Downloadable variation.
         if (isset($data['downloadable'])) {
             $variation->set_downloadable($data['downloadable']);
         }
         // Downloads.
         if ($variation->get_downloadable()) {
             // Downloadable files.
             if (isset($data['downloads']) && is_array($data['downloads'])) {
                 $variation = $this->save_downloadable_files($variation, $data['downloads']);
             }
             // Download limit.
             if (isset($data['download_limit'])) {
                 $variation->set_download_limit($data['download_limit']);
             }
             // Download expiry.
             if (isset($data['download_expiry'])) {
                 $variation->set_download_expiry($data['download_expiry']);
             }
         }
         // Shipping data.
         $variation = $this->save_product_shipping_data($variation, $data);
         // Stock handling.
         if (isset($data['manage_stock'])) {
             $variation->set_manage_stock($data['manage_stock']);
         }
         if (isset($data['in_stock'])) {
             $variation->set_stock_status(true === $data['in_stock'] ? 'instock' : 'outofstock');
         }
         if (isset($data['backorders'])) {
             $variation->set_backorders($data['backorders']);
         }
         if ($variation->get_manage_stock()) {
             if (isset($data['stock_quantity'])) {
                 $variation->set_stock_quantity($data['stock_quantity']);
             } elseif (isset($data['inventory_delta'])) {
                 $stock_quantity = wc_stock_amount($variation->get_stock_amount());
                 $stock_quantity += wc_stock_amount($data['inventory_delta']);
                 $variation->set_stock_quantity($stock_quantity);
             }
         } else {
             $variation->set_backorders('no');
             $variation->set_stock_quantity('');
         }
         // Regular Price.
         if (isset($data['regular_price'])) {
             $variation->set_regular_price($data['regular_price']);
         }
         // Sale Price.
         if (isset($data['sale_price'])) {
             $variation->set_sale_price($data['sale_price']);
         }
         if (isset($data['date_on_sale_from'])) {
             $variation->set_date_on_sale_from($data['date_on_sale_from']);
         }
         if (isset($data['date_on_sale_to'])) {
             $variation->set_date_on_sale_to($data['date_on_sale_to']);
         }
         // Tax class.
         if (isset($data['tax_class'])) {
             $variation->set_tax_class($data['tax_class']);
         }
         // Description.
         if (isset($data['description'])) {
             $variation->set_description(wp_kses_post($data['description']));
         }
         // Update taxonomies.
         if (isset($data['attributes'])) {
             $attributes = array();
             $parent_attributes = $product->get_attributes();
             foreach ($data['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($parent_attributes[$attribute_name]) || !$parent_attributes[$attribute_name]->get_variation()) {
                     continue;
                 }
                 $attribute_key = sanitize_title($parent_attributes[$attribute_name]->get_name());
                 $attribute_value = isset($attribute['option']) ? wc_clean(stripslashes($attribute['option'])) : '';
                 if ($parent_attributes[$attribute_name]->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);
                     }
                 }
                 $attributes[$attribute_key] = $attribute_value;
             }
             $variation->set_attributes($attributes);
         }
         $variation->save();
         do_action('woocommerce_rest_save_product_variation', $variation->get_id(), $menu_order, $data);
     }
     return true;
 }
 /**
  * Save product images.
  *
  * @since  2.2
  * @param  WC_Product $product
  * @param  array $images
  * @throws WC_API_Exception
  * @return WC_Product
  */
 protected function save_product_images($product, $images)
 {
     if (is_array($images)) {
         $gallery = array();
         foreach ($images as $image) {
             if (isset($image['position']) && 0 == $image['position']) {
                 $attachment_id = isset($image['id']) ? absint($image['id']) : 0;
                 if (0 === $attachment_id && isset($image['src'])) {
                     $upload = $this->upload_product_image(esc_url_raw($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, $product->get_id());
                 }
                 $product->set_image_id($attachment_id);
             } else {
                 $attachment_id = isset($image['id']) ? absint($image['id']) : 0;
                 if (0 === $attachment_id && isset($image['src'])) {
                     $upload = $this->upload_product_image(esc_url_raw($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);
                 }
                 $gallery[] = $attachment_id;
             }
             // Set the image alt if present.
             if (!empty($image['alt']) && $attachment_id) {
                 update_post_meta($attachment_id, '_wp_attachment_image_alt', wc_clean($image['alt']));
             }
             // Set the image title if present.
             if (!empty($image['title']) && $attachment_id) {
                 wp_update_post(array('ID' => $attachment_id, 'post_title' => $image['title']));
             }
         }
         if (!empty($gallery)) {
             $product->set_gallery_image_ids($gallery);
         }
     } else {
         $product->set_image_id('');
         $product->set_gallery_image_ids(array());
     }
     return $product;
 }
 /**
  * Get product rating count for a product. Please note this is not cached.
  *
  * @since 2.7.0
  * @param WC_Product $product
  * @return array of integers
  */
 public static function get_rating_counts_for_product(&$product)
 {
     global $wpdb;
     $counts = array();
     $raw_counts = $wpdb->get_results($wpdb->prepare("\n\t\t\tSELECT meta_value, COUNT( * ) as meta_value_count FROM {$wpdb->commentmeta}\n\t\t\tLEFT JOIN {$wpdb->comments} ON {$wpdb->commentmeta}.comment_id = {$wpdb->comments}.comment_ID\n\t\t\tWHERE meta_key = 'rating'\n\t\t\tAND comment_post_ID = %d\n\t\t\tAND comment_approved = '1'\n\t\t\tAND meta_value > 0\n\t\t\tGROUP BY meta_value\n\t\t", $product->get_id()));
     foreach ($raw_counts as $count) {
         $counts[$count->meta_value] = absint($count->meta_value_count);
     }
     $product->set_rating_counts($counts);
     $data_store = $product->get_data_store();
     $data_store->update_rating_counts($product);
     return $counts;
 }