custom/plugins/EsmConfigurator/src/Storefront/Subscriber/CheckoutSubscriber.php line 119

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace EsmConfigurator\Storefront\Subscriber;
  3. use EsmConfigurator\Core\Content\ConfigurationItem\ConfigurationItemEntity;
  4. use Shopware\Core\Checkout\Cart\Event\BeforeLineItemAddedEvent;
  5. use Shopware\Core\Checkout\Cart\Event\CheckoutOrderPlacedEvent;
  6. use Shopware\Core\Checkout\Cart\LineItem\LineItem;
  7. use Shopware\Core\Checkout\Cart\LineItem\LineItemCollection;
  8. use Shopware\Core\Checkout\Cart\Price\QuantityPriceCalculator;
  9. use Shopware\Core\Checkout\Cart\Price\Struct\QuantityPriceDefinition;
  10. use Shopware\Core\Checkout\Order\Aggregate\OrderLineItem\OrderLineItemCollection;
  11. use Shopware\Core\Checkout\Order\Aggregate\OrderLineItem\OrderLineItemEntity;
  12. use Shopware\Core\Content\Product\ProductEntity;
  13. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
  14. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  15. use Shopware\Core\System\SalesChannel\Entity\SalesChannelRepositoryInterface;
  16. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  17. use Shopware\Storefront\Controller\StorefrontController;
  18. use Shopware\Storefront\Page\Checkout\Cart\CheckoutCartPageLoadedEvent;
  19. use Shopware\Storefront\Page\Checkout\Confirm\CheckoutConfirmPageLoadedEvent;
  20. use Shopware\Storefront\Page\Checkout\Finish\CheckoutFinishPageLoadedEvent;
  21. use Shopware\Storefront\Page\Checkout\Offcanvas\OffcanvasCartPageLoadedEvent;
  22. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  23. use Symfony\Component\HttpFoundation\Session\Session;
  24. use Symfony\Contracts\Translation\TranslatorInterface;
  25. use Throwable;
  26. use function array_column;
  27. use function array_key_exists;
  28. use function array_shift;
  29. use function count;
  30. use function implode;
  31. use function in_array;
  32. class CheckoutSubscriber implements EventSubscriberInterface
  33. {
  34.     protected QuantityPriceCalculator $quantityPriceCalculator;
  35.     protected Session $session;
  36.     protected TranslatorInterface $translator;
  37.     protected EntityRepository $orderRepository;
  38.     protected EntityRepository $configurationItemRepository;
  39.     protected SalesChannelRepositoryInterface $salesChannelProductRepository;
  40.     public function __construct(
  41.         QuantityPriceCalculator $quantityPriceCalculator,
  42.         Session $session,
  43.         TranslatorInterface $translator,
  44.         EntityRepository $orderRepository,
  45.         EntityRepository $configurationItemRepository,
  46.         SalesChannelRepositoryInterface $salesChannelProductRepository
  47.     )
  48.     {
  49.         $this->quantityPriceCalculator $quantityPriceCalculator;
  50.         $this->session $session;
  51.         $this->translator $translator;
  52.         $this->orderRepository $orderRepository;
  53.         $this->configurationItemRepository $configurationItemRepository;
  54.         $this->salesChannelProductRepository $salesChannelProductRepository;
  55.     }
  56.     public static function getSubscribedEvents(): array
  57.     {
  58.         return [
  59.             OffcanvasCartPageLoadedEvent::class => 'onOffcanvasCartPageLoadedEvent',
  60.             CheckoutCartPageLoadedEvent::class => 'onCheckoutCartPageLoadedEvent',
  61.             CheckoutConfirmPageLoadedEvent::class => 'onCheckoutConfirmPageLoadedEvent',
  62.             CheckoutFinishPageLoadedEvent::class => 'onCheckoutFinishPageLoadedEvent',
  63.             BeforeLineItemAddedEvent::class => 'onBeforeLineItemAddedEvent',
  64.             CheckoutOrderPlacedEvent::class => 'onCheckoutOrderPlacedEvent'
  65.         ];
  66.     }
  67.     public function onCheckoutOrderPlacedEvent(CheckoutOrderPlacedEvent $event)
  68.     {
  69.         try {
  70.             $lineItems $event->getOrder()->getLineItems();
  71.             $comment '';
  72.             /** @var OrderLineItemEntity $lineItem */
  73.             foreach ($lineItems as $lineItem) {
  74.                 if (array_key_exists('children'$lineItem->getPayload())) {
  75.                     $childIds $lineItem->getPayload()['children'];
  76.                     $comment .= 'Konfiguration für ' $lineItem->getPayload()['productNumber'] . ' => ';
  77.                     foreach ($childIds as $childId) {
  78.                         $child $lineItems->filterByProperty('productId'$childId)->first();
  79.                         if (!$child) {
  80.                             continue;
  81.                         }
  82.                         $comment .= $child->getPayload()['productNumber'] . ' (' $lineItem->getQuantity() . 'x - ' $child->getPayload()['configurationGroupTitle'] . ') ';
  83.                     }
  84.                 }
  85.             }
  86.             // The customer comment is saved by default, we only need to intervene, if there is an upgrade comment
  87.             if($comment) {
  88.                 // Add our internal upgrade comment
  89.                 $mergedComment = [$comment];
  90.                 // Add customer comment, if it exists
  91.                 if($customerComment $event->getOrder()->getCustomerComment()) {
  92.                     $mergedComment[] = $customerComment;
  93.                 }
  94.                 $this->orderRepository->update([
  95.                     [
  96.                         'id' => $event->getOrder()->getId(),
  97.                         'customerComment' => implode('  |  '$mergedComment)
  98.                     ]
  99.                 ], $event->getContext());
  100.             }
  101.         }catch (Throwable $e) {
  102.             error_log($e->getMessage());
  103.         }
  104.     }
  105.     public function onBeforeLineItemAddedEvent(BeforeLineItemAddedEvent $event): void
  106.     {
  107.         try {
  108.             // If "upgrade" is already present (upgrade could be a standalone docking station)
  109.             if(array_key_exists('lineItems'$_POST) && count($_POST['lineItems']) === && in_array('upgrade'array_column($_POST['lineItems'], 'type'), true)) {
  110.                 $parentProduct array_shift($_POST['lineItems']);
  111.                 $upgrade array_shift($_POST['lineItems']);
  112.                 $criteria = new Criteria([$upgrade['id']]);
  113.                 $criteria->addAssociation('product');
  114.                 /** @var ConfigurationItemEntity $configurationItem */
  115.                 $configurationItem $this->configurationItemRepository->search($criteria$event->getContext())->first();
  116.                 if(!$configurationItem || !$configurationItem->getProduct()) {
  117.                     return;
  118.                 }
  119.                 $productId $configurationItem->getProduct()->getId();
  120.                 foreach ($event->getCart()->getLineItems() as $cartLineItem) {
  121.                     if ($cartLineItem->getId() === $productId && !$cartLineItem->getPayloadValue('configurationItemId')) {
  122.                         $this->session->getFlashBag()->add(StorefrontController::DANGER$this->translator->trans('checkout.upgrade_already_basket_article'));
  123.                         $parentLineItem $event->getCart()->getLineItems()->get($parentProduct['id']);
  124.                         if($parentLineItem) {
  125.                             $event->getCart()->remove($parentProduct['id']);
  126.                         }
  127.                     }
  128.                 }
  129.             }
  130.             // If article with upgrade is already present
  131.             $lineItem $event->getCart()->getLineItems()->get($event->getLineItem()->getId());
  132.             if(!$lineItem) {
  133.                 return;
  134.             }
  135.             if($event->isMerged() && $lineItem->getPayloadValue('parentLineItems')) {
  136.                 $this->session->getFlashBag()->add(StorefrontController::DANGER$this->translator->trans('checkout.article_exists_as_upgrade'));
  137.             }
  138.         } catch (Throwable $e) {
  139.             mail('dev@sicor-kdl.net''Fehler im Warenkorb: ' $e->getLine(), $e->getMessage());
  140.         }
  141.     }
  142.     public function onOffcanvasCartPageLoadedEvent(OffcanvasCartPageLoadedEvent $event): void
  143.     {
  144.         $this->onCheckoutAction($event);
  145.     }
  146.     public function onCheckoutCartPageLoadedEvent(CheckoutCartPageLoadedEvent $event): void
  147.     {
  148.         $this->onCheckoutAction($event);
  149.     }
  150.     public function onCheckoutConfirmPageLoadedEvent(CheckoutConfirmPageLoadedEvent $event): void
  151.     {
  152.         $this->onCheckoutAction($event);
  153.     }
  154.     public function onCheckoutFinishPageLoadedEvent(CheckoutFinishPageLoadedEvent $event): void
  155.     {
  156.         $lineItems $event->getPage()->getOrder()->getLineItems();
  157.         if($lineItems) {
  158.             $event->getPage()->getOrder()->addExtension('lineItems'$this->addOrderLineItemChildrenToParent($lineItems$event->getSalesChannelContext()));
  159.         }
  160.     }
  161.     protected function onCheckoutAction($event): void
  162.     {
  163.         $lineItems $event->getPage()->getCart()->getLineItems();
  164.         if($this->session->getFlashBag()->peek('danger')) {
  165.             $this->session->getFlashBag()->get('success');
  166.         }
  167.         $originalLineItems = clone $lineItems;
  168.         /** @var LineItemCollection $originalLineItems */
  169.         foreach($originalLineItems as $originalLineItem) {
  170.             /** @var ProductEntity $product */
  171.             $product $this->salesChannelProductRepository->search(new Criteria([$originalLineItem->getId()]), $event->getSalesChannelContext())->first();
  172.             if($product) {
  173.                 $originalLineItem->setPayload(['productNumber' => $product->getProductNumber()]);
  174.             }
  175.         }
  176.         $event->getPage()->addExtension('originalLineItems'$originalLineItems);
  177.         $event->getPage()->getCart()->setLineItems($this->addLineItemChildrenToParent($lineItems$event->getSalesChannelContext()));
  178.     }
  179.     private function addLineItemChildrenToParent(LineItemCollection $lineItemsSalesChannelContext $context): LineItemCollection
  180.     {
  181.         /** @var LineItem $lineItem */
  182.         foreach($lineItems as $lineItem) {
  183.             if($lineItem->getPayloadValue('parentLineItems')) {
  184.                 foreach ($lineItem->getPayloadValue('parentLineItems') as $parentLineItemId) {
  185.                     $parentLineItem $lineItems->get($parentLineItemId);
  186.                     if(!$parentLineItem) {
  187.                         continue;
  188.                     }
  189.                     /** @var LineItem $parentLineItem */
  190.                     if (array_key_exists('productPrice'$lineItem->getPayload())) {
  191.                         $newUpgradeLineItem = clone $lineItem;
  192.                         $priceDefinition = new QuantityPriceDefinition($lineItem->getPayloadValue('productPrice'), $context->buildTaxRules($lineItem->getPayloadValue('productTaxId')), $parentLineItem->getQuantity());
  193.                         $newUpgradeLineItem->setQuantity($parentLineItem->getQuantity());
  194.                         $newUpgradeLineItem->setPriceDefinition($priceDefinition);
  195.                         $newUpgradeLineItem->setPrice($this->quantityPriceCalculator->calculate($priceDefinition$context));
  196.                         $parentLineItem->getChildren()->add($newUpgradeLineItem);
  197.                         if($lineItem->getQuantity() - $parentLineItem->getQuantity() <= 0) {
  198.                             $lineItems->removeElement($lineItem);
  199.                         }else {
  200.                             $lineItem->setQuantity($lineItem->getQuantity() - $parentLineItem->getQuantity());
  201.                         }
  202.                     }
  203.                 }
  204.             }
  205.         }
  206.         return $lineItems;
  207.     }
  208.     private function addOrderLineItemChildrenToParent(OrderLineItemCollection $lineItemsSalesChannelContext $context): OrderLineItemCollection
  209.     {
  210.         foreach($lineItems as $key => $lineItem) {
  211.             if (array_key_exists('parentLineItems'$lineItem->getPayload())) {
  212.                 foreach ($lineItem->getPayload()['parentLineItems'] as $parentLineItemId) {
  213.                     $parentLineItem $lineItems->filterByProperty('productId'$parentLineItemId)->first();
  214.                     if(!$parentLineItem) {
  215.                         continue;
  216.                     }
  217.                     /** @var OrderLineItemEntity $parentLineItem */
  218.                     if (array_key_exists('productPrice'$lineItem->getPayload())) {
  219.                         $newUpgradeLineItem = clone $lineItem;
  220.                         $priceDefinition = new QuantityPriceDefinition($lineItem->getPayload()['productPrice'], $context->buildTaxRules($lineItem->getPayload()['productTaxId']), $parentLineItem->getQuantity());
  221.                         $newUpgradeLineItem->setQuantity($parentLineItem->getQuantity());
  222.                         $newUpgradeLineItem->setPriceDefinition($priceDefinition);
  223.                         $newUpgradeLineItem->setPrice($this->quantityPriceCalculator->calculate($priceDefinition$context));
  224.                         if (!$parentLineItem->getExtension('children') instanceof OrderLineItemCollection) {
  225.                             $parentLineItem->addExtension('children', new OrderLineItemCollection([]));
  226.                         }
  227.                         // Dirty workaround, because $parentLineItem->setChildren() doesn't change items (always empty) -> used in finish.html.twig
  228.                         $parentLineItem->getExtension('children')->add($newUpgradeLineItem);
  229.                         if ($lineItem->getQuantity() - $parentLineItem->getQuantity() <= 0) {
  230.                             $lineItems->remove($key);
  231.                         } else {
  232.                             $lineItem->setQuantity($lineItem->getQuantity() - $parentLineItem->getQuantity());
  233.                         }
  234.                     }
  235.                 }
  236.             }
  237.         }
  238.         return $lineItems;
  239.     }
  240. }