From bdff0100185b592f11a23ac352fea25a23d40d00 Mon Sep 17 00:00:00 2001 From: vedanshujain Date: Mon, 7 Mar 2022 17:05:19 +0530 Subject: [PATCH] Add class WPPostToCOTMigrator --- .../CustomOrderTable/WPPostToCOTMigrator.php | 217 ++++++++++++++++++ 1 file changed, 217 insertions(+) create mode 100644 plugins/woocommerce/src/Database/Migrations/CustomOrderTable/WPPostToCOTMigrator.php diff --git a/plugins/woocommerce/src/Database/Migrations/CustomOrderTable/WPPostToCOTMigrator.php b/plugins/woocommerce/src/Database/Migrations/CustomOrderTable/WPPostToCOTMigrator.php new file mode 100644 index 00000000000..c3d3b375470 --- /dev/null +++ b/plugins/woocommerce/src/Database/Migrations/CustomOrderTable/WPPostToCOTMigrator.php @@ -0,0 +1,217 @@ + array( + 'primary_id' => 'ID', + 'table_name' => $wpdb->posts, + ), + 'entity_meta_schema' => array( + 'meta_key_column' => 'meta_key', + 'meta_value_column' => 'meta_value', + 'table_name' => $wpdb->postmeta, + ), + 'destination_table' => $wpdb->prefix . 'wc_orders', + 'entity_meta_relation' => array( + 'entity' => 'ID', + 'meta' => 'post_id', + ), + + ); + + $order_table_core_config = array( + 'ID' => array( + 'type' => 'int', + 'destination' => 'post_id', + ), + 'post_status' => array( + 'type' => 'string', + 'destination' => 'status', + ), + 'post_date_gmt' => array( + 'type' => 'date', + 'destination' => 'date_created_gmt', + ), + 'post_modified_gmt' => array( + 'type' => 'date', + 'destination' => 'date_updated_gmt', + ), + 'post_parent' => array( + 'type' => 'int', + 'destination' => 'parent_order_id', + ), + ); + + $order_table_meta_config = array( + '_order_currency' => array( + 'type' => 'string', + 'destination' => 'currency', + ), + '_order_tax' => array( + 'type' => 'decimal', + 'destination' => 'tax_amount', + ), + '_order_total' => array( + 'type' => 'decimal', + 'destination' => 'total_amount', + ), + '_customer_user' => array( + 'type' => 'int', + 'destination' => 'customer_id', + ), + '_billing_email' => array( + 'type' => 'string', + 'destination' => 'billing_email', + ), + '_payment_method' => array( + 'type' => 'string', + 'destination' => 'payment_method', + ), + '_payment_method_title' => array( + 'type' => 'string', + 'destination' => 'payment_method_title', + ), + '_customer_ip_address' => array( + 'type' => 'string', + 'destination' => 'ip_address', + ), + '_customer_user_agent' => array( + 'type' => 'string', + 'destination' => 'user_agent', + ), + ); + $this->order_table_migrator = new MetaToCustomTableMigrator( $order_table_schema_config, $order_table_meta_config, $order_table_core_config ); + $this->error_logger = new MigrationErrorLogger(); + } + + /** + * Process next migration batch, uses option `wc_cot_migration` to checkpoints of what have been processed so far. + * + * @param int $batch_size Batch size of records to migrate. + * + * @return bool True if migration is completed, false if there are still records to process. + */ + public function process_next_migration_batch( $batch_size = 500 ) { + global $wpdb; + $order_by = 'ID ASC'; + + $data = $this->order_table_migrator->fetch_data_for_migration( $this->get_where_clause(), $batch_size, $order_by ); + + foreach ( $data['errors'] as $post_id => $error ) { + $this->error_logger->log( 'info', "Error in importing post id $post_id: " . print_r( $error, true ) ); + } + + if ( count( $data['data'] ) === 0 ) { + return true; + } + + $queries = $this->order_table_migrator->generate_insert_sql_for_batch( $data['data'], 'insert' ); + $result = $wpdb->query( $queries ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- $queries is already prepared. + if ( count( $data['data'] ) !== $result ) { + // Some rows were not inserted. + // TODO: Find and log the entity ids that were not inserted. + echo ' error '; + } + + $last_post_migrated = max( array_keys( $data['data'] ) ); + $this->update_checkpoint( $last_post_migrated ); + + return false; + } + + /** + * Method to migrate single record. + * + * @param int $post_id Post ID of record to migrate. + * + * @return bool|\WP_Error + */ + public function process_single( $post_id ) { + global $wpdb; + + $where_clause = $wpdb->prepare( 'ID = %d', $post_id ); + $data = $this->order_table_migrator->fetch_data_for_migration( $where_clause, 1, 'ID ASC' ); + if ( isset( $data['errors'][ $post_id ] ) ) { + return new \WP_Error( $data['errors'][ $post_id ] ); + } + + $queries = $this->order_table_migrator->generate_insert_sql_for_batch( $data['data'], 'replace' ); + $result = $wpdb->query( $queries ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- $queries is already prepared. + if ( 1 !== $result ) { + // TODO: Fetch and return last error. + echo 'error'; + + return new \WP_Error( 'error' ); + } + + return true; + } + + /** + * Helper function to get where clause to send to MetaToCustomTableMigrator instance. + * + * @return string|void Where clause. + */ + private function get_where_clause() { + global $wpdb; + + $checkpoint = $this->get_checkpoint(); + $where_clause = $wpdb->prepare( + 'post_type = "shop_order" AND ID > %d', + $checkpoint['id'] + ); + + return $where_clause; + } + + /** + * Current checkpoint status. + * + * @return false|mixed|void + */ + private function get_checkpoint() { + return get_option( 'wc_cot_migration', array( 'id' => 0 ) ); + } + + /** + * Updates current checkpoint + * + * @param int $id Order ID. + */ + public function update_checkpoint( $id ) { + update_option( 'wc_cot_migration', array( 'id' => $id ) ); + } +}