mirror of
https://github.com/pronamic/woocommerce-subscriptions.git
synced 2025-10-07 01:54:05 +00:00
2533 lines
111 KiB
PHP
2533 lines
111 KiB
PHP
<?php
|
||
/**
|
||
* Subscriptions Management Class
|
||
*
|
||
* An API of Subscription utility functions and Account Management functions.
|
||
*
|
||
* Subscription activation and cancellation functions are hooked directly to order status changes
|
||
* so your payment gateway only needs to work with WooCommerce APIs. You can however call other
|
||
* management functions directly when necessary.
|
||
*
|
||
* @package WooCommerce Subscriptions
|
||
* @subpackage WC_Subscriptions_Manager
|
||
* @category Class
|
||
* @author Brent Shepherd
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.0
|
||
*/
|
||
class WC_Subscriptions_Manager {
|
||
|
||
/**
|
||
* The database key for user's subscriptions.
|
||
*
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.0
|
||
*/
|
||
public static $users_meta_key = 'woocommerce_subscriptions';
|
||
|
||
/**
|
||
* Set up the class, including it's hooks & filters, when the file is loaded.
|
||
*
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.0
|
||
**/
|
||
public static function init() {
|
||
// When an order's status is changed, run the appropriate subscription function
|
||
add_action( 'woocommerce_order_status_cancelled', __CLASS__ . '::cancel_subscriptions_for_order' );
|
||
add_action( 'woocommerce_order_status_failed', __CLASS__ . '::failed_subscription_sign_ups_for_order' );
|
||
add_action( 'woocommerce_order_status_on-hold', __CLASS__ . '::put_subscription_on_hold_for_order' );
|
||
|
||
// Expire a user's subscription
|
||
add_action( 'woocommerce_scheduled_subscription_expiration', __CLASS__ . '::expire_subscription', 10, 1 );
|
||
|
||
// Expire a user's subscription
|
||
add_action( 'woocommerce_scheduled_subscription_end_of_prepaid_term', __CLASS__ . '::subscription_end_of_prepaid_term', 10, 1 );
|
||
|
||
// Check if the subscription needs to use the failed payment process to repair its status
|
||
add_action( 'woocommerce_scheduled_subscription_payment', __CLASS__ . '::maybe_process_failed_renewal_for_repair', 0, 1 );
|
||
|
||
// Whenever a renewal payment is due, put the subscription on hold and create a renewal order before anything else, in case things don't go to plan
|
||
add_action( 'woocommerce_scheduled_subscription_payment', __CLASS__ . '::prepare_renewal', 1, 1 );
|
||
|
||
// When a subscriptions trial end scheduled action is run, attach a callback to trigger a subscription specific trial ended hook.
|
||
add_action( 'woocommerce_scheduled_subscription_trial_end', __CLASS__ . '::trigger_subscription_trial_ended_hook', 10, 1 );
|
||
|
||
// Attach hooks that depend on WooCommerce being loaded.
|
||
add_action( 'woocommerce_loaded', [ __CLASS__, 'attach_wc_dependant_hooks' ] );
|
||
|
||
// When a user is being deleted from the site, via standard WordPress functions, make sure their subscriptions are cancelled
|
||
add_action( 'delete_user', __CLASS__ . '::trash_users_subscriptions' );
|
||
|
||
// Do the same thing for WordPress networks
|
||
add_action( 'wpmu_delete_user', __CLASS__ . '::trash_users_subscriptions_for_network' );
|
||
|
||
add_filter( 'woocommerce_cancel_unpaid_order', [ __CLASS__, 'exclude_subscription_from_order_cleanup' ], 10, 2 );
|
||
}
|
||
|
||
/**
|
||
* Attaches hooks that depend on WooCommerce being loaded.
|
||
*
|
||
* We need to use different hooks on stores that have HPOS enabled but to check if this feature
|
||
* is enabled, we must wait for WooCommerce to be loaded first.
|
||
*
|
||
* @since 5.2.0
|
||
*/
|
||
public static function attach_wc_dependant_hooks() {
|
||
if ( wcs_is_custom_order_tables_usage_enabled() ) {
|
||
// When a parent order is trashed, untrashed or deleted, make sure the appropriate action is taken on the related subscription
|
||
add_action( 'woocommerce_before_trash_order', [ __CLASS__, 'maybe_trash_subscription' ], 10 );
|
||
add_action( 'woocommerce_untrash_order', [ __CLASS__, 'maybe_untrash_subscription' ], 10 );
|
||
add_action( 'woocommerce_before_delete_order', [ __CLASS__, 'maybe_delete_subscription' ] );
|
||
|
||
// make sure a subscription is cancelled before it is trashed/deleted
|
||
add_action( 'woocommerce_before_trash_subscription', [ __CLASS__, 'maybe_cancel_subscription' ], 10, 1 );
|
||
add_action( 'woocommerce_before_delete_subscription', [ __CLASS__, 'maybe_cancel_subscription' ], 10, 1 );
|
||
|
||
// set correct status to restore after a subscription is trashed/deleted
|
||
add_action( 'woocommerce_trash_subscription', [ __CLASS__, 'fix_trash_meta_status' ] );
|
||
} else {
|
||
// When a parent order is trashed, untrashed or deleted, make sure the appropriate action is taken on the related subscription
|
||
add_action( 'wp_trash_post', __CLASS__ . '::maybe_trash_subscription', 10 );
|
||
add_action( 'untrashed_post', __CLASS__ . '::maybe_untrash_subscription', 10 );
|
||
add_action( 'before_delete_post', array( __CLASS__, 'maybe_delete_subscription' ) );
|
||
|
||
// make sure a subscription is cancelled before it is trashed/deleted
|
||
add_action( 'wp_trash_post', __CLASS__ . '::maybe_cancel_subscription', 10, 1 );
|
||
add_action( 'before_delete_post', __CLASS__ . '::maybe_cancel_subscription', 10, 1 );
|
||
|
||
// set correct status to restore after a subscription is trashed/deleted
|
||
add_action( 'trashed_post', __CLASS__ . '::fix_trash_meta_status' );
|
||
|
||
// call special hooks when a subscription is trashed/deleted
|
||
add_action( 'trashed_post', __CLASS__ . '::trigger_subscription_trashed_hook' );
|
||
add_action( 'deleted_post', __CLASS__ . '::trigger_subscription_deleted_hook' );
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Sets up renewal for subscriptions managed by Subscriptions.
|
||
*
|
||
* This function is hooked early on the scheduled subscription payment hook.
|
||
*
|
||
* @param int $subscription_id The ID of a 'shop_subscription' post
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v2.0
|
||
*/
|
||
public static function prepare_renewal( $subscription_id ) {
|
||
|
||
$order_note = _x( 'Subscription renewal payment due:', 'used in order note as reason for why subscription status changed', 'woocommerce-subscriptions' );
|
||
|
||
$renewal_order = self::process_renewal( $subscription_id, 'active', $order_note );
|
||
|
||
// Backward compatibility with Subscriptions < 2.2.12 where we returned false for an unknown reason
|
||
if ( false === $renewal_order ) {
|
||
return $renewal_order;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Process renewal for a subscription.
|
||
*
|
||
* @param int $subscription_id The ID of a 'shop_subscription' post
|
||
* @param string $required_status The subscription status required to process a renewal order
|
||
* @param string $order_note Reason for subscription status change
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v2.2.12
|
||
*/
|
||
public static function process_renewal( $subscription_id, $required_status, $order_note ) {
|
||
|
||
$subscription = wcs_get_subscription( $subscription_id );
|
||
|
||
// If the subscription is using manual payments, the gateway isn't active or it manages scheduled payments
|
||
if ( ! empty( $subscription ) && $subscription->has_status( $required_status ) && ( 0 == $subscription->get_total() || $subscription->is_manual() || '' == $subscription->get_payment_method() || ! $subscription->payment_method_supports( 'gateway_scheduled_payments' ) ) ) {
|
||
|
||
// Always put the subscription on hold in case something goes wrong while trying to process renewal
|
||
$subscription->update_status( 'on-hold', $order_note );
|
||
|
||
// Generate a renewal order for payment gateways to use to record the payment (and determine how much is due)
|
||
$renewal_order = wcs_create_renewal_order( $subscription );
|
||
|
||
if ( is_wp_error( $renewal_order ) ) {
|
||
// let's try this again
|
||
$renewal_order = wcs_create_renewal_order( $subscription );
|
||
|
||
if ( is_wp_error( $renewal_order ) ) {
|
||
// translators: placeholder %1 is an order note. %2 is the error message that was thrown.
|
||
throw new Exception( sprintf( __( 'Error: Unable to create renewal order with note "%1$s". Message: %2$s', 'woocommerce-subscriptions' ), $order_note, $renewal_order->get_error_message() ) );
|
||
}
|
||
}
|
||
|
||
if ( 0 == $renewal_order->get_total() ) {
|
||
$renewal_order->payment_complete(); // We don't need to reactivate the subscription here because calling payment complete on the order will do that for us.
|
||
} else {
|
||
|
||
if ( $subscription->is_manual() ) {
|
||
do_action( 'woocommerce_generated_manual_renewal_order', wcs_get_objects_property( $renewal_order, 'id' ), $subscription );
|
||
$renewal_order->add_order_note( __( 'Manual renewal order awaiting customer payment.', 'woocommerce-subscriptions' ) );
|
||
} else {
|
||
$renewal_order->set_payment_method( wc_get_payment_gateway_by_order( $subscription ) ); // We need to pass the payment gateway instance to be compatible with WC < 3.0, only WC 3.0+ supports passing the string name
|
||
|
||
if ( is_callable( array( $renewal_order, 'save' ) ) ) { // WC 3.0+ We need to save the payment method.
|
||
$renewal_order->save();
|
||
}
|
||
}
|
||
}
|
||
} else {
|
||
$renewal_order = false;
|
||
}
|
||
|
||
return $renewal_order;
|
||
}
|
||
|
||
/**
|
||
* Expires a single subscription on a users account.
|
||
*
|
||
* @param int $subscription_id The ID of a 'shop_subscription' post
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.0
|
||
*/
|
||
public static function expire_subscription( $subscription_id, $deprecated = null ) {
|
||
|
||
if ( null !== $deprecated ) {
|
||
_deprecated_argument( __METHOD__, '2.0', 'The subscription key is deprecated. Use a subscription post ID' );
|
||
$subscription = wcs_get_subscription_from_key( $deprecated );
|
||
} else {
|
||
$subscription = wcs_get_subscription( $subscription_id );
|
||
}
|
||
|
||
if ( false === $subscription ) {
|
||
// translators: placeholder is a subscription ID.
|
||
throw new InvalidArgumentException( sprintf( __( 'Subscription doesn\'t exist in scheduled action: %d', 'woocommerce-subscriptions' ), $subscription_id ) );
|
||
}
|
||
|
||
$subscription->update_status( 'expired' );
|
||
}
|
||
|
||
/**
|
||
* Fires when a cancelled subscription reaches the end of its prepaid term.
|
||
*
|
||
* @param int $subscription_id The ID of a 'shop_subscription' post
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.3
|
||
*/
|
||
public static function subscription_end_of_prepaid_term( $subscription_id, $deprecated = null ) {
|
||
|
||
if ( null !== $deprecated ) {
|
||
_deprecated_argument( __METHOD__, '2.0', 'The subscription key is deprecated. Use a subscription post ID' );
|
||
$subscription = wcs_get_subscription_from_key( $deprecated );
|
||
} else {
|
||
$subscription = wcs_get_subscription( $subscription_id );
|
||
}
|
||
|
||
if ( $subscription ) {
|
||
$subscription->update_status( 'cancelled' );
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Trigger action hook after a subscription's trial period has ended.
|
||
*
|
||
* @since 5.5.0
|
||
*
|
||
* @param int $subscription_id
|
||
*/
|
||
public static function trigger_subscription_trial_ended_hook( $subscription_id ) {
|
||
do_action( 'woocommerce_subscription_trial_ended', $subscription_id );
|
||
}
|
||
|
||
/**
|
||
* Records a payment on a subscription.
|
||
*
|
||
* @param int $user_id The id of the user who owns the subscription.
|
||
* @param string $subscription_key A subscription key of the form obtained by @see get_subscription_key( $order_id, $product_id )
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.0
|
||
*/
|
||
public static function process_subscription_payment( $user_id, $subscription_key ) {
|
||
_deprecated_function( __METHOD__, '2.0', 'WC_Subscription::payment_complete()' );
|
||
|
||
$subscription = wcs_get_subscription_from_key( $subscription_key );
|
||
|
||
$subscription->payment_complete();
|
||
|
||
// Reset failed payment count & suspension count
|
||
$subscription = array(); // we only want to reset the failed payments and susp count
|
||
$subscription['failed_payments'] = $subscription['suspension_count'] = 0;
|
||
self::update_users_subscriptions( $user_id, array( $subscription_key => $subscription ) );
|
||
}
|
||
|
||
/**
|
||
* Processes a failed payment on a subscription by recording the failed payment and cancelling the subscription if it exceeds the
|
||
* maximum number of failed payments allowed on the site.
|
||
*
|
||
* @param int $user_id The id of the user who owns the expiring subscription.
|
||
* @param string $subscription_key A subscription key of the form obtained by @see get_subscription_key( $order_id, $product_id )
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.0
|
||
*/
|
||
public static function process_subscription_payment_failure( $user_id, $subscription_key ) {
|
||
_deprecated_function( __METHOD__, '2.0', 'WC_Subscription::payment_failed()' );
|
||
|
||
$subscription = wcs_get_subscription_from_key( $subscription_key );
|
||
|
||
// Allow a short circuit for plugins & payment gateways to force max failed payments exceeded
|
||
if ( apply_filters( 'woocommerce_subscriptions_max_failed_payments_exceeded', false, $user_id, $subscription_key ) ) {
|
||
$new_status = 'cancelled';
|
||
} else {
|
||
$new_status = 'on-hold';
|
||
}
|
||
|
||
$subscription->payment_failed( $new_status );
|
||
|
||
// Reset failed payment count & suspension count
|
||
$subscription = array(); // we only want to reset the failed payments and susp count
|
||
$subscription['failed_payments'] = $subscription['failed_payments'] + 1;
|
||
self::update_users_subscriptions( $user_id, array( $subscription_key => $subscription ) );
|
||
}
|
||
|
||
/**
|
||
* This function should be called whenever a subscription payment is made on an order. This includes
|
||
* when the subscriber signs up and for a recurring payment.
|
||
*
|
||
* The function is a convenience wrapper for @see self::process_subscription_payment(), so if calling that
|
||
* function directly, do not call this function also.
|
||
*
|
||
* @param WC_Order|int $order The order or ID of the order for which subscription payments should be marked against.
|
||
* @param int $product_id The ID of the product.
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.0
|
||
*/
|
||
public static function process_subscription_payments_on_order( $order, $product_id = 0 ) {
|
||
wcs_deprecated_function( __METHOD__, '2.6.0' );
|
||
$subscriptions = wcs_get_subscriptions_for_order( $order );
|
||
|
||
if ( ! empty( $subscriptions ) ) {
|
||
|
||
foreach ( $subscriptions as $subscription ) {
|
||
$subscription->payment_complete();
|
||
}
|
||
|
||
do_action( 'processed_subscription_payments_for_order', $order );
|
||
}
|
||
}
|
||
|
||
/**
|
||
* This function should be called whenever a subscription payment has failed on a parent order.
|
||
*
|
||
* The function is a convenience wrapper for @see self::process_subscription_payment_failure(), so if calling that
|
||
* function directly, do not call this function also.
|
||
*
|
||
* @param int|WC_Order $order The order or ID of the order for which subscription payments should be marked against.
|
||
* @param int $product_id The ID of the product.
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.0
|
||
*/
|
||
public static function process_subscription_payment_failure_on_order( $order, $product_id = 0 ) {
|
||
wcs_deprecated_function( __METHOD__, '2.6.0' );
|
||
$subscriptions = wcs_get_subscriptions_for_order( $order );
|
||
|
||
if ( ! empty( $subscriptions ) ) {
|
||
|
||
foreach ( $subscriptions as $subscription ) {
|
||
$subscription->payment_failed();
|
||
}
|
||
|
||
do_action( 'processed_subscription_payment_failure_for_order', $order );
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Activates all the subscriptions created by a given order.
|
||
*
|
||
* @param WC_Order|int $order The order or ID of the order for which subscriptions should be marked as activated.
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.0
|
||
*/
|
||
public static function activate_subscriptions_for_order( $order ) {
|
||
|
||
$subscriptions = wcs_get_subscriptions_for_order( $order );
|
||
|
||
if ( ! empty( $subscriptions ) ) {
|
||
|
||
foreach ( $subscriptions as $subscription ) {
|
||
|
||
try {
|
||
$subscription->update_status( 'active' );
|
||
} catch ( Exception $e ) {
|
||
// translators: $1: order number, $2: error message
|
||
$subscription->add_order_note( sprintf( __( 'Failed to activate subscription status for order #%1$s: %2$s', 'woocommerce-subscriptions' ), is_object( $order ) ? $order->get_order_number() : $order, $e->getMessage() ) );
|
||
}
|
||
}
|
||
|
||
do_action( 'subscriptions_activated_for_order', $order );
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Suspends all the subscriptions on an order by changing their status to "on-hold".
|
||
*
|
||
* @param WC_Order|int $order The order or ID of the order for which subscriptions should be marked as activated.
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.0
|
||
*/
|
||
public static function put_subscription_on_hold_for_order( $order ) {
|
||
|
||
$subscriptions = wcs_get_subscriptions_for_order( $order, array( 'order_type' => 'parent' ) );
|
||
|
||
if ( ! empty( $subscriptions ) ) {
|
||
|
||
foreach ( $subscriptions as $subscription ) {
|
||
|
||
try {
|
||
if ( $subscription->can_be_updated_to( 'on-hold' ) ) {
|
||
$subscription->update_status( 'on-hold' );
|
||
}
|
||
} catch ( Exception $e ) {
|
||
// translators: $1: order number, $2: error message
|
||
$subscription->add_order_note( sprintf( __( 'Failed to update subscription status after order #%1$s was put on-hold: %2$s', 'woocommerce-subscriptions' ), is_object( $order ) ? $order->get_order_number() : $order, $e->getMessage() ) );
|
||
}
|
||
}
|
||
|
||
do_action( 'subscriptions_put_on_hold_for_order', $order );
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Mark all subscriptions in an order as cancelled on the user's account.
|
||
*
|
||
* @param WC_Order|int $order The order or ID of the order for which subscriptions should be marked as cancelled.
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.0
|
||
*/
|
||
public static function cancel_subscriptions_for_order( $order ) {
|
||
|
||
$subscriptions = wcs_get_subscriptions_for_order( $order, array( 'order_type' => 'parent' ) );
|
||
|
||
if ( ! empty( $subscriptions ) ) {
|
||
|
||
foreach ( $subscriptions as $subscription ) {
|
||
|
||
try {
|
||
if ( ! $subscription->has_status( wcs_get_subscription_ended_statuses() ) ) {
|
||
$subscription->cancel_order();
|
||
}
|
||
} catch ( Exception $e ) {
|
||
// translators: $1: order number, $2: error message
|
||
$subscription->add_order_note( sprintf( __( 'Failed to cancel subscription after order #%1$s was cancelled: %2$s', 'woocommerce-subscriptions' ), is_object( $order ) ? $order->get_order_number() : $order, $e->getMessage() ) );
|
||
}
|
||
}
|
||
|
||
do_action( 'subscriptions_cancelled_for_order', $order );
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Marks all the subscriptions in an order as expired
|
||
*
|
||
* @param WC_Order|int $order The order or ID of the order for which subscriptions should be marked as expired.
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.0
|
||
*/
|
||
public static function expire_subscriptions_for_order( $order ) {
|
||
|
||
$subscriptions = wcs_get_subscriptions_for_order( $order );
|
||
|
||
if ( ! empty( $subscriptions ) ) {
|
||
|
||
foreach ( $subscriptions as $subscription ) {
|
||
|
||
try {
|
||
if ( ! $subscription->has_status( wcs_get_subscription_ended_statuses() ) ) {
|
||
$subscription->update_status( 'expired' );
|
||
}
|
||
} catch ( Exception $e ) {
|
||
// translators: $1: order number, $2: error message
|
||
$subscription->add_order_note( sprintf( __( 'Failed to set subscription as expired for order #%1$s: %2$s', 'woocommerce-subscriptions' ), is_object( $order ) ? $order->get_order_number() : $order, $e->getMessage() ) );
|
||
}
|
||
}
|
||
|
||
do_action( 'subscriptions_expired_for_order', $order );
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Called when a sign up fails during the payment processing step.
|
||
*
|
||
* This method only performs actions when a parent order changed to failed status.
|
||
* Overlaps with WC_Subscriptions_Order::maybe_record_subscription_payment.
|
||
*
|
||
* @param WC_Order|int $order The order or ID of the order for which subscriptions should be marked as failed.
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.0
|
||
*/
|
||
public static function failed_subscription_sign_ups_for_order( $order ) {
|
||
$subscriptions = wcs_get_subscriptions_for_order( $order, array( 'order_type' => 'parent' ) );
|
||
|
||
if ( empty( $subscriptions ) ) {
|
||
return;
|
||
}
|
||
|
||
if ( ! is_object( $order ) ) {
|
||
$order = wc_get_order( $order );
|
||
}
|
||
|
||
// Set subscription status to failed and log failure
|
||
if ( $order->has_status( 'failed' ) ) {
|
||
$order->update_status( 'failed', __( 'Subscription sign up failed.', 'woocommerce-subscriptions' ) );
|
||
}
|
||
|
||
foreach ( $subscriptions as $subscription ) {
|
||
|
||
try {
|
||
/**
|
||
* Parent status failure should not change the subscription status in most cases.
|
||
* We only change the status when the parent order is the last order and subscription is active.
|
||
* In that case, we need to put the subscription on hold as we do when the latest renewal order fails.
|
||
* Examples:
|
||
* - if subscription is pending and initial payment fails, we keep subscription as pending to activate it on successful payment.
|
||
* - if subscription has successful renewals and somehow the parent order fails after that, we still keep subscription as active.
|
||
* - if subscription is active after successful initial payment, but later the parent order fails, we move subscription to on-hold.
|
||
*/
|
||
$new_status = $subscription->get_status();
|
||
|
||
if ( 'active' === $new_status && $subscription->get_parent_id() === $order->get_id() ) {
|
||
$last_order = $subscription->get_last_order( 'ids', 'any' );
|
||
$new_status = $last_order === $order->get_id() ? 'on-hold' : 'active';
|
||
}
|
||
|
||
$subscription->payment_failed_for_related_order( $new_status, $order );
|
||
} catch ( Exception $e ) {
|
||
// translators: $1: order number, $2: error message
|
||
$subscription->add_order_note( sprintf( __( 'Failed to process failed payment on subscription for order #%1$s: %2$s', 'woocommerce-subscriptions' ), is_object( $order ) ? $order->get_order_number() : $order, $e->getMessage() ) );
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Fires after an order is marked as failed.
|
||
*
|
||
* @param WC_Order $order Failed order object.
|
||
*
|
||
* @since 1.5.0
|
||
*/
|
||
do_action( 'failed_subscription_sign_ups_for_order', $order );
|
||
}
|
||
|
||
/**
|
||
* Uses the details of an order to create a pending subscription on the customers account
|
||
* for a subscription product, as specified with $product_id.
|
||
*
|
||
* @param int|WC_Order $order The order ID or WC_Order object to create the subscription from.
|
||
* @param int $product_id The ID of the subscription product on the order, if a variation, it must be the variation's ID.
|
||
* @param array $args An array of name => value pairs to customise the details of the subscription, including:
|
||
* 'start_date' A MySQL formatted date/time string on which the subscription should start, in UTC timezone
|
||
* 'expiry_date' A MySQL formatted date/time string on which the subscription should expire, in UTC timezone
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.1
|
||
*/
|
||
public static function create_pending_subscription_for_order( $order, $product_id, $args = array() ) {
|
||
_deprecated_function( __METHOD__, '2.0', 'wcs_create_subscription()' );
|
||
|
||
if ( ! is_object( $order ) ) {
|
||
$order = new WC_Order( $order );
|
||
}
|
||
|
||
if ( ! WC_Subscriptions_Product::is_subscription( $product_id ) ) {
|
||
return;
|
||
}
|
||
|
||
$args = wp_parse_args( $args, array(
|
||
'start_date' => wcs_get_datetime_utc_string( wcs_get_objects_property( $order, 'date_created' ) ), // get_date_created() can return null, but if it does, we have an error anyway
|
||
'expiry_date' => '',
|
||
) );
|
||
|
||
$billing_period = WC_Subscriptions_Product::get_period( $product_id );
|
||
$billing_interval = WC_Subscriptions_Product::get_interval( $product_id );
|
||
|
||
// Support passing timestamps
|
||
$args['start_date'] = is_numeric( $args['start_date'] ) ? gmdate( 'Y-m-d H:i:s', $args['start_date'] ) : $args['start_date'];
|
||
|
||
$product = wc_get_product( $product_id );
|
||
|
||
// Check if there is already a subscription for this product and order
|
||
$subscriptions = wcs_get_subscriptions(
|
||
array(
|
||
'order_id' => wcs_get_objects_property( $order, 'id' ),
|
||
'product_id' => $product_id,
|
||
)
|
||
);
|
||
|
||
if ( ! empty( $subscriptions ) ) {
|
||
|
||
$subscription = array_pop( $subscriptions );
|
||
|
||
// Make sure the subscription is pending and start date is set correctly
|
||
wp_update_post( array(
|
||
'ID' => $subscription->get_id(),
|
||
'post_status' => 'wc-' . apply_filters( 'woocommerce_default_subscription_status', 'pending' ),
|
||
'post_date' => get_date_from_gmt( $args['start_date'] ),
|
||
) );
|
||
|
||
} else {
|
||
|
||
$subscription = wcs_create_subscription( array(
|
||
'start_date' => get_date_from_gmt( $args['start_date'] ),
|
||
'order_id' => wcs_get_objects_property( $order, 'id' ),
|
||
'customer_id' => $order->get_user_id(),
|
||
'billing_period' => $billing_period,
|
||
'billing_interval' => $billing_interval,
|
||
'customer_note' => wcs_get_objects_property( $order, 'customer_note' ),
|
||
) );
|
||
|
||
if ( is_wp_error( $subscription ) ) {
|
||
throw new Exception( __( 'Error: Unable to create subscription. Please try again.', 'woocommerce-subscriptions' ) );
|
||
}
|
||
|
||
$item_id = $subscription->add_product(
|
||
$product,
|
||
1,
|
||
array(
|
||
'variation' => ( method_exists( $product, 'get_variation_attributes' ) ) ? $product->get_variation_attributes() : array(),
|
||
'totals' => array(
|
||
'subtotal' => $product->get_price(),
|
||
'subtotal_tax' => 0,
|
||
'total' => $product->get_price(),
|
||
'tax' => 0,
|
||
'tax_data' => array(
|
||
'subtotal' => array(),
|
||
'total' => array(),
|
||
),
|
||
),
|
||
)
|
||
);
|
||
|
||
if ( ! $item_id ) {
|
||
throw new Exception( __( 'Error: Unable to add product to created subscription. Please try again.', 'woocommerce-subscriptions' ) );
|
||
}
|
||
}
|
||
|
||
// Make sure some of the meta is copied form the order rather than the store's defaults
|
||
if ( wcs_get_objects_property( $order, 'prices_include_tax' ) ) {
|
||
$prices_include_tax = 'yes';
|
||
} else {
|
||
$prices_include_tax = 'no';
|
||
}
|
||
update_post_meta( $subscription->get_id(), '_order_currency', wcs_get_objects_property( $order, 'currency' ) );
|
||
update_post_meta( $subscription->get_id(), '_prices_include_tax', $prices_include_tax );
|
||
|
||
// Adding a new subscription so set the expiry date/time from the order date
|
||
if ( ! empty( $args['expiry_date'] ) ) {
|
||
if ( is_numeric( $args['expiry_date'] ) ) {
|
||
$args['expiry_date'] = gmdate( 'Y-m-d H:i:s', $args['expiry_date'] );
|
||
}
|
||
|
||
$expiration = $args['expiry_date'];
|
||
} else {
|
||
$expiration = WC_Subscriptions_Product::get_expiration_date( $product_id, $args['start_date'] );
|
||
}
|
||
|
||
// Adding a new subscription so set the expiry date/time from the order date
|
||
$trial_expiration = WC_Subscriptions_Product::get_trial_expiration_date( $product_id, $args['start_date'] );
|
||
|
||
$dates_to_update = array();
|
||
|
||
if ( $trial_expiration > 0 ) {
|
||
$dates_to_update['trial_end'] = $trial_expiration;
|
||
}
|
||
|
||
if ( $expiration > 0 ) {
|
||
$dates_to_update['end'] = $expiration;
|
||
}
|
||
|
||
if ( ! empty( $dates_to_update ) ) {
|
||
$subscription->update_dates( $dates_to_update );
|
||
}
|
||
|
||
// Set the recurring totals on the subscription
|
||
$subscription->set_total( 0, 'tax' );
|
||
$subscription->set_total( $product->get_price(), 'total' );
|
||
|
||
$subscription->add_order_note( __( 'Pending subscription created.', 'woocommerce-subscriptions' ) );
|
||
|
||
do_action( 'pending_subscription_created_for_order', $order, $product_id );
|
||
}
|
||
|
||
/**
|
||
* Excludes subscriptions from the order cleanup process.
|
||
*
|
||
* @param bool $should_cancel Whether the order should be cancelled.
|
||
* @param WC_Order $order The order object.
|
||
*
|
||
* @return bool Whether the order should be cancelled.
|
||
*/
|
||
public static function exclude_subscription_from_order_cleanup( $should_cancel, $order ) {
|
||
if ( $should_cancel && 'shop_subscription' === $order->get_type() ) {
|
||
$should_cancel = false;
|
||
}
|
||
|
||
return $should_cancel;
|
||
}
|
||
|
||
/**
|
||
* Creates subscriptions against a users account with a status of pending when a user creates
|
||
* an order containing subscriptions.
|
||
*
|
||
* @param int|WC_Order $order The order ID or WC_Order object to create the subscription from.
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.0
|
||
*/
|
||
public static function process_subscriptions_on_checkout( $order ) {
|
||
_deprecated_function( __METHOD__, '2.0', 'WC_Subscriptions_Checkout::process_checkout()' );
|
||
|
||
if ( ! empty( $_POST['_wpnonce'] ) && wp_verify_nonce( wc_clean( wp_unslash( $_POST['_wpnonce'] ) ), 'woocommerce-process_checkout' ) ) {
|
||
WC_Subscriptions_Checkout::process_checkout( $order, $_POST );
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Updates a user's subscriptions for each subscription product in the order.
|
||
*
|
||
* @param WC_Order $order The order to get subscriptions and user details from.
|
||
* @param string $status (optional) A status to change the subscriptions in an order to. Default is 'active'.
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.0
|
||
*/
|
||
public static function update_users_subscriptions_for_order( $order, $status = 'pending' ) {
|
||
_deprecated_function( __METHOD__, '2.0', 'WC_Subscriptions::update_status()' );
|
||
|
||
if ( ! is_object( $order ) ) {
|
||
$order = new WC_Order( $order );
|
||
}
|
||
|
||
if ( 'suspend' === $status ) {
|
||
$status = 'on-hold';
|
||
_deprecated_argument( __METHOD__, '1.2', 'The "suspend" status value is deprecated. Use "on-hold"' );
|
||
}
|
||
|
||
foreach ( wcs_get_subscriptions_for_order( wcs_get_objects_property( $order, 'id' ), array( 'order_type' => 'parent' ) ) as $subscription_id => $subscription ) {
|
||
|
||
switch ( $status ) {
|
||
case 'cancelled':
|
||
$subscription->cancel_order();
|
||
break;
|
||
case 'active':
|
||
case 'expired':
|
||
case 'on-hold':
|
||
$subscription->update_status( $status );
|
||
break;
|
||
case 'failed':
|
||
_deprecated_argument( __METHOD__, '2.0', 'The "failed" status value is deprecated.' );
|
||
self::failed_subscription_signup( $order->get_user_id(), $subscription_id );
|
||
break;
|
||
case 'pending':
|
||
_deprecated_argument( __METHOD__, '2.0', 'The "pending" status value is deprecated.' );
|
||
default:
|
||
// @phpstan-ignore arguments.count
|
||
self::create_pending_subscription_for_order( $order );
|
||
break;
|
||
}
|
||
}
|
||
|
||
do_action( 'updated_users_subscriptions_for_order', $order, $status );
|
||
}
|
||
|
||
/**
|
||
* Takes a user ID and array of subscription details and updates the users subscription details accordingly.
|
||
*
|
||
* @uses wp_parse_args To allow only part of a subscription's details to be updated, like status.
|
||
* @param int $user_id The ID of the user for whom subscription details should be updated
|
||
* @param array $subscriptions An array of arrays with a subscription key and corresponding 'detail' => 'value' pair. Can alter any of these details:
|
||
* 'start_date' The date the subscription was activated
|
||
* 'expiry_date' The date the subscription expires or expired, false if the subscription will never expire
|
||
* 'failed_payments' The date the subscription's trial expires or expired, false if the subscription has no trial period
|
||
* 'end_date' The date the subscription ended, false if the subscription has not yet ended
|
||
* 'status' Subscription status can be: cancelled, active, expired or failed
|
||
* 'completed_payments' An array of MySQL formatted dates for all payments that have been made on the subscription
|
||
* 'failed_payments' An integer representing a count of failed payments
|
||
* 'suspension_count' An integer representing a count of the number of times the subscription has been suspended for this billing period
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.0
|
||
*/
|
||
public static function update_users_subscriptions( $user_id, $subscriptions ) {
|
||
_deprecated_function( __METHOD__, '2.0', 'WC_Subscriptions API methods' );
|
||
|
||
foreach ( $subscriptions as $subscription_key => $new_subscription_details ) {
|
||
|
||
$subscription = wcs_get_subscription_from_key( $subscription_key );
|
||
|
||
if ( isset( $new_subscription_details['status'] ) && 'deleted' == $new_subscription_details['status'] ) {
|
||
wp_delete_post( $subscription->get_id() );
|
||
} else {
|
||
// There is no direct analog for this in WC_Subscription, so we need to call the deprecated method
|
||
self::update_subscription( $subscription_key, $new_subscription_details );
|
||
}
|
||
}
|
||
|
||
do_action( 'updated_users_subscriptions', $user_id, $subscriptions );
|
||
|
||
return self::get_users_subscriptions( $user_id ); // We need to call this deprecated method to preserve the return value in the deprecated array structure
|
||
}
|
||
|
||
/**
|
||
* Takes a subscription key and array of subscription details and updates the users subscription details accordingly.
|
||
*
|
||
* @uses wp_parse_args To allow only part of a subscription's details to be updated, like status.
|
||
* @param string $subscription_key A subscription key of the form created by @see self::get_subscription_key()
|
||
* @param array $new_subscription_details An array of arrays with a subscription key and corresponding 'detail' => 'value' pair. Can alter any of these details:
|
||
* 'start_date' The date the subscription was activated
|
||
* 'expiry_date' The date the subscription expires or expired, false if the subscription will never expire
|
||
* 'failed_payments' The date the subscription's trial expires or expired, false if the subscription has no trial period
|
||
* 'end_date' The date the subscription ended, false if the subscription has not yet ended
|
||
* 'status' Subscription status can be: cancelled, active, expired or failed
|
||
* 'completed_payments' An array of MySQL formatted dates for all payments that have been made on the subscription
|
||
* 'failed_payments' An integer representing a count of failed payments
|
||
* 'suspension_count' An integer representing a count of the number of times the subscription has been suspended for this billing period
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.4
|
||
*/
|
||
public static function update_subscription( $subscription_key, $new_subscription_details ) {
|
||
_deprecated_function( __METHOD__, '2.0', 'WC_Subscriptions API methods' );
|
||
|
||
$subscription = wcs_get_subscription_from_key( $subscription_key );
|
||
|
||
if ( isset( $new_subscription_details['status'] ) && 'deleted' == $new_subscription_details['status'] ) {
|
||
|
||
wp_delete_post( $subscription->get_id() );
|
||
|
||
} else {
|
||
|
||
foreach ( $new_subscription_details as $meta_key => $meta_value ) {
|
||
switch ( $meta_key ) {
|
||
case 'start_date':
|
||
$subscription->update_dates( array( 'date_created' => $meta_value ) );
|
||
break;
|
||
case 'trial_expiry_date':
|
||
$subscription->update_dates( array( 'trial_end' => $meta_value ) );
|
||
break;
|
||
case 'expiry_date':
|
||
$subscription->update_dates( array( 'end' => $meta_value ) );
|
||
break;
|
||
case 'failed_payments':
|
||
_deprecated_argument( __METHOD__, '2.0', 'The "failed_payments" meta value is deprecated. Create a renewal order with "failed" status instead.' );
|
||
break;
|
||
case 'completed_payments':
|
||
_deprecated_argument( __METHOD__, '2.0', 'The "completed_payments" meta value is deprecated. Create a renewal order with completed payment instead.' );
|
||
break;
|
||
case 'suspension_count':
|
||
$subscription->set_suspension_count( $subscription->get_suspension_count() + 1 );
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
do_action( 'updated_users_subscription', $subscription_key, $new_subscription_details );
|
||
|
||
return wcs_get_subscription_in_deprecated_structure( $subscription );
|
||
}
|
||
|
||
/**
|
||
* Takes a user ID and cancels any subscriptions that user has.
|
||
*
|
||
* @uses wp_parse_args To allow only part of a subscription's details to be updated, like status.
|
||
* @param int $user_id The ID of the user for whom subscription details should be updated
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.3.8
|
||
*/
|
||
public static function cancel_users_subscriptions( $user_id ) {
|
||
|
||
$subscriptions = wcs_get_users_subscriptions( $user_id );
|
||
|
||
if ( ! empty( $subscriptions ) ) {
|
||
|
||
foreach ( $subscriptions as $subscription ) {
|
||
if ( $subscription->can_be_updated_to( 'cancelled' ) ) {
|
||
$subscription->update_status( 'cancelled' );
|
||
}
|
||
}
|
||
|
||
do_action( 'cancelled_users_subscriptions', $user_id );
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Takes a user ID and cancels any subscriptions that user has on any site in a WordPress network
|
||
*
|
||
* @uses wp_parse_args To allow only part of a subscription's details to be updated, like status.
|
||
* @param int $user_id The ID of the user for whom subscription details should be updated
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.3.8
|
||
*/
|
||
public static function cancel_users_subscriptions_for_network( $user_id ) {
|
||
|
||
$sites = get_blogs_of_user( $user_id );
|
||
|
||
if ( ! empty( $sites ) ) {
|
||
|
||
foreach ( $sites as $site ) {
|
||
|
||
switch_to_blog( $site->userblog_id );
|
||
|
||
self::cancel_users_subscriptions( $user_id );
|
||
|
||
restore_current_blog();
|
||
}
|
||
}
|
||
|
||
do_action( 'cancelled_users_subscriptions_for_network', $user_id );
|
||
}
|
||
|
||
/**
|
||
* Clear all subscriptions for a given order.
|
||
*
|
||
* @param WC_Order $order The order for which subscriptions should be cleared.
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.0
|
||
*/
|
||
public static function clear_users_subscriptions_from_order( $order ) {
|
||
|
||
foreach ( wcs_get_subscriptions_for_order( $order, array( 'order_type' => 'parent' ) ) as $subscription_id => $subscription ) {
|
||
$subscription->delete( true );
|
||
}
|
||
|
||
do_action( 'cleared_users_subscriptions_from_order', $order );
|
||
}
|
||
|
||
/**
|
||
* Trash all subscriptions attached to an order when it's trashed.
|
||
*
|
||
* Also make sure all related scheduled actions are cancelled when deleting a subscription.
|
||
*
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.0
|
||
*
|
||
* @param int $order_id The order ID of the WC Subscription or WC Order being trashed
|
||
*/
|
||
public static function maybe_trash_subscription( $order_id ) {
|
||
if ( 'shop_order' === WC_Data_Store::load( 'order' )->get_order_type( $order_id ) ) {
|
||
|
||
// delete subscription
|
||
foreach ( wcs_get_subscriptions_for_order( $order_id, [ 'order_type' => 'parent' ] ) as $subscription ) {
|
||
$subscription->delete();
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Untrash all subscriptions attached to an order when it's restored.
|
||
*
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v2.2.17
|
||
*
|
||
* @param int $order_id The Order ID of the order being restored
|
||
*/
|
||
public static function maybe_untrash_subscription( $order_id ) {
|
||
if ( 'shop_order' !== WC_Data_Store::load( 'order' )->get_order_type( $order_id ) ) {
|
||
return;
|
||
}
|
||
|
||
$data_store = WC_Data_Store::load( 'subscription' );
|
||
$use_crud_method = method_exists( $data_store, 'has_callable' ) && $data_store->has_callable( 'untrash_order' );
|
||
$subscriptions = wcs_get_subscriptions_for_order(
|
||
$order_id,
|
||
[
|
||
'order_type' => 'parent',
|
||
'subscription_status' => [ 'trash' ],
|
||
]
|
||
);
|
||
|
||
foreach ( $subscriptions as $subscription ) {
|
||
if ( $use_crud_method ) {
|
||
$data_store->untrash_order( $subscription );
|
||
} else {
|
||
wp_untrash_post( $subscription->get_id() );
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Delete related subscriptions when an order is deleted.
|
||
*
|
||
* @param int $order_id The post ID being deleted.
|
||
*/
|
||
public static function maybe_delete_subscription( $order_id ) {
|
||
if ( 'shop_order' !== WC_Data_Store::load( 'order' )->get_order_type( $order_id ) ) {
|
||
return;
|
||
}
|
||
|
||
/** @var WC_Subscription[] $subscriptions */
|
||
$subscriptions = wcs_get_subscriptions_for_order(
|
||
$order_id,
|
||
[
|
||
'order_type' => 'parent',
|
||
'subscription_status' => [ 'any', 'trash' ],
|
||
]
|
||
);
|
||
|
||
foreach ( $subscriptions as $subscription ) {
|
||
$subscription->delete( true );
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Make sure a subscription is cancelled before it is trashed or deleted
|
||
*
|
||
* @param int $id
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v2.0
|
||
*/
|
||
public static function maybe_cancel_subscription( $id ) {
|
||
|
||
$subscription = wcs_get_subscription( $id );
|
||
if ( ! $subscription ) {
|
||
return;
|
||
}
|
||
|
||
if ( $subscription->get_type() !== 'shop_subscription' ) {
|
||
return;
|
||
}
|
||
|
||
if ( $subscription->can_be_updated_to( 'cancelled' ) ) {
|
||
|
||
$subscription->update_status( 'cancelled' );
|
||
|
||
}
|
||
}
|
||
|
||
/**
|
||
* When an order is trashed, store the '_wp_trash_meta_status' meta value with a cancelled subscription status
|
||
* to prevent subscriptions being restored with an active status.
|
||
*
|
||
* When WordPress and WooCommerce set this meta value, they use the status of the order in memory.
|
||
* If that status is changed on the before trashed or before deleted hooks,
|
||
* as is the case with a subscription, which is cancelled before being trashed if it is active or on-hold,
|
||
* then the '_wp_trash_meta_status' value will be incorrectly set to its status before being trashed.
|
||
*
|
||
* This function fixes that by setting '_wp_trash_meta_status' to 'wc-cancelled' whenever its former status
|
||
* is something that can not be restored.
|
||
*
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v2.0
|
||
*
|
||
* @param int $id
|
||
*/
|
||
public static function fix_trash_meta_status( $id ) {
|
||
$subscription = wcs_get_subscription( $id );
|
||
|
||
if ( ! $subscription ) {
|
||
return;
|
||
}
|
||
|
||
if ( $subscription->get_type() !== 'shop_subscription' ) {
|
||
return;
|
||
}
|
||
|
||
$data_store = $subscription->get_data_store();
|
||
$meta_data = $data_store->read_meta( $subscription );
|
||
|
||
foreach ( $meta_data as $meta ) {
|
||
if ( '_wp_trash_meta_status' === $meta->meta_key && ! in_array( $meta->meta_value, [ 'wc-pending', 'wc-expired', 'wc-cancelled' ], true ) ) {
|
||
$new_meta = (object) [
|
||
'id' => $meta->meta_id,
|
||
'key' => $meta->meta_key,
|
||
'value' => 'wc-cancelled',
|
||
];
|
||
$data_store->update_meta( $subscription, $new_meta );
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Trigger action hook after a subscription has been trashed.
|
||
*
|
||
* @param int $id
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v2.0
|
||
*/
|
||
public static function trigger_subscription_trashed_hook( $id ) {
|
||
|
||
if ( 'shop_subscription' === WC_Data_Store::load( 'subscription' )->get_order_type( $id ) ) {
|
||
do_action( 'woocommerce_subscription_trashed', $id );
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Takes a user ID and trashes any subscriptions that user has.
|
||
*
|
||
* @param int $user_id The ID of the user whose subscriptions will be trashed
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v2.0
|
||
*/
|
||
public static function trash_users_subscriptions( $user_id ) {
|
||
$subscriptions = wcs_get_users_subscriptions( $user_id );
|
||
$current_user = is_user_logged_in() ? wp_get_current_user() : null;
|
||
|
||
if ( ! empty( $subscriptions ) ) {
|
||
|
||
foreach ( $subscriptions as $subscription ) {
|
||
$subscription_number = $subscription->get_order_number();
|
||
|
||
if ( WCS_Gifting::is_gifted_subscription( $subscription ) ) {
|
||
// translators: %s is the email address of the recipient.
|
||
$message = sprintf( __( 'The gifted subscription moved to the purchaser after the recipient user with email address %s was deleted.', 'woocommerce-subscriptions' ), $subscription->get_meta( '_recipient_user_email_address' ) );
|
||
|
||
$subscription->delete_meta_data( '_recipient_user' );
|
||
$subscription->delete_meta_data( '_recipient_user_email_address' );
|
||
$subscription->save();
|
||
|
||
$subscription->add_order_note( $message, $subscription_number );
|
||
|
||
// Check needed for tests.
|
||
if ( $subscription->get_parent() ) {
|
||
$subscription->get_parent()->add_order_note( $message, $subscription_number );
|
||
}
|
||
|
||
continue;
|
||
}
|
||
|
||
// Before deleting the subscription, add an order note to the related orders.
|
||
foreach ( $subscription->get_related_orders( 'all', array( 'parent', 'renewal', 'switch' ) ) as $order ) {
|
||
if ( $current_user ) {
|
||
// Translators: 1: The subscription ID number. 2: The current user's username.
|
||
$order->add_order_note( sprintf( __( 'The related subscription #%1$s has been deleted after the customer was deleted by %2$s.', 'woocommerce-subscriptions' ), $subscription_number, $current_user->display_name ) );
|
||
} else {
|
||
// Translators: Placeholder is the subscription ID number.
|
||
$order->add_order_note( sprintf( __( 'The related subscription #%s has been deleted after the customer was deleted.', 'woocommerce-subscriptions' ), $subscription_number ) );
|
||
}
|
||
}
|
||
|
||
$subscription->delete( true );
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Takes a user ID and trashes any subscriptions that user has on any site in a WordPress network
|
||
*
|
||
* @param int $user_id The ID of the user whose subscriptions will be trashed
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v2.0
|
||
*/
|
||
public static function trash_users_subscriptions_for_network( $user_id ) {
|
||
|
||
$sites = get_blogs_of_user( $user_id );
|
||
|
||
if ( ! empty( $sites ) ) {
|
||
|
||
foreach ( $sites as $site ) {
|
||
|
||
switch_to_blog( $site->userblog_id );
|
||
|
||
self::trash_users_subscriptions( $user_id );
|
||
|
||
restore_current_blog();
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Trigger action hook after a subscription has been deleted.
|
||
*
|
||
* @param int $id
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v2.0
|
||
*/
|
||
public static function trigger_subscription_deleted_hook( $id ) {
|
||
|
||
if ( 'shop_subscription' === WC_Data_Store::load( 'subscription' )->get_order_type( $id ) ) {
|
||
do_action( 'woocommerce_subscription_deleted', $id );
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Checks if the current request is by a user to change the status of their subscription, and if it is
|
||
* validate the subscription cancellation request and maybe processes the cancellation.
|
||
*
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.0
|
||
* @deprecated 1.0.0 - Migrated from WooCommerce Subscriptions v2.0
|
||
*/
|
||
public static function maybe_change_users_subscription() {
|
||
_deprecated_function( __METHOD__, '2.0', 'WCS_User_Change_Status_Handler::maybe_change_users_subscription()' );
|
||
WCS_User_Change_Status_Handler::maybe_change_users_subscription();
|
||
}
|
||
|
||
/**
|
||
* Check if a given subscription can be changed to a given a status.
|
||
*
|
||
* The function checks the subscription's current status and if the payment gateway used to purchase the
|
||
* subscription allows for the given status to be set via its API.
|
||
*
|
||
* @param string $new_status_or_meta The status or meta data you want to change th subscription to. Can be 'active', 'on-hold', 'cancelled', 'expired', 'trash', 'deleted', 'failed', 'new-payment-date' or some other value attached to the 'woocommerce_can_subscription_be_changed_to' filter.
|
||
* @param string $subscription_key A subscription key of the form created by @see self::get_subscription_key()
|
||
* @param int $user_id The ID of the user who owns the subscriptions. Although this parameter is optional, if you have the User ID you should pass it to improve performance.
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.0
|
||
*/
|
||
public static function can_subscription_be_changed_to( $new_status_or_meta, $subscription_key, $user_id = 0 ) {
|
||
|
||
_deprecated_function( __METHOD__, '2.0', 'WC_Subscription::can_be_updated_to( $new_status_or_meta )' );
|
||
|
||
if ( 'new-payment-date' == $new_status_or_meta ) {
|
||
_deprecated_argument( __METHOD__, '2.0', 'The "new-payment-date" parameter value is deprecated. Use WC_Subscription::can_date_be_updated( "next_payment" ) method instead.' );
|
||
} elseif ( 'suspended' == $new_status_or_meta ) {
|
||
_deprecated_argument( __METHOD__, '2.0', 'The "suspended" parameter value is deprecated. Use "on-hold" instead.' );
|
||
$new_status_or_meta = 'on-hold';
|
||
}
|
||
|
||
try {
|
||
$subscription = wcs_get_subscription_from_key( $subscription_key );
|
||
|
||
switch ( $new_status_or_meta ) {
|
||
case 'new-payment-date':
|
||
$subscription_can_be_changed = $subscription->can_date_be_updated( 'next_payment' );
|
||
break;
|
||
case 'active':
|
||
case 'on-hold':
|
||
case 'cancelled':
|
||
case 'expired':
|
||
case 'trash':
|
||
case 'deleted':
|
||
case 'failed':
|
||
default:
|
||
$subscription_can_be_changed = $subscription->can_be_updated_to( $new_status_or_meta );
|
||
break;
|
||
}
|
||
} catch ( Exception $e ) {
|
||
$subscription_can_be_changed = false;
|
||
}
|
||
|
||
return $subscription_can_be_changed;
|
||
}
|
||
|
||
/*
|
||
* Subscription Getters & Property functions
|
||
*/
|
||
|
||
/**
|
||
* Return an associative array of a given subscriptions details (if it exists).
|
||
*
|
||
* @param string $subscription_key A subscription key of the form created by @see self::get_subscription_key()
|
||
* @param mixed $deprecated Don't use
|
||
* @return array Subscription details
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.1
|
||
*/
|
||
public static function get_subscription( $subscription_key, $deprecated = null ) {
|
||
|
||
if ( null != $deprecated ) {
|
||
_deprecated_argument( __METHOD__, '1.4', 'Second parameter is deprecated' );
|
||
}
|
||
|
||
_deprecated_function( __METHOD__, '2.0', 'wcs_get_subscription( $subscription_id )' );
|
||
|
||
try {
|
||
$subscription = wcs_get_subscription_from_key( $subscription_key );
|
||
$subscription = wcs_get_subscription_in_deprecated_structure( $subscription );
|
||
} catch ( Exception $e ) {
|
||
$subscription = array();
|
||
}
|
||
|
||
return apply_filters( 'woocommerce_get_subscription', $subscription, $subscription_key, $deprecated );
|
||
}
|
||
|
||
/**
|
||
* Return an i18n'ified string for a given subscription status.
|
||
*
|
||
* @param string $status An subscription status of it's internal form.
|
||
* @return string A translated subscription status string for display.
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.2.3
|
||
*/
|
||
public static function get_status_to_display( $status, $subscription_key = '', $user_id = 0 ) {
|
||
_deprecated_function( __METHOD__, '2.0', 'wcs_get_subscription_statuses()' );
|
||
|
||
switch ( $status ) {
|
||
case 'active':
|
||
$status_string = _x( 'Active', 'Subscription status', 'woocommerce-subscriptions' );
|
||
break;
|
||
case 'cancelled':
|
||
$status_string = _x( 'Cancelled', 'Subscription status', 'woocommerce-subscriptions' );
|
||
break;
|
||
case 'expired':
|
||
$status_string = _x( 'Expired', 'Subscription status', 'woocommerce-subscriptions' );
|
||
break;
|
||
case 'pending':
|
||
$status_string = _x( 'Pending', 'Subscription status', 'woocommerce-subscriptions' );
|
||
break;
|
||
case 'failed':
|
||
$status_string = _x( 'Failed', 'Subscription status', 'woocommerce-subscriptions' );
|
||
break;
|
||
case 'on-hold':
|
||
case 'suspend': // Backward compatibility
|
||
$status_string = _x( 'On-hold', 'Subscription status', 'woocommerce-subscriptions' );
|
||
break;
|
||
default:
|
||
$status_string = apply_filters( 'woocommerce_subscriptions_custom_status_string', ucfirst( $status ), $subscription_key, $user_id );
|
||
}
|
||
|
||
return apply_filters( 'woocommerce_subscriptions_status_string', $status_string, $status, $subscription_key, $user_id );
|
||
}
|
||
|
||
/**
|
||
* Return an i18n'ified associative array of all possible subscription periods.
|
||
*
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.1
|
||
* @deprecated 1.0.0 - Migrated from WooCommerce Subscriptions v2.0
|
||
*/
|
||
public static function get_subscription_period_strings( $number = 1, $period = '' ) {
|
||
_deprecated_function( __METHOD__, '2.0', 'wcs_get_subscription_period_strings()' );
|
||
return wcs_get_subscription_period_strings( $number, $period );
|
||
}
|
||
|
||
/**
|
||
* Return an i18n'ified associative array of all possible subscription periods.
|
||
*
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.0
|
||
* @deprecated 1.0.0 - Migrated from WooCommerce Subscriptions v2.0
|
||
*/
|
||
public static function get_subscription_period_interval_strings( $interval = '' ) {
|
||
_deprecated_function( __METHOD__, '2.0', 'wcs_get_subscription_period_interval_strings()' );
|
||
return wcs_get_subscription_period_interval_strings( $interval );
|
||
}
|
||
|
||
/**
|
||
* Returns an array of subscription lengths.
|
||
*
|
||
* PayPal Standard Allowable Ranges
|
||
* D – for days; allowable range is 1 to 90
|
||
* W – for weeks; allowable range is 1 to 52
|
||
* M – for months; allowable range is 1 to 24
|
||
* Y – for years; allowable range is 1 to 5
|
||
*
|
||
* @param string $subscription_period string (optional) One of day, week, month or year. If empty, all subscription ranges are returned.
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.0
|
||
* @deprecated 1.0.0 - Migrated from WooCommerce Subscriptions v2.0
|
||
*/
|
||
public static function get_subscription_ranges( $subscription_period = '' ) {
|
||
_deprecated_function( __METHOD__, '2.0', 'wcs_get_subscription_ranges()' );
|
||
return wcs_get_subscription_ranges( $subscription_period );
|
||
}
|
||
|
||
/**
|
||
* Returns an array of allowable trial periods.
|
||
*
|
||
* @see self::get_subscription_ranges()
|
||
* @param string $subscription_period string (optional) One of day, week, month or year. If empty, all subscription ranges are returned.
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.1
|
||
* @deprecated 1.0.0 - Migrated from WooCommerce Subscriptions v2.0
|
||
*/
|
||
public static function get_subscription_trial_lengths( $subscription_period = '' ) {
|
||
_deprecated_function( __METHOD__, '2.0', 'wcs_get_subscription_trial_lengths( $subscription_period )' );
|
||
return wcs_get_subscription_trial_lengths( $subscription_period );
|
||
}
|
||
|
||
/**
|
||
* Return an i18n'ified associative array of all possible subscription trial periods.
|
||
*
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.2
|
||
* @deprecated 1.0.0 - Migrated from WooCommerce Subscriptions v2.0
|
||
*/
|
||
public static function get_subscription_trial_period_strings( $number = 1, $period = '' ) {
|
||
_deprecated_function( __METHOD__, '2.0', 'wcs_get_subscription_trial_period_strings( $number, $period )' );
|
||
return wcs_get_subscription_trial_period_strings( $number, $period );
|
||
}
|
||
|
||
/**
|
||
* Return an i18n'ified associative array of all time periods allowed for subscriptions.
|
||
*
|
||
* @param string $form Either 'singular' for singular trial periods or 'plural'.
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.2
|
||
* @deprecated 1.0.0 - Migrated from WooCommerce Subscriptions v2.0
|
||
*/
|
||
public static function get_available_time_periods( $form = 'singular' ) {
|
||
_deprecated_function( __METHOD__, '2.0', 'wcs_get_available_time_periods( $form )' );
|
||
return wcs_get_available_time_periods( $form );
|
||
}
|
||
|
||
/**
|
||
* Returns the string key for a subscription purchased in an order specified by $order_id
|
||
*
|
||
* @param int $order_id The ID of the order in which the subscription was purchased.
|
||
* @param int $product_id The ID of the subscription product.
|
||
* @return string The key representing the given subscription.
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.0
|
||
*/
|
||
public static function get_subscription_key( $order_id, $product_id = 0 ) {
|
||
|
||
_deprecated_function( __METHOD__, '2.0', 'wcs_get_old_subscription_key( WC_Subscription $subscription )' );
|
||
|
||
// If we have a child renewal order, we need the parent order's ID
|
||
if ( wcs_order_contains_renewal( $order_id ) ) {
|
||
$order_id = WC_Subscriptions_Renewal_Order::get_parent_order_id( $order_id );
|
||
}
|
||
|
||
// Get the ID of the first order item in a subscription created by this order
|
||
if ( empty( $product_id ) ) {
|
||
|
||
$subscriptions = wcs_get_subscriptions_for_order( $order_id, array( 'order_type' => 'parent' ) );
|
||
|
||
foreach ( $subscriptions as $subscription ) {
|
||
$subscription_items = $subscription->get_items();
|
||
if ( ! empty( $subscription_items ) ) {
|
||
break;
|
||
}
|
||
}
|
||
|
||
if ( ! empty( $subscription_items ) ) {
|
||
$first_item = reset( $subscription_items );
|
||
$product_id = WC_Subscriptions_Order::get_items_product_id( $first_item );
|
||
} else {
|
||
$product_id = '';
|
||
}
|
||
}
|
||
|
||
$subscription_key = $order_id . '_' . $product_id;
|
||
|
||
return apply_filters( 'woocommerce_subscription_key', $subscription_key, $order_id, $product_id );
|
||
}
|
||
|
||
/**
|
||
* Returns the number of failed payments for a given subscription.
|
||
*
|
||
* @param string $subscription_key A subscription key of the form created by @see self::get_subscription_key()
|
||
* @param int $user_id The ID of the user who owns the subscriptions. Although this parameter is optional, if you have the User ID you should pass it to improve performance.
|
||
* @return int The number of outstanding failed payments on the subscription, if any.
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.0
|
||
* @deprecated 1.0.0 - Migrated from WooCommerce Subscriptions v2.0
|
||
*/
|
||
public static function get_subscriptions_failed_payment_count( $subscription_key, $user_id = 0 ) {
|
||
_deprecated_function( __METHOD__, '2.0', 'WC_Subscription::get_failed_payment_count()' );
|
||
return apply_filters( 'woocommerce_subscription_failed_payment_count', wcs_get_subscription_from_key( $subscription_key )->get_failed_payment_count(), $user_id, $subscription_key );
|
||
}
|
||
|
||
/**
|
||
* Returns the number of completed payments for a given subscription (including the initial payment).
|
||
*
|
||
* @param string $subscription_key A subscription key of the form created by @see self::get_subscription_key()
|
||
* @return int The number of outstanding failed payments on the subscription, if any.
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.4
|
||
* @deprecated 1.0.0 - Migrated from WooCommerce Subscriptions v2.0
|
||
*/
|
||
public static function get_subscriptions_completed_payment_count( $subscription_key ) {
|
||
_deprecated_function( __METHOD__, '2.0', 'WC_Subscription::get_payment_count()' );
|
||
return apply_filters( 'woocommerce_subscription_completed_payment_count', wcs_get_subscription_from_key( $subscription_key )->get_payment_count(), $subscription_key );
|
||
}
|
||
|
||
/**
|
||
* Takes a subscription key and returns the date on which the subscription is scheduled to expire
|
||
* or 0 if it is cancelled, expired, or never going to expire.
|
||
*
|
||
* @param string $subscription_key A subscription key of the form created by @see self::get_subscription_key()
|
||
* @param int $user_id The ID of the user who owns the subscriptions. Although this parameter is optional, if you have the User ID you should pass it to improve performance.
|
||
* @param string $type (optional) The format for the Either 'mysql' or 'timestamp'.
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.1
|
||
* @deprecated 1.0.0 - Migrated from WooCommerce Subscriptions v2.0
|
||
*/
|
||
public static function get_subscription_expiration_date( $subscription_key, $user_id = 0, $type = 'mysql' ) {
|
||
_deprecated_function( __METHOD__, '2.0', 'WC_Subscription::get_date( "end" )' );
|
||
$subscription = wcs_get_subscription_from_key( $subscription_key );
|
||
$expiration_date = ( 'mysql' == $type ) ? $subscription->get_date( 'end' ) : $subscription->get_time( 'end' );
|
||
return apply_filters( 'woocommerce_subscription_expiration_date', $expiration_date, $subscription_key, $user_id );
|
||
}
|
||
|
||
/**
|
||
* Updates a subscription's expiration date as scheduled in WP-Cron and in the subscription details array.
|
||
*
|
||
* @param string $subscription_key A subscription key of the form created by @see self::get_subscription_key()
|
||
* @param int $user_id (optional) The ID of the user who owns the subscriptions. Although this parameter is optional, if you have the User ID you should pass it to improve performance.
|
||
* @param string|int $expiration_date (optional)The date and time the subscription will expire, either as MySQL formatted datetime string or a Unix timestamp. If empty, @see self::calculate_subscription_expiration_date() will be called.
|
||
* @return mixed If the expiration does not get set, returns false, otherwise it will return a MySQL datetime formatted string for the new date when the subscription will expire
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.2.4
|
||
* @deprecated 1.0.0 - Migrated from WooCommerce Subscriptions v2.0
|
||
*/
|
||
public static function set_expiration_date( $subscription_key, $user_id = 0, $expiration_date = '' ) {
|
||
_deprecated_function( __METHOD__, '2.0', 'WC_Subscription::update_dates( array( "end" => $expiration_date ) )' );
|
||
if ( is_int( $expiration_date ) ) {
|
||
$expiration_date = gmdate( 'Y-m-d H:i:s', $expiration_date );
|
||
}
|
||
$subscription = wcs_get_subscription_from_key( $subscription_key );
|
||
return apply_filters( 'woocommerce_subscriptions_set_expiration_date', $subscription->update_dates( array( 'end' => $expiration_date ) ), $subscription->get_date( 'end' ), $subscription_key, $user_id );
|
||
}
|
||
|
||
/**
|
||
* A subscription now either has an end date or it doesn't, there is no way to calculate it based on the original subscription
|
||
* product (because a WC_Subscription object can have more than one product and syncing length with expiration date was both
|
||
* cumbersome and error prone).
|
||
*
|
||
* Takes a subscription key and calculates the date on which the subscription is scheduled to expire
|
||
* or 0 if it will never expire.
|
||
*
|
||
* @param string $subscription_key A subscription key of the form created by @see self::get_subscription_key()
|
||
* @param int $user_id The ID of the user who owns the subscriptions. Although this parameter is optional, if you have the User ID you should pass it to improve performance.
|
||
* @param string $type (optional) The format for the Either 'mysql' or 'timestamp'.
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.1
|
||
* @deprecated 1.0.0 - Migrated from WooCommerce Subscriptions v2.0
|
||
*/
|
||
public static function calculate_subscription_expiration_date( $subscription_key, $user_id = 0, $type = 'mysql' ) {
|
||
_deprecated_function( __METHOD__, '2.0', 'WC_Subscription::get_date( "end" )' );
|
||
$subscription = wcs_get_subscription_from_key( $subscription_key );
|
||
$expiration_date = ( 'mysql' == $type ) ? $subscription->get_date( 'end' ) : $subscription->get_time( 'end' );
|
||
return apply_filters( 'woocommerce_subscription_calculated_expiration_date', $expiration_date, $subscription_key, $user_id );
|
||
}
|
||
|
||
/**
|
||
* Takes a subscription key and returns the date on which the next recurring payment is to be billed, if any.
|
||
*
|
||
* @param string $subscription_key A subscription key of the form created by @see self::get_subscription_key()
|
||
* @param int $user_id The ID of the user who owns the subscriptions. Although this parameter is optional, if you have the User ID you should pass it to improve performance.
|
||
* @param string $type (optional) The format for the Either 'mysql' or 'timestamp'.
|
||
* @return mixed If there is no future payment set, returns 0, otherwise it will return a date of the next payment in the form specified by $type
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.2
|
||
* @deprecated 1.0.0 - Migrated from WooCommerce Subscriptions v2.0
|
||
*/
|
||
public static function get_next_payment_date( $subscription_key, $user_id = 0, $type = 'mysql' ) {
|
||
_deprecated_function( __METHOD__, '2.0', 'WC_Subscription::get_date( "next_payment" )' );
|
||
$subscription = wcs_get_subscription_from_key( $subscription_key );
|
||
$next_payment = ( 'mysql' == $type ) ? $subscription->get_date( 'next_payment' ) : $subscription->get_time( 'next_payment' );
|
||
return apply_filters( 'woocommerce_subscription_next_payment_date', $next_payment, $subscription_key, $user_id, $type );
|
||
}
|
||
|
||
/**
|
||
* Clears the payment schedule for a subscription and schedules a new date for the next payment.
|
||
*
|
||
* If updating the an existing next payment date (instead of setting a new date, you should use @see self::update_next_payment_date() instead
|
||
* as it will validate the next payment date and update the WP-Cron lock.
|
||
*
|
||
* @param string $subscription_key A subscription key of the form created by @see self::get_subscription_key()
|
||
* @param int $user_id (optional) The ID of the user who owns the subscriptions. Although this parameter is optional, if you have the User ID you should pass it to improve performance.
|
||
* @param string|int $next_payment (optional) The date and time the next payment is due, either as MySQL formatted datetime string or a Unix timestamp. If empty, @see self::calculate_next_payment_date() will be called.
|
||
* @return mixed If there is no future payment set, returns 0, otherwise it will return a MySQL datetime formatted string for the date of the next payment
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.2
|
||
* @deprecated 1.0.0 - Migrated from WooCommerce Subscriptions v2.0
|
||
*/
|
||
public static function set_next_payment_date( $subscription_key, $user_id = 0, $next_payment = '' ) {
|
||
_deprecated_function( __METHOD__, '2.0', 'WC_Subscription::update_dates( array( "next_payment" => $next_payment ) )' );
|
||
|
||
if ( is_int( $next_payment ) ) {
|
||
$next_payment = gmdate( 'Y-m-d H:i:s', $next_payment );
|
||
}
|
||
|
||
$subscription = wcs_get_subscription_from_key( $subscription_key );
|
||
|
||
return apply_filters( 'woocommerce_subscription_set_next_payment_date', $subscription->update_dates( array( 'next_payment' => $next_payment ) ), $subscription->get_date( 'next_payment' ), $subscription_key, $user_id );
|
||
}
|
||
|
||
/**
|
||
* Takes a subscription key and returns the date on which the next recurring payment is to be billed, if any.
|
||
*
|
||
* @param string $subscription_key A subscription key of the form created by @see self::get_subscription_key()
|
||
* @param int $user_id The ID of the user who owns the subscriptions. Although this parameter is optional, if you have the User ID you should pass it to improve performance.
|
||
* @param string $type (optional) The format for the Either 'mysql' or 'timestamp'.
|
||
* @return mixed If there is no future payment set, returns 0, otherwise it will return a date of the next payment in the form specified by $type
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.2
|
||
* @deprecated 1.0.0 - Migrated from WooCommerce Subscriptions v2.0
|
||
*/
|
||
public static function get_last_payment_date( $subscription_key, $user_id = 0, $type = 'mysql' ) {
|
||
_deprecated_function( __METHOD__, '2.0', 'WC_Subscription::get_date( "last_payment" )' );
|
||
$subscription = wcs_get_subscription_from_key( $subscription_key );
|
||
$last_payment_date = ( 'mysql' == $type ) ? $subscription->get_date( 'last_order_date_created' ) : $subscription->get_time( 'last_order_date_created' );
|
||
return apply_filters( 'woocommerce_subscription_last_payment_date', $last_payment_date, $subscription_key, $user_id, $type );
|
||
}
|
||
|
||
/**
|
||
* Changes the transient used to safeguard against firing scheduled_subscription_payments during a payment period.
|
||
*
|
||
* @param string $subscription_key A subscription key of the form created by @see self::get_subscription_key()
|
||
* @param int $lock_time The amount of time to lock for in seconds from now, the lock will be set 1 hour before this time
|
||
* @param int $user_id (optional) The ID of the user who owns the subscriptions. Although this parameter is optional, if you have the User ID you should pass it to improve performance.
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.2
|
||
* @deprecated 1.0.0 - Migrated from WooCommerce Subscriptions v2.0
|
||
*/
|
||
public static function update_wp_cron_lock( $subscription_key, $lock_time, $user_id = 0 ) {
|
||
_deprecated_function( __METHOD__, '2.0' );
|
||
}
|
||
|
||
/**
|
||
* Clears the payment schedule for a subscription and sets a net date
|
||
*
|
||
* @param string $subscription_key A subscription key of the form created by @see self::get_subscription_key()
|
||
* @param int $user_id (optional) The ID of the user who owns the subscriptions. Although this parameter is optional, if you have the User ID you should pass it to improve performance.
|
||
* @param string $type (optional) The format for the Either 'mysql' or 'timestamp'.
|
||
* @return mixed If there is no future payment set, returns 0, otherwise it will return a date of the next payment of the type specified with $type
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.2
|
||
* @deprecated 1.0.0 - Migrated from WooCommerce Subscriptions v2.0
|
||
*/
|
||
public static function calculate_next_payment_date( $subscription_key, $user_id = 0, $type = 'mysql', $from_date = '' ) {
|
||
_deprecated_function( __METHOD__, '2.0', 'WC_Subscription::calculate_date( "next_payment" )' );
|
||
$subscription = wcs_get_subscription_from_key( $subscription_key );
|
||
$next_payment = $subscription->calculate_date( 'next_payment' );
|
||
return ( 'mysql' == $type ) ? $next_payment : wcs_date_to_time( $next_payment );
|
||
}
|
||
|
||
/**
|
||
* Takes a subscription key and returns the date on which the trial for the subscription ended or is going to end, if any.
|
||
*
|
||
* @param string $subscription_key A subscription key of the form created by @see self::get_subscription_key()
|
||
* @param int $user_id The ID of the user who owns the subscriptions. Although this parameter is optional, if you have the User ID you should pass it to improve performance.
|
||
* @return mixed If the subscription has no trial period, returns 0, otherwise it will return the date the trial period ends or ended in the form specified by $type
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.2
|
||
*/
|
||
public static function get_trial_expiration_date( $subscription_key, $user_id = 0, $type = 'mysql' ) {
|
||
_deprecated_function( __METHOD__, '2.0', 'WC_Subscription::get_date( "trial_end" )' );
|
||
$subscription = wcs_get_subscription_from_key( $subscription_key );
|
||
$trial_end_date = ( 'mysql' == $type ) ? $subscription->get_date( 'trial_end' ) : $subscription->get_time( 'trial_end' );
|
||
return apply_filters( 'woocommerce_subscription_trial_expiration_date', $trial_end_date, $subscription_key, $user_id, $type );
|
||
}
|
||
|
||
/**
|
||
* Updates the trial expiration date as scheduled in WP-Cron and in the subscription details array.
|
||
*
|
||
* @param string $subscription_key A subscription key of the form created by @see self::get_subscription_key()
|
||
* @param int $user_id (optional) The ID of the user who owns the subscription. Although this parameter is optional, if you have the User ID you should pass it to improve performance.
|
||
* @param string|int $trial_expiration_date (optional) The date and time the trial will expire, either as MySQL formatted datetime string or a Unix timestamp. If empty, @see self::calculate_next_payment_date() will be called.
|
||
* @return mixed If the trial expiration does not get set, returns false, otherwise it will return a MySQL datetime formatted string for the new date when the trial will expire
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.2.4
|
||
*/
|
||
public static function set_trial_expiration_date( $subscription_key, $user_id = 0, $trial_expiration_date = '' ) {
|
||
_deprecated_function( __METHOD__, '2.0', 'WC_Subscription::update_dates( array( "trial_end" => $expiration_date ) )' );
|
||
if ( is_int( $trial_expiration_date ) ) {
|
||
$trial_expiration_date = gmdate( 'Y-m-d H:i:s', $trial_expiration_date );
|
||
}
|
||
$subscription = wcs_get_subscription_from_key( $subscription_key );
|
||
return apply_filters( 'woocommerce_subscriptions_set_trial_expiration_date', $subscription->update_dates( array( 'trial_end' => $trial_expiration_date ) ), $subscription->get_date( 'trial_end' ), $subscription_key, $user_id );
|
||
}
|
||
|
||
/**
|
||
* Takes a subscription key and calculates the date on which the subscription's trial should end
|
||
* or 0 if no trial is set.
|
||
*
|
||
* @param string $subscription_key A subscription key of the form created by @see self::get_subscription_key()
|
||
* @param int $user_id The ID of the user who owns the subscriptions. Although this parameter is optional, if you have the User ID you should pass it to improve performance.
|
||
* @param string $type (optional) The format for the Either 'mysql' or 'timestamp'.
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.1
|
||
*/
|
||
public static function calculate_trial_expiration_date( $subscription_key, $user_id = 0, $type = 'mysql' ) {
|
||
_deprecated_function( __METHOD__, '2.0', 'WC_Subscription::calculate_date( "trial_end" )' );
|
||
$subscription = wcs_get_subscription_from_key( $subscription_key );
|
||
$trial_end = $subscription->calculate_date( 'trial_end' );
|
||
$trial_end = ( 'mysql' == $type ) ? $trial_end : wcs_date_to_time( $trial_end );
|
||
return apply_filters( 'woocommerce_subscription_calculated_trial_expiration_date', $trial_end, $subscription_key, $user_id );
|
||
}
|
||
|
||
/**
|
||
* Takes a subscription key and returns the user who owns the subscription (based on the order ID in the subscription key).
|
||
*
|
||
* @param string $subscription_key A subscription key of the form created by @see self::get_subscription_key()
|
||
* @return int The ID of the user who owns the subscriptions, or 0 if no user can be found with the subscription
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.2
|
||
*/
|
||
public static function get_user_id_from_subscription_key( $subscription_key ) {
|
||
_deprecated_function( __METHOD__, '2.0', 'WC_Subscription::get_user_id()' );
|
||
$subscription = wcs_get_subscription_from_key( $subscription_key );
|
||
return $subscription->get_user_id();
|
||
}
|
||
|
||
/**
|
||
* Checks if a subscription requires manual payment because the payment gateway used to purchase the subscription
|
||
* did not support automatic payments at the time of the subscription sign up.
|
||
*
|
||
* @param string $subscription_key A subscription key of the form created by @see self::get_subscription_key()
|
||
* @param int $user_id The ID of the user who owns the subscriptions. Although this parameter is optional, if you have the User ID you should pass it to improve performance.
|
||
* @return bool | null True if the subscription exists and requires manual payments, false if the subscription uses automatic payments, null if the subscription doesn't exist.
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.2
|
||
* @deprecated 1.0.0 - Migrated from WooCommerce Subscriptions v2.0
|
||
*/
|
||
public static function requires_manual_renewal( $subscription_key, $user_id = 0 ) {
|
||
_deprecated_function( __METHOD__, '2.0', 'WC_Subscription::is_manual()' );
|
||
return wcs_get_subscription_from_key( $subscription_key )->is_manual();
|
||
}
|
||
|
||
/**
|
||
* Checks if a subscription has an unpaid renewal order.
|
||
*
|
||
* @param string $subscription_key A subscription key of the form created by @see self::get_subscription_key()
|
||
* @param int $user_id The ID of the user who owns the subscriptions. Although this parameter is optional, if you have the User ID you should pass it to improve performance.
|
||
* @return bool True if the subscription has an unpaid renewal order, false if the subscription has no unpaid renewal orders.
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.2
|
||
*/
|
||
public static function subscription_requires_payment( $subscription_key, $user_id ) {
|
||
_deprecated_function( __METHOD__, '2.0', 'WC_Subscription::needs_payment()' );
|
||
$subscription = wcs_get_subscription_from_key( $subscription_key );
|
||
return apply_filters( 'woocommerce_subscription_requires_payment', $subscription->needs_payment(), wcs_get_subscription_in_deprecated_structure( $subscription ), $subscription_key, $user_id );
|
||
}
|
||
|
||
/*
|
||
* User API Functions
|
||
*/
|
||
|
||
/**
|
||
* Check if a user owns a subscription, as specified with $subscription_key.
|
||
*
|
||
* If no user is specified, the currently logged in user will be used.
|
||
*
|
||
* @param string $subscription_key A subscription key of the form created by @see self::get_subscription_key()
|
||
* @param int $user_id (optional) int The ID of the user to check against. Defaults to the currently logged in user.
|
||
* @return bool True if the user has the subscription (or any subscription if no subscription specified), otherwise false.
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.3
|
||
* @deprecated 1.0.0 - Migrated from WooCommerce Subscriptions v2.0
|
||
*/
|
||
public static function user_owns_subscription( $subscription_key, $user_id = 0 ) {
|
||
_deprecated_function( __METHOD__, '2.0', 'WC_Subscriptions::get_user_id()' );
|
||
|
||
if ( 0 === $user_id ) {
|
||
$user_id = get_current_user_id();
|
||
}
|
||
|
||
$subscription = wcs_get_subscription_from_key( $subscription_key );
|
||
|
||
if ( $subscription->get_user_id() == $user_id ) {
|
||
$owns_subscription = true;
|
||
} else {
|
||
$owns_subscription = false;
|
||
}
|
||
|
||
return apply_filters( 'woocommerce_user_owns_subscription', $owns_subscription, $subscription_key, $user_id );
|
||
}
|
||
|
||
/**
|
||
* Check if a user has a subscription, optionally specified with $product_id.
|
||
*
|
||
* @param int $user_id (optional) The id of the user whose subscriptions you want. Defaults to the currently logged in user.
|
||
* @param int $product_id (optional) The ID of a subscription product.
|
||
* @param string $status (optional) A subscription status to check against. For example, for a $status of 'active', a subscriber must have an active subscription for a return value of true.
|
||
* @return bool True if the user has the subscription (or any subscription if no subscription specified), otherwise false.
|
||
* @version 1.0.0 - Migrated from WooCommerce Subscriptions v1.3.5
|
||
*/
|
||
public static function user_has_subscription( $user_id = 0, $product_id = 0, $status = 'any' ) {
|
||
_deprecated_function( __METHOD__, '2.0', 'wcs_user_has_subscription()' );
|
||
return wcs_user_has_subscription( $user_id, $product_id, $status );
|
||
}
|
||
|
||
/**
|
||
* Gets all the active and inactive subscriptions for all users.
|
||
*
|
||
* @return array An associative array containing all users with subscriptions and the details of their subscriptions: 'user_id' => $subscriptions
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.0
|
||
*/
|
||
public static function get_all_users_subscriptions() {
|
||
_deprecated_function( __METHOD__, '2.0' );
|
||
$subscriptions_in_old_format = array();
|
||
|
||
foreach ( get_users() as $user ) {
|
||
foreach ( wcs_get_users_subscriptions( $user->ID ) as $subscription ) {
|
||
$subscriptions_in_old_format[ wcs_get_old_subscription_key( $subscription ) ] = wcs_get_subscription_in_deprecated_structure( $subscription );
|
||
}
|
||
}
|
||
|
||
return apply_filters( 'woocommerce_all_users_subscriptions', $subscriptions_in_old_format );
|
||
}
|
||
|
||
/**
|
||
* Gets all the active and inactive subscriptions for a user, as specified by $user_id
|
||
*
|
||
* @param int $user_id (optional) The id of the user whose subscriptions you want. Defaults to the currently logged in user.
|
||
* @param array $order_ids (optional) An array of post_ids of WC_Order objects as a way to get only subscriptions for certain orders. Defaults to null, which will return subscriptions for all orders.
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.0
|
||
*/
|
||
public static function get_users_subscriptions( $user_id = 0, $order_ids = array() ) {
|
||
_deprecated_function( __METHOD__, '2.0', 'wcs_get_users_subscriptions( $user_id )' );
|
||
|
||
$subscriptions_in_old_format = array();
|
||
|
||
foreach ( wcs_get_users_subscriptions( $user_id ) as $subscription ) {
|
||
$subscriptions_in_old_format[ wcs_get_old_subscription_key( $subscription ) ] = wcs_get_subscription_in_deprecated_structure( $subscription );
|
||
}
|
||
|
||
return apply_filters( 'woocommerce_users_subscriptions', $subscriptions_in_old_format, $user_id );
|
||
}
|
||
|
||
/**
|
||
* Gets all the subscriptions for a user that have been trashed, as specified by $user_id
|
||
*
|
||
* @param int $user_id (optional) The id of the user whose subscriptions you want. Defaults to the currently logged in user.
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.0
|
||
*/
|
||
public static function get_users_trashed_subscriptions( $user_id = 0 ) {
|
||
|
||
$subscriptions = self::get_users_subscriptions( $user_id );
|
||
|
||
foreach ( $subscriptions as $key => $subscription ) {
|
||
if ( 'trash' != $subscription['status'] ) {
|
||
unset( $subscriptions[ $key ] );
|
||
}
|
||
}
|
||
|
||
return apply_filters( 'woocommerce_users_trashed_subscriptions', $subscriptions, $user_id );
|
||
}
|
||
|
||
/**
|
||
* A convenience wrapper to assign the inactive subscriber role to a user.
|
||
*
|
||
* @param int $user_id The id of the user whose role should be changed
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.2
|
||
* @deprecated 1.0.0 - Migrated from WooCommerce Subscriptions v2.0
|
||
*/
|
||
public static function make_user_inactive( $user_id ) {
|
||
_deprecated_function( __METHOD__, '2.0', 'wcs_make_user_inactive()' );
|
||
wcs_make_user_inactive( $user_id );
|
||
}
|
||
|
||
/**
|
||
* A convenience wrapper to assign the cancelled subscriber role to a user.
|
||
*
|
||
* Hooked to 'subscription_end_of_prepaid_term' hook.
|
||
*
|
||
* @param int $user_id The id of the user whose role should be changed
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.3.2
|
||
* @deprecated 1.0.0 - Migrated from WooCommerce Subscriptions v2.0
|
||
*/
|
||
public static function maybe_assign_user_cancelled_role( $user_id ) {
|
||
_deprecated_function( __METHOD__, '2.0', 'wcs_maybe_make_user_inactive()' );
|
||
wcs_maybe_make_user_inactive( $user_id );
|
||
}
|
||
|
||
/**
|
||
* A convenience wrapper for changing a users role.
|
||
*
|
||
* @param int $user_id The id of the user whose role should be changed
|
||
* @param string $role_name Either a WordPress role or one of the WCS keys: 'default_subscriber_role' or 'default_cancelled_role'
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.0
|
||
* @deprecated 1.0.0 - Migrated from WooCommerce Subscriptions v2.0
|
||
*/
|
||
public static function update_users_role( $user_id, $role_name ) {
|
||
_deprecated_function( __METHOD__, '2.0', 'wcs_update_users_role()' );
|
||
wcs_update_users_role( $user_id, $role_name );
|
||
}
|
||
|
||
/**
|
||
* Marks a customer as a paying customer when their subscription is activated.
|
||
*
|
||
* A wrapper for the @see woocommerce_paying_customer() function.
|
||
*
|
||
* @param int $order The order for which customers should be pulled from and marked as paying.
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.0
|
||
* @deprecated 1.0.0 - Migrated from WooCommerce Subscriptions v2.0
|
||
*/
|
||
public static function mark_paying_customer( $order ) {
|
||
_deprecated_function( __METHOD__, '2.0' );
|
||
|
||
if ( ! is_object( $order ) ) {
|
||
$order = new WC_Order( $order );
|
||
}
|
||
|
||
update_user_meta( $order->get_user_id(), 'paying_customer', 1 );
|
||
}
|
||
|
||
/**
|
||
* Unlike someone making a once-off payment, a subscriber can cease to be a paying customer. This function
|
||
* changes a user's status to non-paying.
|
||
*
|
||
* Deprecated as orders now take care of the customer's status as paying or not paying
|
||
*
|
||
* @param object $order The order for which a customer ID should be pulled from and marked as paying.
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.0
|
||
* @deprecated 1.0.0 - Migrated from WooCommerce Subscriptions v2.0
|
||
*/
|
||
public static function mark_not_paying_customer( $order ) {
|
||
_deprecated_function( __METHOD__, '2.0' );
|
||
|
||
if ( ! is_object( $order ) ) {
|
||
$order = new WC_Order( $order );
|
||
}
|
||
|
||
if ( $order->get_user_id() > 0 ) {
|
||
update_user_meta( $order->get_user_id(), 'paying_customer', 0 );
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Return a link for subscribers to change the status of their subscription, as specified with $status parameter
|
||
*
|
||
* @param string $subscription_key A subscription key of the form created by @see self::get_subscription_key()
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.0
|
||
* @deprecated 1.0.0 - Migrated from WooCommerce Subscriptions v2.0
|
||
*/
|
||
public static function get_users_change_status_link( $subscription_key, $status ) {
|
||
_deprecated_function( __METHOD__, '2.0', 'wcs_get_users_change_status_link( $subscription_id, $status )' );
|
||
|
||
if ( 'suspended' == $status ) {
|
||
_deprecated_argument( __METHOD__, '2.0', 'The "suspended" parameter value is deprecated. Use "on-hold" instead.' );
|
||
$status = 'on-hold';
|
||
}
|
||
|
||
$subscription_id = wcs_get_subscription_id_from_key( $subscription_key );
|
||
|
||
$current_status = '';
|
||
$subscription = wcs_get_subscription( $subscription_id );
|
||
if ( $subscription instanceof WC_Subscription ) {
|
||
$current_status = $subscription->get_status();
|
||
}
|
||
|
||
return apply_filters( 'woocommerce_subscriptions_users_action_link', wcs_get_users_change_status_link( $subscription_id, $status, $current_status ), $subscription_key, $status );
|
||
}
|
||
|
||
/**
|
||
* Change a subscription's next payment date.
|
||
*
|
||
* @param mixed $new_payment_date Either a MySQL formatted Date/time string or a Unix timestamp.
|
||
* @param string $subscription_key A subscription key of the form created by @see self::get_subscription_key()
|
||
* @param int $user_id The id of the user who purchased the subscription
|
||
* @param string $timezone Either 'server' or 'user' to describe the timezone of the $new_payment_date.
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.2
|
||
* @deprecated 1.0.0 - Migrated from WooCommerce Subscriptions v2.0
|
||
*/
|
||
public static function update_next_payment_date( $new_payment_date, $subscription_key, $user_id = 0, $timezone = 'server' ) {
|
||
_deprecated_function( __METHOD__, '2.0', 'WC_Subscription::update_dates( array( "next_payment" => $new_payment_date ) )' );
|
||
|
||
$new_payment_timestamp = ( is_numeric( $new_payment_date ) ) ? $new_payment_date : wcs_date_to_time( $new_payment_date );
|
||
|
||
// The date needs to be converted to GMT/UTC
|
||
if ( 'server' != $timezone ) {
|
||
$new_payment_timestamp = $new_payment_timestamp - ( get_option( 'gmt_offset' ) * 3600 );
|
||
}
|
||
|
||
$new_payment_date = gmdate( 'Y-m-d H:i:s', $new_payment_timestamp );
|
||
|
||
$subscription = wcs_get_subscription_from_key( $subscription_key );
|
||
|
||
try {
|
||
$subscription->update_dates( array( 'next_payment' => $new_payment_date ) );
|
||
$response = $subscription->get_time( 'next_payment' );
|
||
|
||
} catch ( Exception $e ) {
|
||
$response = new WP_Error( 'invalid-date', $e->getMessage() );
|
||
}
|
||
|
||
return $response;
|
||
}
|
||
|
||
/*
|
||
* Helper Functions
|
||
*/
|
||
|
||
/**
|
||
* Because neither PHP nor WP include a real array merge function that works recursively.
|
||
*
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.0
|
||
*/
|
||
public static function array_merge_recursive_for_real( $first_array, $second_array ) {
|
||
|
||
$merged = $first_array;
|
||
|
||
if ( is_array( $second_array ) ) {
|
||
foreach ( $second_array as $key => $val ) {
|
||
if ( is_array( $second_array[ $key ] ) ) {
|
||
$merged[ $key ] = ( isset( $merged[ $key ] ) && is_array( $merged[ $key ] ) ) ? self::array_merge_recursive_for_real( $merged[ $key ], $second_array[ $key ] ) : $second_array[ $key ];
|
||
} else {
|
||
$merged[ $key ] = $val;
|
||
}
|
||
}
|
||
}
|
||
|
||
return $merged;
|
||
}
|
||
|
||
/**
|
||
* Takes a total and calculates the recurring proportion of that based on $proportion and then fixes any rounding bugs to
|
||
* make sure the totals add up.
|
||
*
|
||
* Used mainly to calculate the recurring amount from a total which may also include a sign up fee.
|
||
*
|
||
* @param float $total The total amount
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.2
|
||
* @return float $proportion A proportion of the total (e.g. 0.5 is half of the total)
|
||
*/
|
||
public static function get_amount_from_proportion( $total, $proportion ) {
|
||
|
||
$sign_up_fee_proportion = 1 - $proportion;
|
||
|
||
$sign_up_total = round( $total * $sign_up_fee_proportion, 2 );
|
||
$recurring_amount = round( $total * $proportion, 2 );
|
||
|
||
// Handle any rounding bugs
|
||
if ( $sign_up_total + $recurring_amount != $total ) {
|
||
$recurring_amount = $recurring_amount - ( $sign_up_total + $recurring_amount - $total );
|
||
}
|
||
|
||
return $recurring_amount;
|
||
}
|
||
|
||
/**
|
||
* Creates a subscription price string from an array of subscription details. For example, ""$5 / month for 12 months".
|
||
*
|
||
* @param array $subscription_details A set of name => value pairs for the subscription details to include in the string. Available keys:
|
||
* 'initial_amount': The upfront payment for the subscription, including sign up fees, as a string from the @see woocommerce_price(). Default empty string (no initial payment)
|
||
* 'initial_description': The word after the initial payment amount to describe the amount. Examples include "now" or "initial payment". Defaults to "up front".
|
||
* 'recurring_amount': The amount charged per period. Default 0 (no recurring payment).
|
||
* 'subscription_interval': How regularly the subscription payments are charged. Default 1, meaning each period e.g. per month.
|
||
* 'subscription_period': The temporal period of the subscription. Should be one of {day|week|month|year} as used by @see self::get_subscription_period_strings()
|
||
* 'subscription_length': The total number of periods the subscription should continue for. Default 0, meaning continue indefinitely.
|
||
* 'trial_length': The total number of periods the subscription trial period should continue for. Default 0, meaning no trial period.
|
||
* 'trial_period': The temporal period for the subscription's trial period. Should be one of {day|week|month|year} as used by @see self::get_subscription_period_strings()
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.2
|
||
* @deprecated 1.0.0 - Migrated from WooCommerce Subscriptions v2.0
|
||
* @return float $proportion A proportion of the total (e.g. 0.5 is half of the total)
|
||
*/
|
||
public static function get_subscription_price_string( $subscription_details ) {
|
||
_deprecated_function( __METHOD__, '2.0', 'wcs_price_string()' );
|
||
return wcs_price_string( $subscription_details );
|
||
}
|
||
|
||
|
||
/**
|
||
* Copy of the WordPress "touch_time" template function for use with a variety of different times
|
||
*
|
||
* @param array $args A set of name => value pairs to customise how the function operates. Available keys:
|
||
* 'date': (string) the date to display in the selector in MySQL format ('Y-m-d H:i:s'). Required.
|
||
* 'tab_index': (int) the tab index for the element. Optional. Default 0.
|
||
* 'multiple': (bool) whether there will be multiple instances of the element on the same page (determines whether to include an ID or not). Default false.
|
||
* 'echo': (bool) whether to return and print the element or simply return it. Default true.
|
||
* 'include_time': (bool) whether to include a specific time for the selector. Default true.
|
||
* 'include_year': (bool) whether to include a the year field. Default true.
|
||
* 'include_buttons': (bool) whether to include submit buttons on the selector. Default true.
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.2
|
||
*/
|
||
public static function touch_time( $args = array() ) {
|
||
global $wp_locale;
|
||
|
||
$args = wp_parse_args(
|
||
$args,
|
||
array(
|
||
'date' => true,
|
||
'tab_index' => 0,
|
||
'multiple' => false,
|
||
'echo' => true,
|
||
'include_time' => true,
|
||
'include_buttons' => true,
|
||
)
|
||
);
|
||
|
||
if ( empty( $args['date'] ) ) {
|
||
return;
|
||
}
|
||
|
||
$tab_index_attribute = ( (int) $args['tab_index'] > 0 ) ? ' tabindex="' . $args['tab_index'] . '"' : '';
|
||
|
||
$month = mysql2date( 'n', $args['date'], false );
|
||
|
||
$month_input = '<select ' . ( $args['multiple'] ? '' : 'id="edit-month" ' ) . 'name="edit-month"' . $tab_index_attribute . '>';
|
||
for ( $i = 1; $i < 13; $i = $i + 1 ) {
|
||
$month_numeral = zeroise( $i, 2 );
|
||
$month_input .= '<option value="' . $month_numeral . '"';
|
||
$month_input .= ( $i == $month ) ? ' selected="selected"' : '';
|
||
// translators: 1$: month number (e.g. "01"), 2$: month abbreviation (e.g. "Jan")
|
||
$month_input .= '>' . sprintf( _x( '%1$s-%2$s', 'used in a select box', 'woocommerce-subscriptions' ), $month_numeral, $wp_locale->get_month_abbrev( $wp_locale->get_month( $i ) ) ) . "</option>\n";
|
||
}
|
||
$month_input .= '</select>';
|
||
|
||
$day_input = '<input type="text" ' . ( $args['multiple'] ? '' : 'id="edit-day" ' ) . 'name="edit-day" value="' . mysql2date( 'd', $args['date'], false ) . '" size="2" maxlength="2"' . $tab_index_attribute . ' autocomplete="off" />';
|
||
$year_input = '<input type="text" ' . ( $args['multiple'] ? '' : 'id="edit-year" ' ) . 'name="edit-year" value="' . mysql2date( 'Y', $args['date'], false ) . '" size="4" maxlength="4"' . $tab_index_attribute . ' autocomplete="off" />';
|
||
|
||
if ( $args['include_time'] ) {
|
||
|
||
$hour_input = '<input type="text" ' . ( $args['multiple'] ? '' : 'id="edit-hour" ' ) . 'name="edit-hour" value="' . mysql2date( 'H', $args['date'], false ) . '" size="2" maxlength="2"' . $tab_index_attribute . ' autocomplete="off" />';
|
||
$minute_input = '<input type="text" ' . ( $args['multiple'] ? '' : 'id="edit-minute" ' ) . 'name="edit-minute" value="' . mysql2date( 'i', $args['date'], false ) . '" size="2" maxlength="2"' . $tab_index_attribute . ' autocomplete="off" />';
|
||
|
||
// translators: all fields are full html nodes: 1$: month input, 2$: day input, 3$: year input, 4$: hour input, 5$: minute input. Change the order if you'd like
|
||
$touch_time = sprintf( __( '%1$s%2$s, %3$s @ %4$s : %5$s', 'woocommerce-subscriptions' ), $month_input, $day_input, $year_input, $hour_input, $minute_input );
|
||
|
||
} else {
|
||
// translators: all fields are full html nodes: 1$: month input, 2$: day input, 3$: year input. Change the order if you'd like
|
||
$touch_time = sprintf( __( '%1$s%2$s, %3$s', 'woocommerce-subscriptions' ), $month_input, $day_input, $year_input );
|
||
}
|
||
|
||
if ( $args['include_buttons'] ) {
|
||
$touch_time .= '<p>';
|
||
$touch_time .= '<a href="#edit_timestamp" class="save-timestamp hide-if-no-js button">' . __( 'Change', 'woocommerce-subscriptions' ) . '</a>';
|
||
$touch_time .= '<a href="#edit_timestamp" class="cancel-timestamp hide-if-no-js">' . _x( 'Cancel', 'an action on a subscription', 'woocommerce-subscriptions' ) . '</a>';
|
||
$touch_time .= '</p>';
|
||
}
|
||
|
||
$allowed_html = array(
|
||
'select' => array(
|
||
'id' => array(),
|
||
'name' => array(),
|
||
'tabindex' => array(),
|
||
),
|
||
'option' => array(
|
||
'value' => array(),
|
||
'selected' => array(),
|
||
),
|
||
'input' => array(
|
||
'type' => array(),
|
||
'id' => array(),
|
||
'name' => array(),
|
||
'value' => array(),
|
||
'size' => array(),
|
||
'tabindex' => array(),
|
||
'maxlength' => array(),
|
||
'autocomplete' => array(),
|
||
),
|
||
'p' => array(),
|
||
'a' => array(
|
||
'href' => array(),
|
||
'title' => array(),
|
||
'class' => array(),
|
||
),
|
||
);
|
||
|
||
if ( $args['echo'] ) {
|
||
echo wp_kses( $touch_time, $allowed_html );
|
||
}
|
||
|
||
return $touch_time;
|
||
}
|
||
|
||
/**
|
||
* If a gateway doesn't manage payment schedules, then we should suspend the subscription until it is paid (i.e. for manual payments
|
||
* or token gateways like Stripe). If the gateway does manage the scheduling, then we shouldn't suspend the subscription because a
|
||
* gateway may use batch processing on the time payments are charged and a subscription could end up being incorrectly suspended.
|
||
*
|
||
* @param int $user_id The id of the user whose subscription should be put on-hold.
|
||
* @param string $subscription_key A subscription key of the form created by @see self::get_subscription_key()
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.2.5
|
||
* @deprecated 1.0.0 - Migrated from WooCommerce Subscriptions v2.0
|
||
*/
|
||
public static function maybe_put_subscription_on_hold( $user_id, $subscription_key ) {
|
||
_deprecated_function( __METHOD__, '2.0', 'WC_Subscription::update_status()' );
|
||
|
||
try {
|
||
$subscription = wcs_get_subscription_from_key( $subscription_key );
|
||
|
||
if ( $subscription->has_status( 'on-hold' ) ) {
|
||
return false;
|
||
}
|
||
} catch ( Exception $e ) {
|
||
return false;
|
||
}
|
||
|
||
// If the subscription is using manual payments, the gateway isn't active or it manages scheduled payments
|
||
if ( 0 == $subscription->get_total() || $subscription->is_manual() || '' == $subscription->get_payment_method() || ! $subscription->payment_method_supports( 'gateway_scheduled_payments' ) ) {
|
||
$subscription->update_status( 'on-hold', _x( 'Subscription renewal payment due:', 'used in order note as reason for why subscription status changed', 'woocommerce-subscriptions' ) );
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Check if the subscription needs to use the failed payment process to repair its status after it incorrectly expired due to a date migration
|
||
* bug in upgrade process for 2.0.0 of Subscriptions (i.e. not 2.0.1 or newer). See WCS_Repair_2_0_2::maybe_repair_status() for more details.
|
||
*
|
||
* @param int $subscription_id The ID of a 'shop_subscription' post
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v2.0.2
|
||
*/
|
||
public static function maybe_process_failed_renewal_for_repair( $subscription_id ) {
|
||
$subscription = wcs_get_subscription( $subscription_id );
|
||
if ( 'true' === $subscription->get_meta( '_wcs_repaired_2_0_2_needs_failed_payment', true ) ) {
|
||
// Always put the subscription on hold in case something goes wrong while trying to process renewal
|
||
$subscription->update_status( 'on-hold', _x( 'Subscription renewal payment due:', 'used in order note as reason for why subscription status changed', 'woocommerce-subscriptions' ) );
|
||
|
||
// Create a renewal order to record the failed payment which can then be used by the customer to reactivate the subscription
|
||
wcs_create_renewal_order( $subscription );
|
||
|
||
// Mark the payment as failed so the customer can login to fix up the failed payment
|
||
$subscription->payment_failed();
|
||
|
||
// Only force the failed payment once
|
||
update_post_meta( $subscription_id, '_wcs_repaired_2_0_2_needs_failed_payment', 'false' );
|
||
|
||
// We've already processed the renewal
|
||
remove_action( 'woocommerce_scheduled_subscription_payment', __CLASS__ . '::prepare_renewal' );
|
||
remove_action( 'woocommerce_scheduled_subscription_payment', 'WC_Subscriptions_Payment_Gateways::gateway_scheduled_subscription_payment', 10 );
|
||
}
|
||
}
|
||
|
||
/* Deprecated Functions */
|
||
|
||
/**
|
||
* When a scheduled subscription payment hook is fired, automatically process the subscription payment
|
||
* if the amount is for $0 (and therefore, there is no payment to be processed by a gateway, and likely
|
||
* no gateway used on the initial order).
|
||
*
|
||
* If a subscription has a $0 recurring total and is not already active (after being activated by something else
|
||
* handling the 'scheduled_subscription_payment' with the default priority of 10), then this function will call
|
||
* @see self::process_subscription_payment() to reactive the subscription, generate a renewal order etc.
|
||
*
|
||
* @param int $user_id The id of the user who the subscription belongs to
|
||
* @param string $subscription_key A subscription key of the form created by @see self::get_subscription_key()
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.3.2
|
||
* @deprecated 1.0.0 - Migrated from WooCommerce Subscriptions v2.0
|
||
*/
|
||
public static function maybe_process_subscription_payment( $user_id, $subscription_key ) {
|
||
_deprecated_function( __METHOD__, '2.0', __CLASS__ . '::prepare_renewal( $subscription_id )' );
|
||
self::prepare_renewal( wcs_get_subscription_id_from_key( $subscription_key ) );
|
||
}
|
||
|
||
/**
|
||
* Return a link for subscribers to change the status of their subscription, as specified with $status parameter
|
||
*
|
||
* @param string $subscription_key A subscription key of the form created by @see self::get_subscription_key()
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.0
|
||
*/
|
||
public static function current_user_can_suspend_subscription( $subscription_key ) {
|
||
_deprecated_function( __METHOD__, '2.0', 'wcs_can_user_put_subscription_on_hold( $subscription, $user )' );
|
||
return wcs_can_user_put_subscription_on_hold( wcs_get_subscription_from_key( $subscription_key ) );
|
||
}
|
||
|
||
/**
|
||
* Return a multi-dimensional associative array of subscriptions with a certain value, grouped by user ID.
|
||
*
|
||
* A slow PHP based search routine which can't use the speed of MySQL because subscription details. If you
|
||
* know the key for the value you are search by, use @see self::get_subscriptions() for better performance.
|
||
*
|
||
* @param string $search_query The query to search the database for.
|
||
* @return array Subscription details
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.1
|
||
* @deprecated 1.0.0 - Migrated from WooCommerce Subscriptions v2.0
|
||
*/
|
||
public static function search_subscriptions( $search_query ) {
|
||
_deprecated_function( __METHOD__, '2.0', 'wcs_get_subscriptions()' );
|
||
global $wpdb;
|
||
|
||
$subscriptions_to_search = self::get_all_users_subscriptions();
|
||
|
||
$subscriptions_found = array();
|
||
|
||
$search_terms = explode( ' ', $search_query );
|
||
|
||
foreach ( $subscriptions_to_search as $user_id => $subscriptions ) {
|
||
|
||
$user = get_user_by( 'id', $user_id );
|
||
|
||
if ( false === $user || ! is_object( $user ) ) {
|
||
continue;
|
||
}
|
||
|
||
$user = $user->data;
|
||
|
||
foreach ( $search_terms as $search_term ) {
|
||
|
||
// If the search query is found in the user's details, add all of their subscriptions, otherwise add only subscriptions with a matching item
|
||
if ( false !== stripos( $user->user_nicename, $search_term ) || false !== stripos( $user->display_name, $search_term ) ) {
|
||
$subscriptions_found[ $user_id ] = $subscriptions;
|
||
} elseif ( false !== stripos( $user->user_login, $search_term ) || false !== stripos( $user->user_email, $search_term ) ) {
|
||
$subscriptions_found[ $user_id ] = $subscriptions;
|
||
} else {
|
||
foreach ( $subscriptions as $subscription_key => $subscription ) {
|
||
|
||
$product_title = get_the_title( $subscription['product_id'] );
|
||
|
||
if ( in_array( $search_term, $subscription, true ) || false != preg_match( "/$search_term/i", $product_title ) ) {
|
||
$subscriptions_found[ $user_id ][ $subscription_key ] = $subscription;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
return apply_filters( 'woocommerce_search_subscriptions', $subscriptions_found, $search_query );
|
||
}
|
||
|
||
/**
|
||
* Marks a single subscription as active on a users account.
|
||
*
|
||
* @param int $user_id The id of the user whose subscription is to be activated.
|
||
* @param string $subscription_key A subscription key of the form created by @see self::get_subscription_key()
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.0
|
||
*/
|
||
public static function activate_subscription( $user_id, $subscription_key ) {
|
||
_deprecated_function( __METHOD__, '2.0' );
|
||
|
||
try {
|
||
$subscription = wcs_get_subscription_from_key( $subscription_key );
|
||
|
||
if ( $subscription->has_status( 'active' ) ) {
|
||
return false;
|
||
}
|
||
} catch ( Exception $e ) {
|
||
return false;
|
||
}
|
||
|
||
if ( ! $subscription->has_status( 'pending' ) && ! $subscription->can_be_updated_to( 'active' ) ) {
|
||
|
||
do_action( 'unable_to_activate_subscription', $user_id, $subscription_key );
|
||
|
||
$activated_subscription = false;
|
||
|
||
} else {
|
||
|
||
$subscription->update_status( 'active' );
|
||
|
||
do_action( 'activated_subscription', $user_id, $subscription_key );
|
||
|
||
$activated_subscription = true;
|
||
|
||
}
|
||
|
||
return $activated_subscription;
|
||
}
|
||
|
||
/**
|
||
* Changes a single subscription from on-hold to active on a users account.
|
||
*
|
||
* @param int $user_id The id of the user whose subscription is to be activated.
|
||
* @param string $subscription_key A subscription key of the form created by @see self::get_subscription_key()
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.0
|
||
*/
|
||
public static function reactivate_subscription( $user_id, $subscription_key ) {
|
||
_deprecated_function( __METHOD__, '2.0' );
|
||
|
||
if ( false !== self::activate_subscription( $user_id, $subscription_key ) ) {
|
||
do_action( 'reactivated_subscription', $user_id, $subscription_key );
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Suspends a single subscription on a users account by placing it in the "on-hold" status.
|
||
*
|
||
* @param int $user_id The id of the user whose subscription should be put on-hold.
|
||
* @param string $subscription_key A subscription key of the form created by @see self::get_subscription_key()
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.0
|
||
*/
|
||
public static function put_subscription_on_hold( $user_id, $subscription_key ) {
|
||
_deprecated_function( __METHOD__, '2.0', 'WC_Subscription::update_status( "on-hold" )' );
|
||
|
||
try {
|
||
$subscription = wcs_get_subscription_from_key( $subscription_key );
|
||
|
||
if ( $subscription->has_status( 'on-hold' ) ) {
|
||
return false;
|
||
}
|
||
} catch ( Exception $e ) {
|
||
return false;
|
||
}
|
||
|
||
if ( ! $subscription->can_be_updated_to( 'on-hold' ) ) {
|
||
|
||
do_action( 'unable_to_put_subscription_on-hold', $user_id, $subscription_key );
|
||
do_action( 'unable_to_suspend_subscription', $user_id, $subscription_key );
|
||
|
||
} else {
|
||
|
||
$subscription->update_status( 'on-hold' );
|
||
|
||
do_action( 'subscription_put_on-hold', $user_id, $subscription_key );
|
||
// Backward, backward compatibility
|
||
do_action( 'suspended_subscription', $user_id, $subscription_key );
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Cancels a single subscription on a users account.
|
||
*
|
||
* @param int $user_id The id of the user whose subscription should be cancelled.
|
||
* @param string $subscription_key A subscription key of the form created by @see self::get_subscription_key()
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.0
|
||
*/
|
||
public static function cancel_subscription( $user_id, $subscription_key ) {
|
||
_deprecated_function( __METHOD__, '2.0', 'WC_Subscriptions::cancel_order()' );
|
||
|
||
try {
|
||
$subscription = wcs_get_subscription_from_key( $subscription_key );
|
||
|
||
if ( $subscription->has_status( array( 'pending-cancel', 'cancelled' ) ) ) {
|
||
return false;
|
||
}
|
||
} catch ( Exception $e ) {
|
||
return false;
|
||
}
|
||
|
||
if ( ! $subscription->can_be_updated_to( 'cancelled' ) ) {
|
||
|
||
do_action( 'unable_to_cancel_subscription', $user_id, $subscription_key );
|
||
|
||
} else {
|
||
|
||
$subscription->update_status( 'cancelled' );
|
||
|
||
do_action( 'cancelled_subscription', $user_id, $subscription_key );
|
||
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Sets a single subscription on a users account to be 'on-hold' and keeps a record of the failed sign up on an order.
|
||
*
|
||
* @param int $user_id The id of the user whose subscription should be cancelled.
|
||
* @param string $subscription_key A subscription key of the form created by @see self::get_subscription_key()
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.0
|
||
*/
|
||
public static function failed_subscription_signup( $user_id, $subscription_key ) {
|
||
_deprecated_function( __METHOD__, '2.0' );
|
||
|
||
try {
|
||
$subscription = wcs_get_subscription_from_key( $subscription_key );
|
||
|
||
if ( $subscription->has_status( 'on-hold' ) ) {
|
||
return false;
|
||
}
|
||
} catch ( Exception $e ) {
|
||
return false;
|
||
}
|
||
|
||
// Place the subscription on-hold
|
||
$subscription->update_status( 'on-hold' );
|
||
|
||
// Log failure on order
|
||
// translators: placeholder is subscription ID
|
||
$subscription->get_parent()->add_order_note( sprintf( __( 'Failed sign-up for subscription %s.', 'woocommerce-subscriptions' ), $subscription->get_id() ) );
|
||
|
||
do_action( 'subscription_sign_up_failed', $user_id, $subscription_key );
|
||
}
|
||
|
||
/**
|
||
* Trashes a single subscription on a users account.
|
||
*
|
||
* @param int $user_id The ID of the user who the subscription belongs to
|
||
* @param string $subscription_key A subscription key of the form created by @see self::get_subscription_key()
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.0
|
||
*/
|
||
public static function trash_subscription( $user_id, $subscription_key ) {
|
||
_deprecated_function( __METHOD__, '2.0', 'wp_trash_post()' );
|
||
|
||
try {
|
||
$subscription = wcs_get_subscription_from_key( $subscription_key );
|
||
|
||
if ( $subscription->has_status( 'trash' ) ) {
|
||
return false;
|
||
}
|
||
} catch ( Exception $e ) {
|
||
return false;
|
||
}
|
||
|
||
if ( ! $subscription->can_be_updated_to( 'cancelled' ) ) {
|
||
|
||
do_action( 'unable_to_trash_subscription', $user_id, $subscription_key );
|
||
|
||
} else {
|
||
|
||
// Run all cancellation related functions on the subscription
|
||
if ( ! $subscription->has_status( array( 'cancelled', 'expired', 'trash' ) ) ) {
|
||
$subscription->update_status( 'cancelled' );
|
||
}
|
||
|
||
wp_trash_post( $subscription->get_id() );
|
||
|
||
do_action( 'subscription_trashed', $user_id, $subscription_key );
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Permanently deletes a single subscription on a users account.
|
||
*
|
||
* @param int $user_id The ID of the user who the subscription belongs to
|
||
* @param string $subscription_key A subscription key of the form created by @see self::get_subscription_key()
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.2
|
||
*/
|
||
public static function delete_subscription( $user_id, $subscription_key ) {
|
||
_deprecated_function( __METHOD__, '2.0', 'wp_delete_post()' );
|
||
|
||
try {
|
||
$subscription = wcs_get_subscription_from_key( $subscription_key );
|
||
} catch ( Exception $e ) {
|
||
return false;
|
||
}
|
||
|
||
if ( ! $subscription->can_be_updated_to( 'deleted' ) && ! $subscription->can_be_updated_to( 'cancelled' ) ) {
|
||
|
||
do_action( 'unable_to_delete_subscription', $user_id, $subscription_key );
|
||
|
||
} else {
|
||
|
||
// Run all cancellation related functions on the subscription
|
||
if ( ! $subscription->has_status( array( 'cancelled', 'expired', 'trash' ) ) ) {
|
||
$subscription->update_status( 'cancelled' );
|
||
}
|
||
|
||
wp_delete_post( $subscription->get_id(), true );
|
||
|
||
do_action( 'subscription_deleted', $user_id, $subscription_key, $subscription, null );
|
||
}
|
||
}
|
||
|
||
|
||
/**
|
||
* Processes an ajax request to change a subscription's next payment date.
|
||
*
|
||
* Deprecated because editing a subscription's next payment date is now done from the Edit Subscription screen.
|
||
*
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.2
|
||
* @deprecated 1.0.0 - Migrated from WooCommerce Subscriptions v2.0
|
||
*/
|
||
public static function ajax_update_next_payment_date() {
|
||
_deprecated_function( __METHOD__, '2.0', 'wp_delete_post()' );
|
||
|
||
$response = array( 'status' => 'error' );
|
||
|
||
if ( ! wp_verify_nonce( wc_clean( wp_unslash( $_POST['wcs_nonce'] ) ), 'woocommerce-subscriptions' ) ) {
|
||
|
||
$response['message'] = '<div class="error">' . __( 'Invalid security token, please reload the page and try again.', 'woocommerce-subscriptions' ) . '</div>';
|
||
|
||
} elseif ( ! current_user_can( 'manage_woocommerce' ) ) {
|
||
|
||
$response['message'] = '<div class="error">' . __( 'Only store managers can edit payment dates.', 'woocommerce-subscriptions' ) . '</div>';
|
||
|
||
} elseif ( empty( $_POST['wcs_day'] ) || empty( $_POST['wcs_month'] ) || empty( $_POST['wcs_year'] ) ) {
|
||
|
||
$response['message'] = '<div class="error">' . __( 'Please enter all date fields.', 'woocommerce-subscriptions' ) . '</div>';
|
||
|
||
} else {
|
||
|
||
$new_payment_date = sprintf( '%s-%s-%s %s', (int) $_POST['wcs_year'], zeroise( (int) $_POST['wcs_month'], 2 ), zeroise( (int) $_POST['wcs_day'], 2 ), gmdate( 'H:i:s', current_time( 'timestamp' ) ) );
|
||
$new_payment_timestamp = self::update_next_payment_date( $new_payment_date, wc_clean( wp_unslash( $_POST['wcs_subscription_key'] ) ), self::get_user_id_from_subscription_key( wc_clean( wp_unslash( $_POST['wcs_subscription_key'] ) ) ), 'user' );
|
||
|
||
if ( is_wp_error( $new_payment_timestamp ) ) {
|
||
|
||
$response['message'] = sprintf( '<div class="error">%s</div>', $new_payment_timestamp->get_error_message() );
|
||
|
||
} else {
|
||
|
||
$new_payment_timestamp_user_time = $new_payment_timestamp + ( get_option( 'gmt_offset' ) * 3600 ); // The timestamp is returned in server time
|
||
|
||
$time_diff = $new_payment_timestamp - gmdate( 'U' );
|
||
|
||
if ( $time_diff > 0 && $time_diff < 7 * 24 * 60 * 60 ) {
|
||
// translators: placeholder is human time diff (e.g. "3 weeks")
|
||
$date_to_display = sprintf( __( 'In %s', 'woocommerce-subscriptions' ), human_time_diff( gmdate( 'U' ), $new_payment_timestamp ) );
|
||
} else {
|
||
$date_to_display = date_i18n( wc_date_format(), $new_payment_timestamp_user_time );
|
||
}
|
||
|
||
$response['status'] = 'success';
|
||
$response['message'] = '<div class="updated">' . __( 'Date Changed', 'woocommerce-subscriptions' ) . '</div>';
|
||
$response['dateToDisplay'] = $date_to_display;
|
||
$response['timestamp'] = $new_payment_timestamp_user_time;
|
||
|
||
}
|
||
}
|
||
|
||
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||
echo wcs_json_encode( $response );
|
||
|
||
exit();
|
||
}
|
||
|
||
/**
|
||
* WP-Cron occasionally gets itself into an infinite loop on scheduled events, this function is
|
||
* designed to create a non-cron related safeguard against payments getting caught up in such a loop.
|
||
*
|
||
* When the scheduled subscription payment hook is fired by WP-Cron, this function is attached before
|
||
* any other to make sure the hook hasn't already fired for this period.
|
||
*
|
||
* A transient is used to keep a record of any payment for each period. The transient expiration is
|
||
* set to one billing period in the future, minus 1 hour, if there is a future payment due, otherwise,
|
||
* it is set to 23 hours in the future. This later option provides a safeguard in case a subscription's
|
||
* data is corrupted and the @see self::calculate_next_payment_date() is returning an
|
||
* invalid value. As no subscription can charge a payment more than once per day, the 23 hours is a safe
|
||
* throttle period for billing that still removes the possibility of a catastrophic failure (payments
|
||
* firing every few seconds until a credit card is maxed out).
|
||
*
|
||
* The transient keys use both the user ID and subscription key to ensure it is unique per subscription
|
||
* (even on multisite)
|
||
*
|
||
* @param int $user_id The id of the user who purchased the subscription
|
||
* @param string $subscription_key A subscription key of the form created by @see self::get_subscription_key()
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.1.2
|
||
* @deprecated 1.0.0 - Migrated from WooCommerce Subscriptions v2.0
|
||
*/
|
||
public static function safeguard_scheduled_payments( $user_id, $subscription_key ) {
|
||
_deprecated_function( __METHOD__, '2.0' );
|
||
}
|
||
|
||
/**
|
||
* When a subscription payment hook is fired, reschedule the hook to run again on the
|
||
* time/date of the next payment (if any).
|
||
*
|
||
* WP-Cron's built in wp_schedule_event() function can not be used because the recurrence
|
||
* must be a timestamp, which creates inaccurate schedules for month and year billing periods.
|
||
*
|
||
* @param int $user_id The id of the user who the subscription belongs to
|
||
* @param string $subscription_key A subscription key of the form created by @see self::get_subscription_key()
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.1.5
|
||
* @deprecated 1.0.0 - Migrated from WooCommerce Subscriptions v2.0
|
||
*/
|
||
public static function maybe_reschedule_subscription_payment( $user_id, $subscription_key ) {
|
||
_deprecated_function( __METHOD__, '2.0' );
|
||
|
||
$subscription = wcs_get_subscription_from_key( $subscription_key );
|
||
|
||
// Don't reschedule for cancelled, suspended or expired subscriptions
|
||
if ( ! $subscription->has_status( [ 'expired', 'cancelled', 'on-hold' ] ) ) {
|
||
|
||
// Reschedule the 'scheduled_subscription_payment' hook
|
||
if ( $subscription->can_date_be_updated( 'next_payment' ) ) {
|
||
$subscription->update_dates( array( 'next_payment' => $subscription->calculate_date( 'next_payment' ) ) );
|
||
do_action( 'rescheduled_subscription_payment', $user_id, $subscription_key );
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Fires when the trial period for a subscription has completed.
|
||
*
|
||
* @param int $subscription_id The ID of a 'shop_subscription' post
|
||
* @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.0
|
||
* @deprecated 1.0.0 - Migrated from WooCommerce Subscriptions v2.0
|
||
*/
|
||
public static function subscription_trial_end( $subscription_id, $deprecated = null ) {
|
||
_deprecated_function( __METHOD__, '2.0' );
|
||
}
|
||
}
|