diff --git a/includes/admin/class-wc-admin-duplicate-product.php b/includes/admin/class-wc-admin-duplicate-product.php index 430dbc681b9..d27d215cbbc 100644 --- a/includes/admin/class-wc-admin-duplicate-product.php +++ b/includes/admin/class-wc-admin-duplicate-product.php @@ -1,17 +1,17 @@ get_product_to_duplicate( $id ); + $product = wc_get_product( $product_id ); - // Copy the page and insert it - if ( ! empty( $post ) ) { - $new_id = $this->duplicate_product( $post ); - - // If you have written a plugin which uses non-WP database tables to save - // information about a page you can hook this action to dupe that data. - do_action( 'woocommerce_duplicate_product', $new_id, $post ); - - // Redirect to the edit screen for the new draft page - wp_redirect( admin_url( 'post.php?action=edit&post=' . $new_id ) ); - exit; - } else { + if ( false === $product ) { /* translators: %s: product id */ - wp_die( sprintf( __( 'Product creation failed, could not find original product: %s', 'woocommerce' ), $id ) ); - } - } - - /** - * Function to create the duplicate of the product. - * - * @param mixed $post - * @param int $parent (default: 0) - * @param string $post_status (default: '') - * @return int - */ - public function duplicate_product( $post, $parent = 0, $post_status = '' ) { - global $wpdb; - - $new_post_author = wp_get_current_user(); - $new_post_date = current_time( 'mysql' ); - $new_post_date_gmt = get_gmt_from_date( $new_post_date ); - - if ( $parent > 0 ) { - $post_parent = $parent; - $post_status = $post_status ? $post_status: 'publish'; - $suffix = ''; - $post_title = $post->post_title; - } else { - $post_parent = $post->post_parent; - $post_status = $post_status ? $post_status: 'draft'; - $suffix = ' ' . __( '(Copy)', 'woocommerce' ); - $post_title = $post->post_title . $suffix; + wp_die( sprintf( __( 'Product creation failed, could not find original product: %s', 'woocommerce' ), $product_id ) ); } - // Insert the new template in the post table - $wpdb->insert( - $wpdb->posts, - array( - 'post_author' => $new_post_author->ID, - 'post_date' => $new_post_date, - 'post_date_gmt' => $new_post_date_gmt, - 'post_content' => $post->post_content, - 'post_content_filtered' => $post->post_content_filtered, - 'post_title' => $post_title, - 'post_excerpt' => $post->post_excerpt, - 'post_status' => $post_status, - 'post_type' => $post->post_type, - 'comment_status' => $post->comment_status, - 'ping_status' => $post->ping_status, - 'post_password' => $post->post_password, - 'to_ping' => $post->to_ping, - 'pinged' => $post->pinged, - 'post_modified' => $new_post_date, - 'post_modified_gmt' => $new_post_date_gmt, - 'post_parent' => $post_parent, - 'menu_order' => $post->menu_order, - 'post_mime_type' => $post->post_mime_type, - ) - ); + $duplicate = clone $product; + $duplicate->set_id( 0 ); + $duplicate->save(); - $new_post_id = $wpdb->insert_id; - - // Set title for variations - if ( 'product_variation' === $post->post_type ) { - /* translators: 1: variation id 2: product name */ - $post_title = sprintf( __( 'Variation #%1$s of %2$s', 'woocommerce' ), absint( $new_post_id ), esc_html( get_the_title( $post_parent ) ) ); - $wpdb->update( - $wpdb->posts, - array( - 'post_title' => $post_title, - ), - array( - 'ID' => $new_post_id, - ) - ); + $sku = $duplicate->get_sku(); + if ( '' !== $duplicate->get_sku() ) { + wc_product_force_unique_sku( $duplicate->get_id() ); } - // Set name and GUID - if ( ! in_array( $post_status, array( 'draft', 'pending', 'auto-draft' ) ) ) { - $wpdb->update( - $wpdb->posts, - array( - 'post_name' => wp_unique_post_slug( sanitize_title( $post_title, $new_post_id ), $new_post_id, $post_status, $post->post_type, $post_parent ), - 'guid' => get_permalink( $new_post_id ), - ), - array( - 'ID' => $new_post_id, - ) - ); - } - - // Copy the taxonomies - $this->duplicate_post_taxonomies( $post->ID, $new_post_id, $post->post_type ); - - // Copy the meta information - $this->duplicate_post_meta( $post->ID, $new_post_id ); - - // Copy the children (variations) - $exclude = apply_filters( 'woocommerce_duplicate_product_exclude_children', false ); - - if ( ! $exclude && ( $children_products = get_children( 'post_parent=' . $post->ID . '&post_type=product_variation' ) ) ) { - foreach ( $children_products as $child ) { - $this->duplicate_product( $this->get_product_to_duplicate( $child->ID ), $new_post_id, $child->post_status ); + if ( $product->is_type( 'variable' ) || $product->is_type( 'grouped' ) ) { + foreach( $product->get_children() as $child_id ) { + $child = wc_get_product( $child_id ); + $child_duplicate = clone $child; + $child_duplicate->set_parent_id( $duplicate->get_id() ); + $child_duplicate->set_id( 0 ); + $child_duplicate->save(); + if ( '' !== $child_duplicate->get_sku() ) { + wc_product_force_unique_sku( $child_duplicate->get_id() ); + } } } - // Clear cache - clean_post_cache( $new_post_id ); + // Hook rename to match other woocommerce_product_* hooks, and to move away from depending on a response from the wp_posts table. + // New hook returns new id and old id. + do_action( 'woocommerce_product_duplicate', $duplicate, $product ); + wc_do_deprecated_action( 'woocommerce_duplicate_product', array( $duplicate->get_id(), $this->get_product_to_duplicate( $product_id ) ), '2.7', 'Use woocommerce_product_duplicate action instead.' ); - return $new_post_id; + // Redirect to the edit screen for the new draft page + wp_redirect( admin_url( 'post.php?action=edit&post=' . $duplicate->get_id() ) ); + exit; } /** * Get a product from the database to duplicate. * + * @deprecated 2.7.0 * @param mixed $id * @return WP_Post|bool * @see duplicate_product @@ -238,58 +152,6 @@ class WC_Admin_Duplicate_Product { return $post[0]; } - - /** - * Copy the taxonomies of a post to another post. - * - * @param mixed $id - * @param mixed $new_id - * @param mixed $post_type - */ - private function duplicate_post_taxonomies( $id, $new_id, $post_type ) { - $exclude = array_filter( apply_filters( 'woocommerce_duplicate_product_exclude_taxonomies', array() ) ); - $taxonomies = array_diff( get_object_taxonomies( $post_type ), $exclude ); - - foreach ( $taxonomies as $taxonomy ) { - $post_terms = wc_get_object_terms( $id, $taxonomy ); - $post_terms_count = sizeof( $post_terms ); - - for ( $i = 0; $i < $post_terms_count; $i++ ) { - wp_set_object_terms( $new_id, (int) $post_terms[ $i ]->term_id, $taxonomy, true ); - } - } - } - - /** - * Copy the meta information of a post to another post. - * - * @param mixed $id - * @param mixed $new_id - */ - private function duplicate_post_meta( $id, $new_id ) { - global $wpdb; - - $sql = $wpdb->prepare( "SELECT meta_key, meta_value FROM $wpdb->postmeta WHERE post_id = %d", absint( $id ) ); - $exclude = array_map( 'esc_sql', array_filter( apply_filters( 'woocommerce_duplicate_product_exclude_meta', array( 'total_sales', '_wc_average_rating', '_wc_rating_count', '_wc_review_count', '_sku' ) ) ) ); - - if ( sizeof( $exclude ) ) { - $sql .= " AND meta_key NOT IN ( '" . implode( "','", $exclude ) . "' )"; - } - - $post_meta = $wpdb->get_results( $sql ); - - if ( sizeof( $post_meta ) ) { - $sql_query_sel = array(); - $sql_query = "INSERT INTO $wpdb->postmeta (post_id, meta_key, meta_value) "; - - foreach ( $post_meta as $post_meta_row ) { - $sql_query_sel[] = $wpdb->prepare( "SELECT %d, %s, %s", $new_id, $post_meta_row->meta_key, $post_meta_row->meta_value ); - } - - $sql_query .= implode( " UNION ALL ", $sql_query_sel ); - $wpdb->query( $sql_query ); - } - } } endif;