/**
* Prepare recurring amounts, taxes etc for subscription items
*
* @access public
* @param int $order_id
* @return void
*/
public function new_order($order_id)
{
global $woocommerce;
// Iterate over real cart and work with subscription products (if any)
foreach ($woocommerce->cart->cart_contents as $cart_item_key => $cart_item) {
$id = !empty($cart_item['variation_id']) ? $cart_item['variation_id'] : $cart_item['product_id'];
if (Subscriptio_Subscription_Product::is_subscription($id)) {
$product = new WC_Product($id);
// Store all required renewal order fields here
$renewal_order = array(
'taxes' => array(),
'shipping' => array(),
);
// Create fake cart to mimic renewal order
$renewal_cart = new WC_Cart();
// Add product to cart
$renewal_cart->add_to_cart(
$cart_item['product_id'],
$cart_item['quantity'],
(isset($cart_item['variation_id']) ? $cart_item['variation_id'] : ''),
(isset($cart_item['variation']) ? $cart_item['variation'] : '')
);
// Get fake cart item key
$renewal_cart_item_keys = array_keys($renewal_cart->cart_contents);
$renewal_cart_item_key = array_shift($renewal_cart_item_keys);
// Set renewal price
$renewal_cart->cart_contents[$renewal_cart_item_key]['data']->price = Subscriptio_Subscription_Product::get_recurring_price($id);
// Add shipping
if ($product->needs_shipping() && $renewal_cart->needs_shipping()) {
// Get instance of checkout object to retrieve shipping options
$wc_checkout = WC_Checkout::instance();
// Iterate over shipping packages
foreach ($woocommerce->shipping->get_packages() as $package_key => $package) {
// Check if this rate was selected
if (isset($package['rates'][$wc_checkout->shipping_methods[$package_key]])) {
// Check if it contains current subscription
if (isset($package['contents'][$cart_item_key])) {
// Save shipping details for further calculation
$shipping_details = array(
'shipping_method' => $wc_checkout->shipping_methods[$package_key],
'destination' => $package['destination'],
);
// Save shipping address
$renewal_order['shipping_address'] = array(
// First three lines may need to be changed to make this compatible with shipping extensions that allow multiple shipping addresses
'_shipping_first_name' => $wc_checkout->posted['ship_to_different_address'] ? $wc_checkout->posted['shipping_first_name'] : $wc_checkout->posted['billing_first_name'],
'_shipping_last_name' => $wc_checkout->posted['ship_to_different_address'] ? $wc_checkout->posted['shipping_last_name'] : $wc_checkout->posted['billing_last_name'],
'_shipping_company' => $wc_checkout->posted['ship_to_different_address'] ? $wc_checkout->posted['shipping_company'] : $wc_checkout->posted['billing_company'],
'_shipping_address_1' => $shipping_details['destination']['address'],
'_shipping_address_2' => $shipping_details['destination']['address_2'],
'_shipping_city' => $shipping_details['destination']['city'],
'_shipping_state' => $shipping_details['destination']['state'],
'_shipping_postcode' => $shipping_details['destination']['postcode'],
'_shipping_country' => $shipping_details['destination']['country'],
);
break;
}
}
}
// Got the shipping method and address for the package that contains current subscription?
if (!isset($shipping_details)) {
continue;
}
// Get packages based on renewal order details
$packages = apply_filters('woocommerce_cart_shipping_packages', array(
0 => array(
'contents' => $renewal_cart->get_cart(),
'contents_cost' => isset($renewal_cart->cart_contents[$renewal_cart_item_key]['line_total']) ? $renewal_cart->cart_contents[$renewal_cart_item_key]['line_total'] : 0,
'applied_coupons' => $renewal_cart->applied_coupons,
'destination' => $shipping_details['destination'],
),
));
// Now we need to calculate shipping costs but this requires overwriting session variables
// In order not to affect real cart, we will overwrite them but then set them back to original values
$original_session = array(
'chosen_shipping_methods' => $woocommerce->session->get('chosen_shipping_methods'),
'shipping_method_counts' => $woocommerce->session->get('shipping_method_counts'),
);
// Set fake renewal values
$woocommerce->session->set('chosen_shipping_methods', array($shipping_details['shipping_method']));
$woocommerce->session->set('shipping_method_counts', array(1));
// Override chosen shipping method in case there's a mismatch in shipping_method_counts (more than one available)
add_filter('woocommerce_shipping_chosen_method', array($this, 'set_shipping_chosen_method'));
$this->temp_shipping_chosen_method = $shipping_details['shipping_method'];
// Calculate shipping for fake renewal order now
$woocommerce->shipping->calculate_shipping($packages);
// Remove filter
remove_filter('woocommerce_shipping_chosen_method', array($this, 'set_shipping_chosen_method'));
$this->temp_shipping_chosen_method = null;
}
// Recalculate totals
$renewal_cart->calculate_totals();
// Get taxes
foreach ($renewal_cart->get_tax_totals() as $rate_key => $rate) {
$renewal_order['taxes'][] = array(
'name' => $rate_key,
'rate_id' => $rate->tax_rate_id,
'label' => $rate->label,
'compound' => absint($rate->is_compound ? 1 : 0),
'tax_amount' => wc_format_decimal(isset($renewal_cart->taxes[$rate->tax_rate_id]) ? $renewal_cart->taxes[$rate->tax_rate_id] : 0),
'shipping_tax_amount' => wc_format_decimal(isset($renewal_cart->shipping_taxes[$rate->tax_rate_id]) ? $renewal_cart->shipping_taxes[$rate->tax_rate_id] : 0),
);
}
// Get renewal_order_shipping
$renewal_order['renewal_order_shipping'] = wc_format_decimal($renewal_cart->shipping_total);
// Get renewal_order_shipping_tax
$renewal_order['renewal_order_shipping_tax'] = wc_format_decimal($renewal_cart->shipping_tax_total);
// Get renewal_cart_discount
$renewal_order['renewal_cart_discount'] = wc_format_decimal($renewal_cart->get_cart_discount_total());
// Get renewal_order_discount
$renewal_order['renewal_order_discount'] = wc_format_decimal($renewal_cart->get_order_discount_total());
// Get renewal_order_tax
$renewal_order['renewal_order_tax'] = wc_format_decimal($renewal_cart->tax_total);
// Get renewal_order_total
$renewal_order['renewal_order_total'] = wc_format_decimal($renewal_cart->total, get_option('woocommerce_price_num_decimals'));
// Get renewal_line_subtotal
$renewal_order['renewal_line_subtotal'] = wc_format_decimal($renewal_cart->cart_contents[$renewal_cart_item_key]['line_subtotal']);
// Get renewal_line_subtotal_tax
$renewal_order['renewal_line_subtotal_tax'] = wc_format_decimal($renewal_cart->cart_contents[$renewal_cart_item_key]['line_subtotal_tax']);
// Get renewal_line_total
$renewal_order['renewal_line_total'] = wc_format_decimal($renewal_cart->cart_contents[$renewal_cart_item_key]['line_total']);
// Get renewal_line_tax
$renewal_order['renewal_line_tax'] = wc_format_decimal($renewal_cart->cart_contents[$renewal_cart_item_key]['line_tax']);
// Get shipping details
if ($product->needs_shipping()) {
if (isset($woocommerce->shipping->packages[0]['rates'][$shipping_details['shipping_method']])) {
$method = $woocommerce->shipping->packages[0]['rates'][$shipping_details['shipping_method']];
$renewal_order['shipping'] = array(
'name' => $method->label,
'method_id' => $method->id,
'cost' => wc_format_decimal( $method->cost ),
);
}
// Set session variables to original values and recalculate shipping for original order which is being processed now
$woocommerce->session->set('chosen_shipping_methods', $original_session['chosen_shipping_methods']);
$woocommerce->session->set('shipping_method_counts', $original_session['shipping_method_counts']);
$woocommerce->shipping->calculate_shipping($packages);
}
// Save to object property so it can be accessed from another method
$this->renewal_orders['by_cart_item_key'][$cart_item_key] = $renewal_order;
}
}
}