<?php declare(strict_types=1);
namespace Samson\Subscriber;
/***
*
* This file is part of the "SAMSON Shop" project.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* (c) 2022
*
***/
use Shopware\Core\Content\Product\SalesChannel\Price\AbstractProductPriceCalculator;
use Shopware\Core\Content\Product\SalesChannel\SalesChannelProductEntity;
use Shopware\Core\System\SalesChannel\Entity\SalesChannelEntityLoadedEvent;
use Shopware\Core\System\SalesChannel\SalesChannelContext;
use Shopware\Core\System\SystemConfig\SystemConfigService;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class SalesChannelProductSubscriber implements EventSubscriberInterface
{
private SystemConfigService $systemConfigService;
private AbstractProductPriceCalculator $calculator;
public function __construct(
SystemConfigService $systemConfigService,
AbstractProductPriceCalculator $calculator
) {
$this->systemConfigService = $systemConfigService;
$this->calculator = $calculator;
}
public static function getSubscribedEvents(): array
{
return [
'sales_channel.product.loaded' => ['loaded', -1],
];
}
public function loaded(SalesChannelEntityLoadedEvent $event): void
{
$this->calculator->calculate($event->getEntities(), $event->getSalesChannelContext());
/** @var SalesChannelProductEntity $product */
foreach ($event->getEntities() as $product) {
$product->setCalculatedMaxPurchase(
$this->calculateMaxPurchase($product, $event->getSalesChannelContext()->getSalesChannel()->getId())
);
$this->markAsNew($event->getSalesChannelContext(), $product);
}
}
private function calculateMaxPurchase(SalesChannelProductEntity $product, string $salesChannelId): int
{
$fallback = $this->systemConfigService->getInt('core.cart.maxQuantity', $salesChannelId);
$max = $product->getMaxPurchase() ?? $fallback;
if ($product->getIsCloseout() && $product->getAvailableStock() < $max) {
$max = (int) $product->getAvailableStock();
}
$steps = $product->getPurchaseSteps() ?? 1;
$min = $product->getMinPurchase() ?? 1;
// the amount of times the purchase step is fitting in between min and max added to the minimum
$max = \floor(($max - $min) / $steps) * $steps + $min;
return (int) \max($max, 0);
}
private function markAsNew(SalesChannelContext $context, SalesChannelProductEntity $product): void
{
$markAsNewDayRange = $this->systemConfigService->get('core.listing.markAsNew', $context->getSalesChannel()->getId());
$now = new \DateTime();
/* @var SalesChannelProductEntity $product */
$product->setIsNew(
$product->getReleaseDate() instanceof \DateTimeInterface
&& $product->getReleaseDate()->diff($now)->days <= $markAsNewDayRange
);
}
}