/**
  * Show the subscription template when view a subscription instead of loading the default order template.
  *
  * @param $located
  * @param $template_name
  * @param $args
  * @param $template_path
  * @param $default_path
  * @since 2.0
  */
 public static function add_view_subscription_template($located, $template_name, $args, $template_path, $default_path)
 {
     global $wp;
     if ('myaccount/my-account.php' == $template_name && !empty($wp->query_vars['view-subscription']) && WC_Subscriptions::is_woocommerce_pre('2.6')) {
         $located = wc_locate_template('myaccount/view-subscription.php', $template_path, plugin_dir_path(WC_Subscriptions::$plugin_file) . 'templates/');
     }
     return $located;
 }
 /**
  * Hooks up all of Skip One transaction emails after the WooCommerce object is constructed.
  *
  * @since 1.0.0
  * @access public
  * @static
  */
 public static function hook_transactional_emails()
 {
     // Don't send subscription
     if (WC_Subscriptions::is_duplicate_site() && !defined('WCS_FORCE_EMAIL')) {
         return;
     }
     $skip_emails = array('next_payment_date');
     foreach ($skip_emails as $email) {
         add_action('woocommerce_skip_one_' . $email, __CLASS__ . '::send_' . $email . '_email', 10, 2);
     }
 }
 /**
  * Hooks up all of Subscription's transaction emails after the WooCommerce object is constructed.
  *
  * @since 1.4
  */
 public static function hook_transactional_emails()
 {
     // Don't send subscription
     if (WC_Subscriptions::is_duplicate_site() && !defined('WCS_FORCE_EMAIL')) {
         return;
     }
     add_action('woocommerce_subscription_status_updated', __CLASS__ . '::send_cancelled_email', 10, 2);
     $order_email_actions = array('woocommerce_order_status_pending_to_processing', 'woocommerce_order_status_pending_to_completed', 'woocommerce_order_status_pending_to_on-hold', 'woocommerce_order_status_failed_to_processing_notification', 'woocommerce_order_status_failed_to_completed_notification', 'woocommerce_order_status_failed_to_on-hold_notification', 'woocommerce_order_status_completed', 'woocommerce_generated_manual_renewal_order', 'woocommerce_order_status_failed');
     foreach ($order_email_actions as $action) {
         add_action($action, __CLASS__ . '::maybe_remove_woocommerce_email', 9);
         add_action($action, __CLASS__ . '::send_renewal_order_email', 10);
         add_action($action, __CLASS__ . '::send_switch_order_email', 10);
         add_action($action, __CLASS__ . '::maybe_reattach_woocommerce_email', 11);
     }
 }
 /**
  * Create a simple subscription product object.
  *
  * @access public
  * @param mixed $product
  */
 public function __construct($product, $args = array())
 {
     parent::__construct($product, $args = array());
     $this->parent_product_type = $this->product_type;
     $this->product_type = 'subscription_variation';
     $this->subscription_variation_level_meta_data = array('subscription_price' => 0, 'subscription_period' => '', 'subscription_period_interval' => 'day', 'subscription_length' => 0, 'subscription_trial_length' => 0, 'subscription_trial_period' => 'day', 'subscription_sign_up_fee' => 0, 'subscription_payment_sync_date' => 0);
     if (WC_Subscriptions::is_woocommerce_pre_2_2()) {
         // WC 2.1
         // Convert selected subscription meta fields for easy access
         foreach ($this->subscription_variation_level_meta_data as $meta_key => $default_value) {
             if (!empty($this->product_custom_fields['_' . $meta_key][0])) {
                 $this->{$meta_key} = maybe_unserialize($this->product_custom_fields['_' . $meta_key][0]);
             } else {
                 $this->{$meta_key} = $this->subscription_variation_level_meta_data[$meta_key];
             }
         }
     } else {
         $this->variation_level_meta_data = array_merge($this->variation_level_meta_data, $this->subscription_variation_level_meta_data);
     }
 }
 /**
  * When a new order is inserted, add subscriptions related order meta.
  *
  * @since 1.0
  */
 public static function add_order_meta($order_id, $posted)
 {
     global $woocommerce;
     if (!WC_Subscriptions_Cart::cart_contains_subscription_renewal('child') && WC_Subscriptions_Order::order_contains_subscription($order_id)) {
         // This works because the 'woocommerce_add_order_item_meta' runs before the 'woocommerce_checkout_update_order_meta' hook
         // Set the recurring totals so totals display correctly on order page
         update_post_meta($order_id, '_order_recurring_discount_cart', WC_Subscriptions_Cart::get_recurring_discount_cart());
         update_post_meta($order_id, '_order_recurring_discount_cart_tax', WC_Subscriptions_Cart::get_recurring_discount_cart_tax());
         update_post_meta($order_id, '_order_recurring_discount_total', WC_Subscriptions_Cart::get_recurring_discount_total());
         update_post_meta($order_id, '_order_recurring_shipping_tax_total', WC_Subscriptions_Cart::get_recurring_shipping_tax_total());
         update_post_meta($order_id, '_order_recurring_shipping_total', WC_Subscriptions_Cart::get_recurring_shipping_total());
         update_post_meta($order_id, '_order_recurring_tax_total', WC_Subscriptions_Cart::get_recurring_total_tax());
         update_post_meta($order_id, '_order_recurring_total', WC_Subscriptions_Cart::get_recurring_total());
         // Set the recurring payment method - it starts out the same as the original by may change later
         update_post_meta($order_id, '_recurring_payment_method', get_post_meta($order_id, '_payment_method', true));
         update_post_meta($order_id, '_recurring_payment_method_title', get_post_meta($order_id, '_payment_method_title', true));
         $order = new WC_Order($order_id);
         $order_fees = $order->get_fees();
         // the fee order items have already been set, we just need to to add the recurring total meta
         $cart_fees = $woocommerce->cart->get_fees();
         foreach ($order->get_fees() as $item_id => $order_fee) {
             // Find the matching fee in the cart
             foreach ($cart_fees as $fee_index => $cart_fee) {
                 if (sanitize_title($order_fee['name']) == $cart_fee->id) {
                     woocommerce_add_order_item_meta($item_id, '_recurring_line_total', wc_format_decimal($cart_fee->recurring_amount));
                     woocommerce_add_order_item_meta($item_id, '_recurring_line_tax', wc_format_decimal($cart_fee->recurring_tax));
                     unset($cart_fees[$fee_index]);
                     break;
                 }
             }
         }
         // Get recurring taxes into same format as _order_taxes
         $order_recurring_taxes = array();
         foreach (WC_Subscriptions_Cart::get_recurring_taxes() as $tax_key => $tax_amount) {
             $item_id = woocommerce_add_order_item($order_id, array('order_item_name' => WC_Tax::get_rate_code($tax_key), 'order_item_type' => 'recurring_tax'));
             if ($item_id) {
                 wc_add_order_item_meta($item_id, 'rate_id', $tax_key);
                 wc_add_order_item_meta($item_id, 'label', WC_Tax::get_rate_label($tax_key));
                 wc_add_order_item_meta($item_id, 'compound', absint(WC_Tax::is_compound($tax_key) ? 1 : 0));
                 wc_add_order_item_meta($item_id, 'tax_amount', wc_format_decimal(isset(WC()->cart->recurring_taxes[$tax_key]) ? WC()->cart->recurring_taxes[$tax_key] : 0));
                 wc_add_order_item_meta($item_id, 'shipping_tax_amount', wc_format_decimal(isset(WC()->cart->recurring_shipping_taxes[$tax_key]) ? WC()->cart->recurring_shipping_taxes[$tax_key] : 0));
             }
         }
         $payment_gateways = $woocommerce->payment_gateways->payment_gateways();
         if ('yes' == get_option(WC_Subscriptions_Admin::$option_prefix . '_turn_off_automatic_payments', 'no')) {
             update_post_meta($order_id, '_wcs_requires_manual_renewal', 'true');
         } elseif (isset($payment_gateways[$posted['payment_method']]) && !$payment_gateways[$posted['payment_method']]->supports('subscriptions')) {
             update_post_meta($order_id, '_wcs_requires_manual_renewal', 'true');
         }
         $cart_item = WC_Subscriptions_Cart::cart_contains_subscription_renewal();
         if (isset($cart_item['subscription_renewal']) && 'parent' == $cart_item['subscription_renewal']['role']) {
             update_post_meta($order_id, '_original_order', $cart_item['subscription_renewal']['original_order']);
         }
         // WC 2.1+
         if (!WC_Subscriptions::is_woocommerce_pre('2.1')) {
             // Recurring coupons
             if ($applied_coupons = $woocommerce->cart->get_coupons()) {
                 foreach ($applied_coupons as $code => $coupon) {
                     if (!isset($woocommerce->cart->recurring_coupon_discount_amounts[$code])) {
                         continue;
                     }
                     $item_id = woocommerce_add_order_item($order_id, array('order_item_name' => $code, 'order_item_type' => 'recurring_coupon'));
                     // Add line item meta
                     if ($item_id) {
                         woocommerce_add_order_item_meta($item_id, 'discount_amount', isset($woocommerce->cart->recurring_coupon_discount_amounts[$code]) ? $woocommerce->cart->recurring_coupon_discount_amounts[$code] : 0);
                     }
                 }
             }
             // Add recurring shipping order items
             if (WC_Subscriptions_Cart::cart_contains_subscriptions_needing_shipping()) {
                 $packages = $woocommerce->shipping->get_packages();
                 $checkout = $woocommerce->checkout();
                 foreach ($packages as $i => $package) {
                     if (isset($package['rates'][$checkout->shipping_methods[$i]])) {
                         $method = $package['rates'][$checkout->shipping_methods[$i]];
                         $item_id = woocommerce_add_order_item($order_id, array('order_item_name' => $method->label, 'order_item_type' => 'recurring_shipping'));
                         if ($item_id) {
                             woocommerce_add_order_item_meta($item_id, 'method_id', $method->id);
                             woocommerce_add_order_item_meta($item_id, 'cost', WC_Subscriptions::format_total($method->cost));
                             woocommerce_add_order_item_meta($item_id, 'taxes', array_map('wc_format_decimal', $method->taxes));
                             do_action('woocommerce_subscriptions_add_recurring_shipping_order_item', $order_id, $item_id, $i);
                         }
                     }
                 }
             }
             // Remove shipping on original order if it was added but is not required
             if (!WC_Subscriptions_Cart::charge_shipping_up_front()) {
                 foreach ($order->get_shipping_methods() as $order_item_id => $shipping_method) {
                     woocommerce_update_order_item_meta($order_item_id, 'cost', WC_Subscriptions::format_total(0));
                 }
             }
         } else {
             update_post_meta($order_id, '_recurring_shipping_method', get_post_meta($order_id, '_shipping_method', true), true);
             update_post_meta($order_id, '_recurring_shipping_method_title', get_post_meta($order_id, '_shipping_method_title', true), true);
         }
     }
 }
        ?>
						<?php 
        echo WC_Subscriptions_Order::get_item_name($subscription_details['order_id'], $subscription_details['product_id']);
        ?>
					<?php 
        if (false !== $product) {
            ?>
					</a>
					<?php 
        }
        ?>
					<?php 
        $order_item = WC_Subscriptions_Order::get_item_by_product_id($order, $subscription_details['product_id']);
        ?>
					<?php 
        if (WC_Subscriptions::is_woocommerce_pre('2.4')) {
            ?>
						<?php 
            $item_meta = new WC_Order_Item_Meta($order_item['item_meta'], $product);
            ?>
					<?php 
        } else {
            ?>
						<?php 
            $item_meta = new WC_Order_Item_Meta($order_item, $product);
            ?>
					<?php 
        }
        ?>
					<?php 
        $meta_to_display = $item_meta->display(true, true);
 /**
  * Return an i18n'ified associative array of all possible subscription periods.
  *
  * @since 1.0
  */
 public static function get_subscription_period_interval_strings($interval = '')
 {
     $intervals = array(1 => __('per', WC_Subscriptions::$text_domain));
     foreach (range(2, 6) as $i) {
         $intervals[$i] = sprintf(__('every %s', WC_Subscriptions::$text_domain), WC_Subscriptions::append_numeral_suffix($i));
     }
     $intervals = apply_filters('woocommerce_subscription_period_interval_strings', $intervals);
     if (empty($interval)) {
         return $intervals;
     } else {
         return $intervals[$interval];
     }
 }
 /**
  * Takes a subscription product's ID and returns the date on which the subscription trial will expire,
  * based on the subscription's trial length and calculated from either the $from_date if specified,
  * or the current date/time.
  *
  * @param int $product_id The product/post ID of the subscription
  * @param mixed $from_date A MySQL formatted date/time string from which to calculate the expiration date (in UTC timezone), or empty (default), which will use today's date/time (in UTC timezone).
  * @since 1.0
  */
 public static function get_trial_expiration_date($product_id, $from_date = '')
 {
     $trial_period = self::get_trial_period($product_id);
     $trial_length = self::get_trial_length($product_id);
     if ($trial_length > 0) {
         if (empty($from_date)) {
             $from_date = gmdate('Y-m-d H:i:s');
         }
         if ('month' == $trial_period) {
             $trial_expiration_date = date('Y-m-d H:i:s', WC_Subscriptions::add_months(strtotime($from_date), $trial_length));
         } else {
             // Safe to just add the billing periods
             $trial_expiration_date = date('Y-m-d H:i:s', strtotime("+ {$trial_length} {$trial_period}s", strtotime($from_date)));
         }
     } else {
         $trial_expiration_date = 0;
     }
     return apply_filters('woocommerce_subscriptions_product_trial_expiration_date', $trial_expiration_date, $product_id, $from_date);
 }
 /**
  * A flag to indicate whether the current site has roughly more than 3000 subscriptions. Used to disable
  * features on the Manage Subscriptions list table that do not scale well (yet).
  *
  * @since 1.4.4
  */
 public static function is_large_site()
 {
     if (false === self::$is_large_site) {
         self::$is_large_site = filter_var(get_option('wcs_is_large_site'), FILTER_VALIDATE_BOOLEAN);
         if (false === self::$is_large_site && self::get_total_subscription_count() > 2500) {
             add_option('wcs_is_large_site', 'true', '', false);
             self::$is_large_site = true;
         }
     }
     return apply_filters('woocommerce_subscriptions_is_large_site', self::$is_large_site);
 }
/**
 * Creates a subscription price string from an array of subscription details. For example, "$5 / month for 12 months".
 *
 * @param array $subscription_details A set of name => value pairs for the subscription details to include in the string. Available keys:
 *		'initial_amount': The upfront payment for the subscription, including sign up fees, as a string from the @see wc_price(). Default empty string (no initial payment)
 *		'initial_description': The word after the initial payment amount to describe the amount. Examples include "now" or "initial payment". Defaults to "up front".
 *		'recurring_amount': The amount charged per period. Default 0 (no recurring payment).
 *		'subscription_interval': How regularly the subscription payments are charged. Default 1, meaning each period e.g. per month.
 *		'subscription_period': The temporal period of the subscription. Should be one of {day|week|month|year} as used by @see wcs_get_subscription_period_strings()
 *		'subscription_length': The total number of periods the subscription should continue for. Default 0, meaning continue indefinitely.
 *		'trial_length': The total number of periods the subscription trial period should continue for.  Default 0, meaning no trial period.
 *		'trial_period': The temporal period for the subscription's trial period. Should be one of {day|week|month|year} as used by @see wcs_get_subscription_period_strings()
 * @since 2.0
 * @return string The price string with translated and billing periods included
 */
function wcs_price_string($subscription_details)
{
    global $wp_locale;
    $subscription_details = wp_parse_args($subscription_details, array('currency' => '', 'initial_amount' => '', 'initial_description' => _x('up front', 'initial payment on a subscription', 'woocommerce-subscriptions'), 'recurring_amount' => '', 'subscription_interval' => 1, 'subscription_period' => '', 'subscription_length' => 0, 'trial_length' => 0, 'trial_period' => '', 'is_synced' => false, 'synchronised_payment_day' => 0, 'display_excluding_tax_label' => false));
    $subscription_details['subscription_period'] = strtolower($subscription_details['subscription_period']);
    // Make sure prices have been through wc_price()
    if (is_numeric($subscription_details['initial_amount'])) {
        $initial_amount_string = wc_price($subscription_details['initial_amount'], array('currency' => $subscription_details['currency'], 'ex_tax_label' => $subscription_details['display_excluding_tax_label']));
    } else {
        $initial_amount_string = $subscription_details['initial_amount'];
    }
    if (is_numeric($subscription_details['recurring_amount'])) {
        $recurring_amount_string = wc_price($subscription_details['recurring_amount'], array('currency' => $subscription_details['currency'], 'ex_tax_label' => $subscription_details['display_excluding_tax_label']));
    } else {
        $recurring_amount_string = $subscription_details['recurring_amount'];
    }
    $subscription_period_string = wcs_get_subscription_period_strings($subscription_details['subscription_interval'], $subscription_details['subscription_period']);
    $subscription_ranges = wcs_get_subscription_ranges();
    if ($subscription_details['subscription_length'] > 0 && $subscription_details['subscription_length'] == $subscription_details['subscription_interval']) {
        if (!empty($subscription_details['initial_amount'])) {
            if ($subscription_details['subscription_interval'] == $subscription_details['subscription_length'] && 0 == $subscription_details['trial_length']) {
                $subscription_string = $initial_amount_string;
            } else {
                // translators: 1$: initial amount, 2$: initial description (e.g. "up front"), 3$: recurring amount string (e.g. "£10 / month" )
                $subscription_string = sprintf(__('%1$s %2$s then %3$s', 'woocommerce-subscriptions'), $initial_amount_string, $subscription_details['initial_description'], $recurring_amount_string);
            }
        } else {
            $subscription_string = $recurring_amount_string;
        }
    } elseif (true === $subscription_details['is_synced'] && in_array($subscription_details['subscription_period'], array('week', 'month', 'year'))) {
        // Verbosity is important here to enable translation
        $payment_day = $subscription_details['synchronised_payment_day'];
        switch ($subscription_details['subscription_period']) {
            case 'week':
                $payment_day_of_week = WC_Subscriptions_Synchroniser::get_weekday($payment_day);
                if (1 == $subscription_details['subscription_interval']) {
                    if (!empty($subscription_details['initial_amount'])) {
                        // translators: 1$: initial amount, 2$: initial description (e.g. "up front"), 3$: recurring amount string, 4$: payment day of the week (e.g. "$15 up front, then $10 every Wednesday")
                        $subscription_string = sprintf(__('%1$s %2$s then %3$s every %4$s', 'woocommerce-subscriptions'), $initial_amount_string, $subscription_details['initial_description'], $recurring_amount_string, $payment_day_of_week);
                    } else {
                        // translators: 1$: recurring amount string, 2$: day of the week (e.g. "$10 every Wednesday")
                        $subscription_string = sprintf(__('%1$s every %2$s', 'woocommerce-subscriptions'), $recurring_amount_string, $payment_day_of_week);
                    }
                } else {
                    // e.g. $5 every 2 weeks on Wednesday
                    if (!empty($subscription_details['initial_amount'])) {
                        // translators: 1$: initial amount, 2$: initial description (e.g. "up front" ), 3$: recurring amount, 4$: interval (e.g. "2nd week"), 5$: day of the week (e.g. "Thursday"); (e.g. "$10 up front, then $20 every 2nd week on Wednesday")
                        $subscription_string = sprintf(__('%1$s %2$s then %3$s every %4%s on %5$s', 'woocommerce-subscriptions'), $initial_amount_string, $subscription_details['initial_description'], $recurring_amount_string, wcs_get_subscription_period_strings($subscription_details['subscription_interval'], $subscription_details['subscription_period']), $payment_day_of_week);
                    } else {
                        // translators: 1$: recurring amount string, 2$: interval (e.g. "2nd week"), 3$: day of the week (e.g. "Thursday"); (e.g. "$10 every 2nd week on Wednesday")
                        $subscription_string = sprintf(__('%1$s every %2$s on %3$s', 'woocommerce-subscriptions'), $recurring_amount_string, wcs_get_subscription_period_strings($subscription_details['subscription_interval'], $subscription_details['subscription_period']), $payment_day_of_week);
                    }
                }
                break;
            case 'month':
                if (1 == $subscription_details['subscription_interval']) {
                    // e.g. $15 on the 15th of each month
                    if (!empty($subscription_details['initial_amount'])) {
                        if ($payment_day > 27) {
                            // translators: 1$: initial amount, 2$: initial description (e.g. "up front"), 3$: recurring amount; (e.g. "$10 up front then $30 on the last day of each month")
                            $subscription_string = sprintf(__('%1$s %2$s then %3$s on the last day of each month', 'woocommerce-subscriptions'), $initial_amount_string, $subscription_details['initial_description'], $recurring_amount_string);
                        } else {
                            // translators: 1$: initial amount, 2$: initial description (e.g. "up front"), 3$: recurring amount, 4$: day of the month (e.g. "23rd"); (e.g. "$10 up front then $40 on the 23rd of each month")
                            $subscription_string = sprintf(__('%1$s %2$s then %3$s on the %4$s of each month', 'woocommerce-subscriptions'), $initial_amount_string, $subscription_details['initial_description'], $recurring_amount_string, WC_Subscriptions::append_numeral_suffix($payment_day));
                        }
                    } else {
                        if ($payment_day > 27) {
                            // translators: placeholder is recurring amount
                            $subscription_string = sprintf(__('%s on the last day of each month', 'woocommerce-subscriptions'), $recurring_amount_string);
                        } else {
                            // translators: 1$: recurring amount, 2$: day of the month (e.g. "23rd")
                            $subscription_string = sprintf(__('%1$s on the %2$s of each month', 'woocommerce-subscriptions'), $recurring_amount_string, WC_Subscriptions::append_numeral_suffix($payment_day));
                        }
                    }
                } else {
                    // e.g. $15 on the 15th of every 3rd month
                    if (!empty($subscription_details['initial_amount'])) {
                        if ($payment_day > 27) {
                            // translators: 1$: initial amount, 2$: initial description (e.g. "up front"), 3$: recurring amount, 4$: interval (e.g. "3rd")
                            $subscription_string = sprintf(__('%1$s %2$s then %3$s on the last day of every %4$s month', 'woocommerce-subscriptions'), $initial_amount_string, $subscription_details['initial_description'], $recurring_amount_string, WC_Subscriptions::append_numeral_suffix($subscription_details['subscription_interval']));
                        } else {
                            // translators: 1$: initial amount, 2$: initial description (e.g. "up front"), 3$: recurring amount, 4$: day of the month (e.g. "23rd"), 5$: interval (e.g. "3rd")
                            $subscription_string = sprintf(__('%1$s %2$s then %3$s on the %4$s day of every %5$s month', 'woocommerce-subscriptions'), $initial_amount_string, $subscription_details['initial_description'], $recurring_amount_string, WC_Subscriptions::append_numeral_suffix($payment_day), WC_Subscriptions::append_numeral_suffix($subscription_details['subscription_interval']));
                        }
                    } else {
                        if ($payment_day > 27) {
                            // translators: 1$: recurring amount, 2$: interval (e.g. "3rd")
                            $subscription_string = sprintf(__('%1$s on the last day of every %2$s month', 'woocommerce-subscriptions'), $recurring_amount_string, WC_Subscriptions::append_numeral_suffix($subscription_details['subscription_interval']));
                        } else {
                            // translators: 1$: recurring amount, 2$: day in month (e.g. "23rd"), 3$: interval (e.g. "3rd")
                            $subscription_string = sprintf(__('%1$s on the %2$s day of every %3$s month', 'woocommerce-subscriptions'), $recurring_amount_string, WC_Subscriptions::append_numeral_suffix($payment_day), WC_Subscriptions::append_numeral_suffix($subscription_details['subscription_interval']));
                        }
                    }
                }
                break;
            case 'year':
                if (1 == $subscription_details['subscription_interval']) {
                    // e.g. $15 on March 15th each year
                    if (!empty($subscription_details['initial_amount'])) {
                        // translators: 1$: initial amount, 2$: intial description (e.g. "up front"), 3$: recurring amount, 4$: month of year (e.g. "March"), 5$: day of the month (e.g. "23rd")
                        $subscription_string = sprintf(__('%1$s %2$s then %3$s on %4$s %5$s each year', 'woocommerce-subscriptions'), $initial_amount_string, $subscription_details['initial_description'], $recurring_amount_string, $wp_locale->month[$payment_day['month']], WC_Subscriptions::append_numeral_suffix($payment_day['day']));
                    } else {
                        // translators: 1$: recurring amount, 2$: month (e.g. "March"), 3$: day of the month (e.g. "23rd")
                        $subscription_string = sprintf(__('%1$s on %2$s %3$s each year', 'woocommerce-subscriptions'), $recurring_amount_string, $wp_locale->month[$payment_day['month']], WC_Subscriptions::append_numeral_suffix($payment_day['day']));
                    }
                } else {
                    // e.g. $15 on March 15th every 3rd year
                    if (!empty($subscription_details['initial_amount'])) {
                        // translators: 1$: initial amount, 2$: initial description (e.g. "up front"), 3$: recurring amount, 4$: month (e.g. "March"), 5$: day of the month (e.g. "23rd"), 6$: interval (e.g. "3rd")
                        $subscription_string = sprintf(__('%1$s %2$s then %3$s on %4$s %5$s every %6$s year', 'woocommerce-subscriptions'), $initial_amount_string, $subscription_details['initial_description'], $recurring_amount_string, $wp_locale->month[$payment_day['month']], WC_Subscriptions::append_numeral_suffix($payment_day['day']), WC_Subscriptions::append_numeral_suffix($subscription_details['subscription_interval']));
                    } else {
                        // translators: 1$: recurring amount, 2$: month (e.g. "March"), 3$: day of month (e.g. "23rd"), 4$: interval (e.g. "3rd")
                        $subscription_string = sprintf(__('%1$s on %2$s %3$s every %4$s year', 'woocommerce-subscriptions'), $recurring_amount_string, $wp_locale->month[$payment_day['month']], WC_Subscriptions::append_numeral_suffix($payment_day['day']), WC_Subscriptions::append_numeral_suffix($subscription_details['subscription_interval']));
                    }
                }
                break;
        }
    } elseif (!empty($subscription_details['initial_amount'])) {
        // translators: 1$: initial amount, 2$: initial description (e.g. "up front"), 3$: recurring amount, 4$: subscription period (e.g. "month" or "3 months")
        $subscription_string = sprintf(_n('%1$s %2$s then %3$s / %4$s', '%1$s %2$s then %3$s every %4$s', $subscription_details['subscription_interval'], 'woocommerce-subscriptions'), $initial_amount_string, $subscription_details['initial_description'], $recurring_amount_string, $subscription_period_string);
    } elseif (!empty($subscription_details['recurring_amount']) || intval($subscription_details['recurring_amount']) === 0) {
        // translators: 1$: recurring amount, 2$: subscription period (e.g. "month" or "3 months")
        $subscription_string = sprintf(_n('%1$s / %2$s', ' %1$s every %2$s', $subscription_details['subscription_interval'], 'woocommerce-subscriptions'), $recurring_amount_string, $subscription_period_string);
    } else {
        $subscription_string = '';
    }
    if ($subscription_details['subscription_length'] > 0) {
        // translators: 1$: subscription string (e.g. "$10 up front then $5 on March 23rd every 3rd year"), 2$: length (e.g. "4 years")
        $subscription_string = sprintf(__('%1$s for %2$s', 'woocommerce-subscriptions'), $subscription_string, $subscription_ranges[$subscription_details['subscription_period']][$subscription_details['subscription_length']]);
    }
    if ($subscription_details['trial_length'] > 0) {
        $trial_length = wcs_get_subscription_trial_period_strings($subscription_details['trial_length'], $subscription_details['trial_period']);
        if (!empty($subscription_details['initial_amount'])) {
            // translators: 1$: subscription string (e.g. "$10 up front then $5 on March 23rd every 3rd year"), 2$: trial length (e.g. "3 weeks")
            $subscription_string = sprintf(__('%1$s after %2$s free trial', 'woocommerce-subscriptions'), $subscription_string, $trial_length);
        } else {
            // translators: 1$: trial length (e.g. "3 weeks"), 2$: subscription string (e.g. "$10 up front then $5 on March 23rd every 3rd year")
            $subscription_string = sprintf(__('%1$s free trial then %2$s', 'woocommerce-subscriptions'), ucfirst($trial_length), $subscription_string);
        }
    }
    if ($subscription_details['display_excluding_tax_label'] && get_option('woocommerce_calc_taxes') == 'yes') {
        $subscription_string .= ' <small>' . WC()->countries->ex_tax_or_vat() . '</small>';
    }
    return apply_filters('woocommerce_subscription_price_string', $subscription_string, $subscription_details);
}
 /**
  * Checks if the current request is by a user to change the status of their subscription, and if it is
  * validate the subscription cancellation request and maybe processes the cancellation. 
  *
  * @since 1.0
  */
 public static function maybe_change_users_subscription()
 {
     global $woocommerce;
     if (isset($_GET['change_subscription_to']) && isset($_GET['subscription_key']) && isset($_GET['_wpnonce'])) {
         $user_id = get_current_user_id();
         $subscription = self::get_subscription($_GET['subscription_key']);
         if (wp_verify_nonce($_GET['_wpnonce'], $_GET['subscription_key']) === false) {
             WC_Subscriptions::add_notice(sprintf(__('That subscription can not be changed to %s. Please contact us if you need assistance.', 'woocommerce-subscriptions'), $_GET['change_subscription_to']), 'error');
         } elseif (empty($subscription)) {
             WC_Subscriptions::add_notice(__('That doesn\'t appear to be one of your subscriptions.', 'woocommerce-subscriptions'), 'error');
         } elseif (!WC_Subscriptions_Manager::can_subscription_be_changed_to($_GET['change_subscription_to'], $_GET['subscription_key'], $user_id)) {
             WC_Subscriptions::add_notice(sprintf(__('That subscription can not be changed to %s. Please contact us if you need assistance.', 'woocommerce-subscriptions'), $_GET['change_subscription_to']), 'error');
         } elseif (!in_array($_GET['change_subscription_to'], array('active', 'on-hold', 'cancelled'))) {
             WC_Subscriptions::add_notice(sprintf(__('Unknown subscription status: "%s". Please contact us if you need assistance.', 'woocommerce-subscriptions'), $_GET['change_subscription_to']), 'error');
         } else {
             switch ($_GET['change_subscription_to']) {
                 case 'active':
                     if (WC_Subscriptions_Manager::subscription_requires_payment($_GET['subscription_key'], $user_id)) {
                         WC_Subscriptions::add_notice(sprintf(__('You can not reactive that subscription until paying to renew it. Please contact us if you need assistance.', 'woocommerce-subscriptions'), $_GET['change_subscription_to']), 'error');
                     } else {
                         self::reactivate_subscription($user_id, $_GET['subscription_key']);
                         $status_message = __('reactivated', 'woocommerce-subscriptions');
                     }
                     break;
                 case 'on-hold':
                     if (self::current_user_can_suspend_subscription($_GET['subscription_key'])) {
                         self::put_subscription_on_hold($user_id, $_GET['subscription_key']);
                         $status_message = __('suspended', 'woocommerce-subscriptions');
                     } else {
                         WC_Subscriptions::add_notice(sprintf(__('You can not suspend that subscription - the suspension limit has been reached. Please contact us if you need assistance.', 'woocommerce-subscriptions'), $_GET['change_subscription_to']), 'error');
                     }
                     break;
                 case 'cancelled':
                     self::cancel_subscription($user_id, $_GET['subscription_key']);
                     $status_message = __('cancelled', 'woocommerce-subscriptions');
                     break;
             }
             if (isset($status_message)) {
                 $order = new WC_Order($subscription['order_id']);
                 $order->add_order_note(sprintf(__('The status of subscription %s was changed to %s by the subscriber from their account page.', 'woocommerce-subscriptions'), $_GET['subscription_key'], $_GET['change_subscription_to']));
                 WC_Subscriptions::add_notice(sprintf(__('Your subscription has been %s.', 'woocommerce-subscriptions'), $status_message), 'success');
             }
         }
         wp_safe_redirect(get_permalink(woocommerce_get_page_id('myaccount')));
         exit;
     }
 }
 /**
  * Get, sort and filter subscriptions for display.
  *
  * @uses $this->_column_headers
  * @uses $this->items
  * @uses $this->get_columns()
  * @uses $this->get_sortable_columns()
  * @uses $this->get_pagenum()
  * @uses $this->set_pagination_args()
  * @since 1.0
  */
 function prepare_items()
 {
     global $wcs_list_table_statuses;
     $screen = get_current_screen();
     $per_page = $this->get_items_per_page($screen->get_option('per_page', 'option'), 10);
     $paged = isset($_GET['paged']) ? $_GET['paged'] : 1;
     $this->get_column_info();
     $status_to_show = isset($_GET['status']) ? $_GET['status'] : 'all';
     if (isset($_REQUEST['s']) || !empty($_REQUEST['orderby']) && 'next_payment_date' === $_REQUEST['orderby']) {
         @set_time_limit(300);
         $subscriptions = $wcs_list_table_statuses = array();
         // It's a search
         if (isset($_REQUEST['s'])) {
             $subscriptions_grouped_by_user = WC_Subscriptions_Manager::search_subscriptions($_REQUEST['s']);
         } else {
             // Order by next payment date
             $subscriptions_grouped_by_user = WC_Subscriptions_Manager::get_all_users_subscriptions();
         }
         foreach ($subscriptions_grouped_by_user as $user_id => $users_subscriptions) {
             // Filter by a certain customer?
             if (isset($_GET['_customer_user']) && (int) $user_id !== (int) $_GET['_customer_user']) {
                 continue;
             }
             foreach ($users_subscriptions as $subscription_key => $subscription) {
                 // Filter by a certain product?
                 if (isset($_GET['_product_id']) && (int) $subscription['product_id'] !== (int) $_GET['_product_id']) {
                     continue;
                 }
                 $wcs_list_table_statuses[$subscription['status']] = isset($wcs_list_table_statuses[$subscription['status']]) ? $wcs_list_table_statuses[$subscription['status']] + 1 : 1;
                 if ($status_to_show == $subscription['status'] || $status_to_show == 'all' && $subscription['status'] != 'trash') {
                     $subscriptions[$subscription_key] = $subscription + array('user_id' => $user_id, 'subscription_key' => $subscription_key);
                 }
             }
         }
         // If we have a request for a status that does not exist, default to all subscriptions
         if (!isset($wcs_list_table_statuses[$status_to_show])) {
             if ($status_to_show != 'all') {
                 $status_to_show = $_GET['status'] = 'all';
                 foreach ($subscriptions_grouped_by_user as $user_id => $users_subscriptions) {
                     // Filter by a certain customer?
                     if (isset($_GET['_customer_user']) && (int) $user_id !== (int) $_GET['_customer_user']) {
                         continue;
                     }
                     foreach ($users_subscriptions as $subscription_key => $subscription) {
                         // Filter by a certain product?
                         if (isset($_GET['_product_id']) && (int) $subscription['product_id'] !== (int) $_GET['_product_id']) {
                             continue;
                         }
                         $subscriptions[$subscription_key] = $subscription + array('user_id' => $user_id, 'subscription_key' => $subscription_key);
                     }
                 }
             } else {
                 $_GET['status'] = 'all';
             }
         }
         ksort($wcs_list_table_statuses);
         $wcs_list_table_statuses = array('all' => array_sum($wcs_list_table_statuses)) + $wcs_list_table_statuses;
         if (isset($wcs_list_table_statuses['trash'])) {
             $wcs_list_table_statuses['all'] = $wcs_list_table_statuses['all'] - $wcs_list_table_statuses['trash'];
         }
         $total_items = count($subscriptions);
         @usort($subscriptions, array(&$this, 'sort_subscriptions'));
         // Need to suppress warnings due to PHP bug here: https://bugs.php.net/bug.php?id=50688
         $subscriptions = array_slice($subscriptions, ($paged - 1) * $per_page, $per_page);
     } else {
         $subscriptions_query = array('paged' => $paged, 'subscriptions_per_page' => $per_page, 'subscription_status' => $status_to_show, 'order' => !empty($_REQUEST['order']) ? strtoupper($_REQUEST['order']) : 'DESC', 'orderby' => !empty($_REQUEST['orderby']) ? $_REQUEST['orderby'] : '_subscription_start_date');
         // Filter by a certain customer?
         if (isset($_GET['_customer_user']) && !empty($_GET['_customer_user'])) {
             $subscriptions_query['customer_id'] = $_GET['_customer_user'];
         }
         // Filter by a certain product?
         if (isset($_GET['_product_id']) && !empty($_GET['_product_id'])) {
             $subscriptions_query['product_id'] = $_GET['_product_id'];
         }
         $subscriptions = WC_Subscriptions::get_subscriptions($subscriptions_query);
         $wcs_list_table_statuses = WC_Subscriptions::get_subscription_status_counts();
         if (isset($wcs_list_table_statuses['trash'])) {
             $wcs_list_table_statuses['all'] = $wcs_list_table_statuses['all'] - $wcs_list_table_statuses['trash'];
         }
         if ('all' === $status_to_show && !isset($subscriptions_query['customer_id']) && !isset($subscriptions_query['product_id'])) {
             $total_items = $wcs_list_table_statuses['all'];
         } else {
             $total_items = WC_Subscriptions::get_subscription_count($subscriptions_query);
         }
     }
     // Add sorted & sliced data to the items property to be used by the rest of the class
     $this->items = $subscriptions;
     $this->set_pagination_args(array('total_items' => $total_items, 'per_page' => $per_page, 'total_pages' => ceil($total_items / $per_page)));
 }
    /**
     * Display recurring order totals on the "Edit Order" page.
     *
     * @param int $post_id The post ID of the shop_order post object.
     * @since 1.2.4
     * @return void
     */
    public static function recurring_order_totals_meta_box_section($post_id)
    {
        global $woocommerce, $wpdb, $current_screen;
        $order = new WC_Order($post_id);
        $display_none = ' style="display: none"';
        $contains_subscription = self::order_contains_subscription($order) ? true : false;
        $chosen_gateway = WC_Subscriptions_Payment_Gateways::get_payment_gateway(get_post_meta($post_id, '_recurring_payment_method', true));
        $manual_renewal = self::requires_manual_renewal($post_id);
        $changes_supported = $chosen_gateway === false || $manual_renewal == 'true' || $chosen_gateway->supports('subscription_amount_changes') ? 'true' : 'false';
        $data = get_post_meta($post_id);
        if (WC_Subscriptions::is_woocommerce_pre('2.2')) {
            ?>
	<div class="clear"></div>
</div>
		<?php 
        }
        ?>
<div id="gateway_support"<?php 
        if (!$contains_subscription) {
            echo $display_none;
        }
        ?>
>
	<input type="hidden" name="gateway_supports_subscription_changes" value="<?php 
        echo $changes_supported;
        ?>
">
	<div class="error"<?php 
        if (!$contains_subscription || $changes_supported == 'true') {
            echo $display_none;
        }
        ?>
>
		<p><?php 
        printf(__('The %s payment gateway is used to charge automatic subscription payments for this order. This gateway <strong>does not</strong> support changing a subscription\'s details.', 'woocommerce-subscriptions'), get_post_meta($post_id, '_recurring_payment_method_title', true));
        ?>
</p>
		<p>
			<?php 
        _e('It is strongly recommended you <strong>do not change</strong> any of the recurring totals or subscription item\'s details.', 'woocommerce-subscriptions');
        ?>
			<a href="http://docs.woothemes.com/document/subscriptions/add-or-modify-a-subscription/#section-4"><?php 
        _e('Learn More', 'woocommerce-subscriptions');
        ?>
 &raquo;</a>
		</p>
	</div>
</div>
<div id="recurring_order_totals"<?php 
        if (!$contains_subscription) {
            echo $display_none;
        }
        ?>
>
	<?php 
        if (WC_Subscriptions::is_woocommerce_pre('2.2')) {
            ?>
	<h3><?php 
            _e('Recurring Totals', 'woocommerce-subscriptions');
            ?>
</h3>
	<?php 
        }
        ?>

	<?php 
        if ('add' !== $current_screen->action) {
            // Can't add recurring shipping to a manually added subscription
            ?>
	<div class="totals_group">
		<h4><span class="tax_total_display inline_total"></span><?php 
            _e('Shipping for Renewal Orders', 'woocommerce-subscriptions');
            ?>
</h4>
		<div id="recurring_shipping_rows">
		<?php 
            if (!WC_Subscriptions::is_woocommerce_pre('2.1')) {
                if ($woocommerce->shipping()) {
                    $shipping_methods = $woocommerce->shipping->load_shipping_methods();
                }
                foreach (self::get_recurring_shipping_methods($order) as $item_id => $item) {
                    $chosen_method = $item['method_id'];
                    $shipping_title = $item['name'];
                    $shipping_cost = $item['cost'];
                    include plugin_dir_path(WC_Subscriptions::$plugin_file) . 'templates/admin/post-types/writepanels/order-shipping-html.php';
                }
                // Shipping created pre 2.1
                if (isset($data['_recurring_shipping_method'])) {
                    $item_id = 'old';
                    // so that when saving, we know to delete the data in the old form
                    $chosen_method = !empty($data['_recurring_shipping_method'][0]) ? $data['_recurring_shipping_method'][0] : '';
                    $shipping_title = !empty($data['_recurring_shipping_method_title'][0]) ? $data['_recurring_shipping_method_title'][0] : '';
                    $shipping_cost = !empty($data['_order_recurring_shipping_total'][0]) ? $data['_order_recurring_shipping_total'][0] : '0.00';
                    include plugin_dir_path(WC_Subscriptions::$plugin_file) . 'templates/admin/post-types/writepanels/order-shipping-html.php';
                }
                ?>
		<?php 
            } else {
                // WC < 2.1
                ?>
			<ul class="totals">
				<li class="wide">
					<label><?php 
                _e('Label:', 'woocommerce-subscriptions');
                ?>
</label>
					<input type="text" id="_recurring_shipping_method_title" name="_recurring_shipping_method_title" placeholder="<?php 
                _e('The shipping title for renewal orders', 'woocommerce-subscriptions');
                ?>
" value="<?php 
                echo $order->recurring_shipping_method_title;
                ?>
" class="first" />
				</li>

				<li class="left">
					<label><?php 
                _e('Cost:', 'woocommerce-subscriptions');
                ?>
</label>
					<input type="text" id="_order_recurring_shipping_total" name="_order_recurring_shipping_total" placeholder="0.00 <?php 
                _e('(ex. tax)', 'woocommerce-subscriptions');
                ?>
" value="<?php 
                echo self::get_recurring_shipping_total($order);
                ?>
" class="first" />
				</li>

				<li class="right">
					<label><?php 
                _e('Method:', 'woocommerce-subscriptions');
                ?>
</label>
					<select name="_recurring_shipping_method" id="_recurring_shipping_method" class="first">
						<option value=""><?php 
                _e('N/A', 'woocommerce-subscriptions');
                ?>
</option>
						<?php 
                $chosen_shipping_method = $order->recurring_shipping_method;
                $found_method = false;
                if ($woocommerce->shipping()) {
                    foreach ($woocommerce->shipping->load_shipping_methods() as $method) {
                        if (strpos($chosen_shipping_method, $method->id) === 0) {
                            $value = $chosen_shipping_method;
                        } else {
                            $value = $method->id;
                        }
                        echo '<option value="' . esc_attr($value) . '" ' . selected($chosen_shipping_method == $value, true, false) . '>' . esc_html($method->get_title()) . '</option>';
                        if ($chosen_shipping_method == $value) {
                            $found_method = true;
                        }
                    }
                }
                if (!$found_method && !empty($chosen_shipping_method)) {
                    echo '<option value="' . esc_attr($chosen_shipping_method) . '" selected="selected">' . __('Other', 'woocommerce-subscriptions') . '</option>';
                } else {
                    echo '<option value="other">' . __('Other', 'woocommerce-subscriptions') . '</option>';
                }
                ?>
					</select>
				</li>
			</ul>
		<?php 
            }
            // ! WC_Subscriptions::is_woocommerce_pre( '2.1' )
            ?>
		</div>
		<div class="clear"></div>
	</div>
	<?php 
        }
        ?>

	<?php 
        if ('yes' == get_option('woocommerce_calc_taxes')) {
            ?>

	<div class="totals_group tax_rows_group">
		<h4>
			<span class="tax_total_display inline_total"></span>
			<?php 
            _e('Recurring Taxes', 'woocommerce-subscriptions');
            ?>
			<a class="tips" data-tip="<?php 
            _e('These rows contain taxes included in each recurring amount for this subscription. This allows you to display multiple or compound taxes rather than a single total on future subscription renewal orders.', 'woocommerce-subscriptions');
            ?>
" href="#">[?]</a>
		</h4>
		<div id="recurring_tax_rows" class="total_rows">
			<?php 
            $loop = 0;
            $taxes = self::get_recurring_taxes($order);
            if (is_array($taxes) && sizeof($taxes) > 0) {
                $rates = $wpdb->get_results("SELECT tax_rate_id, tax_rate_country, tax_rate_state, tax_rate_name, tax_rate_priority FROM {$wpdb->prefix}woocommerce_tax_rates ORDER BY tax_rate_name");
                $tax_codes = array();
                foreach ($rates as $rate) {
                    $code = array();
                    $code[] = $rate->tax_rate_country;
                    $code[] = $rate->tax_rate_state;
                    $code[] = $rate->tax_rate_name ? sanitize_title($rate->tax_rate_name) : 'TAX';
                    $code[] = absint($rate->tax_rate_priority);
                    $tax_codes[$rate->tax_rate_id] = strtoupper(implode('-', array_filter($code)));
                }
                foreach ($taxes as $item_id => $item) {
                    include plugin_dir_path(WC_Subscriptions::$plugin_file) . 'templates/admin/post-types/writepanels/order-tax-html.php';
                    $loop++;
                }
            }
            ?>
		</div>
		<h4 style="padding-bottom: 10px;"><a href="#" class="add_recurring_tax_row"><?php 
            _e('+ Add tax row', 'woocommerce-subscriptions');
            ?>
</a></h4>
		<div class="clear"></div>
	</div>

	<?php 
            if (WC_Subscriptions::is_woocommerce_pre('2.1')) {
                ?>
	<div class="totals_group">
		<h4><span class="tax_total_display inline_total"></span><?php 
                _e('Tax Totals', 'woocommerce-subscriptions');
                ?>
</h4>
		<ul class="totals">

			<li class="left">
				<label><?php 
                _e('Recurring Sales Tax:', 'woocommerce-subscriptions');
                ?>
</label>
				<input type="number" step="any" min="0" id="_order_recurring_tax_total" name="_order_recurring_tax_total" placeholder="0.00" value="<?php 
                echo self::get_recurring_total_tax($order);
                ?>
" class="calculated" />
			</li>

			<li class="right">
				<label><?php 
                _e('Shipping Tax:', 'woocommerce-subscriptions');
                ?>
</label>
				<input type="number" step="any" min="0" id="_order_recurring_shipping_tax_total" name="_order_recurring_shipping_tax_total" placeholder="0.00" value="<?php 
                echo self::get_recurring_shipping_tax_total($order);
                ?>
" class="calculated" />
			</li>

		</ul>
		<div class="clear"></div>
	</div>
	<?php 
            }
            // WC_Subscriptions::is_woocommerce_pre( '2.1' )
            ?>

	<?php 
        }
        // woocommerce_calc_taxes
        ?>

	<div class="totals_group">
		<h4><label for="_order_recurring_discount_total"><?php 
        _e('Recurring Order Discount', 'woocommerce-subscriptions');
        ?>
 <a class="tips" data-tip="<?php 
        _e('The discounts applied to each recurring payment charged in the future.', 'woocommerce-subscriptions');
        ?>
" href="#">[?]</a></label></h4>
		<input type="text" class="wc_input_price"  id="_order_recurring_discount_total" name="_order_recurring_discount_total" placeholder="<?php 
        echo wc_format_localized_price(0);
        ?>
" value="<?php 
        echo esc_attr(wc_format_localized_price(self::get_recurring_discount_total($order)));
        ?>
" style="margin: 6px 0 10px;"/>
	</div>

	<div class="totals_group">
		<h4><label for="_order_recurring_total"><?php 
        _e('Recurring Order Total', 'woocommerce-subscriptions');
        ?>
 <a class="tips" data-tip="<?php 
        _e('The total amounts charged for each future recurring payment.', 'woocommerce-subscriptions');
        ?>
" href="#">[?]</a></label></h4>
		<input type="text" id="_order_recurring_total" name="_order_recurring_total" placeholder="<?php 
        echo wc_format_localized_price(0);
        ?>
" value="<?php 
        echo esc_attr(wc_format_localized_price(self::get_recurring_total($order)));
        ?>
" class="calculated"  style="margin: 6px 0 10px;"/>
	</div>

	<div class="totals_group">
		<h4><?php 
        _e('Recurring Payment Method:', 'woocommerce-subscriptions');
        ?>
</h4>
		<div class="<?php 
        echo $order->recurring_payment_method;
        ?>
" style="padding-top: 4px; font-style: italic; margin: 2px 0 10px;"><?php 
        echo $manual_renewal || empty($order->recurring_payment_method) ? __('Manual', 'woocommerce-subscriptions') : $order->recurring_payment_method_title;
        ?>
</div>
	</div>
		<?php 
        if (!WC_Subscriptions::is_woocommerce_pre('2.2')) {
            ?>
</div>
		<?php 
        }
    }
 /**
  * Apply sign up fee or recurring fee discount
  *
  * @since 1.2
  */
 public static function apply_subscription_discount($original_price, $cart_item, $cart)
 {
     _deprecated_function(__METHOD__, '2.0.10', 'Have moved to filtering on "woocommerce_coupon_get_discount_amount" to return discount amount. See: ' . __CLASS__ . '::get_discount_amount()');
     $product_id = $cart_item['data']->is_type(array('subscription_variation')) ? $cart_item['data']->variation_id : $cart_item['data']->id;
     if (!WC_Subscriptions_Product::is_subscription($product_id)) {
         return $original_price;
     }
     $price = $calculation_price = $original_price;
     $calculation_type = WC_Subscriptions_Cart::get_calculation_type();
     if (!empty($cart->applied_coupons)) {
         foreach ($cart->applied_coupons as $code) {
             $coupon = new WC_Coupon($code);
             // Pre 2.5 is_valid_for_product() does not use wc_get_product_coupon_types()
             if (WC_Subscriptions::is_woocommerce_pre('2.5')) {
                 $is_valid_for_product = true;
             } else {
                 $is_valid_for_product = $coupon->is_valid_for_product(wc_get_product($product_id), $cart_item);
             }
             if ($coupon->apply_before_tax() && $coupon->is_valid() && $is_valid_for_product) {
                 $apply_recurring_coupon = $apply_recurring_percent_coupon = $apply_initial_coupon = $apply_initial_percent_coupon = false;
                 // Apply recurring fee discounts to recurring total calculations
                 if ('recurring_total' == $calculation_type) {
                     $apply_recurring_coupon = 'recurring_fee' == $coupon->type ? true : false;
                     $apply_recurring_percent_coupon = 'recurring_percent' == $coupon->type ? true : false;
                 }
                 if ('none' == $calculation_type) {
                     // If all items have a free trial we don't need to apply recurring coupons to the initial total
                     if (!WC_Subscriptions_Cart::all_cart_items_have_free_trial()) {
                         if ('recurring_fee' == $coupon->type) {
                             $apply_initial_coupon = true;
                         }
                         if ('recurring_percent' == $coupon->type) {
                             $apply_initial_percent_coupon = true;
                         }
                     }
                     // Apply sign-up discounts to initial total
                     if (!empty($cart_item['data']->subscription_sign_up_fee)) {
                         if ('sign_up_fee' == $coupon->type) {
                             $apply_initial_coupon = true;
                         }
                         if ('sign_up_fee_percent' == $coupon->type) {
                             $apply_initial_percent_coupon = true;
                         }
                         $calculation_price = $cart_item['data']->subscription_sign_up_fee;
                     }
                 }
                 if ($apply_recurring_coupon || $apply_initial_coupon) {
                     $discount_amount = $calculation_price < $coupon->amount ? $calculation_price : $coupon->amount;
                     // Recurring coupons only apply when there is no free trial (carts can have a mix of free trial and non free trial items)
                     if ($apply_initial_coupon && 'recurring_fee' == $coupon->type && !empty($cart_item['data']->subscription_trial_length)) {
                         $discount_amount = 0;
                     }
                     $cart->discount_cart = $cart->discount_cart + $discount_amount * $cart_item['quantity'];
                     $cart = self::increase_coupon_discount_amount($cart, $coupon->code, $discount_amount * $cart_item['quantity']);
                     $price = $price - $discount_amount;
                 } elseif ($apply_recurring_percent_coupon) {
                     $discount_amount = round($calculation_price / 100 * $coupon->amount, WC()->cart->dp);
                     $cart->discount_cart = $cart->discount_cart + $discount_amount * $cart_item['quantity'];
                     $cart = self::increase_coupon_discount_amount($cart, $coupon->code, $discount_amount * $cart_item['quantity']);
                     $price = $price - $discount_amount;
                 } elseif ($apply_initial_percent_coupon) {
                     // Recurring coupons only apply when there is no free trial (carts can have a mix of free trial and non free trial items)
                     if ('recurring_percent' == $coupon->type && empty($cart_item['data']->subscription_trial_length)) {
                         $amount_to_discount = $cart_item['data']->subscription_price;
                     } else {
                         $amount_to_discount = 0;
                     }
                     // Sign up fee coupons only apply to sign up fees
                     if ('sign_up_fee_percent' == $coupon->type) {
                         $amount_to_discount = $cart_item['data']->subscription_sign_up_fee;
                     }
                     $discount_amount = round($amount_to_discount / 100 * $coupon->amount, WC()->cart->dp);
                     $cart->discount_cart = $cart->discount_cart + $discount_amount * $cart_item['quantity'];
                     $cart = self::increase_coupon_discount_amount($cart, $coupon->code, $discount_amount * $cart_item['quantity']);
                     $price = $price - $discount_amount;
                 }
             }
         }
         if ($price < 0) {
             $price = 0;
         }
     }
     return $price;
 }
 /**
  * When a subscription switch is added to the cart, store a record of pertinent meta about the switch.
  *
  * @since 1.4
  */
 public static function set_switch_details_in_cart($cart_item_data, $product_id, $variation_id)
 {
     try {
         if (!isset($_GET['switch-subscription'])) {
             return $cart_item_data;
         }
         $subscription = wcs_get_subscription($_GET['switch-subscription']);
         // Requesting a switch for someone elses subscription
         if (!current_user_can('switch_shop_subscription', $subscription->id)) {
             WC_Subscriptions::add_notice(__('You can not switch this subscription. It appears you do not own the subscription.', 'woocommerce-subscriptions'), 'error');
             WC()->cart->empty_cart(true);
             wp_redirect(get_permalink($subscription['product_id']));
             exit;
         }
         $item = wcs_get_order_item(absint($_GET['item']), $subscription);
         // Else it's a valid switch
         $product = wc_get_product($item['product_id']);
         $child_products = 0 !== $product->post->post_parent ? wc_get_product($product->post->post_parent)->get_children() : array();
         if ($product_id != $item['product_id'] && !in_array($item['product_id'], $child_products)) {
             return $cart_item_data;
         }
         $next_payment_timestamp = $subscription->get_time('next_payment');
         // If there are no more payments due on the subscription, because we're in the last billing period, we need to use the subscription's expiration date, not next payment date
         if (false == $next_payment_timestamp) {
             $next_payment_timestamp = $subscription->get_time('end');
         }
         $cart_item_data['subscription_switch'] = array('subscription_id' => $subscription->id, 'item_id' => absint($_GET['item']), 'next_payment_timestamp' => $next_payment_timestamp, 'upgraded_or_downgraded' => '');
         return $cart_item_data;
     } catch (Exception $e) {
         WC_Subscriptions::add_notice(__('There was an error locating the switch details.', 'woocommerce-subscriptions'), 'error');
         WC()->cart->empty_cart(true);
         wp_redirect(get_permalink(wc_get_page_id('cart')));
         exit;
     }
 }
Exemple #16
0
	
		<div class="text-center"><a href="#" class="back_to_account"><?php 
_e("<small>Back to</small> My Account", THB_THEME_NAME);
?>
</a></div>
		<?php 
wc_get_template('myaccount/form-edit-account.php');
?>
	
	</div>
	
	<?php 
if ($myaccount_subscriptions == 'on') {
    ?>
	<div class="tab-pane custom_scroll" id="my-subscriptions">
	
		<div class="text-center"><a href="#" class="back_to_account"><?php 
    _e("<small>Back to</small> My Account", THB_THEME_NAME);
    ?>
</a></div>
		<?php 
    if (class_exists('WC_Subscriptions')) {
        WC_Subscriptions::get_my_subscriptions_template();
    }
    ?>
	
	</div>
	<?php 
}
?>
</section>	
        do_action('woocommerce_subscriptions_deactivated');
    }
    /**
     * Called on plugins_loaded to load any translation files.
     *
     * @since 1.1
     */
    public static function load_plugin_textdomain()
    {
        $locale = apply_filters('plugin_locale', get_locale(), 'woocommerce-subscriptions');
        // Allow upgrade safe, site specific language files in /wp-content/languages/woocommerce-subscriptions/
        load_textdomain('woocommerce-subscriptions', WP_LANG_DIR . '/woocommerce/woocommerce-subscriptions-' . $locale . '.mo');
        $plugin_rel_path = apply_filters('woocommerce_subscriptions_translation_file_rel_path', dirname(plugin_basename(__FILE__)) . '/languages');
        // Then check for a language file in /wp-content/plugins/woocommerce-subscriptions/languages/ (this will be overriden by any file already loaded)
        load_plugin_textdomain(self::$text_domain, false, $plugin_rel_path);
    }
    /* Deprecated Functions */
    /**
     * Was called when a plugin is activated using official register_activation_hook() API
     *
     * Upgrade routine is now in @see maybe_activate_woocommerce_subscriptions()
     *
     * @since 1.0
     */
    public static function activate_woocommerce_subscriptions()
    {
        _deprecated_function(__CLASS__ . '::' . __FUNCTION__, '1.1', __CLASS__ . '::maybe_activate_woocommerce_subscriptions()');
    }
}
WC_Subscriptions::init();
 /**
  * If the order is a renewal order, don't send core emails.
  *
  * @param int $user_id The ID of the user who the subscription belongs to
  * @param string $subscription_key A subscription key of the form created by @see self::get_subscription_key()
  * @return void
  */
 public static function maybe_reattach_woocommerce_email($order_id)
 {
     global $woocommerce;
     if (WC_Subscriptions_Renewal_Order::is_renewal($order_id, array('order_role' => 'child')) || WC_Subscriptions_Switcher::order_contains_subscription_switch($order_id)) {
         if (WC_Subscriptions::is_woocommerce_pre('2.3')) {
             add_action(current_filter(), array($woocommerce, 'send_transactional_email'));
         } else {
             add_action(current_filter(), array('WC_Emails', 'send_transactional_email'));
         }
     }
 }
	function woo_ce_return_count( $export_type = '', $args = array() ) {

		global $wpdb;

		$count_sql = null;
		$woocommerce_version = woo_get_woo_version();

		switch( $export_type ) {

			case 'product':
				$post_type = array( 'product', 'product_variation' );
				$args = array(
					'post_type' => $post_type,
					'posts_per_page' => 1,
					'fields' => 'ids',
					'suppress_filters' => 1
				);
				$count_query = new WP_Query( $args );
				$count = $count_query->found_posts;
				break;

			case 'category':
				$term_taxonomy = 'product_cat';
				if( taxonomy_exists( $term_taxonomy ) )
					$count = wp_count_terms( $term_taxonomy );
				break;

			case 'tag':
				$term_taxonomy = 'product_tag';
				if( taxonomy_exists( $term_taxonomy ) )
					$count = wp_count_terms( $term_taxonomy );
				break;

			case 'brand':
				$term_taxonomy = apply_filters( 'woo_ce_brand_term_taxonomy', 'product_brand' );
				if( taxonomy_exists( $term_taxonomy ) )
					$count = wp_count_terms( $term_taxonomy );
				break;

			case 'order':
				$post_type = 'shop_order';
				// Check if this is a WooCommerce 2.2+ instance (new Post Status)
				if( version_compare( $woocommerce_version, '2.2' ) >= 0 )
					$post_status = ( function_exists( 'wc_get_order_statuses' ) ? apply_filters( 'woo_ce_order_post_status', array_keys( wc_get_order_statuses() ) ) : 'any' );
				else
					$post_status = apply_filters( 'woo_ce_order_post_status', woo_ce_post_statuses() );
				$args = array(
					'post_type' => $post_type,
					'posts_per_page' => 1,
					'post_status' => $post_status,
					'fields' => 'ids'
				);
				$count_query = new WP_Query( $args );
				$count = $count_query->found_posts;
				break;

			case 'customer':
				if( $users = woo_ce_return_count( 'user' ) > 1000 ) {
					$count = sprintf( '~%s+', 1000 );
				} else {
					$post_type = 'shop_order';
					$args = array(
						'post_type' => $post_type,
						'posts_per_page' => -1,
						'fields' => 'ids'
					);
					// Check if this is a WooCommerce 2.2+ instance (new Post Status)
					if( version_compare( $woocommerce_version, '2.2' ) >= 0 ) {
						$args['post_status'] = apply_filters( 'woo_ce_customer_post_status', array( 'wc-pending', 'wc-on-hold', 'wc-processing', 'wc-completed' ) );
					} else {
						$args['post_status'] = apply_filters( 'woo_ce_customer_post_status', woo_ce_post_statuses() );
						$args['tax_query'] = array(
							array(
								'taxonomy' => 'shop_order_status',
								'field' => 'slug',
								'terms' => array( 'pending', 'on-hold', 'processing', 'completed' )
							),
						);
					}
					$order_ids = new WP_Query( $args );
					$count = $order_ids->found_posts;
					if( $count > 100 ) {
						$count = sprintf( '~%s', $count );
					} else {
						$customers = array();
						if( $order_ids->posts ) {
							foreach( $order_ids->posts as $order_id ) {
								$email = get_post_meta( $order_id, '_billing_email', true );
								if( !in_array( $email, $customers ) )
									$customers[$order_id] = $email;
								unset( $email );
							}
							$count = count( $customers );
						}
					}
				}
/*
				if( false ) {
					$orders = get_posts( $args );
					if( $orders ) {
						$customers = array();
						foreach( $orders as $order ) {
							$order->email = get_post_meta( $order->ID, '_billing_email', true );
							if( empty( $order->email ) ) {
								if( $order->user_id = get_post_meta( $order->ID, '_customer_user', true ) ) {
									$user = get_userdata( $order->user_id );
									if( $user )
										$order->email = $user->user_email;
									unset( $user );
								} else {
									$order->email = '-';
								}
							}
							if( !in_array( $order->email, $customers ) ) {
								$customers[$order->ID] = $order->email;
								$count++;
							}
						}
						unset( $orders, $order );
					}
				}
*/
				break;

			case 'user':
				if( $users = count_users() )
					$count = $users['total_users'];
				break;

			case 'coupon':
				$post_type = 'shop_coupon';
				if( post_type_exists( $post_type ) )
					$count = wp_count_posts( $post_type );
				break;

			case 'subscription':
				$count = 0;
				// Check that WooCommerce Subscriptions exists
				if( class_exists( 'WC_Subscriptions' ) ) {
					if( method_exists( 'WC_Subscriptions', 'is_large_site' ) ) {
						// Does this store have roughly more than 3000 Subscriptions
						if( false === WC_Subscriptions::is_large_site() ) {
							if( class_exists( 'WC_Subscriptions_Manager' ) ) {
								// Check that the get_all_users_subscriptions() function exists
								if( method_exists( 'WC_Subscriptions_Manager', 'get_all_users_subscriptions' ) ) {
									if( $subscriptions = WC_Subscriptions_Manager::get_all_users_subscriptions() ) {
										foreach( $subscriptions as $key => $user_subscription ) {
											if( !empty( $user_subscription ) ) {
												foreach( $user_subscription as $subscription )
													$count++;
											}
										}
										unset( $subscriptions, $subscription, $user_subscription );
									}
								}
							}
						} else {
							if( method_exists( 'WC_Subscriptions', 'get_total_subscription_count' ) )
								$count = WC_Subscriptions::get_total_subscription_count();
							else
								$count = "~2500";
						}
					}
				}
				break;

			case 'product_vendor':
				$term_taxonomy = 'shop_vendor';
				if( taxonomy_exists( $term_taxonomy ) )
					$count = wp_count_terms( $term_taxonomy );
				break;

			case 'commission':
				$post_type = 'shop_commission';
				if( post_type_exists( $post_type ) )
					$count = wp_count_posts( $post_type );
				break;

			case 'shipping_class':
				$term_taxonomy = 'product_shipping_class';
				if( taxonomy_exists( $term_taxonomy ) )
					$count = wp_count_terms( $term_taxonomy );
				break;

			case 'attribute':
				$attributes = ( function_exists( 'wc_get_attribute_taxonomies' ) ? wc_get_attribute_taxonomies() : array() );
				$count = count( $attributes );
				break;

		}
		if( isset( $count ) || $count_sql ) {
			if( isset( $count ) ) {
				if( is_object( $count ) ) {
					$count = (array)$count;
					$count = (int)array_sum( $count );
				}
				return $count;
			} else {
				if( $count_sql )
					$count = $wpdb->get_var( $count_sql );
				else
					$count = 0;
			}
			return $count;
		} else {
			return 0;
		}

	}
/**
 * Update recurring tax for subscriptions
 * Not executed if Subscriptions plugin is not active
 *
 * @since 4.4
 * @return void
 */
function wootax_update_recurring_tax()
{
    global $wpdb;
    // Exit if subs is not active
    if (!WT_SUBS_ACTIVE) {
        return;
    }
    // Find date/time 12 hours from now
    $twelve_hours = mktime(date('H') + 12);
    $date = new DateTime(date('c', $twelve_hours));
    $date = $date->format('Y-m-d H:i:s');
    // Set up logger
    $logger = false;
    if (WT_LOG_REQUESTS) {
        $logger = class_exists('WC_Logger') ? new WC_Logger() : WC()->logger();
        $logger->add('wootax', 'Starting recurring tax update. Subscriptions with payments due before ' . $date . ' are being considered.');
    }
    // Get all scheduled "scheduled_subscription_payment" actions with post_date <= $twelve_hours
    $scheduled = $wpdb->get_results($wpdb->prepare("SELECT ID, post_content FROM {$wpdb->posts} WHERE post_status = %s AND post_title = %s AND post_date <= %s", "pending", "scheduled_subscription_payment", $date));
    // Update recurring totals if necessary
    if (count($scheduled) > 0) {
        // This will hold any warning messages that need to be sent to the admin
        $warnings = array();
        foreach ($scheduled as $action) {
            $temp_warnings = array();
            $show_warnings = false;
            // Run json_decode on post_content to extract user_id and subscription_key
            $args = json_decode($action->post_content);
            // Parse subscription_key to get order_id/product_id (format: ORDERID_PRODUCTID)
            $subscription_key = $args->subscription_key;
            $key_parts = explode('_', $subscription_key);
            $order_id = (int) $key_parts[0];
            $product_id = (int) $key_parts[1];
            if (get_post_status($order_id) == false) {
                continue;
                // Skip if the order no longer exists
            }
            // Determine if changes to subscription amounts are allowed by the current gateway
            $chosen_gateway = WC_Subscriptions_Payment_Gateways::get_payment_gateway(get_post_meta($order_id, '_recurring_payment_method', true));
            $manual_renewal = WC_Subscriptions_Order::requires_manual_renewal($order_id);
            $changes_supported = $chosen_gateway === false || $manual_renewal == 'true' || $chosen_gateway->supports('subscription_amount_changes') ? true : false;
            // Load order
            $order = WT_Orders::get_order($order_id);
            // Collect data for Lookup request
            $item_data = $type_array = array();
            // Add subscription
            $product = WC_Subscriptions::get_product($product_id);
            // Get order item ID
            $item_id = $wpdb->get_var("SELECT i.order_item_id FROM {$wpdb->prefix}woocommerce_order_items i LEFT JOIN {$wpdb->prefix}woocommerce_order_itemmeta im ON im.order_item_id = i.order_item_id WHERE im.meta_key = '_product_id' AND im.meta_value = {$product_id} AND i.order_id = {$order_id}");
            // Get price
            $recurring_subtotal = $order->get_item_meta($item_id, '_recurring_line_subtotal');
            $regular_subtotal = $order->get_item_meta($item_id, '_line_subtotal');
            $price = $recurring_subtotal === '0' || !empty($recurring_subtotal) ? $recurring_subtotal : $regular_subtotal;
            // Special case: If _subscription_sign_up_fee is set and $price is equal to its value, fall back to product price
            if ($order->get_item_meta($item_id, '_subscription_sign_up_fee') == $price) {
                $price = $product->get_price();
            }
            $item_info = array('Index' => '', 'ItemID' => $item_id, 'Qty' => 1, 'Price' => $price, 'Type' => 'cart');
            $tic = get_post_meta($product_id, 'wootax_tic', true);
            if (!empty($tic) && $tic) {
                $item_info['TIC'] = $tic;
            }
            $item_data[] = $item_info;
            $type_array[$item_id] = 'cart';
            // Add recurring shipping items
            foreach ($order->order->get_items('recurring_shipping') as $item_id => $shipping) {
                $item_data[] = array('Index' => '', 'ItemID' => $item_id, 'TIC' => WT_SHIPPING_TIC, 'Qty' => 1, 'Price' => $shipping['cost'], 'Type' => 'shipping');
                $type_array[$item_id] = 'shipping';
            }
            // Reset "captured" meta so lookup always sent
            $captured = WT_Orders::get_meta($order_id, 'captured');
            WT_Orders::update_meta($order_id, 'captured', false);
            // Issue Lookup request
            $res = $order->do_lookup($item_data, $type_array, true);
            // Set "captured" back to original value
            WT_Orders::update_meta($order_id, 'captured', $captured);
            // If lookup is successful, use result to update recurring tax totals as described here: http://docs.woothemes.com/document/subscriptions/add-or-modify-a-subscription/#change-recurring-total
            if (is_array($res)) {
                // Find recurring tax item and determine original tax/shipping tax totals
                $wootax_item_id = $wpdb->get_var($wpdb->prepare("SELECT i.order_item_id FROM {$wpdb->prefix}woocommerce_order_items i LEFT JOIN {$wpdb->prefix}woocommerce_order_itemmeta im ON im.order_item_id = i.order_item_id WHERE im.meta_key = %s AND im.meta_value = %d AND i.order_id = %d AND i.order_item_type = %s", "rate_id", WT_RATE_ID, $order_id, "recurring_tax"));
                $old_tax = empty($wootax_item_id) ? 0 : $order->get_item_meta($wootax_item_id, 'tax_amount');
                $old_shipping_tax = empty($wootax_item_id) ? 0 : $order->get_item_meta($wootax_item_id, 'shipping_tax_amount');
                // Find new tax/shipping tax totals
                // Update _recurring_line_tax meta for each item
                $tax = $shipping_tax = 0;
                foreach ($res as $item) {
                    $item_id = $item->ItemID;
                    $item_tax = $item->TaxAmount;
                    if ($type_array[$item_id] == 'shipping') {
                        $shipping_tax += $item_tax;
                    } else {
                        $tax += $item_tax;
                    }
                    if ($changes_supported) {
                        wc_update_order_item_meta($item_id, '_recurring_line_tax', $item_tax);
                        wc_update_order_item_meta($item_id, '_recurring_line_subtotal_tax', $item_tax);
                    } else {
                        $temp_warnings[] = 'Recurring tax for item #' . $item_id . ' changed to ' . wc_round_tax_total($item_tax);
                    }
                }
                // Update recurring tax if necessary
                if ($old_tax != $tax || $old_shipping_tax != $shipping_tax) {
                    if ($changes_supported) {
                        if (!empty($wootax_item_id)) {
                            wc_update_order_item_meta($wootax_item_id, 'tax_amount', $tax);
                            wc_update_order_item_meta($wootax_item_id, 'cart_tax', $tax);
                            wc_update_order_item_meta($wootax_item_id, 'shipping_tax_amount', $shipping_tax);
                            wc_update_order_item_meta($wootax_item_id, 'shipping_tax', $shipping_tax);
                        }
                        // Determine rounded difference in old/new tax totals
                        $tax_diff = $tax + $shipping_tax - ($old_tax + $old_shipping_tax);
                        $rounded_tax_diff = wc_round_tax_total($tax_diff);
                        // Set new recurring total by adding difference between old and new tax to existing total
                        $new_recurring_total = get_post_meta($order_id, '_order_recurring_total', true) + $rounded_tax_diff;
                        update_post_meta($order_id, '_order_recurring_total', $new_recurring_total);
                        if ($logger) {
                            $logger->add('wootax', 'Set recurring total for order ' . $order_id . ' to: ' . $new_recurring_total);
                        }
                    } else {
                        $temp_warnings[] = 'Total recurring tax changed from ' . wc_round_tax_total($old_tax) . ' to ' . wc_round_tax_total($tax);
                        $temp_warnings[] = 'Total recurring shipping tax changed from ' . wc_round_tax_total($old_shipping_tax) . ' to ' . wc_round_tax_total($shipping_tax);
                        $show_warnings = true;
                    }
                }
                // Add to warnings array if necessary
                if ($show_warnings) {
                    $warnings[$order_id] = $temp_warnings;
                }
            }
        }
        // Send out a single warning email to the admin if necessary
        // Ex: Email sent if a change in tax rates is detected and the gateway used by an order doesn't allow modification of sub. details
        if (count($warnings) > 0) {
            $email = wootax_get_notification_email();
            if (!empty($email) && is_email($email)) {
                $subject = 'WooTax Warning: Recurring Tax Totals Need To Be Updated';
                $message = 'Hello,' . "\r\n\r\n" . 'During a routine check on ' . date('m/d/Y') . ', WooTax discovered ' . count($warnings) . ' subscription orders whose recurring tax totals need to be updated. Unfortunately, the payment gateway(s) used for these orders does not allow subscription details to be altered, so the required changes must be implemented manually. All changes are listed below for your convenience.' . "\r\n\r\n";
                foreach ($warnings as $order_id => $errors) {
                    $message .= 'Order ' . $order_id . ': ' . "\r\n\r\n";
                    foreach ($errors as $error) {
                        $message .= '- ' . $error . "\r\n";
                    }
                    $message .= "\r\n\r\n";
                }
                $message .= 'For assistance, please contact the WooTax support team at sales@wootax.com.';
                wp_mail($email, $subject, $message);
            }
        }
    } else {
        if ($logger) {
            $logger->add('wootax', 'Ending recurring tax update. No subscriptions due before ' . $date . '.');
        }
    }
}
 /**
  * Process the change payment form.
  *
  * Based on the @see woocommerce_pay_action() function.
  *
  * @access public
  * @return void
  * @since 1.4
  */
 public static function change_payment_method_via_pay_shortcode()
 {
     global $woocommerce;
     if (isset($_POST['woocommerce_change_payment']) && wp_verify_nonce($_POST['_wpnonce'], 'woocommerce-change_payment')) {
         $subscription_key = $_POST['woocommerce_change_payment'];
         // Pay for existing order
         $order_key = isset($_GET['key']) ? $_GET['key'] : $_GET['order'];
         $order_id = absint($_GET['order_id']);
         $order = new WC_Order($order_id);
         do_action('woocommerce_subscriptions_change_payment_method_via_pay_shortcode', $subscription_key, $order);
         ob_start();
         if ($order->id == $order_id && $order->order_key == $order_key) {
             // Set customer location to order location
             if ($order->billing_country) {
                 $woocommerce->customer->set_country($order->billing_country);
             }
             if ($order->billing_state) {
                 $woocommerce->customer->set_state($order->billing_state);
             }
             if ($order->billing_postcode) {
                 $woocommerce->customer->set_postcode($order->billing_postcode);
             }
             if ($order->billing_city) {
                 $woocommerce->customer->set_city($order->billing_city);
             }
             // Update payment method
             $new_payment_method = woocommerce_clean($_POST['payment_method']);
             self::update_recurring_payment_method($subscription_key, $order, $new_payment_method);
             $available_gateways = $woocommerce->payment_gateways->get_available_payment_gateways();
             // Validate
             $available_gateways[$new_payment_method]->validate_fields();
             // Process payment for the new method (with a $0 order total)
             if (function_exists('wc_notice_count')) {
                 // WC 2.1
                 if (wc_notice_count('error') == 0) {
                     $result = $available_gateways[$new_payment_method]->process_payment($order_id);
                     // Redirect to success/confirmation/payment page
                     if ($result['result'] == 'success') {
                         WC_Subscriptions::add_notice(__('Payment method updated.', 'woocommerce-subscriptions'), 'success');
                         wp_redirect($result['redirect']);
                         exit;
                     }
                 }
             } else {
                 if ($woocommerce->error_count() == 0) {
                     $result = $available_gateways[$new_payment_method]->process_payment($order_id);
                     // Redirect to success/confirmation/payment page
                     if ($result['result'] == 'success') {
                         WC_Subscriptions::add_notice(__('Payment method updated.', 'woocommerce-subscriptions'), 'success');
                         wp_redirect($result['redirect']);
                         exit;
                     }
                 }
             }
         }
     }
 }
 /**
  * Adds Subscriptions specific details to the WooCommerce System Status report.
  *
  * @param array $attributes Shortcode attributes.
  * @return array
  */
 public static function add_system_status_items($debug_data)
 {
     $is_wcs_debug = defined('WCS_DEBUG') ? WCS_DEBUG : false;
     $debug_data['wcs_debug'] = array('name' => _x('WCS_DEBUG', 'label that indicates whether debugging is turned on for the plugin', 'woocommerce-subscriptions'), 'note' => $is_wcs_debug ? __('Yes', 'woocommerce-subscriptions') : __('No', 'woocommerce-subscriptions'), 'success' => $is_wcs_debug ? 0 : 1);
     $debug_data['wcs_staging'] = array('name' => _x('Subscriptions Mode', 'Live or Staging, Label on WooCommerce -> System Status page', 'woocommerce-subscriptions'), 'note' => '<strong>' . (WC_Subscriptions::is_duplicate_site() ? _x('Staging', 'refers to staging site', 'woocommerce-subscriptions') : _x('Live', 'refers to live site', 'woocommerce-subscriptions')) . '</strong>', 'success' => WC_Subscriptions::is_duplicate_site() ? 0 : 1);
     return $debug_data;
 }
 /**
  * Sync variable product prices with the childs lowest/highest prices.
  *
  * @access public
  * @return void
  */
 public function variable_product_sync($product_id = '')
 {
     global $woocommerce;
     parent::variable_product_sync();
     $children = get_posts(array('post_parent' => $this->id, 'posts_per_page' => -1, 'post_type' => 'product_variation', 'fields' => 'ids', 'post_status' => 'publish'));
     $lowest_initial_amount = $highest_initial_amount = $lowest_price = $highest_price = '';
     $shortest_initial_period = $longest_initial_period = $shortest_trial_period = $longest_trial_period = $shortest_trial_length = $longest_trial_length = '';
     $longest_initial_interval = $shortest_initial_interval = $variable_subscription_period = $variable_subscription_period_interval = '';
     $lowest_regular_price = $highest_regular_price = $lowest_sale_price = $highest_sale_price = $max_subscription_period = $max_subscription_period_interval = '';
     $variable_subscription_sign_up_fee = $variable_subscription_trial_period = $variable_subscription_trial_length = $variable_subscription_length = $variable_subscription_sign_up_fee = $variable_subscription_trial_period = $variable_subscription_trial_length = $variable_subscription_length = '';
     $min_variation_id = $max_variation_id = NULL;
     if ($children) {
         foreach ($children as $child) {
             $is_max = $is_min = false;
             // WC has already determined the correct price which accounts for sale price
             $child_price = get_post_meta($child, '_price', true);
             $child_billing_period = get_post_meta($child, '_subscription_period', true);
             $child_billing_interval = get_post_meta($child, '_subscription_period_interval', true);
             $child_sign_up_fee = get_post_meta($child, '_subscription_sign_up_fee', true);
             $child_free_trial_length = get_post_meta($child, '_subscription_trial_length', true);
             $child_free_trial_period = get_post_meta($child, '_subscription_trial_period', true);
             if ($child_price === '' && $child_sign_up_fee === '') {
                 continue;
             }
             $child_price = $child_price === '' ? 0 : $child_price;
             $child_sign_up_fee = $child_sign_up_fee === '' ? 0 : $child_sign_up_fee;
             $has_free_trial = $child_free_trial_length !== '' && $child_free_trial_length > 0 ? true : false;
             // Determine some recurring price flags
             $is_lowest_price = $child_price < $lowest_price || '' === $lowest_price ? true : false;
             $is_longest_period = $child_billing_period === WC_Subscriptions::get_longest_period($variable_subscription_period, $child_billing_period) ? true : false;
             $is_longest_interval = $child_billing_interval >= $variable_subscription_period_interval || '' === $variable_subscription_period_interval ? true : false;
             // Find the amount the subscriber will have to pay up-front
             if ($has_free_trial) {
                 $initial_amount = $child_sign_up_fee;
                 $initial_period = $child_free_trial_period;
                 $initial_interval = $child_free_trial_length;
             } else {
                 $initial_amount = $child_price + $child_sign_up_fee;
                 $initial_period = $child_billing_period;
                 $initial_interval = $child_billing_interval;
             }
             // We have a free trial & no sign-up fee, so need to choose the longest free trial (and maybe the shortest)
             if ($has_free_trial && $child_sign_up_fee == 0) {
                 // First variation
                 if ('' === $longest_trial_period) {
                     $is_min = true;
                     // If two variations have the same free trial, choose the variation with the lowest recurring price for the longest period
                 } elseif ($variable_subscription_trial_period === $child_free_trial_period && $child_free_trial_length === $variable_subscription_trial_length) {
                     // If the variation has the lowest recurring price, it's the cheapest
                     if ($is_lowest_price) {
                         $is_min = true;
                         // When current variation's free trial is the same as the lowest, it's the cheaper if it has a longer billing schedule
                     } elseif ($child_price === $lowest_price) {
                         if ($is_longest_period && $is_longest_interval) {
                             $is_min = true;
                             // Longest with a new billing period
                         } elseif ($is_longest_period && $child_billing_period !== $variable_subscription_trial_period) {
                             $is_min = true;
                         }
                     }
                     // Otherwise the cheapest variation is the one with the longer trial
                 } elseif ($variable_subscription_trial_period === $child_free_trial_period) {
                     $is_min = $child_free_trial_length > $variable_subscription_trial_length ? true : false;
                     // Otherwise just a longer trial period (that isn't equal to the longest period)
                 } elseif ($child_free_trial_period === WC_Subscriptions::get_longest_period($longest_trial_period, $child_free_trial_period)) {
                     $is_min = true;
                 }
                 if ($is_min) {
                     $longest_trial_period = $child_free_trial_period;
                     $longest_trial_length = $child_free_trial_length;
                 }
                 // If the current cheapest variation is also free then the shortest trial period is the most expensive
                 if (0 == $lowest_price || '' === $lowest_price) {
                     if ('' === $shortest_trial_period) {
                         $is_max = true;
                         // Need to check trial length
                     } elseif ($shortest_trial_period === $child_free_trial_period) {
                         $is_max = $child_free_trial_length < $shortest_trial_length ? true : false;
                         // Need to find shortest period
                     } elseif ($child_free_trial_period === WC_Subscriptions::get_shortest_period($shortest_trial_period, $child_free_trial_period)) {
                         $is_max = true;
                     }
                     if ($is_max) {
                         $shortest_trial_period = $child_free_trial_period;
                         $shortest_trial_length = $child_free_trial_length;
                     }
                 }
             } else {
                 $longest_initial_period = WC_Subscriptions::get_longest_period($longest_initial_period, $initial_period);
                 $shortest_initial_period = WC_Subscriptions::get_shortest_period($shortest_initial_period, $initial_period);
                 $is_lowest_initial_amount = $initial_amount < $lowest_initial_amount || '' === $lowest_initial_amount ? true : false;
                 $is_longest_initial_period = $initial_period === $longest_initial_period ? true : false;
                 $is_longest_initial_interval = $initial_interval >= $longest_initial_interval || '' === $longest_initial_interval ? true : false;
                 $is_highest_initial = $initial_amount > $highest_initial_amount || '' === $highest_initial_amount ? true : false;
                 $is_shortest_period = $initial_period === $shortest_initial_period || '' === $shortest_initial_period ? true : false;
                 $is_shortest_interval = $initial_interval < $shortest_initial_interval || '' === $shortest_initial_interval ? true : false;
                 // If we're not dealing with the lowest initial access amount, then ignore this variation
                 if (!$is_lowest_initial_amount && $initial_amount !== $lowest_initial_amount) {
                     continue;
                 }
                 // If the variation has the lowest price, it's the cheapest
                 if ($is_lowest_initial_amount) {
                     $is_min = true;
                     // When current variation's price is the same as the lowest, it's the cheapest only if it has a longer billing schedule
                 } elseif ($initial_amount === $lowest_initial_amount) {
                     // We need to check the recurring schedule when the sign-up fee & free trial periods are equal
                     if ($has_free_trial && $initial_period == $longest_initial_period && $initial_interval == $longest_initial_interval) {
                         // If the variation has the lowest recurring price, it's the cheapest
                         if ($is_lowest_price) {
                             $is_min = true;
                             // When current variation's price is the same as the lowest, it's the cheapest only if it has a longer billing schedule
                         } elseif ($child_price === $lowest_price) {
                             if ($is_longest_period && $is_longest_interval) {
                                 $is_min = true;
                                 // Longest with a new billing period
                             } elseif ($is_longest_period && $child_billing_period !== $variable_subscription_period) {
                                 $is_min = true;
                             }
                         }
                         // Longest initial term is the cheapest
                     } elseif ($is_longest_initial_period && $is_longest_initial_interval) {
                         $is_min = true;
                         // Longest with a new billing period
                     } elseif ($is_longest_initial_period && $initial_period !== $longest_initial_period) {
                         $is_min = true;
                     }
                 }
                 // If we have the highest price for the shortest period, we might have the maximum variation
                 if ($is_highest_initial && $is_shortest_period && $is_shortest_interval) {
                     $is_max = true;
                     // But only if its for the shortest billing period
                 } elseif ($child_price === $highest_price) {
                     if ($is_shortest_period && $is_shortest_interval) {
                         $is_max = true;
                     } elseif ($is_shortest_period) {
                         $is_max = true;
                     }
                 }
             }
             // If it's the min subscription terms
             if ($is_min) {
                 $min_variation_id = $child;
                 $lowest_price = $child_price;
                 $lowest_regular_price = get_post_meta($child, '_regular_price', true);
                 $lowest_sale_price = get_post_meta($child, '_sale_price', true);
                 $lowest_regular_price = '' === $lowest_regular_price ? 0 : $lowest_regular_price;
                 $lowest_sale_price = '' === $lowest_sale_price ? 0 : $lowest_sale_price;
                 $lowest_initial_amount = $initial_amount;
                 $longest_initial_period = $initial_period;
                 $longest_initial_interval = $initial_interval;
                 $variable_subscription_sign_up_fee = $child_sign_up_fee;
                 $variable_subscription_period = $child_billing_period;
                 $variable_subscription_period_interval = $child_billing_interval;
                 $variable_subscription_trial_length = $child_free_trial_length;
                 $variable_subscription_trial_period = $child_free_trial_period;
                 $variable_subscription_length = get_post_meta($child, '_subscription_length', true);
             }
             if ($is_max) {
                 $max_variation_id = $child;
                 $highest_price = $child_price;
                 $highest_regular_price = get_post_meta($child, '_regular_price', true);
                 $highest_sale_price = get_post_meta($child, '_sale_price', true);
                 $highest_initial_amount = $initial_amount;
                 $highest_regular_price = '' === $highest_regular_price ? 0 : $highest_regular_price;
                 $highest_sale_price = '' === $highest_sale_price ? 0 : $highest_sale_price;
                 $max_subscription_period = $child_billing_period;
                 $max_subscription_period_interval = $child_billing_interval;
             }
         }
         update_post_meta($this->id, '_min_price_variation_id', $min_variation_id);
         update_post_meta($this->id, '_max_price_variation_id', $max_variation_id);
         update_post_meta($this->id, '_price', $lowest_price);
         update_post_meta($this->id, '_min_variation_price', $lowest_price);
         update_post_meta($this->id, '_max_variation_price', $highest_price);
         update_post_meta($this->id, '_min_variation_regular_price', $lowest_regular_price);
         update_post_meta($this->id, '_max_variation_regular_price', $highest_regular_price);
         update_post_meta($this->id, '_min_variation_sale_price', $lowest_sale_price);
         update_post_meta($this->id, '_max_variation_sale_price', $highest_sale_price);
         update_post_meta($this->id, '_min_variation_period', $variable_subscription_period);
         update_post_meta($this->id, '_max_variation_period', $variable_subscription_period_interval);
         update_post_meta($this->id, '_min_variation_period_interval', $max_subscription_period);
         update_post_meta($this->id, '_max_variation_period_interval', $max_subscription_period_interval);
         update_post_meta($this->id, '_subscription_price', $lowest_price);
         update_post_meta($this->id, '_subscription_sign_up_fee', $variable_subscription_sign_up_fee);
         update_post_meta($this->id, '_subscription_period', $variable_subscription_period);
         update_post_meta($this->id, '_subscription_period_interval', $variable_subscription_period_interval);
         update_post_meta($this->id, '_subscription_trial_period', $variable_subscription_trial_period);
         update_post_meta($this->id, '_subscription_trial_length', $variable_subscription_trial_length);
         update_post_meta($this->id, '_subscription_length', $variable_subscription_length);
         $this->subscription_price = $lowest_price;
         $this->subscription_sign_up_fee = $variable_subscription_sign_up_fee;
         $this->subscription_period = $variable_subscription_period;
         $this->subscription_period_interval = $variable_subscription_period_interval;
         $this->subscription_trial_period = $variable_subscription_trial_period;
         $this->subscription_trial_length = $variable_subscription_trial_length;
         $this->subscription_length = $variable_subscription_length;
         if (function_exists('wc_delete_product_transients')) {
             wc_delete_product_transients($this->id);
         } else {
             $woocommerce->clear_product_transients($this->id);
         }
     } else {
         // No variations yet
         $this->subscription_price = '';
         $this->subscription_sign_up_fee = '';
         $this->subscription_period = 'day';
         $this->subscription_period_interval = 1;
         $this->subscription_trial_period = 'day';
         $this->subscription_trial_length = 1;
         $this->subscription_length = 0;
     }
 }
 * @var WP_POST $variation
 * @var string $subscription_period
 * @var array $variation_data array of variation data
 */
if (!defined('ABSPATH')) {
    exit;
}
global $wp_locale;
?>
<tr class="variable_subscription_sync show_if_variable-subscription">
	<td colspan="1" class="subscription_sync_week_month"<?php 
echo $display_week_month_select;
?>
>
		<?php 
if (WC_Subscriptions::is_woocommerce_pre_2_3()) {
    ?>
		<label><?php 
    _e('Synchronise Renewals', 'woocommerce-subscriptions');
    ?>
</label>
		<?php 
}
woocommerce_wp_select(array('id' => 'variable' . WC_Subscriptions_Synchroniser::$post_meta_key . '[' . $loop . ']', 'class' => 'wc_input_subscription_payment_sync', 'wrapper_class' => '_subscription_payment_sync_field', 'label' => WC_Subscriptions_Synchroniser::$sync_field_label, 'options' => WC_Subscriptions_Synchroniser::get_billing_period_ranges($subscription_period), 'description' => WC_Subscriptions_Synchroniser::$sync_description, 'desc_tip' => true, 'value' => $payment_day));
?>
	</td>
	<td colspan="1" class="subscription_sync_annual"<?php 
echo $display_annual_select;
?>
>
		<label><?php 
/**
 * Return an i18n'ified associative array of all possible subscription periods.
 *
 * @param int (optional) An interval in the range 1-6
 * @since 2.0
 */
function wcs_get_subscription_period_interval_strings($interval = '')
{
    $intervals = array(1 => _x('every', 'period interval (eg "$10 _every_ 2 weeks")', 'woocommerce-subscriptions'));
    foreach (range(2, 6) as $i) {
        // translators: period interval, placeholder is ordinal (eg "$10 every _2nd/3rd/4th_", etc)
        $intervals[$i] = sprintf(_x('every %s', 'period interval with ordinal number (e.g. "every 2nd"', 'woocommerce-subscriptions'), WC_Subscriptions::append_numeral_suffix($i));
    }
    $intervals = apply_filters('woocommerce_subscription_period_interval_strings', $intervals);
    if (empty($interval)) {
        return $intervals;
    } else {
        return $intervals[$interval];
    }
}
 /**
  * Return an i18n'ified associative array of all possible subscription periods.
  *
  * @since 1.5
  */
 public static function get_billing_period_ranges($billing_period = '')
 {
     global $wp_locale;
     if (empty(self::$billing_period_ranges)) {
         foreach (array('week', 'month', 'year') as $key) {
             self::$billing_period_ranges[$key][0] = __('Do not synchronise', 'woocommerce-subscriptions');
         }
         // Week
         $weekdays = array_merge($wp_locale->weekday, array($wp_locale->weekday[0]));
         unset($weekdays[0]);
         foreach ($weekdays as $i => $weekly_billing_period) {
             self::$billing_period_ranges['week'][$i] = sprintf(__('%s each week', 'woocommerce-subscriptions'), $weekly_billing_period);
         }
         // Month
         foreach (range(1, 27) as $i) {
             self::$billing_period_ranges['month'][$i] = sprintf(__('%s day of the month', 'woocommerce-subscriptions'), WC_Subscriptions::append_numeral_suffix($i));
         }
         self::$billing_period_ranges['month'][28] = __('Last day of the month', 'woocommerce-subscriptions');
         self::$billing_period_ranges = apply_filters('woocommerce_subscription_billing_period_ranges', self::$billing_period_ranges);
     }
     if (empty($billing_period)) {
         return self::$billing_period_ranges;
     } elseif (isset(self::$billing_period_ranges[$billing_period])) {
         return self::$billing_period_ranges[$billing_period];
     } else {
         return array();
     }
 }
 /**
  * Generate an order items table using a WC compatible version of the function.
  *
  * @param object $order
  * @param array $args {
  *     @type bool  'show_download_links'
  *     @type bool  'show_sku'
  *     @type bool  'show_purchase_note'
  *     @type array 'image_size'
  *     @type bool  'plain_text'
  * }
  * @return string email order items table html
  */
 public static function email_order_items_table($order, $args = array())
 {
     $items_table = '';
     if (is_numeric($order)) {
         $order = wc_get_order($order);
     }
     if (is_a($order, 'WC_Abstract_Order')) {
         if (WC_Subscriptions::is_woocommerce_pre('2.5')) {
             $items_table = call_user_func_array(array($order, 'email_order_items_table'), $args);
         } else {
             // 2.5 doesn't support both the show_download_links or show_purchase_note parameters but uses $order->is_download_permitted and  $order->is_paid instead
             $show_download_links_callback = isset($args['show_download_links']) && $args['show_download_links'] ? '__return_true' : '__return_false';
             $show_purchase_note_callback = isset($args['show_purchase_note']) && $args['show_purchase_note'] ? '__return_true' : '__return_false';
             unset($args['show_download_links']);
             unset($args['show_purchase_note']);
             add_filter('woocommerce_order_is_download_permitted', $show_download_links_callback);
             add_filter('woocommerce_order_is_paid', $show_purchase_note_callback);
             $items_table = $order->email_order_items_table($args);
             remove_filter('woocommerce_order_is_download_permitted', $show_download_links_callback);
             remove_filter('woocommerce_order_is_paid', $show_purchase_note_callback);
         }
     }
     return $items_table;
 }
 /**
  * When a product is added to the cart, check if it is being added to switch a subscription and if so,
  * make sure it's valid (i.e. not the same subscription).
  *
  * @since 1.4
  */
 public static function validate_switch_request($is_valid, $product_id, $quantity, $variation_id = '')
 {
     global $woocommerce;
     if (!isset($_GET['switch-subscription'])) {
         return $is_valid;
     }
     $subscription = WC_Subscriptions_Manager::get_subscription($_GET['switch-subscription']);
     if ($product_id == $subscription['product_id'] && (empty($variation_id) || $variation_id == $subscription['variation_id'])) {
         WC_Subscriptions::add_notice(__('You can not switch to the same subscription.', 'woocommerce-subscriptions'), 'error');
         $is_valid = false;
     }
     return $is_valid;
 }
 /**
  * Takes a subscription key and calculates the date on which the subscription is scheduled to expire
  * or 0 if it will never expire.
  *
  * @param $subscription_key string A subscription key of the form created by @see self::get_subscription_key()
  * @param $user_id int The ID of the user who owns the subscriptions. Although this parameter is optional, if you have the User ID you should pass it to improve performance.
  * @param $type string (optional) The format for the Either 'mysql' or 'timestamp'.
  * @since 1.1
  */
 public static function calculate_trial_expiration_date($subscription_key, $user_id = '', $type = 'mysql')
 {
     $subscription = self::get_subscription($subscription_key, $user_id);
     if (empty($subscription)) {
         $expiration_date = 0;
     } else {
         $order = new WC_Order($subscription['order_id']);
         $subscription_trial_length = WC_Subscriptions_Order::get_subscription_trial_length($order, $subscription['product_id']);
         $subscription_trial_period = WC_Subscriptions_Order::get_subscription_trial_period($order, $subscription['product_id']);
         if ($subscription_trial_length > 0) {
             if (isset($subscription['start_date']) && !empty($subscription['start_date'])) {
                 $start_date = $subscription['start_date'];
             } elseif (!empty($order->order_date)) {
                 $start_date = get_gmt_from_date($order->order_date);
             } else {
                 $start_date = gmdate('Y-m-d H:i:s');
             }
             if ('month' == $subscription_trial_period) {
                 $expiration_date = WC_Subscriptions::add_months(strtotime($start_date), $subscription_trial_length);
             } else {
                 // Safe to just add the billing periods
                 $expiration_date = strtotime("+ {$subscription_trial_length} {$subscription_trial_period}", strtotime($start_date));
             }
         } else {
             $expiration_date = 0;
         }
     }
     $expiration_date = 'mysql' == $type && 0 != $expiration_date ? date('Y-m-d H:i:s', $expiration_date) : $expiration_date;
     return apply_filters('woocommerce_subscription_calculated_trial_expiration_date', $expiration_date, $subscription_key, $user_id);
 }
 /**
  * Process the change payment form.
  *
  * Based on the @see woocommerce_pay_action() function.
  *
  * @access public
  * @return void
  * @since 1.4
  */
 public static function change_payment_method_via_pay_shortcode()
 {
     if (isset($_POST['_wcsnonce']) && wp_verify_nonce($_POST['_wcsnonce'], 'wcs_change_payment_method')) {
         $subscription = wcs_get_subscription(absint($_POST['woocommerce_change_payment']));
         do_action('woocommerce_subscription_change_payment_method_via_pay_shortcode', $subscription);
         ob_start();
         if ($subscription->order_key == $_GET['key']) {
             // Set customer location to order location
             if ($subscription->billing_country) {
                 WC()->customer->set_country($subscription->billing_country);
             }
             if ($subscription->billing_state) {
                 WC()->customer->set_state($subscription->billing_state);
             }
             if ($subscription->billing_postcode) {
                 WC()->customer->set_postcode($subscription->billing_postcode);
             }
             if ($subscription->billing_city) {
                 WC()->customer->set_city($subscription->billing_city);
             }
             // Update payment method
             $new_payment_method = woocommerce_clean($_POST['payment_method']);
             // Allow some payment gateways which can't process the payment immediately, like PayPal, to do it later after the payment/sign-up is confirmed
             if (apply_filters('woocommerce_subscriptions_update_payment_via_pay_shortcode', true, $new_payment_method, $subscription)) {
                 self::update_payment_method($subscription, $new_payment_method);
             }
             $available_gateways = WC()->payment_gateways->get_available_payment_gateways();
             // Validate
             $available_gateways[$new_payment_method]->validate_fields();
             // Process payment for the new method (with a $0 order total)
             if (wc_notice_count('error') == 0) {
                 $result = $available_gateways[$new_payment_method]->process_payment($subscription->id);
                 $result = apply_filters('woocommerce_subscriptions_process_payment_for_change_method_via_pay_shortcode', $result, $subscription);
                 // Redirect to success/confirmation/payment page
                 if ('success' == $result['result']) {
                     WC_Subscriptions::add_notice(__('Payment method updated.', 'woocommerce-subscriptions'), 'success');
                     wp_redirect($result['redirect']);
                     exit;
                 }
             }
         }
     }
 }