diff --git a/includes/admin/class-wc-admin-post-types.php b/includes/admin/class-wc-admin-post-types.php index ed1bddd0656af..4b773e9a2d567 100644 --- a/includes/admin/class-wc-admin-post-types.php +++ b/includes/admin/class-wc-admin-post-types.php @@ -817,16 +817,8 @@ private function quick_edit_save( $post_id, $product ) { if ( $new_sku !== $sku ) { if ( ! empty( $new_sku ) ) { - $sku_exists = $wpdb->get_var( $wpdb->prepare(" - SELECT $wpdb->posts.ID - FROM $wpdb->posts - LEFT JOIN $wpdb->postmeta ON ($wpdb->posts.ID = $wpdb->postmeta.post_id) - WHERE $wpdb->posts.post_type = 'product' - AND $wpdb->posts.post_status = 'publish' - AND $wpdb->postmeta.meta_key = '_sku' AND $wpdb->postmeta.meta_value = '%s' - ", $new_sku ) ); - - if ( ! $sku_exists ) { + $unique_sku = wp_product_has_unique_sku( $post_id, $new_sku ); + if ( $unique_sku ) { update_post_meta( $post_id, '_sku', $new_sku ); } } else { diff --git a/includes/admin/meta-boxes/class-wc-meta-box-product-data.php b/includes/admin/meta-boxes/class-wc-meta-box-product-data.php index 50c8c9b901e06..363dacd62bb8a 100644 --- a/includes/admin/meta-boxes/class-wc-meta-box-product-data.php +++ b/includes/admin/meta-boxes/class-wc-meta-box-product-data.php @@ -1056,20 +1056,9 @@ public static function save( $post_id, $post ) { update_post_meta( $post_id, '_sku', '' ); } elseif ( $new_sku !== $sku ) { if ( ! empty( $new_sku ) ) { - if ( - $wpdb->get_var( $wpdb->prepare(" - SELECT $wpdb->posts.ID - FROM $wpdb->posts - LEFT JOIN $wpdb->postmeta ON ($wpdb->posts.ID = $wpdb->postmeta.post_id) - WHERE $wpdb->posts.post_type = 'product' - AND $wpdb->posts.post_status = 'publish' - AND $wpdb->postmeta.meta_key = '_sku' AND $wpdb->postmeta.meta_value = '%s' - AND $wpdb->postmeta.post_id <> $post_id LIMIT 1 - ", $new_sku ) ) - ) { - + $unique_sku = wp_product_has_unique_sku( $post_id, $new_sku ); + if ( ! $unique_sku ) { WC_Admin_Meta_Boxes::add_error( __( 'Product SKU must be unique.', 'woocommerce' ) ); - } else { update_post_meta( $post_id, '_sku', $new_sku ); } @@ -1506,20 +1495,9 @@ public static function save_variations( $post_id, $post ) { update_post_meta( $variation_id, '_sku', '' ); } elseif ( $new_sku !== $sku ) { if ( ! empty( $new_sku ) ) { - if ( - $wpdb->get_var( $wpdb->prepare( " - SELECT $wpdb->posts.ID - FROM $wpdb->posts - LEFT JOIN $wpdb->postmeta ON ($wpdb->posts.ID = $wpdb->postmeta.post_id) - WHERE $wpdb->posts.post_type IN ('product', 'product_variation') - AND $wpdb->posts.post_status = 'publish' - AND $wpdb->postmeta.meta_key = '_sku' AND $wpdb->postmeta.meta_value = '%s' - AND $wpdb->postmeta.post_id <> %d LIMIT 1 - ", $new_sku, $variation_id ) ) - ) { - + $unique_sku = wp_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 ); } diff --git a/includes/api/class-wc-api-products.php b/includes/api/class-wc-api-products.php index e42211e9fd66c..a06ee61a76d93 100644 --- a/includes/api/class-wc-api-products.php +++ b/includes/api/class-wc-api-products.php @@ -593,10 +593,22 @@ protected function save_product_meta( $id, $data ) { // SKU if ( isset( $data['sku'] ) ) { - $sku = $this->save_product_sku( $id, $data['sku'] ); - - if ( is_wp_error( $sku ) ) { - return $sku; + $sku = get_post_meta( $id, '_sku', true ); + $new_sku = wc_clean( $data['sku'] ); + + if ( '' == $new_sku ) { + update_post_meta( $id, '_sku', '' ); + } elseif ( $new_sku !== $sku ) { + if ( ! empty( $new_sku ) ) { + $unique_sku = wp_product_has_unique_sku( $id, $new_sku ); + if ( ! $unique_sku ) { + return new WP_Error( 'woocommerce_api_product_sku_already_exists', __( 'The SKU already exists on another product' ), array( 'status' => 400 ) ); + } else { + update_post_meta( $id, '_sku', $new_sku ); + } + } else { + update_post_meta( $id, '_sku', '' ); + } } } @@ -1022,10 +1034,22 @@ protected function save_variations( $id, $data ) { // SKU if ( isset( $variation['sku'] ) ) { - $sku = $this->save_product_sku( $variation_id, $variation['sku'] ); - - if ( is_wp_error( $sku ) ) { - return $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 = wp_product_has_unique_sku( $variation_id, $new_sku ); + if ( ! $unique_sku ) { + return new WP_Error( 'woocommerce_api_product_sku_already_exists', __( 'The SKU already exists on another product' ), array( 'status' => 400 ) ); + } else { + update_post_meta( $variation_id, '_sku', $new_sku ); + } + } else { + update_post_meta( $variation_id, '_sku', '' ); + } } } @@ -1241,33 +1265,6 @@ protected function save_variations( $id, $data ) { return true; } - /** - * Save product SKU. - * - * @version 2.2 - * @param int $id - * @param string $sku - * @return bool|WP_Error - */ - private function save_product_sku( $id, $sku ) { - $sku_found = $wpdb->get_var( $wpdb->prepare( " - SELECT $wpdb->posts.ID - FROM $wpdb->posts - LEFT JOIN $wpdb->postmeta ON ($wpdb->posts.ID = $wpdb->postmeta.post_id) - WHERE $wpdb->posts.post_type = 'product' - AND $wpdb->posts.post_status = 'publish' - AND $wpdb->postmeta.meta_key = '_sku' AND $wpdb->postmeta.meta_value = '%s' - AND $wpdb->posts.ID <> %s - ", wc_clean( $sku, $id ) ) ); - - if ( $sku_found ) { - return new WP_Error( 'woocommerce_api_product_sku_already_exists', __( 'The SKU already exists on another product' ), array( 'status' => 400 ) ); - } - - update_post_meta( $id, '_sku', wc_clean( $sku ) ); - return true; - } - /** * Save product shipping data * diff --git a/includes/wc-product-functions.php b/includes/wc-product-functions.php index 6187747f1dfef..0066944d32361 100644 --- a/includes/wc-product-functions.php +++ b/includes/wc-product-functions.php @@ -29,7 +29,7 @@ function get_product( $the_product = false, $args = array() ) { */ function wc_update_product_stock( $product_id, $new_stock_level ) { $product = get_product( $product_id ); - + if ( $product->get_stock_quantity() !== $new_stock_level ) { $product->set_stock( $new_stock_level ); } @@ -206,55 +206,55 @@ function wc_get_featured_product_ids() { * @return string */ function wc_product_post_type_link( $permalink, $post ) { - // Abort if post is not a product - if ( $post->post_type !== 'product' ) - return $permalink; - - // Abort early if the placeholder rewrite tag isn't in the generated URL - if ( false === strpos( $permalink, '%' ) ) - return $permalink; - - // Get the custom taxonomy terms in use by this post - $terms = get_the_terms( $post->ID, 'product_cat' ); - - if ( empty( $terms ) ) { - // If no terms are assigned to this post, use a string instead (can't leave the placeholder there) - $product_cat = _x( 'uncategorized', 'slug', 'woocommerce' ); - } else { - // Replace the placeholder rewrite tag with the first term's slug - $first_term = array_shift( $terms ); - $product_cat = $first_term->slug; - } - - $find = array( - '%year%', - '%monthnum%', - '%day%', - '%hour%', - '%minute%', - '%second%', - '%post_id%', - '%category%', - '%product_cat%' - ); - - $replace = array( - date_i18n( 'Y', strtotime( $post->post_date ) ), - date_i18n( 'm', strtotime( $post->post_date ) ), - date_i18n( 'd', strtotime( $post->post_date ) ), - date_i18n( 'H', strtotime( $post->post_date ) ), - date_i18n( 'i', strtotime( $post->post_date ) ), - date_i18n( 's', strtotime( $post->post_date ) ), - $post->ID, - $product_cat, - $product_cat - ); - - $replace = array_map( 'sanitize_title', $replace ); - - $permalink = str_replace( $find, $replace, $permalink ); - - return $permalink; + // Abort if post is not a product + if ( $post->post_type !== 'product' ) + return $permalink; + + // Abort early if the placeholder rewrite tag isn't in the generated URL + if ( false === strpos( $permalink, '%' ) ) + return $permalink; + + // Get the custom taxonomy terms in use by this post + $terms = get_the_terms( $post->ID, 'product_cat' ); + + if ( empty( $terms ) ) { + // If no terms are assigned to this post, use a string instead (can't leave the placeholder there) + $product_cat = _x( 'uncategorized', 'slug', 'woocommerce' ); + } else { + // Replace the placeholder rewrite tag with the first term's slug + $first_term = array_shift( $terms ); + $product_cat = $first_term->slug; + } + + $find = array( + '%year%', + '%monthnum%', + '%day%', + '%hour%', + '%minute%', + '%second%', + '%post_id%', + '%category%', + '%product_cat%' + ); + + $replace = array( + date_i18n( 'Y', strtotime( $post->post_date ) ), + date_i18n( 'm', strtotime( $post->post_date ) ), + date_i18n( 'd', strtotime( $post->post_date ) ), + date_i18n( 'H', strtotime( $post->post_date ) ), + date_i18n( 'i', strtotime( $post->post_date ) ), + date_i18n( 's', strtotime( $post->post_date ) ), + $post->ID, + $product_cat, + $product_cat + ); + + $replace = array_map( 'sanitize_title', $replace ); + + $permalink = str_replace( $find, $replace, $permalink ); + + return $permalink; } add_filter( 'post_type_link', 'wc_product_post_type_link', 10, 2 ); @@ -307,11 +307,11 @@ function wc_get_formatted_variation( $variation, $flat = false ) { } // If this is a term slug, get the term's nice name - if ( taxonomy_exists( esc_attr( str_replace( 'attribute_', '', $name ) ) ) ) { - $term = get_term_by( 'slug', $value, esc_attr( str_replace( 'attribute_', '', $name ) ) ); - if ( ! is_wp_error( $term ) && $term->name ) - $value = $term->name; - } + if ( taxonomy_exists( esc_attr( str_replace( 'attribute_', '', $name ) ) ) ) { + $term = get_term_by( 'slug', $value, esc_attr( str_replace( 'attribute_', '', $name ) ) ); + if ( ! is_wp_error( $term ) && $term->name ) + $value = $term->name; + } if ( $flat ) { $variation_list[] = wc_attribute_label( str_replace( 'attribute_', '', $name ) ) . ': ' . urldecode( $value ); @@ -507,3 +507,31 @@ function wc_get_product_types() { 'variable' => __( 'Variable product', 'woocommerce' ) ) ); } + +/** + * Check if product sku is unique. + * + * @since 2.2 + * @param int $product_id + * @param string $sku + * @return bool + */ +function wp_product_has_unique_sku( $product_id, $sku ) { + global $wpdb; + + $sku_found = $wpdb->get_var( $wpdb->prepare( " + SELECT $wpdb->posts.ID + FROM $wpdb->posts + LEFT JOIN $wpdb->postmeta ON ( $wpdb->posts.ID = $wpdb->postmeta.post_id ) + WHERE $wpdb->posts.post_type IN ( 'product', 'product_variation' ) + AND $wpdb->posts.post_status = 'publish' + AND $wpdb->postmeta.meta_key = '_sku' AND $wpdb->postmeta.meta_value = '%s' + AND $wpdb->postmeta.post_id <> %d LIMIT 1 + ", $sku, $product_id ) ); + + if ( $sku_found ) { + return false; + } else { + return true; + } +}