You are here

function commerce_cart_product_add in Commerce Core 7

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

Parameters

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

$line_item: An unsaved product line item to be added to the cart with the following data on the line item being used to determine how to add the product to the cart:

  • $line_item->commerce_unit_price: a non-NULL default unit price.
  • $line_item->commerce_product: reference to the product to add to the cart.
  • $line_item->quantity: quantity of this product to add to the cart.
  • $line_item->data: data array that is saved with the line item if the line item is added to the cart as a new item; merged into an existing line item if combination is possible.
  • $line_item->order_id: this property does not need to be set when calling this function, as it will be set to the specified user's current cart order ID.

Additional field data on the line item may be considered when determining whether or not line items can be combined in the cart. This includes the line item type, referenced product, and any line item fields that have been exposed on the Add to Cart form.

$combine: Boolean indicating whether or not to combine like products on the same line item, incrementing an existing line item's quantity instead of adding a new line item to the cart order. When the incoming line item is combined into an existing line item, field data on the existing line item will be left unchanged. Only the quantity will be incremented and the data array will be updated by merging the data from the existing line item onto the data from the incoming line item, giving precedence to the most recent data.

Return value

The new or updated line item object or FALSE on failure.

3 calls to commerce_cart_product_add()
CommerceBaseTestCase::createDummyOrder in tests/commerce_base.test
Create a dummy order in a given status.
commerce_cart_add_to_cart_form_submit in modules/cart/commerce_cart.module
Form submit handler: add the selected product to the cart.
commerce_cart_product_add_by_id in modules/cart/commerce_cart.module
Adds the specified product to a customer's shopping cart by product ID.

File

modules/cart/commerce_cart.module, line 1318
Implements the shopping cart system and add to cart features.

Code

function commerce_cart_product_add($uid, $line_item, $combine = TRUE) {

  // Do not add the line item if it doesn't have a unit price.
  $line_item_wrapper = entity_metadata_wrapper('commerce_line_item', $line_item);
  if (is_null($line_item_wrapper->commerce_unit_price
    ->value())) {
    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);
    $order->data['last_cart_refresh'] = REQUEST_TIME;
  }

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

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

  // Extract the product and quantity we're adding from the incoming line item.
  $product = $line_item_wrapper->commerce_product
    ->value();
  $quantity = $line_item->quantity;

  // 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;

  // If we are supposed to look for a line item to combine into...
  if ($combine) {

    // Generate an array of properties and fields to compare.
    $comparison_properties = array(
      'type',
      'commerce_product',
    );

    // Add any field that was exposed on the Add to Cart form to the array.
    // TODO: Bypass combination when an exposed field is no longer available but
    // the same base product is added to the cart.
    foreach (field_info_instances('commerce_line_item', $line_item->type) as $info) {
      if (!empty($info['commerce_cart_settings']['field_access'])) {
        $comparison_properties[] = $info['field_name'];
      }
    }

    // Allow other modules to specify what properties should be compared when
    // determining whether or not to combine line items.
    $line_item_clone = clone $line_item;
    drupal_alter('commerce_cart_product_comparison_properties', $comparison_properties, $line_item_clone);

    // Loop over each line item on the order.
    foreach ($order_wrapper->commerce_line_items as $delta => $matching_line_item_wrapper) {

      // Examine each of the comparison properties on the line item.
      foreach ($comparison_properties as $property) {

        // If the property is not present on either line item, bypass it.
        if (!isset($matching_line_item_wrapper
          ->value()->{$property}) && !isset($line_item_wrapper
          ->value()->{$property})) {
          continue;
        }

        // If any property does not match the same property on the incoming line
        // item or exists on one line item but not the other...
        if (!isset($matching_line_item_wrapper
          ->value()->{$property}) && isset($line_item_wrapper
          ->value()->{$property}) || isset($matching_line_item_wrapper
          ->value()->{$property}) && !isset($line_item_wrapper
          ->value()->{$property}) || $matching_line_item_wrapper->{$property}
          ->raw() != $line_item_wrapper->{$property}
          ->raw()) {

          // Continue the loop with the next line item.
          continue 2;
        }
      }

      // If every comparison line item matched, combine into this line item.
      $matching_line_item = $matching_line_item_wrapper
        ->value();
      break;
    }
  }

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

    // Save the incoming 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 matching line item, update the data array,
    // 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);

    // 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 $line_item;
}