From a64e227fdcc4539b73d98e7b2a10a7d5d6007c1c Mon Sep 17 00:00:00 2001 From: And Finally Date: Mon, 30 Sep 2024 15:49:58 +0100 Subject: [PATCH] Fetch promotions in a WP Cron job (#51650) * Getting promotions in a WP Cron job to make them async. We don't want this request to affect the performance of wp-admin. See https://github.com/woocommerce/woocommerce/pull/47262#pullrequestreview-2241835763. * Changelog. * Made callback method `update_promotions` public. * Linter errors. Whitespace. --- ...update-wccom-21774-update-promotions-async | 4 ++ .../class-wc-admin-marketplace-promotions.php | 53 +++++++++++++++---- 2 files changed, 46 insertions(+), 11 deletions(-) create mode 100644 plugins/woocommerce/changelog/update-wccom-21774-update-promotions-async diff --git a/plugins/woocommerce/changelog/update-wccom-21774-update-promotions-async b/plugins/woocommerce/changelog/update-wccom-21774-update-promotions-async new file mode 100644 index 00000000000..8109aa78d61 --- /dev/null +++ b/plugins/woocommerce/changelog/update-wccom-21774-update-promotions-async @@ -0,0 +1,4 @@ +Significance: minor +Type: update + +Changed how we fetch WooCommerce promotions. We're doing it async so as not to affect the loading of wp-admin. diff --git a/plugins/woocommerce/includes/admin/class-wc-admin-marketplace-promotions.php b/plugins/woocommerce/includes/admin/class-wc-admin-marketplace-promotions.php index 02aedbd9556..6026fcbb020 100644 --- a/plugins/woocommerce/includes/admin/class-wc-admin-marketplace-promotions.php +++ b/plugins/woocommerce/includes/admin/class-wc-admin-marketplace-promotions.php @@ -15,6 +15,7 @@ if ( ! defined( 'ABSPATH' ) ) { */ class WC_Admin_Marketplace_Promotions { + const CRON_NAME = 'woocommerce_marketplace_cron_fetch_promotions'; const TRANSIENT_NAME = 'woocommerce_marketplace_promotions_v2'; const TRANSIENT_LIFE_SPAN = DAY_IN_SECONDS; const PROMOTIONS_API_URL = 'https://woocommerce.com/wp-json/wccom-extensions/3.0/promotions'; @@ -39,7 +40,16 @@ class WC_Admin_Marketplace_Promotions { public static function init() { // A legacy hook that can be triggered by action scheduler. add_action( 'woocommerce_marketplace_fetch_promotions', array( __CLASS__, 'clear_deprecated_action' ) ); - add_action( 'woocommerce_marketplace_fetch_promotions_clear', array( __CLASS__, 'clear_scheduled_event' ) ); + add_action( + 'woocommerce_marketplace_fetch_promotions_clear', + array( + __CLASS__, + 'clear_deprecated_scheduled_event', + ) + ); + + // Fetch promotions from the API and store them in a transient. + add_action( self::CRON_NAME, array( __CLASS__, 'update_promotions' ) ); if ( defined( 'DOING_AJAX' ) && DOING_AJAX @@ -53,24 +63,33 @@ class WC_Admin_Marketplace_Promotions { return; } - self::maybe_update_promotions(); + self::schedule_cron_event(); + + register_deactivation_hook( WC_PLUGIN_FILE, array( __CLASS__, 'clear_cron_event' ) ); self::$locale = ( self::$locale ?? get_user_locale() ) ?? 'en_US'; self::maybe_show_bubble_promotions(); } /** - * Fetch promotions from the API and store them in a transient. - * Fetching can be suppressed by the `woocommerce_marketplace_suppress_promotions` filter. + * Schedule a daily cron event to fetch promotions. + * + * @version 9.5.0 * * @return void */ - private static function maybe_update_promotions() { - // Fetch promotions if they're not in the transient. - if ( false !== get_transient( self::TRANSIENT_NAME ) ) { - return; + private static function schedule_cron_event() { + if ( ! wp_next_scheduled( self::CRON_NAME ) ) { + wp_schedule_event( time(), 'daily', self::CRON_NAME ); } + } + /** + * Fetch promotions from the API and store them in a transient. + * + * @return void + */ + public static function update_promotions() { // Fetch promotions from the API. $promotions = self::fetch_marketplace_promotions(); set_transient( self::TRANSIENT_NAME, $promotions, self::TRANSIENT_LIFE_SPAN ); @@ -326,12 +345,24 @@ class WC_Admin_Marketplace_Promotions { } /** - * Clear the scheduled action that was used to fetch promotions in WooCommerce 8.8. - * It's no longer needed as a transient is used to store the data. + * When WooCommerce is disabled, clear the WP Cron event we use to fetch promotions. + * + * @version 9.5.0 * * @return void */ - public static function clear_scheduled_event() { + public static function clear_cron_event() { + $timestamp = wp_next_scheduled( self::CRON_NAME ); + wp_unschedule_event( $timestamp, self::CRON_NAME ); + } + + /** + * Clear deprecated scheduled action that was used to fetch promotions in WooCommerce 8.8. + * Replaced with a transient in WooCommerce 9.0. + * + * @return void + */ + public static function clear_deprecated_scheduled_event() { if ( function_exists( 'as_unschedule_all_actions' ) ) { as_unschedule_all_actions( 'woocommerce_marketplace_fetch_promotions' ); }