Skip to content

Instantly share code, notes, and snippets.

@joshcanhelp
Created February 17, 2015 16:20
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 joshcanhelp/8a2197913b62e69906db to your computer and use it in GitHub Desktop.
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.
<?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
}
@joshcanhelp
Copy link
Author

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:

  • You'll export from the ejunkie transaction report as CSV. Open that in Excel or similar, then change the headers to match the database table
  • Note that a few unused columns have been removed
  • Make sure to format the date for MySQL, in Excel the custom format is 'yyyy-mm-dd hh:mm:ss'
CREATE TABLE `ejunkie_migrate` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `purchase_date_time` datetime NOT NULL,
  `transaction_id` tinytext NOT NULL,
  `payment_processor` tinytext NOT NULL,
  `ejunkie_txn_id` tinytext NOT NULL,
  `payment_status` tinytext NOT NULL,
  `first_name` tinytext NOT NULL,
  `last_name` tinytext NOT NULL,
  `email` tinytext NOT NULL,
  `billing_info` tinytext,
  `payer_ip` tinytext NOT NULL,
  `invoice_id` tinytext NOT NULL,
  `affiliate_email` tinytext,
  `affiliate_name` tinytext,
  `affiliate_id` int(20) DEFAULT NULL,
  `currency` tinytext NOT NULL,
  `item_name` tinytext NOT NULL,
  `item_number` tinytext NOT NULL,
  `quantity` int(3) NOT NULL,
  `amount` float NOT NULL,
  `affiliate_share` float NOT NULL DEFAULT '0',
  `download_info` tinytext,
  `payment_country` tinytext NOT NULL,
  `wp_order_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment