/**
  * Add a 'new-payment-method' handler to the @see WC_Subscriptions_Manager::can_subscription_be_changed_to() function
  * to determine whether the recurring payment method on a subscription can be changed.
  *
  * For the recurring payment method to be changeable, the subscription must be active, have future (automatic) payments
  * and use a payment gateway which allows the subscription to be cancelled.
  *
  * @param bool $subscription_can_be_changed Flag of whether the subscription can be changed to
  * @param string $new_status_or_meta The status or meta data you want to change th subscription to. Can be 'active', 'on-hold', 'cancelled', 'expired', 'trash', 'deleted', 'failed', 'new-payment-date' or some other value attached to the 'woocommerce_can_subscription_be_changed_to' filter.
  * @param object $args Set of values used in @see WC_Subscriptions_Manager::can_subscription_be_changed_to() for determining if a subscription can be changes, include:
  *			'subscription_key'           string A subscription key of the form created by @see WC_Subscriptions_Manager::get_subscription_key()
  *			'subscription'               array Subscription of the form returned by @see WC_Subscriptions_Manager::get_subscription()
  *			'user_id'                    int The ID of the subscriber.
  *			'order'                      WC_Order The order which recorded the successful payment (to make up for the failed automatic payment).
  *			'payment_gateway'            WC_Payment_Gateway The subscription's recurring payment gateway
  *			'order_uses_manual_payments' bool A boolean flag indicating whether the subscription requires manual renewal payment.
  * @since 1.4
  */
 public static function can_subscription_be_changed_to($subscription_can_be_changed, $new_status_or_meta, $args)
 {
     global $woocommerce;
     if ('new-payment-method' === $new_status_or_meta) {
         $next_payment_timestamp = WC_Subscriptions_Manager::get_next_payment_date($args->subscription_key, '', 'timestamp');
         // Check if any payment gateway supports recurring payment method changes
         $one_gateway_supports_changes = false;
         foreach ($woocommerce->payment_gateways->get_available_payment_gateways() as $gateway) {
             if ($gateway->supports('subscription_payment_method_change')) {
                 $one_gateway_supports_changes = true;
                 break;
             }
         }
         if ($one_gateway_supports_changes && 0 !== $next_payment_timestamp && false === $args->order_uses_manual_payments && $args->payment_gateway->supports('subscription_cancellation') && 'active' == $args->subscription['status']) {
             $subscription_can_be_changed = true;
         } else {
             $subscription_can_be_changed = false;
         }
     }
     return $subscription_can_be_changed;
 }
        ?>
				</td>
				<td class="subscription-status" style="text-align:left; white-space:nowrap;" data-title="<?php 
        _e('Status', 'woocommerce-subscriptions');
        ?>
">
					<?php 
        echo WC_Subscriptions_Manager::get_status_to_display($subscription_details['status'], $subscription_key, $user_id);
        ?>
				</td>
				<td class="subscription-next-payment" data-title="<?php 
        _e('Next Payment', 'woocommerce-subscriptions');
        ?>
">
					<?php 
        $next_payment_timestamp = WC_Subscriptions_Manager::get_next_payment_date($subscription_key, $user_id, 'timestamp');
        ?>
					<?php 
        if ($next_payment_timestamp == 0) {
            ?>
						-
					<?php 
        } else {
            ?>
						<?php 
            $time_diff = $next_payment_timestamp - gmdate('U');
            ?>
						<?php 
            if ($time_diff > 0 && $time_diff < 7 * 24 * 60 * 60) {
                ?>
							<?php 
 /**
  * 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)
 {
     if (!isset($_GET['switch-subscription'])) {
         return $cart_item_data;
     }
     $subscription = WC_Subscriptions_Manager::get_subscription($_GET['switch-subscription']);
     $product = get_product($subscription['product_id']);
     $child_products = 0 !== $product->post->post_parent ? get_product($product->post->post_parent)->get_children() : array();
     if ($product_id != $subscription['product_id'] && !in_array($subscription['product_id'], $child_products)) {
         return $cart_item_data;
     }
     $cart_item_data['subscription_switch'] = array('subscription_key' => $_GET['switch-subscription'], 'next_payment_timestamp' => WC_Subscriptions_Manager::get_next_payment_date($_GET['switch-subscription'], get_current_user_id(), 'timestamp'), 'upgraded_or_downgraded' => '');
     return $cart_item_data;
 }
 /**
  * If no sort order set, default to title. If no sort order, default to descending.
  *
  * @since 1.0
  */
 function sort_subscriptions($a, $b)
 {
     $order_by = !empty($_REQUEST['orderby']) ? $_REQUEST['orderby'] : 'start_date';
     $order = !empty($_REQUEST['order']) ? $_REQUEST['order'] : 'desc';
     switch ($order_by) {
         case 'product_name':
             $product_name_a = get_the_title($a['product_id']);
             $product_name_b = get_the_title($b['product_id']);
             $result = strcasecmp($product_name_a, $product_name_b);
             break;
         case 'user':
             $user_a = get_user_by('id', $a['user_id']);
             $user_b = get_user_by('id', $b['user_id']);
             $result = strcasecmp($user_a->display_name, $user_b->display_name);
             break;
         case 'expiry_date':
             if ($order == 'asc') {
                 $result = self::sort_with_zero_at_end($a[$order_by], $b[$order_by]);
             } else {
                 $result = self::sort_with_zero_at_beginning($a[$order_by], $b[$order_by]);
             }
             break;
         case 'end_date':
             $result = self::sort_with_zero_at_end($a[$order_by], $b[$order_by]);
             // Display subscriptions that have not ended at the end of the list
             break;
         case 'next_payment_date':
             $next_payment_a = WC_Subscriptions_Manager::get_next_payment_date($a['subscription_key'], $a['user_id'], 'mysql');
             $next_payment_b = WC_Subscriptions_Manager::get_next_payment_date($b['subscription_key'], $b['user_id'], 'mysql');
             $result = self::sort_with_zero_at_end($next_payment_a, $next_payment_b);
             // Display subscriptions with no future payments at the end
             break;
         case 'last_payment_date':
             $last_payment_a = empty($a['completed_payments']) ? 0 : strtotime(array_pop($a['completed_payments']));
             $last_payment_b = empty($b['completed_payments']) ? 0 : strtotime(array_pop($b['completed_payments']));
             $result = self::sort_with_zero_at_end($last_payment_a, $last_payment_b);
             // Display subscriptions with no compelted payments at the end
             break;
         case 'trial_expiry_date':
             $trial_expiration_a = WC_Subscriptions_Manager::get_trial_expiration_date($a['subscription_key'], $a['user_id'], 'mysql');
             $trial_expiration_b = WC_Subscriptions_Manager::get_trial_expiration_date($b['subscription_key'], $b['user_id'], 'mysql');
             $result = self::sort_with_zero_at_end($trial_expiration_a, $trial_expiration_b);
             break;
         case 'renewal_order_count':
             $result = strcmp(WC_Subscriptions_Renewal_Order::get_renewal_order_count($a['order_id']), WC_Subscriptions_Renewal_Order::get_renewal_order_count($b['order_id']));
             break;
         case 'order_id':
             $result = strnatcmp($a[$order_by], $b[$order_by]);
             break;
         default:
             $result = strcmp($a[$order_by], $b[$order_by]);
             break;
     }
     return $order == 'asc' ? $result : -$result;
     // Send final sort direction to usort
 }
    /**
     * Display subscription columns in my memberships section
     *
     * @since 1.0.0
     * @param WC_Memberships_User_Membership $user_membership
     */
    public function output_subscription_columns(WC_Memberships_User_Membership $user_membership)
    {
        $subscription = $this->get_user_membership_subscription($user_membership->get_id());
        if (!$this->is_subscriptions_gte_2_0()) {
            $subscription_key = $this->get_user_membership_subscription_key($user_membership->get_id());
        }
        if ($subscription && in_array($user_membership->get_status(), array('active', 'free_trial'))) {
            $next_payment = $this->is_subscriptions_gte_2_0() ? $subscription->get_time('next_payment') : WC_Subscriptions_Manager::get_next_payment_date($subscription_key, $user_membership->get_user_id(), 'timestamp');
        }
        ?>
		<td class="membership-membership-next-bill-on" data-title="<?php 
        esc_attr_e('Next Bill On', WC_Memberships::TEXT_DOMAIN);
        ?>
">
			<?php 
        if ($subscription && !empty($next_payment)) {
            ?>
				<?php 
            echo date_i18n(get_option('date_format'), $next_payment);
            ?>
			<?php 
        } else {
            ?>
				<?php 
            _e('N/A', WC_Memberships::TEXT_DOMAIN);
            ?>
			<?php 
        }
        ?>
		</td>
		<?php 
    }
 /**
  * Takes a subscription product's ID and the order it was purchased in and returns the date on
  * which the next payment is due.
  *
  * A convenience wrapper for @see WC_Subscriptions_Manager::get_next_payment_date() to get the next
  * payment date for a subscription when all you have is the order and product.
  *
  * @param mixed $order A WC_Order object or the ID of the order which the subscription was purchased in.
  * @param int $product_id The product/post ID of the subscription
  * @param mixed $deprecated Never used.
  * @return mixed If no more payments are due, returns 0, otherwise it returns the MySQL formatted date/time string for the next payment date.
  * @version 1.2
  * @since 1.0
  */
 public static function get_next_payment_date($order, $product_id, $deprecated = null)
 {
     if (null != $deprecated) {
         // We want to calculate a date
         _deprecated_argument(__CLASS__ . '::' . __FUNCTION__, '1.2');
         $next_payment_date = self::calculate_next_payment_date($order, $product_id, 'mysql', $deprecated);
     } else {
         if (!is_object($order)) {
             $order = new WC_Order($order);
         }
         $subscription_key = WC_Subscriptions_Manager::get_subscription_key($order->id, $product_id);
         $next_payment_date = WC_Subscriptions_Manager::get_next_payment_date($subscription_key, $order->user_id, 'mysql');
     }
     return $next_payment_date;
 }
 /**
  * Change the send date of the email for 'before_renewal' and 'before_expire' triggers
  * @param array $insert
  * @param FUE_Email $email
  * @return array
  */
 public function modify_insert_send_date($insert, $email)
 {
     if ($email->type != 'subscription') {
         return $insert;
     }
     $order_id = $insert['order_id'];
     $order = WC_FUE_Compatibility::wc_get_order($order_id);
     if (!WC_Subscriptions_Order::order_contains_subscription($order)) {
         return $insert;
     }
     $subs_key = WC_Subscriptions_Manager::get_subscription_key($order_id);
     if ($email->trigger == 'subs_before_renewal') {
         $renewal_date = WC_Subscriptions_Manager::get_next_payment_date($subs_key);
         if (!$renewal_date) {
             // return false to tell FUE to skip importing this email/order
             return false;
         }
         // convert to local time
         $local_renewal_date = get_date_from_gmt($renewal_date, 'U');
         $add = FUE_Sending_Scheduler::get_time_to_add($email->interval, $email->duration);
         $insert['send_on'] = $local_renewal_date - $add;
     } elseif ($email->trigger == 'subs_before_expire') {
         $expiry_date = WC_Subscriptions_Manager::get_subscription_expiration_date($subs_key);
         if (!$expiry_date) {
             return false;
         }
         // convert to local time
         $expiry_timestamp = get_date_from_gmt($expiry_date, 'U');
         $add = FUE_Sending_Scheduler::get_time_to_add($email->interval, $email->duration);
         $insert['send_on'] = $expiry_timestamp - $add;
     }
     // Add the subscription key if it is not present in the meta
     if (!isset($insert['meta']) || empty($insert['meta']['subs_key'])) {
         $insert['meta']['subs_key'] = $subs_key;
     }
     return $insert;
 }
 /**
  * Override the default PayPal standard args in WooCommerce for subscription purchases.
  *
  * Based on the HTML Variables documented here: https://developer.paypal.com/webapps/developer/docs/classic/paypal-payments-standard/integration-guide/Appx_websitestandard_htmlvariables/#id08A6HI00JQU
  *
  * @since 1.0
  */
 public static function paypal_standard_subscription_args($paypal_args)
 {
     extract(self::get_order_id_and_key($paypal_args));
     if (WC_Subscriptions_Order::order_contains_subscription($order_id) && 'yes' !== get_option(WC_Subscriptions_Admin::$option_prefix . '_turn_off_automatic_payments', 'no')) {
         $order = new WC_Order($order_id);
         $order_items = $order->get_items();
         // Only one subscription allowed in the cart when PayPal Standard is active
         $product = $order->get_product_from_item(array_pop($order_items));
         // It's a subscription
         $paypal_args['cmd'] = '_xclick-subscriptions';
         if (count($order->get_items()) > 1) {
             foreach ($order->get_items() as $item) {
                 if ($item['qty'] > 1) {
                     $item_names[] = $item['qty'] . ' x ' . $item['name'];
                 } else {
                     if ($item['qty'] > 0) {
                         $item_names[] = $item['name'];
                     }
                 }
             }
             $paypal_args['item_name'] = sprintf(__('Order %s', WC_Subscriptions::$text_domain), $order->get_order_number());
         } else {
             $paypal_args['item_name'] = $product->get_title();
         }
         $unconverted_periods = array('billing_period' => WC_Subscriptions_Order::get_subscription_period($order), 'trial_period' => WC_Subscriptions_Order::get_subscription_trial_period($order));
         $converted_periods = array();
         // Convert period strings into PayPay's format
         foreach ($unconverted_periods as $key => $period) {
             switch (strtolower($period)) {
                 case 'day':
                     $converted_periods[$key] = 'D';
                     break;
                 case 'week':
                     $converted_periods[$key] = 'W';
                     break;
                 case 'year':
                     $converted_periods[$key] = 'Y';
                     break;
                 case 'month':
                 default:
                     $converted_periods[$key] = 'M';
                     break;
             }
         }
         $price_per_period = WC_Subscriptions_Order::get_recurring_total($order);
         $subscription_interval = WC_Subscriptions_Order::get_subscription_interval($order);
         $subscription_length = WC_Subscriptions_Order::get_subscription_length($order);
         $subscription_installments = $subscription_length / $subscription_interval;
         $is_payment_change = WC_Subscriptions_Change_Payment_Gateway::$is_request_to_change_payment;
         $is_switch_order = WC_Subscriptions_Switcher::order_contains_subscription_switch($order->id);
         $sign_up_fee = $is_payment_change ? 0 : WC_Subscriptions_Order::get_sign_up_fee($order);
         $initial_payment = $is_payment_change ? 0 : WC_Subscriptions_Order::get_total_initial_payment($order);
         if ($is_payment_change) {
             // Add a nonce to the order ID to avoid "This invoice has already been paid" error when changing payment method to PayPal when it was previously PayPal
             $paypal_args['invoice'] = $paypal_args['invoice'] . '-wcscpm-' . wp_create_nonce();
             // Set a flag on the order if changing from PayPal *to* PayPal to prevent incorrectly cancelling the subscription
             if ('paypal' == $order->recurring_payment_method) {
                 add_post_meta($order_id, '_wcs_changing_payment_from_paypal_to_paypal', 'true', true);
             }
         }
         // If we're changing the payment date or switching subs, we need to set the trial period to the next payment date & installments to be the number of installments left
         if ($is_payment_change || $is_switch_order) {
             $subscription_key = WC_Subscriptions_Manager::get_subscription_key($order_id, $product->id);
             // Give a free trial until the next payment date
             $next_payment_timestamp = WC_Subscriptions_Manager::get_next_payment_date($subscription_key, $order->user_id, 'timestamp');
             // When the subscription is on hold
             if ($next_payment_timestamp != false) {
                 $trial_until = self::calculate_trial_periods_until($next_payment_timestamp);
                 $subscription_trial_length = $trial_until['first_trial_length'];
                 $converted_periods['trial_period'] = $trial_until['first_trial_period'];
                 $second_trial_length = $trial_until['second_trial_length'];
                 $second_trial_period = $trial_until['second_trial_period'];
             }
             // If is a payment change, we need to account for completed payments on the number of installments owing
             if ($is_payment_change && $subscription_length > 0) {
                 $subscription_installments -= WC_Subscriptions_Manager::get_subscriptions_completed_payment_count($subscription_key);
             }
         } else {
             $subscription_trial_length = WC_Subscriptions_Order::get_subscription_trial_length($order);
         }
         if ($subscription_trial_length > 0) {
             // Specify a free trial period
             if ($is_switch_order) {
                 $paypal_args['a1'] = $initial_payment > 0 ? $initial_payment : 0;
             } else {
                 $paypal_args['a1'] = $sign_up_fee > 0 ? $sign_up_fee : 0;
             }
             // Maybe add the sign up fee to the free trial period
             // Trial period length
             $paypal_args['p1'] = $subscription_trial_length;
             // Trial period
             $paypal_args['t1'] = $converted_periods['trial_period'];
             // We need to use a second trial period before we have more than 90 days until the next payment
             if (WC_Subscriptions_Change_Payment_Gateway::$is_request_to_change_payment && $second_trial_length > 0) {
                 $paypal_args['a2'] = 0;
                 $paypal_args['p2'] = $second_trial_length;
                 $paypal_args['t2'] = $second_trial_period;
             }
         } elseif ($sign_up_fee > 0 || $initial_payment !== $price_per_period) {
             // No trial period, so charge sign up fee and per period price for the first period
             if ($subscription_installments == 1) {
                 $param_number = 3;
             } else {
                 $param_number = 1;
             }
             $paypal_args['a' . $param_number] = $initial_payment;
             // Sign Up interval
             $paypal_args['p' . $param_number] = $subscription_interval;
             // Sign Up unit of duration
             $paypal_args['t' . $param_number] = $converted_periods['billing_period'];
         }
         // We have a recurring payment
         if (!isset($param_number) || $param_number == 1) {
             // Subscription price
             $paypal_args['a3'] = $price_per_period;
             // Subscription duration
             $paypal_args['p3'] = $subscription_interval;
             // Subscription period
             $paypal_args['t3'] = $converted_periods['billing_period'];
         }
         // Recurring payments
         if ($subscription_installments == 1 || $sign_up_fee > 0 && $subscription_trial_length == 0 && $subscription_installments == 2) {
             // Non-recurring payments
             $paypal_args['src'] = 0;
         } else {
             $paypal_args['src'] = 1;
             if ($subscription_installments > 0) {
                 if ($sign_up_fee > 0 && $subscription_trial_length == 0) {
                     // An initial period is being used to charge a sign-up fee
                     $subscription_installments--;
                 }
                 $paypal_args['srt'] = $subscription_installments;
             }
         }
         // Don't reattempt failed payments, instead let Subscriptions handle the failed payment
         $paypal_args['sra'] = 0;
         // Force return URL so that order description & instructions display
         $paypal_args['rm'] = 2;
     }
     return $paypal_args;
 }
 /**
  * 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)
 {
     global $woocommerce;
     if (!isset($_GET['switch-subscription'])) {
         return $cart_item_data;
     }
     $subscription = WC_Subscriptions_Manager::get_subscription($_GET['switch-subscription']);
     // Requesting a switch for someone elses subscription
     if (!WC_Subscriptions_Manager::user_owns_subscription($_GET['switch-subscription'])) {
         WC_Subscriptions::add_notice(__('You can not switch this subscription. It appears you do not own the subscription.', 'woocommerce-subscriptions'), 'error');
         $woocommerce->cart->empty_cart(true);
         wp_redirect(get_permalink($subscription['product_id']));
         exit;
     }
     // Else it's a valid switch
     $product = get_product($subscription['product_id']);
     $child_products = 0 !== $product->post->post_parent ? get_product($product->post->post_parent)->get_children() : array();
     if ($product_id != $subscription['product_id'] && !in_array($subscription['product_id'], $child_products)) {
         return $cart_item_data;
     }
     $next_payment_timestamp = WC_Subscriptions_Manager::get_next_payment_date($_GET['switch-subscription'], get_current_user_id(), 'timestamp');
     // 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 && WC_Subscriptions_Manager::get_subscriptions_completed_payment_count($_GET['switch-subscription']) >= WC_Subscriptions_Order::get_subscription_length($subscription['order_id'], $subscription['product_id'])) {
         $next_payment_timestamp = WC_Subscriptions_Manager::get_subscription_expiration_date($_GET['switch-subscription'], get_current_user_id(), 'timestamp');
     }
     $cart_item_data['subscription_switch'] = array('subscription_key' => $_GET['switch-subscription'], 'next_payment_timestamp' => $next_payment_timestamp, 'upgraded_or_downgraded' => '');
     return $cart_item_data;
 }
 /**
  * Override the default PayPal standard args in WooCommerce for subscription purchases when
  * automatic payments are enabled and when the recurring order totals is over $0.00 (because
  * PayPal doesn't support subscriptions with a $0 recurring total, we need to circumvent it and
  * manage it entirely ourselves.)
  *
  * Based on the HTML Variables documented here: https://developer.paypal.com/webapps/developer/docs/classic/paypal-payments-standard/integration-guide/Appx_websitestandard_htmlvariables/#id08A6HI00JQU
  *
  * @since 1.0
  */
 public static function paypal_standard_subscription_args($paypal_args)
 {
     extract(self::get_order_id_and_key($paypal_args));
     $order = new WC_Order($order_id);
     if ($cart_item = WC_Subscriptions_Cart::cart_contains_failed_renewal_order_payment() || false !== WC_Subscriptions_Renewal_Order::get_failed_order_replaced_by($order_id)) {
         $renewal_order = $order;
         $order = WC_Subscriptions_Renewal_Order::get_parent_order($renewal_order);
         $order_contains_failed_renewal = true;
     } else {
         $order_contains_failed_renewal = false;
     }
     if ($order_contains_failed_renewal || WC_Subscriptions_Order::order_contains_subscription($order) && WC_Subscriptions_Order::get_recurring_total($order) > 0 && 'yes' !== get_option(WC_Subscriptions_Admin::$option_prefix . '_turn_off_automatic_payments', 'no')) {
         // Only one subscription allowed in the cart when PayPal Standard is active
         $product = $order->get_product_from_item(array_pop(WC_Subscriptions_Order::get_recurring_items($order)));
         // It's a subscription
         $paypal_args['cmd'] = '_xclick-subscriptions';
         if (count($order->get_items()) > 1) {
             foreach ($order->get_items() as $item) {
                 if ($item['qty'] > 1) {
                     $item_names[] = $item['qty'] . ' x ' . self::paypal_item_name($item['name']);
                 } elseif ($item['qty'] > 0) {
                     $item_names[] = self::paypal_item_name($item['name']);
                 }
             }
             $paypal_args['item_name'] = self::paypal_item_name(sprintf(__('Order %s', 'woocommerce-subscriptions'), $order->get_order_number() . " - " . implode(', ', $item_names)));
         } else {
             $paypal_args['item_name'] = self::paypal_item_name($product->get_title());
         }
         $unconverted_periods = array('billing_period' => WC_Subscriptions_Order::get_subscription_period($order), 'trial_period' => WC_Subscriptions_Order::get_subscription_trial_period($order));
         $converted_periods = array();
         // Convert period strings into PayPay's format
         foreach ($unconverted_periods as $key => $period) {
             switch (strtolower($period)) {
                 case 'day':
                     $converted_periods[$key] = 'D';
                     break;
                 case 'week':
                     $converted_periods[$key] = 'W';
                     break;
                 case 'year':
                     $converted_periods[$key] = 'Y';
                     break;
                 case 'month':
                 default:
                     $converted_periods[$key] = 'M';
                     break;
             }
         }
         $price_per_period = WC_Subscriptions_Order::get_recurring_total($order);
         $subscription_interval = WC_Subscriptions_Order::get_subscription_interval($order);
         $subscription_length = WC_Subscriptions_Order::get_subscription_length($order);
         $subscription_installments = $subscription_length / $subscription_interval;
         $is_payment_change = WC_Subscriptions_Change_Payment_Gateway::$is_request_to_change_payment;
         $is_switch_order = WC_Subscriptions_Switcher::order_contains_subscription_switch($order->id);
         $is_synced_subscription = WC_Subscriptions_Synchroniser::order_contains_synced_subscription($order->id);
         $sign_up_fee = $is_payment_change ? 0 : WC_Subscriptions_Order::get_sign_up_fee($order);
         $initial_payment = $is_payment_change ? 0 : WC_Subscriptions_Order::get_total_initial_payment($order);
         if ($is_payment_change) {
             // Add a nonce to the order ID to avoid "This invoice has already been paid" error when changing payment method to PayPal when it was previously PayPal
             $paypal_args['invoice'] = $paypal_args['invoice'] . '-wcscpm-' . wp_create_nonce();
         } elseif ($order_contains_failed_renewal) {
             // Set the invoice details to the original order's invoice but also append a special string and this renewal orders ID so that we can match it up as a failed renewal order payment later
             $paypal_args['invoice'] = self::$invoice_prefix . ltrim($order->get_order_number(), '#') . '-wcsfrp-' . $renewal_order->id;
             $paypal_args['custom'] = serialize(array($order->id, $order->order_key));
         }
         if ($order_contains_failed_renewal) {
             $sign_up_fee = 0;
             $initial_payment = $renewal_order->get_total();
             // Initial payment can be left in case the customer is purchased other products with the payment
             $subscription_trial_length = 0;
             $subscription_installments = max($subscription_installments - WC_Subscriptions_Manager::get_subscriptions_completed_payment_count(WC_Subscriptions_Manager::get_subscription_key($order_id, $product->id)), 0);
             // If we're changing the payment date or switching subs, we need to set the trial period to the next payment date & installments to be the number of installments left
         } elseif ($is_payment_change || $is_switch_order || $is_synced_subscription) {
             $subscription_key = WC_Subscriptions_Manager::get_subscription_key($order_id, $product->id);
             // Give a free trial until the next payment date
             if ($is_switch_order) {
                 $next_payment_timestamp = get_post_meta($order->id, '_switched_subscription_first_payment_timestamp', true);
             } elseif ($is_synced_subscription) {
                 $next_payment_timestamp = WC_Subscriptions_Synchroniser::calculate_first_payment_date($product, 'timestamp');
             } else {
                 $next_payment_timestamp = WC_Subscriptions_Manager::get_next_payment_date($subscription_key, $order->user_id, 'timestamp');
             }
             // When the subscription is on hold
             if ($next_payment_timestamp != false && !empty($next_payment_timestamp)) {
                 $trial_until = self::calculate_trial_periods_until($next_payment_timestamp);
                 $subscription_trial_length = $trial_until['first_trial_length'];
                 $converted_periods['trial_period'] = $trial_until['first_trial_period'];
                 $second_trial_length = $trial_until['second_trial_length'];
                 $second_trial_period = $trial_until['second_trial_period'];
             } else {
                 $subscription_trial_length = 0;
             }
             // If is a payment change, we need to account for completed payments on the number of installments owing
             if ($is_payment_change && $subscription_length > 0) {
                 $subscription_installments -= WC_Subscriptions_Manager::get_subscriptions_completed_payment_count($subscription_key);
             }
         } else {
             $subscription_trial_length = WC_Subscriptions_Order::get_subscription_trial_length($order);
         }
         if ($subscription_trial_length > 0) {
             // Specify a free trial period
             if ($is_switch_order || $is_synced_subscription || $initial_payment != $sign_up_fee) {
                 $paypal_args['a1'] = $initial_payment > 0 ? $initial_payment : 0;
             } else {
                 $paypal_args['a1'] = $sign_up_fee > 0 ? $sign_up_fee : 0;
                 // Maybe add the sign up fee to the free trial period
             }
             // Trial period length
             $paypal_args['p1'] = $subscription_trial_length;
             // Trial period
             $paypal_args['t1'] = $converted_periods['trial_period'];
             // We need to use a second trial period before we have more than 90 days until the next payment
             if (isset($second_trial_length) && $second_trial_length > 0) {
                 $paypal_args['a2'] = 0.01;
                 // Alas, although it's undocumented, PayPal appears to require a non-zero value in order to allow a second trial period
                 $paypal_args['p2'] = $second_trial_length;
                 $paypal_args['t2'] = $second_trial_period;
             }
         } elseif ($sign_up_fee > 0 || $initial_payment != $price_per_period) {
             // No trial period, so charge sign up fee and per period price for the first period
             if ($subscription_installments == 1) {
                 $param_number = 3;
             } else {
                 $param_number = 1;
             }
             $paypal_args['a' . $param_number] = $initial_payment;
             // Sign Up interval
             $paypal_args['p' . $param_number] = $subscription_interval;
             // Sign Up unit of duration
             $paypal_args['t' . $param_number] = $converted_periods['billing_period'];
         }
         // We have a recurring payment
         if (!isset($param_number) || $param_number == 1) {
             // Subscription price
             $paypal_args['a3'] = $price_per_period;
             // Subscription duration
             $paypal_args['p3'] = $subscription_interval;
             // Subscription period
             $paypal_args['t3'] = $converted_periods['billing_period'];
         }
         // Recurring payments
         if ($subscription_installments == 1 || $sign_up_fee > 0 && $subscription_trial_length == 0 && $subscription_installments == 2) {
             // Non-recurring payments
             $paypal_args['src'] = 0;
         } else {
             $paypal_args['src'] = 1;
             if ($subscription_installments > 0) {
                 if ($sign_up_fee > 0 && $subscription_trial_length == 0) {
                     // An initial period is being used to charge a sign-up fee
                     $subscription_installments--;
                 }
                 $paypal_args['srt'] = $subscription_installments;
             }
         }
         // Don't reattempt failed payments, instead let Subscriptions handle the failed payment
         $paypal_args['sra'] = 0;
         // Force return URL so that order description & instructions display
         $paypal_args['rm'] = 2;
     }
     return $paypal_args;
 }
 /**
  * Outputs the content for each column.
  *
  * @param array $item A singular item (one full row's worth of data)
  * @param array $column_name The name/slug of the column to be processed
  * @return string Text or HTML to be placed inside the column <td>
  * @since 1.0
  */
 public function column_default($item, $column_name)
 {
     global $woocommerce;
     $current_gmt_time = gmdate('U');
     switch ($column_name) {
         case 'status':
             $actions = array();
             $action_url = add_query_arg(array('page' => $_REQUEST['page'], 'user' => $item['user_id'], 'subscription' => $item['subscription_key'], '_wpnonce' => wp_create_nonce($item['subscription_key'])));
             if (isset($_REQUEST['status'])) {
                 $action_url = add_query_arg(array('status' => $_REQUEST['status']), $action_url);
             }
             $order = new WC_Order($item['order_id']);
             $all_statuses = array('active' => __('Reactivate', WC_Subscriptions::$text_domain), 'on-hold' => __('Suspend', WC_Subscriptions::$text_domain), 'cancelled' => __('Cancel', WC_Subscriptions::$text_domain), 'trash' => __('Trash', WC_Subscriptions::$text_domain), 'deleted' => __('Delete Permanently', WC_Subscriptions::$text_domain));
             foreach ($all_statuses as $status => $label) {
                 if (WC_Subscriptions_Manager::can_subscription_be_changed_to($status, $item['subscription_key'], $item['user_id'])) {
                     $action = 'deleted' == $status ? 'delete' : $status;
                     // For built in CSS
                     $actions[$action] = sprintf('<a href="%s">%s</a>', add_query_arg('new_status', $status, $action_url), $label);
                 }
             }
             if ($item['status'] == 'pending') {
                 unset($actions['active']);
                 unset($actions['trash']);
             } elseif (!in_array($item['status'], array('cancelled', 'expired', 'suspended'))) {
                 unset($actions['trash']);
             }
             $actions = apply_filters('woocommerce_subscriptions_list_table_actions', $actions, $item);
             $column_content = sprintf('<mark class="%s">%s</mark> %s', sanitize_title($item[$column_name]), WC_Subscriptions_Manager::get_status_to_display($item[$column_name], $item['subscription_key'], $item['user_id']), $this->row_actions($actions));
             $column_content = apply_filters('woocommerce_subscriptions_list_table_column_status_content', $column_content, $item, $actions, $this);
             break;
         case 'title':
             //Return the title contents
             $column_content = sprintf('<a href="%s">%s</a>', get_edit_post_link($item['product_id']), WC_Subscriptions_Order::get_item_name($item['order_id'], $item['product_id']));
             $column_content .= sprintf('<input type="hidden" class="%1$s" name="%2$s[%3$s][%4$s][][%1$s]" value="%5$s" />', 'product_id', $this->_args['plural'], $item['user_id'], $item['subscription_key'], $item['product_id']);
             $order = new WC_Order($item['order_id']);
             $order_item = WC_Subscriptions_Order::get_item_by_product_id($order, $item['product_id']);
             $product = $order->get_product_from_item($order_item);
             if (isset($product->variation_data)) {
                 $column_content .= '<br />' . woocommerce_get_formatted_variation($product->variation_data, true);
             }
             break;
         case 'order_id':
             $order = new WC_Order($item[$column_name]);
             $column_content = sprintf('<a href="%1$s">%2$s</a>', get_edit_post_link($item[$column_name]), sprintf(__('Order %s', WC_Subscriptions::$text_domain), $order->get_order_number()));
             $column_content .= sprintf('<input type="hidden" class="%1$s" name="%2$s[%3$s][%4$s][][%1$s]" value="%5$s" />', $column_name, $this->_args['plural'], $item['user_id'], $item['subscription_key'], $item[$column_name]);
             break;
         case 'user':
             $user = get_user_by('id', $item['user_id']);
             $column_content = sprintf('<a href="%s">%s</a>', admin_url('user-edit.php?user_id=' . $user->ID), ucfirst($user->display_name));
             $column_content .= sprintf('<input type="hidden" class="%1$s" name="%2$s[%3$s][%4$s][][%1$s]" value="%5$s" />', 'user_id', $this->_args['plural'], $item['user_id'], $item['subscription_key'], $item['user_id']);
             break;
         case 'start_date':
         case 'expiry_date':
         case 'end_date':
             if ($column_name == 'expiry_date' && $item[$column_name] == 0) {
                 $column_content = __('Never', WC_Subscriptions::$text_domain);
             } else {
                 if ($column_name == 'end_date' && $item[$column_name] == 0) {
                     $column_content = __('Not yet ended', WC_Subscriptions::$text_domain);
                 } else {
                     $gmt_timestamp = strtotime($item[$column_name]);
                     $user_timestamp = $gmt_timestamp + get_option('gmt_offset') * 3600;
                     $column_content = sprintf('<time title="%s">%s</time>', esc_attr($gmt_timestamp), date_i18n(woocommerce_date_format(), $user_timestamp));
                 }
             }
             break;
         case 'trial_expiry_date':
             $trial_expiration = WC_Subscriptions_Manager::get_trial_expiration_date($item['subscription_key'], $item['user_id'], 'timestamp');
             if (empty($trial_expiration)) {
                 $column_content = '-';
             } else {
                 $column_content = sprintf('<time title="%s">%s</time>', esc_attr($trial_expiration), date_i18n(woocommerce_date_format(), $trial_expiration + get_option('gmt_offset') * 3600));
             }
             break;
         case 'last_payment_date':
             $last_payment_timestamp = strtotime($item['last_payment_date']);
             $time_diff = $current_gmt_time - $last_payment_timestamp;
             if ($time_diff > 0 && $time_diff < 7 * 24 * 60 * 60) {
                 $last_payment = sprintf(__('%s ago', WC_Subscriptions::$text_domain), human_time_diff($last_payment_timestamp, $current_gmt_time));
             } else {
                 $last_payment = date_i18n(woocommerce_date_format(), $last_payment_timestamp + get_option('gmt_offset') * 3600);
             }
             $column_content = sprintf('<time title="%s">%s</time>', esc_attr($last_payment_timestamp), $last_payment);
             break;
         case 'next_payment_date':
             $next_payment_timestamp = WC_Subscriptions_Manager::get_next_payment_date($item['subscription_key'], $item['user_id'], 'timestamp');
             if ($next_payment_timestamp == 0) {
                 $column_content = '-';
             } else {
                 // Convert to site time
                 $time_diff = $next_payment_timestamp - $current_gmt_time;
                 if ($time_diff > 0 && $time_diff < 7 * 24 * 60 * 60) {
                     $next_payment = sprintf(__('In %s', WC_Subscriptions::$text_domain), human_time_diff($current_gmt_time, $next_payment_timestamp));
                 } else {
                     $next_payment = date_i18n(woocommerce_date_format(), $next_payment_timestamp + get_option('gmt_offset') * 3600);
                 }
                 $column_content = sprintf('<time class="next-payment-date" title="%s">%s</time>', esc_attr($next_payment_timestamp), $next_payment);
                 if (WC_Subscriptions_Manager::can_subscription_be_changed_to('new-payment-date', $item['subscription_key'], $item['user_id'])) {
                     $column_content .= '<div class="edit-date-div row-actions hide-if-no-js">';
                     $column_content .= '<img class="date-picker-icon" src="' . admin_url('images/date-button.gif') . '" title="Date Picker Icon"/>';
                     $column_content .= '<a href="#edit_timestamp" class="edit-timestamp" tabindex="4">' . __('Change', WC_Subscriptions::$text_domain) . '</a>';
                     $column_content .= '<div class="date-picker-div hide-if-js">';
                     $column_content .= WC_Subscriptions_Manager::touch_time(array('date' => date('Y-m-d', $next_payment_timestamp), 'echo' => false, 'multiple' => true, 'include_time' => false));
                     $column_content .= '</div>';
                     $column_content .= '</form>';
                 }
             }
             break;
         case 'renewal_order_count':
             $count = WC_Subscriptions_Renewal_Order::get_renewal_order_count($item['order_id']);
             $column_content = sprintf('<a href="%1$s">%2$d</a>', admin_url('edit.php?post_status=all&post_type=shop_order&_renewal_order_parent_id=' . absint($item['order_id'])), $count);
             break;
     }
     return $column_content;
 }
Пример #12
0
function blendercloud_api($atts)
{
    $user_data = array('shop_id' => '0', 'cloud_access' => 0, 'expiration_date' => '1970-01-01 00:00:00');
    $last_expiration_date = new DateTime('1970-01-01 00:00:00');
    // map blenderid to userid
    $args = array('search' => $_GET['blenderid'], 'search_columns' => array('user_login'));
    $user_query = new WP_User_Query($args);
    // Get the results from the query, returning the first user
    $users = $user_query->get_results();
    if (!empty($users)) {
        $user_id = $users[0]->ID;
        $user_data['shop_id'] = $user_id;
        // process simple products (prepaid subscriptions)
        $order_ids = bo_get_all_user_orders($user_id, 'completed');
        foreach ($order_ids as $order_id) {
            $order = new WC_Order($order_id);
            $order_date = $order->order_date;
            $items = $order->get_items();
            foreach ($items as $item) {
                $tmp = bo_empty_subscription_line();
                $product_id = $item['product_id'];
                $product = get_product($product_id);
                $sku = $product->get_sku();
                $expiry_date = new DateTime($order_date);
                $tmp['sku'] = $sku;
                switch ($sku) {
                    case 'cloud-prepaid-3':
                    case 'cloud-prepaid-3-renewal':
                        $expiry_date->modify('+3 month');
                        break;
                    case 'cloud-prepaid-18':
                        $expiry_date->modify('+18 month');
                        break;
                    default:
                        continue 2;
                        // skip to next product
                }
                $tmp['expiration_date'] = $expiry_date->format('Y-m-d H:i:s');
                $tmp['subscription_status'] = 'prepaid';
                $now = new DateTime("now");
                if ($expiry_date > $now) {
                    $tmp['cloud_access'] = 1;
                }
                if ($expiry_date > $last_expiration_date) {
                    $last_expiration_date = $expiry_date;
                }
                $user_data['subscriptions'][] = $tmp;
            }
        }
        // process recurring subscriptions
        $subscriptions = WC_Subscriptions_Manager::get_users_subscriptions($user_id);
        if (!empty($subscriptions)) {
            // iterate over all subscriptions.
            foreach ($subscriptions as $subscription_details) {
                if ($subscription_details['status'] != 'trash') {
                    $order_id = $subscription_details['order_id'];
                    $product_id = $subscription_details['product_id'];
                    $order = new WC_Order($order_id);
                    // print_r($order);
                    // $next_payment_date	= WC_Subscriptions_Manager::get_next_payment_date( $subscription_key, $user_id, 'mysql' );
                    $subscription_key = WC_Subscriptions_Manager::get_subscription_key($order_id, $product_id);
                    if ($subscription_details['expiry_date'] == 0 && !in_array($subscription_details['status'], array('cancelled', 'switched'))) {
                        $end_time = WC_Subscriptions_Manager::get_next_payment_date($subscription_key, $user_id, 'mysql');
                        $end_timestamp = strtotime($end_time);
                    } else {
                        if (in_array($subscription_details['status'], array('cancelled', 'switched'))) {
                            $end_of_prepaid_term = wc_next_scheduled_action('scheduled_subscription_end_of_prepaid_term', array('user_id' => (int) $user_id, 'subscription_key' => $subscription_key));
                            if (false === $end_of_prepaid_term) {
                                $end_timestamp = strtotime($subscription_details['end_date']);
                            } else {
                                $end_timestamp = $end_of_prepaid_term;
                            }
                        } else {
                            $end_timestamp = strtotime($subscription_details['expiry_date']);
                        }
                    }
                    //					if( $users[0]->data->user_email == '*****@*****.**' ) {
                    //						print_r($subscription_details);
                    //					}
                    if ($subscription_details['status'] == 'cancelled') {
                        $end_timestamp = strtotime($subscription_details['trial_expiry_date']);
                    }
                    if ($subscription_details['status'] == 'on-hold') {
                        $end_timestamp = strtotime($subscription_details['last_payment_date']);
                    }
                    $end_time = date("Y-m-d H:i:s", $end_timestamp);
                    $product = get_product($product_id);
                    $sku = $product->get_sku();
                    $tmp = bo_empty_subscription_line();
                    $tmp['expiration_date'] = $end_time;
                    $tmp['subscription_status'] = $subscription_details['status'];
                    $expiry_date = new DateTime($end_time);
                    if ($expiry_date > $last_expiration_date) {
                        $last_expiration_date = $expiry_date;
                    }
                    $now = new DateTime("now");
                    $tmp['cloud_access'] = $expiry_date > $now ? 1 : 0;
                    $tmp['sku'] = $sku;
                    // if order is refunded, stop access
                    if ($order->status == 'refunded') {
                        $tmp['expiration_date'] = $end_time;
                        $tmp['subscription_status'] = 'refunded';
                        $tmp['cloud_access'] = 0;
                    }
                    switch ($sku) {
                        case 'cloud-subscription-1-renewal':
                        case 'cloud-subscription-3':
                            //$tmp['failed_payments'] = $subscription['failed_payments'];
                            break;
                        case 'cloud-subscription-team':
                            // purchased team size
                            $variation_id = $subscription_details['variation_id'];
                            // find variation info from order to pass on # of seats
                            $order = new WC_Order($order_id);
                            $items = $order->get_items();
                            $team_members = 0;
                            foreach ($items as $item) {
                                // does product variation id match the current subscription?
                                if ($item['item_meta']['_variation_id'][0] == $variation_id) {
                                    $team_members = $item['item_meta']['pa_team-size'][0];
                                }
                            }
                            $tmp['team_members'] = $team_members;
                            break;
                    }
                    $user_data['subscriptions'][] = $tmp;
                }
            }
        }
    }
    // add one grace day to expiration
    $last_expiration_date->add(DateInterval::createfromdatestring('+1 day'));
    $user_data['expiration_date'] = $last_expiration_date->format('Y-m-d H:i:s');
    $now = new DateTime("now");
    if ($last_expiration_date > $now) {
        $user_data['cloud_access'] = 1;
    }
    //echo "<pre>";print_r($user_data);
    echo json_encode($user_data, JSON_PRETTY_PRINT);
    die;
}
Пример #13
0
function woo_ce_get_subscription_next_payment( $subscription_key = '', $user_id = 0 ) {

	$next_payment = '-';
	// Check that get_next_payment_date() exists within the WC_Subscriptions_Manager class
	if( method_exists( 'WC_Subscriptions_Manager', 'get_next_payment_date' ) ) {
		// Check that $subscription_key and $user_id aren't empty
		if( $subscription_key && !empty( $user_id ) ) {
			if( $next_payment_timestamp = WC_Subscriptions_Manager::get_next_payment_date( $subscription_key, $user_id, 'timestamp' ) ) {
				// Date formatting for Next Payment is provided by WooCommerce Subscriptions
				$time_diff = $next_payment_timestamp - gmdate( 'U' );
				if( $time_diff > 0 && $time_diff < 7 * 24 * 60 * 60 )
					$next_payment = sprintf( __( 'In %s', 'woocommerce-subscriptions' ), human_time_diff( $next_payment_timestamp ) );
				else
					$next_payment = date_i18n( woocommerce_date_format(), $next_payment_timestamp );
			}
		}
	}
	return $next_payment;

}