<?php declare(strict_types=1);
namespace Dkc\Productoptions\Subscriber;
use Shopware\Core\Checkout\Cart\Event\BeforeLineItemAddedEvent;
use Shopware\Core\Checkout\Cart\Event\CartChangedEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Shopware\Core\Checkout\Cart\Price\QuantityPriceCalculator;
use Shopware\Core\Checkout\Cart\Price\Struct\QuantityPriceDefinition;
use Symfony\Component\HttpFoundation\RequestStack;
class CartPriceSubscriber implements EventSubscriberInterface
{
private QuantityPriceCalculator $priceCalculator;
private RequestStack $requestStack;
public function __construct(
QuantityPriceCalculator $priceCalculator,
RequestStack $requestStack
) {
$this->priceCalculator = $priceCalculator;
$this->requestStack = $requestStack;
}
public static function getSubscribedEvents(): array
{
return [
BeforeLineItemAddedEvent::class => ['onBeforeLineItemAdded', 9999],
CartChangedEvent::class => ['onCartChanged', 9999],
];
}
public function onBeforeLineItemAdded(BeforeLineItemAddedEvent $event): void
{
$lineItem = $event->getLineItem();
$lineItemId = $lineItem->getId();
$request = $this->requestStack->getCurrentRequest();
if (!$request) {
return;
}
$allParams = $request->request->all();
if (
isset($allParams['lineItems']) &&
isset($allParams['lineItems'][$lineItemId]) &&
isset($allParams['lineItems'][$lineItemId]['payload']) &&
isset($allParams['lineItems'][$lineItemId]['payload']['dkc_product_options'])
) {
$options = $allParams['lineItems'][$lineItemId]['payload']['dkc_product_options'];
$price = $allParams['lineItems'][$lineItemId]['payload']['dkc_product_options_price'] ?? 0;
$labels = $allParams['lineItems'][$lineItemId]['payload']['dkc_product_options_labels'] ?? null;
if (is_string($options)) {
$options = json_decode($options, true);
}
if (is_string($labels)) {
$labels = json_decode($labels, true);
}
$lineItem->setPayloadValue('dkc_product_options', $options);
$lineItem->setPayloadValue('dkc_product_options_price', (float)$price);
if ($labels) {
$lineItem->setPayloadValue('dkc_product_options_labels', $labels);
}
}
}
public function onCartChanged(CartChangedEvent $event): void
{
$cart = $event->getCart();
foreach ($cart->getLineItems() as $lineItem) {
if (
!$lineItem->hasPayloadValue('dkc_product_options') ||
!$lineItem->hasPayloadValue('dkc_product_options_price')
) {
continue;
}
$optionPrice = (float)$lineItem->getPayloadValue('dkc_product_options_price');
$originalPrice = $lineItem->getPrice();
if ($optionPrice <= 0 || !$originalPrice) {
continue;
}
$taxRules = $originalPrice->getTaxRules();
$unitPrice = $originalPrice->getUnitPrice() + $optionPrice;
$quantity = $lineItem->getQuantity();
$priceDefinition = new QuantityPriceDefinition(
$unitPrice,
$taxRules,
$quantity
);
$newPrice = $this->priceCalculator->calculate($priceDefinition, $event->getContext());
$lineItem->setPrice($newPrice);
}
}
}