<?php declare(strict_types=1);
/**
* Shopware
* Copyright © 2020
*
* @category Shopware
* @package SwpPriceOnRequestSix
* @subpackage Frontend.php
*
* @copyright 2020 Iguana-Labs GmbH
* @author Module Factory <info at module-factory.com>
* @license https://www.module-factory.com/eula
*/
namespace Swp\PriceOnRequestSix\Subscriber;
use Shopware\Core\Checkout\Cart\Price\QuantityPriceCalculator;
use Shopware\Core\Checkout\Cart\Price\Struct\CalculatedPrice;
use Shopware\Core\Checkout\Cart\Price\Struct\QuantityPriceDefinition;
use Shopware\Core\Checkout\Cart\Price\Struct\ReferencePriceDefinition;
use Shopware\Core\Content\Cms\Events\CmsPageLoadedEvent;
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\SalesChannelRepository;
use Shopware\Core\System\SalesChannel\SalesChannelContext;
use Shopware\Core\System\SystemConfig\SystemConfigService;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class Frontend implements EventSubscriberInterface
{
/**
* @var SalesChannelRepository
*/
private $productRepository;
/**
* @var SystemConfigService
*/
private $configService;
private QuantityPriceCalculator $calculator;
private AbstractProductPriceCalculator $priceCalculator;
public function __construct(
SalesChannelRepository $productRepository,
SystemConfigService $configService,
QuantityPriceCalculator $calculator,
AbstractProductPriceCalculator $priceCalculator
)
{
$this->productRepository = $productRepository;
$this->configService = $configService;
$this->calculator = $calculator;
$this->priceCalculator = $priceCalculator;
}
public static function getSubscribedEvents()
{
// Return the events to listen to as array like this: <event to listen to> => <method to execute>
return [
CmsPageLoadedEvent::class => 'onCmsPageLoaded'
];
}
/**
* @param CmsPageLoadedEvent $event
* @return mixed
*/
public function onCmsPageLoaded(CmsPageLoadedEvent $event)
{
$page = $event->getResult()->getVars();
$request = $event->getRequest();
if (empty($request->get('priceOnRequest'))) {
return;
}
$criteria = new Criteria([]);
$criteria->addFilter(new EqualsFilter('productNumber', $request->get('priceOnRequest')));
$results = $this->productRepository->search($criteria, $event->getSalesChannelContext());
if ($results->getTotal() == 0) {
return;
}
/** @var SalesChannelProductEntity $product */
foreach ($results->getElements() as $product) {
if ($product->getProductNumber() == $request->get('priceOnRequest')) {
$contactPageId = $this->configService->get('core.basicInformation.contactPage');
if (!empty($product->getTranslated()) && !empty($product->getTranslated()['name'])) {
$productName = $product->getTranslated()['name'];
} else {
$productName = $product->getName();
}
$quantity = intval($request->get('quantity'));
$definition = $this->getPriceDefinition($product, $event->getSalesChannelContext(), $quantity);
$price = $this->calculator->calculate($definition, $event->getSalesChannelContext());
$extensions = $page['elements'][$contactPageId]->getExtensions();
$extensions['priceOnRequestSubject'] = $productName . " (" . $request->get('priceOnRequest') . ")";
$extensions['priceOnRequest'] = \json_encode([
'name' => $productName,
'id' => $product->getId(),
'price' => $price->getUnitPrice(),
'brand' => $request->get('manufacturer'),
'category' => $request->get('category'),
'variant' => $request->get('variation'),
'quantity' => $quantity,
]);
$page['elements'][$contactPageId]->setExtensions($extensions);
}
}
}
private function getPriceDefinition(SalesChannelProductEntity $product, SalesChannelContext $context, int $quantity): QuantityPriceDefinition
{
$this->priceCalculator->calculate([$product], $context);
if ($product->getCalculatedPrices()->count() === 0) {
return $this->buildPriceDefinition($product->getCalculatedPrice(), $quantity);
}
// keep loop reference to $price variable to get last quantity price in case of "null"
$price = $product->getCalculatedPrice();
foreach ($product->getCalculatedPrices() as $price) {
if ($quantity <= $price->getQuantity()) {
break;
}
}
return $this->buildPriceDefinition($price, $quantity);
}
private function buildPriceDefinition(CalculatedPrice $price, int $quantity): QuantityPriceDefinition
{
$definition = new QuantityPriceDefinition($price->getUnitPrice(), $price->getTaxRules(), $quantity);
if ($price->getListPrice() !== null) {
$definition->setListPrice($price->getListPrice()->getPrice());
}
if ($price->getReferencePrice() !== null) {
$definition->setReferencePriceDefinition(
new ReferencePriceDefinition(
$price->getReferencePrice()->getPurchaseUnit(),
$price->getReferencePrice()->getReferenceUnit(),
$price->getReferencePrice()->getUnitName()
)
);
}
return $definition;
}
}