You are here

function commerce_product_bundle_calculate_price in Commerce Product Bundle 7

Same name and namespace in other branches
  1. 7.2 commerce_product_bundle.rules.inc \commerce_product_bundle_calculate_price()

Calculates the price for a bundle line item.

Parameters

obj $line_item: The parent line item object.

bool $multiply_by_quantity: Indicates wether we should multiply the sub line items with the quantity of these items or not.

1 string reference to 'commerce_product_bundle_calculate_price'
commerce_product_bundle_default_rules_configuration in ./commerce_product_bundle.rules_defaults.inc
Implements hook_default_rules_configuration().

File

./commerce_product_bundle.rules.inc, line 120
Rules integration for product bundle.

Code

function commerce_product_bundle_calculate_price($line_item, $multiply_by_quantity) {
  $original_line_item_wrapper = entity_metadata_wrapper('commerce_line_item', $line_item);
  $original_line_item = $line_item;
  $unitprice = 0;
  $found_bundle = FALSE;
  $sub_items = commerce_product_bundle_get_sub_line_items($line_item);

  // If we do not find any sub line item. So we should try to find
  // the default sub products, to get a default price for this
  // product. This is primarly used for the product view, where we dont
  // get any line item with sub line items.
  if (count($sub_items) == 0) {

    // Save the currency_code before resetting the unit price.
    $original_line_item_currency_code = $original_line_item_wrapper->commerce_unit_price->currency_code
      ->value();

    // Reset the unit price to the product price - This will reset the price components.
    $original_line_item_wrapper->commerce_unit_price = $original_line_item_wrapper->commerce_product->commerce_price
      ->value();

    // Restore the currency_code after resetting the unit price.
    $original_line_item_wrapper->commerce_unit_price->currency_code = $original_line_item_currency_code;
    $product = $original_line_item_wrapper->commerce_product;
    foreach (field_info_instances('commerce_product', $product->type
      ->value()) as $product_field_name => $product_field) {

      // Set sub_product to false so that data does not carry over from the previous loop.
      $sub_product = FALSE;
      $info = field_info_field($product_field_name);

      // If it is a product reference.
      if ($info['type'] == 'commerce_product_reference') {

        // Check if the reference is potential a bundle product:
        $form_in_full_node_display = isset($product_field['display']['node_full']) && $product_field['display']['node_full']['type'] == 'commerce_bundle_product_add_to_cart_form';
        $form_in_default_display = isset($product_field['display']['default']) && $product_field['display']['default']['type'] == 'commerce_bundle_product_add_to_cart_form';
        if ($form_in_full_node_display || $form_in_default_display && !isset($product_field['display']['node_full'])) {

          // Get first sub product of this field, we assume that this is the
          // default product. (reset() or each() does not work, so use a foreach
          // loop.
          $product = $original_line_item_wrapper->commerce_product;
          foreach ($product->{$product_field_name} as $sub_product) {
            break;
          }

          // Check there is actually a value for $sub_product.
          if ($sub_product) {

            // For single value product reference field, we got no
            // commerce_product object. This checks, if we have the correct
            // objects and create one if not.
            if ($sub_product
              ->type() !== 'commerce_product' && is_numeric($sub_product
              ->value())) {

              // Load the product.
              $product = commerce_product_load($sub_product
                ->value());

              // Create commerce_product object instance.
              $sub_product = entity_metadata_wrapper('commerce_product', $product);
            }
            if ($form_in_full_node_display) {
              $settings = $product_field['display']['node_full']['settings'];
            }
            elseif ($form_in_default_display) {
              $settings = $product_field['display']['default']['settings'];
            }

            // Use the default value from the display settings to determine
            // the default quantity to use.
            $quantity = $settings['default_quantity'];
            if ($multiply_by_quantity) {
              $commerce_total = array();
              $commerce_total['amount'] = $quantity * $sub_product->commerce_price->amount
                ->value();
              $commerce_total['currency_code'] = $sub_product->commerce_price->currency_code
                ->value();

              // Add the components multiplied by the quantity to the data array.
              $data = $sub_product->commerce_price->data
                ->value();
              if (empty($data['components'])) {
                $data['components'] = array();
              }
              else {
                foreach ($data['components'] as $key => $component) {
                  $data['components'][$key]['price']['amount'] *= $quantity;
                }
              }

              // Set the updated data array to the total price.
              $commerce_total['data'] = $data;
              $component_total = $commerce_total;
            }
            else {
              $component_total['amount'] = $sub_product->commerce_price->amount
                ->value();
              $component_total['currency_code'] = $sub_product->commerce_price->currency_code
                ->value();
              $component_total['data'] = $sub_product->commerce_price->data
                ->value();
              $component_total['data']['components'] += array();
            }
            $unitprice += commerce_currency_convert($component_total['amount'], $component_total['currency_code'], $original_line_item_wrapper->commerce_unit_price->currency_code
              ->value());

            // Combine the line item total's component prices into the
            // unit price total.
            $original_line_item_wrapper->commerce_unit_price->data = commerce_price_components_combine($original_line_item_wrapper->commerce_unit_price
              ->value(), $component_total);
            $found_bundle = TRUE;
          }
        }
      }
    }
  }
  else {

    // Save the currency_code before resetting the unit price.
    $original_line_item_currency_code = $original_line_item_wrapper->commerce_unit_price->currency_code
      ->value();

    // Reset the unit price to the product price - This will reset the price components.
    $original_line_item_wrapper->commerce_unit_price = $original_line_item_wrapper->commerce_product->commerce_price
      ->value();

    // Restore the currency_code after resetting the unit price.
    $original_line_item_wrapper->commerce_unit_price->currency_code = $original_line_item_currency_code;
    foreach ($sub_items as $item) {
      $line_item_wrapper = entity_metadata_wrapper('commerce_line_item', $item);
      if ($multiply_by_quantity) {
        $line_item_wrapper->commerce_total->amount = $item->quantity * $line_item_wrapper->commerce_unit_price->amount
          ->value();
        $line_item_wrapper->commerce_total->currency_code = $line_item_wrapper->commerce_unit_price->currency_code
          ->value();

        // Add the components multiplied by the quantity to the data array.
        $data = $line_item_wrapper->commerce_unit_price->data
          ->value();
        if (empty($data['components'])) {
          $data['components'] = array();
        }
        else {
          foreach ($data['components'] as $key => $component) {
            $data['components'][$key]['price']['amount'] *= $item->quantity;
          }
        }

        // Set the updated data array to the total price.
        $line_item_wrapper->commerce_total->data = $data;
      }

      /*else {
          $component_total = commerce_price_component_total($line_item_wrapper->commerce_unit_price->value());
        }*/
      $line_item = $line_item_wrapper
        ->value();
      rules_invoke_event('commerce_product_bundle_calc', $line_item, commerce_order_load($original_line_item->order_id));
      $line_item_wrapper = entity_metadata_wrapper('commerce_line_item', $line_item);
      $component_total = commerce_price_component_total($line_item_wrapper->commerce_total
        ->value());
      $unitprice += commerce_currency_convert($component_total['amount'], $component_total['currency_code'], $original_line_item_wrapper->commerce_unit_price->currency_code
        ->value());

      // Combine the line item total's component prices into the unit
      // price total.
      $original_line_item_wrapper->commerce_unit_price->data = commerce_price_components_combine($original_line_item_wrapper->commerce_unit_price
        ->value(), $line_item_wrapper->commerce_total
        ->value());
      $found_bundle = TRUE;
    }
  }
  if ($found_bundle) {
    $original_line_item_wrapper->commerce_unit_price->amount = $unitprice;
  }
}