From 5b14aebd98a7513ca3f254339f1315175389aee6 Mon Sep 17 00:00:00 2001 From: Rasmy Nguyen Date: Mon, 2 Dec 2024 16:41:59 -0500 Subject: [PATCH] feat(woocommerce-subscriptions): add url redirect for wc subscription renewals (#3525) This PR adds handling for a new `my-account/renew-subscription` endpoint to redirect readers to the first available pending renewal checkout, otherwise the subscriptions my account page. --- .../class-renewal.php | 127 ++++++++++++++++++ .../class-woocommerce-subscriptions.php | 21 ++- .../class-reader-activation.php | 15 ++- src/reader-activation-auth/auth-form.js | 6 +- 4 files changed, 158 insertions(+), 11 deletions(-) create mode 100644 includes/plugins/woocommerce-subscriptions/class-renewal.php diff --git a/includes/plugins/woocommerce-subscriptions/class-renewal.php b/includes/plugins/woocommerce-subscriptions/class-renewal.php new file mode 100644 index 0000000000..802317d78c --- /dev/null +++ b/includes/plugins/woocommerce-subscriptions/class-renewal.php @@ -0,0 +1,127 @@ + Subscriptions page. + * + * @return string + */ + public static function get_subscriptions_url() { + return wc_get_account_endpoint_url( 'subscriptions' ); + } + + /** + * Returns true when on the My Account > Subscriptions front end page. + * + * @return bool + */ + public static function is_subscriptions_page() { + if ( ! WooCommerce_Subscriptions::is_active() ) { + return false; + } + return is_wc_endpoint_url( 'subscriptions' ); + } + + /** + * Conditionally redirects the renewal endpoint url. + * + * @param \WP_Query $query Query object. + */ + public static function maybe_redirect_renewal_endpoint( $query ) { // phpcs:ignore WordPressVIPMinimum.Hooks.AlwaysReturnInFilter.VoidReturn, WordPressVIPMinimum.Hooks.AlwaysReturnInFilter.MissingReturnStatement + if ( + ! $query->is_main_query() || + ! isset( $query->query_vars[ self::RENEWAL_ENDPOINT ] ) + ) { + return; + } + $redirect_url = wc_get_account_endpoint_url( 'subscriptions' ); + if ( is_user_logged_in() ) { + $pending_renewal = wcs_get_subscriptions( + [ + 'customer_id' => get_current_user_id(), + 'subscription_status' => [ + 'pending', + 'on-hold', + ], + ] + ); + if ( count( $pending_renewal ) === 1 ) { + $orders = array_pop( $pending_renewal )->get_related_orders( 'all', 'renewal' ); + foreach ( $orders as $order ) { + if ( $order->needs_payment() ) { + $redirect_url = $order->get_checkout_payment_url(); + break; + } + } + } + } else { + $redirect_url .= '?redirect=' . wc_get_account_endpoint_url( self::RENEWAL_ENDPOINT ); + } + wp_safe_redirect( $redirect_url ); + exit(); + } + + /** + * Refresh permalinks the first time this feature is enabled. + */ + private static function flush_rewrite_rules() { + if ( ! get_option( 'newspack_subscriptions_renewal_permalinks_refreshed', false ) ) { + flush_rewrite_rules(); // phpcs:ignore WordPressVIPMinimum.Functions.RestrictedFunctions.flush_rewrite_rules_flush_rewrite_rules + update_option( 'newspack_subscriptions_renewal_permalinks_refreshed', true ); + } + } +} diff --git a/includes/plugins/woocommerce-subscriptions/class-woocommerce-subscriptions.php b/includes/plugins/woocommerce-subscriptions/class-woocommerce-subscriptions.php index f61529cf0f..7ff67e3d6e 100644 --- a/includes/plugins/woocommerce-subscriptions/class-woocommerce-subscriptions.php +++ b/includes/plugins/woocommerce-subscriptions/class-woocommerce-subscriptions.php @@ -17,13 +17,25 @@ class WooCommerce_Subscriptions { * Initialize hooks and filters. */ public static function init() { + add_action( 'plugins_loaded', [ __CLASS__, 'woocommerce_subscriptions_integration_init' ] ); + } + + /** + * Initialize WooCommerce Subscriptions Integration. + */ + public static function woocommerce_subscriptions_integration_init() { + // To be included only if WooCommerce Subscriptions Integration is enabled. + // See is_enabled() method. if ( self::is_enabled() ) { include_once __DIR__ . '/class-on-hold-duration.php'; - On_Hold_Duration::init(); } + + include_once __DIR__ . '/class-renewal.php'; + Renewal::init(); } + /** * Check if WooCommerce Subscriptions is active. * @@ -36,12 +48,15 @@ public static function is_active() { /** * Check if WooCommerce Subscriptions Integration is enabled. * - * Enalbed if Reader activation is enabled and the feature flag is defined. + * True if: + * - WooCommerce Subscriptions is active and, + * - Reader Activation is enabled and, + * - The NEWSPACK_SUBSCRIPTIONS_EXPIRATION feature flag is defined * * @return bool */ public static function is_enabled() { - return Reader_Activation::is_enabled() && defined( 'NEWSPACK_SUBSCRIPTIONS_EXPIRATION' ) && NEWSPACK_SUBSCRIPTIONS_EXPIRATION; + return self::is_active() && Reader_Activation::is_enabled() && defined( 'NEWSPACK_SUBSCRIPTIONS_EXPIRATION' ) && NEWSPACK_SUBSCRIPTIONS_EXPIRATION; } } WooCommerce_Subscriptions::init(); diff --git a/includes/reader-activation/class-reader-activation.php b/includes/reader-activation/class-reader-activation.php index bbe44d5802..3d9cca7632 100644 --- a/includes/reader-activation/class-reader-activation.php +++ b/includes/reader-activation/class-reader-activation.php @@ -9,6 +9,7 @@ use Newspack\Recaptcha; use Newspack\Reader_Activation\Sync; +use Newspack\Renewal; defined( 'ABSPATH' ) || exit; @@ -1330,10 +1331,16 @@ public static function render_auth_form( $in_modal = true ) { $referer = \wp_parse_url( \wp_get_referer() ); $labels = self::get_reader_activation_labels( 'signin' ); - $auth_callback_url = '#'; - // If we are already on the my account page, set the my account URL so the page reloads on submit. - if ( function_exists( 'wc_get_page_permalink' ) && function_exists( 'is_account_page' ) && \is_account_page() ) { - $auth_callback_url = \wc_get_page_permalink( 'myaccount' ); + // If there is a redirect parameter, use it as the auth callback URL. + $auth_callback_url = filter_input( INPUT_GET, 'redirect', FILTER_SANITIZE_URL ) ?? '#'; + if ( '#' === $auth_callback_url ) { + if ( Renewal::is_subscriptions_page() ) { + // If we are on the subscriptions page, set the auth callback URL to the subscriptions page. + $auth_callback_url = Renewal::get_subscriptions_url(); + } elseif ( function_exists( 'wc_get_page_permalink' ) && function_exists( 'is_account_page' ) && \is_account_page() ) { + // If we are already on the my account page, set the my account URL so the page reloads on submit. + $auth_callback_url = \wc_get_page_permalink( 'myaccount' ); + } } ?>
diff --git a/src/reader-activation-auth/auth-form.js b/src/reader-activation-auth/auth-form.js index e17f121cab..c627363da7 100644 --- a/src/reader-activation-auth/auth-form.js +++ b/src/reader-activation-auth/auth-form.js @@ -323,12 +323,10 @@ window.newspackRAS.push( function ( readerActivation ) { container.querySelector( '.success-description' ).innerHTML = labels.success_description || ''; const callbackButton = container.querySelector( '.auth-callback' ); - if ( callbackButton ) { + if ( callbackButton && callback ) { callbackButton.addEventListener( 'click', ev => { ev.preventDefault(); - if ( callback ) { - callback( message, data ); - } + callback( message, data ); } ); }