Here is some code for adding the rules based on number of products of specific product-type:
/**
* 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;
}
}
This could be combined with:
#1267156-20: Create a "Remove single item from cart" action →