custom/plugins/MetalementsTheme/src/Subscriber/PicklistSubscriber.php line 67

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. namespace MetalementsTheme\Subscriber;
  4. use Shopware\Core\Checkout\Cart\Event\CartConvertedEvent;
  5. use Shopware\Core\Checkout\Cart\Event\CartLineItemWrittenEvent;
  6. use Shopware\Core\Checkout\Order\Aggregate\OrderLineItem\OrderLineItemEntity;
  7. use Shopware\Core\Checkout\Order\OrderEntity;
  8. use Shopware\Core\Checkout\Order\OrderEvents;
  9. use Shopware\Core\Checkout\Order\OrderService;
  10. use Shopware\Core\Framework\Context;
  11. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
  12. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  13. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
  14. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  15. use Shopware\Core\Checkout\Cart\Cart;
  16. use Shopware\Core\Checkout\Cart\CartBehavior;
  17. use Shopware\Core\Checkout\Cart\LineItemFactoryRegistry;
  18. use Shopware\Core\Checkout\Cart\LineItem\LineItem;
  19. use Shopware\Core\Checkout\Cart\CartPersister;
  20. use Shopware\Storefront\Page\Checkout\Confirm\CheckoutConfirmPageLoadedEvent;
  21. use Shopware\Core\Checkout\Cart\SalesChannel\CartService;
  22. use Shopware\Core\Checkout\Cart\Event\AfterLineItemRemovedEvent;
  23. use Shopware\Core\Checkout\Cart\LineItem\LineItemCollection;
  24. use Shopware\Core\Framework\Uuid\Uuid;
  25. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  26. use Shopware\Core\Checkout\Cart\Event\BeforeLineItemAddedEvent;
  27. class PicklistSubscriber implements EventSubscriberInterface {
  28.     private EntityRepositoryInterface $productRepository;
  29.     private CartService $cartService;
  30.     public function __construct(EntityRepositoryInterface $productRepositoryCartService $cartService) {
  31.         $this->productRepository $productRepository;
  32.         $this->cartService $cartService;
  33.     }
  34.     public static function getSubscribedEvents(): array {
  35.         return [
  36.             CheckoutConfirmPageLoadedEvent::class => "onCheckoutConfirmPageLoaded",
  37.             AfterLineItemRemovedEvent::class => 'onCartItemRemoved',
  38.             BeforeLineItemAddedEvent::class => 'onLineItemAdded',
  39.         ];
  40.     }
  41.     /**
  42.      * Liefert die Produkt-ID basierend auf der Produktnummer
  43.      *
  44.      * @param string $productNumber Die Produktnummer
  45.      * @param Context $context
  46.      *
  47.      * @return string|null Die Produkt-ID oder null, falls das Produkt nicht gefunden wurde
  48.      */
  49.     public function getProductIdByNumber(string $productNumberContext $context): ?string {
  50.         $criteria = new Criteria();
  51.         $criteria->addFilter(new EqualsFilter('productNumber'$productNumber));
  52.         $criteria->setLimit(1);
  53.         /** @var ProductEntity|null $product */
  54.         $product $this->productRepository->search($criteria$context)->first();
  55.         return $product $product->getId() : null;
  56.     }
  57.     public function onCheckoutConfirmPageLoaded(CheckoutConfirmPageLoadedEvent $event): void {
  58.         $salesChannelContext $event->getSalesChannelContext();
  59.         $context $salesChannelContext->getContext();
  60.         $customer $salesChannelContext->getCustomer();
  61.         $cart $this->cartService->getCart(
  62.             $salesChannelContext->getToken(),
  63.             $salesChannelContext
  64.         );
  65.         $cart $this->removeSinglePartItems($cart$salesChannelContext);
  66.         $lineItems $cart->getLineItems();
  67.         if ($customer !== null) {
  68.             $billingAddress $customer->getDefaultBillingAddress();
  69.         } else {
  70.             $billingAddress $salesChannelContext->getCustomerBillingAddress();
  71.         }
  72.         if ($billingAddress == null) {
  73.             return;
  74.         }
  75.         $productIds = [];
  76.         foreach ($lineItems as $lineItem) {
  77.             $payload $lineItem->getPayload();
  78.             if (array_key_exists('wct_single_part_main_line_item_id'$payload)) {
  79.                 $productIds[] = $lineItem->getId();
  80.             }
  81.         }
  82.         foreach ($lineItems as $lineItem) {
  83.             if ($lineItem->getType() !== LineItem::PRODUCT_LINE_ITEM_TYPE) {
  84.                 continue;
  85.             }
  86.             $payload $lineItem->getPayload();
  87.             if (!array_key_exists('wct_added_single_parts'$payload)) {
  88.                 $productId $lineItem->getReferencedId();
  89.                 $criteria = new Criteria([$productId]);
  90.                 $product $this->productRepository->search($criteria$context)->get($productId);
  91.                 $customFields $product->getCustomFields();
  92.                 if ($customFields && array_key_exists('wct_custom_field_single_parts'$customFields)) {
  93.                     $parts explode(';'$customFields['wct_custom_field_single_parts']);
  94.                     foreach ($parts as $part) {
  95.                         $singlePartSplit explode(':'$part);
  96.                         if (count($singlePartSplit) != 3) {
  97.                             continue;
  98.                         }
  99.                         $productNumber $singlePartSplit[0];
  100.                         $required $singlePartSplit[1];
  101.                         $amount $singlePartSplit[2];
  102.                         $productId $this->getProductIdByNumber($productNumber$context);
  103.                         if ($productId && !in_array($lineItem->getId(), $productIds) && $required) {
  104.                             $newLineItem = new LineItem(
  105.                                 Uuid::randomHex(),
  106.                                 LineItem::PRODUCT_LINE_ITEM_TYPE,
  107.                                 $productId,
  108.                                 intval($amount)
  109.                             );
  110.                             $newLineItem->setStackable(false);
  111.                             $newLineItem->setPayloadValue('wct_single_part_main_line_item_id'$lineItem->getId());
  112.                             $lineItem->setPayloadValue('wct_added_single_parts''true');
  113.                             $cart->add($newLineItem);
  114.                         }
  115.                     }
  116.                 }
  117.             }
  118.         }
  119.         $this->cartService->recalculate($cart$salesChannelContext);
  120.     }
  121.     public function removeSinglePartItems(\Shopware\Core\Checkout\Cart\Cart $cart\Shopware\Core\System\SalesChannel\SalesChannelContext $salesChannelContext): \Shopware\Core\Checkout\Cart\Cart {
  122.         $lineItems $cart->getLineItems();
  123.         $lineItemIds = [];
  124.         foreach ($lineItems as $lineItem) {
  125.             $lineItemIds[] = $lineItem->getId();
  126.         }
  127.         foreach ($lineItems as $lineItem) {
  128.             $payload $lineItem->getPayload();
  129.             if (array_key_exists('wct_single_part_main_line_item_id'$payload)) {
  130.                 if (!in_array($payload['wct_single_part_main_line_item_id'], $lineItemIds)) {
  131.                     $lineItem->setRemovable(true);
  132.                     $cart->remove($lineItem->getId());
  133.                 }
  134.             }
  135.         }
  136.         $this->cartService->recalculate($cart$salesChannelContext);
  137.         return $cart;
  138.     }
  139.     public function onCartItemRemoved(AfterLineItemRemovedEvent $event): void {
  140.         $this->removeSinglePartItems($event->getCart(), $event->getSalesChannelContext());
  141.     }
  142.     public function onLineItemAdded(BeforeLineItemAddedEvent $event): void {
  143.         $salesChannelContext $event->getSalesChannelContext();
  144.         $context $salesChannelContext->getContext();
  145.         $lineItem $event->getLineItem();
  146.         if ($lineItem->getType() !== LineItem::PRODUCT_LINE_ITEM_TYPE) {
  147.             return;
  148.         }
  149.         $productId $lineItem->getReferencedId();
  150.         $criteria = new Criteria([$productId]);
  151.         $product $this->productRepository->search($criteria$context)->get($productId);
  152.         $customFields $product->getCustomFields();
  153.         if ($customFields && array_key_exists('wct_custom_field_single_parts'$customFields)) {
  154.             $lineItem->setId(Uuid::randomHex());
  155.             $lineItem->setPayloadValue('wct_custom_field_single_parts'$customFields['wct_custom_field_single_parts']);
  156.         }
  157.     }
  158. }