You are here

function _commerce_discount_check_compatibility in Commerce Discount 7

Performs a discount compatibility check for the given price field.

Parameters

object $discount: The discount entity whose compatibility is being checked.

array $price: The price field value whose components array indicates which discounts have already been applied to it.

Return value

bool Boolean indicating whether or not the compatibility check passed.

2 calls to _commerce_discount_check_compatibility()
commerce_discount_compatibility_check in ./commerce_discount.rules.inc
Rules callback: executes the "Check discount compatibility at the order level" condition.
commerce_discount_line_item_compatibility_check in ./commerce_discount.rules.inc
Rules callback: executes the "Check discount compatibility at the line item level" condition.

File

./commerce_discount.rules.inc, line 471
Rules integration for the Commerce Discount module.

Code

function _commerce_discount_check_compatibility($discount, $price) {

  // Get the strategy from the compatibility strategy field.
  $strategy = commerce_discount_get_compatibility_strategy($discount);

  // Determine which discounts of a similar discount type have been applied to
  // the price thus far. Compatibility checks currently only take into account
  // discounts of the same type due to process limitations (i.e. Product
  // discounts *always* apply before Order discounts) and usability constraints
  // (i.e. we have data to make Order discount applicability dependent on
  // Product discounts, but we do not have a clear way to indicate that uni-
  // directionality in the UI yet).
  $applied_discounts = commerce_discount_get_discounts_applied_to_price($price, $discount->type);

  // Ensure none of them indicate they are incompatible with the current one.
  foreach ($applied_discounts as $applied_discount_id => $applied_discount_name) {

    // Determine the strategy of the existing discount.
    $existing_discount = entity_load_single('commerce_discount', $applied_discount_name);
    $existing_strategy = commerce_discount_get_compatibility_strategy($existing_discount);

    // If the discount is compatible with any other discount, continue on.
    if ($existing_strategy == 'any') {
      continue;
    }

    // If the discount is not compatible with any other discount, return FALSE.
    if ($existing_strategy == 'none') {
      return FALSE;
    }

    // Get the selected discount value from the existing discount.
    $existing_selection = commerce_discount_get_compatibility_selection($existing_discount);

    // If the discount is incompatible with select discounts and the current
    // discount was selected, return FALSE.
    if ($existing_strategy == 'except' && in_array($discount->discount_id, $existing_selection)) {
      return FALSE;
    }

    // If the discount is only compatible with select discounts and the current
    // discount was not selected, return FALSE.
    if ($existing_strategy == 'only' && !in_array($discount->discount_id, $existing_selection)) {
      return FALSE;
    }
  }

  // If the discount is not compatible with any other discount and we found
  // applied discounts, return FALSE.
  if ($strategy == 'none' && count($applied_discounts) > 0) {
    return FALSE;
  }

  // Get the selected discount value from the discount being evaluated.
  $selection = commerce_discount_get_compatibility_selection($discount);

  // If the discount is not compatible with selected discounts, ensure they
  // are not on the order.
  if ($strategy == 'except') {
    foreach ($applied_discounts as $applied_discount_id => $applied_discount_name) {
      if (in_array($applied_discount_id, $selection)) {
        return FALSE;
      }
    }
  }

  // If the discount is only compatible with selected discounts, ensure no other
  // discounts are on the order.
  if ($strategy == 'only') {
    foreach ($applied_discounts as $applied_discount_id => $applied_discount_name) {
      if (!in_array($applied_discount_id, $selection)) {
        return FALSE;
      }
    }
  }

  // Return TRUE if nothing has disqualified compatibility yet. For example, if
  // the discount is compatible with any other discount and no other discounts
  // on the order specifies an incompatibility with this discount or if this
  // discount were incompatible with other discounts but none have been applied
  // to the order yet.
  return TRUE;
}