Created
February 27, 2025 19:52
-
-
Save kimcoleman/85cfe2cccb02a2bda0932b7e3c1169ad to your computer and use it in GitHub Desktop.
Let members switch payment methods but preserve their current subscription price and renewal date.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Get the next payment date for a user's level inclusive of subscriptions and expiration dates. | |
* | |
* If the current user has a subscription for a passed level ID, return the next payment date for that subscription. | |
* Otherwise, if the user has an expiration date set for the level, return that. | |
* Otherwise, return null. | |
* | |
* @param int $level_id The level ID to check for. | |
* @return int|null The next payment date/expiration date as a timestamp or null. | |
*/ | |
function my_pmpro_renew_or_change_payment_method_get_next_payment_date( $level_id ) { | |
global $current_user; | |
// Bail if not logged in. | |
if ( empty( $current_user->ID ) ) { | |
return null; | |
} | |
// See if the user has a subscription or level for the passed level ID. | |
$current_subscriptions = PMPro_Subscription::get_subscriptions_for_user( $current_user->ID, $level_id ); | |
$current_level = pmpro_getSpecificMembershipLevelForUser( $current_user->ID, $level_id ); | |
if ( ! empty( $current_subscriptions ) ) { | |
// Return the next payment date for the subscription. | |
$next_payment_date = $current_subscriptions[0]->get_next_payment_date(); | |
} elseif ( ! empty( $current_level ) ) { | |
// Return the expiration date for the level. | |
$next_payment_date = $current_level->enddate; | |
} | |
// If we do not have a next payment date, return null. | |
if ( empty( $next_payment_date ) ) { | |
return null; | |
} | |
// If we have a subscription start date in the past, return null. | |
if ( $next_payment_date < current_time( 'timestamp' ) ) { | |
return null; | |
} | |
// Ok, we can adjust the start date. | |
return $next_payment_date; | |
} | |
/** | |
* If checking out for same level with active membership, set initial payment to $0 and start subscription on next payment date OR expiration date. | |
*/ | |
function my_pmpro_renew_or_change_payment_method_checkout_level( $level ) { | |
global $current_user; | |
// Bail if PMPro is not active. | |
if ( ! class_exists( 'PMPro_Subscription' ) ) { | |
return $level; | |
} | |
// Return early if using a discount code | |
if ( ! empty( $level->discount_code ) || ! empty( $_REQUEST['discount_code'] ) ) { | |
return $level; | |
} | |
// Assume we do not need to adjust the checkout level. | |
$subscription_start_date = my_pmpro_renew_or_change_payment_method_get_next_payment_date( $level->id ); | |
// If we do not have a subscription start date, return. | |
if ( empty( $subscription_start_date ) ) { | |
return $level; | |
} | |
// Ok, we can adjust the level. | |
// Charge them nothing today. | |
$level->initial_payment = 0; | |
// Set the billing start date on the checkout level. | |
$level->profile_start_date = date( 'Y-m-d H:i:s', $subscription_start_date ); | |
// Get their active or last active subscription. | |
$last_subscription = PMPro_Subscription::get_subscription( | |
array( | |
'user_id' => $current_user->ID, | |
'membership_level_id' => $level->id | |
) | |
); | |
// If they have a last subscription, set the billing amount. | |
if ( ! empty( $last_subscription ) ) { | |
$level->billing_amount = $last_subscription->get_billing_amount(); | |
} | |
return $level; | |
} | |
add_filter( 'pmpro_checkout_level', 'my_pmpro_renew_or_change_payment_method_checkout_level', 10 ); | |
/** | |
* Change the Level Cost Text on the checkout page | |
*/ | |
function my_pmpro_renew_or_change_payment_method_level_cost_text( $cost, $level ) { | |
global $pmpro_pages; | |
// Bail if PMPro is not active. | |
if ( ! function_exists( 'pmpro_isLevelRecurring' ) ) { | |
return $cost; | |
} | |
// Bail if this is not the checkout page. | |
if ( empty( $pmpro_pages ) || empty( $pmpro_pages['checkout'] ) || ! is_page( $pmpro_pages['checkout'] ) ) { | |
return $cost; | |
} | |
// Return early if using a discount code | |
if ( ! empty( $level->discount_code ) || ! empty( $_REQUEST['discount_code'] ) ) { | |
return $cost; | |
} | |
// Bail if the level is not recurring. | |
if ( ! pmpro_isLevelRecurring( $level ) ) { | |
return $cost; | |
} | |
// Assume we do not need to adjust the cost text. | |
$subscription_start_date = my_pmpro_renew_or_change_payment_method_get_next_payment_date( $level->id ); | |
// If we do not have a subscription start date, bail. | |
if ( empty( $subscription_start_date ) ) { | |
return $cost; | |
} | |
// Ok, we can adjust the cost text. | |
$cost .= 'Your first subscription payment will be processed on ' . date_i18n( get_option( 'date_format' ), $subscription_start_date ) . '.'; | |
return $cost; | |
} | |
add_filter( 'pmpro_level_cost_text', 'my_pmpro_renew_or_change_payment_method_level_cost_text', 10, 2 ); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment