<?php
namespace Twigel\SportPlugin\Subscriber;
use Shopware\Core\Checkout\Cart\Event\BeforeLineItemAddedEvent;
use Shopware\Core\Checkout\Cart\LineItem\LineItem;
use Shopware\Core\Checkout\Cart\LineItem\LineItemCollection;
use Shopware\Core\Checkout\Cart\LineItemFactoryRegistry;
use Shopware\Core\Checkout\Cart\Price\Struct\CalculatedPrice;
use Shopware\Core\Checkout\Cart\Tax\Struct\CalculatedTaxCollection;
use Shopware\Core\Checkout\Cart\Tax\Struct\TaxRuleCollection;
use Shopware\Core\Checkout\Promotion\Cart\PromotionItemBuilder;
use Shopware\Core\Checkout\Promotion\PromotionEntity;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\Uuid\Uuid;
use Shopware\Core\System\SalesChannel\Entity\SalesChannelRepositoryInterface;
use Shopware\Core\System\SystemConfig\SystemConfigService;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RequestStack;
class BeforeLineItemAddedSubscriber implements EventSubscriberInterface
{
/**
* @var RequestStack
*/
private RequestStack $requestStack;
/**
* @var LineItemFactoryRegistry
*/
private LineItemFactoryRegistry $factory;
/**
* @var PromotionItemBuilder
*/
private PromotionItemBuilder $promotionItemBuilder;
/**
* @var SystemConfigService
*/
private SystemConfigService $systemConfigService;
/**
* @var SalesChannelRepositoryInterface $productRepository
*/
private SalesChannelRepositoryInterface $productRepository;
/**
* @var EntityRepositoryInterface $promotionRepository
*/
private EntityRepositoryInterface $promotionRepository;
/**
* @param RequestStack $requestStack
* @param LineItemFactoryRegistry $factory
* @param PromotionItemBuilder $promotionItemBuilder
* @param SystemConfigService $systemConfigService
* @param SalesChannelRepositoryInterface $productRepository
* @param EntityRepositoryInterface $promotionRepository
*/
public function __construct(
RequestStack $requestStack,
LineItemFactoryRegistry $factory,
PromotionItemBuilder $promotionItemBuilder,
SystemConfigService $systemConfigService,
SalesChannelRepositoryInterface $productRepository,
EntityRepositoryInterface $promotionRepository
)
{
$this->requestStack = $requestStack;
$this->factory = $factory;
$this->promotionItemBuilder = $promotionItemBuilder;
$this->systemConfigService = $systemConfigService;
$this->productRepository = $productRepository;
$this->promotionRepository = $promotionRepository;
}
public static function getSubscribedEvents(): array
{
return [
BeforeLineItemAddedEvent::class => 'onLineItemAdded',
];
}
/**
* @param BeforeLineItemAddedEvent $event
*/
public function onLineItemAdded(BeforeLineItemAddedEvent $event)
{
$productSet = $this->requestStack->getCurrentRequest()->get('productSet');
$productSet = json_decode($productSet);
if (is_null($productSet) || empty($productSet)) {
return;
}
$pluginConfig = $this->systemConfigService->get('TwigelSportPlugin.config');
if (is_null($pluginConfig['setPromotionFull']) && is_null($pluginConfig['setPromotionPartial'])) {
return;
}
$full = $this->requestStack->getCurrentRequest()->get('productSetFull');
if ($full == 'true'){
$setPromotion = $pluginConfig['setPromotionFull'];
}else{
$setPromotion = $pluginConfig['setPromotionPartial'];
}
$lineItems = [];
$total = 0;
foreach ($productSet as $set) {
$product = $this->productRepository->search(new Criteria([$set]), $event->getSalesChannelContext())->get($set);
if (is_null($product)) {
return;
}
$params = [
'type' => LineItem::PRODUCT_LINE_ITEM_TYPE,
'referencedId' => $set,
'quantity' => 1
];
$calcPrice = new CalculatedPrice(
$product->getPrice()->get($event->getSalesChannelContext()->getCurrencyId())->getGross(),
$product->getPrice()->get($event->getSalesChannelContext()->getCurrencyId())->getGross() * (1),
$product->calculatedPrice->getCalculatedTaxes(),
$product->calculatedPrice->getTaxRules(),
1
);
$total += $calcPrice->getTotalPrice();
$lineItem = $this->factory->create($params, $event->getSalesChannelContext());
$lineItem->setRemovable(true);
$lineItem->setStackable(true);
$lineItem->setPayloadValue('productSet', 'true');
$lineItem->setPrice($calcPrice);
$lineItems[] = $lineItem;
}
$criteria = new Criteria([$setPromotion]);
$criteria->addAssociation('discounts');
/** @var PromotionEntity $promotion */
$promotion = $this->promotionRepository->search($criteria, $event->getContext())->get($setPromotion);
if (!empty($promotion)) {
$discount = $promotion->getDiscounts()->first();
if (!empty($discount) && $promotion->isActive()) {
$promotionLineItem = $this->promotionItemBuilder->buildDiscountLineItem(
$promotion->getCode(),
$promotion,
$discount,
$event->getSalesChannelContext()->getCurrencyId()
);
switch ($promotionLineItem->getPayloadValue('discountType')) {
case 'fixed_unit':
$promotionValue = $promotionLineItem->getPayloadValue('value');
break;
default:
$promotionValue = $total / 100 * $promotionLineItem->getPayloadValue('value');
}
$promotionValue = -1 * $promotionValue;
$promotionLineItem->setPrice(
new CalculatedPrice(
$promotionValue,
$promotionValue,
new CalculatedTaxCollection(),
new TaxRuleCollection()
)
);
$promotionLineItem->setId(Uuid::randomHex());
$promotionLineItem->setRemovable(true);
$promotionLineItem->setStackable(false);
$lineItems[] = $promotionLineItem;
}
}
foreach ($event->getCart()->getLineItems() as $lineItem){
$lineItems[] = $lineItem;
}
$lineItems = new LineItemCollection($lineItems);
$event->getCart()->setLineItems($lineItems);
$event->getCart()->markModified();
}
}