public function column_due_date($item, $column_name)
 {
     $due_now = false;
     $is_paid = $item->is_paid();
     if (!$is_paid) {
         $diff = MS_Helper_Period::subtract_dates($item->due_date, MS_Helper_Period::current_date(), null, true);
         $due_now = $diff < 0;
     }
     $due_date = MS_Helper_Period::format_date($item->due_date);
     if ($due_now) {
         $html = sprintf('<span class="due-now" title="%2$s">%1$s</span>', $due_date, __('Payment is overdue', 'membership2'));
     } elseif ($item->pay_date) {
         $pay_date = MS_Helper_Period::format_date($item->pay_date, 'M j, Y');
         $html = sprintf('<span class="is-paid" title="%2$s">%1$s</span>', $due_date, sprintf(__('Paid: %s', 'membership2'), $pay_date));
     } else {
         $html = sprintf('<span>%1$s</span>', $due_date);
     }
     return $html;
 }
 /**
  * Check for card expiration date.
  *
  * Save event for card expire soon.
  *
  * @since  1.0.0
  *
  * @access protected
  * @param MS_Model_Relationship $subscription The membership relationship.
  */
 public function check_card_expiration($subscription)
 {
     do_action('ms_gateway_check_card_expiration_before', $this);
     $member = MS_Factory::load('MS_Model_Member', $subscription->user_id);
     $card_exp = $member->get_gateway_profile($this->id, 'card_exp');
     if (!empty($card_exp)) {
         $comm = MS_Model_Communication::get_communication(MS_Model_Communication::COMM_TYPE_CREDIT_CARD_EXPIRE);
         $days = MS_Helper_Period::get_period_in_days($comm->period['period_unit'], $comm->period['period_type']);
         $card_expire_days = MS_Helper_Period::subtract_dates($card_exp, MS_Helper_Period::current_date(), DAY_IN_SECONDS, true);
         if ($card_expire_days < 0 || $days == $card_expire_days) {
             MS_Model_Event::save_event(MS_Model_Event::TYPE_CREDIT_CARD_EXPIRE, $subscription);
         }
     }
     do_action('ms_gateway_check_card_expiration_after', $this, $subscription);
 }
 public function column_due_date($item, $column_name)
 {
     $due_now = false;
     if (!$item->is_paid()) {
         $diff = MS_Helper_Period::subtract_dates($item->due_date, MS_Helper_Period::current_date(), null, true);
         $due_now = $diff < 0;
     }
     $date = MS_Helper_Period::format_date($item->due_date);
     if ($due_now) {
         $html = sprintf('<span class="due-now" title="%2$s">%1$s</span>', $date, __('Payment is overdue', MS_TEXT_DOMAIN));
     } else {
         $html = sprintf('<span>%1$s</span>', $date);
     }
     return $html;
 }
 /**
  * Check membership status.
  *
  * Execute actions when time/period condition are met.
  * E.g. change membership status, add communication to queue, create invoices.
  *
  * This check is called via a cron job.
  *
  * @since  1.0.0
  * @internal  Used by Cron
  * @see MS_Model_Plugin::check_membership_status()
  */
 public function check_membership_status()
 {
     do_action('ms_model_relationship_check_membership_status_before', $this);
     /**
      * Use `define( 'MS_LOCK_SUBSCRIPTIONS', true );` in wp-config.php to prevent
      * Membership2 from sending *any* emails to users.
      * Also any currently enqueued message is removed from the queue
      *
      * @since  1.0.0
      */
     if (MS_Plugin::get_modifier('MS_LOCK_SUBSCRIPTIONS')) {
         return false;
     }
     $membership = $this->get_membership();
     $remaining_days = $this->get_remaining_period();
     $remaining_trial_days = $this->get_remaining_trial_period();
     $comms = MS_Model_Communication::get_communications($membership);
     $invoice_before_days = 5;
     //@todo create a setting to configure this period.
     $deactivate_expired_after_days = 30;
     //@todo create a setting to configure this period.
     $deactivate_pending_after_days = 30;
     //@todo create a setting to configure this period.
     $deactivate_trial_expired_after_days = 5;
     //@todo create a setting to configure this period.
     //@todo: Add a flag to subscriptions with sent communications. Then improve the conditions below to prevent multiple emails.
     do_action('ms_check_membership_status-' . $this->status, $this, $remaining_days, $remaining_trial_days);
     // Update the Subscription status.
     $next_status = $this->calculate_status(null);
     switch ($next_status) {
         case self::STATUS_TRIAL:
             if (MS_Model_Addon::is_enabled(MS_Model_Addon::ADDON_TRIAL) && MS_Model_Addon::is_enabled(MS_Model_Addon::ADDON_AUTO_MSGS_PLUS)) {
                 // Send trial end communication.
                 $comm = $comms[MS_Model_Communication::COMM_TYPE_BEFORE_TRIAL_FINISHES];
                 if ($comm->enabled) {
                     $days = MS_Helper_Period::get_period_in_days($comm->period['period_unit'], $comm->period['period_type']);
                     //@todo: This will send out the reminder multiple times on the reminder-day (4 times or more often)
                     if ($days == $remaining_trial_days) {
                         $comm->add_to_queue($this->id);
                         MS_Model_Event::save_event(MS_Model_Event::TYPE_MS_BEFORE_TRIAL_FINISHES, $this);
                     }
                 }
             }
             // Check for card expiration
             $gateway = $this->get_gateway();
             $gateway->check_card_expiration($this);
             break;
         case self::STATUS_TRIAL_EXPIRED:
             if (MS_Model_Addon::is_enabled(MS_Model_Addon::ADDON_TRIAL)) {
                 // Mark the trial period as completed. $this->save() is below.
                 $this->trial_period_completed = true;
                 // Request payment to the gateway (for gateways that allows it).
                 $gateway = $this->get_gateway();
                 /*
                  * The subscription will be either automatically activated
                  * or set to pending.
                  *
                  * Important: Set trial_period_completed=true before calling
                  * request_payment()!
                  */
                 if ($gateway->request_payment($this)) {
                     $next_status = self::STATUS_ACTIVE;
                     $this->status = $next_status;
                     $this->config_period();
                     // Needed because of status change.
                 }
                 // Check for card expiration
                 $gateway->check_card_expiration($this);
                 // Deactivate expired memberships after a period of time.
                 if ($deactivate_trial_expired_after_days < -$remaining_trial_days) {
                     $this->deactivate_membership();
                 }
             }
             break;
         case self::STATUS_ACTIVE:
         case self::STATUS_EXPIRED:
         case self::STATUS_CANCELED:
             /*
              * Make sure the expire date has a correct value, in case the user
              * changed the payment_type of the parent membership after this
              * subscription was created.
              */
             if ($this->payment_type != $membership->payment_type) {
                 $this->payment_type = $membership->payment_type;
                 switch ($this->payment_type) {
                     case MS_Model_Membership::PAYMENT_TYPE_PERMANENT:
                         $this->expire_date = false;
                         break;
                     default:
                         // Either keep the current expire date (if valid) or
                         // calculate a new expire date, based on current date.
                         if (!$this->expire_date) {
                             $this->expire_date = $this->calc_expire_date(MS_Helper_Period::current_date());
                         }
                         break;
                 }
                 // Recalculate the days until the subscription expires.
                 $remaining_days = $this->get_remaining_period();
                 // Recalculate the new Subscription status.
                 $next_status = $this->calculate_status();
             }
             /*
              * Only "Recurring" memberships will ever try to automatically
              * renew the subscription. All other types will expire when the
              * end date is reached.
              */
             $auto_renew = $membership->payment_type == MS_Model_Membership::PAYMENT_TYPE_RECURRING;
             $deactivate = false;
             $invoice = null;
             if ($auto_renew && $membership->pay_cycle_repetitions > 0) {
                 /*
                  * The membership has a payment-repetition limit.
                  * When this limit is reached then we do not auto-renew the
                  * subscription but expire it.
                  */
                 $payments = $this->get_payments();
                 if (count($payments) >= $membership->pay_cycle_repetitions) {
                     $auto_renew = false;
                 }
             }
             if ($auto_renew) {
                 if ($remaining_days < $invoice_before_days) {
                     // Create a new invoice.
                     $invoice = $this->get_next_invoice();
                 } else {
                     $invoice = $this->get_current_invoice();
                 }
             } else {
                 $invoice = $this->get_current_invoice();
             }
             // Advanced communications Add-on.
             if (MS_Model_Addon::is_enabled(MS_Model_Addon::ADDON_AUTO_MSGS_PLUS)) {
                 // Before finishes communication.
                 $comm = $comms[MS_Model_Communication::COMM_TYPE_BEFORE_FINISHES];
                 $days = MS_Helper_Period::get_period_in_days($comm->period['period_unit'], $comm->period['period_type']);
                 if ($days == $remaining_days) {
                     $comm->add_to_queue($this->id);
                     MS_Model_Event::save_event(MS_Model_Event::TYPE_MS_BEFORE_FINISHES, $this);
                 }
                 // After finishes communication.
                 $comm = $comms[MS_Model_Communication::COMM_TYPE_AFTER_FINISHES];
                 $days = MS_Helper_Period::get_period_in_days($comm->period['period_unit'], $comm->period['period_type']);
                 if ($remaining_days < 0 && $days == abs($remaining_days)) {
                     $comm->add_to_queue($this->id);
                     MS_Model_Event::save_event(MS_Model_Event::TYPE_MS_AFTER_FINISHES, $this);
                 }
                 // Before payment due.
                 $comm = $comms[MS_Model_Communication::COMM_TYPE_BEFORE_PAYMENT_DUE];
                 $days = MS_Helper_Period::get_period_in_days($comm->period['period_unit'], $comm->period['period_type']);
                 $invoice_days = MS_Helper_Period::subtract_dates($invoice->due_date, MS_Helper_Period::current_date());
                 if (MS_Model_Invoice::STATUS_BILLED == $invoice->status && $days == $invoice_days) {
                     $comm->add_to_queue($this->id);
                     MS_Model_Event::save_event(MS_Model_Event::TYPE_PAYMENT_BEFORE_DUE, $this);
                 }
                 // After payment due event
                 $comm = $comms[MS_Model_Communication::COMM_TYPE_AFTER_PAYMENT_DUE];
                 $days = MS_Helper_Period::get_period_in_days($comm->period['period_unit'], $comm->period['period_type']);
                 $invoice_days = MS_Helper_Period::subtract_dates($invoice->due_date, MS_Helper_Period::current_date());
                 if (MS_Model_Invoice::STATUS_BILLED == $invoice->status && $days == $invoice_days) {
                     $comm->add_to_queue($this->id);
                     MS_Model_Event::save_event(MS_Model_Event::TYPE_PAYMENT_AFTER_DUE, $this);
                 }
             }
             // -- End of advanced communications Add-on
             // Subscription ended. See if we can renew it.
             if ($remaining_days <= 0) {
                 if ($auto_renew) {
                     /*
                      * The membership can be renewed. Try to renew it
                      * automatically by requesting the next payment from the
                      * payment gateway (only works if gateway supports this)
                      */
                     $gateway = $this->get_gateway();
                     $gateway->check_card_expiration($this);
                     $gateway->request_payment($this);
                     // Check if the payment was successful.
                     $remaining_days = $this->get_remaining_period();
                 }
                 /*
                  * User did not renew the membership. Give him some time to
                  * react before restricting his access.
                  */
                 if ($deactivate_expired_after_days < -$remaining_days) {
                     $deactivate = true;
                 }
             }
             $next_status = $this->calculate_status(null);
             /*
              * When the subscription expires the first time then create a
              * new event that triggers the "Expired" email.
              */
             if (self::STATUS_EXPIRED == $next_status && $next_status != $this->status) {
                 MS_Model_Event::save_event(MS_Model_Event::TYPE_MS_EXPIRED, $this);
             } elseif ($deactivate) {
                 $this->deactivate_membership();
                 $next_status = $this->status;
                 // Move membership to configured membership.
                 $membership = $this->get_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', $this->user_id);
                     $new_subscription = $member->add_membership($membership->on_end_membership_id, $this->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 (!$new_membership->is_free()) {
                         $new_subscription->status = self::STATUS_PENDING;
                     }
                 }
             }
             break;
         case self::STATUS_DEACTIVATED:
             /*
              * A subscription was finally deactivated.
              * Lets check if the member has any other active subscriptions,
              * or (if not) his account should be deactivated.
              *
              * First get a list of all subscriptions that do not have status
              * Pending / Deactivated.
              */
             $subscriptions = self::get_subscriptions(array('user_id' => $this->user_id));
             // Check if there is a subscription that keeps the user active.
             $deactivate = true;
             foreach ($subscriptions as $item) {
                 if ($item->id == $this->id) {
                     continue;
                 }
                 $deactivate = false;
             }
             if ($deactivate) {
                 $member = $this->get_member();
                 $member->is_member = false;
                 $member->save();
             }
             break;
         case self::STATUS_PENDING:
         default:
             // Do nothing.
             break;
     }
     // Save the new status.
     $this->status = $next_status;
     $this->save();
     // Save the changed email queue.
     foreach ($comms as $comm) {
         $comm->save();
     }
     do_action('ms_model_relationship_check_membership_status_after', $this);
 }
 /**
  * Prepare the PayPal IPN fields
  *
  * Details here:
  * https://developer.paypal.com/docs/classic/paypal-payments-standard/integration-guide/Appx_websitestandard_htmlvariables/
  *
  * @since  1.0.0
  * @return array
  */
 private function prepare_fields()
 {
     $subscription = $this->data['ms_relationship'];
     $membership = $subscription->get_membership();
     if (0 === $membership->price) {
         return;
     }
     $gateway = $this->data['gateway'];
     $invoice = $subscription->get_current_invoice();
     $regular_invoice = null;
     $settings = MS_Factory::load('MS_Model_Settings');
     $nonce = wp_create_nonce($gateway->id . '_' . $subscription->id);
     $cancel_url = MS_Model_Pages::get_page_url(MS_Model_Pages::MS_PAGE_REGISTER);
     $return_url = esc_url_raw(add_query_arg(array('ms_relationship_id' => $subscription->id), MS_Model_Pages::get_page_url(MS_Model_Pages::MS_PAGE_REG_COMPLETE, false)));
     $fields = array('_wpnonce' => array('id' => '_wpnonce', 'type' => MS_Helper_Html::INPUT_TYPE_HIDDEN, 'value' => $nonce), 'charset' => array('id' => 'charset', 'type' => MS_Helper_Html::INPUT_TYPE_HIDDEN, 'value' => 'utf-8'), 'business' => array('id' => 'business', 'type' => MS_Helper_Html::INPUT_TYPE_HIDDEN, 'value' => $gateway->merchant_id), 'cmd' => array('id' => 'cmd', 'type' => MS_Helper_Html::INPUT_TYPE_HIDDEN, 'value' => '_xclick-subscriptions'), 'bn' => array('id' => 'bn', 'type' => MS_Helper_Html::INPUT_TYPE_HIDDEN, 'value' => 'incsub_SP'), 'item_name' => array('id' => 'item_name', 'type' => MS_Helper_Html::INPUT_TYPE_HIDDEN, 'value' => $membership->name), 'item_number' => array('id' => 'item_number', 'type' => MS_Helper_Html::INPUT_TYPE_HIDDEN, 'value' => $membership->id), 'currency_code' => array('id' => 'currency_code', 'type' => MS_Helper_Html::INPUT_TYPE_HIDDEN, 'value' => MS_Plugin::instance()->settings->currency), 'return' => array('id' => 'return', 'type' => MS_Helper_Html::INPUT_TYPE_HIDDEN, 'value' => $return_url), 'cancel_return' => array('id' => 'cancel_return', 'type' => MS_Helper_Html::INPUT_TYPE_HIDDEN, 'value' => $cancel_url), 'notify_url' => array('id' => 'notify_url', 'type' => MS_Helper_Html::INPUT_TYPE_HIDDEN, 'value' => $gateway->get_return_url()), 'country' => array('id' => 'country', 'type' => MS_Helper_Html::INPUT_TYPE_HIDDEN, 'value' => $gateway->paypal_site), 'no_note' => array('id' => 'no_note', 'type' => MS_Helper_Html::INPUT_TYPE_HIDDEN, 'value' => 1), 'no_shipping' => array('id' => 'no_shipping', 'type' => MS_Helper_Html::INPUT_TYPE_HIDDEN, 'value' => 1), 'invoice' => array('id' => 'invoice', 'type' => MS_Helper_Html::INPUT_TYPE_HIDDEN, 'value' => $invoice->id));
     $fields['submit'] = array('id' => 'submit', 'type' => MS_Helper_Html::INPUT_TYPE_IMAGE, 'value' => 'https://www.paypal.com/en_US/i/btn/btn_subscribe_LG.gif', 'alt' => __('PayPal - The safer, easier way to pay online', 'membership2'));
     // custom pay button defined in gateway settings
     $custom_label = $gateway->pay_button_url;
     if (!empty($custom_label)) {
         if (false !== strpos($custom_label, '://')) {
             $fields['submit']['value'] = $custom_label;
         } else {
             $fields['submit'] = array('id' => 'submit', 'type' => MS_Helper_Html::INPUT_TYPE_SUBMIT, 'value' => $custom_label);
         }
     }
     // Trial period
     if ($subscription->is_trial_eligible()) {
         $fields['a1'] = array('id' => 'a1', 'type' => MS_Helper_Html::INPUT_TYPE_HIDDEN, 'value' => $invoice->trial_price);
         $trial_type = MS_Helper_Period::get_period_value($membership->trial_period, 'period_type');
         $trial_type = strtoupper($trial_type[0]);
         $trial_value = MS_Helper_Period::get_period_value($membership->trial_period, 'period_unit');
         $trial_value = MS_Helper_Period::validate_range($trial_value, $trial_type);
         $fields['p1'] = array('id' => 'p1', 'type' => MS_Helper_Html::INPUT_TYPE_HIDDEN, 'value' => $trial_value);
         $fields['t1'] = array('id' => 't1', 'type' => MS_Helper_Html::INPUT_TYPE_HIDDEN, 'value' => $trial_type);
     }
     // Membership price
     $membership_price = $invoice->total;
     $membership_price = MS_Helper_Billing::format_price($membership_price);
     $fields['a3'] = array('id' => 'a3', 'type' => MS_Helper_Html::INPUT_TYPE_HIDDEN, 'value' => $membership_price);
     $fields['amount'] = array('id' => 'amount', 'type' => MS_Helper_Html::INPUT_TYPE_HIDDEN, 'value' => $membership_price);
     $recurring = 0;
     switch ($membership->payment_type) {
         // == RECURRING PAYMENTS
         case MS_Model_Membership::PAYMENT_TYPE_RECURRING:
             $period_type = MS_Helper_Period::get_period_value($membership->pay_cycle_period, 'period_type');
             $period_type = strtoupper($period_type[0]);
             $period_value = MS_Helper_Period::get_period_value($membership->pay_cycle_period, 'period_unit');
             $period_value = MS_Helper_Period::validate_range($period_value, $period_type);
             $fields['p3'] = array('id' => 'p3', 'type' => MS_Helper_Html::INPUT_TYPE_HIDDEN, 'value' => $period_value);
             $fields['t3'] = array('id' => 't3', 'type' => MS_Helper_Html::INPUT_TYPE_HIDDEN, 'value' => $period_type);
             // This makes the payments recurring!
             $recurring = 1;
             break;
             // == FINITE END DATE
         // == FINITE END DATE
         case MS_Model_Membership::PAYMENT_TYPE_FINITE:
             $period_type = MS_Helper_Period::get_period_value($membership->period, 'period_type');
             $period_type = strtoupper($period_type[0]);
             $period_value = MS_Helper_Period::get_period_value($membership->period, 'period_unit');
             $period_value = MS_Helper_Period::validate_range($period_value, $period_type);
             $fields['p3'] = array('id' => 'p3', 'type' => MS_Helper_Html::INPUT_TYPE_HIDDEN, 'value' => $period_value);
             $fields['t3'] = array('id' => 't3', 'type' => MS_Helper_Html::INPUT_TYPE_HIDDEN, 'value' => $period_type);
             break;
             // == DATE RANGE
         // == DATE RANGE
         case MS_Model_Membership::PAYMENT_TYPE_DATE_RANGE:
             $period_value = MS_Helper_Period::subtract_dates($membership->period_date_end, $membership->period_date_start);
             $period_value = MS_Helper_Period::validate_range($period_value, 'D');
             $fields['p3'] = array('id' => 'p3', 'type' => MS_Helper_Html::INPUT_TYPE_HIDDEN, 'value' => $period_value);
             $fields['t3'] = array('id' => 't3', 'type' => MS_Helper_Html::INPUT_TYPE_HIDDEN, 'value' => 'D');
             break;
             // == PERMANENT
         // == PERMANENT
         case MS_Model_Membership::PAYMENT_TYPE_PERMANENT:
             /*
              * Permanent membership: Set the subscription range to 5 years!
              * PayPal requires us to provide the subscription range and the
              * maximum possible value is 5 years.
              */
             $period_value = MS_Helper_Period::validate_range(5, 'Y');
             $fields['p3'] = array('id' => 'p3', 'type' => MS_Helper_Html::INPUT_TYPE_HIDDEN, 'value' => $period_value);
             $fields['t3'] = array('id' => 't3', 'type' => MS_Helper_Html::INPUT_TYPE_HIDDEN, 'value' => 'Y');
             break;
     }
     if (1 == $recurring) {
         if (1 == $membership->pay_cycle_repetitions) {
             $recurring = 0;
         } elseif ($membership->pay_cycle_repetitions > 1) {
             /**
              * Recurring times.
              * The number of times that a recurring payment is made.
              */
             $fields['srt'] = array('id' => 'srt', 'type' => MS_Helper_Html::INPUT_TYPE_HIDDEN, 'value' => $membership->pay_cycle_repetitions);
         }
     }
     /**
      * Recurring field.
      * 0 - one time payment
      * 1 - recurring payments
      */
     $fields['src'] = array('id' => 'src', 'type' => MS_Helper_Html::INPUT_TYPE_HIDDEN, 'value' => $recurring);
     /**
      * Modify current subscription field.
      * value != 0 does not allow trial period.
      * 0 - allows subscribers only to sign up for new subscriptions
      * 1 - allows subscribers to sign up for new subscriptions and modify their current subscriptions
      * 2 - allows subscribers to modify only their current subscriptions
      */
     $modify = !empty($move_from_id);
     $fields['modify'] = array('id' => 'modify', 'type' => MS_Helper_Html::INPUT_TYPE_HIDDEN, 'value' => $modify ? 2 : 0);
     if ($gateway->is_live_mode()) {
         $this->data['action_url'] = 'https://www.paypal.com/cgi-bin/webscr';
     } else {
         $this->data['action_url'] = 'https://www.sandbox.paypal.com/cgi-bin/webscr';
     }
     return apply_filters('ms_gateway_paypalstandard_view_prepare_fields', $fields);
 }
 /**
  * Add a message in the "send queue".
  *
  * @since  1.0.0
  * @api
  * @param  int $subscription_id The membership relationship ID to add to queue.
  */
 public function add_to_queue($subscription_id)
 {
     do_action('ms_model_communication_add_to_queue_before', $this);
     /**
      * Documented in process_queue()
      *
      * @since  1.0.0
      */
     if (MS_Plugin::get_modifier('MS_STOP_EMAILS')) {
         $subscription = MS_Factory::load('MS_Model_Relationship', $subscription_id);
         do_action('lib2_debug_log', sprintf('Following Email was not sent: "%s" to user "%s".', $this->type, $subscription->user_id));
         return false;
     }
     $is_enqueued = array_key_exists($subscription_id, $this->queue);
     if ($this->enabled && !$is_enqueued) {
         $can_add = true;
         /**
          * Check if email enqueuing is limited to prevent duplicate emails.
          *
          * Use setting `define( 'MS_DUPLICATE_EMAIL_HOURS', 24 )` to prevent
          * duplicate emails from being sent for 24 hours.
          *
          * @var int Number of hours
          */
         $pause_hours = 0;
         if (defined('MS_DUPLICATE_EMAIL_HOURS') && is_numeric(MS_DUPLICATE_EMAIL_HOURS)) {
             $pause_hours = MS_DUPLICATE_EMAIL_HOURS;
         }
         if ($pause_hours > 0) {
             if (array_key_exists($subscription_id, $this->sent_queue)) {
                 $pause_hours = apply_filters('ms_model_communication_hours_before_resend', $pause_hours);
                 /*
                  * The sent_queue is saved in DB and only contains messages
                  * from the current Communications object. So
                  * $subscription_id defines the email contents and receiver.
                  */
                 $sent_date = $this->sent_queue[$subscription_id];
                 $now = MS_Helper_Period::current_time();
                 $current_delay = MS_Helper_Period::subtract_dates($now, $sent_date, HOURS_IN_SECONDS);
                 $can_add = $current_delay >= $pause_hours;
             }
         }
         if ($can_add) {
             $this->queue[$subscription_id] = MS_Helper_Period::current_time();
         }
     }
     do_action('ms_model_communication_add_to_queue_after', $this);
 }
 /**
  * Calculate pro rate value.
  *
  * Pro rate using remaining membership days.
  *
  * @since  1.0.1.0
  *
  * @return float The pro rate value.
  */
 protected function get_discount($subscription)
 {
     $value = 0;
     $membership = $subscription->get_membership();
     if (MS_Model_Membership::PAYMENT_TYPE_PERMANENT !== $membership->payment_type) {
         $invoice = $subscription->get_previous_invoice();
         if ($invoice && $invoice->is_paid()) {
             switch ($subscription->status) {
                 case MS_Model_Relationship::STATUS_TRIAL:
                     // No Pro-Rate given for trial memberships.
                     break;
                 case MS_Model_Relationship::STATUS_ACTIVE:
                 case MS_Model_Relationship::STATUS_WAITING:
                 case MS_Model_Relationship::STATUS_CANCELED:
                     $remaining_days = $subscription->get_remaining_period();
                     $total_days = MS_Helper_Period::subtract_dates($subscription->expire_date, $subscription->start_date);
                     $value = $remaining_days / $total_days;
                     $value *= $invoice->total;
                     break;
                 default:
                     // No Pro-Rate for other subscription status.
                     break;
             }
         }
     }
     return apply_filters('ms_addon_prorate_get_discount', $value, $subscription);
 }