<?php declare(strict_types=1);
namespace Uandi\EFB\Storefront\Subscriber;
use Shopware\Core\Content\Product\SalesChannel\Price\AbstractProductPriceCalculator;
use Shopware\Core\Content\Product\SalesChannel\SalesChannelProductEntity;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
use Shopware\Core\System\SalesChannel\Entity\SalesChannelRepositoryInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Uandi\EFB\Storefront\Trait\LockExtensionTrait;
use VioCustomerPrice\Event\CustomerPriceEvent;
class CustomerPriceSubscriber implements EventSubscriberInterface
{
use LockExtensionTrait;
private const LOCK = self::class . '_lock';
private SalesChannelRepositoryInterface $productRepository;
private AbstractProductPriceCalculator $priceCalculator;
public function __construct(
SalesChannelRepositoryInterface $productRepository,
AbstractProductPriceCalculator $priceCalculator
) {
$this->productRepository = $productRepository;
$this->priceCalculator = $priceCalculator;
}
public static function getSubscribedEvents(): array
{
return [
CustomerPriceEvent::class => 'recalculateCheapestPrice',
];
}
public function recalculateCheapestPrice(CustomerPriceEvent $event): void
{
$product = $event->getProduct();
$context = $event->getContext();
if ($this->locked($context, self::LOCK)) {
return;
}
if (null === $product->getParentId()) {
return;
}
$variants = $this->productRepository->searchIds(
(new Criteria())->addFilter(new EqualsFilter('active', true))->addFilter(new EqualsFilter('parentId', $product->getParentId())),
$context
);
if ($variants->getTotal() <= 1) {
return;
}
$this->lock($context, self::LOCK);
$products = $this->productRepository->search((new Criteria($variants->getIds()))->addFilter(new EqualsFilter('active', true)), $context);
$this->unlock($context, self::LOCK);
$products->sort(function (SalesChannelProductEntity $a, SalesChannelProductEntity $b) {
return ($a->getCalculatedCheapestPrice()->getTotalPrice()
- $b->getCalculatedCheapestPrice()->getTotalPrice())
* 1000;
});
$product->setCalculatedCheapestPrice($products->first()->getCalculatedCheapestPrice());
}
}