You are here

function commerce_product_bundle_add_to_cart in Commerce Product Bundle 7

Same name and namespace in other branches
  1. 7.2 commerce_product_bundle.module \commerce_product_bundle_add_to_cart()

Adds the specified product to a customer's shopping cart.

Most of the code is copied from commerce_cart_product_add, we need to copy to reorder the rules invokations.

Parameters

int $uid: The uid of the user whose cart you are adding the product to.

int $product_id: The ID of the product to add to the cart.

int $quantity: The quantity of this product to add to the cart.

array $subproducts: An array of products that relates to this bundle.

$line_item: The full line item object to save.

Return value

array|FALSE Returns FALSE if we can't load a product from the provided $product_id. Returns an array of new or updated line item objects for the bundle_line_item and the sub_line_items

1 call to commerce_product_bundle_add_to_cart()
commerce_product_bundle_add_to_cart_form_submit in ./commerce_product_bundle.module
Submit function to add product bundles to the cart.

File

./commerce_product_bundle.module, line 839
Allows the bundling of products in Drupal Commerce.

Code

function commerce_product_bundle_add_to_cart($uid, $product_id, $quantity, $subproducts, $line_item) {

  // Load and validate the specified product ID.
  $product = commerce_product_load($product_id);

  // Fail if the product does not exist or is disabled.
  if (empty($product) || !$product->status) {
    return FALSE;
  }

  // First attempt to load the customer's shopping cart order.
  $order = commerce_cart_order_load($uid);

  // If no order existed, create one now.
  if (empty($order)) {
    $order = commerce_cart_order_new($uid);
  }

  // Wrap the order for easy access to field data.
  $order_wrapper = entity_metadata_wrapper('commerce_order', $order);

  // Invoke the product prepare event with the shopping cart order.
  rules_invoke_all('commerce_cart_product_prepare', $order, $product, $quantity);

  // Determine if the product already exists on the order and increment its
  // quantity instead of adding a new line if it does.
  $matching_line_item = NULL;

  // TODO: Find a way to identify same bundles. A possible approach can be a
  // nested loop. Additionally we need to put this in a separate method with
  // a hook, because the commerce_option modules need to change this and other
  // modules too.

  /*
    // Loop through the line items looking for products.
    foreach ($order_wrapper->commerce_line_items as $delta => $line_item_wrapper) {
      // If this line item matches the product being added...
      if ($line_item_wrapper->type->value() == 'product' &&
          $line_item_wrapper->commerce_product->product_id->value() == $product_id) {
        $line_item = $line_item_wrapper->value();
        // Exit this loop with the $line_item intact so it gets updated.
        break;
      }
    }*/

  // If no matching line item was found.
  if (empty($matching_line_item)) {

    // Adjust the quantity.
    $line_item->quantity = $quantity;

    // Set the incoming line item's order_id.
    $line_item->order_id = $order->order_id;

    // Process the unit price through Rules so it reflects the user's actual
    // purchase price.
    rules_invoke_event('commerce_product_calculate_sell_price', $line_item);

    // Save the line item now so we get its ID.
    commerce_line_item_save($line_item);
    $sub_line_items = array();

    // Iterates over all sub products:
    foreach ($subproducts as $item_values) {
      $product_ids = array();
      if (is_array($item_values['product_id'])) {
        $product_ids = $item_values['product_id'];
      }
      else {
        $product_ids = array(
          $item_values['product_id'],
        );
      }
      foreach ($product_ids as $product_id) {

        // Check product.
        $subproduct = commerce_product_load($product_id);
        if (empty($subproduct) || !$subproduct->status) {

          // Skip this item, because it is not a valid one.
          continue;
        }

        // Check quantity.
        if ($item_values['quantity'] < 0) {

          // Skip, because it is not a valid quantity.
          continue;
        }
        $sub_line_item = commerce_product_bundle_line_item_new($subproduct, $line_item, $item_values['quantity'], $order->order_id);

        // Process the unit price through Rules so it reflects the user's actual
        // purchase price.
        rules_invoke_event('commerce_product_calculate_sell_price', $sub_line_item);

        // Save the line item.
        commerce_line_item_save($sub_line_item);
        $sub_line_items[$product_id] = $sub_line_item;
      }
    }

    // Process the unit price through Rules so it reflects the user's actual
    // purchase price.
    rules_invoke_event('commerce_product_calculate_sell_price', $line_item);

    // Save the line item now so we get its ID.
    commerce_line_item_save($line_item);

    // Add it to the order's line item reference value.
    $order_wrapper->commerce_line_items[] = $line_item;
  }
  else {

    // Increment the quantity of the line item and save it.
    $matching_line_item->quantity += $quantity;
    $matching_line_item->data = array_merge($line_item->data, $matching_line_item->data);
    commerce_line_item_save($matching_line_item);

    // Clear the line item cache so the updated quantity will be available to
    // the ensuing load instead of the original quantity as loaded above.
    entity_get_controller('commerce_line_item')
      ->resetCache(array(
      $matching_line_item->line_item_id,
    ));

    // Update the line item variable for use in the invocation and return value.
    $line_item = $matching_line_item;
  }

  // Save the updated order.
  commerce_order_save($order);

  // Invoke the product add event with the newly saved or updated line item.
  rules_invoke_all('commerce_cart_product_add', $order, $product, $quantity, $line_item);

  // Return the line item.
  return array(
    'line_item' => $line_item,
    'sub_line_items' => $sub_line_items,
  );
}