/**
  * WCS API function to get all the subscriptions tied to a particular customer.
  *
  * @since 2.0
  * @param $id int
  * @param $fields array
  */
 public function get_customer_subscriptions($id, $fields = null)
 {
     global $wpdb;
     // check the customer id given is a valid customer in the store. We're able to leech off WC-API for this.
     $id = $this->validate_request($id, 'customer', 'read');
     if (is_wp_error($id)) {
         return $id;
     }
     $subscription_ids = $wpdb->get_col($wpdb->prepare("SELECT ID, post_date_gmt\n\t\t\t\t\t\tFROM {$wpdb->posts} AS posts\n\t\t\t\t\t\tLEFT JOIN {$wpdb->postmeta} AS meta on posts.ID = meta.post_id\n\t\t\t\t\t\tWHERE meta.meta_key = '_customer_user'\n\t\t\t\t\t\tAND   meta.meta_value = '%d'\n\t\t\t\t\t\tAND   posts.post_type = 'shop_subscription'\n\t\t\t\t\t\tAND   posts.post_status IN ( '" . implode("','", array_keys(wcs_get_subscription_statuses())) . "' )\n\t\t\t\t\t\tGROUP BY posts.ID\n\t\t\t\t\t\tORDER BY posts.post_date_gmt DESC\n\t\t\t\t\t", $id));
     $subscriptions = array();
     foreach ($subscription_ids as $subscription_id) {
         $subscriptions[] = WC()->api->WC_API_Subscriptions->get_subscription($subscription_id, $fields);
     }
     return array('customer_subscriptions' => apply_filters('wc_subscriptions_api_customer_subscriptions', $subscriptions, $id, $fields, $subscription_ids, $this->server));
 }
/**
 * Get the nice name for a subscription's status
 *
 * @since  2.0
 * @param  string $status
 * @return string
 */
function wcs_get_subscription_status_name($status)
{
    if (!is_string($status)) {
        return new WP_Error('woocommerce_subscription_wrong_status_format', __('Can not get status name. Status is not a string.', 'woocommerce-subscriptions'));
    }
    $statuses = wcs_get_subscription_statuses();
    $sanitized_status_key = wcs_sanitize_subscription_status_key($status);
    // if the sanitized status key is not in the list of filtered subscription names, return the
    // original key, without the wc-
    $status_name = isset($statuses[$sanitized_status_key]) ? $statuses[$sanitized_status_key] : $status;
    return apply_filters('woocommerce_subscription_status_name', $status_name, $status);
}
    /**
     * Output the metabox
     */
    public static function output($post)
    {
        global $the_subscription;
        if (!is_object($the_subscription) || $the_subscription->id !== $post->ID) {
            $the_subscription = wc_get_order($post->ID);
        }
        $subscription = $the_subscription;
        self::init_address_fields();
        wp_nonce_field('woocommerce_save_data', 'woocommerce_meta_nonce');
        ?>
		<style type="text/css">
			#post-body-content, #titlediv, #major-publishing-actions, #minor-publishing-actions, #visibility, #submitdiv { display:none }
		</style>
		<div class="panel-wrap woocommerce">
			<input name="post_title" type="hidden" value="<?php 
        echo empty($post->post_title) ? esc_attr(get_post_type_object($subscription->post->post_type)->labels->singular_name) : esc_attr($post->post_title);
        ?>
" />
			<input name="post_status" type="hidden" value="<?php 
        echo esc_attr($subscription->get_status());
        ?>
" />
			<div id="order_data" class="panel">

				<h2><?php 
        // translators: placeholder is the ID of the subscription
        printf(esc_html_x('Subscription %s details', 'edit subscription header', 'woocommerce-subscriptions'), esc_html($subscription->get_order_number()));
        ?>
</h2>

				<div class="order_data_column_container">
					<div class="order_data_column">

						<p class="form-field form-field-wide wc-customer-user">
							<label for="customer_user"><?php 
        esc_html_e('Customer:', 'woocommerce-subscriptions');
        ?>
 <?php 
        if (!empty($subscription->customer_user)) {
            $args = array('post_status' => 'all', 'post_type' => 'shop_subscription', '_customer_user' => absint($subscription->customer_user));
            printf('<a href="%s">%s &rarr;</a>', esc_url(add_query_arg($args, admin_url('edit.php'))), esc_html__('View other subscriptions', 'woocommerce-subscriptions'));
        }
        ?>
</label>
							<?php 
        $user_string = '';
        $user_id = '';
        if (!empty($subscription->customer_user) && false !== get_userdata($subscription->customer_user)) {
            $user_id = absint($subscription->customer_user);
            $user = get_user_by('id', $user_id);
            $user_string = esc_html($user->display_name) . ' (#' . absint($user->ID) . ' &ndash; ' . esc_html($user->user_email);
        }
        ?>
							<input type="hidden" class="wc-customer-search" id="customer_user" name="customer_user" data-placeholder="<?php 
        esc_attr_e('Search for a customer&hellip;', 'woocommerce-subscriptions');
        ?>
" data-selected="<?php 
        echo esc_attr($user_string);
        ?>
" value="<?php 
        echo esc_attr($user_id);
        ?>
" />
						</p>

						<p class="form-field form-field-wide">
							<label for="order_status"><?php 
        esc_html_e('Subscription Status:', 'woocommerce-subscriptions');
        ?>
</label>
							<select id="order_status" name="order_status">
								<?php 
        $statuses = wcs_get_subscription_statuses();
        foreach ($statuses as $status => $status_name) {
            if (!$subscription->can_be_updated_to($status) && !$subscription->has_status(str_replace('wc-', '', $status))) {
                continue;
            }
            echo '<option value="' . esc_attr($status) . '" ' . selected($status, 'wc-' . $subscription->get_status(), false) . '>' . esc_html($status_name) . '</option>';
        }
        ?>
							</select>
						</p>

						<?php 
        do_action('woocommerce_admin_order_data_after_order_details', $subscription);
        ?>

					</div>
					<div class="order_data_column">
						<h4><?php 
        esc_html_e('Billing Details', 'woocommerce-subscriptions');
        ?>
 <a class="edit_address" href="#"><a href="#" class="tips load_customer_billing" data-tip="Load billing address" style="display:none;">Load billing address</a></a></h4>
						<?php 
        // Display values
        echo '<div class="address">';
        if ($subscription->get_formatted_billing_address()) {
            echo '<p><strong>' . esc_html__('Address', 'woocommerce-subscriptions') . ':</strong>' . wp_kses($subscription->get_formatted_billing_address(), array('br' => array())) . '</p>';
        } else {
            echo '<p class="none_set"><strong>' . esc_html__('Address', 'woocommerce-subscriptions') . ':</strong> ' . esc_html__('No billing address set.', 'woocommerce-subscriptions') . '</p>';
        }
        foreach (self::$billing_fields as $key => $field) {
            if (isset($field['show']) && false === $field['show']) {
                continue;
            }
            $field_name = 'billing_' . $key;
            if ($subscription->{$field_name}) {
                echo '<p><strong>' . esc_html($field['label']) . ':</strong> ' . wp_kses_post(make_clickable(esc_html($subscription->{$field_name}))) . '</p>';
            }
        }
        echo '<p' . (!empty($subscription->payment_method) ? ' class="' . esc_attr($subscription->payment_method) . '"' : '') . '><strong>' . esc_html__('Payment Method', 'woocommerce-subscriptions') . ':</strong>' . wp_kses_post(nl2br($subscription->get_payment_method_to_display()));
        // Display help tip
        if (!empty($subscription->payment_method) && !$subscription->is_manual()) {
            echo '<img class="help_tip" data-tip="Gateway ID: [' . esc_attr($subscription->payment_gateway->id) . ']" src="' . esc_url(WC()->plugin_url()) . '/assets/images/help.png" height="16" width="16" />';
        }
        echo '</p>';
        echo '</div>';
        // Display form
        echo '<div class="edit_address">';
        foreach (self::$billing_fields as $key => $field) {
            if (!isset($field['type'])) {
                $field['type'] = 'text';
            }
            switch ($field['type']) {
                case 'select':
                    // allow for setting a default value programaticaly, and draw the selectbox
                    woocommerce_wp_select(array('id' => '_billing_' . $key, 'label' => $field['label'], 'options' => $field['options'], 'value' => isset($field['value']) ? $field['value'] : null));
                    break;
                default:
                    // allow for setting a default value programaticaly, and draw the textbox
                    woocommerce_wp_text_input(array('id' => '_billing_' . $key, 'label' => $field['label'], 'value' => isset($field['value']) ? $field['value'] : null));
                    break;
            }
        }
        WCS_Change_Payment_Method_Admin::display_fields($subscription);
        echo '</div>';
        do_action('woocommerce_admin_order_data_after_billing_address', $subscription);
        ?>
					</div>
					<div class="order_data_column">

						<h4><?php 
        esc_html_e('Shipping Details', 'woocommerce-subscriptions');
        ?>
							<a class="edit_address" href="#">
								<a href="#" class="tips billing-same-as-shipping" data-tip="Copy from billing" style="display:none;">Copy from billing</a>
								<a href="#" class="tips load_customer_shipping" data-tip="Load shipping address" style="display:none;">Load shipping address</a>
							</a>
						</h4>
						<?php 
        // Display values
        echo '<div class="address">';
        if ($subscription->get_formatted_shipping_address()) {
            echo '<p><strong>' . esc_html__('Address', 'woocommerce-subscriptions') . ':</strong>' . wp_kses($subscription->get_formatted_shipping_address(), array('br' => array())) . '</p>';
        } else {
            echo '<p class="none_set"><strong>' . esc_html__('Address', 'woocommerce-subscriptions') . ':</strong> ' . esc_html__('No shipping address set.', 'woocommerce-subscriptions') . '</p>';
        }
        if (self::$shipping_fields) {
            foreach (self::$shipping_fields as $key => $field) {
                if (isset($field['show']) && false === $field['show']) {
                    continue;
                }
                $field_name = 'shipping_' . $key;
                if (!empty($subscription->{$field_name})) {
                    echo '<p><strong>' . esc_html($field['label']) . ':</strong> ' . wp_kses_post(make_clickable(esc_html($subscription->{$field_name}))) . '</p>';
                }
            }
        }
        if (apply_filters('woocommerce_enable_order_notes_field', 'yes' == get_option('woocommerce_enable_order_comments', 'yes')) && $post->post_excerpt) {
            echo '<p><strong>' . esc_html__('Customer Note', 'woocommerce-subscriptions') . ':</strong> ' . wp_kses_post(nl2br($post->post_excerpt)) . '</p>';
        }
        echo '</div>';
        // Display form
        echo '<div class="edit_address">';
        if (self::$shipping_fields) {
            foreach (self::$shipping_fields as $key => $field) {
                if (!isset($field['type'])) {
                    $field['type'] = 'text';
                }
                switch ($field['type']) {
                    case 'select':
                        woocommerce_wp_select(array('id' => '_shipping_' . $key, 'label' => $field['label'], 'options' => $field['options']));
                        break;
                    default:
                        woocommerce_wp_text_input(array('id' => '_shipping_' . $key, 'label' => $field['label']));
                        break;
                }
            }
        }
        if (apply_filters('woocommerce_enable_order_notes_field', 'yes' == get_option('woocommerce_enable_order_comments', 'yes'))) {
            ?>
							<p class="form-field form-field-wide"><label for="excerpt"><?php 
            esc_html_e('Customer Note:', 'woocommerce-subscriptions');
            ?>
</label>
								<textarea rows="1" cols="40" name="excerpt" tabindex="6" id="excerpt" placeholder="<?php 
            esc_attr_e('Customer\'s notes about the order', 'woocommerce-subscriptions');
            ?>
"><?php 
            echo wp_kses_post($post->post_excerpt);
            ?>
</textarea></p>
								<?php 
        }
        echo '</div>';
        do_action('woocommerce_admin_order_data_after_shipping_address', $subscription);
        ?>
					</div>
				</div>
				<div class="clear"></div>
			</div>
		</div>
		<?php 
    }
 /**
  * Filters and sorting handler
  *
  * @param  array $vars
  * @return array
  */
 public function request_query($vars)
 {
     global $typenow;
     if ('shop_subscription' === $typenow) {
         // Filter the orders by the posted customer.
         if (isset($_GET['_customer_user']) && $_GET['_customer_user'] > 0) {
             $vars['meta_query'][] = array('key' => '_customer_user', 'value' => (int) $_GET['_customer_user'], 'compare' => '=');
         }
         if (isset($_GET['_wcs_product']) && $_GET['_wcs_product'] > 0) {
             $subscription_ids = wcs_get_subscriptions_for_product($_GET['_wcs_product']);
             if (!empty($subscription_ids)) {
                 $vars['post__in'] = $subscription_ids;
             } else {
                 // no subscriptions contain this product, but we need to pass post__in an ID that no post will have because WP returns all posts when post__in is an empty array: https://core.trac.wordpress.org/ticket/28099
                 $vars['post__in'] = array(0);
             }
         }
         if (!empty($_GET['_payment_method'])) {
             $payment_gateway_filter = 'none' == $_GET['_payment_method'] ? '' : $_GET['_payment_method'];
             $query_vars = array('post_type' => 'shop_subscription', 'posts_per_page' => -1, 'post_status' => 'any', 'fields' => 'ids', 'meta_query' => array(array('key' => '_payment_method', 'value' => $payment_gateway_filter)));
             // If there are already set post restrictions (post__in) apply them to this query
             if (isset($vars['post__in'])) {
                 $query_vars['post__in'] = $vars['post__in'];
             }
             $subscription_ids = get_posts($query_vars);
             if (!empty($subscription_ids)) {
                 $vars['post__in'] = $subscription_ids;
             } else {
                 $vars['post__in'] = array(0);
             }
         }
         // Sorting
         if (isset($vars['orderby'])) {
             switch ($vars['orderby']) {
                 case 'order_total':
                     $vars = array_merge($vars, array('meta_key' => '_order_total', 'orderby' => 'meta_value_num'));
                     break;
                 case 'last_payment_date':
                     add_filter('posts_clauses', array($this, 'posts_clauses'), 10, 2);
                     break;
                 case 'trial_end_date':
                 case 'next_payment_date':
                 case 'end_date':
                     $vars = array_merge($vars, array('meta_key' => sprintf('_schedule_%s', str_replace('_date', '', $vars['orderby'])), 'meta_type' => 'DATETIME', 'orderby' => 'meta_value'));
                     break;
             }
         }
         // Status
         if (!isset($vars['post_status'])) {
             $vars['post_status'] = array_keys(wcs_get_subscription_statuses());
         }
     }
     return $vars;
 }
 /**
  * Updates status of the subscription
  *
  * @param string $new_status Status to change the order to. No internal wc- prefix is required.
  * @param string $note (default: '') Optional note to add
  */
 public function update_status($new_status, $note = '', $manual = false)
 {
     if (!$this->id) {
         return;
     }
     // Standardise status names.
     $new_status = 'wc-' === substr($new_status, 0, 3) ? substr($new_status, 3) : $new_status;
     $new_status_key = 'wc-' . $new_status;
     $old_status = $this->get_status();
     $old_status_key = $this->post_status;
     if ($new_status !== $old_status || !in_array($this->post_status, array_keys(wcs_get_subscription_statuses()))) {
         // Only update is possible
         if (!$this->can_be_updated_to($new_status)) {
             $message = sprintf(__('Unable to change subscription status to "%s".', 'woocommerce-subscriptions'), $new_status);
             $this->add_order_note($message);
             do_action('woocommerce_subscription_unable_to_update_status', $this, $new_status, $old_status);
             // Let plugins handle it if they tried to change to an invalid status
             throw new Exception($message);
         }
         try {
             wp_update_post(array('ID' => $this->id, 'post_status' => $new_status_key));
             $this->post_status = $new_status_key;
             switch ($new_status) {
                 case 'pending':
                     // Nothing to do here
                     break;
                 case 'pending-cancel':
                     $end_date = $this->calculate_date('end_of_prepaid_term');
                     // If there is no future payment and no expiration date set, the customer has no prepaid term (this shouldn't be possible as only active subscriptions can be set to pending cancellation and an active subscription always has either an end date or next payment)
                     if (0 == $end_date) {
                         $end_date = current_time('mysql', true);
                     }
                     $this->delete_date('trial_end');
                     $this->delete_date('next_payment');
                     $this->update_dates(array('end' => $end_date));
                     break;
                 case 'completed':
                     // core WC order status mapped internally to avoid exceptions
                 // core WC order status mapped internally to avoid exceptions
                 case 'active':
                     // Recalculate and set next payment date
                     $next_payment = $this->get_time('next_payment');
                     if ($next_payment < gmdate('U')) {
                         // also accounts for a $next_payment of 0, meaning it's not set
                         $next_payment = $this->calculate_date('next_payment');
                         if ($next_payment > 0) {
                             $this->update_dates(array('next_payment' => $next_payment));
                         }
                     }
                     // Trial end date and end/expiration date don't change at all - they should be set when the subscription is first created
                     wcs_make_user_active($this->customer_user);
                     break;
                 case 'failed':
                     // core WC order status mapped internally to avoid exceptions
                 // core WC order status mapped internally to avoid exceptions
                 case 'on-hold':
                     // Record date of suspension - 'post_modified' column?
                     $this->update_suspension_count($this->suspension_count + 1);
                     wcs_maybe_make_user_inactive($this->customer_user);
                     break;
                 case 'cancelled':
                 case 'switched':
                 case 'expired':
                     $this->delete_date('trial_end');
                     $this->delete_date('next_payment');
                     $this->update_dates(array('end' => current_time('mysql', true)));
                     wcs_maybe_make_user_inactive($this->customer_user);
                     break;
             }
             $this->add_order_note(trim($note . ' ' . sprintf(__('Status changed from %s to %s.', 'woocommerce-subscriptions'), wcs_get_subscription_status_name($old_status), wcs_get_subscription_status_name($new_status))), 0, $manual);
             // dynamic hooks for convenience
             do_action('woocommerce_subscription_status_' . $new_status, $this);
             do_action('woocommerce_subscription_status_' . $old_status . '_to_' . $new_status, $this);
             // Trigger a hook with params we want
             do_action('woocommerce_subscription_status_updated', $this, $new_status, $old_status);
             // Trigger a hook with params matching WooCommerce's 'woocommerce_order_status_changed' hook so functions attached to it can be attached easily to subscription status changes
             do_action('woocommerce_subscription_status_changed', $this->id, $old_status, $new_status);
         } catch (Exception $e) {
             // Make sure the old status is restored
             wp_update_post(array('ID' => $this->id, 'post_status' => $old_status_key));
             $this->post_status = $old_status_key;
             $this->add_order_note(sprintf(__('Unable to change subscription status to "%s".', 'woocommerce-subscriptions'), $new_status));
             do_action('woocommerce_subscription_unable_to_update_status', $this, $new_status, $old_status);
             throw $e;
         }
     }
 }
 /**
  * Returns an associative array with the structure 'status' => 'count' for all subscriptions on the site
  * and includes an "all" status, representing all subscriptions.
  *
  * @since 1.4
  * @deprecated 2.0
  */
 public static function get_subscription_status_counts()
 {
     _deprecated_function(__METHOD__, '2.0');
     $results = wp_count_posts('shop_subscription');
     $count = array();
     foreach ($results as $status => $count) {
         if (in_array($status, array_keys(wcs_get_subscription_statuses())) || in_array($status, array('trash', 'draft'))) {
             $counts[$status] = $count;
         }
     }
     // Order with 'all' at the beginning, then alphabetically
     ksort($counts);
     $counts = array('all' => array_sum($counts)) + $counts;
     return apply_filters('woocommerce_subscription_status_counts', $counts);
 }
 /**
  * Filters and sorting handler
  *
  * @param  array $vars
  * @return array
  */
 public function request_query($vars)
 {
     global $typenow;
     if ('shop_subscription' === $typenow) {
         // Filter the orders by the posted customer.
         if (isset($_GET['_customer_user']) && $_GET['_customer_user'] > 0) {
             $vars['meta_key'] = '_customer_user';
             $vars['meta_value'] = (int) $_GET['_customer_user'];
         }
         if (isset($_GET['_wcs_product']) && $_GET['_wcs_product'] > 0) {
             $subscription_ids = wcs_get_subscriptions_for_product($_GET['_wcs_product']);
             if (!empty($subscription_ids)) {
                 $vars['post__in'] = $subscription_ids;
             } else {
                 // no subscriptions contain this product, but we need to pass post__in an ID that no post will have because WP returns all posts when post__in is an empty array: https://core.trac.wordpress.org/ticket/28099
                 $vars['post__in'] = array(0);
             }
         }
         // Sorting
         if (isset($vars['orderby'])) {
             switch ($vars['orderby']) {
                 case 'order_total':
                     $vars = array_merge($vars, array('meta_key' => '_order_total', 'orderby' => 'meta_value_num'));
                     break;
                 case 'last_payment_date':
                     add_filter('posts_clauses', array($this, 'posts_clauses'), 10, 2);
                     break;
                 case 'trial_end_date':
                 case 'next_payment_date':
                 case 'end_date':
                     $vars = array_merge($vars, array('meta_key' => sprintf('_schedule_%s', str_replace('_date', '', $vars['orderby'])), 'meta_type' => 'DATETIME', 'orderby' => 'meta_value'));
                     break;
             }
         }
         // Status
         if (!isset($vars['post_status'])) {
             $vars['post_status'] = array_keys(wcs_get_subscription_statuses());
         }
     }
     return $vars;
 }
 /**
  * Helper method to get order post objects
  *
  * We need to override WC_API_Orders::query_orders() because it uses wc_get_order_statuses()
  * for the query, but subscriptions use the values returned by wcs_get_subscription_statuses().
  *
  * @since 2.0
  * @param array $args request arguments for filtering query
  * @return WP_Query
  */
 protected function query_orders($args)
 {
     // set base query arguments
     $query_args = array('fields' => 'ids', 'post_type' => $this->post_type, 'post_status' => array_keys(wcs_get_subscription_statuses()));
     // add status argument
     if (!empty($args['status'])) {
         $statuses = 'wc-' . str_replace(',', ',wc-', $args['status']);
         $statuses = explode(',', $statuses);
         $query_args['post_status'] = $statuses;
         unset($args['status']);
     }
     $query_args = $this->merge_query_args($query_args, $args);
     return new WP_Query($query_args);
 }