You are here

class PromotionOrderProcessor in Commerce Core 8.2

Applies promotions to orders during the order refresh process.

Hierarchy

Expanded class hierarchy of PromotionOrderProcessor

1 string reference to 'PromotionOrderProcessor'
commerce_promotion.services.yml in modules/promotion/commerce_promotion.services.yml
modules/promotion/commerce_promotion.services.yml
1 service uses PromotionOrderProcessor
commerce_promotion.promotion_order_processor in modules/promotion/commerce_promotion.services.yml
Drupal\commerce_promotion\PromotionOrderProcessor

File

modules/promotion/src/PromotionOrderProcessor.php, line 15

Namespace

Drupal\commerce_promotion
View source
class PromotionOrderProcessor implements OrderPreprocessorInterface, OrderProcessorInterface {

  /**
   * The entity type manager.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected $entityTypeManager;

  /**
   * The language manager.
   *
   * @var \Drupal\Core\Language\LanguageManagerInterface
   */
  protected $languageManager;

  /**
   * Constructs a new PromotionOrderProcessor object.
   *
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   *   The entity type manager.
   * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
   *   The language manager.
   */
  public function __construct(EntityTypeManagerInterface $entity_type_manager, LanguageManagerInterface $language_manager) {
    $this->entityTypeManager = $entity_type_manager;
    $this->languageManager = $language_manager;
  }

  /**
   * {@inheritdoc}
   */
  public function preprocess(OrderInterface $order) {

    // Collect the promotion adjustments, to give promotions a chance to clear
    // any potential modifications made to the order prior to refreshing it.
    $promotion_ids = [];
    foreach ($order
      ->collectAdjustments([
      'promotion',
    ]) as $adjustment) {
      if (empty($adjustment
        ->getSourceId())) {
        continue;
      }
      $promotion_ids[] = $adjustment
        ->getSourceId();
    }

    // Additionally, promotions may have altered the order without actually
    // adding promotion adjustments to the order, in this case, we need to
    // inspect the order item data to see if arbitrary data was stored by
    // promotion offers.
    // This will eventually need to be replaced by a proper solution at some
    // point once we have a more reliable way to figure out what the applied
    // promotions are.
    foreach ($order
      ->getItems() as $order_item) {
      if ($order_item
        ->get('data')
        ->isEmpty()) {
        continue;
      }
      $data = $order_item
        ->get('data')
        ->first()
        ->getValue();
      foreach ($data as $key => $value) {
        $key_parts = explode(':', $key);

        // Skip order item data keys that are not starting by
        // "promotion:<promotion_id>".
        if (count($key_parts) === 1 || $key_parts[0] !== 'promotion' || !is_numeric($key_parts[1])) {
          continue;
        }
        $promotion_ids[] = $key_parts[1];
      }
    }

    // No promotions were found, stop here.
    if (!$promotion_ids) {
      return;
    }
    $promotion_ids = array_unique($promotion_ids);

    /** @var \Drupal\commerce_promotion\PromotionStorageInterface $promotion_storage */
    $promotion_storage = $this->entityTypeManager
      ->getStorage('commerce_promotion');
    $promotions = $promotion_storage
      ->loadMultiple($promotion_ids);

    /** @var \Drupal\commerce_promotion\Entity\PromotionInterface $promotion */
    foreach ($promotions as $promotion) {
      $promotion
        ->clear($order);
    }
  }

  /**
   * {@inheritdoc}
   */
  public function process(OrderInterface $order) {

    // Remove coupons that are no longer valid (due to availability/conditions.)
    $coupons_field_list = $order
      ->get('coupons');
    $constraints = $coupons_field_list
      ->validate();

    /** @var \Symfony\Component\Validator\ConstraintViolationInterface $constraint */
    foreach ($constraints as $constraint) {
      list($delta, $property_name) = explode('.', $constraint
        ->getPropertyPath());
      $coupons_field_list
        ->removeItem($delta);
    }
    $content_langcode = $this->languageManager
      ->getCurrentLanguage(LanguageInterface::TYPE_CONTENT)
      ->getId();

    /** @var \Drupal\commerce_promotion\Entity\CouponInterface[] $coupons */
    $coupons = $order
      ->get('coupons')
      ->referencedEntities();
    foreach ($coupons as $index => $coupon) {
      $promotion = $coupon
        ->getPromotion();
      $promotion
        ->apply($order);
    }

    // Non-coupon promotions are loaded and applied separately.

    /** @var \Drupal\commerce_promotion\PromotionStorageInterface $promotion_storage */
    $promotion_storage = $this->entityTypeManager
      ->getStorage('commerce_promotion');
    $promotions = $promotion_storage
      ->loadAvailable($order);
    foreach ($promotions as $promotion) {
      if (!$promotion
        ->applies($order)) {
        continue;
      }

      // Ensure the promotion is in the right language, to ensure promotions
      // adjustments labels are correctly translated.
      if ($promotion
        ->hasTranslation($content_langcode)) {
        $promotion = $promotion
          ->getTranslation($content_langcode);
      }
      $promotion
        ->apply($order);
    }
  }

}

Members

Namesort descending Modifiers Type Description Overrides
PromotionOrderProcessor::$entityTypeManager protected property The entity type manager.
PromotionOrderProcessor::$languageManager protected property The language manager.
PromotionOrderProcessor::preprocess public function Preprocesses an order. Overrides OrderPreprocessorInterface::preprocess
PromotionOrderProcessor::process public function Processes an order. Overrides OrderProcessorInterface::process
PromotionOrderProcessor::__construct public function Constructs a new PromotionOrderProcessor object.