<?php
declare(strict_types=1);
namespace BartCPreemiumArticle\PremiumArticle\Subscriber;
use BartCPreemiumArticle\PremiumArticle\Core\Content\Premium\PremiumDefinition;
use BartCPreemiumArticle\PremiumArticle\Repository\MinPriceRepositoryInterface;
use BartCPreemiumArticle\PremiumArticle\Repository\TotalPriceRepositoryInterface;
use BartCPreemiumArticle\PremiumArticle\Service\CheckIfVariantsAreAvailableInterface;
use BartCPreemiumArticle\PremiumArticle\Service\FindPremiumProductsInCartInterface;
use BartCPreemiumArticle\PremiumArticle\Service\PremiumAccessControl;
use BartCPreemiumArticle\PremiumArticle\Service\RemoveProductsWithMaxMultiAddCounts;
use Psr\Log\LoggerInterface;
use Shopware\Core\Checkout\Cart\SalesChannel\CartService;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
use Shopware\Core\Framework\DataAbstractionLayer\Exception\InconsistentCriteriaIdsException;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\MultiFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\NotFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\RangeFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Sorting\FieldSorting;
use Shopware\Core\Framework\Struct\ArrayEntity;
use Shopware\Core\System\SalesChannel\SalesChannelContext;
use Shopware\Core\System\SystemConfig\SystemConfigService;
use Shopware\Storefront\Page\Checkout\Cart\CheckoutCartPageLoadedEvent;
use Shopware\Storefront\Page\Checkout\Confirm\CheckoutConfirmPage;
use Shopware\Storefront\Page\Checkout\Confirm\CheckoutConfirmPageLoadedEvent;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class ShowPremiumProducts implements EventSubscriberInterface
{
private CartService $cartService;
private PremiumDefinition $premium;
private ContainerInterface $container;
private FindPremiumProductsInCartInterface $findPremiumProducts;
private CheckIfVariantsAreAvailableInterface $checkIfVariantsAreAvailable;
private LoggerInterface $logger;
private SystemConfigService $systemConfigService;
private MinPriceRepositoryInterface $minPrice;
private RemoveProductsWithMaxMultiAddCounts $removeProductsWithMaxMultiAddCounts;
private TotalPriceRepositoryInterface $totalPrice;
private PremiumAccessControl $premiumAccessControl;
public function __construct(
CartService $cartService,
PremiumDefinition $premium,
ContainerInterface $container,
FindPremiumProductsInCartInterface $findPremiumProducts,
CheckIfVariantsAreAvailableInterface $checkIfVariantsAreAvailable,
LoggerInterface $logger,
SystemConfigService $systemConfigService,
MinPriceRepositoryInterface $minPrice,
RemoveProductsWithMaxMultiAddCounts $removeProductsWithMaxMultiAddCounts,
TotalPriceRepositoryInterface $totalPrice,
PremiumAccessControl $premiumAccessControl
) {
$this->cartService = $cartService;
$this->premium = $premium;
$this->container = $container;
$this->findPremiumProducts = $findPremiumProducts;
$this->checkIfVariantsAreAvailable = $checkIfVariantsAreAvailable;
$this->logger = $logger;
$this->systemConfigService = $systemConfigService;
$this->minPrice = $minPrice;
$this->removeProductsWithMaxMultiAddCounts = $removeProductsWithMaxMultiAddCounts;
$this->totalPrice = $totalPrice;
$this->premiumAccessControl = $premiumAccessControl;
}
public static function getSubscribedEvents(): array
{
return [
CheckoutCartPageLoadedEvent::class => 'onProductsLoaded',
CheckoutConfirmPageLoadedEvent::class => 'onProductsLoaded',
];
}
public function onProductsLoaded($event): void
{
/** @var SalesChannelContext $salesChannelContext */
$salesChannelContext = $event->getSalesChannelContext();
$salesChannel = $event->getSalesChannelContext()->getSalesChannel();
$token = $salesChannelContext->getToken();
$cart = $this->cartService->getCart($token, $salesChannelContext);
if ($this->premiumAccessControl->isAllowed($cart, $salesChannelContext)) {
$ignoreStoreCount = $this->systemConfigService->get(
'BartCPreemiumArticle.config.ignoreStoreCount',
$salesChannel->getId()
);
$multiAdd = $this->systemConfigService->get(
'BartCPreemiumArticle.config.multiadd',
$salesChannel->getId()
);
$multiAddMax = (int) $this->systemConfigService->get(
'BartCPreemiumArticle.config.multiaddMax',
$salesChannel->getId()
);
$multiAddMaxInCart = (int) $this->systemConfigService->get(
'BartCPreemiumArticle.config.multiaddMaxInCart',
$salesChannel->getId()
);
$showOnConfirmPage = $this->systemConfigService->get(
'BartCPreemiumArticle.config.showpremiumonconfirm',
$salesChannel->getId()
);
$showPremiumName = $this->systemConfigService->get(
'BartCPreemiumArticle.config.showpremiumname',
$salesChannel->getId()
);
$premiumProductsInCart = $this->findPremiumProducts->find($cart);
if ($premiumProductsInCart->count() === 0 || $multiAdd) {
/** @var EntityRepository $premiumCollection */
$premiumCollection = $this->container->get($this->premium->getEntityName() . '.repository');
try {
$criteria = new Criteria();
$criteria->addFilter(
new MultiFilter(
NotFilter::CONNECTION_OR,
[
new EqualsFilter(
'salesChannelId',
$salesChannelContext->getSalesChannel()->getId()
),
new EqualsFilter(
'salesChannelId',
null
),
]
)
);
$criteria->addFilter(
new MultiFilter(
NotFilter::CONNECTION_OR,
[
new EqualsFilter(
'customerGroupId',
$salesChannelContext->getCurrentCustomerGroup()->getId()
),
new EqualsFilter(
'customerGroupId',
null
),
]
)
);
$criteria->addFilter(
new EqualsFilter(
'product.active',
1
)
);
if (!$ignoreStoreCount) {
$criteria->addFilter(
new RangeFilter('product.availableStock', [
RangeFilter::GT => 0,
])
);
}
$criteria->addSorting(
new FieldSorting($this->premium->getEntityName() . '.minPrice')
);
$criteria->addAssociation('product.children');
$criteria->addAssociation('product.children.options');
$criteria->addAssociation('product.media');
} catch (InconsistentCriteriaIdsException $e) {
$this->logger->error(
'[Premium Article] ' . $e->getMessage(),
[
'file' => $e->getFile(),
'line' => $e->getLine(),
]
);
return;
}
$premiumArticles = $premiumCollection
->search(
$criteria,
$event->getContext()
)->getElements();
$premiumArticles = $this->checkIfVariantsAreAvailable->remove($premiumArticles);
if ($multiAddMaxInCart > 0
&& $multiAddMaxInCart <= $premiumProductsInCart->getTotalQuantity()) {
$premiumArticles = [];
}
if ($multiAddMax > 0) {
$premiumArticles = $this->removeProductsWithMaxMultiAddCounts->remove($cart, $premiumArticles, $multiAddMax);
}
$totalPrice = $this->totalPrice->get($cart, $salesChannelContext);
$products = $this->findPremiumProducts->find($cart);
$minPrice = $this->minPrice->get($products);
$event->getPage()->addExtension(
'view',
new ArrayEntity(
[
'premium_products' => $premiumArticles,
'total_price' => $totalPrice,
'currency_symbol' => $salesChannelContext->getCurrency()->getSymbol(),
'multiAdd' => $multiAdd,
'multiAddMax' => $multiAddMax,
'$multiAddMaxInCart' => $multiAddMaxInCart,
'minPrice' => $minPrice,
'showPremiumOnConfirmPage' => $showOnConfirmPage,
'showpremiumname' => $showPremiumName,
'isConfirmPage' => (int) ($event->getPage() instanceof CheckoutConfirmPage),
]
)
);
}
}
}
}