* Installation related functions and actions.
* @package WooCommerce\Classes
use Automattic\Jetpack\Constants;
use Automattic\WooCommerce\Admin\API\Reports\Orders\Stats\DataStore;
use Automattic\WooCommerce\Enums\ProductType;
use Automattic\WooCommerce\Internal\Admin\EmailImprovements\EmailImprovements;
use Automattic\WooCommerce\Internal\TransientFiles\TransientFilesEngine;
use Automattic\WooCommerce\Internal\DataStores\Orders\{ CustomOrdersTableController, DataSynchronizer, OrdersTableDataStore };
use Automattic\WooCommerce\Internal\DataStores\StockNotifications\StockNotificationsDataStore;
use Automattic\WooCommerce\Internal\Features\FeaturesController;
use Automattic\WooCommerce\Internal\ProductAttributesLookup\DataRegenerator;
use Automattic\WooCommerce\Internal\ProductDownloads\ApprovedDirectories\Synchronize as Download_Directories_Sync;
use Automattic\WooCommerce\Admin\API\Reports\Orders\Stats\DataStore as OrdersStatsDataStore;
use Automattic\WooCommerce\Utilities\FeaturesUtil;
use Automattic\WooCommerce\Internal\Utilities\DatabaseUtil;
use Automattic\WooCommerce\Internal\WCCom\ConnectionHelper as WCConnectionHelper;
use Automattic\WooCommerce\Utilities\{ OrderUtil, PluginUtil };
use Automattic\WooCommerce\Internal\Utilities\PluginInstaller;
defined( 'ABSPATH' ) || exit;
* DB updates and callbacks that need to be run per version.
* Please note that these functions are invoked when WooCommerce is updated from a previous version,
* but NOT when WooCommerce is newly installed.
* Database schema changes must be incorporated to the SQL returned by get_schema, which is applied
* via dbDelta at both install and update time. If any other kind of database change is required
* at install time (e.g. populating tables), use the 'woocommerce_installed' hook.
* When adding new update callbacks after feature freeze, always use a unique version key with a suffix (e.g. `10.2.0-1`)
* if the base version already exists in the array.
* This ensures all users, including those on beta or RC versions, receive the update.
private static $db_updates = array(
'wc_update_200_file_paths',
'wc_update_200_permalinks',
'wc_update_200_subcat_display',
'wc_update_200_taxrates',
'wc_update_200_line_items',
'wc_update_200_db_version',
'wc_update_209_brazillian_state',
'wc_update_209_db_version',
'wc_update_210_remove_pages',
'wc_update_210_file_paths',
'wc_update_210_db_version',
'wc_update_220_shipping',
'wc_update_220_order_status',
'wc_update_220_variations',
'wc_update_220_attributes',
'wc_update_220_db_version',
'wc_update_230_db_version',
'wc_update_240_shipping_methods',
'wc_update_240_api_keys',
'wc_update_240_db_version',
'wc_update_241_variations',
'wc_update_241_db_version',
'wc_update_250_currency',
'wc_update_250_db_version',
'wc_update_260_termmeta',
'wc_update_260_zone_methods',
'wc_update_260_db_version',
'wc_update_300_grouped_products',
'wc_update_300_settings',
'wc_update_300_product_visibility',
'wc_update_300_db_version',
'wc_update_310_downloadable_products',
'wc_update_310_old_comments',
'wc_update_310_db_version',
'wc_update_312_shop_manager_capabilities',
'wc_update_312_db_version',
'wc_update_320_mexican_states',
'wc_update_320_db_version',
'wc_update_330_image_options',
'wc_update_330_webhooks',
'wc_update_330_product_stock_status',
'wc_update_330_set_default_product_cat',
'wc_update_330_clear_transients',
'wc_update_330_set_paypal_sandbox_credentials',
'wc_update_330_db_version',
'wc_update_340_last_active',
'wc_update_340_db_version',
'wc_update_343_cleanup_foreign_keys',
'wc_update_343_db_version',
'wc_update_344_recreate_roles',
'wc_update_344_db_version',
'wc_update_350_reviews_comment_type',
'wc_update_350_db_version',
'wc_update_352_drop_download_log_fk',
'wc_update_354_modify_shop_manager_caps',
'wc_update_354_db_version',
'wc_update_360_product_lookup_tables',
'wc_update_360_term_meta',
'wc_update_360_downloadable_product_permissions_index',
'wc_update_360_db_version',
'wc_update_370_tax_rate_classes',
'wc_update_370_mro_std_currency',
'wc_update_370_db_version',
'wc_update_390_move_maxmind_database',
'wc_update_390_change_geolocation_database_update_cron',
'wc_update_390_db_version',
'wc_update_product_lookup_tables',
'wc_update_400_increase_size_of_column',
'wc_update_400_reset_action_scheduler_migration_status',
'wc_admin_update_0201_order_status_index',
'wc_admin_update_0230_rename_gross_total',
'wc_admin_update_0251_remove_unsnooze_action',
'wc_update_400_db_version',
'wc_update_440_insert_attribute_terms_for_variable_products',
'wc_admin_update_110_remove_facebook_note',
'wc_admin_update_130_remove_dismiss_action_from_tracking_opt_in_note',
'wc_update_440_db_version',
'wc_update_450_sanitize_coupons_code',
'wc_update_450_db_version',
'wc_update_500_fix_product_review_count',
'wc_admin_update_160_remove_facebook_note',
'wc_admin_update_170_homescreen_layout',
'wc_update_500_db_version',
'wc_update_560_create_refund_returns_page',
'wc_update_560_db_version',
'wc_update_600_migrate_rate_limit_options',
'wc_admin_update_270_delete_report_downloads',
'wc_admin_update_271_update_task_list_options',
'wc_admin_update_280_order_status',
'wc_admin_update_290_update_apperance_task_option',
'wc_admin_update_290_delete_default_homepage_layout_option',
'wc_update_600_db_version',
'wc_update_630_create_product_attributes_lookup_table',
'wc_admin_update_300_update_is_read_from_last_read',
'wc_update_630_db_version',
'wc_update_640_add_primary_key_to_product_attributes_lookup_table',
'wc_admin_update_340_remove_is_primary_from_note_action',
'wc_update_640_db_version',
'wc_update_650_approved_download_directories',
'wc_update_651_approved_download_directories',
'wc_update_670_purge_comments_count_cache',
'wc_update_670_delete_deprecated_remote_inbox_notifications_option',
'wc_update_700_remove_download_log_fk',
'wc_update_700_remove_recommended_marketing_plugins_transient',
'wc_update_721_adjust_new_zealand_states',
'wc_update_721_adjust_ukraine_states',
'wc_update_722_adjust_new_zealand_states',
'wc_update_722_adjust_ukraine_states',
'wc_update_750_add_columns_to_order_stats_table',
'wc_update_750_disable_new_product_management_experience',
'wc_update_770_remove_multichannel_marketing_feature_options',
'wc_update_790_blockified_product_grid_block',
'wc_update_810_migrate_transactional_metadata_for_hpos',
'wc_update_830_rename_checkout_template',
'wc_update_830_rename_cart_template',
'wc_update_860_remove_recommended_marketing_plugins_transient',
'wc_update_870_prevent_listing_of_transient_files_directory',
'wc_update_890_update_connect_to_woocommerce_note',
'wc_update_890_update_paypal_standard_load_eligibility',
'wc_update_891_create_plugin_autoinstall_history_option',
'wc_update_910_add_launch_your_store_tour_option',
'wc_update_910_remove_obsolete_user_meta',
'wc_update_920_add_wc_hooked_blocks_version_option',
'wc_update_930_add_woocommerce_coming_soon_option',
'wc_update_930_migrate_user_meta_for_launch_your_store_tour',
'wc_update_940_add_phone_to_order_address_fts_index',
'wc_update_940_remove_help_panel_highlight_shown',
'wc_update_950_tracking_option_autoload',
'wc_update_961_migrate_default_email_base_color',
'wc_update_980_remove_order_attribution_install_banner_dismissed_option',
'wc_update_985_enable_new_payments_settings_page_feature',
'wc_update_990_remove_wc_count_comments_transient',
'wc_update_990_remove_email_notes',
'wc_update_1000_multisite_visibility_setting',
'wc_update_1000_remove_patterns_toolkit_transient',
'wc_update_1020_add_old_refunded_order_items_to_product_lookup_table',
'wc_update_1030_add_comments_date_type_index',
'wc_update_1040_add_idx_date_paid_status_parent',
'wc_update_1040_cleanup_legacy_ptk_patterns_fetching',
'wc_update_1050_migrate_brand_permalink_setting',
'wc_update_1050_enable_autoload_options',
'wc_update_1050_add_idx_user_email',
'wc_update_1050_remove_deprecated_marketplace_option',
'wc_update_1060_add_woo_idx_comment_approved_type_index',
* Option name used to track new installations of WooCommerce.
const NEWLY_INSTALLED_OPTION = 'woocommerce_newly_installed';
* Option name used to track new installation versions of WooCommerce.
const INITIAL_INSTALLED_VERSION = 'woocommerce_initial_installed_version';
* Option name used to uniquely identify installations of WooCommerce.
const STORE_ID_OPTION = 'woocommerce_store_id';
public static function init() {
if ( ! empty( $GLOBALS['wc_uninstalling_plugin'] ) ) {
add_action( 'init', array( __CLASS__, 'check_version' ), 5 );
add_action( 'init', array( __CLASS__, 'manual_database_update' ), 20 );
add_action( 'woocommerce_newly_installed', array( __CLASS__, 'maybe_enable_hpos' ), 20 );
add_action( 'woocommerce_newly_installed', array( __CLASS__, 'add_coming_soon_option' ), 20 );
add_action( 'woocommerce_newly_installed', array( __CLASS__, 'enable_email_improvements_for_newly_installed' ), 20 );
add_action( 'woocommerce_newly_installed', array( __CLASS__, 'enable_customer_stock_notifications_signups' ), 20 );
add_action( 'woocommerce_newly_installed', array( __CLASS__, 'enable_analytics_scheduled_import' ), 20 );
add_action( 'woocommerce_updated', array( __CLASS__, 'enable_email_improvements_for_existing_merchants' ), 20 );
add_action( 'woocommerce_run_update_callback', array( __CLASS__, 'run_update_callback' ) );
add_action( 'woocommerce_update_db_to_current_version', array( __CLASS__, 'update_db_version' ) );
add_action( 'admin_init', array( __CLASS__, 'install_actions' ) );
add_action( 'woocommerce_page_created', array( __CLASS__, 'page_created' ), 10, 2 );
add_filter( 'plugin_action_links_' . WC_PLUGIN_BASENAME, array( __CLASS__, 'plugin_action_links' ) );
add_filter( 'plugin_row_meta', array( __CLASS__, 'plugin_row_meta' ), 10, 2 );
add_filter( 'wpmu_drop_tables', array( __CLASS__, 'wpmu_drop_tables' ) );
add_filter( 'cron_schedules', array( __CLASS__, 'cron_schedules' ) );
add_action( 'admin_init', array( __CLASS__, 'newly_installed' ) );
add_action( 'woocommerce_activate_legacy_rest_api_plugin', array( __CLASS__, 'maybe_install_legacy_api_plugin' ) );
add_filter( 'woocommerce_get_note_from_db', array( \WC_Notes_Run_Db_Update::class, 'maybe_update_notice' ), 10 );
add_action( 'woocommerce_hide_update_notice', array( __CLASS__, 'remove_update_db_notice' ) );
* Trigger `woocommerce_newly_installed` action for new installations.
* @internal For exclusive usage of WooCommerce core, backwards compatibility not guaranteed.
public static function newly_installed() {
if ( 'yes' === get_option( self::NEWLY_INSTALLED_OPTION, false ) ) {
* Run when WooCommerce has been installed for the first time.
do_action( 'woocommerce_newly_installed' );
do_action_deprecated( 'woocommerce_admin_newly_installed', array(), '6.5.0', 'woocommerce_newly_installed' );
update_option( self::NEWLY_INSTALLED_OPTION, 'no' );
* This option is used to track the initial version of WooCommerce that was installed.
add_option( self::INITIAL_INSTALLED_VERSION, WC()->version, '', false );
* Check WooCommerce version and run the updater is required.
* This check is done on all requests and runs if the versions do not match.
public static function check_version() {
$wc_version = get_option( 'woocommerce_version' );
$wc_code_version = WC()->version;
$requires_update = version_compare( $wc_version, $wc_code_version, '<' );
if ( ! Constants::is_defined( 'IFRAME_REQUEST' ) && $requires_update ) {
* Run after WooCommerce has been updated.
do_action( 'woocommerce_updated' );
do_action_deprecated( 'woocommerce_admin_updated', array(), $wc_code_version, 'woocommerce_updated' );
* Performan manual database update when triggered by WooCommerce System Tools.
public static function manual_database_update() {
$blog_id = get_current_blog_id();
add_action( 'wp_' . $blog_id . '_wc_updater_cron', array( __CLASS__, 'run_manual_database_update' ) );
* Add WC Admin based db update notice.
public static function wc_admin_db_update_notice() {
WC()->is_wc_admin_active()
&& false !== get_option( 'woocommerce_admin_install_timestamp' )
new WC_Notes_Run_Db_Update();
* Adds the db update notice.
private static function add_update_db_notice() {
if ( ! \WC_Admin_Notices::has_notice( 'update' ) ) {
\WC_Admin_Notices::add_notice( 'update', true );
if ( WC()->is_wc_admin_active() && false !== get_option( 'woocommerce_admin_install_timestamp' ) ) {
\WC_Notes_Run_Db_Update::add_notice();
} catch ( Exception $e ) {
wc_get_logger()->error( 'Error adding db update note: ' . $e->getMessage(), array( 'source' => 'wc-updater' ) );
* Removes the db update notice.
public static function remove_update_db_notice() {
if ( \WC_Admin_Notices::has_notice( 'update' ) ) {
\WC_Admin_Notices::remove_notice( 'update', true );
if ( WC()->is_wc_admin_active() && false !== get_option( 'woocommerce_admin_install_timestamp' ) ) {
\WC_Notes_Run_Db_Update::set_notice_actioned();