2

How can I use information in Views about whether a particular product is in this user's cart? Particularly, how many times into a Views row for that product?

For example, on a view listing available products, I'd like to be able to stylistically differentiate the rows representing products the customer has already added to their cart, and/or show a field, empty by default, stating how many of that item are already in the user's cart.

I've looked at existing Commerce modules such as Commerce Views Display and Commerce Add to Cart Extras, but can't see anything directly relevant. I'm not sure how to proceed with creating something to do this short of writing a custom Views query which also loads the Commerce cart for each row, which I'd rather not do since I'm not sure how I could make it reasonably efficient.

Does anything exist to support this, or if not, is there a simpler/more integrated, less "reinventing the wheel" approach using the Views and/or Commerce API?


An ideal result would be a Views Field for commerce products outputting a simple number representing how many times a product with this product ID is in the cart. Turning that into all the above use-cases is easy (e.g. rewrite as a class product-in-cart-N then apply default styles to .product-in-cart-0, simply display the field with a label, etc etc).

1 Answer 1

2

I am not aware of any modules, that will provide the functionality that you described out of the box, but the snippets below will probably get you moving in the right direction.


You'd write a function that gets all product IDs that are in the cart.

/**
 * Return the product_id values for all products in the cart
 *
 * @return
 *  An array of product ids
 */
function CUSTOMMODULE_get_products_in_cart() {
  $cart_product_ids = &drupal_static(__FUNCTION__);

  if (!isset($cart_product_ids)) {
    global $user;
    $cart_product_ids = array();
    $order = commerce_cart_order_load($user->uid);
    if ($order) {
      $order_wrapper = entity_metadata_wrapper('commerce_order', $order);
      foreach ($order_wrapper->commerce_line_items as $delta => $line_item_wrapper) {
                if ($line_item_wrapper->type->value() == 'product') {
                    $product_wrapper = $line_item_wrapper->commerce_product;
                    $cart_product_ids[] = $product_wrapper->product_id->value();
                }
      }
    }
        $unique_cart_product_ids = array_unique($cart_product_ids);
  }

  return $cart_product_ids;
}

For adding a class to the views row according to the quantity in the cart you'd implement hook_views_pre_render() and implement your logic there

/**
 * Implements hook_views_pre_render().
 */
function CUSTOMMODULE_views_pre_render(&$view) {
  if ($view->name == 'your_view_name') {
        // get product_ids in cart
        $cart_product_ids = CUSTOMMODULE_get_products_in_cart();
        if (in_array($product->product_id, $cart_product_ids)) {
            // check how many times product_id is in the present in the array
            // do other stuff - apply class, etc.
        }
  }
}

Also, you'd probably want to change the "Add to Cart" button text to something custom if the product is already in the cart

function CUSTOMMODULE_form_commerce_cart_add_to_cart_form_alter(&$form, &$form_state) {
  $cart_product_ids = CUSTOMMODULE_get_products_in_cart();
    if (in_array($product->product_id, $unique_cart_product_ids)) {
        // Product is already in cart
        // Change "Add to Cart" button text
        $form['submit']['#value'] = t('Add one more'); // your custom text and maybe a quantity of that product that is already in cart...
    }
}

I think using hook_views_pre_render() is the right way to go about this, but if there is more efficient or easier way I'd like for others to pitch in with ideas.

Hope this helps.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.