custom/plugins/SwpProductOptionsSix/src/Subscriber/MailTemplate/OrderMailSubscriber.php line 61

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. /**
  3.  * Shopware
  4.  * Copyright © 2021
  5.  *
  6.  * @category   Shopware
  7.  * @package    SwpProductOptionsSix
  8.  * @subpackage OrderMailSubscriber.php
  9.  *
  10.  * @copyright  2021 Iguana-Labs GmbH
  11.  * @author     Module Factory <info at module-factory.com>
  12.  * @license    https://www.module-factory.com/eula
  13.  */
  14. namespace Swp\ProductOptionsSix\Subscriber\MailTemplate;
  15. use Shopware\Core\Checkout\Cart\LineItem\LineItem;
  16. use Shopware\Core\Checkout\Order\Aggregate\OrderLineItem\OrderLineItemCollection;
  17. use Shopware\Core\Checkout\Order\Aggregate\OrderLineItem\OrderLineItemEntity;
  18. use Shopware\Core\Checkout\Order\OrderEntity;
  19. use Shopware\Core\Content\MailTemplate\MailTemplateTypes;
  20. use Shopware\Core\Content\MailTemplate\Service\Event\MailBeforeValidateEvent;
  21. use Shopware\Core\Framework\Context;
  22. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
  23. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  24. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsAnyFilter;
  25. use Shopware\Core\System\SystemConfig\SystemConfigService;
  26. use Swp\ProductOptionsSix\Core\Checkout\ProductOptions\Cart\ProductOptionsCartDataCollector;
  27. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  28. class OrderMailSubscriber implements EventSubscriberInterface
  29. {
  30.     /** @var EntityRepository */
  31.     private $mailTemplateRepository;
  32.     /** @var SystemConfigService */
  33.     private $systemConfigService;
  34.     /**
  35.      * @param EntityRepository $mailTemplateRepository
  36.      * @param SystemConfigService $systemConfigService
  37.      */
  38.     public function __construct(
  39.         EntityRepository $mailTemplateRepository,
  40.         SystemConfigService $systemConfigService
  41.     ) {
  42.         $this->mailTemplateRepository $mailTemplateRepository;
  43.         $this->systemConfigService $systemConfigService;
  44.     }
  45.     public static function getSubscribedEvents(): array
  46.     {
  47.         return [
  48.             MailBeforeValidateEvent::class => 'prepareOrderMailTemplate'
  49.         ];
  50.     }
  51.     /**
  52.      * @param MailBeforeValidateEvent $event
  53.      */
  54.     public function prepareOrderMailTemplate(MailBeforeValidateEvent $event): void
  55.     {
  56.         $mailData $event->getData();
  57.         if (!\array_key_exists('templateId'$mailData)) {
  58.             return;
  59.         }
  60.         if ($mailData['templateId'] !== $this->getOrderConfirmationMailTemplateId($event->getContext())) {
  61.             return;
  62.         }
  63.         $order $event->getTemplateData()['order'];
  64.         if ($order === null || !$order instanceof OrderEntity) {
  65.             return;
  66.         }
  67.         if ($this->isCannelActive($order->getSalesChannelId()) !== true) {
  68.             return;
  69.         }
  70.         $orderLineItemCollection $order->getLineItems();
  71.         if ($orderLineItemCollection === null) {
  72.             return;
  73.         }
  74.         $orderLineItemCollection->sortByPosition();
  75.         $productWithOptionsLineItems $orderLineItemCollection->filterByType(
  76.             ProductOptionsCartDataCollector::PRODUCT_OPTIONS_LINE_ITEM_TYPE
  77.         );
  78.         foreach ($productWithOptionsLineItems as $productWithOptionsLineItem) {
  79.             $childLineItems $orderLineItemCollection->filterByProperty('parentId'$productWithOptionsLineItem->getId());
  80.             $this->setChildrenLabelAndValues($childLineItems$orderLineItemCollection);
  81.             $productWithOptionsLineItem->setChildren($childLineItems);
  82.         }
  83.         $orderLineItemCollection $orderLineItemCollection->filter(static function (OrderLineItemEntity $lineItem) {
  84.             return $lineItem->getType() !== ProductOptionsCartDataCollector::PRODUCT_OPTIONS_OPTION_LINE_ITEM_TYPE
  85.                 && $lineItem->getType() !== ProductOptionsCartDataCollector::PRODUCT_OPTIONS_OPTION_LINE_ITEM_TYPE_PRODUCT;
  86.         });
  87.         $orderLineItemCollection->sortByPosition();
  88.         $order->setLineItems($this->flattenOrderLineItemCollection($orderLineItemCollection));
  89.     }
  90.     /**
  91.      * @param Context $context
  92.      * @return string|null
  93.      */
  94.     private function getOrderConfirmationMailTemplateId(Context $context): ?string
  95.     {
  96.         $criteria = new Criteria();
  97.         $criteria->addFilter(
  98.             new EqualsAnyFilter('mailTemplateType.technicalName', [
  99.                 MailTemplateTypes::MAILTYPE_ORDER_CONFIRM,
  100.                 MailTemplateTypes::MAILTYPE_STATE_ENTER_ORDER_TRANSACTION_STATE_PAID,
  101.                 MailTemplateTypes::MAILTYPE_STATE_ENTER_ORDER_TRANSACTION_STATE_CANCELLED,
  102.             ])
  103.         );
  104.         return $this->mailTemplateRepository->searchIds($criteria$context)->firstId();
  105.     }
  106.     /**
  107.      * @param OrderLineItemCollection $optionsLineItems,
  108.      * @param OrderLineItemCollection $orderLineItemCollection
  109.      */
  110.     private function setChildrenLabelAndValues(
  111.         OrderLineItemCollection $optionsLineItems,
  112.         OrderLineItemCollection $orderLineItemCollection
  113.     ): void {
  114.         foreach ($optionsLineItems as $optionsLineItem) {
  115.             $payload $optionsLineItem->getPayload();
  116.             $this->setLabels($optionsLineItem$payload);
  117.             unset($payload['productNumber']);
  118.             $optionsLineItem->setPayload($payload);
  119.             /** @var OrderLineItemCollection $childLineItems */
  120.             $childLineItems $orderLineItemCollection->filterByProperty('parentId'$optionsLineItem->getId());
  121.             if ($childLineItems->count() > 0) {
  122.                 foreach ($childLineItems as $childLineItem) {
  123.                     $payload $childLineItem->getPayload();
  124.                     if ($childLineItem->getType() === ProductOptionsCartDataCollector::PRODUCT_OPTIONS_OPTION_LINE_ITEM_TYPE_PRODUCT) {
  125.                         $childLineItem->setLabel(\sprintf('* * %s (%s)'$childLineItem->getLabel(), $payload['productNumber']));
  126.                         $childLineItem->setQuantity($optionsLineItem->getQuantity() * $childLineItem->getQuantity());
  127.                     }
  128.                     unset($payload['productNumber']);
  129.                     $childLineItem->setPayload($payload);
  130.                 }
  131.                 $optionsLineItem->setChildren($childLineItems);
  132.                 continue;
  133.             }
  134.             if ($value $this->extractPayload($optionsLineItem)) {
  135.                 $optionsLineItem->setLabel(\sprintf('%s (%s)'$optionsLineItem->getLabel(), $value));
  136.             }
  137.         }
  138.     }
  139.     /**
  140.      * @param OrderLineItemEntity $optionsLineItem
  141.      * @param array $payload
  142.      * @return void
  143.      */
  144.     private function setLabels(
  145.         OrderLineItemEntity $optionsLineItem,
  146.         array $payload
  147.     ): void {
  148.         if ($optionsLineItem->getType() === LineItem::PRODUCT_LINE_ITEM_TYPE) {
  149.             $optionsLineItem->setLabel(\sprintf('* %s (%s)'$optionsLineItem->getLabel(), $payload['productNumber']));
  150.         }
  151.         if ($optionsLineItem->getType() === ProductOptionsCartDataCollector::PRODUCT_OPTIONS_OPTION_LINE_ITEM_TYPE) {
  152.             $group \array_key_exists('group'$payload) ? $payload['group'] : '';
  153.             $optionsLineItem->setLabel(\sprintf('* %s: %s'$group$optionsLineItem->getLabel()));
  154.         }
  155.     }
  156.     /**
  157.      * @param OrderLineItemEntity $optionsLineItem
  158.      * @return string|null
  159.      */
  160.     private function extractPayload(OrderLineItemEntity $optionsLineItem): ?string
  161.     {
  162.         $payload $optionsLineItem->getPayload() ?? [];
  163.         $type $payload['type'] ?? null;
  164.         switch($type) {
  165.             case 'textfield':
  166.             case 'textarea':
  167.                 $value $payload['optionText'];
  168.                 break;
  169.             default:
  170.                 $value null;
  171.         }
  172.         return $value;
  173.     }
  174.     /**
  175.      * @param OrderLineItemCollection $orderLineItemCollection
  176.      * @return OrderLineItemCollection
  177.      */
  178.     private function flattenOrderLineItemCollection(OrderLineItemCollection $orderLineItemCollection): OrderLineItemCollection
  179.     {
  180.         $newOrderLineItemCollection = new OrderLineItemCollection();
  181.         foreach ($orderLineItemCollection->getElements() as $item) {
  182.             $newOrderLineItemCollection->add($item);
  183.             $children $item->getChildren();
  184.             if ($children !== null) {
  185.                 $newOrderLineItemCollection->merge($this->flattenOrderLineItemCollection($children));
  186.                 $item->setChildren(new OrderLineItemCollection());
  187.             }
  188.         }
  189.         return $newOrderLineItemCollection;
  190.     }
  191.     /**
  192.      * @param string $salesChannelId
  193.      * @return array|mixed|null
  194.      */
  195.     private function isCannelActive(string $salesChannelId)
  196.     {
  197.         return $this->systemConfigService->get(
  198.             'SwpProductOptionsSix.config.channelActive',
  199.             $salesChannelId
  200.         );
  201.     }
  202. }