You are here

public function PromotionStorage::loadAvailable in Commerce Core 8.2

Loads the available promotions for the given order.

Parameters

\Drupal\commerce_order\Entity\OrderInterface $order: The order.

string[] $offer_ids: (Optional) A list of offer IDs to filter by.

Return value

\Drupal\commerce_promotion\Entity\PromotionInterface[] The available promotions.

Overrides PromotionStorageInterface::loadAvailable

File

modules/promotion/src/PromotionStorage.php, line 82

Class

PromotionStorage
Defines the promotion storage.

Namespace

Drupal\commerce_promotion

Code

public function loadAvailable(OrderInterface $order, array $offer_ids = []) {
  $date = $order
    ->getCalculationDate()
    ->format(DateTimeItemInterface::DATETIME_STORAGE_FORMAT);
  $query = $this
    ->getQuery();
  $or_condition = $query
    ->orConditionGroup()
    ->condition('end_date', $date, '>')
    ->notExists('end_date');
  $query
    ->condition('stores', [
    $order
      ->getStoreId(),
  ], 'IN')
    ->condition('order_types', [
    $order
      ->bundle(),
  ], 'IN')
    ->condition('start_date', $date, '<=')
    ->condition('status', TRUE)
    ->condition($or_condition)
    ->accessCheck(FALSE);
  if ($offer_ids) {
    $query
      ->condition('offer.target_plugin_id', $offer_ids, 'IN');
  }

  // Only load promotions without coupons. Promotions with coupons are loaded
  // coupon-first in a different process.
  $query
    ->notExists('coupons');
  $result = $query
    ->execute();
  if (empty($result)) {
    return [];
  }
  $promotions = $this
    ->loadMultiple($result);

  // Remove any promotions that do not have a usage limit.
  $promotions_with_usage_limits = array_filter($promotions, function ($promotion) {

    /** @var \Drupal\commerce_promotion\Entity\PromotionInterface $promotion */
    return !empty($promotion
      ->getUsageLimit());
  });
  $usages = $this->usage
    ->loadMultiple($promotions_with_usage_limits);
  foreach ($promotions_with_usage_limits as $promotion_id => $promotion) {

    /** @var \Drupal\commerce_promotion\Entity\PromotionInterface $promotion */
    if ($promotion
      ->getUsageLimit() <= $usages[$promotion_id]) {
      unset($promotions[$promotion_id]);
    }
  }

  // Remove any promotions that do not have a customer usage limit.
  $promotions_with_customer_usage_limits = array_filter($promotions, function ($promotion) {

    /** @var \Drupal\commerce_promotion\Entity\PromotionInterface $promotion */
    return !empty($promotion
      ->getCustomerUsageLimit());
  });

  // Email is required for promotions that have customer usage limits.
  $email = $order
    ->getEmail();
  if (!$email) {
    foreach ($promotions_with_customer_usage_limits as $promotion_id => $promotion) {
      unset($promotions[$promotion_id]);
    }
  }
  else {
    $customer_usages = $this->usage
      ->loadMultiple($promotions_with_customer_usage_limits, $email);
    foreach ($promotions_with_customer_usage_limits as $promotion_id => $promotion) {

      /** @var \Drupal\commerce_promotion\Entity\PromotionInterface $promotion */
      if ($promotion
        ->getCustomerUsageLimit() <= $customer_usages[$promotion_id]) {
        unset($promotions[$promotion_id]);
      }
    }
  }

  // Sort the remaining promotions.
  uasort($promotions, [
    $this->entityType
      ->getClass(),
    'sort',
  ]);
  return $promotions;
}