2

We have a field in our user profiles that is checkmarked when a user adds a product to their shopping cart (with Drupal Commerce). This is used to display a message reminding them to checkout if they have items in their cart. I have successfully set up rules to check the field when they add a product, and uncheck it when they make it through checkout.

However, I also need to uncheck the field if a user removes all products from their cart. I can't seem to figure out what conditions to add to check if the user's cart is empty after a product has been removed.

Any suggestions?

1

You could try adding a rule that looks at the total number of items in the cart. Just get the count of the line items list within rules.

| improve this answer | |
  • 1
    I ended up using "Data value is empty" for commerce-order:commerce-line-items instead of counting the number of line items, but it's the same idea. I wasn't thinking of checking line items as opposed to checking the cart itself. – Mrweiner Dec 31 '15 at 0:53
1

May be "Commerce Cart Context" module will be usefull for you.

| improve this answer | |
  • Adding another module for this seems like it may be overkill, but it definitely does cover this use case perfectly. – Mrweiner Jan 3 '16 at 18:23
0

You can define a condition rule which can count products in your cart, for example:

/**
 * Implements hook_rules_condition_info().
 */
function foo_webstore_rules_condition_info() {
  return array(
    'foo_webstore_rules_condition_ordered_num_line_items' => array(
      'group' => t('Commerce'),
      'callbacks' => array(
        'execute' => 'foo_webstore_rules_condition_ordered_num_line_items',
      ),
      'label' => t('User ordered number of line items'),
      'parameter' => array(
        'count_type' => array(
          'type' => 'text',
          'label' => t('Products to compare'),
          'description' => t('Select which products should be taken into consideration.'),
          'optional' => TRUE,
          'default value' => '=',
          'options list' => 'foo_webstore_rules_condition_ordered_num_line_items_count_types',
          'restriction' => 'input',
        ),
        'commerce_line_item' => array(
          'type' => 'commerce_line_item',
          'label' => t('Product')
        ),
        'operator' => array(
          'type' => 'text',
          'label' => t('Operator'),
          'description' => t('The comparison operator.'),
          'optional' => TRUE,
          'default value' => '=',
          'options list' => 'commerce_numeric_comparison_operator_options_list',
          'restriction' => 'input',
        ),
        'value' => array(
          'type' => 'text',
          'label' => t('Value'),
          'description' => t('Integer representing a value.'),
          'default value' => '0',
        ),
      ),
      'module' => 'foo_webstore',
    ),
  );
}

/**
 * Rules condition's select box items for "Products to compare".
 */
function foo_webstore_rules_condition_ordered_num_line_items_count_types() {
  return array(
    'any' => t('Count products of any type'),
    'any|free' => t('Count free products of any type'),
    'exact' => t('Count products of the same type'),
    'exact|free' => t('Count free products of the same type'),
  );
}

/**
 * Rules action callback for "User ordered number of line items".
 */
function foo_webstore_rules_condition_ordered_num_line_items($count_type, $line_item, $operator, $value) {
  $count_types = explode('|', $count_type);

  $num_in_cart  = 0;
  $product_id   = $line_item->data['context']['entity']['entity_id'];
  $line_item_id = $line_item->line_item_id;
  $product_id   = reset($line_item->data['context']['product_ids']);

  // Checking total number of products in the cart.
  $cart_order = commerce_cart_order_load($GLOBALS['user']->uid);

  foreach ($cart_order->commerce_line_items[LANGUAGE_NONE] as $item) {
    $cart_line_item = commerce_line_item_load($item['line_item_id']);
    $cart_product_id = reset($cart_line_item->data['context']['product_ids']);
    $cart_product_price_free = $cart_line_item->commerce_total[LANGUAGE_NONE][0]['amount'] == 0;

    if (in_array('any', $count_types) || (in_array('exact', $count_types) && $cart_product_id === $product_id)) {
      if (!in_array('free', $count_types) || $cart_product_price_free) {
        ++$num_in_cart;
      }
    }
  }

  $num_bought = 0;

  // Checking how many products of this is user already bought.
  $data = db_query("
    SELECT LI.line_item_id AS lid, LI.quantity, LI.data
    FROM commerce_order O
    LEFT JOIN commerce_line_item LI ON LI.order_id = O.order_id
    WHERE O.`status` NOT IN ('selected', 'cart', 'canceled') AND O.uid = :uid
  ", array(
    ':uid' => $GLOBALS['user']->uid
  ))->fetchAll();

  foreach ($data as $row) {
    $commerce_data = unserialize ($row->data);
    $bought_product_id = reset($commerce_data['context']['product_ids']);

    // @TODO: Would be a good idea to check price in another way if we want code to be shareable.
    $bought_product = commerce_product_load($bought_product_id);

    $bought_product_price_free = $bought_product->commerce_price_eur[LANGUAGE_NONE][0]['amount'] == 0;

    if (in_array('any', $count_types) || (in_array('exact', $count_types) && $bought_product_id === $product_id)) {
      if (!in_array('free', $count_types) || $bought_product_price_free) {
        ++$num_bought;
      }
    }
  }

  // "1" is for current line item.
  $num_total = $num_in_cart + $num_bought + 1;

  switch ($operator) {
    case '<':  return $num_total <  $value;
    case '<=': return $num_total <= $value;
    case '=':  return $num_total == $value;
    case '>=': return $num_total >= $value;
    case '>':  return $num_total >  $value;
  }
}

Related: Add rule for counting/limiting the product line items

| improve this answer | |

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.