Merge pull request #32817 from woocommerce/cot/effectively_sync_posts_to_cot
[COT] Effectively synchronize orders from the posts table to the custom orders table
This commit is contained in:
commit
53a6202d68
|
@ -0,0 +1,4 @@
|
|||
Significance: minor
|
||||
Type: add
|
||||
|
||||
Effectively synchronize orders from the posts table to the custom orders table.
|
|
@ -8,7 +8,8 @@ namespace Automattic\WooCommerce\Database\Migrations\CustomOrderTable;
|
|||
use Automattic\WooCommerce\Database\Migrations\MigrationHelper;
|
||||
|
||||
/**
|
||||
* Class MetaToCustomTableMigrator.
|
||||
* Base class for implementing migrations from the standard WordPress meta table
|
||||
* to custom structured tables.
|
||||
*
|
||||
* @package Automattic\WooCommerce\Database\Migrations\CustomOrderTable
|
||||
*/
|
||||
|
@ -78,7 +79,7 @@ abstract class MetaToCustomTableMigrator {
|
|||
'primary_key_type' => $type bool|int|string|decimal
|
||||
)
|
||||
*/
|
||||
abstract public function get_schema_config();
|
||||
abstract public function get_schema_config(): array;
|
||||
|
||||
/**
|
||||
* Specify column config from the source table.
|
||||
|
@ -95,7 +96,7 @@ abstract class MetaToCustomTableMigrator {
|
|||
* ....
|
||||
* ).
|
||||
*/
|
||||
abstract public function get_core_column_mapping();
|
||||
abstract public function get_core_column_mapping(): array;
|
||||
|
||||
/**
|
||||
* Specify meta keys config from source meta table.
|
||||
|
@ -112,7 +113,7 @@ abstract class MetaToCustomTableMigrator {
|
|||
* ....
|
||||
* ).
|
||||
*/
|
||||
abstract public function get_meta_column_config();
|
||||
abstract public function get_meta_column_config(): array;
|
||||
|
||||
/**
|
||||
* Generate SQL for data insertion.
|
||||
|
@ -125,7 +126,7 @@ abstract class MetaToCustomTableMigrator {
|
|||
* ($value for row 2)
|
||||
* ...
|
||||
*/
|
||||
public function generate_insert_sql_for_batch( $batch ) {
|
||||
public function generate_insert_sql_for_batch( array $batch ): string {
|
||||
$table = $this->schema_config['destination']['table_name'];
|
||||
|
||||
list( $value_sql, $column_sql ) = $this->generate_column_clauses( array_merge( $this->core_column_mapping, $this->meta_column_mapping ), $batch );
|
||||
|
@ -150,7 +151,7 @@ abstract class MetaToCustomTableMigrator {
|
|||
* $column2 = VALUES($column2)
|
||||
* ...
|
||||
*/
|
||||
public function generate_update_sql_for_batch( $batch, $entity_row_mapping ) {
|
||||
public function generate_update_sql_for_batch( array $batch, array $entity_row_mapping ): string {
|
||||
$table = $this->schema_config['destination']['table_name'];
|
||||
|
||||
$destination_primary_id_schema = $this->get_destination_table_primary_id_schema();
|
||||
|
@ -173,7 +174,7 @@ abstract class MetaToCustomTableMigrator {
|
|||
*
|
||||
* @return array[] Schema for primary ID column.
|
||||
*/
|
||||
protected function get_destination_table_primary_id_schema() {
|
||||
protected function get_destination_table_primary_id_schema(): array {
|
||||
return array(
|
||||
'destination_primary_key' => array(
|
||||
'destination' => $this->schema_config['destination']['primary_key'],
|
||||
|
@ -190,7 +191,7 @@ abstract class MetaToCustomTableMigrator {
|
|||
*
|
||||
* @return array SQL clause for values, columns placeholders, and columns.
|
||||
*/
|
||||
protected function generate_column_clauses( $columns_schema, $batch ) {
|
||||
protected function generate_column_clauses( array $columns_schema, array $batch ): array {
|
||||
global $wpdb;
|
||||
|
||||
$columns = array();
|
||||
|
@ -229,7 +230,7 @@ abstract class MetaToCustomTableMigrator {
|
|||
*
|
||||
* @return array List of errors happened during migration.
|
||||
*/
|
||||
public function process_migration_batch_for_ids( $entity_ids ) {
|
||||
public function process_migration_batch_for_ids( array $entity_ids ): array {
|
||||
$data = $this->fetch_data_for_migration_for_ids( $entity_ids );
|
||||
|
||||
foreach ( $data['errors'] as $entity_id => $error ) {
|
||||
|
@ -259,7 +260,7 @@ abstract class MetaToCustomTableMigrator {
|
|||
*
|
||||
* @param array $batch Data to insert, will be of the form as returned by `data` in `fetch_data_for_migration_for_ids`.
|
||||
*/
|
||||
protected function process_insert_batch( $batch ) {
|
||||
protected function process_insert_batch( array $batch ): void {
|
||||
global $wpdb;
|
||||
if ( 0 === count( $batch ) ) {
|
||||
return;
|
||||
|
@ -279,7 +280,7 @@ abstract class MetaToCustomTableMigrator {
|
|||
* @param array $batch Data to insert, will be of the form as returned by `data` in `fetch_data_for_migration_for_ids`.
|
||||
* @param array $already_migrated Maps rows to update data with their original IDs.
|
||||
*/
|
||||
protected function process_update_batch( $batch, $already_migrated ) {
|
||||
protected function process_update_batch( array $batch, array $already_migrated ): void {
|
||||
global $wpdb;
|
||||
if ( 0 === count( $batch ) ) {
|
||||
return;
|
||||
|
@ -310,7 +311,7 @@ abstract class MetaToCustomTableMigrator {
|
|||
* ...,
|
||||
* )
|
||||
*/
|
||||
public function fetch_data_for_migration_for_ids( $entity_ids ) {
|
||||
public function fetch_data_for_migration_for_ids( array $entity_ids ): array {
|
||||
global $wpdb;
|
||||
|
||||
if ( empty( $entity_ids ) ) {
|
||||
|
@ -352,7 +353,7 @@ abstract class MetaToCustomTableMigrator {
|
|||
* ...
|
||||
* )
|
||||
*/
|
||||
public function get_already_migrated_records( $entity_ids ) {
|
||||
public function get_already_migrated_records( array $entity_ids ): array {
|
||||
global $wpdb;
|
||||
$source_table = $this->schema_config['source']['entity']['table_name'];
|
||||
$source_destination_join_column = $this->schema_config['source']['entity']['destination_rel_column'];
|
||||
|
@ -389,7 +390,7 @@ WHERE source.`$source_primary_key_column` IN ( $entity_id_placeholder )
|
|||
*
|
||||
* @return string Query that can be used to fetch data.
|
||||
*/
|
||||
protected function build_entity_table_query( $entity_ids ) {
|
||||
protected function build_entity_table_query( array $entity_ids ): string {
|
||||
global $wpdb;
|
||||
$source_entity_table = $this->schema_config['source']['entity']['table_name'];
|
||||
$source_meta_rel_id_column = "`$source_entity_table`.`{$this->schema_config['source']['entity']['meta_rel_column']}`";
|
||||
|
@ -430,7 +431,7 @@ WHERE $where_clause;
|
|||
*
|
||||
* @return string Query for fetching meta data.
|
||||
*/
|
||||
protected function build_meta_data_query( $entity_ids ) {
|
||||
protected function build_meta_data_query( array $entity_ids ): string {
|
||||
global $wpdb;
|
||||
$meta_table = $this->schema_config['source']['meta']['table_name'];
|
||||
$meta_keys = array_keys( $this->meta_column_mapping );
|
||||
|
@ -469,7 +470,7 @@ WHERE
|
|||
*
|
||||
* @return array[] Validated and combined data with errors.
|
||||
*/
|
||||
private function process_and_sanitize_data( $entity_data, $meta_data ) {
|
||||
private function process_and_sanitize_data( array $entity_data, array $meta_data ): array {
|
||||
$sanitized_entity_data = array();
|
||||
$error_records = array();
|
||||
$this->process_and_sanitize_entity_data( $sanitized_entity_data, $error_records, $entity_data );
|
||||
|
@ -488,7 +489,7 @@ WHERE
|
|||
* @param array $error_records Error records.
|
||||
* @param array $entity_data Original source data.
|
||||
*/
|
||||
private function process_and_sanitize_entity_data( &$sanitized_entity_data, &$error_records, $entity_data ) {
|
||||
private function process_and_sanitize_entity_data( array &$sanitized_entity_data, array &$error_records, array $entity_data ): void {
|
||||
foreach ( $entity_data as $entity ) {
|
||||
$row_data = array();
|
||||
foreach ( $this->core_column_mapping as $column_name => $schema ) {
|
||||
|
@ -512,7 +513,7 @@ WHERE
|
|||
* @param array $error_records Error records.
|
||||
* @param array $meta_data Original source data.
|
||||
*/
|
||||
private function processs_and_sanitize_meta_data( &$sanitized_entity_data, &$error_records, $meta_data ) {
|
||||
private function processs_and_sanitize_meta_data( array &$sanitized_entity_data, array &$error_records, array $meta_data ): void {
|
||||
foreach ( $meta_data as $datum ) {
|
||||
$column_schema = $this->meta_column_mapping[ $datum->meta_key ];
|
||||
$value = $this->validate_data( $datum->meta_value, $column_schema['type'] );
|
||||
|
@ -532,7 +533,7 @@ WHERE
|
|||
*
|
||||
* @return float|int|mixed|string|\WP_Error
|
||||
*/
|
||||
private function validate_data( $value, $type ) {
|
||||
private function validate_data( $value, string $type ) {
|
||||
switch ( $type ) {
|
||||
case 'decimal':
|
||||
$value = (float) $value;
|
||||
|
|
|
@ -8,9 +8,8 @@ namespace Automattic\WooCommerce\Database\Migrations\CustomOrderTable;
|
|||
use Automattic\WooCommerce\Database\Migrations\MigrationHelper;
|
||||
|
||||
/**
|
||||
* Class MetaToMetaTableMigrator.
|
||||
*
|
||||
* Generic class for powering migrations from one meta table to another table.
|
||||
* Base class for implementing migrations from the standard WordPress meta table
|
||||
* to custom meta (key-value pairs) tables.
|
||||
*
|
||||
* @package Automattic\WooCommerce\Database\Migrations\CustomOrderTable
|
||||
*/
|
||||
|
@ -61,7 +60,7 @@ abstract class MetaToMetaTableMigrator {
|
|||
* ),
|
||||
* )
|
||||
*/
|
||||
abstract public function get_meta_config();
|
||||
abstract public function get_meta_config(): array;
|
||||
|
||||
/**
|
||||
* MetaToMetaTableMigrator constructor.
|
||||
|
@ -76,7 +75,7 @@ abstract class MetaToMetaTableMigrator {
|
|||
*
|
||||
* @param array $entity_ids Entity IDs to process migration for.
|
||||
*/
|
||||
public function process_migration_batch_for_ids( $entity_ids ) {
|
||||
public function process_migration_batch_for_ids( array $entity_ids ): void {
|
||||
global $wpdb;
|
||||
$to_migrate = $this->fetch_data_for_migration_for_ids( $entity_ids );
|
||||
|
||||
|
@ -111,7 +110,7 @@ abstract class MetaToMetaTableMigrator {
|
|||
*
|
||||
* @return string Query to update batch records.
|
||||
*/
|
||||
public function generate_update_sql_for_batch( $batch ) {
|
||||
public function generate_update_sql_for_batch( array $batch ): string {
|
||||
global $wpdb;
|
||||
|
||||
$table = $this->schema_config['destination']['meta']['table_name'];
|
||||
|
@ -149,7 +148,7 @@ abstract class MetaToMetaTableMigrator {
|
|||
*
|
||||
* @return string Insert SQL query.
|
||||
*/
|
||||
public function generate_insert_sql_for_batch( $batch ) {
|
||||
public function generate_insert_sql_for_batch( array $batch ): string {
|
||||
global $wpdb;
|
||||
|
||||
$table = $this->schema_config['destination']['meta']['table_name'];
|
||||
|
@ -196,7 +195,7 @@ abstract class MetaToMetaTableMigrator {
|
|||
* ...,
|
||||
* )
|
||||
*/
|
||||
public function fetch_data_for_migration_for_ids( $entity_ids ) {
|
||||
public function fetch_data_for_migration_for_ids( array $entity_ids ): array {
|
||||
global $wpdb;
|
||||
if ( empty( $entity_ids ) ) {
|
||||
return array(
|
||||
|
@ -241,7 +240,7 @@ abstract class MetaToMetaTableMigrator {
|
|||
*
|
||||
* @return array Already migrated records.
|
||||
*/
|
||||
private function get_already_migrated_records( $entity_ids ) {
|
||||
private function get_already_migrated_records( array $entity_ids ): array {
|
||||
global $wpdb;
|
||||
|
||||
$destination_table_name = $this->schema_config['destination']['meta']['table_name'];
|
||||
|
@ -298,7 +297,7 @@ WHERE destination.$destination_entity_id_column in ( $entity_ids_placeholder ) O
|
|||
*
|
||||
* @return array[] Returns two arrays, first for records to migrate, and second for records to upgrade.
|
||||
*/
|
||||
private function classify_update_insert_records( $to_migrate, $already_migrated ) {
|
||||
private function classify_update_insert_records( array $to_migrate, array $already_migrated ): array {
|
||||
$to_update = array();
|
||||
$to_insert = array();
|
||||
|
||||
|
@ -347,7 +346,7 @@ WHERE destination.$destination_entity_id_column in ( $entity_ids_placeholder ) O
|
|||
*
|
||||
* @return string Query that can be used to fetch data.
|
||||
*/
|
||||
private function build_meta_table_query( $entity_ids ) {
|
||||
private function build_meta_table_query( array $entity_ids ): string {
|
||||
global $wpdb;
|
||||
$source_meta_table = $this->schema_config['source']['meta']['table_name'];
|
||||
$source_meta_key_column = $this->schema_config['source']['meta']['meta_key_column'];
|
||||
|
|
|
@ -6,11 +6,12 @@
|
|||
namespace Automattic\WooCommerce\Database\Migrations\CustomOrderTable;
|
||||
|
||||
/**
|
||||
* Class WPPostMetaToOrderMetaMigrator.
|
||||
* Helper class to migrate records from the WordPress post meta table
|
||||
* to the custom orders meta table.
|
||||
*
|
||||
* @package Automattic\WooCommerce\Database\Migrations\CustomOrderTable
|
||||
*/
|
||||
class WPPostMetaToOrderMetaMigrator extends MetaToMetaTableMigrator {
|
||||
class PostMetaToOrderMetaMigrator extends MetaToMetaTableMigrator {
|
||||
|
||||
/**
|
||||
* List of meta keys to exclude from migration.
|
||||
|
@ -20,7 +21,7 @@ class WPPostMetaToOrderMetaMigrator extends MetaToMetaTableMigrator {
|
|||
private $excluded_columns;
|
||||
|
||||
/**
|
||||
* WPPostMetaToOrderMetaMigrator constructor.
|
||||
* PostMetaToOrderMetaMigrator constructor.
|
||||
*
|
||||
* @param array $excluded_columns List of meta keys to exclude from migration.
|
||||
*/
|
||||
|
@ -34,7 +35,7 @@ class WPPostMetaToOrderMetaMigrator extends MetaToMetaTableMigrator {
|
|||
*
|
||||
* @return array Meta data migration config.
|
||||
*/
|
||||
public function get_meta_config() {
|
||||
public function get_meta_config(): array {
|
||||
global $wpdb;
|
||||
// TODO: Remove hardcoding.
|
||||
$this->table_names = array(
|
|
@ -6,11 +6,12 @@
|
|||
namespace Automattic\WooCommerce\Database\Migrations\CustomOrderTable;
|
||||
|
||||
/**
|
||||
* Class WPPostToOrderAddressTableMigrator
|
||||
* Helper class to migrate records from the WordPress post table
|
||||
* to the custom order addresses table.
|
||||
*
|
||||
* @package Automattic\WooCommerce\Database\Migrations\CustomOrderTable
|
||||
*/
|
||||
class WPPostToOrderAddressTableMigrator extends MetaToCustomTableMigrator {
|
||||
class PostToOrderAddressTableMigrator extends MetaToCustomTableMigrator {
|
||||
/**
|
||||
* Type of addresses being migrated, could be billing|shipping.
|
||||
*
|
||||
|
@ -19,7 +20,7 @@ class WPPostToOrderAddressTableMigrator extends MetaToCustomTableMigrator {
|
|||
protected $type;
|
||||
|
||||
/**
|
||||
* WPPostToOrderAddressTableMigrator constructor.
|
||||
* PostToOrderAddressTableMigrator constructor.
|
||||
*
|
||||
* @param string $type Type of addresses being migrated, could be billing|shipping.
|
||||
*/
|
||||
|
@ -33,7 +34,7 @@ class WPPostToOrderAddressTableMigrator extends MetaToCustomTableMigrator {
|
|||
*
|
||||
* @return array Config.
|
||||
*/
|
||||
public function get_schema_config() {
|
||||
public function get_schema_config(): array {
|
||||
global $wpdb;
|
||||
// TODO: Remove hardcoding.
|
||||
$this->table_names = array(
|
||||
|
@ -72,7 +73,7 @@ class WPPostToOrderAddressTableMigrator extends MetaToCustomTableMigrator {
|
|||
*
|
||||
* @return \string[][] Config.
|
||||
*/
|
||||
public function get_core_column_mapping() {
|
||||
public function get_core_column_mapping(): array {
|
||||
$type = $this->type;
|
||||
|
||||
return array(
|
||||
|
@ -93,7 +94,7 @@ class WPPostToOrderAddressTableMigrator extends MetaToCustomTableMigrator {
|
|||
*
|
||||
* @return \string[][] Config.
|
||||
*/
|
||||
public function get_meta_column_config() {
|
||||
public function get_meta_column_config(): array {
|
||||
$type = $this->type;
|
||||
|
||||
return array(
|
||||
|
@ -158,7 +159,7 @@ class WPPostToOrderAddressTableMigrator extends MetaToCustomTableMigrator {
|
|||
* ...
|
||||
* )
|
||||
*/
|
||||
public function get_already_migrated_records( $entity_ids ) {
|
||||
public function get_already_migrated_records( array $entity_ids ): array {
|
||||
global $wpdb;
|
||||
$source_table = $this->schema_config['source']['entity']['table_name'];
|
||||
$source_destination_join_column = $this->schema_config['source']['entity']['destination_rel_column'];
|
|
@ -6,18 +6,19 @@
|
|||
namespace Automattic\WooCommerce\Database\Migrations\CustomOrderTable;
|
||||
|
||||
/**
|
||||
* Class WPPostToOrderOpTableMigrator
|
||||
* Helper class to migrate records from the WordPress post table
|
||||
* to the custom order operations table.
|
||||
*
|
||||
* @package Automattic\WooCommerce\Database\Migrations\CustomOrderTable
|
||||
*/
|
||||
class WPPostToOrderOpTableMigrator extends MetaToCustomTableMigrator {
|
||||
class PostToOrderOpTableMigrator extends MetaToCustomTableMigrator {
|
||||
|
||||
/**
|
||||
* Get schema config for wp_posts and wc_order_operational_detail table.
|
||||
*
|
||||
* @return array Config.
|
||||
*/
|
||||
public function get_schema_config() {
|
||||
public function get_schema_config(): array {
|
||||
global $wpdb;
|
||||
// TODO: Remove hardcoding.
|
||||
$this->table_names = array(
|
||||
|
@ -57,7 +58,7 @@ class WPPostToOrderOpTableMigrator extends MetaToCustomTableMigrator {
|
|||
*
|
||||
* @return \string[][] Config.
|
||||
*/
|
||||
public function get_core_column_mapping() {
|
||||
public function get_core_column_mapping(): array {
|
||||
return array(
|
||||
'id' => array(
|
||||
'type' => 'int',
|
||||
|
@ -72,7 +73,7 @@ class WPPostToOrderOpTableMigrator extends MetaToCustomTableMigrator {
|
|||
*
|
||||
* @return \string[][] Config.
|
||||
*/
|
||||
public function get_meta_column_config() {
|
||||
public function get_meta_column_config(): array {
|
||||
return array(
|
||||
'_created_via' => array(
|
||||
'type' => 'string',
|
|
@ -6,16 +6,18 @@
|
|||
namespace Automattic\WooCommerce\Database\Migrations\CustomOrderTable;
|
||||
|
||||
/**
|
||||
* Class WPPostToOrderTableMigrator.
|
||||
* Helper class to migrate records from the WordPress post table
|
||||
* to the custom order table (and only that table - PostsToOrdersMigrationController
|
||||
* is used for fully migrating orders).
|
||||
*/
|
||||
class WPPostToOrderTableMigrator extends MetaToCustomTableMigrator {
|
||||
class PostToOrderTableMigrator extends MetaToCustomTableMigrator {
|
||||
|
||||
/**
|
||||
* Get schema config for wp_posts and wc_order table.
|
||||
*
|
||||
* @return array Config.
|
||||
*/
|
||||
public function get_schema_config() {
|
||||
public function get_schema_config(): array {
|
||||
global $wpdb;
|
||||
|
||||
// TODO: Remove hardcoding.
|
||||
|
@ -55,7 +57,7 @@ class WPPostToOrderTableMigrator extends MetaToCustomTableMigrator {
|
|||
*
|
||||
* @return \string[][] Config.
|
||||
*/
|
||||
public function get_core_column_mapping() {
|
||||
public function get_core_column_mapping(): array {
|
||||
return array(
|
||||
'ID' => array(
|
||||
'type' => 'int',
|
||||
|
@ -85,7 +87,7 @@ class WPPostToOrderTableMigrator extends MetaToCustomTableMigrator {
|
|||
*
|
||||
* @return \string[][] Config.
|
||||
*/
|
||||
public function get_meta_column_config() {
|
||||
public function get_meta_column_config(): array {
|
||||
return array(
|
||||
'_order_currency' => array(
|
||||
'type' => 'string',
|
|
@ -0,0 +1,102 @@
|
|||
<?php
|
||||
/**
|
||||
* Class for implementing migration from wp_posts and wp_postmeta to custom order tables.
|
||||
*/
|
||||
|
||||
namespace Automattic\WooCommerce\Database\Migrations\CustomOrderTable;
|
||||
|
||||
use Automattic\WooCommerce\Database\Migrations\MigrationErrorLogger;
|
||||
|
||||
/**
|
||||
* This is the main class used to perform the complete migration of orders
|
||||
* from the posts table to the custom orders table.
|
||||
*
|
||||
* @package Automattic\WooCommerce\Database\Migrations\CustomOrderTable
|
||||
*/
|
||||
class PostsToOrdersMigrationController {
|
||||
|
||||
/**
|
||||
* Error logger for migration errors.
|
||||
*
|
||||
* @var MigrationErrorLogger $error_logger
|
||||
*/
|
||||
private $error_logger;
|
||||
|
||||
/**
|
||||
* Migrator instance to migrate data into wc_order table.
|
||||
*
|
||||
* @var PostToOrderTableMigrator
|
||||
*/
|
||||
private $order_table_migrator;
|
||||
|
||||
/**
|
||||
* Migrator instance to migrate billing data into address table.
|
||||
*
|
||||
* @var PostToOrderAddressTableMigrator
|
||||
*/
|
||||
private $billing_address_table_migrator;
|
||||
|
||||
/**
|
||||
* Migrator instance to migrate shipping data into address table.
|
||||
*
|
||||
* @var PostToOrderAddressTableMigrator
|
||||
*/
|
||||
private $shipping_address_table_migrator;
|
||||
|
||||
/**
|
||||
* Migrator instance to migrate operational data.
|
||||
*
|
||||
* @var PostToOrderOpTableMigrator
|
||||
*/
|
||||
private $operation_data_table_migrator;
|
||||
|
||||
/**
|
||||
* Migrator instance to migrate meta data.
|
||||
*
|
||||
* @var MetaToMetaTableMigrator
|
||||
*/
|
||||
private $meta_table_migrator;
|
||||
|
||||
/**
|
||||
* PostsToOrdersMigrationController constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
|
||||
$this->order_table_migrator = new PostToOrderTableMigrator();
|
||||
$this->billing_address_table_migrator = new PostToOrderAddressTableMigrator( 'billing' );
|
||||
$this->shipping_address_table_migrator = new PostToOrderAddressTableMigrator( 'shipping' );
|
||||
$this->operation_data_table_migrator = new PostToOrderOpTableMigrator();
|
||||
|
||||
$excluded_columns = array_keys( $this->order_table_migrator->get_meta_column_config() );
|
||||
$excluded_columns = array_merge( $excluded_columns, array_keys( $this->billing_address_table_migrator->get_meta_column_config() ) );
|
||||
$excluded_columns = array_merge( $excluded_columns, array_keys( $this->shipping_address_table_migrator->get_meta_column_config() ) );
|
||||
$excluded_columns = array_merge( $excluded_columns, array_keys( $this->operation_data_table_migrator->get_meta_column_config() ) );
|
||||
|
||||
$this->meta_table_migrator = new PostMetaToOrderMetaMigrator( $excluded_columns );
|
||||
$this->error_logger = new MigrationErrorLogger();
|
||||
}
|
||||
|
||||
/**
|
||||
* Migrates a set of orders from the posts table to the custom orders tables.
|
||||
*
|
||||
* @param array $order_post_ids List of post IDs of the orders to migrate.
|
||||
*/
|
||||
public function migrate_orders( array $order_post_ids ): void {
|
||||
$this->order_table_migrator->process_migration_batch_for_ids( $order_post_ids );
|
||||
$this->billing_address_table_migrator->process_migration_batch_for_ids( $order_post_ids );
|
||||
$this->shipping_address_table_migrator->process_migration_batch_for_ids( $order_post_ids );
|
||||
$this->operation_data_table_migrator->process_migration_batch_for_ids( $order_post_ids );
|
||||
$this->meta_table_migrator->process_migration_batch_for_ids( $order_post_ids );
|
||||
// TODO: Return merged error array.
|
||||
}
|
||||
|
||||
/**
|
||||
* Migrates an order from the posts table to the custom orders tables.
|
||||
*
|
||||
* @param int $order_post_id Post ID of the order to migrate.
|
||||
*/
|
||||
public function migrate_order( int $order_post_id ): void {
|
||||
$this->migrate_orders( array( $order_post_id ) );
|
||||
// TODO: Return error.
|
||||
}
|
||||
}
|
|
@ -1,170 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* Class for implementing migration from wp_posts and wp_postmeta to custom order tables.
|
||||
*/
|
||||
|
||||
namespace Automattic\WooCommerce\Database\Migrations\CustomOrderTable;
|
||||
|
||||
use Automattic\WooCommerce\Database\Migrations\MigrationErrorLogger;
|
||||
|
||||
/**
|
||||
* Class WPPostToCOTMigrator
|
||||
*
|
||||
* @package Automattic\WooCommerce\Database\Migrations\CustomOrderTable
|
||||
*/
|
||||
class WPPostToCOTMigrator {
|
||||
|
||||
/**
|
||||
* Error logger for migration errors.
|
||||
*
|
||||
* @var MigrationErrorLogger $error_logger
|
||||
*/
|
||||
private $error_logger;
|
||||
|
||||
/**
|
||||
* Migrator instance to migrate data into wc_order table.
|
||||
*
|
||||
* @var WPPostToOrderTableMigrator
|
||||
*/
|
||||
private $order_table_migrator;
|
||||
|
||||
/**
|
||||
* Migrator instance to migrate billing data into address table.
|
||||
*
|
||||
* @var WPPostToOrderAddressTableMigrator
|
||||
*/
|
||||
private $billing_address_table_migrator;
|
||||
|
||||
/**
|
||||
* Migrator instance to migrate shipping data into address table.
|
||||
*
|
||||
* @var WPPostToOrderAddressTableMigrator
|
||||
*/
|
||||
private $shipping_address_table_migrator;
|
||||
|
||||
/**
|
||||
* Migrator instance to migrate operational data.
|
||||
*
|
||||
* @var WPPostToOrderOpTableMigrator
|
||||
*/
|
||||
private $operation_data_table_migrator;
|
||||
|
||||
/**
|
||||
* Migrator instance to migrate meta data.
|
||||
*
|
||||
* @var MetaToMetaTableMigrator
|
||||
*/
|
||||
private $meta_table_migrator;
|
||||
|
||||
/**
|
||||
* WPPostToCOTMigrator constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
|
||||
$this->order_table_migrator = new WPPostToOrderTableMigrator();
|
||||
$this->billing_address_table_migrator = new WPPostToOrderAddressTableMigrator( 'billing' );
|
||||
$this->shipping_address_table_migrator = new WPPostToOrderAddressTableMigrator( 'shipping' );
|
||||
$this->operation_data_table_migrator = new WPPostToOrderOpTableMigrator();
|
||||
|
||||
$excluded_columns = array_keys( $this->order_table_migrator->get_meta_column_config() );
|
||||
$excluded_columns = array_merge( $excluded_columns, array_keys( $this->billing_address_table_migrator->get_meta_column_config() ) );
|
||||
$excluded_columns = array_merge( $excluded_columns, array_keys( $this->shipping_address_table_migrator->get_meta_column_config() ) );
|
||||
$excluded_columns = array_merge( $excluded_columns, array_keys( $this->operation_data_table_migrator->get_meta_column_config() ) );
|
||||
|
||||
$this->meta_table_migrator = new WPPostMetaToOrderMetaMigrator( $excluded_columns );
|
||||
$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 = 100 ) {
|
||||
$order_post_ids = $this->get_next_batch_ids( $batch_size );
|
||||
if ( 0 === count( $order_post_ids ) ) {
|
||||
return true;
|
||||
}
|
||||
$this->process_migration_for_ids( $order_post_ids );
|
||||
$last_post_migrated = max( $order_post_ids );
|
||||
$this->update_checkpoint( $last_post_migrated );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process migration for specific order post IDs.
|
||||
*
|
||||
* @param array $order_post_ids List of post IDs to migrate.
|
||||
*/
|
||||
public function process_migration_for_ids( $order_post_ids ) {
|
||||
$this->order_table_migrator->process_migration_batch_for_ids( $order_post_ids );
|
||||
$this->billing_address_table_migrator->process_migration_batch_for_ids( $order_post_ids );
|
||||
$this->shipping_address_table_migrator->process_migration_batch_for_ids( $order_post_ids );
|
||||
$this->operation_data_table_migrator->process_migration_batch_for_ids( $order_post_ids );
|
||||
$this->meta_table_migrator->process_migration_batch_for_ids( $order_post_ids );
|
||||
// TODO: Return merged error array.
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to migrate single record.
|
||||
*
|
||||
* @param int $post_id Post ID of record to migrate.
|
||||
*/
|
||||
public function process_single( $post_id ) {
|
||||
$this->process_migration_for_ids( array( $post_id ) );
|
||||
// TODO: Return error.
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to get where clause to send to MetaToCustomTableMigrator instance.
|
||||
*
|
||||
* @param int $batch_size Number of orders in batch.
|
||||
*
|
||||
* @return array List of IDs in the current patch.
|
||||
*/
|
||||
private function get_next_batch_ids( $batch_size ) {
|
||||
global $wpdb;
|
||||
|
||||
$checkpoint = $this->get_checkpoint();
|
||||
$post_ids = $wpdb->get_col(
|
||||
$wpdb->prepare(
|
||||
"SELECT ID FROM $wpdb->posts WHERE ID > %d AND post_type = %s ORDER BY ID ASC LIMIT %d ",
|
||||
$checkpoint['id'],
|
||||
'shop_order',
|
||||
$batch_size
|
||||
)
|
||||
);
|
||||
|
||||
return $post_ids;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 ) {
|
||||
return update_option( 'wc_cot_migration', array( 'id' => $id ), false );
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove checkpoint.
|
||||
*
|
||||
* @return bool Whether checkpoint was removed.
|
||||
*/
|
||||
public function delete_checkpoint() {
|
||||
return delete_option( 'wp_cot_migration' );
|
||||
}
|
||||
}
|
|
@ -6,8 +6,6 @@
|
|||
namespace Automattic\WooCommerce\Database\Migrations;
|
||||
|
||||
/**
|
||||
* Class MigrationErrorLogger.
|
||||
*
|
||||
* Error logging for custom table migrations.
|
||||
*
|
||||
* @package Automattic\WooCommerce\Database\Migrations
|
||||
|
|
|
@ -6,8 +6,6 @@
|
|||
namespace Automattic\WooCommerce\Database\Migrations;
|
||||
|
||||
/**
|
||||
* Class MigrationHelper.
|
||||
*
|
||||
* Helper class to assist with migration related operations.
|
||||
*/
|
||||
class MigrationHelper {
|
||||
|
@ -33,7 +31,7 @@ class MigrationHelper {
|
|||
*
|
||||
* @return string Insert clause.
|
||||
*/
|
||||
public static function get_insert_switch( $switch ) {
|
||||
public static function get_insert_switch( string $switch ): string {
|
||||
switch ( $switch ) {
|
||||
case 'insert_ignore':
|
||||
$insert_query = 'INSERT IGNORE';
|
||||
|
@ -59,7 +57,7 @@ class MigrationHelper {
|
|||
*
|
||||
* @return array Schema config escaped for backtick.
|
||||
*/
|
||||
public static function escape_schema_for_backtick( $schema_config ) {
|
||||
public static function escape_schema_for_backtick( array $schema_config ): array {
|
||||
array_walk( $schema_config['source']['entity'], array( self::class, 'escape_and_add_backtick' ) );
|
||||
array_walk( $schema_config['source']['meta'], array( self::class, 'escape_and_add_backtick' ) );
|
||||
array_walk( $schema_config['destination'], array( self::class, 'escape_and_add_backtick' ) );
|
||||
|
@ -85,7 +83,7 @@ class MigrationHelper {
|
|||
*
|
||||
* @return string $wpdb placeholder.
|
||||
*/
|
||||
public static function get_wpdb_placeholder_for_type( $type ) {
|
||||
public static function get_wpdb_placeholder_for_type( string $type ): string {
|
||||
return self::$wpdb_placeholder_for_type[ $type ];
|
||||
}
|
||||
|
||||
|
@ -96,7 +94,7 @@ class MigrationHelper {
|
|||
*
|
||||
* @return string SQL clause for INSERT...ON DUPLICATE KEY UPDATE
|
||||
*/
|
||||
public static function generate_on_duplicate_statement_clause( $columns ) {
|
||||
public static function generate_on_duplicate_statement_clause( array $columns ): string {
|
||||
$update_value_statements = array();
|
||||
foreach ( $columns as $column ) {
|
||||
$update_value_statements[] = "$column = VALUES( $column )";
|
||||
|
|
|
@ -23,6 +23,11 @@ class CustomOrdersTableController {
|
|||
*/
|
||||
public const CUSTOM_ORDERS_TABLE_USAGE_ENABLED_OPTION = 'woocommerce_custom_orders_table_enabled';
|
||||
|
||||
/**
|
||||
* The name of the option that tells that the authoritative table must be flipped once sync finishes.
|
||||
*/
|
||||
private const AUTO_FLIP_AUTHORITATIVE_TABLE_ROLES_OPTION = 'woocommerce_auto_flip_authoritative_table_roles';
|
||||
|
||||
/**
|
||||
* The data store object to use.
|
||||
*
|
||||
|
@ -371,7 +376,7 @@ class CustomOrdersTableController {
|
|||
__( 'Switch to using the orders table as the authoritative data store for orders when sync finishes', 'woocommerce' );
|
||||
$settings[] = array(
|
||||
'desc' => $message,
|
||||
'id' => DataSynchronizer::AUTO_FLIP_AUTHORITATIVE_TABLE_ROLES_OPTION,
|
||||
'id' => self::AUTO_FLIP_AUTHORITATIVE_TABLE_ROLES_OPTION,
|
||||
'type' => 'checkbox',
|
||||
);
|
||||
}
|
||||
|
@ -422,10 +427,14 @@ class CustomOrdersTableController {
|
|||
return $value;
|
||||
}
|
||||
|
||||
// TODO: Re-enable the following code once the COT to posts table sync is implemented (it's currently disabled to ease testing).
|
||||
|
||||
/*
|
||||
$sync_is_pending = 0 !== $this->data_synchronizer->get_current_orders_pending_sync_count();
|
||||
if ( $sync_is_pending ) {
|
||||
throw new \Exception( "The authoritative table for orders storage can't be changed while there are orders out of sync" );
|
||||
}
|
||||
*/
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
@ -435,11 +444,11 @@ class CustomOrdersTableController {
|
|||
* Here we switch the authoritative table if needed.
|
||||
*/
|
||||
private function process_sync_finished() {
|
||||
if ( $this->auto_flip_authoritative_table_enabled() ) {
|
||||
if ( ! $this->auto_flip_authoritative_table_enabled() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
update_option( DataSynchronizer::AUTO_FLIP_AUTHORITATIVE_TABLE_ROLES_OPTION, 'no' );
|
||||
update_option( self::AUTO_FLIP_AUTHORITATIVE_TABLE_ROLES_OPTION, 'no' );
|
||||
|
||||
if ( $this->custom_orders_table_usage_is_enabled() ) {
|
||||
update_option( self::CUSTOM_ORDERS_TABLE_USAGE_ENABLED_OPTION, 'no' );
|
||||
|
@ -454,7 +463,7 @@ class CustomOrdersTableController {
|
|||
* @return bool
|
||||
*/
|
||||
private function auto_flip_authoritative_table_enabled(): bool {
|
||||
return 'yes' === get_option( DataSynchronizer::AUTO_FLIP_AUTHORITATIVE_TABLE_ROLES_OPTION );
|
||||
return 'yes' === get_option( self::AUTO_FLIP_AUTHORITATIVE_TABLE_ROLES_OPTION );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -465,16 +474,14 @@ class CustomOrdersTableController {
|
|||
|
||||
// Disabling the sync implies disabling the automatic authoritative table switch too.
|
||||
if ( ! $data_sync_is_enabled && $this->auto_flip_authoritative_table_enabled() ) {
|
||||
update_option( DataSynchronizer::AUTO_FLIP_AUTHORITATIVE_TABLE_ROLES_OPTION, 'no' );
|
||||
update_option( self::AUTO_FLIP_AUTHORITATIVE_TABLE_ROLES_OPTION, 'no' );
|
||||
}
|
||||
|
||||
// Enabling the sync implies starting it too, if needed.
|
||||
// We do this check here, and not in process_pre_update_option, so that if for some reason
|
||||
// the setting is enabled but no sync is in process, sync will start by just saving the
|
||||
// settings even without modifying them.
|
||||
if ( $data_sync_is_enabled && ! $this->data_synchronizer->pending_data_sync_is_in_progress() ) {
|
||||
$this->data_synchronizer->start_synchronizing_pending_orders();
|
||||
}
|
||||
$this->data_synchronizer->maybe_start_synchronizing_pending_orders( true );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
namespace Automattic\WooCommerce\Internal\DataStores\Orders;
|
||||
|
||||
use Automattic\WooCommerce\Database\Migrations\CustomOrderTable\PostsToOrdersMigrationController;
|
||||
use Automattic\WooCommerce\Internal\Utilities\DatabaseUtil;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
@ -19,12 +20,14 @@ class DataSynchronizer {
|
|||
|
||||
public const ORDERS_DATA_SYNC_ENABLED_OPTION = 'woocommerce_custom_orders_table_data_sync_enabled';
|
||||
private const INITIAL_ORDERS_PENDING_SYNC_COUNT_OPTION = 'woocommerce_initial_orders_pending_sync_count';
|
||||
public const AUTO_FLIP_AUTHORITATIVE_TABLE_ROLES_OPTION = 'woocommerce_auto_flip_authoritative_table_roles';
|
||||
private const PENDING_SYNC_IS_IN_PROGRESS_OPTION = 'woocommerce_custom_orders_table_pending_sync_in_progress';
|
||||
private const ORDERS_SYNC_SCHEDULED_ACTION_CALLBACK = 'woocommerce_run_orders_sync_callback';
|
||||
public const PENDING_SYNCHRONIZATION_FINISHED_ACTION = 'woocommerce_orders_sync_finished';
|
||||
public const PLACEHOLDER_ORDER_POST_TYPE = 'shop_order_placehold';
|
||||
|
||||
private const ORDERS_SYNC_BATCH_SIZE = 250;
|
||||
private const SECONDS_BETWEEN_BATCH_SYNCS = 5;
|
||||
|
||||
// Allowed values for $type in get_ids_of_orders_pending_sync method.
|
||||
public const ID_TYPE_MISSING_IN_ORDERS_TABLE = 0;
|
||||
public const ID_TYPE_MISSING_IN_POSTS_TABLE = 1;
|
||||
|
@ -47,6 +50,13 @@ class DataSynchronizer {
|
|||
*/
|
||||
private $database_util;
|
||||
|
||||
/**
|
||||
* The posts to COT migrator to use.
|
||||
*
|
||||
* @var DatabaseUtil
|
||||
*/
|
||||
private $posts_to_cot_migrator;
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*/
|
||||
|
@ -57,18 +67,27 @@ class DataSynchronizer {
|
|||
$this->do_pending_orders_synchronization();
|
||||
}
|
||||
);
|
||||
|
||||
add_action(
|
||||
'woocommerce_after_order_object_save',
|
||||
function() {
|
||||
$this->maybe_start_synchronizing_pending_orders();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Class initialization, invoked by the DI container.
|
||||
*
|
||||
* @internal
|
||||
* @param OrdersTableDataStore $data_store The data store to use.
|
||||
* @param DatabaseUtil $database_util The database util class to use.
|
||||
* @param PostsToOrdersMigrationController $posts_to_cot_migrator The posts to COT migration class to use.
|
||||
*@internal
|
||||
*/
|
||||
final public function init( OrdersTableDataStore $data_store, DatabaseUtil $database_util ) {
|
||||
final public function init( OrdersTableDataStore $data_store, DatabaseUtil $database_util, PostsToOrdersMigrationController $posts_to_cot_migrator ) {
|
||||
$this->data_store = $data_store;
|
||||
$this->database_util = $database_util;
|
||||
$this->posts_to_cot_migrator = $posts_to_cot_migrator;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -128,7 +147,6 @@ class DataSynchronizer {
|
|||
return array(
|
||||
'initial_pending_count' => (int) get_option( self::INITIAL_ORDERS_PENDING_SYNC_COUNT_OPTION, 0 ),
|
||||
'current_pending_count' => $this->get_current_orders_pending_sync_count(),
|
||||
'auto_flip' => 'yes' === get_option( self::AUTO_FLIP_AUTHORITATIVE_TABLE_ROLES_OPTION ),
|
||||
'sync_in_progress' => $this->pending_data_sync_is_in_progress(),
|
||||
);
|
||||
}
|
||||
|
@ -156,7 +174,7 @@ class DataSynchronizer {
|
|||
|
||||
$orders_table = $wpdb->prefix . 'wc_orders';
|
||||
|
||||
if ( 'yes' === get_option( CustomOrdersTableController::CUSTOM_ORDERS_TABLE_USAGE_ENABLED_OPTION ) ) {
|
||||
if ( $this->custom_orders_table_is_authoritative() ) {
|
||||
$missing_orders_count_sql = "
|
||||
SELECT COUNT(1) FROM $wpdb->posts posts
|
||||
INNER JOIN $orders_table orders ON posts.id=orders.id
|
||||
|
@ -188,6 +206,15 @@ SELECT(
|
|||
return (int) $wpdb->get_var( $sql );
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the custom orders table the authoritative data source for orders currently?
|
||||
*
|
||||
* @return bool Whether the custom orders table the authoritative data source for orders currently.
|
||||
*/
|
||||
private function custom_orders_table_is_authoritative(): bool {
|
||||
return 'yes' === get_option( CustomOrdersTableController::CUSTOM_ORDERS_TABLE_USAGE_ENABLED_OPTION );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of ids of orders than are out of sync.
|
||||
*
|
||||
|
@ -244,10 +271,21 @@ WHERE
|
|||
}
|
||||
|
||||
/**
|
||||
* Start an orders synchronization process.
|
||||
* Start an orders synchronization process if all the following is true:
|
||||
*
|
||||
* 1. Data synchronization is enabled.
|
||||
* 2. Data synchronization isn't already in progress ($force can be used to bypass this).
|
||||
* 3. There's at least one out of sync order.
|
||||
*
|
||||
* This will set up the appropriate status information and schedule the first synchronization batch.
|
||||
*
|
||||
* @param bool $force If true, (re)start the sync process even if it's already in progress.
|
||||
*/
|
||||
public function start_synchronizing_pending_orders() {
|
||||
public function maybe_start_synchronizing_pending_orders( bool $force = false ) {
|
||||
if ( ! $this->data_sync_is_enabled() || ( $this->pending_data_sync_is_in_progress() && ! $force ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$initial_pending_count = $this->get_current_orders_pending_sync_count();
|
||||
if ( 0 === $initial_pending_count ) {
|
||||
return;
|
||||
|
@ -268,7 +306,7 @@ WHERE
|
|||
private function schedule_pending_orders_synchronization() {
|
||||
$queue = WC()->get_instance_of( \WC_Queue::class );
|
||||
$queue->schedule_single(
|
||||
WC()->call_function( 'time' ) + 1,
|
||||
WC()->call_function( 'time' ) + self::SECONDS_BETWEEN_BATCH_SYNCS,
|
||||
self::ORDERS_SYNC_SCHEDULED_ACTION_CALLBACK,
|
||||
array(),
|
||||
'woocommerce-db-updates'
|
||||
|
@ -287,9 +325,8 @@ WHERE
|
|||
$fake_count = get_option( self::FAKE_ORDERS_PENDING_SYNC_COUNT_OPTION );
|
||||
if ( false !== $fake_count ) {
|
||||
update_option( 'woocommerce_fake_orders_pending_sync_count', (int) $fake_count - 1 );
|
||||
// phpcs:ignore Generic.CodeAnalysis.EmptyStatement.DetectedElse
|
||||
} else {
|
||||
// TODO: Use get_ids_of_orders_pending_sync to get a batch of order ids and syncrhonize them.
|
||||
$this->sync_next_batch();
|
||||
}
|
||||
|
||||
if ( 0 === $this->get_current_orders_pending_sync_count() ) {
|
||||
|
@ -304,6 +341,49 @@ WHERE
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes a batch of out of sync orders.
|
||||
* First it synchronizes orders that don't exist in the backup table, and after that,
|
||||
* it synchronizes orders that exist in both tables but have a different last update date.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function sync_next_batch(): void {
|
||||
/**
|
||||
* Filter to customize the count of orders that will be synchronized in each step of the custom orders table to/from posts table synchronization process.
|
||||
*
|
||||
* @since 6.6.0
|
||||
*
|
||||
* @param int Default value for the count.
|
||||
*/
|
||||
$batch_size = apply_filters( 'woocommerce_orders_cot_and_posts_sync_step_size', self::ORDERS_SYNC_BATCH_SIZE );
|
||||
|
||||
if ( $this->custom_orders_table_is_authoritative() ) {
|
||||
$order_ids = $this->get_ids_of_orders_pending_sync( self::ID_TYPE_MISSING_IN_POSTS_TABLE, $batch_size );
|
||||
// TODO: Load $order_ids orders from the orders table and create them (by updating the corresponding placeholder record) in the posts table.
|
||||
} else {
|
||||
$order_ids = $this->get_ids_of_orders_pending_sync( self::ID_TYPE_MISSING_IN_ORDERS_TABLE, $batch_size );
|
||||
$this->posts_to_cot_migrator->migrate_orders( $order_ids );
|
||||
}
|
||||
|
||||
$batch_size -= count( $order_ids );
|
||||
if ( 0 === $batch_size ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$order_ids = $this->get_ids_of_orders_pending_sync( self::ID_TYPE_DIFFERENT_UPDATE_DATE, $batch_size );
|
||||
if ( 0 === count( $order_ids ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// phpcs:ignore Generic.CodeAnalysis.EmptyStatement.DetectedIf
|
||||
if ( $this->custom_orders_table_is_authoritative() ) {
|
||||
// TODO: Load $order_ids orders from the orders table and update them in the posts table.
|
||||
} else {
|
||||
$this->posts_to_cot_migrator->migrate_orders( $order_ids );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleanup all the synchronization status information,
|
||||
* because the process has been disabled by the user via settings,
|
||||
|
@ -312,6 +392,5 @@ WHERE
|
|||
public function cleanup_synchronization_state() {
|
||||
delete_option( self::INITIAL_ORDERS_PENDING_SYNC_COUNT_OPTION );
|
||||
delete_option( self::PENDING_SYNC_IS_IN_PROGRESS_OPTION );
|
||||
delete_option( self::AUTO_FLIP_AUTHORITATIVE_TABLE_ROLES_OPTION );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
namespace Automattic\WooCommerce\Internal\DependencyManagement\ServiceProviders;
|
||||
|
||||
use Automattic\WooCommerce\Database\Migrations\CustomOrderTable\WPPostToCOTMigrator;
|
||||
use Automattic\WooCommerce\Database\Migrations\CustomOrderTable\PostsToOrdersMigrationController;
|
||||
use Automattic\WooCommerce\Internal\DependencyManagement\AbstractServiceProvider;
|
||||
|
||||
/**
|
||||
|
@ -21,7 +21,7 @@ class COTMigrationServiceProvider extends AbstractServiceProvider {
|
|||
* @var string[]
|
||||
*/
|
||||
protected $provides = array(
|
||||
WPPostToCOTMigrator::class,
|
||||
PostsToOrdersMigrationController::class,
|
||||
);
|
||||
|
||||
/**
|
||||
|
@ -32,6 +32,6 @@ class COTMigrationServiceProvider extends AbstractServiceProvider {
|
|||
* @return void
|
||||
*/
|
||||
public function register() {
|
||||
$this->share( WPPostToCOTMigrator::class );
|
||||
$this->share( PostsToOrdersMigrationController::class );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
namespace Automattic\WooCommerce\Internal\DependencyManagement\ServiceProviders;
|
||||
|
||||
use Automattic\WooCommerce\Database\Migrations\CustomOrderTable\PostsToOrdersMigrationController;
|
||||
use Automattic\WooCommerce\Internal\DependencyManagement\AbstractServiceProvider;
|
||||
use Automattic\WooCommerce\Internal\DataStores\Orders\DataSynchronizer;
|
||||
use Automattic\WooCommerce\Internal\DataStores\Orders\CustomOrdersTableController;
|
||||
|
@ -31,7 +32,7 @@ class OrdersDataStoreServiceProvider extends AbstractServiceProvider {
|
|||
* Register the classes.
|
||||
*/
|
||||
public function register() {
|
||||
$this->share( DataSynchronizer::class )->addArguments( array( OrdersTableDataStore::class, DatabaseUtil::class ) );
|
||||
$this->share( DataSynchronizer::class )->addArguments( array( OrdersTableDataStore::class, DatabaseUtil::class, PostsToOrdersMigrationController::class ) );
|
||||
$this->share( CustomOrdersTableController::class )->addArguments( array( OrdersTableDataStore::class, DataSynchronizer::class ) );
|
||||
$this->share( OrdersTableDataStore::class );
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<?php
|
||||
/**
|
||||
* Tests for WPPostToCOTMigrator class.
|
||||
* Tests for PostsToOrdersMigrationController class.
|
||||
*/
|
||||
|
||||
use Automattic\WooCommerce\Database\Migrations\CustomOrderTable\WPPostToCOTMigrator;
|
||||
use Automattic\WooCommerce\Database\Migrations\CustomOrderTable\PostsToOrdersMigrationController;
|
||||
use Automattic\WooCommerce\Internal\DataStores\Orders\DataSynchronizer;
|
||||
use Automattic\WooCommerce\Internal\DataStores\Orders\OrdersTableDataStore;
|
||||
use Automattic\WooCommerce\RestApi\UnitTests\Helpers\CustomerHelper;
|
||||
|
@ -11,9 +11,9 @@ use Automattic\WooCommerce\RestApi\UnitTests\Helpers\OrderHelper;
|
|||
use Automattic\WooCommerce\RestApi\UnitTests\Helpers\ShippingHelper;
|
||||
|
||||
/**
|
||||
* Class WPPostToCOTMigratorTest.
|
||||
* Class PostsToOrdersMigrationControllerTest.
|
||||
*/
|
||||
class WPPostToCOTMigratorTest extends WC_Unit_Test_Case {
|
||||
class PostsToOrdersMigrationControllerTest extends WC_Unit_Test_Case {
|
||||
|
||||
/**
|
||||
* @var DataSynchronizer
|
||||
|
@ -21,7 +21,7 @@ class WPPostToCOTMigratorTest extends WC_Unit_Test_Case {
|
|||
private $synchronizer;
|
||||
|
||||
/**
|
||||
* @var WPPostToCOTMigrator
|
||||
* @var PostsToOrdersMigrationController
|
||||
*/
|
||||
private $sut;
|
||||
|
||||
|
@ -37,16 +37,16 @@ class WPPostToCOTMigratorTest extends WC_Unit_Test_Case {
|
|||
parent::setUp();
|
||||
OrderHelper::create_order_custom_table_if_not_exist();
|
||||
$this->data_store = wc_get_container()->get( OrdersTableDataStore::class );
|
||||
$this->sut = wc_get_container()->get( WPPostToCOTMigrator::class );
|
||||
$this->sut = wc_get_container()->get( PostsToOrdersMigrationController::class );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that migration for a normal order happens as expected.
|
||||
*/
|
||||
public function test_process_next_migration_batch_normal_order() {
|
||||
public function test_migration_for_normal_order() {
|
||||
$order = wc_get_order( OrderHelper::create_complex_wp_post_order() );
|
||||
$this->clear_all_orders_and_reset_checkpoint();
|
||||
$this->sut->process_next_migration_batch( 100 );
|
||||
$this->clear_all_orders();
|
||||
$this->sut->migrate_order( $order->get_id() );
|
||||
|
||||
$this->assert_core_data_is_migrated( $order );
|
||||
$this->assert_order_addresses_are_migrated( $order );
|
||||
|
@ -57,17 +57,16 @@ class WPPostToCOTMigratorTest extends WC_Unit_Test_Case {
|
|||
/**
|
||||
* Test that already migrated order isn't migrated twice.
|
||||
*/
|
||||
public function test_process_next_migration_batch_already_migrated_order() {
|
||||
public function test_migration_for_already_migrated_order() {
|
||||
global $wpdb;
|
||||
$order = wc_get_order( OrderHelper::create_complex_wp_post_order() );
|
||||
$this->clear_all_orders_and_reset_checkpoint();
|
||||
$this->clear_all_orders();
|
||||
|
||||
// Run the migration once.
|
||||
$this->sut->process_next_migration_batch( 100 );
|
||||
$this->sut->migrate_order( $order->get_id() );
|
||||
|
||||
// Delete checkpoint and run migration again, assert there are still no duplicates.
|
||||
$this->sut->update_checkpoint( 0 );
|
||||
$this->sut->process_next_migration_batch( 100 );
|
||||
// Run the migration again, assert there are still no duplicates.
|
||||
$this->sut->migrate_order( $order->get_id() );
|
||||
|
||||
// phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
|
||||
$this->assertEquals(
|
||||
|
@ -132,21 +131,21 @@ WHERE order_id = {$order_id} AND meta_key = 'non_unique_key_1' AND meta_value in
|
|||
/**
|
||||
* Test that when an order is partially migrated, it can still be resumed as expected.
|
||||
*/
|
||||
public function test_process_next_migration_batch_interrupted_migrating_order() {
|
||||
public function test_interrupted_migration() {
|
||||
$this->markTestSkipped();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that invalid order data is not migrated but logged.
|
||||
*/
|
||||
public function test_process_next_migration_batch_invalid_order_data() {
|
||||
public function test_migrating_invalid_order_data() {
|
||||
$this->markTestSkipped();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test when one order is invalid but other one is valid in a migration batch.
|
||||
*/
|
||||
public function test_process_next_migration_batch_invalid_valid_order_combo() {
|
||||
public function test_migrating_invalid_valid_order_combo() {
|
||||
$this->markTestSkipped();
|
||||
}
|
||||
|
||||
|
@ -352,13 +351,12 @@ WHERE order_id = {$order_id} AND meta_key = 'non_unique_key_1' AND meta_value in
|
|||
/**
|
||||
* Helper method to clear checkout and truncate order tables.
|
||||
*/
|
||||
private function clear_all_orders_and_reset_checkpoint() {
|
||||
private function clear_all_orders() {
|
||||
global $wpdb;
|
||||
$order_tables = $this->data_store->get_all_table_names();
|
||||
foreach ( $order_tables as $table ) {
|
||||
// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
|
||||
$wpdb->query( "TRUNCATE table $table;" );
|
||||
}
|
||||
$this->sut->delete_checkpoint();
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
use Automattic\WooCommerce\Database\Migrations\CustomOrderTable\WPPostToCOTMigrator;
|
||||
use Automattic\WooCommerce\Database\Migrations\CustomOrderTable\PostsToOrdersMigrationController;
|
||||
use Automattic\WooCommerce\Internal\DataStores\Orders\OrdersTableDataStore;
|
||||
use Automattic\WooCommerce\RestApi\UnitTests\Helpers\OrderHelper;
|
||||
|
||||
|
@ -12,7 +12,7 @@ use Automattic\WooCommerce\RestApi\UnitTests\Helpers\OrderHelper;
|
|||
class OrdersTableDataStoreTests extends WC_Unit_Test_Case {
|
||||
|
||||
/**
|
||||
* @var WPPostToCOTMigrator
|
||||
* @var PostsToOrdersMigrationController
|
||||
*/
|
||||
private $migrator;
|
||||
|
||||
|
@ -36,7 +36,7 @@ class OrdersTableDataStoreTests extends WC_Unit_Test_Case {
|
|||
remove_filter( 'query', array( $this, '_drop_temporary_tables' ) );
|
||||
OrderHelper::create_order_custom_table_if_not_exist();
|
||||
$this->sut = wc_get_container()->get( OrdersTableDataStore::class );
|
||||
$this->migrator = wc_get_container()->get( WPPostToCOTMigrator::class );
|
||||
$this->migrator = wc_get_container()->get( PostsToOrdersMigrationController::class );
|
||||
$this->cpt_data_store = new WC_Order_Data_Store_CPT();
|
||||
// Add back removed filter.
|
||||
add_filter( 'query', array( $this, '_create_temporary_tables' ) );
|
||||
|
@ -48,7 +48,7 @@ class OrdersTableDataStoreTests extends WC_Unit_Test_Case {
|
|||
*/
|
||||
public function test_read_from_migrated_order() {
|
||||
$post_order_id = OrderHelper::create_complex_wp_post_order();
|
||||
$this->migrator->process_migration_for_ids( array( $post_order_id ) );
|
||||
$this->migrator->migrate_orders( array( $post_order_id ) );
|
||||
|
||||
$cot_order = new WC_Order();
|
||||
$cot_order->set_id( $post_order_id );
|
||||
|
|
Loading…
Reference in New Issue