<?php
declare(strict_types=1);
namespace MetalementsTheme\Subscriber;
use Shopware\Core\Checkout\Cart\Event\CartConvertedEvent;
use Shopware\Core\Checkout\Cart\Event\CartLineItemWrittenEvent;
use Shopware\Core\Checkout\Order\Aggregate\OrderLineItem\OrderLineItemEntity;
use Shopware\Core\Checkout\Order\OrderEntity;
use Shopware\Core\Checkout\Order\OrderEvents;
use Shopware\Core\Checkout\Order\OrderService;
use Shopware\Core\Framework\Context;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Shopware\Core\Checkout\Cart\Cart;
use Shopware\Core\Checkout\Cart\CartBehavior;
use Shopware\Core\Checkout\Cart\LineItemFactoryRegistry;
use Shopware\Core\Checkout\Cart\LineItem\LineItem;
use Shopware\Core\Checkout\Cart\CartPersister;
use Shopware\Storefront\Page\Checkout\Confirm\CheckoutConfirmPageLoadedEvent;
use Shopware\Core\Checkout\Cart\SalesChannel\CartService;
use Shopware\Core\Checkout\Cart\Event\AfterLineItemRemovedEvent;
use Shopware\Core\Checkout\Cart\LineItem\LineItemCollection;
use Shopware\Core\Framework\Uuid\Uuid;
use Shopware\Core\System\SalesChannel\SalesChannelContext;
use Shopware\Core\Checkout\Cart\Event\BeforeLineItemAddedEvent;
class PicklistSubscriber implements EventSubscriberInterface {
private EntityRepositoryInterface $productRepository;
private CartService $cartService;
public function __construct(EntityRepositoryInterface $productRepository, CartService $cartService) {
$this->productRepository = $productRepository;
$this->cartService = $cartService;
}
public static function getSubscribedEvents(): array {
return [
CheckoutConfirmPageLoadedEvent::class => "onCheckoutConfirmPageLoaded",
AfterLineItemRemovedEvent::class => 'onCartItemRemoved',
BeforeLineItemAddedEvent::class => 'onLineItemAdded',
];
}
/**
* Liefert die Produkt-ID basierend auf der Produktnummer
*
* @param string $productNumber Die Produktnummer
* @param Context $context
*
* @return string|null Die Produkt-ID oder null, falls das Produkt nicht gefunden wurde
*/
public function getProductIdByNumber(string $productNumber, Context $context): ?string {
$criteria = new Criteria();
$criteria->addFilter(new EqualsFilter('productNumber', $productNumber));
$criteria->setLimit(1);
/** @var ProductEntity|null $product */
$product = $this->productRepository->search($criteria, $context)->first();
return $product ? $product->getId() : null;
}
public function onCheckoutConfirmPageLoaded(CheckoutConfirmPageLoadedEvent $event): void {
$salesChannelContext = $event->getSalesChannelContext();
$context = $salesChannelContext->getContext();
$customer = $salesChannelContext->getCustomer();
$cart = $this->cartService->getCart(
$salesChannelContext->getToken(),
$salesChannelContext
);
$cart = $this->removeSinglePartItems($cart, $salesChannelContext);
$lineItems = $cart->getLineItems();
if ($customer !== null) {
$billingAddress = $customer->getDefaultBillingAddress();
} else {
$billingAddress = $salesChannelContext->getCustomerBillingAddress();
}
if ($billingAddress == null) {
return;
}
$productIds = [];
foreach ($lineItems as $lineItem) {
$payload = $lineItem->getPayload();
if (array_key_exists('wct_single_part_main_line_item_id', $payload)) {
$productIds[] = $lineItem->getId();
}
}
foreach ($lineItems as $lineItem) {
if ($lineItem->getType() !== LineItem::PRODUCT_LINE_ITEM_TYPE) {
continue;
}
$payload = $lineItem->getPayload();
if (!array_key_exists('wct_added_single_parts', $payload)) {
$productId = $lineItem->getReferencedId();
$criteria = new Criteria([$productId]);
$product = $this->productRepository->search($criteria, $context)->get($productId);
$customFields = $product->getCustomFields();
if ($customFields && array_key_exists('wct_custom_field_single_parts', $customFields)) {
$parts = explode(';', $customFields['wct_custom_field_single_parts']);
foreach ($parts as $part) {
$singlePartSplit = explode(':', $part);
if (count($singlePartSplit) != 3) {
continue;
}
$productNumber = $singlePartSplit[0];
$required = $singlePartSplit[1];
$amount = $singlePartSplit[2];
$productId = $this->getProductIdByNumber($productNumber, $context);
if ($productId && !in_array($lineItem->getId(), $productIds) && $required) {
$newLineItem = new LineItem(
Uuid::randomHex(),
LineItem::PRODUCT_LINE_ITEM_TYPE,
$productId,
intval($amount)
);
$newLineItem->setStackable(false);
$newLineItem->setPayloadValue('wct_single_part_main_line_item_id', $lineItem->getId());
$lineItem->setPayloadValue('wct_added_single_parts', 'true');
$cart->add($newLineItem);
}
}
}
}
}
$this->cartService->recalculate($cart, $salesChannelContext);
}
public function removeSinglePartItems(\Shopware\Core\Checkout\Cart\Cart $cart, \Shopware\Core\System\SalesChannel\SalesChannelContext $salesChannelContext): \Shopware\Core\Checkout\Cart\Cart {
$lineItems = $cart->getLineItems();
$lineItemIds = [];
foreach ($lineItems as $lineItem) {
$lineItemIds[] = $lineItem->getId();
}
foreach ($lineItems as $lineItem) {
$payload = $lineItem->getPayload();
if (array_key_exists('wct_single_part_main_line_item_id', $payload)) {
if (!in_array($payload['wct_single_part_main_line_item_id'], $lineItemIds)) {
$lineItem->setRemovable(true);
$cart->remove($lineItem->getId());
}
}
}
$this->cartService->recalculate($cart, $salesChannelContext);
return $cart;
}
public function onCartItemRemoved(AfterLineItemRemovedEvent $event): void {
$this->removeSinglePartItems($event->getCart(), $event->getSalesChannelContext());
}
public function onLineItemAdded(BeforeLineItemAddedEvent $event): void {
$salesChannelContext = $event->getSalesChannelContext();
$context = $salesChannelContext->getContext();
$lineItem = $event->getLineItem();
if ($lineItem->getType() !== LineItem::PRODUCT_LINE_ITEM_TYPE) {
return;
}
$productId = $lineItem->getReferencedId();
$criteria = new Criteria([$productId]);
$product = $this->productRepository->search($criteria, $context)->get($productId);
$customFields = $product->getCustomFields();
if ($customFields && array_key_exists('wct_custom_field_single_parts', $customFields)) {
$lineItem->setId(Uuid::randomHex());
$lineItem->setPayloadValue('wct_custom_field_single_parts', $customFields['wct_custom_field_single_parts']);
}
}
}