/** * Test wc_product_has_unique_sku() * * @since 2.3 */ public function test_wc_product_has_unique_sku() { $product_1 = \WC_Helper_Product::create_simple_product(); $this->assertEquals(true, wc_product_has_unique_sku($product_1->id, $product_1->sku)); $product_2 = \WC_Helper_Product::create_simple_product(); $this->assertEquals(false, wc_product_has_unique_sku($product_2->id, $product_2->sku)); \WC_Helper_Product::delete_product($product_1->id); $this->assertEquals(true, wc_product_has_unique_sku($product_2->id, $product_2->sku)); \WC_Helper_Product::delete_product($product_2->id); }
/** * Save variations * * @since 2.2 * @param int $id * @param array $data * @return bool */ 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; // Generate a useful post title $variation_post_title = sprintf(__('Variation #%s of %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']) && isset($image['src']) && $image['position'] == 0) { $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); 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'; update_post_meta($variation_id, '_manage_stock', $managing_stock); } else { $managing_stock = get_post_meta($variation_id, '_manage_stock', true); } // Only update stock status to user setting if changed by the user, but do so before looking at stock levels at variation level if (isset($variation['in_stock'])) { $stock_status = true === $variation['in_stock'] ? 'instock' : 'outofstock'; wc_update_product_stock_status($variation_id, $stock_status); } if ('yes' === $managing_stock) { if (isset($variation['backorders'])) { if ('notify' == $variation['backorders']) { $backorders = 'notify'; } else { $backorders = true === $variation['backorders'] ? 'yes' : 'no'; } } else { $backorders = 'no'; } update_post_meta($variation_id, '_backorders', $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'] ? '' : wc_format_decimal($variation['regular_price']); update_post_meta($variation_id, '_regular_price', $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'] ? '' : wc_format_decimal($variation['sale_price']); update_post_meta($variation_id, '_sale_price', $sale_price); } else { $sale_price = get_post_meta($variation_id, '_sale_price', true); } $date_from = isset($variation['sale_price_dates_from']) ? strtotime($variation['sale_price_dates_from']) : get_post_meta($variation_id, '_sale_price_dates_from', true); $date_to = isset($variation['sale_price_dates_to']) ? strtotime($variation['sale_price_dates_to']) : get_post_meta($variation_id, '_sale_price_dates_to', true); // Save Dates if ($date_from) { update_post_meta($variation_id, '_sale_price_dates_from', $date_from); } else { update_post_meta($variation_id, '_sale_price_dates_from', ''); } if ($date_to) { update_post_meta($variation_id, '_sale_price_dates_to', $date_to); } else { update_post_meta($variation_id, '_sale_price_dates_to', ''); } if ($date_to && !$date_from) { update_post_meta($variation_id, '_sale_price_dates_from', strtotime('NOW', current_time('timestamp'))); } // Update price if on sale if ('' != $sale_price && '' == $date_to && '' == $date_from) { update_post_meta($variation_id, '_price', $sale_price); } else { update_post_meta($variation_id, '_price', $regular_price); } if ('' != $sale_price && $date_from && $date_from < strtotime('NOW', current_time('timestamp'))) { update_post_meta($variation_id, '_price', $sale_price); } if ($date_to && $date_to < strtotime('NOW', current_time('timestamp'))) { update_post_meta($variation_id, '_price', $regular_price); update_post_meta($variation_id, '_sale_price_dates_from', ''); update_post_meta($variation_id, '_sale_price_dates_to', ''); } // Tax class if (isset($variation['tax_class'])) { if ($variation['tax_class'] !== 'parent') { 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', ''); } // Update taxonomies if (isset($variation['attributes'])) { $updated_attribute_keys = array(); foreach ($variation['attributes'] as $attribute_key => $attribute) { if (!isset($attribute['name'])) { continue; } $_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 meta box data * * @deprecated 2.4.0 Deprecated in favor to WC_AJAX::save_variations() */ 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 #%s of %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 { $wpdb->update($wpdb->posts, array('post_status' => $post_status, 'post_title' => $variation_post_title, 'menu_order' => $variable_menu_order[$i]), array('ID' => $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(stripslashes($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(__('Variation SKU must be unique.', 'woocommerce')); } 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); // 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]); } 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'); } // Price handling $regular_price = wc_format_decimal($variable_regular_price[$i]); $sale_price = $variable_sale_price[$i] === '' ? '' : wc_format_decimal($variable_sale_price[$i]); $date_from = wc_clean($variable_sale_price_dates_from[$i]); $date_to = wc_clean($variable_sale_price_dates_to[$i]); update_post_meta($variation_id, '_regular_price', $regular_price); update_post_meta($variation_id, '_sale_price', $sale_price); // Save Dates update_post_meta($variation_id, '_sale_price_dates_from', $date_from ? strtotime($date_from) : ''); update_post_meta($variation_id, '_sale_price_dates_to', $date_to ? strtotime($date_to) : ''); if ($date_to && !$date_from) { update_post_meta($variation_id, '_sale_price_dates_from', strtotime('NOW', current_time('timestamp'))); } // Update price if on sale if ('' !== $sale_price && '' === $date_to && '' === $date_from) { update_post_meta($variation_id, '_price', $sale_price); } else { update_post_meta($variation_id, '_price', $regular_price); } if ('' !== $sale_price && $date_from && strtotime($date_from) < strtotime('NOW', current_time('timestamp'))) { update_post_meta($variation_id, '_price', $sale_price); } if ($date_to && strtotime($date_to) < strtotime('NOW', current_time('timestamp'))) { update_post_meta($variation_id, '_price', $regular_price); update_post_meta($variation_id, '_sale_price_dates_from', ''); update_post_meta($variation_id, '_sale_price_dates_to', ''); } 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, '?')); $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(__('The downloadable file %s cannot be used as it does not have an allowed file type. Allowed types include: %s', 'woocommerce'), '<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(__('The downloadable file %s cannot be used as it does not exist on the server.', 'woocommerce'), '<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']) { // Don't use wc_clean as it destroys sanitized characters if (isset($_POST['default_attribute_' . sanitize_title($attribute['name'])])) { $value = sanitize_title(trim(stripslashes($_POST['default_attribute_' . sanitize_title($attribute['name'])]))); } else { $value = ''; } if ($value) { $default_attributes[sanitize_title($attribute['name'])] = $value; } } } update_post_meta($post_id, '_default_attributes', $default_attributes); }
/** * Quick edit * * @param integer $post_id * @param WC_Product $product */ private function quick_edit_save($post_id, $product) { global $wpdb; $old_regular_price = $product->regular_price; $old_sale_price = $product->sale_price; // Save fields if (isset($_REQUEST['_sku'])) { $sku = get_post_meta($post_id, '_sku', true); $new_sku = wc_clean($_REQUEST['_sku']); if ($new_sku !== $sku) { if (!empty($new_sku)) { $unique_sku = wc_product_has_unique_sku($post_id, $new_sku); if ($unique_sku) { update_post_meta($post_id, '_sku', $new_sku); } } else { update_post_meta($post_id, '_sku', ''); } } } if (isset($_REQUEST['_weight'])) { update_post_meta($post_id, '_weight', wc_clean($_REQUEST['_weight'])); } if (isset($_REQUEST['_length'])) { update_post_meta($post_id, '_length', wc_clean($_REQUEST['_length'])); } if (isset($_REQUEST['_width'])) { update_post_meta($post_id, '_width', wc_clean($_REQUEST['_width'])); } if (isset($_REQUEST['_height'])) { update_post_meta($post_id, '_height', wc_clean($_REQUEST['_height'])); } if (!empty($_REQUEST['_shipping_class'])) { $shipping_class = '_no_shipping_class' == $_REQUEST['_shipping_class'] ? '' : wc_clean($_REQUEST['_shipping_class']); wp_set_object_terms($post_id, $shipping_class, 'product_shipping_class'); } if (isset($_REQUEST['_visibility'])) { if (update_post_meta($post_id, '_visibility', wc_clean($_REQUEST['_visibility']))) { do_action('woocommerce_product_set_visibility', $post_id, wc_clean($_REQUEST['_visibility'])); } } if (isset($_REQUEST['_featured'])) { if (update_post_meta($post_id, '_featured', 'yes')) { delete_transient('wc_featured_products'); } } else { if (update_post_meta($post_id, '_featured', 'no')) { delete_transient('wc_featured_products'); } } if (isset($_REQUEST['_tax_status'])) { update_post_meta($post_id, '_tax_status', wc_clean($_REQUEST['_tax_status'])); } if (isset($_REQUEST['_tax_class'])) { update_post_meta($post_id, '_tax_class', wc_clean($_REQUEST['_tax_class'])); } if ($product->is_type('simple') || $product->is_type('external')) { if (isset($_REQUEST['_regular_price'])) { $new_regular_price = $_REQUEST['_regular_price'] === '' ? '' : wc_format_decimal($_REQUEST['_regular_price']); update_post_meta($post_id, '_regular_price', $new_regular_price); } else { $new_regular_price = null; } if (isset($_REQUEST['_sale_price'])) { $new_sale_price = $_REQUEST['_sale_price'] === '' ? '' : wc_format_decimal($_REQUEST['_sale_price']); update_post_meta($post_id, '_sale_price', $new_sale_price); } else { $new_sale_price = null; } // Handle price - remove dates and set to lowest $price_changed = false; if (!is_null($new_regular_price) && $new_regular_price != $old_regular_price) { $price_changed = true; } elseif (!is_null($new_sale_price) && $new_sale_price != $old_sale_price) { $price_changed = true; } if ($price_changed) { update_post_meta($post_id, '_sale_price_dates_from', ''); update_post_meta($post_id, '_sale_price_dates_to', ''); if (!is_null($new_sale_price) && $new_sale_price !== '') { update_post_meta($post_id, '_price', $new_sale_price); } else { update_post_meta($post_id, '_price', $new_regular_price); } } } // Handle stock status if (isset($_REQUEST['_stock_status'])) { $stock_status = wc_clean($_REQUEST['_stock_status']); if ($product->is_type('variable')) { foreach ($product->get_children() as $child_id) { if ('yes' !== get_post_meta($child_id, '_manage_stock', true)) { wc_update_product_stock_status($child_id, $stock_status); } } WC_Product_Variable::sync_stock_status($post_id); } else { wc_update_product_stock_status($post_id, $stock_status); } } // Handle stock if (!$product->is_type('grouped')) { if (isset($_REQUEST['_manage_stock'])) { update_post_meta($post_id, '_manage_stock', 'yes'); wc_update_product_stock($post_id, wc_stock_amount($_REQUEST['_stock'])); } else { update_post_meta($post_id, '_manage_stock', 'no'); wc_update_product_stock($post_id, 0); } if (!empty($_REQUEST['_backorders'])) { update_post_meta($post_id, '_backorders', wc_clean($_REQUEST['_backorders'])); } } do_action('woocommerce_product_quick_edit_save', $product); }
/** * woocommerce_untrash_post function. * * @param mixed $id */ public function untrash_post($id) { global $wpdb; if ($id > 0) { $post_type = get_post_type($id); if (in_array($post_type, wc_get_order_types('order-count'))) { // Delete count - meta doesn't work on trashed posts $user_id = get_post_meta($id, '_customer_user', true); if ($user_id > 0) { delete_user_meta($user_id, '_money_spent'); delete_user_meta($user_id, '_order_count'); } $refunds = $wpdb->get_results($wpdb->prepare("SELECT ID FROM {$wpdb->posts} WHERE post_type = 'shop_order_refund' AND post_parent = %d", $id)); foreach ($refunds as $refund) { $wpdb->update($wpdb->posts, array('post_status' => 'wc-completed'), array('ID' => $refund->ID)); } delete_transient('woocommerce_processing_order_count'); wc_delete_shop_order_transients($id); } else { if ('product' === $post_type) { // Check if SKU is valid before untrash the product. $sku = get_post_meta($id, '_sku', true); if (!empty($sku)) { if (!wc_product_has_unique_sku($id, $sku)) { update_post_meta($id, '_sku', ''); } } } } } }
/** * Save variations. * * @param WC_Product $product * @param WP_REST_Request $request * @return bool * @throws WC_REST_Exception */ protected function save_variations_data($product, $request) { global $wpdb; $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 #%s of %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 = current($variation['image']); if ($image && is_array($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 = wc_rest_upload_image_from_url(wc_clean($image['src'])); if (is_wp_error($upload)) { throw new WC_REST_Exception('woocommerce_product_image_upload_error', $upload->get_error_message(), 400); } $attachment_id = wc_rest_set_uploaded_image_as_attachment($upload, $product->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 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'); 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['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 ($variation['tax_class'] !== 'parent') { 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; 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_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 = ''; if (isset($attribute['option'])) { if ($_attribute['is_taxonomy']) { // Don't use wc_clean as it destroys sanitized characters. $value = sanitize_title(trim(stripslashes($attribute['option']))); } else { $value = wc_clean(trim(stripslashes($attribute['option']))); } } if ($value) { $default_attributes[$attribute_name] = $value; } } } } update_post_meta($product->id, '_default_attributes', $default_attributes); } return true; }
/** * Save product meta * * @since 2.2 * @param WC_Product $product * @param array $data * @return WC_Product * @throws WC_API_Exception */ protected function save_product_meta($product, $data) { global $wpdb; // Virtual if (isset($data['virtual'])) { $product->set_virtual($data['virtual']); } // Tax status if (isset($data['tax_status'])) { $product->set_tax_status(wc_clean($data['tax_status'])); } // Tax Class if (isset($data['tax_class'])) { $product->set_tax_class(wc_clean($data['tax_class'])); } // Catalog Visibility if (isset($data['catalog_visibility'])) { $product->set_catalog_visibility(wc_clean($data['catalog_visibility'])); } // Purchase Note if (isset($data['purchase_note'])) { $product->set_purchase_note(wc_clean($data['purchase_note'])); } // Featured Product if (isset($data['featured'])) { $product->set_featured($data['featured']); } // Shipping data $product = $this->save_product_shipping_data($product, $data); // SKU if (isset($data['sku'])) { $sku = $product->get_sku(); $new_sku = wc_clean($data['sku']); if ('' == $new_sku) { $product->set_sku(''); } elseif ($new_sku !== $sku) { if (!empty($new_sku)) { $unique_sku = wc_product_has_unique_sku($product->get_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 { $product->set_sku($new_sku); } } else { $product->set_sku(''); } } } // Attributes if (isset($data['attributes'])) { $attributes = array(); foreach ($data['attributes'] as $attribute) { $is_taxonomy = 0; $taxonomy = 0; if (!isset($attribute['name'])) { continue; } $attribute_slug = sanitize_title($attribute['name']); if (isset($attribute['slug'])) { $taxonomy = $this->get_attribute_taxonomy_by_slug($attribute['slug']); $attribute_slug = sanitize_title($attribute['slug']); } if ($taxonomy) { $is_taxonomy = 1; } if ($is_taxonomy) { $attribute_id = wc_attribute_taxonomy_id_by_name($attribute['name']); if (isset($attribute['options'])) { $options = $attribute['options']; if (!is_array($attribute['options'])) { // Text based attributes - Posted values are term names $options = explode(WC_DELIMITER, $options); } $values = array_map('wc_sanitize_term_text_based', $options); $values = array_filter($values, 'strlen'); } else { $values = array(); } // Update post terms if (taxonomy_exists($taxonomy)) { wp_set_object_terms($product->get_id(), $values, $taxonomy); } if (!empty($values)) { // Add attribute to array, but don't set values. $attribute_object = new WC_Product_Attribute(); $attribute_object->set_id($attribute_id); $attribute_object->set_name($taxonomy); $attribute_object->set_options($values); $attribute_object->set_position(isset($attribute['position']) ? absint($attribute['position']) : 0); $attribute_object->set_visible(isset($attribute['visible']) && $attribute['visible'] ? 1 : 0); $attribute_object->set_variation(isset($attribute['variation']) && $attribute['variation'] ? 1 : 0); $attributes[] = $attribute_object; } } elseif (isset($attribute['options'])) { // Array based if (is_array($attribute['options'])) { $values = $attribute['options']; // Text based, separate by pipe } else { $values = array_map('wc_clean', explode(WC_DELIMITER, $attribute['options'])); } // Custom attribute - Add attribute to array and set the values. $attribute_object = new WC_Product_Attribute(); $attribute_object->set_name($attribute['name']); $attribute_object->set_options($values); $attribute_object->set_position(isset($attribute['position']) ? absint($attribute['position']) : 0); $attribute_object->set_visible(isset($attribute['visible']) && $attribute['visible'] ? 1 : 0); $attribute_object->set_variation(isset($attribute['variation']) && $attribute['variation'] ? 1 : 0); $attributes[] = $attribute_object; } } uasort($attributes, 'wc_product_attribute_uasort_comparison'); $product->set_attributes($attributes); } // Sales and prices if (in_array($product->get_type(), array('variable', 'grouped'))) { // Variable and grouped products have no prices. $product->set_regular_price(''); $product->set_sale_price(''); $product->set_date_on_sale_to(''); $product->set_date_on_sale_from(''); $product->set_price(''); } else { // Regular Price if (isset($data['regular_price'])) { $regular_price = '' === $data['regular_price'] ? '' : $data['regular_price']; } else { $regular_price = $product->get_regular_price(); } // Sale Price if (isset($data['sale_price'])) { $sale_price = '' === $data['sale_price'] ? '' : $data['sale_price']; } else { $sale_price = $product->get_sale_price(); } $product->set_regular_price($regular_price); $product->set_sale_price($sale_price); if (isset($data['sale_price_dates_from'])) { $date_from = $data['sale_price_dates_from']; } else { $date_from = $product->get_date_on_sale_from() ? date('Y-m-d', $date_from) : ''; } if (isset($data['sale_price_dates_to'])) { $date_to = $data['sale_price_dates_to']; } else { $date_to = $product->get_date_on_sale_to() ? date('Y-m-d', $date_to) : ''; } if ($date_to && !$date_from) { $date_from = strtotime('NOW', current_time('timestamp')); } $product->set_date_on_sale_to($date_to); $product->set_date_on_sale_from($date_from); if ($product->is_on_sale()) { $product->set_price($product->get_sale_price()); } else { $product->set_price($product->get_regular_price()); } } // Product parent ID for groups if (isset($data['parent_id'])) { $product->set_parent_id(absint($data['parent_id'])); } // Sold Individually if (isset($data['sold_individually'])) { $product->set_sold_individually(true === $data['sold_individually'] ? 'yes' : ''); } // Stock status if (isset($data['in_stock'])) { $stock_status = true === $data['in_stock'] ? 'instock' : 'outofstock'; } else { $stock_status = $product->get_stock_status(); if ('' === $stock_status) { $stock_status = 'instock'; } } // Stock Data if ('yes' == get_option('woocommerce_manage_stock')) { // Manage stock if (isset($data['managing_stock'])) { $managing_stock = true === $data['managing_stock'] ? 'yes' : 'no'; $product->set_manage_stock($managing_stock); } else { $managing_stock = $product->get_manage_stock() ? 'yes' : 'no'; } // Backorders if (isset($data['backorders'])) { if ('notify' == $data['backorders']) { $backorders = 'notify'; } else { $backorders = true === $data['backorders'] ? 'yes' : 'no'; } $product->set_backorders($backorders); } else { $backorders = $product->get_backorders(); } if ($product->is_type('grouped')) { $product->set_manage_stock('no'); $product->set_backorders('no'); $product->set_stock_quantity(''); $product->set_stock_status($stock_status); } elseif ($product->is_type('external')) { $product->set_manage_stock('no'); $product->set_backorders('no'); $product->set_stock_quantity(''); $product->set_stock_status('instock'); } elseif ('yes' == $managing_stock) { $product->set_backorders($backorders); // Stock status is always determined by children so sync later. if (!$product->is_type('variable')) { $product->set_stock_status($stock_status); } // Stock quantity if (isset($data['stock_quantity'])) { $product->set_stock_quantity(wc_stock_amount($data['stock_quantity'])); } } else { // Don't manage stock. $product->set_manage_stock('no'); $product->set_backorders($backorders); $product->set_stock_quantity(''); $product->set_stock_status($stock_status); } } elseif (!$product->is_type('variable')) { $product->set_stock_status($stock_status); } // Upsells if (isset($data['upsell_ids'])) { $upsells = array(); $ids = $data['upsell_ids']; if (!empty($ids)) { foreach ($ids as $id) { if ($id && $id > 0) { $upsells[] = $id; } } $product->set_upsell_ids($upsells); } else { $product->set_upsell_ids(array()); } } // Cross sells if (isset($data['cross_sell_ids'])) { $crosssells = array(); $ids = $data['cross_sell_ids']; if (!empty($ids)) { foreach ($ids as $id) { if ($id && $id > 0) { $crosssells[] = $id; } } $product->set_cross_sell_ids($crosssells); } else { $product->set_cross_sell_ids(array()); } } // Product categories if (isset($data['categories']) && is_array($data['categories'])) { $term_ids = array_unique(array_map('intval', $data['categories'])); $product->set_category_ids($term_ids); } // Product tags if (isset($data['tags']) && is_array($data['tags'])) { $term_ids = array_unique(array_map('intval', $data['tags'])); $product->set_tag_ids($term_ids); } // Downloadable if (isset($data['downloadable'])) { $is_downloadable = true === $data['downloadable'] ? 'yes' : 'no'; $product->set_downloadable($is_downloadable); } else { $is_downloadable = $product->get_downloadable() ? 'yes' : 'no'; } // Downloadable options if ('yes' == $is_downloadable) { // Downloadable files if (isset($data['downloads']) && is_array($data['downloads'])) { $product = $this->save_downloadable_files($product, $data['downloads']); } // Download limit if (isset($data['download_limit'])) { $product->set_download_limit($data['download_limit']); } // Download expiry if (isset($data['download_expiry'])) { $product->set_download_expiry($data['download_expiry']); } } // Product url if ($product->is_type('external')) { if (isset($data['product_url'])) { $product->set_product_url($data['product_url']); } if (isset($data['button_text'])) { $product->set_button_text($data['button_text']); } } // Reviews allowed if (isset($data['reviews_allowed'])) { $product->set_reviews_allowed($data['reviews_allowed']); } // Save default attributes for variable products. if ($product->is_type('variable')) { $product = $this->save_default_attributes($product, $data); } // Do action for product type do_action('woocommerce_api_process_product_meta_' . $product->get_type(), $product->get_id(), $data); return $product; }
/** * Set SKU. * * @since 2.7.0 * @throws WC_Data_Exception * @param string $sku Product SKU. */ public function set_sku($sku) { $sku = (string) $sku; if (!empty($sku) && !wc_product_has_unique_sku($this->get_id(), $sku)) { $this->error('product_invalid_sku', __('Invalid or duplicated SKU.', 'woocommerce')); } $this->set_prop('sku', $sku); }
/** * Quick edit. * * @param integer $post_id * @param WC_Product $product */ private function quick_edit_save($post_id, $product) { $data_store = $product->get_data_store(); $old_regular_price = $product->get_regular_price(); $old_sale_price = $product->get_sale_price(); // Save fields if (isset($_REQUEST['_sku'])) { $sku = $product->get_sku(); $new_sku = (string) wc_clean($_REQUEST['_sku']); if ($new_sku !== $sku) { if (!empty($new_sku)) { $unique_sku = wc_product_has_unique_sku($post_id, $new_sku); if ($unique_sku) { $product->set_sku($new_sku); } } else { $product->set_sku(''); } } } if (isset($_REQUEST['_weight'])) { $product->set_weight(wc_clean($_REQUEST['_weight'])); } if (isset($_REQUEST['_length'])) { $product->set_length(wc_clean($_REQUEST['_length'])); } if (isset($_REQUEST['_width'])) { $product->set_width(wc_clean($_REQUEST['_width'])); } if (isset($_REQUEST['_height'])) { $product->set_height(wc_clean($_REQUEST['_height'])); } if (!empty($_REQUEST['_shipping_class'])) { $shipping_class = '_no_shipping_class' == $_REQUEST['_shipping_class'] ? '' : wc_clean($_REQUEST['_shipping_class']); $shipping_class_id = $data_store->get_shipping_class_id_by_slug($shipping_class); if ($shipping_class_id) { $product->set_shipping_class_id($shipping_class_id); } } if (isset($_REQUEST['_visibility'])) { $product->set_catalog_visibility(wc_clean($_REQUEST['_visibility'])); } if (isset($_REQUEST['_featured'])) { $product->set_featured(true); } else { $product->set_featured(false); } if (isset($_REQUEST['_tax_status'])) { $product->set_tax_status(wc_clean($_REQUEST['_tax_status'])); } if (isset($_REQUEST['_tax_class'])) { $product->set_tax_class(wc_clean($_REQUEST['_tax_class'])); } if ($product->is_type('simple') || $product->is_type('external')) { if (isset($_REQUEST['_regular_price'])) { $new_regular_price = '' === $_REQUEST['_regular_price'] ? '' : wc_format_decimal($_REQUEST['_regular_price']); $product->set_regular_price($new_regular_price); } else { $new_regular_price = null; } if (isset($_REQUEST['_sale_price'])) { $new_sale_price = '' === $_REQUEST['_sale_price'] ? '' : wc_format_decimal($_REQUEST['_sale_price']); $product->set_sale_price($new_sale_price); } else { $new_sale_price = null; } // Handle price - remove dates and set to lowest $price_changed = false; if (!is_null($new_regular_price) && $new_regular_price != $old_regular_price) { $price_changed = true; } elseif (!is_null($new_sale_price) && $new_sale_price != $old_sale_price) { $price_changed = true; } if ($price_changed) { $product->set_date_on_sale_to(''); $product->set_date_on_sale_from(''); } } // Handle Stock Data $manage_stock = !empty($_REQUEST['_manage_stock']) && 'grouped' !== $product->get_type() ? 'yes' : 'no'; $backorders = !empty($_REQUEST['_backorders']) ? wc_clean($_REQUEST['_backorders']) : 'no'; $stock_status = !empty($_REQUEST['_stock_status']) ? wc_clean($_REQUEST['_stock_status']) : 'instock'; $stock_amount = 'yes' === $manage_stock ? wc_stock_amount($_REQUEST['_stock']) : ''; if ('yes' === get_option('woocommerce_manage_stock')) { // Apply product type constraints to stock status if ($product->is_type('external')) { // External always in stock $stock_status = 'instock'; } elseif ($product->is_type('variable')) { // Stock status is always determined by children foreach ($product->get_children() as $child_id) { $child = wc_get_product($child_id); if (!$product->get_manage_stock()) { $child->set_stock_status($stock_status); $child->save(); } } $product = WC_Product_Variable::sync($product, false); } $product->set_manage_stock($manage_stock); $product->set_backorders($backorders); $product->save(); if (!$product->is_type('variable')) { wc_update_product_stock_status($post_id, $stock_status); } wc_update_product_stock($post_id, $stock_amount); } else { $product->save(); wc_update_product_stock_status($post_id, $stock_status); } do_action('woocommerce_product_quick_edit_save', $product); }
/** * Test wc_product_has_unique_sku(). * * @since 2.3 */ public function test_wc_product_has_unique_sku() { $product_1 = WC_Helper_Product::create_simple_product(); $this->assertEquals(true, wc_product_has_unique_sku($product_1->get_id(), $product_1->get_sku())); $product_2 = WC_Helper_Product::create_simple_product(); // we need to manually set a sku, because WC_Product now uses wc_product_has_unique_sku before setting // so we need to manually set it to test the functionality. update_post_meta($product_2->get_id(), '_sku', $product_1->get_sku()); $this->assertEquals(false, wc_product_has_unique_sku($product_2->get_id(), $product_1->get_sku())); WC_Helper_Product::delete_product($product_1->get_id()); $this->assertEquals(true, wc_product_has_unique_sku($product_2->get_id(), $product_2->get_sku())); WC_Helper_Product::delete_product($product_2->get_id()); }
public function mp_save_variation($id, $data) { global $wpdb; /*================= my method*/ $menu_order = 0; $attributes = (array) maybe_unserialize(get_post_meta($id, '_product_attributes', true)); /* echo '<pre>'; print_r($attributes); echo '</pre>';*/ // $data=array_reverse($data); $cinv = 0; foreach ($data as $variation_id) { /*start of loop*/ $variation_id = isset($variation_id) ? absint($variation_id) : 0; /*if($cinv==0 && isset($_POST['new_added_variation']) && $_POST['new_added_variation']>=1){ $post_title='Variation #'.$id.' of Product'; $product_data=array( 'post_author'=>get_current_user_id(), 'post_content'=>'', 'post_title'=>$post_title, 'post_status'=>'publish', 'post_type'=>'product_variation', 'post_parent'=>$id, 'menu_order'=>'' ); $var_id = wp_insert_post($product_data); if($var_id!=''){ wp_delete_post($var_id); } } $cinv++;*/ // SKU if (isset($_POST['wkmp_variable_sku'][$variation_id])) { $sku = get_post_meta($variation_id, '_sku', true); $new_sku = wc_clean($_POST['wkmp_variable_sku'][$variation_id]); $is_sku_unique = wc_product_has_unique_sku($variation_id, $new_sku); if ('' == $new_sku) { update_post_meta($variation_id, '_sku', ''); } elseif ($new_sku != $sku && $is_sku_unique) { if (!empty($new_sku)) { update_post_meta($variation_id, '_sku', $new_sku); } else { update_post_meta($variation_id, '_sku', ''); } } } // Thumbnail if (isset($_POST['upload_var_img'][$variation_id])) { $attachment_id = $_POST['upload_var_img'][$variation_id]; if ($attachment_id) { update_post_meta($variation_id, '_thumbnail_id', $attachment_id); } else { // delete_post_meta( $variation_id, '_thumbnail_id' ); update_post_meta($variation_id, '_thumbnail_id', 0); } } // Virtual variation if (isset($_POST['wkmp_variable_is_virtual'][$variation_id])) { $is_virtual = $_POST['wkmp_variable_is_virtual'][$variation_id] == 'yes' ? 'yes' : 'no'; update_post_meta($variation_id, '_virtual', $is_virtual); } else { update_post_meta($variation_id, '_virtual', 'no'); } // Downloadable variation if (isset($_POST['wkmp_variable_is_downloadable'][$variation_id])) { $is_downloadable = 'yes' == $_POST['wkmp_variable_is_downloadable'][$variation_id] ? 'yes' : 'no'; update_post_meta($variation_id, '_downloadable', $is_downloadable); } else { update_post_meta($variation_id, '_downloadable', 'no'); // $is_downloadable = get_post_meta( $variation_id, '_downloadable', true ); $is_downloadable = 'no'; } /*// Shipping data $this->mp_save_product_shipping_data( $variation_id, $_POST );*/ // Stock handling if (isset($_POST['wkmp_variable_manage_stock'][$variation_id])) { $managing_stock = 'yes' == $_POST['wkmp_variable_manage_stock'][$variation_id] ? 'yes' : 'no'; update_post_meta($variation_id, '_manage_stock', $managing_stock); } else { update_post_meta($variation_id, '_manage_stock', 'no'); // $managing_stock = get_post_meta( $variation_id, '_manage_stock', true ); $managing_stock = 'no'; } // Only update stock status to user setting if changed by the user, but do so before looking at stock levels at variation level if (isset($_POST['wkmp_variable_stock_status'][$variation_id])) { $stock_status = 'instock' == $_POST['wkmp_variable_stock_status'][$variation_id] ? 'instock' : 'outofstock'; wc_update_product_stock_status($variation_id, $stock_status); /*update_post_meta( $variation_id, '_stock_status', $managing_stock );*/ } if ('yes' === $managing_stock) { if (isset($_POST['wkmp_variable_backorders'][$variation_id])) { if ('notify' == $_POST['wkmp_variable_backorders'][$variation_id]) { $backorders = 'notify'; } else { $backorders = 'yes' == $_POST['wkmp_variable_backorders'][$variation_id] ? 'yes' : 'no'; } } else { $backorders = 'no'; } update_post_meta($variation_id, '_backorders', $backorders); if (isset($_POST['wkmp_variable_stock'][$variation_id])) { wc_update_product_stock($variation_id, wc_stock_amount($_POST['wkmp_variable_stock'][$variation_id])); } } else { delete_post_meta($variation_id, '_backorders'); delete_post_meta($variation_id, '_stock'); } // Regular Price if (isset($_POST['wkmp_variable_regular_price'][$variation_id])) { $regular_price = '' === $_POST['wkmp_variable_regular_price'][$variation_id] ? '' : wc_format_decimal($_POST['wkmp_variable_regular_price'][$variation_id]); update_post_meta($variation_id, '_regular_price', wc_format_decimal($regular_price)); } else { update_post_meta($variation_id, '_regular_price', ''); // $regular_price = get_post_meta( $variation_id, '_regular_price', true ); $regular_price = ''; } // Sale Price if (isset($_POST['wkmp_variable_sale_price'][$variation_id])) { $sale_price = '' === $_POST['wkmp_variable_sale_price'][$variation_id] ? '' : wc_format_decimal($_POST['wkmp_variable_sale_price'][$variation_id]); update_post_meta($variation_id, '_sale_price', $sale_price); } else { // update_post_meta( $variation_id, '_sale_price', '' ); // $sale_price = get_post_meta( $variation_id, '_sale_price', true ); $sale_price = ''; } $date_from = isset($_POST['wkmp_variable_sale_price_dates_from'][$variation_id]) ? strtotime($_POST['wkmp_variable_sale_price_dates_from'][$variation_id]) : get_post_meta($variation_id, '_sale_price_dates_from', true); $date_to = isset($_POST['wkmp_variable_sale_price_dates_to'][$variation_id]) ? strtotime($_POST['wkmp_variable_sale_price_dates_to'][$variation_id]) : get_post_meta($variation_id, '_sale_price_dates_to', true); // Save Dates if ($date_from) { update_post_meta($variation_id, '_sale_price_dates_from', $date_from); } else { update_post_meta($variation_id, '_sale_price_dates_from', ''); } if ($date_to) { update_post_meta($variation_id, '_sale_price_dates_to', $date_to); } else { update_post_meta($variation_id, '_sale_price_dates_to', ''); } if ($date_to && !$date_from) { update_post_meta($variation_id, '_sale_price_dates_from', strtotime('NOW', current_time('timestamp'))); } // Update price if on sale if ('' != $sale_price && '' == $date_to && '' == $date_from) { update_post_meta($variation_id, '_price', wc_format_decimal($sale_price)); } else { update_post_meta($variation_id, '_price', wc_format_decimal($regular_price)); } if ('' != $sale_price && $date_from && $date_from < strtotime('NOW', current_time('timestamp'))) { update_post_meta($variation_id, '_price', wc_format_decimal($sale_price)); } if ($date_to && $date_to < strtotime('NOW', current_time('timestamp'))) { update_post_meta($variation_id, '_price', wc_format_decimal($regular_price)); update_post_meta($variation_id, '_sale_price_dates_from', ''); update_post_meta($variation_id, '_sale_price_dates_to', ''); } /*// Tax class if ( isset( $_POST['tax_class'] ) ) { if ( $_POST['tax_class'] !== 'parent' ) { update_post_meta( $variation_id, '_tax_class', wc_clean( $_POST['tax_class'] ) ); } else { /*delete_post_meta( $variation_id, '_tax_class' );*/ /* } }*/ // Downloads if ('yes' == $is_downloadable && isset($_POST['_mp_variation_downloads_files_url'][$variation_id])) { /*// Downloadable files if ( isset( $variation['downloads'] ) && is_array( $variation['downloads'] ) ) { $this->save_downloadable_files( $id, $variation['downloads'], $variation_id ); }*/ $variation_files = $_POST['_mp_variation_downloads_files_url'][$variation_id]; $variation_names = isset($_POST['_mp_variation_downloads_files_name'][$variation_id]) ? $_POST['_mp_variation_downloads_files_name'][$variation_id] : ''; $var_downloadable = array(); $var_down_name = array(); if (isset($_POST['_mp_variation_downloads_files_url'][$variation_id]) && count($_POST['_mp_variation_downloads_files_url'][$variation_id]) > 0) { $files = array(); /*$file_url_size = count( $variation_files );*/ /*foreach ($variation_files as $key => $value) {*/ if (!empty($variation_files)) { for ($i = 0; $i < count($variation_files); $i++) { $file_url = wc_clean($variation_files[$i]); if ($file_url != '') { $files[md5($file_url)] = array('name' => $variation_names[$i], 'file' => $file_url); } } } update_post_meta($variation_id, '_downloadable_files', $files); } // Download limit if (isset($_POST['wkmp_variable_download_limit'][$variation_id])) { $download_limit = absint($_POST['wkmp_variable_download_limit'][$variation_id]); update_post_meta($variation_id, '_download_limit', !$download_limit ? '' : $download_limit); } // Download expiry if (isset($_POST['wkmp_variable_download_expiry'][$variation_id])) { $download_expiry = absint($_POST['wkmp_variable_download_expiry'][$variation_id]); 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', ''); } if (isset($_POST['wkmp_variable_weight'][$variation_id])) { update_post_meta($variation_id, '_weight', '' === $_POST['wkmp_variable_weight'][$variation_id] ? '' : wc_format_decimal($_POST['wkmp_variable_weight'][$variation_id])); } // Product dimensions // Height if (isset($_POST['wkmp_variable_height'][$variation_id])) { update_post_meta($variation_id, '_height', '' === $_POST['wkmp_variable_height'][$variation_id] ? '' : wc_format_decimal($_POST['wkmp_variable_height'][$variation_id])); } // Width if (isset($_POST['wkmp_variable_width'][$variation_id])) { update_post_meta($variation_id, '_width', '' === $_POST['wkmp_variable_width'][$variation_id] ? '' : wc_format_decimal($_POST['wkmp_variable_width'][$variation_id])); } // Length if (isset($_POST['wkmp_variable_length'][$variation_id])) { update_post_meta($variation_id, '_length', '' === $_POST['wkmp_variable_length'][$variation_id] ? '' : wc_format_decimal($_POST['wkmp_variable_length'][$variation_id])); } // Virtual if (isset($_POST['wkmp_variable_is_virtual'][$variation_id])) { $virtual = true === $_POST['wkmp_variable_is_virtual'][$variation_id] ? 'yes' : 'no'; if ('yes' == $virtual) { update_post_meta($id, '_weight', ''); update_post_meta($id, '_length', ''); update_post_meta($id, '_width', ''); update_post_meta($id, '_height', ''); } } /*wkmp_variable_is_virtual*/ // Shipping class if (isset($data['shipping_class'])) { wp_set_object_terms($id, wc_clean($data['shipping_class']), 'product_shipping_class'); } // Update taxonomies if (isset($_POST['mp_attribute_name'][$variation_id])) { $updated_attribute_keys = array(); $men_odr = 0; foreach ($_POST['mp_attribute_name'][$variation_id] as $variation_type) { $attribute['option'] = strtolower($_POST['attribute_' . $variation_type][$variation_id]); $attribute['slug'] = $attribute['name'] = $variation_type; if (!isset($attribute['name'])) { continue; } $taxonomy = $attribute['name']; $_attribute = array(); if (isset($attributes[$taxonomy])) { $_attribute = $attributes[$taxonomy]; } if (isset($_attribute['is_variation']) && $_attribute['is_variation']) { $attribute_key = 'attribute_' . strtolower($_attribute['name']); $attribute_value = isset($attribute['option']) ? stripslashes($attribute['option']) : ''; update_post_meta($variation_id, $attribute_key, $attribute_value); // enable/diable variation wkmp_variable_enabled[464] if (isset($_POST['wkmp_variable_enabled'][$variation_id])) { $my_post = array('ID' => $variation_id, 'post_title' => 'Variation #' . $variation_id . ' of ' . get_the_title($_POST['sell_pr_id']), 'menu_order' => $menu_order, 'post_name' => 'product-' . $_POST['sell_pr_id'] . '-variation', 'post_status' => 'publish'); } else { $my_post = array('ID' => $variation_id, 'post_title' => 'Variation #' . $variation_id . ' of ' . get_the_title($_POST['sell_pr_id']), 'menu_order' => $menu_order, 'post_name' => 'product-' . $_POST['sell_pr_id'] . '-variation', 'post_status' => 'private'); } // Update the post into the database wp_update_post($my_post); $men_odr++; } } // 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 ); $menu_order++; } // end of loop // 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->mp_get_attribute_taxonomy_by_slug( $default_attr['slug'] ); } if ( isset( $attributes[ $taxonomy ] ) ) { $_attribute = $attributes[ $taxonomy ]; if ( $_attribute['is_variation'] ) { // Don't use wc_clean as it destroys sanitized characters if ( isset( $default_attr['option'] ) ) { $value = sanitize_title( trim( stripslashes( $default_attr['option'] ) ) ); } else { $value = ''; } if ( $value ) { $default_attributes[ $taxonomy ] = $value; } } } } update_post_meta( $id, '_default_attributes', $default_attributes ); }*/ return true; }
public function product_sku_validation() { global $wpdb; $chk_sku = $_POST['psku']; if (isset($_POST['var_id'])) { $var_id_with_sku = $_POST['var_id']; $var_id_array_with_sku = explode("_", $var_id_with_sku); $var_id = $var_id_array_with_sku[1]; $is_sku_uniquee = wc_product_has_unique_sku($var_id, $chk_sku); // $data=$wpdb->get_results("select meta_value from $wpdb->postmeta where meta_key='_sku'"); /*foreach($data as $d) { $sku[]=$d->meta_value; }*/ if ($is_sku_uniquee) { echo "1"; } else { echo "0"; } } else { $data = $wpdb->get_results("select meta_value from {$wpdb->postmeta} where meta_key='_sku'"); foreach ($data as $d) { $sku[] = $d->meta_value; } if (!empty($sku)) { if (in_array($chk_sku, $sku)) { echo "sku already exist please select another sku"; } else { echo "sku is ok"; } } else { echo "sku is ok"; } } die; }