I have Drupal 8 and Commerce 2. I created a "Merchant" and "Premium Merchant" role. By default, users who create a store have the "Merchant" role.

What I am trying to do is the following.

  • If the user has the "Merchant" role, the "Add to Cart" button on his products is deactivated for all users and visitors
  • If the user has the "Premium Merchant" role, the "Add to Cart" button on his products is activated for all users and visitors

How do I activate or deactivate the "Add to cart" button of a store's products according to the role of the store owner?

The Rules module is of no use because it has been in development for several years and is still not usable.

To summarize, the rule should be:

  • If the shop owner has the role "Premium Merchant", the products of his stores are purchasable
  • If the shop owner has the role "Merchant", the products of his stores are not purchasable

I also installed the Commerce Add To Cart Link module, which may be useful in my use case.

Option 1

In template files, may have conditions like the following.

{% if logged_in %}
{% else %}
{% endif %}

I discover programming. Can we write the rules of my questions in a template file?

<div{{ attributes }}>
  <a href="{{ url }}" class="add-to-cart-link" data-variation="{{ product_variation.id }}">{{ 'Add to cart'|t }}</a>


Option 2

I'm trying to create a custom module, but I do not know how to do it.

name: 'Commerce Add To Cart Access'
type: module
description: "Commerce Add To Cart Access for working with the commerce cart module."
# core: 8.x
package: Commerce
  - commerce:commerce_cart
  - commerce:commerce_product

# Information added by Drupal.org packaging script on 2018-10-25
version: '8.x-1.0'
core: '8.x'
project: 'commerce_add_to_cart_link'
datestamp: 1524519795

 * @file
 * Hook implementations of commerce_add_to_cart_access module.

use Drupal\commerce_product\Entity\ProductType;
use Drupal\commerce_product\Entity\ProductVariationType;
use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Url;

 * Implements ????? for commerce_product_variation.
function ????? {
  /** @var \Drupal\commerce_store\CurrentStoreInterface $current_store */
  $current_store = \Drupal::service('commerce_store.current_store');
  $owner = $current_store->getStore()->getOwner();
  $build['add_to_cart_link']['#access'] = $owner->hasRole('premium_merchant');
  $form['access_denied'] = ['#markup' => t('No online sales'),];
  • 1
    Questions aren't for a back and forth between the user who answer the question and the users who answer. It cannot be changed basing on the answers, and it cannot be expected that the users who answered change their answers basing on the new version of the question. Stack Exchange sites aren't forums. – apaderno Oct 28 '18 at 17:04

I think the function you need is: MYMODULE_form_commerce_order_item_add_to_cart_form_alter() source

I have a similar setup, but I am using the Variation Cart Form module, so some of the details are different. In my case I'm using HOOK_preprocess_commerce_product_variation() function.

In either case, I recommend using the preprocess function AND a custom template. The preprocess can run some logic and pass a variable to the template, which is where you decide what to display. I find working with templates easier than render arrays.

In your case, the .module file could have:

function MODULE_form_commerce_order_item_add_to_cart_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
  // Your original code to get store owner.
  $current_store = \Drupal::service('commerce_store.current_store');
  $owner = $current_store->getStore()->getOwner();
  // Default behavior is to disable add-to-cart button.
  $store_open = FALSE;
  if ($owner->hasRole('premium_merchant')) {
    // Only enable button if logic passes.
    $store_open = TRUE;
  // Pass variable to the form.
  // Not sure this is correct in the case of a form.
  $form['store_open'] = $store_open;

And in the template you could have the logic you referenced above:

{% if store_open %}
  add to cart
{% else %}
  product unavailable
{% endif %} 

FWIW, there may be other ways to solve this, which don't rely on the store owner's role. You could create a global variable, true/false, to run this check. In my case, I have a field on the products, so that some can be available to purchase and others not.

EDIT: the absolute easiest way is to avoid the template, as it's a relatively simple form element in this case. You can totally overwrite the form:

function MODULE_form_commerce_order_item_add_to_cart_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
  // Your original code to get store owner.
  $current_store = \Drupal::service('commerce_store.current_store');
  $owner = $current_store->getStore()->getOwner();
  if (!$owner->hasRole('premium_merchant')) {
    // Overwrite the whole form markup!
    $form = ['#markup' => 'Not available for purchase'];        

To clarify, you don't need to return $form in this case, because the function is passing the form by reference, i.e. &$form.

  • Thank you. I updated my question, your answer does not work for me – 553aa08930 Oct 27 '18 at 15:02
  • 1
    I edited above to show the correct function signature for hook_form_alter. My mistake. But you're going to have to do some more work to get this to function. Your .module file MUST have the actual code to get the store owner, as you originally had it. "// get store owner ..." was intended as a placeholder for that code. Also, realize that this function passes variable to a specific template. It does not pass it to the template you mention. Twig debug will help you identify that template: drupal.org/docs/8/theming/twig/debugging-twig-templates – BWagner Oct 27 '18 at 19:34
  • @WBagner I updated my question with a screenshot. I did not understand what I need to change. I do not master the code. I changed to debug: true. Here is one of my product page s1biose.com/produit/savon-artisanal-bio-la-cannelle Now, what should I do ? Thank you – 553aa08930 Oct 27 '18 at 22:57
  • @553aa08930 I had to spin up a demo site to verify this. I think you were on the right track, by emitting the markup from the form_alter module function. (You can definitely create structured html markup as an array, but it's not as simple as using 'markup'.) I updated the answer with that example. – BWagner Oct 28 '18 at 4:26
  • 2
    @553aa08930 My friend, the issues you raise are good, but they are different questions. You can create separate questions here to get those answers. FWIW, I think you're looking for the similar level of customization that I was. Your best opportunity for that is the Variation Cart Form module, as I mentioned at the top. – BWagner Oct 29 '18 at 16:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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