custom/plugins/AcrisRuleSurchargeDiscountCS/src/Storefront/Subscriber/SurchargeDiscountSubscriber.php line 81

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Acris\RuleSurchargeDiscount\Storefront\Subscriber;
  3. use Acris\RuleSurchargeDiscount\Components\Service\SurchargeDiscountService;
  4. use Acris\RuleSurchargeDiscount\Components\Struct\AdditionalCostStruct;
  5. use Acris\RuleSurchargeDiscount\Core\Checkout\SurchargeDiscount\Cart\AbstractSurchargeDiscountProcessor;
  6. use Shopware\Core\Checkout\Cart\LineItem\LineItem;
  7. use Shopware\Core\Checkout\Cart\LineItem\LineItemCollection;
  8. use Shopware\Core\Checkout\Cart\Order\CartConvertedEvent;
  9. use Shopware\Core\Checkout\Cart\Order\OrderConvertedEvent;
  10. use Shopware\Core\Checkout\Cart\Tax\Struct\CalculatedTax;
  11. use Shopware\Core\Checkout\Cart\Tax\Struct\TaxRule;
  12. use Shopware\Core\Checkout\Order\Aggregate\OrderLineItem\OrderLineItemEntity;
  13. use Shopware\Core\Checkout\Order\OrderEntity;
  14. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  15. use Shopware\Storefront\Page\Account\Order\AccountOrderPageLoadedEvent;
  16. use Shopware\Storefront\Page\Checkout\Finish\CheckoutFinishPageLoadedEvent;
  17. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  18. class SurchargeDiscountSubscriber implements EventSubscriberInterface
  19. {
  20.     public const SURCHARGE_DISCOUNT_ADDITIONAL_COSTS_DATA_KEY 'acrisSurchargeDiscountAdditionalCosts';
  21.     public const MOLLIE_PAYMENTS_ADDITIONAL_COSTS_DATA_KEY 'molliePaymentsData';
  22.     public const TYPE_DISCOUNT 'discount';
  23.     private SurchargeDiscountService $surchargeDiscountService;
  24.     public function __construct(
  25.         SurchargeDiscountService $surchargeDiscountService
  26.     )
  27.     {
  28.         $this->surchargeDiscountService $surchargeDiscountService;
  29.     }
  30.     public static function getSubscribedEvents(): array
  31.     {
  32.         return [
  33.             CartConvertedEvent::class => [
  34.                 ['onCartConverted', -200]
  35.             ],
  36.             OrderConvertedEvent::class => [
  37.                 ['onOrderConverted', -200]
  38.             ],
  39.             CheckoutFinishPageLoadedEvent::class => [
  40.                 ['onCheckoutFinishPageLoaded', -200]
  41.             ],
  42.             AccountOrderPageLoadedEvent::class => [
  43.                 ['onAccountOrderPageLoaded', -200]
  44.             ]
  45.         ];
  46.     }
  47.     public function onCartConverted(CartConvertedEvent $event): void
  48.     {
  49.         $additionalCostLineItems $this->getAdditionalCostLineItems($event->getSalesChannelContext());
  50.         $convertedCart $this->checkLineItemQuantity($event->getConvertedCart(), $event);
  51.         if ($additionalCostLineItems->count() === 0) return;
  52.         $customFields = !empty($convertedCart) && array_key_exists('customFields'$convertedCart)
  53.         && !empty($convertedCart['customFields'] && is_array($convertedCart['customFields'])) ? $convertedCart['customFields'] : [];
  54.         $additionalCostData = [];
  55.         foreach ($additionalCostLineItems->getElements() as $lineItem) {
  56.             $additionalCostData[] = $this->buildAdditionalCostData($lineItem);
  57.         }
  58.         if (empty($additionalCostData)) return;
  59.         $customFields[self::SURCHARGE_DISCOUNT_ADDITIONAL_COSTS_DATA_KEY] = $additionalCostData;
  60.         $convertedCart['customFields'] = $customFields;
  61.         $event->setConvertedCart($convertedCart);
  62.     }
  63.     public function onOrderConverted(OrderConvertedEvent $event): void
  64.     {
  65.         $cart $event->getConvertedCart();
  66.         if (!empty($event->getOrder()->getCustomFields()) && is_array($event->getOrder()->getCustomFields()) && array_key_exists(self::SURCHARGE_DISCOUNT_ADDITIONAL_COSTS_DATA_KEY$event->getOrder()->getCustomFields()) && is_array($event->getOrder()->getCustomFields()[self::SURCHARGE_DISCOUNT_ADDITIONAL_COSTS_DATA_KEY])) {
  67.             $cart->addExtension(self::SURCHARGE_DISCOUNT_ADDITIONAL_COSTS_DATA_KEY, new AdditionalCostStruct($event->getOrder()->getCustomFields()[self::SURCHARGE_DISCOUNT_ADDITIONAL_COSTS_DATA_KEY]));
  68.         } else {
  69.             if ($cart->hasExtension(self::SURCHARGE_DISCOUNT_ADDITIONAL_COSTS_DATA_KEY)) {
  70.                 $cart->removeExtension(self::SURCHARGE_DISCOUNT_ADDITIONAL_COSTS_DATA_KEY);
  71.             }
  72.         }
  73.     }
  74.     public function onCheckoutFinishPageLoaded(CheckoutFinishPageLoadedEvent $event): void
  75.     {
  76.         $this->assignMediaToOrderLineItems($event->getPage()->getOrder(), $event->getSalesChannelContext());
  77.     }
  78.     public function onAccountOrderPageLoaded(AccountOrderPageLoadedEvent $event): void
  79.     {
  80.         if ($event->getPage()->getOrders()->count() === 0) return;
  81.         foreach ($event->getPage()->getOrders()->getEntities()->getElements() as $order) {
  82.             $this->assignMediaToOrderLineItems($order$event->getSalesChannelContext());
  83.         }
  84.     }
  85.     private function getAdditionalCostLineItems(SalesChannelContext $context): LineItemCollection
  86.     {
  87.         return $context->hasExtension(AbstractSurchargeDiscountProcessor::LINE_ITEM_COLLECTION) && !empty($context->getExtension(AbstractSurchargeDiscountProcessor::LINE_ITEM_COLLECTION)) && $context->getExtension(AbstractSurchargeDiscountProcessor::LINE_ITEM_COLLECTION) instanceof LineItemCollection $context->getExtension(AbstractSurchargeDiscountProcessor::LINE_ITEM_COLLECTION) : new LineItemCollection();
  88.     }
  89.     private function assignMediaToOrderLineItems(OrderEntity $orderSalesChannelContext $salesChannelContext): void
  90.     {
  91.         if (empty($order->getLineItems()) || $order->getLineItems()->count() === 0) return;
  92.         /** @var OrderLineItemEntity $lineItem */
  93.         foreach ($order->getLineItems() as $lineItem) {
  94.             if ($lineItem->getType() === AbstractSurchargeDiscountProcessor::LINE_ITEM_TYPE && !empty($lineItem->getPayload()) && is_array($lineItem->getPayload()) && array_key_exists('surchargeDiscountId'$lineItem->getPayload()) && !empty($lineItem->getPayload()['surchargeDiscountId']) && array_key_exists('displayIcon'$lineItem->getPayload()) && !empty($lineItem->getPayload()['displayIcon']) && $lineItem->getPayload()['displayIcon'] === 'image' && array_key_exists('iconMediaId'$lineItem->getPayload()) && !empty($lineItem->getPayload()['iconMediaId'])) {
  95.                 $this->surchargeDiscountService->loadOrderLineItemExtension($lineItem$lineItem->getPayload()['surchargeDiscountId'], $salesChannelContext);
  96.             }
  97.         }
  98.     }
  99.     private function checkLineItemQuantity(array $convertedCartCartConvertedEvent $event): array
  100.     {
  101.         if (empty($convertedCart) || !array_key_exists('lineItems'$convertedCart) || empty($convertedCart['lineItems']) || !is_array($convertedCart['lineItems'])) return $convertedCart;
  102.         $lineItems $convertedCart['lineItems'];
  103.         $quantityChanged false;
  104.         foreach ($lineItems as $key => $lineItem) {
  105.             if (empty($lineItem) || !is_array($lineItem) || !array_key_exists('type'$lineItem) || empty($lineItem['type']) || $lineItem['type'] !== AbstractSurchargeDiscountProcessor::LINE_ITEM_TYPE || !array_key_exists('quantity'$lineItem) || empty($lineItem['quantity']) || !array_key_exists('payload'$lineItem) || empty($lineItem['payload']) || !is_array($lineItem['payload'])) continue;
  106.             $quantity $lineItem['quantity'];
  107.             $payload $lineItem['payload'];
  108.             if (!array_key_exists('calculateQuantityResult'$payload) || empty($payload['calculateQuantityResult']) || !is_array($payload['calculateQuantityResult']) || !array_key_exists('quantity'$payload['calculateQuantityResult']) || empty($payload['calculateQuantityResult']['quantity']) || $payload['calculateQuantityResult']['quantity'] === $quantity) continue;
  109.             $lineItems[$key]['quantity'] = $payload['calculateQuantityResult']['quantity'];
  110.             $quantityChanged true;
  111.         }
  112.         if ($quantityChanged === true) {
  113.             $convertedCart['lineItems'] = $lineItems;
  114.             $event->setConvertedCart($convertedCart);
  115.         }
  116.         return $convertedCart;
  117.     }
  118.     private function buildAdditionalCostData(LineItem $lineItem): array
  119.     {
  120.         $data = ['label' => $lineItem->getLabel(), 'originalId' => $lineItem->getId(),  'price' => ['totalPrice' => $lineItem->getPrice()->getTotalPrice()]];
  121.         // compatibility with the MolliePayments plugin and additional costs
  122.         return $this->buildMollieAdditionalCostData($data$lineItem);
  123.     }
  124.     private function buildMollieAdditionalCostData(array $originalDataLineItem $lineItem): array
  125.     {
  126.         try {
  127.             $data = [];
  128.             if (!empty($lineItem->getPrice())) {
  129.                 $data['unitPrice'] = $lineItem->getPrice()->getUnitPrice();
  130.                 $data['totalPrice'] = $lineItem->getPrice()->getTotalPrice();
  131.                 if (!empty($lineItem->getPrice()->getCalculatedTaxes()) && $lineItem->getPrice()->getCalculatedTaxes()->count() > 0) {
  132.                     $calculatedTaxes = [];
  133.                     /** @var CalculatedTax $calculatedTax */
  134.                     foreach ($lineItem->getPrice()->getCalculatedTaxes()->getElements() as $key => $calculatedTax) {
  135.                         $calculatedTaxes[$key] = [
  136.                             'tax' => $calculatedTax->getTax(),
  137.                             'taxRate' => $calculatedTax->getTaxRate(),
  138.                             'price' => $calculatedTax->getPrice(),
  139.                             'extensions' => $calculatedTax->getExtensions()
  140.                         ];
  141.                     }
  142.                     if (!empty($calculatedTaxes)) {
  143.                         $data['calculatedTaxes'] = $calculatedTaxes;
  144.                     }
  145.                 }
  146.                 if (!empty($lineItem->getPrice()->getTaxRules()) && $lineItem->getPrice()->getTaxRules()->count() > 0) {
  147.                     $taxRules = [];
  148.                     /** @var TaxRule $taxRule */
  149.                     foreach ($lineItem->getPrice()->getTaxRules()->getElements() as $key => $taxRule) {
  150.                         $taxRules[$key] = [
  151.                             'taxRate' => $taxRule->getTaxRate(),
  152.                             'percentage' => $taxRule->getPercentage(),
  153.                             'extensions' => $taxRule->getExtensions()
  154.                         ];
  155.                     }
  156.                     if (!empty($taxRules)) {
  157.                         $data['taxRules'] = $taxRules;
  158.                     }
  159.                 }
  160.             }
  161.             $data array_merge($data, [
  162.                 'id' => $lineItem->getId(),
  163.                 'type' => self::TYPE_DISCOUNT,
  164.                 'label' => $lineItem->getLabel(),
  165.                 'quantity' => $lineItem->getQuantity()
  166.             ]);
  167.             $originalData[self::MOLLIE_PAYMENTS_ADDITIONAL_COSTS_DATA_KEY] = $data;
  168.             return $originalData;
  169.         } catch (\Throwable $e) {
  170.             return $originalData;
  171.         }
  172.     }
  173. }