Development

Drupal Commerce Add To Cart Form Tweaks / Registration Improvements

In this example I’m showing how to improve the Add to Cart button for Drupal Commerce products to show differently based on whether or not users have already purchased a product, or whether the product is already in their cart.

I’m currently working on a site where users are registering for “programs,” which are synonymous with classes, courses, etc. I’m using the following modules (among others) in this example:

  • Drupal Commerce
  • Registration
  • Commerce Registration

Please understand that when a user registers for a course, they are actually purchasing a product that has a referenced Registration entity.

Here are the objectives I address with the code below:

Only allow the user to register once for each program (purchase a product once), and update the Add to Cart button to tell them they’ve already enrolled in the program (purchased the product).

If the user already added a program to their cart, update the Add To Cart button to tell them they’ve already added the program to their cart. As far as I can see, you could use this code for any type of product. You would simply replace “program” with the product type you wish to target. Please read the comments throughout the code to understand how the pieces work.

There are some considerations for people looking to do this with registrations, specifically. Note that the code below doesn’t handle the situation where a registration is canceled but the order isn’t updated to remove the associated program product line item. This is because we’re looking at the user’s product order history, not the user’s registration status for each program. To overcome this, instead of looking at the products a user has purchased, maybe we should look at registrations that are in the system for the user. I’ll post a comment to this post when I’ve written that functionality.

DISCLAIMER: This is not a plug-and-play module for a reason: there would be much to consider to make a contributed module that would work for every situation. This is simply an example of what you can do with a few functions for a custom implementation on a site.

Code

Result

Here is what the output looks like:

programs_mod

8 Comments

  • Avinash Raut

    Modify code to get product ids from commerce_line_item
    you made some very good join it help me to get exact that i want
    Thanks once again …

    /******************** get Product id for your custom (business logic)
    ********************* add in commerce_checkout module (commerce_checkout_complete) fucntion..
    *********************/
    function commerce_checkout_get_users_purchased_products($order_id) {
    /*start*/
    global $user;
    $purchased_product_ids = &drupal_static(__FUNCTION__);

    if (!isset($purchased_product_ids)) {
    $query = db_select(‘commerce_order’, ‘corder’);
    $query->join(‘commerce_line_item’, ‘li’, ‘corder.order_id = li.order_id’);
    $query->join(‘field_data_commerce_product’, ‘prod’, ‘li.line_item_id = prod.entity_id’);
    $query->condition(‘corder.uid’, $user->uid, ‘=’)
    ->condition(‘li.order_id’,$order_id, ‘=’)
    ->condition(‘corder.status’, ‘pending’, ‘=’)
    ->fields(‘prod’, array(‘commerce_product_product_id’));
    $result = $query->execute();

    $purchased_product_ids = array_unique($result->fetchCol());
    }

    return $purchased_product_ids;

    /*end*/
    }

  • Andrew

    This looks great. I am trying to do something very similar.

    Where do I put this code to intigrate into my site?

    Thanks for your help

    Andrew

  • Andrew

    In addition, does this apply to the active cart before checkout or is this user specific. Why I ask is that I want the user to be able to make separate bookings for different children. Each child has to have an individual order. So if this stops a user from purcvhasing two tickets to the same course it would not work for me.

    Thanks again

    Andrew

  • Hans K

    Thanks for this code. It works very well for one thing. I use it for the Commerce Add-to-cart button and had to change:
    $form['submit']['#disabled'] = TRUE;

    for:
    $form['submit']['#attributes']['disabled'] = 'disabled';

  • Natan Miranda

    Hey man, you saved my life!!! Tanks a lot! haha I was searching how check if user already purshased one product to limit only one product id by user. Perfect, tnks 😉

  • Juan Pablo

    Hello,

    recently I wrote a thanks giving comment for this approach that pointed me on the good way for my project.

    But after working a while I got an error:

    EntityMetadataWrapperException: Unknown data property commerce_product. in EntityStructureWrapper->getPropertyInfo() (line 335 of home/mysite/all/modules/contrib/entity/includes/entity.wrapper.inc

    because your code on mymodule_get_products_in_cart() function doesn’t checks the line item type on:

    $product_wrapper = $line_item_wrapper->commerce_product;

    assumming that all line item types have a ‘commerce_product’ field.
    But this is not the case on certain modules, for example commerce_shipping or custom_fees, that will set a line item type when you install them.

    I resolved this issue adding an if inside the foreach statement checking it:

    // There are ‘line_items’ as ‘shipping’ or ‘custom_fee’ without ‘commerce_product’ field
    if(isset($line_item_wrapper->commerce_product)) {
    $product_wrapper = $line_item_wrapper->commerce_product;
    $cart_product_ids[] = $product_wrapper->product_id->value();
    }

    Hope this helps somebody.

    And Thanks again!!

Leave a Reply

Your email address will not be published.