custom/plugins/SwagCustomizedProducts/src/Core/Content/MailTemplate/Service/Event/OrderConfirmationSubscriber.php line 40

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. /*
  3.  * (c) shopware AG <info@shopware.com>
  4.  * For the full copyright and license information, please view the LICENSE
  5.  * file that was distributed with this source code.
  6.  */
  7. namespace Swag\CustomizedProducts\Core\Content\MailTemplate\Service\Event;
  8. use Shopware\Core\Checkout\Cart\LineItem\LineItem;
  9. use Shopware\Core\Checkout\Cart\Price\Struct\PercentagePriceDefinition;
  10. use Shopware\Core\Checkout\Order\Aggregate\OrderLineItem\OrderLineItemCollection;
  11. use Shopware\Core\Checkout\Order\Aggregate\OrderLineItem\OrderLineItemEntity;
  12. use Shopware\Core\Checkout\Order\OrderEntity;
  13. use Shopware\Core\Content\MailTemplate\MailTemplateTypes;
  14. use Shopware\Core\Content\MailTemplate\Service\Event\MailBeforeValidateEvent;
  15. use Shopware\Core\Framework\Context;
  16. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
  17. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  18. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsAnyFilter;
  19. use Swag\CustomizedProducts\Core\Checkout\CustomizedProductsCartDataCollector;
  20. use Swag\CustomizedProducts\Template\Aggregate\TemplateOption\Type\Checkbox;
  21. use Swag\CustomizedProducts\Template\Aggregate\TemplateOption\Type\DateTime;
  22. use Swag\CustomizedProducts\Template\Aggregate\TemplateOption\Type\FileUpload;
  23. use Swag\CustomizedProducts\Template\Aggregate\TemplateOption\Type\ImageUpload;
  24. use Swag\CustomizedProducts\Template\Aggregate\TemplateOption\Type\Timestamp;
  25. class OrderConfirmationSubscriber
  26. {
  27.     /**
  28.      * @var EntityRepositoryInterface
  29.      */
  30.     private $mailTemplateRepository;
  31.     public function __construct(EntityRepositoryInterface $mailTemplateRepository)
  32.     {
  33.         $this->mailTemplateRepository $mailTemplateRepository;
  34.     }
  35.     public function __invoke(MailBeforeValidateEvent $event): void
  36.     {
  37.         $data $event->getData();
  38.         if (!\array_key_exists('templateId'$data)) {
  39.             return;
  40.         }
  41.         if (!$this->isRelevantMailTemplate($data['templateId'], $event->getContext())) {
  42.             return;
  43.         }
  44.         $order $event->getTemplateData()['order'];
  45.         if ($order === null || !$order instanceof OrderEntity) {
  46.             return;
  47.         }
  48.         $orderLineItemCollection $order->getLineItems();
  49.         if ($orderLineItemCollection === null) {
  50.             return;
  51.         }
  52.         $orderLineItemCollection->sortByPosition();
  53.         $customizedProductOptionValueLineItems $orderLineItemCollection->filterByType(
  54.             CustomizedProductsCartDataCollector::CUSTOMIZED_PRODUCTS_OPTION_VALUE_LINE_ITEM_TYPE
  55.         );
  56.         $this->adjustQuantityAndRemoveProductNumber($customizedProductOptionValueLineItems);
  57.         $templateLineItems $orderLineItemCollection->filterByType(
  58.             CustomizedProductsCartDataCollector::CUSTOMIZED_PRODUCTS_TEMPLATE_LINE_ITEM_TYPE
  59.         );
  60.         foreach ($templateLineItems as $templateLineItem) {
  61.             $childLineItems $orderLineItemCollection->filterByProperty('parentId'$templateLineItem->getId());
  62.             $productLineItems $childLineItems->filterByType(LineItem::PRODUCT_LINE_ITEM_TYPE);
  63.             $customizedProductOptionLineItems $childLineItems->filterByType(
  64.                 CustomizedProductsCartDataCollector::CUSTOMIZED_PRODUCTS_OPTION_LINE_ITEM_TYPE
  65.             );
  66.             $this->adjustQuantityAndRemoveProductNumber($customizedProductOptionLineItems);
  67.             $this->addCustomerValueToChildLabel($customizedProductOptionLineItems$customizedProductOptionValueLineItems);
  68.             foreach ($productLineItems as $productLineItem) {
  69.                 $productLineItem->assign(['parentId' => null]);
  70.                 foreach ($customizedProductOptionLineItems as $child) {
  71.                     $child->setParentId($productLineItem->getId());
  72.                 }
  73.                 $productLineItem->setChildren($customizedProductOptionLineItems);
  74.                 $productLineItem->setPosition($templateLineItem->getPosition());
  75.             }
  76.         }
  77.         // removes all customized products entries except the product
  78.         $orderLineItemCollection $orderLineItemCollection->filter(static function (OrderLineItemEntity $lineItem) {
  79.             return $lineItem->getType() !== CustomizedProductsCartDataCollector::CUSTOMIZED_PRODUCTS_TEMPLATE_LINE_ITEM_TYPE
  80.                 && $lineItem->getType() !== CustomizedProductsCartDataCollector::CUSTOMIZED_PRODUCTS_OPTION_VALUE_LINE_ITEM_TYPE
  81.                 && $lineItem->getType() !== CustomizedProductsCartDataCollector::CUSTOMIZED_PRODUCTS_OPTION_LINE_ITEM_TYPE;
  82.         });
  83.         $orderLineItemCollection->sortByPosition();
  84.         // reinsert options after its parent product
  85.         $order->setLineItems($this->flattenOrderLineItemCollection($orderLineItemCollection));
  86.     }
  87.     private function isRelevantMailTemplate(string $templateIdContext $context): bool
  88.     {
  89.         $criteria = new Criteria([$templateId]);
  90.         $criteria->addFilter(
  91.             new EqualsAnyFilter('mailTemplateType.technicalName', [
  92.                 MailTemplateTypes::MAILTYPE_ORDER_CONFIRM,
  93.                 MailTemplateTypes::MAILTYPE_STATE_ENTER_ORDER_TRANSACTION_STATE_PAID,
  94.                 MailTemplateTypes::MAILTYPE_STATE_ENTER_ORDER_TRANSACTION_STATE_CANCELLED,
  95.             ])
  96.         );
  97.         return $this->mailTemplateRepository->searchIds($criteria$context)->firstId() !== null;
  98.     }
  99.     private function adjustQuantityAndRemoveProductNumber(
  100.         OrderLineItemCollection $orderLineItemCollection
  101.     ): void {
  102.         foreach ($orderLineItemCollection as $lineItem) {
  103.             $payload $lineItem->getPayload();
  104.             $isOneTimeSurcharge \is_array($payload) && isset($payload['isOneTimeSurcharge']) && $payload['isOneTimeSurcharge'] === true;
  105.             if ($lineItem->getPriceDefinition() instanceof PercentagePriceDefinition || $isOneTimeSurcharge) {
  106.                 $lineItem->setQuantity(1);
  107.             }
  108.             if (isset($payload['productNumber']) && $payload['productNumber'] === '*') {
  109.                 unset($payload['productNumber']);
  110.                 $lineItem->setPayload($payload);
  111.             }
  112.         }
  113.     }
  114.     private function addCustomerValueToChildLabel(OrderLineItemCollection $optionCollectionOrderLineItemCollection $optionValueCollection): void
  115.     {
  116.         foreach ($optionCollection as $option) {
  117.             $option->setLabel(\sprintf('* %s'$option->getLabel()));
  118.             // ToDo CUS-17 - Remove when nested line items are shown and loaded correctly
  119.             /** @var OrderLineItemCollection $childLineItems */
  120.             $childLineItems $optionValueCollection->filterByProperty('parentId'$option->getId());
  121.             if ($childLineItems->count() > 0) {
  122.                 foreach ($childLineItems as $childLineItem) {
  123.                     $childLineItem->setLabel(\sprintf('* * %s'$childLineItem->getLabel()));
  124.                 }
  125.                 $option->setChildren($childLineItems);
  126.                 continue;
  127.             }
  128.             if ($value $this->extractValueFromPayload($option)) {
  129.                 $option->setLabel(\sprintf('%s: %s'$option->getLabel(), $value));
  130.             }
  131.         }
  132.     }
  133.     private function extractValueFromPayload(OrderLineItemEntity $option): ?string
  134.     {
  135.         $payload $option->getPayload() ?? [];
  136.         $type $payload['type'] ?? null;
  137.         $value $payload['value'] ?? '';
  138.         if (!$type) {
  139.             return null;
  140.         }
  141.         if ($type === Checkbox::NAME) {
  142.             return null;
  143.         }
  144.         if ($type === DateTime::NAME) {
  145.             return $value \date('d.m.Y'\strtotime($value)) : null;
  146.         }
  147.         if ($type === Timestamp::NAME) {
  148.             return $value \date('H:i'\strtotime($value)) : null;
  149.         }
  150.         if ($type === ImageUpload::NAME || $type === FileUpload::NAME) {
  151.             return \implode(', '\array_column($option->getPayload()['media'] ?? [], 'filename'));
  152.         }
  153.         if (\strlen($value) > 50) {
  154.             return \substr($value045) . '[...]';
  155.         }
  156.         return $value;
  157.     }
  158.     private function flattenOrderLineItemCollection(OrderLineItemCollection $orderLineItemCollection): OrderLineItemCollection
  159.     {
  160.         $newOrderLineItemCollection = new OrderLineItemCollection();
  161.         foreach ($orderLineItemCollection->getElements() as $item) {
  162.             $newOrderLineItemCollection->add($item);
  163.             $children $item->getChildren();
  164.             if ($children !== null) {
  165.                 $newOrderLineItemCollection->merge($this->flattenOrderLineItemCollection($children));
  166.             }
  167.         }
  168.         return $newOrderLineItemCollection;
  169.     }
  170. }