Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <?php
- /*
- Change cancellation to set expiration date for next payment instead of cancelling immediately.
- Assumes orders are generated for each payment (i.e. your webhooks/etc are setup correctly).
- Since 2015-09-21 and PMPro v1.8.5.6 contains code to look up next payment dates via Stripe and PayPal Express APIs.
- */
- //before cancelling, save the next_payment_timestamp to a global for later use. (Requires PMPro 1.8.5.6 or higher.)
- function my_pmpro_before_change_membership_level($level_id, $user_id) {
- //are we on the cancel page?
- global $pmpro_pages, $wpdb, $pmpro_stripe_event, $pmpro_next_payment_timestamp;
- if($level_id == 0 && (is_page($pmpro_pages['cancel']) || (is_admin() && (empty($_REQUEST['from']) || $_REQUEST['from'] != 'profile')))) {
- //get last order
- $order = new MemberOrder();
- $order->getLastMemberOrder($user_id, "success");
- //get level to check if it already has an end date
- if(!empty($order) && !empty($order->membership_id))
- $level = $wpdb->get_row("SELECT * FROM $wpdb->pmpro_memberships_users WHERE membership_id = '" . $order->membership_id . "' AND user_id = '" . $user_id . "' ORDER BY id DESC LIMIT 1");
- //figure out the next payment timestamp
- if(empty($level) || (!empty($level->enddate) && $level->enddate != '0000-00-00 00:00:00')) {
- //level already has an end date. set to false so we really cancel.
- $pmpro_next_payment_timestamp = false;
- } elseif(!empty($order) && $order->gateway == "payflowpro") {
- //if PayPal, try to use the API
- if(!empty($_POST['next_payment_date']) && $_POST['next_payment_date'] != 'N/A') {
- //cancel initiated from IPN
- $pmpro_next_payment_timestamp = strtotime($_POST['next_payment_date'], current_time('timestamp'));
- } else {
- //cancel initiated from PMPro
- $pmpro_next_payment_timestamp = PMProGateway_payflowpro::pmpro_next_payment("", $user_id, "success");
- }
- } else {
- //use built in PMPro function to guess next payment date
- $pmpro_next_payment_timestamp = pmpro_next_payment($user_id);
- }
- }
- }
- add_action('pmpro_before_change_membership_level', 'my_pmpro_before_change_membership_level', 10, 2);
- //give users their level back with an expiration
- function my_pmpro_after_change_membership_level($level_id, $user_id) {
- global $pmpro_pages, $wpdb, $pmpro_next_payment_timestamp;
- if($pmpro_next_payment_timestamp !== false && //this is false if the level already has an enddate
- $level_id == 0 && //make sure we're cancelling
- (is_page($pmpro_pages['cancel']) || (is_admin() && (empty($_REQUEST['from']) || $_REQUEST['from'] != 'profile')))) { //on the cancel page or in admin/adminajax/webhook and not the edit user page
- /*
- okay, let's give the user his old level back with an expiration based on his subscription date
- */
- //get last order
- $order = new MemberOrder();
- $order->getLastMemberOrder($user_id, "cancelled");
- //can't do this if we can't find the order
- if(empty($order->id))
- return false;
- //get the last level they had
- $level = $wpdb->get_row("SELECT * FROM $wpdb->pmpro_memberships_users WHERE membership_id = '" . $order->membership_id . "' AND user_id = '" . $user_id . "' ORDER BY id DESC LIMIT 1");
- //can't do if we can't find an old level
- if(empty($level))
- return false;
- //last payment date
- $lastdate = date("Y-m-d", $order->timestamp);
- /*
- next payment date
- */
- //if stripe or PayPal, try to use the API
- if(!empty($pmpro_next_payment_timestamp)) {
- $nextdate = $pmpro_next_payment_timestamp;
- } else {
- $nextdate = $wpdb->get_var("SELECT UNIX_TIMESTAMP('" . $lastdate . "' + INTERVAL " . $level->cycle_number . " " . $level->cycle_period . ")");
- }
- //if the date in the future?
- if($nextdate - time() > 0) {
- //give them their level back with the expiration date set
- $old_level = $wpdb->get_row("SELECT * FROM $wpdb->pmpro_memberships_users WHERE membership_id = '" . $order->membership_id . "' AND user_id = '" . $user_id . "' ORDER BY id DESC LIMIT 1", ARRAY_A);
- $old_level['enddate'] = date("Y-m-d H:i:s", $nextdate);
- //disable this hook so we don't loop
- remove_action("pmpro_after_change_membership_level", "my_pmpro_after_change_membership_level", 10, 2);
- remove_filter('pmpro_cancel_previous_subscriptions', 'my_pmpro_before_change_membership_level', 10, 2);
- //disable the action to set the default level on cancels
- remove_action('pmpro_after_change_membership_level', 'pmpro_after_change_membership_level_default_level', 10, 2);
- //change level
- pmpro_changeMembershipLevel($old_level, $user_id);
- //add the action back just in case
- add_action("pmpro_after_change_membership_level", "my_pmpro_after_change_membership_level", 10, 2);
- add_filter('pmpro_cancel_previous_subscriptions', 'my_pmpro_before_change_membership_level', 10, 2);
- //add the action back to set the default level on cancels
- remove_action('pmpro_after_change_membership_level', 'pmpro_after_change_membership_level_default_level', 10, 2);
- //change message shown on cancel page
- add_filter("gettext", "my_gettext_cancel_text", 10, 3);
- }
- }
- //clear up this global in case we're changing many levels at once (e.g. expiration script running)
- unset($pmpro_next_payment_timestamp);
- }
- add_action("pmpro_after_change_membership_level", "my_pmpro_after_change_membership_level", 10, 2);
- //this replaces the cancellation text so people know they'll still have access for a certain amount of time
- function my_gettext_cancel_text($translated_text, $text, $domain) {
- if(($domain == "pmpro" || $domain == "paid-memberships-pro") && $text == "Your membership has been cancelled.") {
- global $current_user;
- $translated_text = "Your recurring subscription has been cancelled. Your active membership will expire on " . date(get_option("date_format"), pmpro_next_payment($current_user->ID, "cancelled")) . ".";
- }
- return $translated_text;
- }
- //want to update the cancellation email as well
- function my_pmpro_email_body($body, $email) {
- if($email->template == "cancel") {
- global $wpdb;
- $user_id = $wpdb->get_var("SELECT ID FROM $wpdb->users WHERE user_email = '" . esc_sql($email->email) . "' LIMIT 1");
- if(!empty($user_id)) {
- $expiration_date = pmpro_next_payment($user_id);
- //if the date in the future?
- if($expiration_date - time() > 0) {
- $body .= "<p>Your access will expire on " . date(get_option("date_format"), $expiration_date) . ".</p>";
- }
- }
- }
- return $body;
- }
- add_filter("pmpro_email_body", "my_pmpro_email_body", 10, 2);
Add Comment
Please, Sign In to add comment