Last active
May 24, 2019 06:00
-
-
Save wpmudev-sls/351aaa686d6ce8f8b3fd35f9ac8418e1 to your computer and use it in GitHub Desktop.
[Membership] - Override Cron Status Check
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 | |
/** | |
* Plugin Name: [Membership] - Override Cron Status Check | |
* Plugin URI: https://premium.wpmudev.org/ | |
* Description: Override Cron Status Check | |
* Author: Panos Lyrakis @ WPMUDEV | |
* Author URI: https://premium.wpmudev.org/ | |
* License: GPLv2 or later | |
*/ | |
// NOTE : | |
// At this point we only care about setting the db status to expired where required. | |
// We skip the rest cases so they are handled by the `check_membership_status()` method | |
if ( ! defined( 'ABSPATH' ) ) { | |
exit; | |
} | |
if ( ! class_exists( 'WPMUDEV_MS_Cron_Status_Check' ) ) { | |
class WPMUDEV_MS_Cron_Status_Check { | |
private static $_instance = null; | |
private $transaction_type = 'ms_transaction_log'; | |
public static function get_instance() { | |
if( is_null( self::$_instance ) ){ | |
self::$_instance = new WPMUDEV_MS_Cron_Status_Check(); | |
} | |
return self::$_instance; | |
} | |
private function __construct() { | |
add_filter( 'ms_model_relationship_skip_membership_status_check', array( $this, 'subscription_status_check' ), 20, 2 ); | |
} | |
/* | |
* This method checks purely the expiration date based on last transaction log. | |
* It does not check the invoice dates | |
* It creates an invoice only if subscription gets expired and there is no current invoice | |
*/ | |
public function subscription_status_check( $skip, $subscription ) { | |
if ( $subscription->is_trial_eligible() | |
&& strtotime( $subscription->trial_expire_date ) >= strtotime( MS_Helper_Period::current_date() ) | |
) { | |
// Still on trial. Lets continue with normal Cron check | |
return $skip; | |
} | |
/** | |
* TODO: | |
* We can set the STATUS_TRIAL_EXPIRED status temporarily if is_trial_eligible and trial_expire_date has passed. | |
*/ | |
if ( empty( $subscription->expire_date ) ) { | |
// If there is no expiration date, subscription should be set to active. | |
// This can be handled by the Cron check | |
return $skip; | |
} | |
$subscription_current_status = get_post_meta( $subscription->id, 'status', true ); | |
$subscription_next_status = ''; | |
$subscription_expiration_date = $subscription->expire_date;; | |
if ( 'admin' != $subscription->gateway_id && 'free' != $subscription->gateway_id ) { | |
$payment = $this->get_subscription_last_payment( $subscription ); | |
if ( ! $payment || empty( $payment ) ){ | |
return $skip; | |
} | |
$last_payment_date = $payment->date; | |
$subscription_expiration_date = $this->get_subscription_expiration_date( $subscription, $last_payment_date ); | |
} | |
if ( strtotime( $subscription_expiration_date ) >= strtotime( MS_Helper_Period::current_date() ) ) { | |
//Should be set to active | |
$subscription_next_status = MS_Model_Relationship::STATUS_ACTIVE; | |
} | |
else { | |
// if current status is MS_Model_Relationship::STATUS_PENDING, it should ermain like that else | |
//should be set to expired | |
if ( MS_Model_Relationship::STATUS_PENDING == $subscription->status ) { | |
$subscription_next_status = MS_Model_Relationship::STATUS_PENDING; | |
} | |
else { | |
$subscription_next_status = MS_Model_Relationship::STATUS_EXPIRED; | |
$this->set_status( $subscription, $subscription_next_status ); | |
return true; | |
} | |
} | |
//$this->set_status( $subscription, $subscription_next_status ); | |
//switch( $subscription->status ) { | |
//} | |
/** | |
* Filter documented in class-ms-model-relationship.php | |
*/ | |
/* | |
do_action( | |
'ms_relationship_status_check_communication', | |
$subscription_next_status, | |
$days, | |
$membership, | |
$subscription, | |
false | |
); | |
*/ | |
//return true; | |
// It is better/safer to just to skip as at this point we have set all the expired ones. | |
return $skip; | |
} | |
private function maybe_move_membership( $subscription, $membership ) { | |
// Do not continue if on_end_membership_id is empty. | |
if ( empty( $membership->on_end_membership_id ) ) { | |
return; | |
} | |
// Deactivate the current membership. | |
$subscription->deactivate_membership(); | |
// Move membership to configured membership. | |
$new_membership = MS_Factory::load( | |
'MS_Model_Membership', | |
$membership->on_end_membership_id | |
); | |
if ( $new_membership->is_valid() ) { | |
$member = MS_Factory::load( 'MS_Model_Member', $subscription->user_id ); | |
$new_subscription = $member->add_membership( | |
$membership->on_end_membership_id, | |
$subscription->gateway_id | |
); | |
MS_Model_Event::save_event( | |
MS_Model_Event::TYPE_MS_MOVED, | |
$new_subscription | |
); | |
/* | |
* If the new membership is paid we want that the user | |
* confirms the payment in his account. So we set it | |
* to "Pending" first. If its free we set it as active | |
*/ | |
if ( ! $new_membership->is_free() ) { | |
$new_subscription->status = MS_Model_Relationship::STATUS_PENDING; | |
} else { | |
$new_subscription->status = MS_Model_Relationship::STATUS_ACTIVE; | |
} | |
// Save new membership. | |
$new_subscription->save(); | |
} | |
} | |
private function set_status( $subscription, $status ) { | |
update_post_meta( $subscription->id, 'status', $status ); | |
if ( MS_Model_Relationship::STATUS_EXPIRED == $status ) { | |
// Since this subscription is expired, lets check if we need to move membership: | |
$membership = $subscription->get_membership(); | |
if ( ! empty( $membership->on_end_membership_id ) ) { | |
$this->maybe_move_membership( $subscription, $membership ); | |
} | |
} | |
} | |
public function get_subscription_last_payment( $subscription ) { | |
$transaction = $this->get_subscription_last_transaction( $subscription->id ); | |
if ( ! $transaction || empty( $transaction ) ) { | |
return false; | |
} | |
return $this->payment_from_transaction( $transaction ); | |
} | |
public function get_subscription_last_transaction( $subscription_id ) { | |
if ( is_object( $subscription_id ) ) { | |
if ( ! isset( $subscription_id->id ) ) { | |
return false; | |
} | |
$subscription_id = $subscription_id->id; | |
} | |
$transaction = array(); | |
$args = array( | |
'numberposts' => 1, | |
'offset' => 0, | |
'post_status' => 'any', //'private', // transaction logs have private status in posts table | |
'post_type' => 'ms_transaction_log', | |
'meta_query' => array( | |
array( | |
'key' => 'subscription_id', | |
'value' => $subscription_id, | |
'compare' => '=', | |
), | |
array( | |
'key' => 'success', | |
'value' => 'ok', | |
'compare' => '=' | |
) | |
) | |
); | |
$transactions = get_posts( $args ); | |
if ( ! empty( $transactions ) ) { | |
return $transactions[0]; | |
} | |
else { | |
return false; | |
} | |
} | |
// This returns the required fields of the transaction. | |
public function payment_from_transaction( $transaction ) { | |
$payment = array(); | |
if ( ! $transaction instanceof WP_Post || 'ms_transaction_log' != $transaction->post_type ) { | |
return $payment; | |
} | |
$payment = array( | |
'id' => $transaction->ID, | |
'date' => $transaction->post_date | |
); | |
/* | |
// Currently we don't need to use transaction meta | |
$meta = get_post_meta( $transaction->ID ); | |
foreach ( $meta as $meta_key => $meta_value ) { | |
if ( isset( $meta_value[0] ) && ! isset( $payment[ $meta_key ] ) ) { | |
$payment[ $meta_key ] = $meta_value[0]; | |
} | |
} | |
*/ | |
return (object) $payment; | |
} | |
public function get_subscription_expiration_date( $subscription, $last_payment_date ) { | |
$grace_period = apply_filters( | |
'ms_subscription_expiration_grace_period', | |
1, | |
$subscription | |
); | |
$period_duration = $this->get_subscription_duration( $subscription ); | |
$expiration_date = date( 'Y-m-d H:i:s', strtotime( $last_payment_date . "+{$period_duration->period_unit} {$period_duration->period_type}" ) ); | |
return date( 'Y-m-d H:i:s', strtotime( $expiration_date . "+{$grace_period} days" ) ); | |
} | |
public function get_subscription_duration( $subscription ) { | |
if ( ! $subscription instanceof MS_Model_Relationship ) { | |
return false; | |
} | |
return (object) MS_Factory::load( | |
'MS_Model_Membership', | |
$subscription->membership_id | |
)->period; | |
} | |
} | |
if ( ! function_exists( 'wpmudev_ms_cron_status_check' ) ) { | |
function wpmudev_ms_cron_status_check(){ | |
return WPMUDEV_MS_Cron_Status_Check::get_instance(); | |
}; | |
add_action( 'plugins_loaded', 'wpmudev_ms_cron_status_check', 10 ); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Requires to add the following filter at the beginning of MS_Model_Relationship::check_membership_status