From 56333c425f99beea027f2d209005e6eca10615ae Mon Sep 17 00:00:00 2001 From: Vedanshu Jain Date: Wed, 23 Aug 2023 17:56:31 +0530 Subject: [PATCH] Add CLI commands to enable or disable HPOS. --- .../changelog/fix-cli-hpos-activate | 4 + .../Migrations/CustomOrderTable/CLIRunner.php | 180 ++++++++++++++++++ .../Orders/CustomOrdersTableController.php | 1 + 3 files changed, 185 insertions(+) create mode 100644 plugins/woocommerce/changelog/fix-cli-hpos-activate diff --git a/plugins/woocommerce/changelog/fix-cli-hpos-activate b/plugins/woocommerce/changelog/fix-cli-hpos-activate new file mode 100644 index 00000000000..49504721ae0 --- /dev/null +++ b/plugins/woocommerce/changelog/fix-cli-hpos-activate @@ -0,0 +1,4 @@ +Significance: patch +Type: enhancement + +Add CLI commands to enable or disable HPOS. diff --git a/plugins/woocommerce/src/Database/Migrations/CustomOrderTable/CLIRunner.php b/plugins/woocommerce/src/Database/Migrations/CustomOrderTable/CLIRunner.php index 4a819757010..500540119c6 100644 --- a/plugins/woocommerce/src/Database/Migrations/CustomOrderTable/CLIRunner.php +++ b/plugins/woocommerce/src/Database/Migrations/CustomOrderTable/CLIRunner.php @@ -5,6 +5,7 @@ namespace Automattic\WooCommerce\DataBase\Migrations\CustomOrderTable; use Automattic\WooCommerce\Internal\DataStores\Orders\CustomOrdersTableController; use Automattic\WooCommerce\Internal\DataStores\Orders\DataSynchronizer; use Automattic\WooCommerce\Internal\DataStores\Orders\OrdersTableDataStore; +use Automattic\WooCommerce\Internal\Features\FeaturesController; use WP_CLI; /** @@ -60,6 +61,8 @@ class CLIRunner { WP_CLI::add_command( 'wc cot migrate', array( $this, 'migrate' ) ); WP_CLI::add_command( 'wc cot sync', array( $this, 'sync' ) ); WP_CLI::add_command( 'wc cot verify_cot_data', array( $this, 'verify_cot_data' ) ); + WP_CLI::add_command( 'wc cot enable', array( $this, 'enable' ) ); + WP_CLI::add_command( 'wc cot disable', array( $this, 'disable' ) ); } /** @@ -671,4 +674,181 @@ ORDER BY $meta_table.order_id ASC, $meta_table.meta_key ASC; return $clubbed_data; } + /** + * Set custom order tables (HPOS) to authoritative if: + * 1. HPOS and posts tables are in sync, or, + * 2. This is a new shop (in this case also create tables). + * and + * 3. All installed WC plugins are compatible. + * + * ## OPTIONS + * + * [--for-new-shop] + * : Enable only if this is a new shop, irrespective of whether tables are in sync. + * --- + * default: false + * --- + * + * [--with-sync] + * : Also enables sync (if it's currently not enabled). + * --- + * default: false + * --- + * + * ### EXAMPLES + * + * # Enable HPOS on new shops. + * wp wc cot enable --for-new-shop + * + * @param array $args Positional arguments passed to the command. + * @param array $assoc_args Associative arguments (options) passed to the command. + * + * @return void + */ + public function enable( array $args = array(), array $assoc_args = array() ) { + $assoc_args = wp_parse_args( + $assoc_args, + array( + 'for-new-shop' => false, + 'with-sync' => false, + ) + ); + + $enable_hpos = true; + WP_CLI::log( __( 'Running pre-enable checks...', 'woocommerce' ) ); + + $is_new_shop = \WC_Install::is_new_install(); + if ( $assoc_args['for-new-shop'] && ! $is_new_shop ) { + WP_CLI::warning( __( '[Failed] This is not a new shop, but --for-new-shop flag was passed.', 'woocommerce' ) ); + $enable_hpos = false; + } + + /** Feature controller instance @var FeaturesController $feature_controller */ + $feature_controller = wc_get_container()->get( FeaturesController::class ); + $plugin_info = $feature_controller->get_compatible_plugins_for_feature( 'custom_order_tables', true ); + if ( count( array_merge( $plugin_info['uncertain'], $plugin_info['incompatible'] ) ) > 0 ) { + WP_CLI::warning( __( '[Failed] Some installed plugins are incompatible. Please review the plugins by going to WooCommerce > Settings > Advanced > Features and see the Data storage for orders section.', 'woocommerce' ) ); + $enable_hpos = false; + } + + /** DataSynchronizer instance @var DataSynchronizer $data_synchronizer */ + $data_synchronizer = wc_get_container()->get( DataSynchronizer::class ); + $pending_orders = $data_synchronizer->get_total_pending_count(); + $table_exists = $data_synchronizer->check_orders_table_exists(); + + if ( ! $table_exists ) { + WP_CLI::warning( __( 'Orders table does not exist. Creating...', 'woocommerce' ) ); + if ( $is_new_shop || 0 === $pending_orders ) { + $data_synchronizer->create_database_tables(); + if ( $data_synchronizer->check_orders_table_exists() ) { + WP_CLI::log( __( 'Orders table created.', 'woocommerce' ) ); + $table_exists = true; + } else { + WP_CLI::warning( __( '[Failed] Orders table could not be created.', 'woocommerce' ) ); + $enable_hpos = false; + } + } else { + WP_CLI::warning( __( '[Failed] The orders table does not exist and this is not a new shop. Please create the table by going to WooCommerce > Settings > Advanced > Features and enabling sync.', 'woocommerce' ) ); + $enable_hpos = false; + } + } + + if ( $pending_orders > 0 ) { + WP_CLI::warning( + sprintf( + // translators: %s is the command to run (wp wc cot sync). + __( '[Failed] There are orders pending sync. Please run `%s` to sync pending orders.', 'woocommerce' ), + 'wp wc cot sync', + ) + ); + $enable_hpos = false; + } + + if ( $assoc_args['with-sync'] && $table_exists ) { + if ( $data_synchronizer->data_sync_is_enabled() ) { + WP_CLI::warning( __( 'Sync is already enabled.', 'woocommerce' ) ); + } else { + $feature_controller->change_feature_enable( DataSynchronizer::ORDERS_DATA_SYNC_ENABLED_OPTION, true ); + WP_CLI::log( __( 'Sync enabled.', 'woocommerce' ) ); + } + } + + if ( ! $enable_hpos ) { + WP_CLI::error( __( 'HPOS could not be enabled, see the errors above', 'woocommerce' ) ); + return; + } + + /** CustomOrdersTableController instance @var CustomOrdersTableController $cot_status */ + $cot_status = wc_get_container()->get( CustomOrdersTableController::class ); + if ( $cot_status->custom_orders_table_usage_is_enabled() ) { + WP_CLI::warning( __( 'HPOS is already enabled.', 'woocommerce' ) ); + } else { + $feature_controller->change_feature_enable( 'custom_order_tables', true ); + WP_CLI::log( __( 'HPOS enabled.', 'woocommerce' ) ); + } + } + + /** + * Disables custom order tables (HPOS) and posts to authoritative if HPOS and post tables are in sync. + * + * ## OPTIONS + * + * [--with-sync] + * : Also disables sync (if it's currently enabled). + * --- + * default: false + * --- + * + * ### EXAMPLES + * + * # Disable HPOS. + * wp wc cot disable + * + * @param array $args Positional arguments passed to the command. + * @param array $assoc_args Associative arguments (options) passed to the command. + */ + public function disable( $args, $assoc_args ) { + $assoc_args = wp_parse_args( + $assoc_args, + array( + 'with-sync' => false, + ) + ); + + WP_CLI::log( __( 'Running pre-disable checks...', 'woocommerce' ) ); + + /** DataSynchronizer instance @var DataSynchronizer $data_synchronizer */ + $data_synchronizer = wc_get_container()->get( DataSynchronizer::class ); + $pending_orders = $data_synchronizer->get_total_pending_count(); + if ( $pending_orders > 0 ) { + return WP_CLI::error( + sprintf( + // translators: %s is the command to run (wp wc cot sync). + __( '[Failed] There are orders pending sync. Please run `%s` to sync pending orders.', 'woocommerce' ), + 'wp wc cot sync', + ) + ); + } + + /** FeaturesController instance @var FeaturesController $feature_controller */ + $feature_controller = wc_get_container()->get( FeaturesController::class ); + + /** CustomOrdersTableController instance @var CustomOrdersTableController $cot_status */ + $cot_status = wc_get_container()->get( CustomOrdersTableController::class ); + if ( ! $cot_status->custom_orders_table_usage_is_enabled() ) { + WP_CLI::warning( __( 'HPOS is already disabled.', 'woocommerce' ) ); + } else { + $feature_controller->change_feature_enable( 'custom_order_tables', false ); + WP_CLI::log( __( 'HPOS disabled.', 'woocommerce' ) ); + } + + if ( $assoc_args['with-sync'] ) { + if ( ! $data_synchronizer->data_sync_is_enabled() ) { + return WP_CLI::warning( __( 'Sync is already enabled.', 'woocommerce' ) ); + } + $feature_controller->change_feature_enable( DataSynchronizer::ORDERS_DATA_SYNC_ENABLED_OPTION, false ); + WP_CLI::log( __( 'Sync disabled.', 'woocommerce' ) ); + } + } + } diff --git a/plugins/woocommerce/src/Internal/DataStores/Orders/CustomOrdersTableController.php b/plugins/woocommerce/src/Internal/DataStores/Orders/CustomOrdersTableController.php index d008f9391b5..04db92ba0c4 100644 --- a/plugins/woocommerce/src/Internal/DataStores/Orders/CustomOrdersTableController.php +++ b/plugins/woocommerce/src/Internal/DataStores/Orders/CustomOrdersTableController.php @@ -469,6 +469,7 @@ class CustomOrdersTableController { $plugin_incompat_warning = $this->plugin_util->generate_incompatible_plugin_feature_warning( 'custom_order_tables', $plugin_info ); $sync_complete = 0 === $sync_status['current_pending_count']; $disabled_option = array(); + // Changing something here? might also want to look at `enable|disable` functions in CLIRunner. if ( count( array_merge( $plugin_info['uncertain'], $plugin_info['incompatible'] ) ) > 0 ) { $disabled_option = array( 'yes' ); }