In a current project i am looking for the following:

When a users clicks the 'add to cart' button to add a product, a message should appear telling the user they first need to login to be able to add the product to the cart.

With a checkout rule i can create the message which tells te user that they should login. Problem is the item is still added to the cart after the message is shown.

So my first question is, how can i deny the product from being added to the cart after showing the message.
My second question is, how can i make sure that the user can go to the login page and after logging in the user will be redirected back to the product he/she was trying to add?

If some things may be unclear, i will be more then happy to supply the needed information.

Thanx in advance,
Marco Fijn

Comments

EndEd’s picture

Hi, not in rules but in a module you can try a simple alterform like the following:

function MODULENAME_form_commerce_cart_add_to_cart_form_alter(&$form, &$form_state, $form_id) {
  $form['#validate'][] = 'MODULENAME_commerce_cart_add_to_cart_form_validate';
}
function MODULENAME_commerce_cart_add_to_cart_form_validate($form, &$form_state) {
  if ($form['uid']['#value'] == 0) { // Check for anonymous.
    form_set_error('quantity', t("ANY MESSAGE")); // Message telling the user to login.
    drupal_goto('user/login', drupal_get_destination()); // Redirection to the login form with current path as destination.
  }
}

That way the user recieves a message but the product will not be added to the Shopping Cart. It also redirects the user to the login form with the current path as destination when the user submits the login form.

Hope this helps :)

strakkie’s picture

Thanx a million! Works like a charm!

I implemented it in my template.php for my custom theme, thank you very much for your assistance!

-Edit:
Only the redirect after logging in does not work. It just redirects me to the normal users/% page.

strakkie’s picture

Status: Active » Needs work
EndEd’s picture

Ok, I think you should try the $form_state['redirect'] property then. http://drupal.org/node/310513

rszrama’s picture

Status: Needs work » Closed (fixed)

Another way you can accomplish this through Rules is by adding a product pricing rule to your site that sets the unit price of line items in anonymous carts to NULL (i.e. not just 0). Drupal Commerce will remove from the cart any product with a NULL price, so even if the product gets added, it will be removed on the subsequent pageload. Still, I'd recommend a code based solution to prevent the Add to Cart form submission process from happening at all.

ressa’s picture

Version: 7.x-1.0-beta2 » 7.x-1.2

I tried the module solution, but there were some things that didn't work in my situation. So based on Ryan's feedback I made a rule which fires if an anonymous user tries to add a product to the cart. It removes the product from the order, redirects to the register account page, showing the user a message why, and redirects to the page the user came from, after completing registration.

You can create the rule from the 'Product pricing rules' page, but you would have to remove the event 'Calculating the sell price of a product', so you might as well do it from the standard Rules page admin/config/workflow/rules

Add Event
- 'After adding a product to the cart'

Add Condition
- 'User has role(s)': 'anonymous user'

Add Actions
- 'Remove all products from an order': [commerce_order]
- 'Page redirect': user/register?destination=[site:current-page:path]
- 'Show a message on the site': 'Please register to add a product to your cart.', as a warning

For some reason, the message "YOUR_PRODUCT_NAME added to your cart." is shown. I got around this by showing 'register to add to cart' message as a warning, and hiding the 'added to cart' message with CSS:

.page-user-register .status {
  display: none;
}

I dont think confirmation messages(.status) are shown on the registration page(.page-user-register) anyway, so it shouldn't be a problem.

The rule 'Deny anonymous add to cart' exported

{ "rules_commerce_deny_anonymous_cart" : {
    "LABEL" : "Deny anonymous add to cart",
    "PLUGIN" : "reaction rule",
    "REQUIRES" : [ "rules", "commerce_cart" ],
    "ON" : [ "commerce_cart_product_add" ],
    "IF" : [
      { "user_has_role" : {
          "account" : [ "site:current-user" ],
          "roles" : { "value" : { "1" : "1" } }
        }
      }
    ],
    "DO" : [
      { "commerce_cart_empty" : { "commerce_order" : [ "commerce_order" ] } },
      { "redirect" : { "url" : "user\/register?destination=[site:current-page:path]" } },
      { "drupal_message" : {
          "message" : "Please register to add a product to your cart.",
          "type" : "warning",
          "repeat" : 0
        }
      }
    ]
  }
}
staceyrice’s picture

Importing this rule worked awesome for me! I created a view for my products and now when an anonymous user clicks the add to cart button, they get redirected to the user login page with a proper warning as to why and redirected to their original page! thank you!

ressa’s picture

I am glad it worked for you! The project the rule was intended for was scrapped, but at least it is being put to good use here on drupal.org :)

staceyrice’s picture

Definitely! And the instructions walking through how to set it up have helped me set up my own custom rules. I hadn't gotten around to learning how to use rules before, but it's pretty handy. Thanks!

user654’s picture

.

vegantriathlete’s picture

The rule was a clever way to deal with this. So, let's make it even slicker.

Instead of manually appending the destination query variable, I just clicked that handy checkbox at the bottom of the form that says "APPEND DESTINATION PARAMETER."

Since we are dealing with rules, why not create a custom action to remove the system messages?

/**
 * Implements hook_rules_action_info().
 */
function MODULENAME_rules_action_info() {
  $actions['MODULENAME_remove_messages'] = array(
    'label' => t('Remove all the system messages'),
    'group' => t('MODULENAME custom actions'),
  );
  return $actions;
}

/**
 * Custom action to remove system messages
 */
function MODULENAME_remove_messages() {
  // Retrieve all messages and clear the queue
  drupal_get_messages();
}

Sweet!

zooter626’s picture

i have a site where anonymous customers are allowed to purchase some products without creating an account. However, here are other products on the site which can only be purchased by users with role permission. So..

1) Users without role permission to buy those products should still be able to see the products. but..

2) They should not be able to add them to their cart, and should instead be redirected to the login page when they hit the "add to cart" button. and..

3) They should keep the other products already in their order.

The custom validation add to cart form hook from #1 does not totally work because drupal_goto is a redirect which is not permitted with ajax forms (usually on the node display of a product). same for me with $form_state['redirect'].

The suggestion in #5 to set the price to NULL works, but it disables the 'add to cart' button, so customers can't really be redirected to sign in in order to purchase the products.

Finally, the rule to 'remove all products from an order' is a bit overkill, especially if the customer just got done filling it with products they can actually purchase.

Still looking for ideas...

Anonymous’s picture

Issue summary: View changes

Excellent work @ressa #6 and @vegantriathlete #11. Implemented both suggestions and everything is working great. Thanks again for sharing.

sj.suraj’s picture

#1 will work fine. But login destination is working correctly. Here is the correct code for the same.

function MODULENAME_form_commerce_cart_add_to_cart_form_alter(&$form, &$form_state, $form_id) {
  $form['#validate'][] = 'MODULENAME_commerce_cart_add_to_cart_form_validate';
}
function MODULENAME_commerce_cart_add_to_cart_form_validate($form, &$form_state) {
  if ($form['uid']['#value'] == 0) { // Check for anonymous.
    form_set_error('quantity', t("ANY MESSAGE")); // Message telling the user to login.
    drupal_goto('user/login', array('query' => drupal_get_destination())); //CHANGED LINE // Redirection to the login form with current path as destination.
  }
}