Skip to content
This repository was archived by the owner on Jun 15, 2022. It is now read-only.

Commit a230c15

Browse files
committed
Public beta release
0 parents  commit a230c15

8 files changed

+1152
-0
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/vendor
2+
composer.lock

composer.json

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{
2+
"name": "liquidweb/wc-custom-order-table",
3+
"description": "Store WooCommerce order data in a custom table.",
4+
"type": "wordpress-plugin",
5+
"license": "GPL-2.0",
6+
"require": {
7+
"composer/installers": "^1.4",
8+
"xrstf/composer-php52": "^1.0"
9+
},
10+
"autoload": {
11+
"classmap": ["includes"]
12+
},
13+
"scripts": {
14+
"post-install-cmd": [
15+
"xrstf\\Composer52\\Generator::onPostInstallCmd"
16+
],
17+
"post-update-cmd": [
18+
"xrstf\\Composer52\\Generator::onPostInstallCmd"
19+
],
20+
"post-autoload-dump": [
21+
"xrstf\\Composer52\\Generator::onPostInstallCmd"
22+
]
23+
}
24+
}
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
<?php
2+
3+
/**
4+
* CLI Tool for migrating order data to/from custom table.
5+
*
6+
* @version 1.0.0
7+
* @category Class
8+
*/
9+
class WC_Custom_Order_Table_CLI extends WP_CLI_Command
10+
{
11+
12+
private $count;
13+
14+
/**
15+
* Count how many orders have yet to be migrated.
16+
*
17+
* ## EXAMPLES
18+
*
19+
* wp wc-order-table count
20+
*
21+
*/
22+
public function count() {
23+
global $wpdb;
24+
25+
$order_table = wc_custom_order_table()->get_table_name();
26+
27+
$order_count = $wpdb->get_var( $wpdb->prepare("
28+
SELECT COUNT(1)
29+
FROM {$wpdb->posts} p
30+
LEFT JOIN {$order_table} o ON p.ID = o.order_id
31+
WHERE p.post_type IN ('%s')
32+
AND o.order_id IS NULL
33+
ORDER BY p.post_date DESC
34+
", implode(',', wc_get_order_types('reports'))));
35+
36+
WP_CLI::log( sprintf( __( '%d orders to be migrated.', 'wc-custom-order-table' ), $order_count ) );
37+
38+
return $order_count;
39+
}
40+
41+
/**
42+
* Migrate order data to the custom order table.
43+
*
44+
* ## OPTIONS
45+
*
46+
* [--batch=<batch>]
47+
* : The number of orders to process.
48+
* ---
49+
* default: 1000
50+
* ---
51+
*
52+
* [--page=<page>]
53+
* : The page to start from.
54+
* ---
55+
* default: 1
56+
* ---
57+
*
58+
* ## EXAMPLES
59+
*
60+
* wp wc-order-table migrate --batch=100 --page=1
61+
*
62+
*/
63+
public function migrate($args, $assoc_args)
64+
{
65+
global $wpdb;
66+
67+
$orders_batch = isset($assoc_args['batch']) ? absint($assoc_args['batch']) : 1000;
68+
$orders_page = isset($assoc_args['page']) ? absint($assoc_args['page']) : 1;
69+
70+
$order_table = wc_custom_order_table()->get_table_name();
71+
72+
$order_count = $this->count();
73+
74+
$total_pages = ceil($order_count / $orders_batch);
75+
76+
$progress = \WP_CLI\Utils\make_progress_bar('Order Data Migration', $order_count);
77+
78+
$orders_sql = $wpdb->prepare("
79+
SELECT ID FROM {$wpdb->posts}
80+
WHERE post_type IN ('%s')
81+
ORDER BY post_date DESC
82+
", implode(',', wc_get_order_types('reports')));
83+
$batches_processed = 0;
84+
85+
for ($page = $orders_page; $page <= $total_pages; $page++) {
86+
$offset = ($page * $orders_batch) - $orders_batch;
87+
$sql = $wpdb->prepare($orders_sql . ' LIMIT %d OFFSET %d', $orders_batch, max($offset, 0));
88+
$orders = $wpdb->get_col($sql);
89+
90+
foreach ($orders as $order) {
91+
// Accessing the order via wc_get_order will automatically migrate the order to the custom table.
92+
wc_get_order($order);
93+
94+
$progress->tick();
95+
}
96+
97+
$batches_processed++;
98+
}
99+
100+
$progress->finish();
101+
102+
WP_CLI::log(sprintf(__('%d orders processed in %d batches.', 'wc-custom-order-table'), $order_count, $batches_processed));
103+
}
104+
105+
/**
106+
* Backfill order meta data into postmeta.
107+
*
108+
* ## OPTIONS
109+
*
110+
* [--batch=<batch>]
111+
* : The number of orders to process.
112+
* ---
113+
* default: 1000
114+
* ---
115+
*
116+
* [--page=<page>]
117+
* : The page to start from.
118+
* ---
119+
* default: 1
120+
* ---
121+
*
122+
* ## EXAMPLES
123+
*
124+
* wp wc-order-table backfill --batch=100 --page=1
125+
*
126+
*/
127+
public function backfill($args, $assoc_args)
128+
{
129+
global $wpdb;
130+
131+
$orders_batch = isset($assoc_args['batch']) ? absint($assoc_args['batch']) : 1000;
132+
$orders_page = isset($assoc_args['page']) ? absint($assoc_args['page']) : 1;
133+
134+
$order_table = wc_custom_order_table()->get_table_name();
135+
136+
$order_count = $wpdb->get_var("SELECT COUNT(1) FROM {$order_table} o" );
137+
138+
WP_CLI::log( sprintf( __( '%d orders to be backfilled.', 'wc-custom-order-table' ), $order_count ) );
139+
140+
$total_pages = ceil($order_count / $orders_batch);
141+
142+
$progress = \WP_CLI\Utils\make_progress_bar('Order Data Migration', $order_count);
143+
144+
$orders_sql = "SELECT order_id FROM {$order_table} o";
145+
$batches_processed = 0;
146+
147+
for ($page = $orders_page; $page <= $total_pages; $page++) {
148+
$offset = ($page * $orders_batch) - $orders_batch;
149+
$sql = $wpdb->prepare($orders_sql . ' LIMIT %d OFFSET %d', $orders_batch, max($offset, 0));
150+
$orders = $wpdb->get_col($sql);
151+
152+
foreach ($orders as $order) {
153+
// Accessing the order via wc_get_order will automatically migrate the order to the custom table.
154+
$order = wc_get_order($order);
155+
$order->get_data_store()->backfill_postmeta( $order );
156+
157+
$progress->tick();
158+
}
159+
160+
$batches_processed++;
161+
}
162+
163+
$progress->finish();
164+
165+
WP_CLI::log(sprintf(__('%d orders processed in %d batches.', 'wc-custom-order-table'), $order_count, $batches_processed));
166+
}
167+
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
<?php
2+
3+
class WC_Custom_Order_Table_Install {
4+
protected $table_version = 1;
5+
6+
public function activate() {
7+
$this->maybe_install_tables();
8+
}
9+
10+
public function get_latest_table_version() {
11+
return absint( $this->table_version );
12+
}
13+
14+
public function get_installed_table_version() {
15+
return absint( get_option( 'wc_orders_table_version' ) );
16+
}
17+
18+
protected function maybe_install_tables() {
19+
if( $this->get_installed_table_version() < $this->get_latest_table_version() ) {
20+
$this->install_tables();
21+
}
22+
}
23+
24+
protected function install_tables() {
25+
global $wpdb;
26+
27+
require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
28+
29+
$collate = '';
30+
31+
if ( $wpdb->has_cap( 'collation' ) ) {
32+
$collate = $wpdb->get_charset_collate();
33+
}
34+
35+
$table = wc_custom_order_table()->get_table_name();
36+
37+
$tables = "
38+
CREATE TABLE {$table} (
39+
order_id BIGINT UNSIGNED NOT NULL,
40+
order_key varchar(100) NOT NULL,
41+
customer_id BIGINT UNSIGNED NOT NULL,
42+
billing_first_name varchar(100) NOT NULL,
43+
billing_last_name varchar(100) NOT NULL,
44+
billing_company varchar(100) NOT NULL,
45+
billing_address_1 varchar(200) NOT NULL,
46+
billing_address_2 varchar(200) NOT NULL,
47+
billing_city varchar(100) NOT NULL,
48+
billing_state varchar(100) NOT NULL,
49+
billing_postcode varchar(100) NOT NULL,
50+
billing_country varchar(100) NOT NULL,
51+
billing_email varchar(200) NOT NULL,
52+
billing_phone varchar(200) NOT NULL,
53+
shipping_first_name varchar(100) NOT NULL,
54+
shipping_last_name varchar(100) NOT NULL,
55+
shipping_company varchar(100) NOT NULL,
56+
shipping_address_1 varchar(200) NOT NULL,
57+
shipping_address_2 varchar(200) NOT NULL,
58+
shipping_city varchar(100) NOT NULL,
59+
shipping_state varchar(100) NOT NULL,
60+
shipping_postcode varchar(100) NOT NULL,
61+
shipping_country varchar(100) NOT NULL,
62+
payment_method varchar(100) NOT NULL,
63+
payment_method_title varchar(100) NOT NULL,
64+
65+
discount_total float NOT NULL DEFAULT 0,
66+
discount_tax float NOT NULL DEFAULT 0,
67+
shipping_total float NOT NULL DEFAULT 0,
68+
shipping_tax float NOT NULL DEFAULT 0,
69+
cart_tax float NOT NULL DEFAULT 0,
70+
total float NOT NULL DEFAULT 0,
71+
version varchar(16) NOT NULL,
72+
currency varchar(3) NOT NULL,
73+
prices_include_tax tinyint(1) NOT NULL,
74+
75+
transaction_id varchar(200) NOT NULL,
76+
customer_ip_address varchar(40) NOT NULL,
77+
customer_user_agent varchar(200) NOT NULL,
78+
created_via varchar(200) NOT NULL,
79+
date_completed datetime DEFAULT NULL,
80+
date_paid datetime DEFAULT NULL,
81+
cart_hash varchar(32) NOT NULL,
82+
83+
PRIMARY KEY (order_id)
84+
) $collate;
85+
";
86+
87+
dbDelta( $tables );
88+
update_option('wc_orders_table_version', $this->get_latest_table_version() );
89+
}
90+
}
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
<?php
2+
3+
class WC_Custom_Order_Table {
4+
5+
protected $table_name = null;
6+
7+
public function setup() {
8+
global $wpdb;
9+
10+
$this->table_name = $wpdb->prefix . 'woocommerce_orders';
11+
12+
add_filter( 'woocommerce_order_data_store', array( $this, 'order_data_store' ) );
13+
add_filter( 'posts_join', array( $this, 'wp_query_customer_query' ), 10, 2 );
14+
15+
// Register the CLI command if we're running WP_CLI
16+
if (defined('WP_CLI') && WP_CLI) {
17+
WP_CLI::add_command('wc-order-table', 'WC_Custom_Order_Table_CLI');
18+
}
19+
}
20+
21+
public function get_table_name() {
22+
return apply_filters( 'wc_customer_order_table_name', $this->table_name );
23+
}
24+
25+
/**
26+
* Init the order data store.
27+
*
28+
* @return string
29+
*/
30+
public function order_data_store() {
31+
return 'WC_Order_Data_Store_Custom_Table';
32+
}
33+
34+
/**
35+
* Filter WP_Query for wc_customer_query
36+
*
37+
* @return string
38+
*/
39+
public function wp_query_customer_query( $join, $wp_query ) {
40+
global $wpdb;
41+
42+
// If there is no wc_customer_query then no need to process anything
43+
if( ! isset( $wp_query->query_vars['wc_customer_query'] ) ) {
44+
return $join;
45+
}
46+
47+
$customer_query = $this->generate_wc_customer_query( $wp_query->query_vars['wc_customer_query'] );
48+
49+
50+
$query_parts = array();
51+
52+
if( ! empty( $customer_query['emails'] ) ) {
53+
$emails = '\'' . implode( '\', \'', array_unique( $customer_query['emails'] ) ) . '\'';
54+
$query_parts[] = "{$this->get_table_name()}.billing_email IN ( {$emails} )";
55+
}
56+
57+
if( ! empty( $customer_query['users'] ) ) {
58+
$users = implode( ',', array_unique( $customer_query['users'] ) );
59+
$query_parts[] = "{$this->get_table_name()}.customer_id IN ( {$users} )";
60+
}
61+
62+
if( ! empty( $query_parts ) ) {
63+
$query = '( ' . implode( ') OR (', $query_parts ) . ' )';
64+
$join .= "
65+
JOIN {$this->get_table_name()} ON
66+
( {$wpdb->posts}.ID = {$this->get_table_name()}.order_id )
67+
AND ( {$query} )";
68+
}
69+
70+
return $join;
71+
}
72+
73+
public function generate_wc_customer_query( $values ) {
74+
$customer_query['emails'] = array();
75+
$customer_query['users'] = array();
76+
77+
foreach ( $values as $value ) {
78+
if ( is_array( $value ) ) {
79+
$query = $this->generate_wc_customer_query( $value );
80+
81+
if( is_array( $query['emails'] ) ) {
82+
$customer_query['emails'] = array_merge( $customer_query['emails'], $query['emails'] );
83+
}
84+
85+
if( is_array( $query['users'] ) ) {
86+
$customer_query['users'] = array_merge( $customer_query['users'], $query['users'] );
87+
}
88+
} elseif ( is_email( $value ) ) {
89+
$customer_query['emails'][] = sanitize_email( $value );
90+
} else {
91+
$customer_query['users'][] = strval( absint( $value ) );
92+
}
93+
}
94+
95+
return $customer_query;
96+
}
97+
}

0 commit comments

Comments
 (0)