<?php declare(strict_types=1);
/**
* digitvision
*
* @category digitvision
* @package Shopware\Plugins\DvsnBundle
* @copyright (c) 2021 digitvision
*/
namespace Dvsn\Bundle\Subscriber\Core\Checkout\Cart\Order;
use Dvsn\Bundle\Service\Cart\LineItemFactoryServiceInterface;
use Shopware\Core\Checkout\Cart\LineItem\LineItem;
use Shopware\Core\Checkout\Cart\Order\CartConvertedEvent;
use Shopware\Core\Checkout\Cart\Price\QuantityPriceCalculator;
use Shopware\Core\Checkout\Cart\Price\Struct\QuantityPriceDefinition;
use Shopware\Core\System\SystemConfig\SystemConfigService;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class OrderConverterSubscriber implements EventSubscriberInterface
{
private QuantityPriceCalculator $quantityPriceCalculator;
private SystemConfigService $systemConfigService;
public function __construct(
QuantityPriceCalculator $quantityPriceCalculator,
SystemConfigService $systemConfigService
) {
$this->quantityPriceCalculator = $quantityPriceCalculator;
$this->systemConfigService = $systemConfigService;
}
/**
* {@inheritDoc}
*/
public static function getSubscribedEvents(): array
{
return [
CartConvertedEvent::class => 'onCartConverted'
];
}
/**
* ...
*
* @param CartConvertedEvent $event
*/
public function onCartConverted(CartConvertedEvent $event): void
{
if ((boolean) $this->systemConfigService->get('DvsnBundle.config.status', $event->getSalesChannelContext()->getSalesChannel()->getId()) === false) {
return;
}
if ($this->hasBundles($event->getConvertedCart()) === false) {
return;
}
if ((boolean) $this->systemConfigService->get('DvsnBundle.config.orderFlattenBundle', $event->getSalesChannelContext()->getSalesChannel()->getId()) === true) {
$this->flattenBundle($event);
if ((boolean) $this->systemConfigService->get('DvsnBundle.config.dropParentContainer', $event->getSalesChannelContext()->getSalesChannel()->getId()) === true) {
$this->removeParent($event);
}
}
$this->resetLineItemType($event);
$this->fixLineItemPositions($event);
}
/**
* ...
*
* @param array $cart
*
* @return bool
*/
private function hasBundles(array $cart): bool
{
foreach ($cart['lineItems'] as $lineItem) {
if ($lineItem['type'] === LineItemFactoryServiceInterface::BUNDLE_LINE_ITEM_TYPE) {
return true;
}
}
return false;
}
/**
* ...
*
* @param CartConvertedEvent $event
*/
private function resetLineItemType(CartConvertedEvent $event): void
{
// get the cart
$cart = $event->getConvertedCart();
// loop every line item to make them products
foreach ($cart['lineItems'] as $i => $lineItem) {
switch ($lineItem['type']) {
case LineItemFactoryServiceInterface::BUNDLE_PRODUCT_LINE_ITEM_TYPE:
$cart['lineItems'][$i]['type'] = LineItem::PRODUCT_LINE_ITEM_TYPE;
$cart['lineItems'][$i]['productId'] = $lineItem['payload']['dvsnBundleProductId'];
break;
}
}
// save back
$event->setConvertedCart($cart);
}
/**
* ...
*
* @param CartConvertedEvent $event
*/
private function flattenBundle(CartConvertedEvent $event): void
{
// get the cart
$cart = $event->getConvertedCart();
// flatten the bundle items
foreach ($cart['lineItems'] as $i => $lineItem) {
switch ($lineItem['type']) {
case LineItemFactoryServiceInterface::BUNDLE_LINE_ITEM_TYPE:
$cart['lineItems'][$i]['priceDefinition'] = new QuantityPriceDefinition(
0,
$event->getSalesChannelContext()->buildTaxRules($lineItem['payload']['taxId']),
$lineItem['quantity']
);
$cart['lineItems'][$i]['price'] = $this->quantityPriceCalculator->calculate(
$lineItem['priceDefinition'],
$event->getSalesChannelContext()
);
break;
case LineItemFactoryServiceInterface::BUNDLE_PRODUCT_LINE_ITEM_TYPE:
case LineItemFactoryServiceInterface::BUNDLE_DISCOUNT_LINE_ITEM_TYPE:
$cart['lineItems'][$i]['payload']['dvsnBundleFormerParentId'] = $cart['lineItems'][$i]['parentId'];
unset($cart['lineItems'][$i]['parentId']);
break;
}
}
// save back
$event->setConvertedCart($cart);
}
/**
* ...
*
* @param CartConvertedEvent $event
*/
private function removeParent(CartConvertedEvent $event): void
{
$cart = $event->getConvertedCart();
foreach ($cart['lineItems'] as $i => $lineItem) {
if ($lineItem['type'] !== LineItemFactoryServiceInterface::BUNDLE_LINE_ITEM_TYPE) {
continue;
}
unset($cart['lineItems'][$i]);
foreach ($cart['deliveries'] as $deliveryId => $delivery) {
$positions = [];
foreach ($delivery['positions'] as $j => $position) {
if ($position['orderLineItemId'] !== $lineItem['id']) {
$positions[] = $position;
continue;
}
foreach ($cart['lineItems'] as $childLineItem) {
if (!isset($childLineItem['payload']) || !is_array($childLineItem['payload']) || !isset($childLineItem['payload']['dvsnBundleFormerParentId'])) {
continue;
}
if ($childLineItem['payload']['dvsnBundleFormerParentId'] !== $lineItem['id']) {
continue;
}
$positions[] = [
'id' => null,
'price' => $childLineItem['price'],
'orderLineItemId' => $childLineItem['id'],
'orderLineItemVersionId' => $position['orderLineItemVersionId']
];
}
}
$cart['deliveries'][$deliveryId]['positions'] = $positions;
}
}
$event->setConvertedCart($cart);
}
/**
* ...
*
* @param CartConvertedEvent $event
*/
private function fixLineItemPositions(CartConvertedEvent $event): void
{
// get the cart
$cart = $event->getConvertedCart();
// fix every position
foreach ($cart['lineItems'] as $key => $lineItem) {
// set position
$cart['lineItems'][$key]['position'] = $key + 1;
}
// save back
$event->setConvertedCart($cart);
}
}