function commerce_order_calculate_total in Commerce Core 7
Calculates the order total, updating the commerce_order_total field data in the order object this function receives.
Parameters
$order: The order object whose order total should be calculated.
See also
1 call to commerce_order_calculate_total()
- CommerceOrderEntityController::save in modules/
order/ includes/ commerce_order.controller.inc - Saves an order.
File
- modules/
order/ commerce_order.module, line 1295 - Defines the core Commerce order entity and API functions to manage orders and interact with them.
Code
function commerce_order_calculate_total($order) {
$order_wrapper = entity_metadata_wrapper('commerce_order', $order);
// First determine the currency to use for the order total.
$default_currency_code = $currency_code = commerce_default_currency();
$currencies = array();
// Populate an array of how many line items on the order use each currency.
foreach ($order_wrapper->commerce_line_items as $delta => $line_item_wrapper) {
// If the current line item actually no longer exists...
if (!$line_item_wrapper
->value()) {
// Remove the reference from the order and continue to the next value.
$order_wrapper->commerce_line_items
->offsetUnset($delta);
continue;
}
$line_item_currency_code = $line_item_wrapper->commerce_total->currency_code
->value();
if (!isset($currencies[$line_item_currency_code])) {
$currencies[$line_item_currency_code] = 1;
}
else {
$currencies[$line_item_currency_code]++;
}
}
reset($currencies);
// If only one currency is present on the order, use that to calculate the
// order total.
if (count($currencies) == 1) {
$currency_code = key($currencies);
}
elseif (isset($currencies[$default_currency_code])) {
// Otherwise use the site default currency if it's in the order.
$currency_code = $default_currency_code;
}
elseif (count($currencies) > 1) {
// Otherwise use the first currency on the order. We do this instead of
// trying to determine the most dominant currency for now because using the
// first currency leaves the option open for a UI based module to let
// customers reorder the items in the cart by currency to get the order
// total in a different currency. The currencies array still contains useful
// data, though, should we decide to expand on the count by currency approach.
$currency_code = key($currencies);
}
// Initialize the order total with the selected currency.
$order_wrapper->commerce_order_total->amount = 0;
$order_wrapper->commerce_order_total->currency_code = $currency_code;
// Reset the data array of the order total field to only include a
// base price component, set the currency code from any line item.
$base_price = array(
'amount' => 0,
'currency_code' => $currency_code,
'data' => array(),
);
$order_wrapper->commerce_order_total->data = commerce_price_component_add($base_price, 'base_price', $base_price, TRUE);
$order_total = $order_wrapper->commerce_order_total
->value();
// Then loop over each line item and add its total to the order total.
$amount = 0;
foreach ($order_wrapper->commerce_line_items as $delta => $line_item_wrapper) {
// Convert the line item's total to the order's currency for totalling.
$line_item_total = $line_item_wrapper->commerce_total
->value();
$component_total = commerce_price_component_total($line_item_total);
// Add the totals.
$amount += commerce_currency_convert($component_total['amount'], $component_total['currency_code'], $currency_code);
// Combine the line item total's component prices into the order total.
$order_total['data'] = commerce_price_components_combine($order_total, $line_item_total);
}
// Update the order total price field with the final total amount and data.
$order_wrapper->commerce_order_total->amount = round($amount);
$order_wrapper->commerce_order_total->data = $order_total['data'];
}