Skip to content

Instantly share code, notes, and snippets.

@janhocevar
Created October 2, 2017 21:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save janhocevar/a84ba7fd10ff5f5f11a9fb669501ddca to your computer and use it in GitHub Desktop.
Save janhocevar/a84ba7fd10ff5f5f11a9fb669501ddca to your computer and use it in GitHub Desktop.
Duplicate woocommerce order with custom meta data
<?php
/**
* Duplicate order functionality
*
* @author Jan Hocevar
* @category Admin
* @package WooCommerce/Admin
* @version 1.0.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
if ( ! class_exists( 'WC_Admin_Duplicate_Order' ) ) :
/**
* WC_Admin_Duplicate_Order Class.
*/
class WC_Admin_Duplicate_Order {
/**
* Constructor.
*/
public function __construct() {
add_action( 'admin_action_duplicate_order', array( $this, 'duplicate_order_action' ) );
add_filter( 'post_row_actions', array( $this, 'dupe_link' ), 10, 2 );
add_filter( 'page_row_actions', array( $this, 'dupe_link' ), 10, 2 );
add_action( 'post_submitbox_start', array( $this, 'dupe_button' ) );
}
/**
* Show the "Duplicate" link in admin orders list.
* @param array $actions
* @param WP_Post $post Post object
* @return array
*/
public function dupe_link( $actions, $post ) {
if ( ! current_user_can( apply_filters( 'woocommerce_duplicate_product_capability', 'manage_woocommerce' ) ) ) {
return $actions;
}
if ( $post->post_type != 'shop_order' ) {
return $actions;
}
$actions['duplicate'] = '<a href="' . wp_nonce_url( admin_url( 'edit.php?post_type=shop_order&action=duplicate_order&amp;post=' . $post->ID ), 'woocommerce-duplicate-order_' . $post->ID ) . '" title="' . esc_attr__( 'Make a duplicate from this order', 'woocommerce' )
. '" rel="permalink">' . __( 'Duplicate', 'woocommerce' ) . '</a>';
return $actions;
}
/**
* Show the dupe order link in admin.
*/
public function dupe_button() {
global $post;
if ( ! current_user_can( apply_filters( 'woocommerce_duplicate_product_capability', 'manage_woocommerce' ) ) ) {
return;
}
if ( ! is_object( $post ) ) {
return;
}
if ( $post->post_type != 'shop_order' ) {
return;
}
if ( isset( $_GET['post'] ) ) {
$notifyUrl = wp_nonce_url( admin_url( "edit.php?post_type=shop_order&action=duplicate_order&post=" . absint( $_GET['post'] ) ), 'woocommerce-duplicate-order_' . $_GET['post'] );
?>
<div id="duplicate-action"><a class="submitduplicate duplication" href="<?php echo esc_url( $notifyUrl ); ?>"><?php _e( 'Copy to a new draft', 'woocommerce' ); ?></a></div>
<?php
}
}
/**
* Duplicate a order action.
*/
public function duplicate_order_action() {
if ( empty( $_REQUEST['post'] ) ) {
wp_die( __( 'No order to duplicate has been supplied!', 'woocommerce' ) );
}
// Get the original page
$id = isset( $_REQUEST['post'] ) ? absint( $_REQUEST['post'] ) : '';
check_admin_referer( 'woocommerce-duplicate-order_' . $id );
$post = wc_get_order( $id );
// Copy the page and insert it
if ( ! empty( $post ) ) {
$new_id = $this->duplicate_order( $post );
do_action( 'woocommerce_duplicate_order', $new_id, $post );
wp_redirect( admin_url( 'post.php?action=edit&post=' . $new_id ) );
exit;
} else {
wp_die( __( 'Order creation failed, could not find original order:', 'woocommerce' ) . ' ' . $id );
}
}
/**
* Function to create the duplicate of the order.
*
* @param mixed $post
* @return int
*/
public function duplicate_order( $post ) {
global $wpdb;
$original_order_id = $post->id;
$original_order = $post;
$order_id = $this->create_order($original_order_id);
if ( is_wp_error( $order_id ) ){
$msg = 'Unable to create order: ' . $order_id->get_error_message();;
throw new Exception( $msg );
} else {
$order = new WC_Order($order_id);
$this->duplicate_order_header($original_order_id, $order_id);
$this->duplicate_billing_fieds($original_order_id, $order_id);
$this->duplicate_shipping_fieds($original_order_id, $order_id);
$this->duplicate_line_items($original_order, $order_id);
$this->duplicate_shipping_items($original_order, $order_id);
$this->duplicate_coupons($original_order, $order_id);
$this->duplicate_payment_info($original_order_id, $order_id, $order);
$order->calculate_taxes();
$this->add_order_note($original_order_id, $order);
return $order_id;
}
}
private function create_order($original_order_id) {
$new_post_author = wp_get_current_user();
$new_post_date = current_time( 'mysql' );
$new_post_date_gmt = get_gmt_from_date( $new_post_date );
$order_data = array(
'post_author' => $new_post_author->ID,
'post_date' => $new_post_date,
'post_date_gmt' => $new_post_date_gmt,
'post_type' => 'shop_order',
'post_title' => __( 'Duplicate Order', 'woocommerce' ),
'post_status' => 'wc-processing',
'ping_status' => 'closed',
'post_password' => uniqid( 'order_' ), // Protects the post just in case
'post_modified' => $new_post_date,
'post_modified_gmt' => $new_post_date_gmt
);
$new_post_id = wp_insert_post( $order_data, true );
return $new_post_id;
}
private function duplicate_order_header($original_order_id, $order_id) {
update_post_meta( $order_id, '_order_shipping', get_post_meta($original_order_id, '_order_shipping', true) );
update_post_meta( $order_id, '_order_discount', get_post_meta($original_order_id, '_order_discount', true) );
update_post_meta( $order_id, '_cart_discount', get_post_meta($original_order_id, '_cart_discount', true) );
update_post_meta( $order_id, '_order_tax', get_post_meta($original_order_id, '_order_tax', true) );
update_post_meta( $order_id, '_order_shipping_tax', get_post_meta($original_order_id, '_order_shipping_tax', true) );
update_post_meta( $order_id, '_order_total', get_post_meta($original_order_id, '_order_total', true) );
update_post_meta( $order_id, '_order_key', 'wc_' . apply_filters('woocommerce_generate_order_key', uniqid('order_') ) );
update_post_meta( $order_id, '_customer_user', get_post_meta($original_order_id, '_customer_user', true) );
update_post_meta( $order_id, '_order_currency', get_post_meta($original_order_id, '_order_currency', true) );
update_post_meta( $order_id, '_prices_include_tax', get_post_meta($original_order_id, '_prices_include_tax', true) );
update_post_meta( $order_id, '_customer_ip_address', get_post_meta($original_order_id, '_customer_ip_address', true) );
update_post_meta( $order_id, '_customer_user_agent', get_post_meta($original_order_id, '_customer_user_agent', true) );
}
private function duplicate_billing_fieds($original_order_id, $order_id) {
update_post_meta( $order_id, '_billing_city', get_post_meta($original_order_id, '_billing_city', true));
update_post_meta( $order_id, '_billing_state', get_post_meta($original_order_id, '_billing_state', true));
update_post_meta( $order_id, '_billing_postcode', get_post_meta($original_order_id, '_billing_postcode', true));
update_post_meta( $order_id, '_billing_email', get_post_meta($original_order_id, '_billing_email', true));
update_post_meta( $order_id, '_billing_phone', get_post_meta($original_order_id, '_billing_phone', true));
update_post_meta( $order_id, '_billing_address_1', get_post_meta($original_order_id, '_billing_address_1', true));
update_post_meta( $order_id, '_billing_address_2', get_post_meta($original_order_id, '_billing_address_2', true));
update_post_meta( $order_id, '_billing_country', get_post_meta($original_order_id, '_billing_country', true));
update_post_meta( $order_id, '_billing_first_name', get_post_meta($original_order_id, '_billing_first_name', true));
update_post_meta( $order_id, '_billing_last_name', get_post_meta($original_order_id, '_billing_last_name', true));
update_post_meta( $order_id, '_billing_company', get_post_meta($original_order_id, '_billing_company', true));
}
private function duplicate_shipping_fieds($original_order_id, $order_id) {
update_post_meta( $order_id, '_shipping_country', get_post_meta($original_order_id, '_shipping_country', true));
update_post_meta( $order_id, '_shipping_first_name', get_post_meta($original_order_id, '_shipping_first_name', true));
update_post_meta( $order_id, '_shipping_last_name', get_post_meta($original_order_id, '_shipping_last_name', true));
update_post_meta( $order_id, '_shipping_company', get_post_meta($original_order_id, '_shipping_company', true));
update_post_meta( $order_id, '_shipping_address_1', get_post_meta($original_order_id, '_shipping_address_1', true));
update_post_meta( $order_id, '_shipping_address_2', get_post_meta($original_order_id, '_shipping_address_2', true));
update_post_meta( $order_id, '_shipping_city', get_post_meta($original_order_id, '_shipping_city', true));
update_post_meta( $order_id, '_shipping_state', get_post_meta($original_order_id, '_shipping_state', true));
update_post_meta( $order_id, '_shipping_postcode', get_post_meta($original_order_id, '_shipping_postcode', true));
}
private function duplicate_line_items($original_order, $order_id) {
foreach($original_order->get_items() as $originalOrderItem){
$itemName = $originalOrderItem['name'];
$qty = $originalOrderItem['qty'];
$lineTotal = $originalOrderItem['line_total'];
$lineTax = $originalOrderItem['line_tax'];
$productID = $originalOrderItem['product_id'];
$item_id = wc_add_order_item( $order_id, array(
'order_item_name' => $itemName,
'order_item_type' => 'line_item'
) );
wc_add_order_item_meta( $item_id, '_qty', $qty );
wc_add_order_item_meta( $item_id, '_tax_class', $originalOrderItem['tax_class'] );
wc_add_order_item_meta( $item_id, '_product_id', $productID );
wc_add_order_item_meta( $item_id, '_line_subtotal', wc_format_decimal( $lineTotal ) );
wc_add_order_item_meta( $item_id, '_line_total', wc_format_decimal( $lineTotal ) );
wc_add_order_item_meta( $item_id, '_line_tax', wc_format_decimal( $lineTax ) );
wc_add_order_item_meta( $item_id, '_line_subtotal_tax', wc_format_decimal( $originalOrderItem['line_subtotal_tax'] ) );
foreach ( $originalOrderItem['item_meta'] as $meta_name => $meta_value ) {
if ( taxonomy_is_product_attribute( $meta_name ) ) {
wc_add_order_item_meta( $item_id, $meta_name, $meta_value );
} elseif ( meta_is_product_attribute( $meta_name, $meta_value, $product_id ) ) {
wc_add_order_item_meta( $item_id, $meta_name, $meta_value );
}
}
}
}
private function duplicate_shipping_items($original_order, $order_id) {
$original_order_shipping_items = $original_order->get_items('shipping');
foreach ( $original_order_shipping_items as $original_order_shipping_item ) {
$item_id = wc_add_order_item( $order_id, array(
'order_item_name' => $original_order_shipping_item['name'],
'order_item_type' => 'shipping'
) );
if ( $item_id ) {
wc_add_order_item_meta( $item_id, 'method_id', $original_order_shipping_item['method_id'] );
wc_add_order_item_meta( $item_id, 'cost', wc_format_decimal( $original_order_shipping_item['cost'] ) );
}
}
}
private function duplicate_coupons($original_order, $order_id) {
$original_order_coupons = $original_order->get_items('coupon');
foreach ( $original_order_coupons as $original_order_coupon ) {
$item_id = wc_add_order_item( $order_id, array(
'order_item_name' => $original_order_coupon['name'],
'order_item_type' => 'coupon'
) );
if ( $item_id ) {
wc_add_order_item_meta( $item_id, 'discount_amount', $original_order_coupon['discount_amount'] );
}
}
}
private function duplicate_payment_info($original_order_id, $order_id, $order) {
update_post_meta( $order_id, '_payment_method', get_post_meta($original_order_id, '_payment_method', true) );
update_post_meta( $order_id, '_payment_method_title', get_post_meta($original_order_id, '_payment_method_title', true) );
}
private function add_order_note($original_order_id, $order) {
$updateNote = 'This order was duplicated from order ' . $original_order_id . '.';
$order->add_order_note($updateNote);
}
}
endif;
return new WC_Admin_Duplicate_Order();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment