/** * @inheritdoc */ public function exec() { $discount = 0; $cartItems = $this->facade->getCart()->getCartItems(); /** @var Product $eligibleProduct */ $eligibleProduct = null; /** @var CartItem $cartItem */ foreach ($cartItems as $cartItem) { if (in_array($cartItem->getProduct()->getId(), $this->product_list)) { if (!$cartItem->getPromo() || $this->isAvailableOnSpecialOffers()) { $eligibleProduct = $cartItem; break; } } } if ($eligibleProduct !== null) { // Get the cart item for the eligible product $freeProductCartItem = $this->getRelatedCartItem($eligibleProduct); // We add the free product it only if it not yet in the cart. if ($freeProductCartItem === false) { if (null !== ($freeProduct = ProductQuery::create()->findPk($this->offeredProductId))) { // Store in the session that the free product is added to the cart, // so that we don't enter the following infinite loop : // // 1) exec() adds a product by firing a CART_ADDITEM event, // 2) the event is processed by Action\Coupon::updateOrderDiscount(), // 3) Action\Coupon::updateOrderDiscount() calls CouponManager::getDiscount() // 4) CouponManager::getDiscount() calls exec() -> Infinite loop !! // Store a marker first, we do not have the cart item id yet. $this->setRelatedCartItem($eligibleProduct, self::ADD_TO_CART_IN_PROCESS); $cartEvent = new CartEvent($this->facade->getCart()); $cartEvent->setNewness(true); $cartEvent->setAppend(false); $cartEvent->setQuantity(1); $cartEvent->setProductSaleElementsId($freeProduct->getDefaultSaleElements()->getId()); $cartEvent->setProduct($this->offeredProductId); $this->facade->getDispatcher()->dispatch(TheliaEvents::CART_ADDITEM, $cartEvent); // Store the final cart item ID. $this->setRelatedCartItem($eligibleProduct, $cartEvent->getCartItem()->getId()); $freeProductCartItem = $cartEvent->getCartItem(); } } if ($freeProductCartItem instanceof CartItem) { // The discount is the product price. $discount = $freeProductCartItem->getPromo() ? $freeProductCartItem->getPromoPrice() : $freeProductCartItem->getPrice(); } } else { // Remove all free products for this coupon, but no not remove the product from the cart. $this->clearFreeProductsCartItemIds(); } return $discount; }