-
Notifications
You must be signed in to change notification settings - Fork 49
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(wcs): add expired subscription cli tool (#3593)
This PR adds a cli command to migrate the status of all on-hold subscriptions that have failed all retries to expired
- Loading branch information
1 parent
398e370
commit 463c063
Showing
2 changed files
with
186 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,184 @@ | ||
<?php | ||
/** | ||
* WooCommerce Subscriptions Integration CLI commands. | ||
* | ||
* @package Newspack | ||
*/ | ||
|
||
namespace Newspack\CLI; | ||
|
||
use WP_CLI; | ||
use Newspack\Woocommerce_Subscriptions as WooCommerce_Subscriptions_Integration; | ||
|
||
defined( 'ABSPATH' ) || exit; | ||
|
||
/** | ||
* WooCommerce Subscriptions Integration CLI commands. | ||
*/ | ||
class WooCommerce_Subscriptions { | ||
/** | ||
* Flag for live mode. | ||
* | ||
* @var bool | ||
*/ | ||
private static $live = false; | ||
|
||
/** | ||
* Flag for verbose output. | ||
* | ||
* @var bool | ||
*/ | ||
private static $verbose = false; | ||
|
||
/** | ||
* Subscription ids to process. | ||
* | ||
* @var bool|array | ||
*/ | ||
private static $ids = false; | ||
|
||
/** | ||
* Migrate status of on-hold WooCommerce subscriptions that have failed all payment retries to expired. | ||
* | ||
* ## OPTIONS | ||
* | ||
* [--live] | ||
* : Run the command in live mode, updating the subscriptions. | ||
* | ||
* [--verbose] | ||
* : Produce more output. | ||
* | ||
* [--ids] | ||
* : Comma-separated list of subscription IDs. If provided, only ubscriptions with these IDs will be processed. | ||
* | ||
* @param array $args Positional arguments. | ||
* @param array $assoc_args Assoc arguments. | ||
* | ||
* @return void | ||
*/ | ||
public function migrate_expired_subscriptions( $args, $assoc_args ) { | ||
WP_CLI::line( '' ); | ||
if ( ! WooCommerce_Subscriptions_Integration::is_enabled() ) { | ||
WP_CLI::error( 'WooCommerce Subscriptions Integration is not enabled.' ); | ||
WP_CLI::line( '' ); | ||
return; | ||
} | ||
self::$ids = isset( $assoc_args['ids'] ) ? explode( ',', $assoc_args['ids'] ) : false; | ||
self::$live = isset( $assoc_args['live'] ) ? true : false; | ||
self::$verbose = isset( $assoc_args['verbose'] ) ? true : false; | ||
$updated = 0; | ||
$page = 1; | ||
$per_page = 25; | ||
$subscriptions = self::get_subscriptions( $page ); | ||
if ( empty( $subscriptions ) ) { | ||
WP_CLI::success( 'No on-hold subscriptions to process.' ); | ||
WP_CLI::line( '' ); | ||
return; | ||
} | ||
WP_CLI::line( 'Processing subscriptions in ' . ( self::$live ? 'live' : 'dry run' ) . ' mode...' ); | ||
WP_CLI::line( '' ); | ||
while ( ! empty( $subscriptions ) ) { | ||
foreach ( $subscriptions as $subscription ) { | ||
$id = $subscription->get_id(); | ||
if ( self::$verbose ) { | ||
WP_CLI::line( 'Processing subscription ' . $id . '...' ); | ||
} | ||
// A pending retry indicates the subscription is awaiting payment retry. | ||
if ( $subscription->get_date( 'payment_retry' ) > 0 ) { | ||
if ( self::$verbose ) { | ||
WP_CLI::line( 'Subscription is awaiting payment retry. Moving to next subscription...' ); | ||
WP_CLI::line( '' ); | ||
} | ||
continue; | ||
} | ||
$renewal_order = $subscription->get_last_order( | ||
'all', | ||
[ 'renewal' ], | ||
[ | ||
'completed', | ||
'processing', | ||
'refunded', | ||
] | ||
); | ||
// No failed or pending renewal orders indicates the subscription was likely manually placed on hold. | ||
if ( empty( $renewal_order ) ) { | ||
if ( self::$verbose ) { | ||
WP_CLI::line( 'Subscription has no pending renewal orders. Moving to next subscription...' ); | ||
WP_CLI::line( '' ); | ||
} | ||
continue; | ||
} | ||
$last_retry = \WCS_Retry_Manager::store()->get_last_retry_for_order( wcs_get_objects_property( $renewal_order, 'id' ) ); | ||
// No retries indicates the subscription was likely manually placed on hold. | ||
if ( empty( $last_retry ) ) { | ||
if ( self::$verbose ) { | ||
WP_CLI::line( 'No retries scheduled. Moving to next subscription...' ); | ||
WP_CLI::line( '' ); | ||
} | ||
continue; | ||
} | ||
// A non failed status indicates the retry was either manually cancelled | ||
// or was successful at one point but likely placed on hold for some other reason. | ||
if ( 'failed' !== $last_retry->get_status() ) { | ||
if ( self::$verbose ) { | ||
WP_CLI::line( 'Last retry does not have a failed status. Moving to next subscription...' ); | ||
WP_CLI::line( '' ); | ||
} | ||
continue; | ||
} else { | ||
if ( self::$verbose ) { | ||
WP_CLI::line( 'Updating subscription status to expired...' ); | ||
} | ||
if ( self::$live ) { | ||
$subscription->update_status( 'expired', __( 'Subscription status updated by Newspack CLI command.', 'newspack-plugin' ) ); | ||
$subscription->set_end_date( $last_retry->get_date() ); | ||
$subscription->save(); | ||
} | ||
++$updated; | ||
} | ||
if ( self::$verbose ) { | ||
WP_CLI::line( 'Finished processing subscription ' . $id ); | ||
WP_CLI::line( '' ); | ||
} | ||
} | ||
$subscriptions = self::get_subscriptions( ++$page ); | ||
} | ||
WP_CLI::success( 'Finished processing subscriptions. ' . $updated . ' subscriptions updated.' ); | ||
if ( ! self::$live ) { | ||
WP_CLI::warning( 'Dry run. Use --live flag to process live subscriptions.' ); | ||
} | ||
WP_CLI::line( '' ); | ||
} | ||
|
||
/** | ||
* Get subscriptions to process. | ||
* | ||
* @param int $page Page number. | ||
* | ||
* @return array | ||
*/ | ||
private static function get_subscriptions( $page = 1 ) { | ||
$subscriptions = []; | ||
if ( false !== self::$ids ) { | ||
while ( ! empty( self::$ids ) ) { | ||
$id = array_shift( self::$ids ); | ||
if ( ! is_numeric( $id ) ) { | ||
continue; | ||
} | ||
$subscription = wcs_get_subscription( $id ); | ||
if ( $subscription ) { | ||
$subscriptions[] = $subscription; | ||
} | ||
} | ||
} else { | ||
$subscriptions = wcs_get_subscriptions( | ||
[ | ||
'paged' => $page, | ||
'subscriptions_per_page' => 25, | ||
'subscription_status' => 'on-hold', | ||
] | ||
); | ||
} | ||
return $subscriptions; | ||
} | ||
} |