Created
February 17, 2015 16:20
-
-
Save joshcanhelp/8a2197913b62e69906db to your computer and use it in GitHub Desktop.
This script is used to migrate a transaction export from ejunkie into a Woocommerce-powered site. Please read the comments throughout to adjust this to your use case.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Class EjunkieWpCli | |
* | |
* This class adds an 'ejunkie' command to wp-cli with a 'migrate' action | |
* This works for simple products, variations, and the Woocommerce API Manager | |
* TODO: Look for lines marked as "TODO" to change this script for your use case | |
*/ | |
final class EjunkieWpCli extends WP_CLI_Command { | |
public function migrate ( $args = array(), $assoc_args = array() ) { | |
global $wpdb; | |
WP_CLI::line( 'Processing ... ' ); | |
// TODO: change this to the table name holding your ejunkie data | |
$query = 'SELECT * FROM `ejunkie_migrate`'; | |
// Add '--id=INT' to your command to only import a record with a specific id number | |
if ( ! empty( $assoc_args['id'] ) ) { | |
$query .= ' WHERE `id` = ' . intval( $assoc_args['id'] ); | |
} | |
// Get all the transactions and iterate through | |
$all_txns = $wpdb->get_results( $query ); | |
foreach ( $all_txns as $txn ) { | |
// This script stores the WP order number in the migration table and skips records that have one | |
// Comment out the 4 lines below to re-import orders that exist | |
if ( ! empty( $txn->wp_order_id ) ) { | |
WP_CLI::line( 'Order already exists for ' . $txn->email . ': ' . $txn->wp_order_id ); | |
continue; | |
} | |
// User to use for this order | |
$user = array(); | |
// Find user, returns false if none | |
$existing_user = get_user_by( 'email', $txn->email ); | |
if ( $existing_user ) { | |
// User found, store the ID | |
$user['id'] = $existing_user->ID; | |
WP_CLI::line( 'Found user for ' . $txn->email . ': ' . $user['id'] ); | |
} else { | |
// User not found, create one | |
// Make sure to remind users that they'll need to reset their password | |
$user['id'] = wp_insert_user( array( | |
'user_login' => $txn->email, | |
'user_email' => $txn->email, | |
'display_name' => $txn->first_name . ' ' . $txn->last_name, | |
'first_name' => $txn->first_name, | |
'last_name' => $txn->last_name, | |
'user_pass' => wp_generate_password( 12, TRUE, TRUE ), | |
) ); | |
if ( ! is_wp_error( $user['id'] ) ) { | |
WP_CLI::line( 'Created user for ' . $txn->email . ': ' . $user['id'] ); | |
} else { | |
// There was a problem creating the user, notice in the CLI, skip to next record | |
WP_CLI::line( 'SKIPPED: Could not create user for ' . $txn->email ); | |
continue; | |
} | |
} | |
// Show that the user was migrated from e-junkie | |
update_user_meta( $user['id'], '_from_ejunkie', 1 ); | |
// Determine product for this order | |
// TODO: Update the switch statement below to map ejunkie items to Woocommerce ones | |
// TODO: The product_id is required and the variation_id is only used for variable products | |
$product_id = 0; | |
$variation_id = ''; | |
switch ( $txn->item_number ) { | |
case 'WPD01': | |
$product_id = 31; | |
$variation_id = 1834; | |
break; | |
case 'WPD02': | |
$product_id = 31; | |
$variation_id = 1835; | |
break; | |
case 'WPWB01': | |
$product_id = 1839; | |
break; | |
// For products that do not need to be migrated | |
default: | |
continue; | |
} | |
// Get the product | |
$product = new WC_Product( $product_id ); | |
if ( ! $product ) { | |
// Could not find a product, notice in the CLI, skip to next record | |
WP_CLI::line( 'SKIPPED: Product could not be found: ' . $product_id ); | |
continue; | |
} | |
// Previous order data | |
$unique_id = uniqid(); | |
$date_timecode = strtotime( $txn->purchase_date_time ); | |
// Is this an active license? | |
// Everything after 1/1/2014 is active | |
// TODO: This is for downloadable and API products to set the activation date | |
// TODO: Remove this line and subsequent references if you are not importing this ype of product | |
$license_active = $date_timecode > 1388563200 ? TRUE : FALSE; | |
// Standard order data pulled from the WooCommerce order creation process | |
// TODO: It's a good idea to check that this is still valid since it might change a bit over time | |
$order_data = array( | |
'post_name' => 'order-' . date( 'M-d-Y-hi-a', $date_timecode ), | |
'post_type' => 'shop_order', | |
'post_title' => sprintf( | |
__( 'Order – %s', 'woocommerce' ), | |
strftime( _x( '%b %d, %Y @ %I:%M %p', 'Order date parsed by strftime', 'woocommerce' ) ) | |
), | |
// TODO: If there is processing that needs to happen on order completion, set this to 'wc-pending' | |
// TODO: If this is just pulling in data with no actions needed, set to 'wc-completed' | |
'post_status' => $license_active? 'wc-pending' : 'wc-completed', | |
'ping_status' => 'closed', | |
'post_author' => 1, | |
'post_password' => 'order_' . $unique_id, | |
'post_date' => $txn->purchase_date_time, | |
'comment_status' => 'closed' | |
); | |
// Create the order | |
$order_id = wp_insert_post( $order_data, TRUE ); | |
if ( is_wp_error( $order_id ) ) { | |
// Something happened, notice in the CLI, skip to next record | |
WP_CLI::line( 'SKIPPED: Could not create order for ' . $txn->email ); | |
continue; | |
} else { | |
WP_CLI::success( 'Created order: ' . $order_id ); | |
// Prepare data | |
$original_price = intval( $txn->amount ); | |
$price = wc_format_decimal( $original_price ); | |
// Core Woo data | |
add_post_meta( $order_id, 'transaction_id', $txn->transaction_id, TRUE ); | |
add_post_meta( $order_id, 'Payer first name', $txn->first_name, TRUE ); | |
add_post_meta( $order_id, 'Payer last name', $txn->last_name, TRUE ); | |
add_post_meta( $order_id, 'Payer PayPal address', $txn->email, TRUE ); | |
add_post_meta( $order_id, 'Payment type', 'instant', TRUE ); | |
add_post_meta( $order_id, '_billing_first_name', $txn->first_name, TRUE ); | |
add_post_meta( $order_id, '_billing_last_name', $txn->last_name, TRUE ); | |
add_post_meta( $order_id, '_billing_email', $txn->email, TRUE ); | |
add_post_meta( $order_id, '_billing_country', trim( $txn->payment_country ), TRUE ); | |
add_post_meta( $order_id, '_cart_discount', 0, TRUE ); | |
add_post_meta( $order_id, '_completed_date', $txn->purchase_date_time, TRUE ); | |
add_post_meta( $order_id, '_customer_ip_address', $txn->payer_ip, TRUE ); | |
add_post_meta( $order_id, '_customer_user', $user['id'], TRUE ); | |
add_post_meta( $order_id, '_order_currency', $txn->currency, TRUE ); | |
add_post_meta( $order_id, '_order_key', 'wc_order_' . apply_filters( | |
'woocommerce_generate_order_key', $unique_id | |
), TRUE ); | |
add_post_meta( $order_id, '_order_total', $price, TRUE ); | |
add_post_meta( $order_id, '_paid_date', $txn->purchase_date_time, TRUE ); | |
add_post_meta( $order_id, '_payment_method', $txn->purchase_date_time, TRUE ); | |
add_post_meta( $order_id, '_payment_method_title', $txn->payment_processor, TRUE ); | |
add_post_meta( $order_id, '_prices_include_tax', | |
get_option( 'woocommerce_prices_include_tax' ), TRUE ); | |
// Discounted orders | |
// TODO: this relies on existing product prices to determine whether a discount was applied | |
// TODO: If this is not relevant, delete of comment out the next 11 lines | |
$order_discount = 0; | |
$retail_price = get_post_meta( $variation_id ? $variation_id : $product_id, '_regular_price', TRUE ); | |
if ( $txn->item_number === 'WPD01' ) { | |
if ( ! in_array( $original_price, array( 39, 49, 69, 79 ) ) ) { | |
$order_discount = $retail_price - $original_price; | |
} | |
} else if ( $txn->item_number === 'WPD02' ) { | |
if ( ! in_array( $original_price, array( 149, 249, 279 ) ) ) { | |
$order_discount = $retail_price - $original_price; | |
} | |
} | |
add_post_meta( $order_id, '_order_discount', $order_discount, TRUE ); | |
// Additional e-junkie data | |
// TODO: Not required for WooCommerce, these meta keys can be whatever you'd like or skipped | |
add_post_meta( $order_id, '_ejunkie_migrate', 1, TRUE ); | |
add_post_meta( $order_id, '_ejunkie_txn_id', $txn->ejunkie_txn_id, TRUE ); | |
add_post_meta( $order_id, '_ejunkie_invoice_id', $txn->invoice_id, TRUE ); | |
add_post_meta( $order_id, '_ejunkie_affiliate_email', $txn->affiliate_email, TRUE ); | |
add_post_meta( $order_id, '_ejunkie_affiliate_name', $txn->affiliate_name, TRUE ); | |
add_post_meta( $order_id, '_ejunkie_affiliate_id', $txn->affiliate_id, TRUE ); | |
add_post_meta( $order_id, '_ejunkie_affiliate_share', $txn->affiliate_share, TRUE ); | |
// Add an order note with additional ejunkie information | |
$data = array( | |
'comment_post_ID' => $order_id, | |
'comment_author' => 'Josh Cunningham', | |
'comment_author_email' => 'hi@theproperweb.com', | |
'comment_content' => sprintf( | |
'Download info: %s | Billing info: %s', | |
$txn->download_info, | |
$txn->billing_info | |
), | |
'comment_type' => 'order_note', | |
'comment_parent' => 0, | |
'user_id' => 0, | |
'comment_date' => current_time( 'mysql' ), | |
'comment_approved' => 1, | |
'comment_agent' => 'WooCommerce', | |
); | |
wp_insert_comment( $data ); | |
// Add line item | |
$item_id = wc_add_order_item( $order_id, array( | |
'order_item_name' => $product->get_title(), | |
'order_item_type' => 'line_item' | |
) ); | |
// Add an item ID | |
if ( $item_id ) { | |
// Core Woo item meta | |
wc_add_order_item_meta( $item_id, '_qty', 1 ); | |
wc_add_order_item_meta( $item_id, '_tax_class', '' ); | |
wc_add_order_item_meta( $item_id, '_product_id', $product->id ); | |
wc_add_order_item_meta( $item_id, '_variation_id', $variation_id ); | |
wc_add_order_item_meta( $item_id, '_line_subtotal', $price ); | |
wc_add_order_item_meta( $item_id, '_line_total', $price ); | |
wc_add_order_item_meta( $item_id, '_line_tax', wc_format_decimal( 0 ) ); | |
wc_add_order_item_meta( $item_id, '_line_subtotal_tax', wc_format_decimal( 0 ) ); | |
// TODO: Adjust if your products have special attributes or remove if not | |
wc_add_order_item_meta( $item_id, 'license', $txn->item_number === 'WPD02' ? | |
'Developer License' : 'Single Site License' ); | |
} | |
// Set order status as completed | |
// TODO: This will run all hooks tied to the order completed process, including notification emails | |
// TODO: Be careful running this as the standard notification email looks like a new order charge | |
// TODO: Functions for changing the email format are at the bottom of this script | |
if ( $license_active ) { | |
add_filter( 'woocommerce_email_heading_customer_completed_order', 'ejunkie_email_header', 999 ); | |
add_action( 'woocommerce_email_before_order_table', 'ejunkie_intro_text', 0 ); | |
$order = wc_get_order( $order_id ); | |
$order->update_status( 'completed' ); | |
remove_filter( 'woocommerce_email_heading_customer_completed_order', 'ejunkie_email_header', 999 ); | |
remove_action( 'woocommerce_email_before_order_table', 'ejunkie_intro_text', 0 ); | |
} | |
// Update migrate table | |
$wpdb->update( | |
'ejunkie_migrate', | |
array( 'wp_order_id' => $order_id ), | |
array( 'id' => $txn->id ), | |
'%d' | |
); | |
} | |
} | |
WP_CLI::success( 'Success!' ); | |
} | |
} | |
WP_CLI::add_command( 'ejunkie', 'EjunkieWpCli' ); | |
function ejunkie_email_header () { | |
// Add text here to show up in the email header | |
} | |
function ejunkie_intro_text () { | |
// Add text here to appear at the top of the email sent out when the order is created | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
You'll need to create a new table and import your ejunkie data before running this. Table syntax is below, a few things to keep in mind: