custom/plugins/CheckoutPlugin/src/Storefront/Subscriber/CartSubscriber.php line 91

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Virgin\CheckoutPlugin\Storefront\Subscriber;
  3. use Shopware\Core\Checkout\Cart\Event\CartDeletedEvent;
  4. use Shopware\Core\Checkout\Cart\LineItem\LineItem;
  5. use Shopware\Core\Checkout\Cart\SalesChannel\CartService;
  6. use Shopware\Core\Checkout\Cart\Transaction\TransactionProcessor;
  7. use Shopware\Core\Checkout\Promotion\PromotionEntity;
  8. use Shopware\Core\Framework\Context;
  9. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
  10. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  11. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
  12. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\MultiFilter;
  13. use Shopware\Core\Framework\Rule\Exception\UnsupportedOperatorException;
  14. use Shopware\Core\Framework\Rule\Rule;
  15. use Shopware\Storefront\Page\Checkout\Confirm\CheckoutConfirmPageLoadedEvent;
  16. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  17. use Symfony\Component\HttpFoundation\Session\Session;
  18. use Virgin\CheckoutPlugin\Utils\Services\CartServiceCalculator;
  19. use Virgin\ProductModelExtension\Custom\ProductType\ProductTypeEntity;
  20. use Virgin\SubscriptionsConfigurator\Utils\Services\SubscriptionsConfiguratorService;
  21. class CartSubscriber implements EventSubscriberInterface
  22. {
  23. /**
  24. * @var TransactionProcessor
  25. */
  26. private $transactionProcessor;
  27. /**
  28. * @var CartServiceCalculator
  29. */
  30. private $cartServiceCalculator;
  31. /** @var EntityRepositoryInterface */
  32. private $promotionRepository;
  33. /** @var EntityRepositoryInterface */
  34. private $ruleConditionRepository;
  35. /** @var CartService */
  36. private $cartService;
  37. /**
  38. * @var Session
  39. */
  40. private $session;
  41. /**
  42. * @param TransactionProcessor $transactionProcessor
  43. * @param CartServiceCalculator $cartServiceCalculator
  44. * @param EntityRepositoryInterface $promotionRepository
  45. * @param EntityRepositoryInterface $ruleConditionRepository
  46. * @param CartService $cartService
  47. * @param Session $session
  48. */
  49. public function __construct(
  50. TransactionProcessor $transactionProcessor,
  51. CartServiceCalculator $cartServiceCalculator,
  52. EntityRepositoryInterface $promotionRepository,
  53. EntityRepositoryInterface $ruleConditionRepository,
  54. CartService $cartService,
  55. Session $session
  56. ) {
  57. $this->transactionProcessor = $transactionProcessor;
  58. $this->cartServiceCalculator = $cartServiceCalculator;
  59. $this->promotionRepository = $promotionRepository;
  60. $this->ruleConditionRepository = $ruleConditionRepository;
  61. $this->cartService = $cartService;
  62. $this->session = $session;
  63. }
  64. public static function getSubscribedEvents(): array
  65. {
  66. return [
  67. CheckoutConfirmPageLoadedEvent::class => 'addCartInfo',
  68. CartDeletedEvent::class => 'deleteCart'
  69. ];
  70. }
  71. public function deleteCart(CartDeletedEvent $event): void
  72. {
  73. $this->session->remove("promotionCode");
  74. $this->session->remove("fullpriceTotalAmount");
  75. unset($_SESSION['super_promo_user']);
  76. unset($_SESSION['super_promo_flow']);
  77. }
  78. public function addCartInfo(CheckoutConfirmPageLoadedEvent $event): void
  79. {
  80. if ($event->getSalesChannelContext()->getCustomer() || isset($_SESSION['isDirectFlow'])) {
  81. $cart = $event->getPage()->getCart();
  82. $lineItems = $cart->getLineItems();
  83. // The line above may not be true with new promotions and flows in future
  84. // Check if line item has a special flow promo like Black Days promo, if so do not remove promotions and discounts
  85. $isSpecialPromoFlow = false;
  86. /** @var LineItem $lineItem */
  87. foreach ($lineItems as $lineItem){
  88. if (!is_null($lineItem->getPayloadValue('main'))) {
  89. $productType = $lineItem->getPayloadValue('product_type');
  90. }
  91. if ($lineItem->getPayloadValue('isSpecialPromoFlow') === true) {
  92. $isSpecialPromoFlow = true;
  93. }
  94. }
  95. if (isset($productType) && $productType == ProductTypeEntity::SUBSCRIPTION) {
  96. $isGift = isset($_SESSION['gift_user_params']);
  97. $customer = $event->getSalesChannelContext()->getCustomer();
  98. if (!$isSpecialPromoFlow && is_null($customer)) {
  99. /** @var LineItem $lineItem */
  100. foreach ($lineItems as $lineItem) {
  101. if ($lineItem->getType() == 'promotion') {
  102. if (($lineItem->getPayloadValue('code') == '' || $lineItem->getPayloadValue('exerpPromotion'))) {
  103. $lineItems->remove($lineItem->getId());
  104. }
  105. }
  106. }
  107. } else {
  108. if ($isGift && strpos(strtolower($event->getSalesChannelContext()->getCurrentCustomerGroup()->getName()), strtolower(SubscriptionsConfiguratorService::BOCCONI_STRING)) !== false) {
  109. /** @var LineItem $lineItem */
  110. foreach ($lineItems as $lineItem) {
  111. if ($lineItem->getType() == 'promotion') {
  112. $promotionId = $lineItem->getPayloadValue('promotionId');
  113. $criteria = new Criteria();
  114. $criteria->addFilter(new EqualsFilter('id', $promotionId));
  115. $criteria->addAssociation('personaRules');
  116. /** @var PromotionEntity $promotionEntity */
  117. $promotionEntity = $this->promotionRepository
  118. ->search($criteria, Context::createDefaultContext())
  119. ->first();
  120. $personaRules = $promotionEntity->getPersonaRules();
  121. if (null !== $personaRules) {
  122. foreach ($personaRules as $personaRule) {
  123. $criteria = new Criteria();
  124. $criteria->addFilter(new MultiFilter(
  125. MultiFilter::CONNECTION_AND,
  126. [
  127. new EqualsFilter('rule_condition.type', 'customerCustomerGroup'),
  128. new EqualsFilter('rule_condition.ruleId', $personaRule->getId()),
  129. ]
  130. ));
  131. $condition = $this->ruleConditionRepository
  132. ->search($criteria, Context::createDefaultContext())
  133. ->first();
  134. if ($condition) {
  135. $customerGroupHasPromo = $this->match($condition->getValue()['operator'],
  136. $condition->getValue()['customerGroupIds'],
  137. [$_SESSION['gift_user_params']['customerGroupId']]);
  138. if (!$customerGroupHasPromo) {
  139. $this->cartService->remove($cart, $lineItem->getId(), $event->getSalesChannelContext());
  140. }
  141. }
  142. }
  143. }
  144. }
  145. }
  146. }
  147. }
  148. }
  149. $cart->setLineItems($this->cartServiceCalculator->setExerpPrice($lineItems, $event->getSalesChannelContext()));
  150. $amount= $this->cartServiceCalculator->reCalculateCartAmount($event->getSalesChannelContext(), $cart, $isSpecialPromoFlow);
  151. $cart->setPrice($amount);
  152. $cart->setTransactions(
  153. $this->transactionProcessor->process($cart, $event->getSalesChannelContext())
  154. );
  155. $event->getPage()->setCart($cart);
  156. }
  157. }
  158. /**
  159. * @param $operator
  160. * @param $identifiers
  161. * @param $target
  162. * @return bool
  163. */
  164. private function match($operator, $identifiers, $target)
  165. {
  166. switch ($operator) {
  167. case Rule::OPERATOR_EQ:
  168. return !empty(array_intersect($identifiers, $target));
  169. case Rule::OPERATOR_NEQ:
  170. return empty(array_intersect($identifiers, $target));
  171. default:
  172. throw new UnsupportedOperatorException($operator, Rule::class);
  173. }
  174. }
  175. }