custom/plugins/GoodaheadCart/src/Subscriber/BeforeLineItemAdded.php line 50

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace GoodaheadCart\Subscriber;
  3. use Shopware\Core\Checkout\Payment\Cart\Error\PaymentMethodBlockedError;
  4. use Shopware\Core\Checkout\Payment\PaymentMethodEntity;
  5. use Shopware\Core\Checkout\Promotion\Cart\PromotionItemBuilder;
  6. use Shopware\Core\Checkout\Promotion\Gateway\PromotionGateway;
  7. use Shopware\Core\Checkout\Promotion\Gateway\Template\PermittedGlobalCodePromotions;
  8. use Shopware\Core\Checkout\Promotion\Gateway\Template\PermittedIndividualCodePromotions;
  9. use Shopware\Core\Framework\DataAbstractionLayer\EntityCollection;
  10. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  11. use Shopware\Core\Framework\Validation\DataBag\DataBag;
  12. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  13. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  14. use Shopware\Core\Checkout\Cart\Event\BeforeLineItemAddedEvent;
  15. use Shopware\Core\Checkout\Promotion\PromotionCollection;
  16. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
  17. use Shopware\Core\System\SalesChannel\SalesChannel\SalesChannelContextSwitcher;
  18. use Shopware\Core\Framework\Context;
  19. class BeforeLineItemAdded implements EventSubscriberInterface
  20. {
  21.     protected PromotionGateway $gateway;
  22.     protected PromotionItemBuilder $itemBuilder;
  23.     protected EntityRepositoryInterface $ruleRepository;
  24.     protected SalesChannelContextSwitcher $salesChannelContextSwitcher;
  25.     public function __construct(
  26.         PromotionGateway $gateway,
  27.         PromotionItemBuilder $itemBuilder,
  28.         SalesChannelContextSwitcher $salesChannelContextSwitcher,
  29.         EntityRepositoryInterface $ruleRepository
  30.     ) {
  31.         $this->gateway $gateway;
  32.         $this->itemBuilder $itemBuilder;
  33.         $this->ruleRepository $ruleRepository;
  34.         $this->salesChannelContextSwitcher $salesChannelContextSwitcher;
  35.     }
  36.     public static function getSubscribedEvents(): array
  37.     {
  38.         // Return the events to listen to as array like this:  <event to listen to> => <method to execute>
  39.         return [
  40.             BeforeLineItemAddedEvent::class => 'onLineItemAdded',
  41.         ];
  42.     }
  43.     public function onLineItemAdded(BeforeLineItemAddedEvent $event)
  44.     {
  45.         // return $this;
  46.         $lineItem $event->getLineItem();
  47.         if ($lineItem->getType() != 'promotion') {
  48.             return $this;
  49.         }
  50.         $currentCode $lineItem->getReferencedId();
  51.         $foundPromotions $this->getMatchedPromotions($currentCode$event->getSalesChannelContext());
  52.         if (!\is_iterable($foundPromotions)) {
  53.             return $this;
  54.         }
  55.         foreach ($foundPromotions->getElements() as $promotion) {
  56.             if ($promotion->getCartRules() && \is_iterable($promotion->getCartRules()->getElements())) {
  57.                 foreach ($promotion->getCartRules()->getElements() as $rule) {
  58.                     $ruleCriteria = new Criteria([$rule->getId()]);
  59.                     $ruleCriteria->addAssociation('conditions');
  60.                     $loadedRule $this->ruleRepository->search($ruleCriteria$event->getSalesChannelContext()->getContext())->first();
  61.                     if ($loadedRule->getConditions() && \is_iterable($loadedRule->getConditions()->getElements())) {
  62.                         foreach ($loadedRule->getConditions()->getElements() as $element) {
  63.                             if ($element->getType() == 'paymentMethod' && \is_iterable($element->getValue())) {
  64.                                 foreach ($element->getValue() as $key => $value) {
  65.                                     if ($key == 'operator' && $value === '=') {
  66.                                         $paymentMethodIds = isset($element->getValue()['paymentMethodIds']) ? $element->getValue()['paymentMethodIds'] : [];
  67.                                         if (\is_iterable($paymentMethodIds)) {
  68.                                             foreach ($paymentMethodIds as $paymentMethodId) {
  69.                                                 $dataBag = new DataBag(['paymentMethodId' => $paymentMethodId]);
  70.                                                 try {
  71.                                                     $this->salesChannelContextSwitcher->update($dataBag$event->getSalesChannelContext());
  72.                                                     $this->cleanCartErrors($event->getCart());
  73.                                                     return $this;
  74.                                                 } catch (\Exception $e) {
  75.                                                     // TODO: add logging here
  76.                                                 }
  77.                                             }
  78.                                         }
  79.                                     }
  80.                                 }
  81.                             }
  82.                         }
  83.                     }
  84.                 }
  85.             }
  86.         }
  87.         return $this;
  88.     }
  89.     public function validatePromotions(\Shopware\Core\Checkout\Cart\Cart $cartSalesChannelContext $salesChannelContext)
  90.     {
  91.         foreach ($cart->getLineItems() as $lineItem) {
  92.             if ($lineItem->getType() != 'promotion') {
  93.                 continue;
  94.             }
  95.             $currentCode $lineItem->getReferencedId();
  96.             $foundPromotions $this->getMatchedPromotions($currentCode$salesChannelContext);
  97.             if (!\is_iterable($foundPromotions)) {
  98.                 return $this;
  99.             }
  100.             foreach ($foundPromotions->getElements() as $promotion) {
  101.                 if ($promotion->getCartRules() && \is_iterable($promotion->getCartRules()->getElements())) {
  102.                     foreach ($promotion->getCartRules()->getElements() as $rule) {
  103.                         $ruleCriteria = new Criteria([$rule->getId()]);
  104.                         $ruleCriteria->addAssociation('conditions');
  105.                         $loadedRule $this->ruleRepository->search($ruleCriteria$salesChannelContext->getContext())->first();
  106.                         if ($loadedRule->getConditions() && \is_iterable($loadedRule->getConditions()->getElements())) {
  107.                             foreach ($loadedRule->getConditions()->getElements() as $element) {
  108.                                 if ($element->getType() == 'paymentMethod' && \is_iterable($element->getValue())) {
  109.                                     foreach ($element->getValue() as $key => $value) {
  110.                                         if ($key == 'operator' && $value === '=') {
  111.                                             $paymentMethodIds = isset($element->getValue()['paymentMethodIds']) ? $element->getValue()['paymentMethodIds'] : [];
  112.                                             if (\is_iterable($paymentMethodIds)) {
  113.                                                 foreach ($paymentMethodIds as $paymentMethodId) {
  114.                                                     $dataBag = new DataBag(['paymentMethodId' => $paymentMethodId]);
  115.                                                     try {
  116.                                 $this->salesChannelContextSwitcher->update($dataBag$salesChannelContext);
  117.                                 $this->cleanCartErrors($cart);
  118.                                                         return $this;
  119.                                                     } catch (\Exception $e) {
  120.                                                         // TODO: add logging here
  121.                                                     }
  122.                                                 }
  123.                                             }
  124.                                         }
  125.                                     }
  126.                                 }
  127.                             }
  128.                         }
  129.                     }
  130.                 }
  131.             }
  132.         }
  133.         return $this;
  134.     }
  135.     protected function getMatchedPromotions($promoCode$salesChannelContext): EntityCollection
  136.     {
  137.         $foundPromotions $this->getGlobalCodePromotion($promoCode$salesChannelContext);
  138.         if (\count($foundPromotions->getElements()) <= 0) {
  139.             // no global code, so try with an individual code instead
  140.             $foundPromotions $this->getIndividualMatchedPromotions($promoCode$salesChannelContext);
  141.         }
  142.         return $foundPromotions;
  143.     }
  144.     protected function getGlobalCodePromotion($promoCode$salesChannelContext): EntityCollection
  145.     {
  146.         $globalCriteria = (new Criteria())->addFilter(
  147.             new PermittedGlobalCodePromotions([$promoCode], $salesChannelContext->getSalesChannelId())
  148.         );
  149.         foreach ($this->getPromoAssociations() as $association) {
  150.             $globalCriteria->addAssociation($association);
  151.         }
  152.         return $this->gateway->get($globalCriteria$salesChannelContext);
  153.     }
  154.     protected function getIndividualMatchedPromotions($promoCode$salesChannelContext): EntityCollection
  155.     {
  156.         $individualCriteria = (new Criteria())->addFilter(
  157.             new PermittedIndividualCodePromotions([$promoCode], $salesChannelContext->getSalesChannelId())
  158.         );
  159.         foreach ($this->getPromoAssociations() as $association) {
  160.             $individualCriteria->addAssociation($association);
  161.         }
  162.         /** @var PromotionCollection $foundPromotions */
  163.         return $this->gateway->get($individualCriteria$salesChannelContext);
  164.     }
  165.     private function getPromoAssociations(): array
  166.     {
  167.         return [
  168.             'personaRules',
  169.             'personaCustomers',
  170.             'cartRules',
  171.             'orderRules',
  172.             'discounts.discountRules',
  173.             'discounts.promotionDiscountPrices',
  174.             'setgroups',
  175.             'setgroups.setGroupRules',
  176.         ];
  177.     }
  178.     private function cleanCartErrors($cart)
  179.     {
  180.         foreach ($cart->getErrors()->getElements() as $key => $cartError) {
  181.             if ($cartError instanceof PaymentMethodBlockedError) {
  182.                 $cart->getErrors()->remove($key);
  183.             }
  184.         }
  185.     }
  186. }