/**
  * Add subscription related order item meta when a subscription product is added as an item to an order via Ajax.
  *
  * @param item_id int An order_item_id as returned by the insert statement of @see woocommerce_add_order_item()
  * @since 1.2.5
  * @version 1.4
  * @return void
  */
 public static function prefill_order_item_meta($item, $item_id)
 {
     $order_id = $_POST['order_id'];
     $product_id = $item['variation_id'] ? $item['variation_id'] : $item['product_id'];
     if ($item_id && WC_Subscriptions_Product::is_subscription($product_id)) {
         $order = new WC_Order($order_id);
         $_product = get_product($product_id);
         $recurring_amount = $_product->get_price_excluding_tax();
         $sign_up_fee = $_product->get_sign_up_fee_excluding_tax();
         $free_trial_length = WC_Subscriptions_Product::get_trial_length($product_id);
         woocommerce_add_order_item_meta($item_id, '_subscription_period', WC_Subscriptions_Product::get_period($product_id));
         woocommerce_add_order_item_meta($item_id, '_subscription_interval', WC_Subscriptions_Product::get_interval($product_id));
         woocommerce_add_order_item_meta($item_id, '_subscription_length', WC_Subscriptions_Product::get_length($product_id));
         woocommerce_add_order_item_meta($item_id, '_subscription_trial_length', $free_trial_length);
         woocommerce_add_order_item_meta($item_id, '_subscription_trial_period', WC_Subscriptions_Product::get_trial_period($product_id));
         woocommerce_add_order_item_meta($item_id, '_subscription_recurring_amount', $recurring_amount);
         woocommerce_add_order_item_meta($item_id, '_subscription_sign_up_fee', $sign_up_fee);
         woocommerce_add_order_item_meta($item_id, '_recurring_line_total', $recurring_amount);
         woocommerce_add_order_item_meta($item_id, '_recurring_line_tax', 0);
         woocommerce_add_order_item_meta($item_id, '_recurring_line_subtotal', $recurring_amount);
         woocommerce_add_order_item_meta($item_id, '_recurring_line_subtotal_tax', 0);
         WC_Subscriptions_Manager::create_pending_subscription_for_order($order_id, $item['product_id']);
         switch ($order->status) {
             case 'completed':
             case 'processing':
                 woocommerce_update_order_item_meta($item_id, '_subscription_status', 'active');
                 break;
             case 'on-hold':
                 woocommerce_update_order_item_meta($item_id, '_subscription_status', 'on-hold');
                 break;
             case 'failed':
             case 'cancelled':
                 woocommerce_add_order_item_meta($item_id, '_subscription_status', 'cancelled');
                 break;
         }
         // We need to override the line totals to $0 when there is a free trial
         if ($free_trial_length > 0 || $sign_up_fee > 0) {
             $line_total_keys = array('line_subtotal', 'line_total');
             // Make sure sign up fees are included in the total (or $0 if no sign up fee and a free trial)
             foreach ($line_total_keys as $line_total_key) {
                 $item[$line_total_key] = $sign_up_fee;
             }
             // If there is no free trial, make sure line totals include sign up fee and recurring fees
             if (0 == $free_trial_length) {
                 foreach ($line_total_keys as $line_total_key) {
                     $item[$line_total_key] += $recurring_amount;
                 }
             }
             foreach ($line_total_keys as $line_total_key) {
                 $item[$line_total_key] = WC_Subscriptions::format_total($item[$line_total_key], 2);
             }
         } else {
             $item['line_subtotal'] = $recurring_amount;
             $item['line_total'] = $recurring_amount;
         }
         woocommerce_update_order_item_meta($item_id, '_line_subtotal', $item['line_subtotal']);
         woocommerce_update_order_item_meta($item_id, '_line_total', $item['line_total']);
     }
     return $item;
 }
 /**
  * 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);
         }
     }
 }
 /**
  * Creates a new order for renewing a subscription product based on the details of a previous order.
  *
  * No trial periods or sign up fees are applied to the renewal order. However, if the order has failed
  * payments and the store manager has set failed payments to be added to renewal orders, then the
  * orders totals will be set to include the outstanding balance.
  *
  * If the $args['new_order_role'] flag is set to 'parent', then the renewal order will supersede the existing 
  * order. The existing order and subscription associated with it will be cancelled. A new order and
  * subscription will be created. 
  *
  * If the $args['new_order_role'] flag is 'child', the $original_order will remain the master order for the
  * subscription and the new order is just for accepting a recurring payment on the subscription.
  *
  * Renewal orders have the same meta data as the original order. If the renewal order is set to be a 'child'
  * then any subscription related meta data will not be stored on the new order. This is to keep subscription
  * meta data associated only with the one master order for the subscription.
  *
  * @param WC_Order|int $order The WC_Order object or ID of the order for which the a new order should be created.
  * @param string $product_id The ID of the subscription product in the order which needs to be added to the new order.
  * @param array $args (optional) An array of name => value flags:
  *         'new_order_role' string A flag to indicate whether the new order should become the master order for the subscription. Accepts either 'parent' or 'child'. Defaults to 'parent' - replace the existing order.
  *         'checkout_renewal' bool Indicates if invoked from an interactive cart/checkout session and certain order items are not set, like taxes, shipping as they need to be set in teh calling function, like @see WC_Subscriptions_Checkout::filter_woocommerce_create_order(). Default false.
  *         'failed_order_id' int For checkout_renewal true, indicates order id being replaced
  * @since 1.2
  */
 public static function generate_renewal_order($original_order, $product_id, $args = array())
 {
     global $wpdb, $woocommerce;
     if (!is_object($original_order)) {
         $original_order = new WC_Order($original_order);
     }
     if (!WC_Subscriptions_Order::order_contains_subscription($original_order) || !WC_Subscriptions_Order::is_item_subscription($original_order, $product_id)) {
         return false;
     }
     if (self::is_renewal($original_order, array('order_role' => 'child'))) {
         $original_order = self::get_parent_order($original_order);
     }
     if (!is_array($args)) {
         _deprecated_argument(__CLASS__ . '::' . __FUNCTION__, '1.3', __('Third parameter is now an array of name => value pairs. Use array( "new_order_role" => "parent" ) instead.', 'woocommerce-subscriptions'));
         $args = array('new_order_role' => $args);
     }
     $args = wp_parse_args($args, array('new_order_role' => 'parent', 'checkout_renewal' => false));
     $renewal_order_key = uniqid('order_');
     // Create the new order
     $renewal_order_data = array('post_type' => 'shop_order', 'post_title' => sprintf(__('Subscription Renewal Order – %s', 'woocommerce-subscriptions'), strftime(_x('%b %d, %Y @ %I:%M %p', 'Order date parsed by strftime', 'woocommerce-subscriptions'))), 'post_status' => 'publish', 'ping_status' => 'closed', 'post_excerpt' => $original_order->customer_note, 'post_author' => 1, 'post_password' => $renewal_order_key);
     $create_new_order = true;
     if ('child' == $args['new_order_role']) {
         $renewal_order_data['post_parent'] = $original_order->id;
     }
     if (true === $args['checkout_renewal']) {
         $renewal_order_id = null;
         if ($woocommerce->session->order_awaiting_payment > 0) {
             $renewal_order_id = absint($woocommerce->session->order_awaiting_payment);
         } elseif (isset($args['failed_order_id'])) {
             $failed_order_id = $args['failed_order_id'];
             /* Check order is unpaid by getting its status */
             $terms = wp_get_object_terms($failed_order_id, 'shop_order_status', array('fields' => 'slugs'));
             $order_status = isset($terms[0]) ? $terms[0] : 'pending';
             /* If paying on a pending order, we are resuming */
             if ($order_status == 'pending') {
                 $renewal_order_id = $failed_order_id;
             }
         }
         if ($renewal_order_id) {
             /* Check order is unpaid by getting its status */
             $terms = wp_get_object_terms($renewal_order_id, 'shop_order_status', array('fields' => 'slugs'));
             $order_status = isset($terms[0]) ? $terms[0] : 'pending';
             // Resume the unpaid order if its pending
             if ($order_status == 'pending' || $order_status == 'failed') {
                 // Update the existing order as we are resuming it
                 $create_new_order = false;
                 $renewal_order_data['ID'] = $renewal_order_id;
                 wp_update_post($renewal_order_data);
                 // Clear the old line items - we'll add these again in case they changed
                 $wpdb->query($wpdb->prepare("DELETE FROM {$wpdb->prefix}woocommerce_order_itemmeta WHERE order_item_id IN ( SELECT order_item_id FROM {$wpdb->prefix}woocommerce_order_items WHERE order_id = %d )", $renewal_order_id));
                 $wpdb->query($wpdb->prepare("DELETE FROM {$wpdb->prefix}woocommerce_order_items WHERE order_id = %d", $renewal_order_id));
             }
         }
     }
     if ($create_new_order) {
         $renewal_order_id = wp_insert_post($renewal_order_data);
     }
     // Set the order as pending
     wp_set_object_terms($renewal_order_id, 'pending', 'shop_order_status');
     // Set a unique key for this order
     update_post_meta($renewal_order_id, '_order_key', $renewal_order_key);
     $order_meta_query = "SELECT `meta_key`, `meta_value`\n\t\t\t\t\t\t\t FROM {$wpdb->postmeta}\n\t\t\t\t\t\t\t WHERE `post_id` = {$original_order->id}\n\t\t\t\t\t\t\t AND `meta_key` NOT IN ('_paid_date', '_completed_date', '_order_key', '_edit_lock', '_original_order')";
     // Superseding existing order so don't carry over payment details
     if ('parent' == $args['new_order_role'] || true === $args['checkout_renewal']) {
         $order_meta_query .= " AND `meta_key` NOT IN ('_payment_method', '_payment_method_title', '_recurring_payment_method', '_recurring_payment_method_title', '_shipping_method', '_shipping_method_title', '_recurring_shipping_method', '_recurring_shipping_method_title')";
     } else {
         $order_meta_query .= " AND `meta_key` NOT LIKE '_order_recurring_%' AND `meta_key` NOT IN ('_payment_method', '_payment_method_title', '_recurring_payment_method', '_recurring_payment_method_title', '_shipping_method', '_shipping_method_title', '_recurring_shipping_method', '_recurring_shipping_method_title')";
     }
     // Allow extensions to add/remove order meta
     $order_meta_query = apply_filters('woocommerce_subscriptions_renewal_order_meta_query', $order_meta_query, $original_order->id, $renewal_order_id, $args['new_order_role']);
     // Carry all the required meta from the old order over to the new order
     $order_meta = $wpdb->get_results($order_meta_query, 'ARRAY_A');
     $order_meta = apply_filters('woocommerce_subscriptions_renewal_order_meta', $order_meta, $original_order->id, $renewal_order_id, $args['new_order_role']);
     foreach ($order_meta as $meta_item) {
         add_post_meta($renewal_order_id, $meta_item['meta_key'], maybe_unserialize($meta_item['meta_value']), true);
     }
     $outstanding_balance = WC_Subscriptions_Order::get_outstanding_balance($original_order, $product_id);
     $failed_payment_multiplier = 1;
     if (false == $args['checkout_renewal']) {
         // If there are outstanding payment amounts, add them to the order, otherwise set the order details to the values of the recurring totals
         if ($outstanding_balance > 0 && 'yes' == get_option(WC_Subscriptions_Admin::$option_prefix . '_add_outstanding_balance', 'no')) {
             $failed_payment_multiplier = WC_Subscriptions_Order::get_failed_payment_count($original_order, $product_id);
         }
         // Set order totals based on recurring totals from the original order
         $cart_discount = $failed_payment_multiplier * get_post_meta($original_order->id, '_order_recurring_discount_cart', true);
         $order_discount = $failed_payment_multiplier * get_post_meta($original_order->id, '_order_recurring_discount_total', true);
         $order_shipping_tax = $failed_payment_multiplier * get_post_meta($original_order->id, '_order_recurring_shipping_tax_total', true);
         $order_shipping = $failed_payment_multiplier * get_post_meta($original_order->id, '_order_recurring_shipping_total', true);
         $order_tax = $failed_payment_multiplier * get_post_meta($original_order->id, '_order_recurring_tax_total', true);
         $order_total = $failed_payment_multiplier * get_post_meta($original_order->id, '_order_recurring_total', true);
         update_post_meta($renewal_order_id, '_cart_discount', $cart_discount);
         update_post_meta($renewal_order_id, '_order_discount', $order_discount);
         update_post_meta($renewal_order_id, '_order_shipping_tax', $order_shipping_tax);
         update_post_meta($renewal_order_id, '_order_shipping', $order_shipping);
         update_post_meta($renewal_order_id, '_order_tax', $order_tax);
         update_post_meta($renewal_order_id, '_order_total', $order_total);
         // Set shipping for orders created with WC 2.0.n (or when we are using WC 2.0.n)
         if (WC_Subscriptions::is_woocommerce_pre_2_1() || isset($original_order->recurring_shipping_method)) {
             update_post_meta($renewal_order_id, '_shipping_method', $original_order->recurring_shipping_method);
             update_post_meta($renewal_order_id, '_shipping_method_title', $original_order->recurring_shipping_method_title);
             // Also set recurring shipping as it's a parent renewal order
             if ('parent' == $args['new_order_role']) {
                 update_post_meta($renewal_order_id, '_recurring_shipping_method', $original_order->recurring_shipping_method);
                 update_post_meta($renewal_order_id, '_recurring_shipping_method_title', $original_order->recurring_shipping_method_title);
             }
         }
         // Apply the recurring shipping & payment methods to child renewal orders
         if ('child' == $args['new_order_role']) {
             update_post_meta($renewal_order_id, '_payment_method', $original_order->recurring_payment_method);
             update_post_meta($renewal_order_id, '_payment_method_title', $original_order->recurring_payment_method_title);
         }
         // Set order taxes based on recurring taxes from the original order
         $recurring_order_taxes = WC_Subscriptions_Order::get_recurring_taxes($original_order);
         foreach ($recurring_order_taxes as $index => $recurring_order_tax) {
             $item_ids = array();
             $item_ids[] = woocommerce_add_order_item($renewal_order_id, array('order_item_name' => $recurring_order_tax['name'], 'order_item_type' => 'tax'));
             // Also set recurring taxes on parent renewal orders
             if ('parent' == $args['new_order_role']) {
                 $item_ids[] = woocommerce_add_order_item($renewal_order_id, array('order_item_name' => $recurring_order_tax['name'], 'order_item_type' => 'recurring_tax'));
             }
             // Add line item meta
             foreach ($item_ids as $item_id) {
                 woocommerce_add_order_item_meta($item_id, 'compound', absint(isset($recurring_order_tax['compound']) ? $recurring_order_tax['compound'] : 0));
                 woocommerce_add_order_item_meta($item_id, 'tax_amount', woocommerce_clean($failed_payment_multiplier * $recurring_order_tax['tax_amount']));
                 woocommerce_add_order_item_meta($item_id, 'shipping_tax_amount', woocommerce_clean($failed_payment_multiplier * $recurring_order_tax['shipping_tax_amount']));
                 if (isset($recurring_order_tax['rate_id'])) {
                     woocommerce_add_order_item_meta($item_id, 'rate_id', $recurring_order_tax['rate_id']);
                 }
                 if (isset($recurring_order_tax['label'])) {
                     woocommerce_add_order_item_meta($item_id, 'label', $recurring_order_tax['label']);
                 }
             }
         }
         // Set up shipping items on renewal order
         $recurring_shipping_items = WC_Subscriptions_Order::get_recurring_shipping_methods($original_order);
         foreach ($recurring_shipping_items as $index => $recurring_shipping_item) {
             $item_ids = array();
             $item_ids[] = woocommerce_add_order_item($renewal_order_id, array('order_item_name' => $recurring_shipping_item['name'], 'order_item_type' => 'shipping'));
             // Also set recurring shipping as it's a parent renewal order
             if ('parent' == $args['new_order_role']) {
                 $item_ids[] = woocommerce_add_order_item($renewal_order_id, array('order_item_name' => $recurring_shipping_item['name'], 'order_item_type' => 'recurring_shipping'));
             }
             // Add shipping item meta
             foreach ($item_ids as $item_id) {
                 woocommerce_add_order_item_meta($item_id, 'method_id', $recurring_shipping_item['method_id']);
                 woocommerce_add_order_item_meta($item_id, 'cost', woocommerce_clean($failed_payment_multiplier * $recurring_shipping_item['cost']));
             }
         }
     }
     // Set line totals to be recurring line totals and remove the subscription/recurring related item meta from each order item
     $order_items = WC_Subscriptions_Order::get_recurring_items($original_order);
     // Allow extensions to add/remove items or item meta
     $order_items = apply_filters('woocommerce_subscriptions_renewal_order_items', $order_items, $original_order->id, $renewal_order_id, $product_id, $args['new_order_role']);
     if (true === $args['checkout_renewal']) {
         $cart_items = $woocommerce->cart->get_cart();
     }
     foreach ($order_items as $item_index => $order_item) {
         if ('child' == $args['new_order_role']) {
             $renewal_order_item_name = sprintf(__('Renewal of "%s" purchased in Order %s', 'woocommerce-subscriptions'), $order_item['name'], $original_order->get_order_number());
         } else {
             $renewal_order_item_name = $order_item['name'];
         }
         $renewal_order_item_name = apply_filters('woocommerce_subscriptions_renewal_order_item_name', $renewal_order_item_name, $order_item, $original_order);
         // Create order line item on the renewal order
         $recurring_item_id = woocommerce_add_order_item($renewal_order_id, array('order_item_name' => $renewal_order_item_name, 'order_item_type' => 'line_item'));
         if (true === $args['checkout_renewal']) {
             $cart_item = array();
             foreach ($cart_items as $item) {
                 if ($item['product_id'] == $order_item['product_id'] && (empty($order_item['variation_id']) || $item['variation_id'] == $order_item['variation_id'])) {
                     $cart_item = $item;
                 }
             }
             if (!empty($cart_item)) {
                 woocommerce_update_order_item_meta($recurring_item_id, '_line_total', woocommerce_format_decimal($cart_item['line_total']));
                 woocommerce_update_order_item_meta($recurring_item_id, '_line_tax', woocommerce_format_decimal($cart_item['line_tax']));
                 woocommerce_update_order_item_meta($recurring_item_id, '_line_subtotal', woocommerce_format_decimal($cart_item['line_subtotal']));
                 woocommerce_update_order_item_meta($recurring_item_id, '_line_subtotal_tax', woocommerce_format_decimal($cart_item['line_subtotal_tax']));
                 if (is_object($cart_item['data'])) {
                     woocommerce_update_order_item_meta($recurring_item_id, '_tax_class', $cart_item['data']->get_tax_class());
                 }
             }
             $cart_items = $woocommerce->cart->get_cart();
         }
         $item_meta = new WC_Order_Item_Meta($order_item['item_meta']);
         // Remove recurring line items and set item totals based on recurring line totals
         foreach ($item_meta->meta as $meta_key => $meta) {
             // $meta is an array, so the item needs to be extracted from $meta[0] (just like order meta on a WC Order)
             $meta_value = $meta[0];
             if (false === $args['checkout_renewal']) {
                 // Already set earlier
                 // Map line item totals based on recurring line totals
                 switch ($meta_key) {
                     case '_recurring_line_total':
                         woocommerce_delete_order_item_meta($recurring_item_id, '_line_total');
                         woocommerce_update_order_item_meta($recurring_item_id, '_line_total', woocommerce_format_decimal($failed_payment_multiplier * $meta_value));
                         break;
                     case '_recurring_line_tax':
                         woocommerce_delete_order_item_meta($recurring_item_id, '_line_tax');
                         woocommerce_update_order_item_meta($recurring_item_id, '_line_tax', woocommerce_format_decimal($failed_payment_multiplier * $meta_value));
                         break;
                     case '_recurring_line_subtotal':
                         woocommerce_delete_order_item_meta($recurring_item_id, '_line_subtotal');
                         woocommerce_update_order_item_meta($recurring_item_id, '_line_subtotal', woocommerce_format_decimal($failed_payment_multiplier * $meta_value));
                         break;
                     case '_recurring_line_subtotal_tax':
                         woocommerce_delete_order_item_meta($recurring_item_id, '_line_subtotal_tax');
                         woocommerce_update_order_item_meta($recurring_item_id, '_line_subtotal_tax', woocommerce_format_decimal($failed_payment_multiplier * $meta_value));
                         break;
                     default:
                         break;
                 }
             }
             // Copy over line item meta data, with some parent/child role based exceptions for recurring amounts
             $copy_to_renewal_item = true;
             switch ($meta_key) {
                 case '_recurring_line_total':
                 case '_recurring_line_tax':
                 case '_recurring_line_subtotal':
                 case '_recurring_line_subtotal_tax':
                 case '_subscription_recurring_amount':
                 case '_subscription_sign_up_fee':
                 case '_subscription_period':
                 case '_subscription_interval':
                 case '_subscription_length':
                 case '_subscription_trial_period':
                 case '_subscription_end_date':
                 case '_subscription_expiry_date':
                 case '_subscription_start_date':
                 case '_subscription_status':
                 case '_subscription_completed_payments':
                     if ('child' == $args['new_order_role']) {
                         $copy_to_renewal_item = false;
                     }
                     break;
                 case '_subscription_trial_length':
                     // We never want to duplicate free trials on renewal orders
                     $copy_to_renewal_item = false;
                     break;
                 case '_subscription_suspension_count':
                     // We want to reset some values for the new order
                 // We want to reset some values for the new order
                 case '_subscription_trial_expiry_date':
                 case '_subscription_failed_payments':
                     $copy_to_renewal_item = false;
                     $meta_value = 0;
                     break;
                 default:
                     break;
             }
             // Copy existing item over to new recurring order item
             if ($copy_to_renewal_item) {
                 woocommerce_add_order_item_meta($recurring_item_id, $meta_key, $meta_value);
             }
         }
     }
     if (false == $args['checkout_renewal']) {
         // Add fees
         foreach ($original_order->get_fees() as $item_id => $order_fee) {
             if (!isset($order_fee['recurring_line_total'])) {
                 continue;
             }
             $item_id = woocommerce_add_order_item($renewal_order_id, array('order_item_name' => $order_fee['name'], 'order_item_type' => 'fee'));
             woocommerce_add_order_item_meta($item_id, '_tax_class', $order_fee['tax_class']);
             woocommerce_add_order_item_meta($item_id, '_line_total', WC_Subscriptions::format_total($order_fee['recurring_line_total']));
             woocommerce_add_order_item_meta($item_id, '_line_tax', WC_Subscriptions::format_total($order_fee['recurring_line_tax']));
         }
     }
     // Keep a record of the original order's ID on the renewal order
     update_post_meta($renewal_order_id, '_original_order', $original_order->id, true);
     $renewal_order = new WC_Order($renewal_order_id);
     if ('parent' == $args['new_order_role']) {
         WC_Subscriptions_Manager::process_subscriptions_on_checkout($renewal_order_id);
         $original_order->add_order_note(sprintf(__('Order superseded by Renewal Order %s.', 'woocommerce-subscriptions'), $renewal_order->get_order_number()));
     }
     do_action('woocommerce_subscriptions_renewal_order_created', $renewal_order, $original_order, $product_id, $args['new_order_role']);
     return apply_filters('woocommerce_subscriptions_renewal_order_id', $renewal_order_id, $original_order, $product_id, $args['new_order_role']);
 }
 /**
  * When an order is added or updated from the admin interface, check if a subscription product
  * has been manually added to the order or the details of the subscription have been modified,
  * and create/update the subscription as required.
  *
  * Save subscription order meta items
  *
  * @param int $post_id The ID of the post which is the WC_Order object.
  * @param Object $post The post object of the order.
  * @since 1.1
  */
 public static function pre_process_shop_order_meta($post_id, $post)
 {
     global $woocommerce, $wpdb;
     $order_contains_subscription = false;
     $order = new WC_Order($post_id);
     $existing_product_ids = array();
     foreach ($order->get_items() as $existing_item) {
         $existing_product_ids[] = self::get_items_product_id($existing_item);
     }
     $product_ids = array();
     if (isset($_POST['order_item_id'])) {
         foreach ($_POST['order_item_id'] as $order_item_id) {
             $product_ids[$order_item_id] = woocommerce_get_order_item_meta($order_item_id, '_product_id');
         }
     }
     // Check if there are new subscription products to be added, or the order already has a subscription item
     foreach (array_merge($product_ids, $existing_product_ids) as $order_item_id => $product_id) {
         $is_existing_item = false;
         if (in_array($product_id, $existing_product_ids)) {
             $is_existing_item = true;
         }
         // If this is a new item and it's a subscription product, we have a subscription
         if (!$is_existing_item && WC_Subscriptions_Product::is_subscription($product_id)) {
             $order_contains_subscription = true;
         }
         // If this is an existing item and it's a subscription item, we have a subscription
         if ($is_existing_item && self::is_item_subscription($order, $product_id)) {
             $order_contains_subscription = true;
         }
     }
     if (!$order_contains_subscription) {
         return $post_id;
     }
     $existing_payment_method = get_post_meta($post_id, '_recurring_payment_method', true);
     $chosen_payment_method = isset($_POST['_recurring_payment_method']) ? stripslashes($_POST['_recurring_payment_method']) : '';
     // If the recurring payment method is changing, or it isn't set make sure we have correct manual payment flag set
     if (isset($_POST['_recurring_payment_method']) || empty($existing_payment_method) && ($chosen_payment_method != $existing_payment_method || empty($chosen_payment_method))) {
         $payment_gateways = $woocommerce->payment_gateways->payment_gateways();
         // Make sure the subscription is cancelled with the current gateway
         if (!empty($existing_payment_method) && isset($payment_gateways[$existing_payment_method]) && $payment_gateways[$existing_payment_method]->supports('subscriptions')) {
             foreach ($product_ids as $product_id) {
                 WC_Subscriptions_Payment_Gateways::trigger_gateway_cancelled_subscription_hook(absint($_POST['customer_user']), WC_Subscriptions_Manager::get_subscription_key($post_id, $product_id));
             }
         }
         if (!empty($chosen_payment_method) && isset($payment_gateways[$chosen_payment_method]) && $payment_gateways[$chosen_payment_method]->supports('subscriptions')) {
             $manual_renewal = 'false';
         } else {
             $manual_renewal = 'true';
         }
         update_post_meta($post_id, '_wcs_requires_manual_renewal', $manual_renewal);
         if (!empty($chosen_payment_method)) {
             update_post_meta($post_id, '_recurring_payment_method', stripslashes($_POST['_recurring_payment_method']));
         }
     }
     // Make sure the recurring order totals are correct
     update_post_meta($post_id, '_order_recurring_discount_total', stripslashes($_POST['_order_recurring_discount_total']));
     update_post_meta($post_id, '_order_recurring_total', stripslashes($_POST['_order_recurring_total']));
     // Update fields for WC < 2.1
     if (WC_Subscriptions::is_woocommerce_pre_2_1()) {
         // Also allow updates to the recurring payment method's title
         if (isset($_POST['_recurring_payment_method_title'])) {
             update_post_meta($post_id, '_recurring_payment_method_title', stripslashes($_POST['_recurring_payment_method_title']));
         } else {
             // it's been deleted
             update_post_meta($post_id, '_recurring_payment_method_title', '');
         }
         if (isset($_POST['_order_recurring_discount_cart'])) {
             update_post_meta($post_id, '_order_recurring_discount_cart', stripslashes($_POST['_order_recurring_discount_cart']));
         } else {
             // it's been deleted
             update_post_meta($post_id, '_order_recurring_discount_cart', 0);
         }
         if (isset($_POST['_order_recurring_tax_total'])) {
             // WC < 2.1
             update_post_meta($post_id, '_order_recurring_tax_total', stripslashes($_POST['_order_recurring_tax_total']));
         } else {
             // it's been deleted
             update_post_meta($post_id, '_order_recurring_tax_total', 0);
         }
         if (isset($_POST['_order_recurring_shipping_tax_total'])) {
             update_post_meta($post_id, '_order_recurring_shipping_tax_total', stripslashes($_POST['_order_recurring_shipping_tax_total']));
         } else {
             // it's been deleted
             update_post_meta($post_id, '_order_recurring_shipping_tax_total', 0);
         }
         if (isset($_POST['_order_recurring_shipping_total'])) {
             update_post_meta($post_id, '_order_recurring_shipping_total', stripslashes($_POST['_order_recurring_shipping_total']));
         } else {
             // it's been deleted
             update_post_meta($post_id, '_order_recurring_shipping_total', 0);
         }
     }
     // Save tax rows
     $total_tax = 0;
     $total_shipping_tax = 0;
     if (isset($_POST['recurring_order_taxes_id'])) {
         // WC 2.0+
         $tax_keys = array('recurring_order_taxes_id', 'recurring_order_taxes_rate_id', 'recurring_order_taxes_amount', 'recurring_order_taxes_shipping_amount');
         foreach ($tax_keys as $tax_key) {
             ${$tax_key} = isset($_POST[$tax_key]) ? $_POST[$tax_key] : array();
         }
         foreach ($recurring_order_taxes_id as $item_id => $value) {
             $item_id = absint($item_id);
             $rate_id = absint($recurring_order_taxes_rate_id[$item_id]);
             if ($rate_id) {
                 $rate = $wpdb->get_row($wpdb->prepare("SELECT * FROM {$wpdb->prefix}woocommerce_tax_rates WHERE tax_rate_id = %s", $rate_id));
                 $label = $rate->tax_rate_name ? $rate->tax_rate_name : $woocommerce->countries->tax_or_vat();
                 $compound = $rate->tax_rate_compound ? 1 : 0;
                 $code = array();
                 $code[] = $rate->tax_rate_country;
                 $code[] = $rate->tax_rate_state;
                 $code[] = $rate->tax_rate_name ? $rate->tax_rate_name : 'TAX';
                 $code[] = absint($rate->tax_rate_priority);
                 $code = strtoupper(implode('-', array_filter($code)));
             } else {
                 $code = '';
                 $label = $woocommerce->countries->tax_or_vat();
             }
             $wpdb->update($wpdb->prefix . "woocommerce_order_items", array('order_item_name' => woocommerce_clean($code)), array('order_item_id' => $item_id), array('%s'), array('%d'));
             woocommerce_update_order_item_meta($item_id, 'rate_id', $rate_id);
             woocommerce_update_order_item_meta($item_id, 'label', $label);
             woocommerce_update_order_item_meta($item_id, 'compound', $compound);
             if (isset($recurring_order_taxes_amount[$item_id])) {
                 woocommerce_update_order_item_meta($item_id, 'tax_amount', woocommerce_clean($recurring_order_taxes_amount[$item_id]));
                 $total_tax += WC_Subscriptions::format_total($recurring_order_taxes_amount[$item_id]);
             }
             if (isset($recurring_order_taxes_shipping_amount[$item_id])) {
                 woocommerce_update_order_item_meta($item_id, 'shipping_tax_amount', woocommerce_clean($recurring_order_taxes_shipping_amount[$item_id]));
                 $total_shipping_tax += WC_Subscriptions::format_total($recurring_order_taxes_shipping_amount[$item_id]);
             }
         }
     }
     if (!isset($_POST['_order_recurring_tax_total']) && function_exists('wc_round_tax_total')) {
         // WC 2.1+
         update_post_meta($post_id, '_order_recurring_tax_total', wc_round_tax_total($total_tax));
     }
     if (!isset($_POST['_order_recurring_shipping_tax_total']) && function_exists('wc_round_tax_total')) {
         // WC 2.1+
         update_post_meta($post_id, '_order_recurring_shipping_tax_total', wc_round_tax_total($total_shipping_tax));
     }
     // And that shipping methods are updated as required
     if (isset($_POST['_recurring_shipping_method']) || isset($_POST['_recurring_shipping_method_title'])) {
         // WC < 2.1
         update_post_meta($post_id, '_recurring_shipping_method', stripslashes($_POST['_recurring_shipping_method']));
         update_post_meta($post_id, '_recurring_shipping_method_title', stripslashes($_POST['_recurring_shipping_method_title']));
     }
     // Shipping Rows
     $recurring_order_shipping = 0;
     if (isset($_POST['recurring_shipping_method_id'])) {
         // WC 2.1+
         $get_values = array('recurring_shipping_method_id', 'recurring_shipping_method_title', 'recurring_shipping_method', 'recurring_shipping_cost');
         foreach ($get_values as $value) {
             ${$value} = isset($_POST[$value]) ? $_POST[$value] : array();
         }
         foreach ($recurring_shipping_method_id as $item_id => $value) {
             if ('new' == $item_id) {
                 foreach ($value as $new_key => $new_value) {
                     $method_id = woocommerce_clean($recurring_shipping_method[$item_id][$new_key]);
                     $method_title = woocommerce_clean($recurring_shipping_method_title[$item_id][$new_key]);
                     $cost = WC_Subscriptions::format_total($recurring_shipping_cost[$item_id][$new_key]);
                     $new_id = woocommerce_add_order_item($post_id, array('order_item_name' => $method_title, 'order_item_type' => 'recurring_shipping'));
                     if ($new_id) {
                         woocommerce_add_order_item_meta($new_id, 'method_id', $method_id);
                         woocommerce_add_order_item_meta($new_id, 'cost', $cost);
                     }
                     $recurring_order_shipping += $cost;
                 }
             } elseif ('old' == $item_id) {
                 // Migrate a WC 2.0.n shipping method to WC 2.1 format
                 $method_id = woocommerce_clean($recurring_shipping_method[$item_id]);
                 $method_title = woocommerce_clean($recurring_shipping_method_title[$item_id]);
                 $cost = WC_Subscriptions::format_total($recurring_shipping_cost[$item_id]);
                 $new_id = woocommerce_add_order_item($post_id, array('order_item_name' => $method_title, 'order_item_type' => 'recurring_shipping'));
                 if ($new_id) {
                     woocommerce_add_order_item_meta($new_id, 'method_id', $method_id);
                     woocommerce_add_order_item_meta($new_id, 'cost', $cost);
                 }
                 $recurring_order_shipping += $cost;
                 delete_post_meta($post_id, '_recurring_shipping_method');
                 delete_post_meta($post_id, '_recurring_shipping_method_title');
             } else {
                 $item_id = absint($item_id);
                 $method_id = woocommerce_clean($recurring_shipping_method[$item_id]);
                 $method_title = woocommerce_clean($recurring_shipping_method_title[$item_id]);
                 $cost = WC_Subscriptions::format_total($recurring_shipping_cost[$item_id]);
                 $wpdb->update($wpdb->prefix . "woocommerce_order_items", array('order_item_name' => $method_title), array('order_item_id' => $item_id), array('%s'), array('%d'));
                 woocommerce_update_order_item_meta($item_id, 'method_id', $method_id);
                 woocommerce_update_order_item_meta($item_id, 'cost', $cost);
                 $recurring_order_shipping += $cost;
             }
         }
     }
     if (!isset($_POST['_order_recurring_shipping_total'])) {
         // WC 2.1+
         update_post_meta($post_id, '_order_recurring_shipping_total', $recurring_order_shipping);
     }
     // Check if all the subscription products on the order have associated subscriptions on the user's account, and if not, add a new one
     foreach ($product_ids as $order_item_id => $product_id) {
         $is_existing_item = false;
         if (in_array($product_id, $existing_product_ids)) {
             $is_existing_item = true;
         }
         // If this is a new item and it's not a subscription product, ignore it
         if (!$is_existing_item && !WC_Subscriptions_Product::is_subscription($product_id)) {
             continue;
         }
         // If this is an existing item and it's not a subscription, ignore it
         if ($is_existing_item && !self::is_item_subscription($order, $product_id)) {
             continue;
         }
         $subscription_key = WC_Subscriptions_Manager::get_subscription_key($post_id, $product_id);
         $subscription = array();
         // In case it's a new order or the customer has changed
         $order->customer_user = $order->user_id = (int) $_POST['customer_user'];
         $subscription = WC_Subscriptions_Manager::get_subscription($subscription_key);
         if (empty($subscription)) {
             // Add a new subscription
             // The order may not exist yet, so we need to set a few things ourselves
             if (empty($order->order_key)) {
                 $order->order_key = uniqid('order_');
                 add_post_meta($post_id, '_order_key', $order->order_key, true);
             }
             if (empty($_POST['order_date'])) {
                 $start_date = gmdate('Y-m-d H:i:s');
             } else {
                 $start_date = get_gmt_from_date($_POST['order_date'] . ' ' . (int) $_POST['order_date_hour'] . ':' . (int) $_POST['order_date_minute'] . ':00');
             }
             WC_Subscriptions_Manager::create_pending_subscription_for_order($order, $product_id, array('start_date' => $start_date));
             // Add the subscription meta for this item to the order
             $functions_and_meta = array('get_period' => '_order_subscription_periods', 'get_interval' => '_order_subscription_intervals', 'get_length' => '_order_subscription_lengths');
             foreach ($functions_and_meta as $function_name => $meta_key) {
                 $subscription_meta = self::get_meta($order, $meta_key, array());
                 $subscription_meta[$product_id] = WC_Subscriptions_Product::$function_name($product_id);
                 update_post_meta($order->id, $meta_key, $subscription_meta);
             }
             // This works because meta is added when the item is added via Ajax
             self::process_shop_order_item_meta($post_id, $post);
             // If the order's existing status is something other than pending and the order status is not being changed, manually set the subscription's status (otherwise, it will be handled when WC transitions the order's status)
             if ($order->status == $_POST['order_status'] && 'pending' != $order->status) {
                 switch ($order->status) {
                     case 'completed':
                     case 'processing':
                         WC_Subscriptions_Manager::activate_subscription($order->customer_user, $subscription_key);
                         break;
                     case 'refunded':
                     case 'cancelled':
                         WC_Subscriptions_Manager::cancel_subscription($order->customer_user, $subscription_key);
                         break;
                     case 'failed':
                         WC_Subscriptions_Manager::failed_subscription_signup($order->customer_user, $subscription_key);
                         break;
                 }
             }
         }
     }
     // Determine whether we need to update any subscription dates for existing subscriptions (before the item meta is updated)
     if (!empty($product_ids)) {
         $start_date = $_POST['order_date'] . ' ' . (int) $_POST['order_date_hour'] . ':' . (int) $_POST['order_date_minute'] . ':00';
         // Start date changed for an existing order
         if (!empty($order->order_date) && $order->order_date != $start_date) {
             self::$requires_update['expiration_date'] = array_values($product_ids);
             self::$requires_update['trial_expiration'] = array_values($product_ids);
             self::$requires_update['next_billing_date'] = array_values($product_ids);
         } elseif (isset($_POST['meta_key'])) {
             $item_meta_keys = isset($_POST['meta_key']) ? $_POST['meta_key'] : array();
             $new_meta_values = isset($_POST['meta_value']) ? $_POST['meta_value'] : array();
             foreach ($item_meta_keys as $item_meta_id => $meta_key) {
                 $meta_data = self::get_item_meta_data($item_meta_id);
                 $product_id = woocommerce_get_order_item_meta($meta_data->order_item_id, '_product_id');
                 // Set flags to update payment dates if required
                 switch ($meta_key) {
                     case '_subscription_period':
                     case '_subscription_interval':
                         if ($new_meta_values[$item_meta_id] != $meta_data->meta_value) {
                             self::$requires_update['next_billing_date'][] = $product_id;
                         }
                         break;
                     case '_subscription_start_date':
                     case '_subscription_trial_length':
                     case '_subscription_trial_period':
                         if ($new_meta_values[$item_meta_id] != $meta_data->meta_value) {
                             self::$requires_update['expiration_date'][] = $product_id;
                             self::$requires_update['trial_expiration'][] = $product_id;
                             self::$requires_update['next_billing_date'][] = $product_id;
                         }
                         break;
                     case '_subscription_length':
                         if ($new_meta_values[$item_meta_id] != $meta_data->meta_value) {
                             self::$requires_update['expiration_date'][] = $product_id;
                             self::$requires_update['next_billing_date'][] = $product_id;
                         }
                         break;
                     case '_subscription_trial_expiry_date':
                         if ($new_meta_values[$item_meta_id] != $meta_data->meta_value) {
                             self::$requires_update['trial_expiration'][] = $product_id;
                         }
                         break;
                     case '_subscription_expiry_date':
                         if ($new_meta_values[$item_meta_id] != $meta_data->meta_value) {
                             self::$requires_update['expiration_date'][] = $product_id;
                         }
                         break;
                 }
             }
         }
     }
 }
 /**
  * Version 1.2 introduced a massive change to the order meta data schema. This function goes
  * through and upgrades the existing data on all orders to the new schema.
  *
  * The upgrade process is timeout safe as it keeps a record of the orders upgraded and only
  * deletes this record once all orders have been upgraded successfully. If operating on a huge
  * number of orders and the upgrade process times out, only the orders not already upgraded
  * will be upgraded in future requests that trigger this function.
  *
  * @since 1.2
  */
 private static function upgrade_database_to_1_2()
 {
     global $wpdb;
     // Get IDs only and use a direct DB query for efficiency
     $orders_to_upgrade = $wpdb->get_col("SELECT ID FROM {$wpdb->posts} WHERE post_type = 'shop_order' AND post_parent = 0");
     $upgraded_orders = get_option('wcs_1_2_upgraded_order_ids', array());
     // Transition deprecated subscription status if we aren't in the middle of updating orders
     if (empty($upgraded_orders)) {
         $wpdb->query($wpdb->prepare("UPDATE {$wpdb->usermeta} SET meta_value = replace( meta_value, 's:9:\"suspended\"', 's:7:\"on-hold\"' ) WHERE meta_key LIKE %s", '%_woocommerce_subscriptions'));
         $wpdb->query($wpdb->prepare("UPDATE {$wpdb->usermeta} SET meta_value = replace( meta_value, 's:6:\"failed\"', 's:9:\"cancelled\"' ) WHERE meta_key LIKE %s", '%_woocommerce_subscriptions'));
     }
     $orders_to_upgrade = array_diff($orders_to_upgrade, $upgraded_orders);
     // Upgrade all _sign_up_{field} order meta to new order data format
     foreach ($orders_to_upgrade as $order_id) {
         $order = new WC_Order($order_id);
         // Manually check if a product in an order is a subscription, we can't use WC_Subscriptions_Order::order_contains_subscription( $order ) because it relies on the new data structure
         $contains_subscription = false;
         foreach ($order->get_items() as $order_item) {
             if (WC_Subscriptions_Product::is_subscription(WC_Subscriptions_Order::get_items_product_id($order_item))) {
                 $contains_subscription = true;
                 break;
             }
         }
         if (!$contains_subscription) {
             continue;
         }
         $trial_lengths = WC_Subscriptions_Order::get_meta($order, '_order_subscription_trial_lengths', array());
         $trial_length = array_pop($trial_lengths);
         $has_trial = !empty($trial_length) && $trial_length > 0 ? true : false;
         $sign_up_fee_total = WC_Subscriptions_Order::get_meta($order, '_sign_up_fee_total', 0);
         // Create recurring_* meta data from existing cart totals
         $cart_discount = $order->get_cart_discount();
         update_post_meta($order_id, '_order_recurring_discount_cart', $cart_discount);
         $order_discount = $order->get_order_discount();
         update_post_meta($order_id, '_order_recurring_discount_total', $order_discount);
         $order_shipping_tax = get_post_meta($order_id, '_order_shipping_tax', true);
         update_post_meta($order_id, '_order_recurring_shipping_tax_total', $order_shipping_tax);
         $order_tax = get_post_meta($order_id, '_order_tax', true);
         // $order->get_total_tax() includes shipping tax
         update_post_meta($order_id, '_order_recurring_tax_total', $order_tax);
         $order_total = $order->get_total();
         update_post_meta($order_id, '_order_recurring_total', $order_total);
         // Set order totals to include sign up fee fields, if there was a sign up fee on the order and a trial period (other wise, the recurring totals are correct)
         if ($sign_up_fee_total > 0) {
             // Order totals need to be changed to be equal to sign up fee totals
             if ($has_trial) {
                 $cart_discount = WC_Subscriptions_Order::get_meta($order, '_sign_up_fee_discount_cart', 0);
                 $order_discount = WC_Subscriptions_Order::get_meta($order, '_sign_up_fee_discount_total', 0);
                 $order_tax = WC_Subscriptions_Order::get_meta($order, '_sign_up_fee_tax_total', 0);
                 $order_total = $sign_up_fee_total;
             } else {
                 // No trial, sign up fees need to be added to order totals
                 $cart_discount += WC_Subscriptions_Order::get_meta($order, '_sign_up_fee_discount_cart', 0);
                 $order_discount += WC_Subscriptions_Order::get_meta($order, '_sign_up_fee_discount_total', 0);
                 $order_tax += WC_Subscriptions_Order::get_meta($order, '_sign_up_fee_tax_total', 0);
                 $order_total += $sign_up_fee_total;
             }
             update_post_meta($order_id, '_order_total', $order_total);
             update_post_meta($order_id, '_cart_discount', $cart_discount);
             update_post_meta($order_id, '_order_discount', $order_discount);
             update_post_meta($order_id, '_order_tax', $order_tax);
         }
         // Make sure we get order taxes in WC 1.x format
         if (false == self::$is_wc_version_2) {
             $order_taxes = $order->get_taxes();
         } else {
             $order_tax_row = $wpdb->get_row($wpdb->prepare("\n\t\t\t\t\tSELECT * FROM {$wpdb->postmeta}\n\t\t\t\t\tWHERE meta_key = '_order_taxes_old'\n\t\t\t\t\tAND post_id = %s\n\t\t\t\t\t", $order_id));
             $order_taxes = (array) maybe_unserialize($order_tax_row->meta_value);
         }
         // Set recurring taxes to order taxes, if using WC 2.0, this will be migrated to the new format in @see self::upgrade_to_latest_wc()
         update_post_meta($order_id, '_order_recurring_taxes', $order_taxes);
         $sign_up_fee_taxes = WC_Subscriptions_Order::get_meta($order, '_sign_up_fee_taxes', array());
         // Update order taxes to include sign up fee taxes
         foreach ($sign_up_fee_taxes as $index => $sign_up_tax) {
             if ($has_trial && $sign_up_fee_total > 0) {
                 // Order taxes need to be set to the same as the sign up fee taxes
                 if (isset($sign_up_tax['cart_tax']) && $sign_up_tax['cart_tax'] > 0) {
                     $order_taxes[$index]['cart_tax'] = $sign_up_tax['cart_tax'];
                 }
             } elseif (!$has_trial && $sign_up_fee_total > 0) {
                 // Sign up fee taxes need to be added to order taxes
                 if (isset($sign_up_tax['cart_tax']) && $sign_up_tax['cart_tax'] > 0) {
                     $order_taxes[$index]['cart_tax'] += $sign_up_tax['cart_tax'];
                 }
             }
         }
         if (false == self::$is_wc_version_2) {
             // Doing it right: updated Subs *before* updating WooCommerce, the WooCommerce updater will take care of data migration
             update_post_meta($order_id, '_order_taxes', $order_taxes);
         } else {
             // Doing it wrong: updated Subs *after* updating WooCommerce, need to store in WC2.0 tax structure
             $index = 0;
             $new_order_taxes = $order->get_taxes();
             foreach ($new_order_taxes as $item_id => $order_tax) {
                 $index = $index + 1;
                 if (!isset($order_taxes[$index]['label']) || !isset($order_taxes[$index]['cart_tax']) || !isset($order_taxes[$index]['shipping_tax'])) {
                     continue;
                 }
                 // Add line item meta
                 if ($item_id) {
                     woocommerce_update_order_item_meta($item_id, 'compound', absint(isset($order_taxes[$index]['compound']) ? $order_taxes[$index]['compound'] : 0));
                     woocommerce_update_order_item_meta($item_id, 'tax_amount', WC_Subscriptions::format_total($order_taxes[$index]['cart_tax']));
                     woocommerce_update_order_item_meta($item_id, 'shipping_tax_amount', WC_Subscriptions::format_total($order_taxes[$index]['shipping_tax']));
                 }
             }
         }
         /* Upgrade each order item to use new Item Meta schema */
         $order_subscription_periods = WC_Subscriptions_Order::get_meta($order_id, '_order_subscription_periods', array());
         $order_subscription_intervals = WC_Subscriptions_Order::get_meta($order_id, '_order_subscription_intervals', array());
         $order_subscription_lengths = WC_Subscriptions_Order::get_meta($order_id, '_order_subscription_lengths', array());
         $order_subscription_trial_lengths = WC_Subscriptions_Order::get_meta($order_id, '_order_subscription_trial_lengths', array());
         $order_items = $order->get_items();
         foreach ($order_items as $index => $order_item) {
             $product_id = WC_Subscriptions_Order::get_items_product_id($order_item);
             if (WC_Subscriptions::is_woocommerce_pre('2.4')) {
                 $item_meta = new WC_Order_Item_Meta($order_item['item_meta']);
             } else {
                 $item_meta = new WC_Order_Item_Meta($order_item);
             }
             $subscription_interval = isset($order_subscription_intervals[$product_id]) ? $order_subscription_intervals[$product_id] : 1;
             $subscription_length = isset($order_subscription_lengths[$product_id]) ? $order_subscription_lengths[$product_id] : 0;
             $subscription_trial_length = isset($order_subscription_trial_lengths[$product_id]) ? $order_subscription_trial_lengths[$product_id] : 0;
             $subscription_sign_up_fee = WC_Subscriptions_Order::get_meta($order, '_cart_contents_sign_up_fee_total', 0);
             if ($sign_up_fee_total > 0) {
                 // Discounted price * Quantity
                 $sign_up_fee_line_total = WC_Subscriptions_Order::get_meta($order, '_cart_contents_sign_up_fee_total', 0);
                 $sign_up_fee_line_tax = WC_Subscriptions_Order::get_meta($order, '_sign_up_fee_tax_total', 0);
                 // Base price * Quantity
                 $sign_up_fee_line_subtotal = WC_Subscriptions_Order::get_meta($order, '_cart_contents_sign_up_fee_total', 0) + WC_Subscriptions_Order::get_meta($order, '_sign_up_fee_discount_cart', 0);
                 $sign_up_fee_propotion = $sign_up_fee_line_total > 0 ? $sign_up_fee_line_subtotal / $sign_up_fee_line_total : 0;
                 $sign_up_fee_line_subtotal_tax = WC_Subscriptions_Manager::get_amount_from_proportion(WC_Subscriptions_Order::get_meta($order, '_sign_up_fee_tax_total', 0), $sign_up_fee_propotion);
                 if ($has_trial) {
                     // Set line item totals equal to sign up fee totals
                     $order_item['line_subtotal'] = $sign_up_fee_line_subtotal;
                     $order_item['line_subtotal_tax'] = $sign_up_fee_line_subtotal_tax;
                     $order_item['line_total'] = $sign_up_fee_line_total;
                     $order_item['line_tax'] = $sign_up_fee_line_tax;
                 } else {
                     // No trial period, sign up fees need to be added to order totals
                     $order_item['line_subtotal'] += $sign_up_fee_line_subtotal;
                     $order_item['line_subtotal_tax'] += $sign_up_fee_line_subtotal_tax;
                     $order_item['line_total'] += $sign_up_fee_line_total;
                     $order_item['line_tax'] += $sign_up_fee_line_tax;
                 }
             }
             // Upgrading with WC 1.x
             if (method_exists($item_meta, 'add')) {
                 $item_meta->add('_subscription_period', $order_subscription_periods[$product_id]);
                 $item_meta->add('_subscription_interval', $subscription_interval);
                 $item_meta->add('_subscription_length', $subscription_length);
                 $item_meta->add('_subscription_trial_length', $subscription_trial_length);
                 $item_meta->add('_subscription_recurring_amount', $order_item['line_subtotal']);
                 // WC_Subscriptions_Product::get_price() would return a price without filters applied
                 $item_meta->add('_subscription_sign_up_fee', $subscription_sign_up_fee);
                 // Set recurring amounts for the item
                 $item_meta->add('_recurring_line_total', $order_item['line_total']);
                 $item_meta->add('_recurring_line_tax', $order_item['line_tax']);
                 $item_meta->add('_recurring_line_subtotal', $order_item['line_subtotal']);
                 $item_meta->add('_recurring_line_subtotal_tax', $order_item['line_subtotal_tax']);
                 $order_item['item_meta'] = $item_meta->meta;
                 $order_items[$index] = $order_item;
             } else {
                 // Ignoring all advice, upgrading 4 months after version 1.2 was released, and doing it with WC 2.0 installed
                 woocommerce_add_order_item_meta($index, '_subscription_period', $order_subscription_periods[$product_id]);
                 woocommerce_add_order_item_meta($index, '_subscription_interval', $subscription_interval);
                 woocommerce_add_order_item_meta($index, '_subscription_length', $subscription_length);
                 woocommerce_add_order_item_meta($index, '_subscription_trial_length', $subscription_trial_length);
                 woocommerce_add_order_item_meta($index, '_subscription_trial_period', $order_subscription_periods[$product_id]);
                 woocommerce_add_order_item_meta($index, '_subscription_recurring_amount', $order_item['line_subtotal']);
                 woocommerce_add_order_item_meta($index, '_subscription_sign_up_fee', $subscription_sign_up_fee);
                 // Calculated recurring amounts for the item
                 woocommerce_add_order_item_meta($index, '_recurring_line_total', $order_item['line_total']);
                 woocommerce_add_order_item_meta($index, '_recurring_line_tax', $order_item['line_tax']);
                 woocommerce_add_order_item_meta($index, '_recurring_line_subtotal', $order_item['line_subtotal']);
                 woocommerce_add_order_item_meta($index, '_recurring_line_subtotal_tax', $order_item['line_subtotal_tax']);
                 if ($sign_up_fee_total > 0) {
                     // Order totals have changed
                     woocommerce_update_order_item_meta($index, '_line_subtotal', woocommerce_format_decimal($order_item['line_subtotal']));
                     woocommerce_update_order_item_meta($index, '_line_subtotal_tax', woocommerce_format_decimal($order_item['line_subtotal_tax']));
                     woocommerce_update_order_item_meta($index, '_line_total', woocommerce_format_decimal($order_item['line_total']));
                     woocommerce_update_order_item_meta($index, '_line_tax', woocommerce_format_decimal($order_item['line_tax']));
                 }
             }
         }
         // Save the new meta on the order items for WC 1.x (the API functions already saved the data for WC2.x)
         if (false == self::$is_wc_version_2) {
             update_post_meta($order_id, '_order_items', $order_items);
         }
         $upgraded_orders[] = $order_id;
         update_option('wcs_1_2_upgraded_order_ids', $upgraded_orders);
     }
 }
 /**
  * Creates a new order for renewing a subscription product based on the details of a previous order.
  *
  * No trial periods or sign up fees are applied to the renewal order. However, if the order has failed
  * payments and the store manager has set failed payments to be added to renewal orders, then the
  * orders totals will be set to include the outstanding balance.
  *
  * If the $args['new_order_role'] flag is set to 'parent', then the renewal order will supersede the existing
  * order. The existing order and subscription associated with it will be cancelled. A new order and
  * subscription will be created.
  *
  * If the $args['new_order_role'] flag is 'child', the $original_order will remain the master order for the
  * subscription and the new order is just for accepting a recurring payment on the subscription.
  *
  * Renewal orders have the same meta data as the original order. If the renewal order is set to be a 'child'
  * then any subscription related meta data will not be stored on the new order. This is to keep subscription
  * meta data associated only with the one master order for the subscription.
  *
  * @param WC_Order|int $order The WC_Order object or ID of the order for which the a new order should be created.
  * @param string $product_id The ID of the subscription product in the order which needs to be added to the new order.
  * @param array $args (optional) An array of name => value flags:
  *         'new_order_role' string A flag to indicate whether the new order should become the master order for the subscription. Accepts either 'parent' or 'child'. Defaults to 'parent' - replace the existing order.
  *         'checkout_renewal' bool Indicates if invoked from an interactive cart/checkout session and certain order items are not set, like taxes, shipping as they need to be set in teh calling function, like @see WC_Subscriptions_Checkout::filter_woocommerce_create_order(). Default false.
  *         'failed_order_id' int For checkout_renewal true, indicates order id being replaced
  * @since 1.2
  */
 public static function generate_renewal_order($original_order, $product_id, $args = array())
 {
     global $wpdb, $woocommerce;
     if (!is_object($original_order)) {
         $original_order = new WC_Order($original_order);
     }
     if (!WC_Subscriptions_Order::order_contains_subscription($original_order) || !WC_Subscriptions_Order::is_item_subscription($original_order, $product_id)) {
         return false;
     }
     if (self::is_renewal($original_order, array('order_role' => 'child'))) {
         $original_order = self::get_parent_order($original_order);
     }
     if (!is_array($args)) {
         _deprecated_argument(__CLASS__ . '::' . __FUNCTION__, '1.3', __('Third parameter is now an array of name => value pairs. Use array( "new_order_role" => "parent" ) instead.', 'woocommerce-subscriptions'));
         $args = array('new_order_role' => $args);
     }
     $args = wp_parse_args($args, array('new_order_role' => 'parent', 'checkout_renewal' => false));
     $renewal_order_key = uniqid('order_');
     // Create the new order
     $renewal_order_data = array('post_type' => 'shop_order', 'post_title' => sprintf(__('Subscription Renewal Order &ndash; %s', 'woocommerce-subscriptions'), strftime(_x('%b %d, %Y @ %I:%M %p', 'Order date parsed by strftime', 'woocommerce-subscriptions'))), 'ping_status' => 'closed', 'post_excerpt' => $original_order->customer_note, 'post_author' => 1, 'post_password' => $renewal_order_key);
     $create_new_order = true;
     if (!WC_Subscriptions::is_woocommerce_pre('2.2')) {
         // WC 2.2 order status
         $renewal_order_data['post_status'] = 'wc-pending';
     } else {
         $renewal_order_data['post_status'] = 'publish';
     }
     if ('child' == $args['new_order_role']) {
         $renewal_order_data['post_parent'] = $original_order->id;
     }
     if (true === $args['checkout_renewal']) {
         $renewal_order_id = null;
         if ($woocommerce->session->order_awaiting_payment > 0) {
             $renewal_order_id = absint($woocommerce->session->order_awaiting_payment);
         } elseif (isset($args['failed_order_id'])) {
             $failed_order_id = $args['failed_order_id'];
             if (WC_Subscriptions::is_woocommerce_pre('2.2')) {
                 // WC 2.1  - need to use taxonomy
                 /* Check order is unpaid by getting its status */
                 $terms = wp_get_object_terms($failed_order_id, 'shop_order_status', array('fields' => 'slugs'));
                 $order_status = isset($terms[0]) ? $terms[0] : 'pending';
             } else {
                 // WC 2.2+
                 $failed_order = wc_get_order($failed_order_id);
                 $order_status = $failed_order->get_status();
             }
             /* If paying on a pending order, we are resuming */
             if ($order_status == 'pending') {
                 $renewal_order_id = $failed_order_id;
             }
         }
         if ($renewal_order_id) {
             if (WC_Subscriptions::is_woocommerce_pre('2.2')) {
                 // WC 2.1  - need to use taxonomy
                 /* Check order is unpaid by getting its status */
                 $terms = wp_get_object_terms($renewal_order_id, 'shop_order_status', array('fields' => 'slugs'));
                 $order_status = isset($terms[0]) ? $terms[0] : 'pending';
             } else {
                 // WC 2.2+
                 $existing_order = wc_get_order($renewal_order_id);
                 $order_status = $existing_order->get_status();
             }
             // Resume the unpaid order if its pending
             if ($order_status == 'pending' || $order_status == 'failed') {
                 // Update the existing order as we are resuming it
                 $create_new_order = false;
                 $renewal_order_data['ID'] = $renewal_order_id;
                 wp_update_post($renewal_order_data);
                 // Clear the old line items - we'll add these again in case they changed
                 $wpdb->query($wpdb->prepare("DELETE FROM {$wpdb->prefix}woocommerce_order_itemmeta WHERE order_item_id IN ( SELECT order_item_id FROM {$wpdb->prefix}woocommerce_order_items WHERE order_id = %d )", $renewal_order_id));
                 $wpdb->query($wpdb->prepare("DELETE FROM {$wpdb->prefix}woocommerce_order_items WHERE order_id = %d", $renewal_order_id));
             }
         }
     }
     if ($create_new_order) {
         $renewal_order_id = wp_insert_post($renewal_order_data);
     }
     if (WC_Subscriptions::is_woocommerce_pre('2.2')) {
         // WC 2.1 order status
         // Set the order as pending
         wp_set_object_terms($renewal_order_id, 'pending', 'shop_order_status');
     }
     // Set a unique key for this order
     update_post_meta($renewal_order_id, '_order_key', $renewal_order_key);
     $order_meta_query = "SELECT `meta_key`, `meta_value`\n\t\t\t\t\t\t\t FROM {$wpdb->postmeta}\n\t\t\t\t\t\t\t WHERE `post_id` = {$original_order->id}\n\t\t\t\t\t\t\t AND `meta_key` NOT IN ('_paid_date', '_completed_date', '_order_key', '_edit_lock', '_original_order', '_wc_points_earned', '_transaction_id')";
     // Superseding existing order so don't carry over payment details
     if ('parent' == $args['new_order_role'] || true === $args['checkout_renewal']) {
         $order_meta_query .= " AND `meta_key` NOT IN ('_payment_method', '_payment_method_title', '_recurring_payment_method', '_recurring_payment_method_title', '_shipping_method', '_shipping_method_title', '_recurring_shipping_method', '_recurring_shipping_method_title')";
     } else {
         $order_meta_query .= " AND `meta_key` NOT LIKE '_order_recurring_%' AND `meta_key` NOT IN ('_payment_method', '_payment_method_title', '_recurring_payment_method', '_recurring_payment_method_title', '_shipping_method', '_shipping_method_title', '_recurring_shipping_method', '_recurring_shipping_method_title')";
     }
     // Allow extensions to add/remove order meta
     $order_meta_query = apply_filters('woocommerce_subscriptions_renewal_order_meta_query', $order_meta_query, $original_order->id, $renewal_order_id, $args['new_order_role']);
     // Carry all the required meta from the old order over to the new order
     $order_meta = $wpdb->get_results($order_meta_query, 'ARRAY_A');
     $order_meta = apply_filters('woocommerce_subscriptions_renewal_order_meta', $order_meta, $original_order->id, $renewal_order_id, $args['new_order_role']);
     foreach ($order_meta as $meta_item) {
         add_post_meta($renewal_order_id, $meta_item['meta_key'], maybe_unserialize($meta_item['meta_value']), true);
     }
     $outstanding_balance = WC_Subscriptions_Order::get_outstanding_balance($original_order, $product_id);
     $failed_payment_multiplier = 1;
     if (false == $args['checkout_renewal']) {
         // If there are outstanding payment amounts, add them to the order, otherwise set the order details to the values of the recurring totals
         if ($outstanding_balance > 0 && 'yes' == get_option(WC_Subscriptions_Admin::$option_prefix . '_add_outstanding_balance', 'no')) {
             $failed_payment_multiplier += WC_Subscriptions_Order::get_failed_payment_count($original_order, $product_id);
         }
         // Set order totals based on recurring totals from the original order
         $cart_discount = $failed_payment_multiplier * wc_format_decimal(get_post_meta($original_order->id, '_order_recurring_discount_cart', true));
         $order_discount = $failed_payment_multiplier * wc_format_decimal(get_post_meta($original_order->id, '_order_recurring_discount_total', true));
         $order_shipping_tax = $failed_payment_multiplier * wc_format_decimal(get_post_meta($original_order->id, '_order_recurring_shipping_tax_total', true));
         $order_shipping = $failed_payment_multiplier * wc_format_decimal(get_post_meta($original_order->id, '_order_recurring_shipping_total', true));
         $order_tax = $failed_payment_multiplier * wc_format_decimal(get_post_meta($original_order->id, '_order_recurring_tax_total', true));
         $order_total = $failed_payment_multiplier * wc_format_decimal(get_post_meta($original_order->id, '_order_recurring_total', true));
         update_post_meta($renewal_order_id, '_cart_discount', $cart_discount);
         update_post_meta($renewal_order_id, '_order_discount', $order_discount);
         update_post_meta($renewal_order_id, '_order_shipping_tax', $order_shipping_tax);
         update_post_meta($renewal_order_id, '_order_shipping', $order_shipping);
         update_post_meta($renewal_order_id, '_order_tax', $order_tax);
         update_post_meta($renewal_order_id, '_order_total', $order_total);
         // Set shipping for orders created with WC 2.0.n (or when we are using WC 2.0.n)
         if (WC_Subscriptions::is_woocommerce_pre('2.1') || isset($original_order->recurring_shipping_method)) {
             update_post_meta($renewal_order_id, '_shipping_method', $original_order->recurring_shipping_method);
             update_post_meta($renewal_order_id, '_shipping_method_title', $original_order->recurring_shipping_method_title);
             // Also set recurring shipping as it's a parent renewal order
             if ('parent' == $args['new_order_role']) {
                 update_post_meta($renewal_order_id, '_recurring_shipping_method', $original_order->recurring_shipping_method);
                 update_post_meta($renewal_order_id, '_recurring_shipping_method_title', $original_order->recurring_shipping_method_title);
             }
         }
         // Apply the recurring shipping & payment methods to child renewal orders
         if ('child' == $args['new_order_role']) {
             update_post_meta($renewal_order_id, '_payment_method', $original_order->recurring_payment_method);
             update_post_meta($renewal_order_id, '_payment_method_title', $original_order->recurring_payment_method_title);
         }
         // Set order taxes based on recurring taxes from the original order
         $recurring_order_taxes = WC_Subscriptions_Order::get_recurring_taxes($original_order);
         foreach ($recurring_order_taxes as $index => $recurring_order_tax) {
             $item_ids = array();
             $item_ids[] = woocommerce_add_order_item($renewal_order_id, array('order_item_name' => $recurring_order_tax['name'], 'order_item_type' => 'tax'));
             // Also set recurring taxes on parent renewal orders
             if ('parent' == $args['new_order_role']) {
                 $item_ids[] = woocommerce_add_order_item($renewal_order_id, array('order_item_name' => $recurring_order_tax['name'], 'order_item_type' => 'recurring_tax'));
             }
             // Add line item meta
             foreach ($item_ids as $item_id) {
                 woocommerce_add_order_item_meta($item_id, 'compound', absint(isset($recurring_order_tax['compound']) ? $recurring_order_tax['compound'] : 0));
                 woocommerce_add_order_item_meta($item_id, 'tax_amount', $failed_payment_multiplier * WC_Subscriptions::format_total($recurring_order_tax['tax_amount']));
                 woocommerce_add_order_item_meta($item_id, 'shipping_tax_amount', $failed_payment_multiplier * WC_Subscriptions::format_total($recurring_order_tax['shipping_tax_amount']));
                 if (isset($recurring_order_tax['rate_id'])) {
                     woocommerce_add_order_item_meta($item_id, 'rate_id', $recurring_order_tax['rate_id']);
                 }
                 if (isset($recurring_order_tax['label'])) {
                     woocommerce_add_order_item_meta($item_id, 'label', $recurring_order_tax['label']);
                 }
             }
         }
         // Set up shipping items on renewal order
         $recurring_shipping_items = WC_Subscriptions_Order::get_recurring_shipping_methods($original_order);
         foreach ($recurring_shipping_items as $recurring_shipping_item_id => $recurring_shipping_item) {
             $item_ids = array();
             $item_ids[] = woocommerce_add_order_item($renewal_order_id, array('order_item_name' => $recurring_shipping_item['name'], 'order_item_type' => 'shipping'));
             // Also set recurring shipping as it's a parent renewal order
             if ('parent' == $args['new_order_role']) {
                 $item_ids[] = woocommerce_add_order_item($renewal_order_id, array('order_item_name' => $recurring_shipping_item['name'], 'order_item_type' => 'recurring_shipping'));
             }
             // Add shipping item meta
             foreach ($item_ids as $item_id) {
                 woocommerce_add_order_item_meta($item_id, 'method_id', $recurring_shipping_item['method_id']);
                 woocommerce_add_order_item_meta($item_id, 'cost', $failed_payment_multiplier * WC_Subscriptions::format_total($recurring_shipping_item['cost']));
                 // Set line taxes for shipping
                 if (isset($recurring_shipping_item['taxes'])) {
                     $taxes = maybe_unserialize($recurring_shipping_item['taxes']);
                 } else {
                     // try to determine recurring shipping taxes from original order's shipping taxes
                     $taxes = array();
                     foreach ($original_order->get_shipping_methods() as $original_shipping_item_id => $original_shipping_item) {
                         // We need to use the amount of the same shipping method as this one
                         if ($recurring_shipping_item['method_id'] != $original_shipping_item['method_id']) {
                             continue;
                         }
                         // If we don't have taxes on the matching shipping item, there's nothing we can do
                         if (!isset($original_shipping_item['taxes'])) {
                             break;
                         }
                         $original_shipping_item['taxes'] = maybe_unserialize($original_shipping_item['taxes']);
                         // Make sure we account for any amount on the original original shipping not applied to renewals by determining what proportion of the initial amount the recurring total represents
                         if (0 != $original_shipping_item['cost'] && $recurring_shipping_item['cost'] != $original_shipping_item['cost']) {
                             $recurring_ratio = $recurring_shipping_item['cost'] / $original_shipping_item['cost'];
                             foreach ($original_shipping_item['taxes'] as $tax_id => $tax_amount) {
                                 $original_shipping_item['taxes'][$tax_id] = $recurring_ratio * $tax_amount;
                             }
                         }
                         foreach ($original_shipping_item['taxes'] as $tax_id => $tax_amount) {
                             $taxes[$tax_id] = WC_Subscriptions::format_total($failed_payment_multiplier * $tax_amount);
                         }
                     }
                 }
                 woocommerce_add_order_item_meta($item_id, 'taxes', $taxes);
             }
         }
     }
     // Set line totals to be recurring line totals and remove the subscription/recurring related item meta from each order item
     $order_items = WC_Subscriptions_Order::get_recurring_items($original_order);
     // Allow extensions to add/remove items or item meta
     $order_items = apply_filters('woocommerce_subscriptions_renewal_order_items', $order_items, $original_order->id, $renewal_order_id, $product_id, $args['new_order_role']);
     if (true === $args['checkout_renewal']) {
         $cart_items = $woocommerce->cart->get_cart();
     }
     foreach ($order_items as $item_index => $order_item) {
         $renewal_order_item_name = apply_filters('woocommerce_subscriptions_renewal_order_item_name', $order_item['name'], $order_item, $original_order);
         // Create order line item on the renewal order
         $recurring_item_id = woocommerce_add_order_item($renewal_order_id, array('order_item_name' => $renewal_order_item_name, 'order_item_type' => 'line_item'));
         if (true === $args['checkout_renewal']) {
             $cart_item = array();
             foreach ($cart_items as $item) {
                 if ($item['product_id'] == $order_item['product_id'] && (empty($order_item['variation_id']) || $item['variation_id'] == $order_item['variation_id'])) {
                     $cart_item = $item;
                 }
             }
             if (!empty($cart_item)) {
                 woocommerce_update_order_item_meta($recurring_item_id, '_line_total', woocommerce_format_decimal($cart_item['line_total']));
                 woocommerce_update_order_item_meta($recurring_item_id, '_line_tax', woocommerce_format_decimal($cart_item['line_tax']));
                 woocommerce_update_order_item_meta($recurring_item_id, '_line_subtotal', woocommerce_format_decimal($cart_item['line_subtotal']));
                 woocommerce_update_order_item_meta($recurring_item_id, '_line_subtotal_tax', woocommerce_format_decimal($cart_item['line_subtotal_tax']));
                 if (is_object($cart_item['data'])) {
                     woocommerce_update_order_item_meta($recurring_item_id, '_tax_class', $cart_item['data']->get_tax_class());
                 }
             }
             $cart_items = $woocommerce->cart->get_cart();
         }
         if (WC_Subscriptions::is_woocommerce_pre('2.4')) {
             $item_meta = new WC_Order_Item_Meta($order_item['item_meta']);
         } else {
             $item_meta = new WC_Order_Item_Meta($order_item);
         }
         // Remove recurring line items and set item totals based on recurring line totals
         foreach ($item_meta->meta as $meta_key => $meta) {
             // meta value might be an array. If it is, we need to preserve all values
             foreach ($meta as $key => $value) {
                 $meta_values[$key] = maybe_unserialize($value);
             }
             if (false === $args['checkout_renewal']) {
                 // Already set earlier
                 // Map line item totals based on recurring line totals
                 switch ($meta_key) {
                     case '_recurring_line_total':
                         woocommerce_update_order_item_meta($recurring_item_id, '_line_total', $failed_payment_multiplier * woocommerce_format_decimal($meta_values[0]));
                         break;
                     case '_recurring_line_tax':
                         woocommerce_update_order_item_meta($recurring_item_id, '_line_tax', $failed_payment_multiplier * woocommerce_format_decimal($meta_values[0]));
                         break;
                     case '_recurring_line_subtotal':
                         woocommerce_update_order_item_meta($recurring_item_id, '_line_subtotal', $failed_payment_multiplier * woocommerce_format_decimal($meta_values[0]));
                         break;
                     case '_recurring_line_subtotal_tax':
                         woocommerce_update_order_item_meta($recurring_item_id, '_line_subtotal_tax', $failed_payment_multiplier * woocommerce_format_decimal($meta_values[0]));
                         break;
                     case '_line_tax_data':
                         // Copy line tax data if the order doesn't have a _recurring_line_tax_data (for backward compatibility)
                         if (!array_key_exists('_recurring_line_tax_data', $item_meta->meta)) {
                             $meta_value = $meta_values[0];
                             $line_total = $item_meta->meta['_line_total'][0];
                             $recurring_line_total = $item_meta->meta['_recurring_line_total'][0];
                             // There will only be recurring tax data if the recurring amount is > 0 and we can only retroactively calculate recurring amount from initial amoutn if it is > 0
                             if ($line_total > 0 && $recurring_line_total > 0) {
                                 // Make sure we account for any sign-up fees by determining what proportion of the initial amount the recurring total represents
                                 $recurring_ratio = $recurring_line_total / $line_total;
                                 $recurring_tax_data = array();
                                 $tax_data_keys = array('total', 'subtotal');
                                 foreach ($tax_data_keys as $tax_data_key) {
                                     foreach ($meta_value[$tax_data_key] as $tax_index => $tax_value) {
                                         // Use total tax amount for both total and subtotal because we don't want any initial discounts to be applied to recurring amounts
                                         $total_tax_amount = $meta_value['total'][$tax_index];
                                         $recurring_tax_data[$tax_data_key][$tax_index] = woocommerce_format_decimal($failed_payment_multiplier * ($recurring_ratio * $total_tax_amount));
                                     }
                                 }
                             } else {
                                 $recurring_tax_data = array('total' => array(), 'subtotal' => array());
                             }
                             woocommerce_update_order_item_meta($recurring_item_id, '_line_tax_data', $recurring_tax_data);
                         }
                         break;
                     case '_recurring_line_tax_data':
                         $meta_value = $meta_values[0];
                         $recurring_tax_data = array();
                         $tax_data_keys = array('total', 'subtotal');
                         foreach ($tax_data_keys as $tax_data_key) {
                             foreach ($meta_value[$tax_data_key] as $tax_index => $tax_value) {
                                 $recurring_tax_data[$tax_data_key][$tax_index] = woocommerce_format_decimal($failed_payment_multiplier * $tax_value);
                             }
                         }
                         woocommerce_update_order_item_meta($recurring_item_id, '_line_tax_data', $recurring_tax_data);
                         break;
                     default:
                         break;
                 }
             }
             // Copy over line item meta data, with some parent/child role based exceptions for recurring amounts
             $copy_to_renewal_item = true;
             switch ($meta_key) {
                 case '_recurring_line_total':
                 case '_recurring_line_tax':
                 case '_recurring_line_subtotal':
                 case '_recurring_line_subtotal_tax':
                 case '_recurring_line_tax_data':
                 case '_line_tax_data':
                 case '_subscription_recurring_amount':
                 case '_subscription_sign_up_fee':
                 case '_subscription_period':
                 case '_subscription_interval':
                 case '_subscription_length':
                 case '_subscription_trial_period':
                 case '_subscription_end_date':
                 case '_subscription_expiry_date':
                 case '_subscription_start_date':
                 case '_subscription_status':
                 case '_subscription_completed_payments':
                     if ('child' == $args['new_order_role']) {
                         $copy_to_renewal_item = false;
                     }
                     break;
                 case '_subscription_trial_length':
                     // We never want to duplicate free trials on renewal orders
                     $copy_to_renewal_item = false;
                     break;
                 case '_subscription_suspension_count':
                     // We want to reset some values for the new order
                 // We want to reset some values for the new order
                 case '_subscription_trial_expiry_date':
                 case '_subscription_failed_payments':
                     $copy_to_renewal_item = false;
                     $meta_value = 0;
                     break;
                 default:
                     break;
             }
             // Copy existing item over to new recurring order item
             if ($copy_to_renewal_item) {
                 // cast it to an array. Arrays will be kept, strings will be an array. Tested back to PHP 5.2.16
                 foreach ($meta_values as $meta_value) {
                     woocommerce_add_order_item_meta($recurring_item_id, $meta_key, $meta_value);
                 }
             }
         }
     }
     if (false == $args['checkout_renewal']) {
         // Add fees
         foreach ($original_order->get_fees() as $item_id => $order_fee) {
             if (!isset($order_fee['recurring_line_total'])) {
                 continue;
             }
             $item_id = woocommerce_add_order_item($renewal_order_id, array('order_item_name' => $order_fee['name'], 'order_item_type' => 'fee'));
             woocommerce_add_order_item_meta($item_id, '_tax_class', $order_fee['tax_class']);
             woocommerce_add_order_item_meta($item_id, '_line_total', WC_Subscriptions::format_total($order_fee['recurring_line_total']));
             woocommerce_add_order_item_meta($item_id, '_line_tax', WC_Subscriptions::format_total($order_fee['recurring_line_tax']));
         }
     }
     // Keep a record of the original order's ID on the renewal order
     update_post_meta($renewal_order_id, '_original_order', $original_order->id, true);
     $renewal_order = new WC_Order($renewal_order_id);
     if ('parent' == $args['new_order_role']) {
         WC_Subscriptions_Manager::process_subscriptions_on_checkout($renewal_order_id);
         $original_order->add_order_note(sprintf(__('Order superseded by Renewal Order %s.', 'woocommerce-subscriptions'), $renewal_order->get_order_number()));
     }
     do_action('woocommerce_subscriptions_renewal_order_created', $renewal_order, $original_order, $product_id, $args['new_order_role']);
     return apply_filters('woocommerce_subscriptions_renewal_order_id', $renewal_order_id, $original_order, $product_id, $args['new_order_role']);
 }