/**
  * Set the subscription prices to be used in calculating totals by @see WC_Subscriptions_Cart::calculate_subscription_totals()
  *
  * @since 1.4
  */
 public static function maybe_set_apporitioned_totals($total)
 {
     global $woocommerce;
     if (false === self::cart_contains_subscription_switch()) {
         return $total;
     }
     // Maybe charge an initial amount to account for upgrading from a cheaper subscription
     $apportion_recurring_price = get_option(WC_Subscriptions_Admin::$option_prefix . '_apportion_recurring_price', 'no');
     $apportion_sign_up_fee = get_option(WC_Subscriptions_Admin::$option_prefix . '_apportion_sign_up_fee', 'no');
     $apportion_length = get_option(WC_Subscriptions_Admin::$option_prefix . '_apportion_length', 'no');
     foreach ($woocommerce->cart->get_cart() as $cart_item_key => $cart_item) {
         if (!isset($cart_item['subscription_switch']['subscription_key'])) {
             continue;
         }
         $old_subscription_key = $cart_item['subscription_switch']['subscription_key'];
         $item_data = $cart_item['data'];
         $product_id = empty($cart_item['variation_id']) ? $cart_item['product_id'] : $cart_item['variation_id'];
         $product = get_product($product_id);
         // Set the date on which the first payment for the new subscription should be charged
         $woocommerce->cart->cart_contents[$cart_item_key]['subscription_switch']['first_payment_timestamp'] = $cart_item['subscription_switch']['next_payment_timestamp'];
         $is_virtual_product = 'no' != $item_data->virtual ? true : false;
         // Add any extra sign up fees required to switch to the new subscription
         if ('yes' == $apportion_sign_up_fee) {
             $old_subscription = WC_Subscriptions_Manager::get_subscription($old_subscription_key);
             $sign_up_fee_due = $product->subscription_sign_up_fee;
             if (self::order_contains_subscription_switch($old_subscription['order_id'])) {
                 $old_order = new WC_Order($old_subscription['order_id']);
                 $sign_up_fee_paid = $old_order->get_total();
             } else {
                 $sign_up_fee_paid = WC_Subscriptions_Order::get_item_sign_up_fee($old_subscription['order_id'], $old_subscription['product_id']);
             }
             $woocommerce->cart->cart_contents[$cart_item_key]['data']->subscription_sign_up_fee = max($sign_up_fee_due - $sign_up_fee_paid, 0);
         } elseif ('no' == $apportion_sign_up_fee) {
             // $0 the initial sign-up fee
             $woocommerce->cart->cart_contents[$cart_item_key]['data']->subscription_sign_up_fee = 0;
         }
         // Now lets see if we should add an apportioned amount to the sign-up fee (for upgrades) or extend the next payment date (for downgrades)
         if ('yes' == $apportion_recurring_price || 'virtual' == $apportion_recurring_price && $is_virtual_product) {
             // Get the current subscription
             $old_subscription = isset($old_subscription) ? $old_subscription : WC_Subscriptions_Manager::get_subscription($old_subscription_key);
             // Get the current subscription's original order
             $old_order = isset($old_order) ? $old_order : new WC_Order($old_subscription['order_id']);
             // Get the current subscription's last payment date
             $last_payment_timestamp = WC_Subscriptions_Manager::get_last_payment_date($old_subscription_key, get_current_user_id(), 'timestamp');
             $days_since_last_payment = round((gmdate('U') - $last_payment_timestamp) / (60 * 60 * 24));
             // Get the current subscription's next payment date
             $next_payment_timestamp = $cart_item['subscription_switch']['next_payment_timestamp'];
             $days_until_next_payment = round(($next_payment_timestamp - gmdate('U')) / (60 * 60 * 24));
             // Find the number of days between the two
             $days_in_old_cycle = $days_until_next_payment + $days_since_last_payment;
             // Find the $price per day for the old subscription's recurring total
             $old_recurring_total = WC_Subscriptions_Order::get_item_recurring_amount($old_subscription['order_id'], $old_subscription['product_id']);
             $old_price_per_day = $old_recurring_total / $days_in_old_cycle;
             // Find the price per day for the new subscription's recurring total
             // If the subscription uses the same billing interval & cycle as the old subscription,
             if ($item_data->subscription_period == $old_subscription['period'] && $item_data->subscription_period_interval == $old_subscription['interval']) {
                 $days_in_new_cycle = $days_in_old_cycle;
                 // Use $days_in_old_cycle to make sure they're consistent
                 $new_price_per_day = $product->subscription_price / $days_in_old_cycle;
             } else {
                 // We need to figure out the price per day for the new subscription based on its billing schedule
                 switch ($item_data->subscription_period) {
                     case 'day':
                         $days_in_new_cycle = $item_data->subscription_period_interval;
                         break;
                     case 'week':
                         $days_in_new_cycle = $item_data->subscription_period_interval * 7;
                         break;
                     case 'month':
                         $days_in_new_cycle = $item_data->subscription_period_interval * 30.4375;
                         // Average days per month over 4 year period
                         break;
                     case 'year':
                         $days_in_new_cycle = $item_data->subscription_period_interval * 365.25;
                         // Average days per year over 4 year period
                         break;
                 }
                 $new_price_per_day = $product->subscription_price / $days_in_new_cycle;
             }
             // If the customer is upgrading, we may need to add a gap payment to the sign-up fee or to reduce the pre-paid period (or both)
             if ($old_price_per_day < $new_price_per_day) {
                 // The new subscription may be more expensive, but it's also on a shorter billing cycle, so reduce the next pre-paid term
                 if ($days_in_old_cycle > $days_in_new_cycle) {
                     // Find out how many days at the new price per day the customer would receive for the total amount already paid
                     // (e.g. if the customer paid $10 / month previously, and was switching to a $5 / week subscription, she has pre-paid 14 days at the new price)
                     $pre_paid_days = 0;
                     do {
                         $pre_paid_days++;
                         $new_total_paid = $pre_paid_days * $new_price_per_day;
                     } while ($new_total_paid < $old_recurring_total);
                     // If the total amount the customer has paid entitles her to more days at the new price than she has received, there is no gap payment, just shorten the pre-paid term the appropriate number of days
                     if ($days_since_last_payment < $pre_paid_days) {
                         $woocommerce->cart->cart_contents[$cart_item_key]['subscription_switch']['first_payment_timestamp'] = $last_payment_timestamp + $pre_paid_days * 60 * 60 * 24;
                         // If the total amount the customer has paid entitles her to the same or less days at the new price then start the new subscription from today
                     } else {
                         $woocommerce->cart->cart_contents[$cart_item_key]['subscription_switch']['first_payment_timestamp'] = 0;
                     }
                 } else {
                     $extra_to_pay = $days_until_next_payment * ($new_price_per_day - $old_price_per_day);
                     $woocommerce->cart->cart_contents[$cart_item_key]['data']->subscription_sign_up_fee += round($extra_to_pay, 2);
                 }
                 $woocommerce->cart->cart_contents[$cart_item_key]['subscription_switch']['upgraded_or_downgraded'] = 'upgraded';
                 // If the customer is downgrading, we need to extend the next payment date for n more days
             } elseif ($old_price_per_day > $new_price_per_day && $new_price_per_day > 0) {
                 $old_total_paid = $old_price_per_day * $days_until_next_payment;
                 $new_total_paid = $new_price_per_day;
                 // Find how many more days at the new lower price it takes to exceed the amount already paid
                 for ($days_to_add = 1; $new_total_paid <= $old_total_paid; $days_to_add++) {
                     $new_total_paid = $days_to_add * $new_price_per_day;
                 }
                 $days_to_add -= $days_until_next_payment;
                 $woocommerce->cart->cart_contents[$cart_item_key]['subscription_switch']['first_payment_timestamp'] = $next_payment_timestamp + $days_to_add * 60 * 60 * 24;
                 $woocommerce->cart->cart_contents[$cart_item_key]['subscription_switch']['upgraded_or_downgraded'] = 'downgraded';
             }
             // The old price per day == the new price per day, no need to change anything
         }
         // Finally, if we need to make sure the initial total doesn't include any recurring amount, we can by spoofing a free trial
         if (0 != $woocommerce->cart->cart_contents[$cart_item_key]['subscription_switch']['first_payment_timestamp']) {
             $woocommerce->cart->cart_contents[$cart_item_key]['data']->subscription_trial_length = 1;
         }
         if ('yes' == $apportion_length || 'virtual' == $apportion_length && $is_virtual_product) {
             // Maybe charge an initial amount to account for upgrading from a cheaper subscription
             $base_length = WC_Subscriptions_Product::get_length($product_id);
             $completed_payments = WC_Subscriptions_Manager::get_subscriptions_completed_payment_count($old_subscription_key);
             $length_remaining = $base_length - $completed_payments;
             // Default to the base length if more payments have already been made than this subscription requires
             if ($length_remaining < 0) {
                 $length_remaining = $base_length;
             }
             $woocommerce->cart->cart_contents[$cart_item_key]['data']->subscription_length = $length_remaining;
         }
     }
     return $total;
 }
 /**
  * If a subscription has the status of active, this function checks to make sure that a payment was completed
  * within the last couple of days. It is hooked to the 'paypal_check_subscription_payment' action triggered by
  * WP-Cron and scheduled with @see self::scheduled_subscription_payment() to run 24 hours after the payment was due.
  *
  * @since 1.4.3
  */
 public static function check_subscription_payment($subscription_key)
 {
     $subscription = WC_Subscriptions_Manager::get_subscription($subscription_key);
     $order = new WC_Order($subscription['order_id']);
     if ('active' === $subscription['status']) {
         $last_payment_plus_two_days = 60 * 60 * 24 * 2 + WC_Subscriptions_Manager::get_last_payment_date($subscription_key, $order->user_id, 'timestamp');
         // If the last payment was more than 2 days ago, then we're missing a payment because this function is called 24 hours after payment was due
         if ($last_payment_plus_two_days < gmdate('U')) {
             // @TODO process a subscription payment failure when this has been reliably tested
             //remove_action( 'subscription_put_on-hold_paypal', __CLASS__ . '::suspend_subscription_with_paypal', 10, 2 );
             //WC_Subscriptions_Manager::process_subscription_payment_failure( $order->user_id, $subscription_key );
             //$order->add_order_note( __( 'Subscription payment failure triggered as no recurring payment has been processed by PayPal.', 'woocommerce-subscriptions' ) );
             //add_action( 'subscription_put_on-hold_paypal', __CLASS__ . '::suspend_subscription_with_paypal', 10, 2 );
         }
     }
 }
 /**
  * Takes a subscription product's ID and the order it was purchased in and returns the date on
  * which the last payment was made.
  *
  * A convenience wrapper for @see WC_Subscriptions_Manager::get_last_payment_date() to get the next
  * payment date for a subscription when all you have is the order and product.
  *
  * @param mixed $order A WC_Order object or the ID of the order which the subscription was purchased in.
  * @param int $product_id The product/post ID of the subscription
  * @param mixed $deprecated Never used.
  * @return mixed If no more payments are due, returns 0, otherwise it returns the MySQL formatted date/time string for the next payment date.
  * @version 1.2.1
  * @since 1.0
  */
 public static function get_last_payment_date($order, $product_id)
 {
     if (!is_object($order)) {
         $order = new WC_Order($order);
     }
     $subscription_key = WC_Subscriptions_Manager::get_subscription_key($order->id, $product_id);
     $last_payment_date = WC_Subscriptions_Manager::get_last_payment_date($subscription_key, $order->user_id);
     return $last_payment_date;
 }
 /**
  * get_content_plain function.
  *
  * @access public
  * @return string
  */
 function get_content_plain()
 {
     $order = new WC_Order($this->object['order_id']);
     $item_name = WC_Subscriptions_Order::get_item_name($this->object['order_id'], $this->object['product_id']);
     $order_item = WC_Subscriptions_Order::get_item_by_product_id($order, $this->object['product_id']);
     $product = $order->get_product_from_item($order_item);
     if (isset($product->variation_data)) {
         $item_name .= ' (' . woocommerce_get_formatted_variation($product->variation_data, true) . ')';
     }
     WC_Subscriptions_Order::$recurring_only_price_strings = true;
     $recurring_total = WC_Subscriptions_Order::get_formatted_order_total(0, $order);
     WC_Subscriptions_Order::$recurring_only_price_strings = false;
     if ($end_of_prepaid_term = wp_next_scheduled('scheduled_subscription_end_of_prepaid_term', array('user_id' => (int) $order->user_id, 'subscription_key' => $this->subscription_key))) {
         $end_of_prepaid_term = date_i18n(woocommerce_date_format(), $end_of_prepaid_term + get_option('gmt_offset') * 3600);
     }
     ob_start();
     woocommerce_get_template($this->template_plain, array('subscription_key' => $this->subscription_key, 'subscription' => $this->object, 'order' => $order, 'email_heading' => $this->get_heading(), 'item_name' => $item_name, 'recurring_total' => $recurring_total, 'last_payment' => date_i18n(woocommerce_date_format(), WC_Subscriptions_Manager::get_last_payment_date($this->subscription_key, '', 'timestamp')), 'end_of_prepaid_term' => $end_of_prepaid_term), '', $this->template_base);
     return ob_get_clean();
 }