diff --git a/plugins/woocommerce/changelog/fix-38682-newly-installed-hook b/plugins/woocommerce/changelog/fix-38682-newly-installed-hook new file mode 100644 index 00000000000..10e35e820b6 --- /dev/null +++ b/plugins/woocommerce/changelog/fix-38682-newly-installed-hook @@ -0,0 +1,4 @@ +Significance: minor +Type: fix + +Trigger "woocommerce_newly_installed" hook for new installations diff --git a/plugins/woocommerce/includes/class-wc-install.php b/plugins/woocommerce/includes/class-wc-install.php index 6fc5bb59934..33465f128c6 100644 --- a/plugins/woocommerce/includes/class-wc-install.php +++ b/plugins/woocommerce/includes/class-wc-install.php @@ -13,6 +13,7 @@ use Automattic\WooCommerce\Internal\ProductDownloads\ApprovedDirectories\Registe use Automattic\WooCommerce\Internal\ProductDownloads\ApprovedDirectories\Synchronize as Download_Directories_Sync; use Automattic\WooCommerce\Internal\Utilities\DatabaseUtil; use Automattic\WooCommerce\Internal\WCCom\ConnectionHelper as WCConnectionHelper; +use Automattic\WooCommerce\Internal\Traits\AccessiblePrivateMethods; defined( 'ABSPATH' ) || exit; @@ -20,6 +21,7 @@ defined( 'ABSPATH' ) || exit; * WC_Install Class. */ class WC_Install { + use AccessiblePrivateMethods; /** * DB updates and callbacks that need to be run per version. @@ -237,6 +239,13 @@ class WC_Install { ), ); + /** + * Option name used to track new installations of WooCommerce. + * + * @var string + */ + const NEWLY_INSTALLED_OPTION = 'woocommerce_newly_installed'; + /** * Hook in tabs. */ @@ -253,6 +262,26 @@ class WC_Install { 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' ) ); + self::add_action( 'admin_init', array( __CLASS__, 'newly_installed' ) ); + } + + /** + * Trigger `woocommerce_newly_installed` action for new installations. + * + * @since 8.0.0 + */ + private static function newly_installed() { + if ( 'yes' === get_option( self::NEWLY_INSTALLED_OPTION, false ) ) { + /** + * Run when WooCommerce has been installed for the first time. + * + * @since 6.5.0 + */ + 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' ); + } } /** @@ -273,16 +302,6 @@ class WC_Install { */ do_action( 'woocommerce_updated' ); do_action_deprecated( 'woocommerce_admin_updated', array(), $wc_code_version, 'woocommerce_updated' ); - // If there is no woocommerce_version option, consider it as a new install. - if ( ! $wc_version ) { - /** - * Run when WooCommerce has been installed for the first time. - * - * @since 6.5.0 - */ - do_action( 'woocommerce_newly_installed' ); - do_action_deprecated( 'woocommerce_admin_newly_installed', array(), $wc_code_version, 'woocommerce_newly_installed' ); - } } } @@ -394,6 +413,10 @@ class WC_Install { set_transient( 'wc_installing', 'yes', MINUTE_IN_SECONDS * 10 ); wc_maybe_define_constant( 'WC_INSTALLING', true ); + if ( self::is_new_install() && ! get_option( self::NEWLY_INSTALLED_OPTION, false ) ) { + update_option( self::NEWLY_INSTALLED_OPTION, 'yes' ); + } + WC()->wpdb_table_fix(); self::remove_admin_notices(); self::create_tables(); diff --git a/plugins/woocommerce/src/Internal/Admin/Notes/CouponPageMoved.php b/plugins/woocommerce/src/Internal/Admin/Notes/CouponPageMoved.php index 778b74968f3..0ddafe28adb 100644 --- a/plugins/woocommerce/src/Internal/Admin/Notes/CouponPageMoved.php +++ b/plugins/woocommerce/src/Internal/Admin/Notes/CouponPageMoved.php @@ -35,7 +35,7 @@ class CouponPageMoved { add_action( 'admin_init', [ $this, 'possibly_add_note' ] ); add_action( 'admin_init', [ $this, 'redirect_to_coupons' ] ); - add_action( 'woocommerce_admin_newly_installed', [ $this, 'disable_legacy_menu_for_new_install' ] ); + add_action( 'woocommerce_newly_installed', [ $this, 'disable_legacy_menu_for_new_install' ] ); } /** diff --git a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/install.php b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/install.php index 96e736ba032..e5c91b6e445 100644 --- a/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/install.php +++ b/plugins/woocommerce/tests/legacy/unit-tests/woocommerce-admin/install.php @@ -132,13 +132,19 @@ class WC_Admin_Tests_Install extends WP_UnitTestCase { * Test the following options are created. * * - woocommerce_admin_install_timestamp + * - WC_Install::NEWLY_INSTALLED_OPTION * * @return void */ public function test_options_are_set() { delete_transient( 'wc_installing' ); WC_Install::install(); - $options = array( 'woocommerce_admin_install_timestamp' ); + + $options = array( + 'woocommerce_admin_install_timestamp', + WC_Install::NEWLY_INSTALLED_OPTION, + ); + foreach ( $options as $option ) { $this->assertNotFalse( get_option( $option ) ); } @@ -168,13 +174,19 @@ class WC_Admin_Tests_Install extends WP_UnitTestCase { } /** - * Test woocommerce_newly_installed action gets fired. + * Test woocommerce_newly_installed action gets fired and the option is set to 'no'. + * * @return void */ public function test_woocommerce_newly_installed_action() { - delete_option( 'woocommerce_version' ); - WC_Install::check_version(); - $this->assertTrue( did_action( 'woocommerce_newly_installed' ) > 0 ); + update_option( WC_Install::NEWLY_INSTALLED_OPTION, 'yes' ); + + // Call twice to ensure `woocommerce_newly_installed` is only triggered once. + WC_Install::newly_installed(); + WC_Install::newly_installed(); + + $this->assertTrue( 1 === did_action( 'woocommerce_newly_installed' ) ); + $this->assertEquals( get_option( WC_Install::NEWLY_INSTALLED_OPTION ), 'no' ); } /**