<?php declare(strict_types=1);
namespace Neon\Unitarticles\Subscribers;
use Neon\Unitarticles\Events\UnitarticlesEditFormLoadedEvent;
use Neon\Unitarticles\NeonPlatformUnitarticles;
use Neon\Unitarticles\Services\PriceFactorService;
use Shopware\Core\Checkout\Customer\Event\CustomerWishlistProductListingResultEvent;
use Shopware\Core\Content\Cms\CmsPageEntity;
use Shopware\Core\Content\Cms\Events\CmsPageLoadedEvent;
use Shopware\Core\Content\Cms\SalesChannel\Struct\BuyBoxStruct;
use Shopware\Core\Content\Cms\SalesChannel\Struct\ProductBoxStruct;
use Shopware\Core\Content\Cms\SalesChannel\Struct\ProductSliderStruct;
use Shopware\Core\Content\Product\Events\ProductCrossSellingsLoadedEvent;
use Shopware\Core\Content\Product\Events\ProductListingResultEvent;
use Shopware\Core\Content\Product\Events\ProductSearchResultEvent;
use Shopware\Core\Content\Product\Events\ProductSuggestResultEvent;
use Shopware\Core\Content\Product\ProductEntity;
use Shopware\Core\Content\Product\SalesChannel\SalesChannelProductEntity;
use Shopware\Storefront\Page\PageLoadedEvent;
use Shopware\Storefront\Page\Product\ProductPageLoadedEvent;
use Shopware\Storefront\Page\Wishlist\WishlistPageLoadedEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class OnPageLoaded implements EventSubscriberInterface
{
/** @var PriceFactorService */
private $priceFactorService;
/**
* @inheritDoc
*/
public static function getSubscribedEvents()
{
return [
ProductPageLoadedEvent::class => 'onPageLoaded',
'Swag\CmsExtensions\Storefront\Pagelet\Quickview\QuickviewPageletLoadedEvent' => 'onPageletLoaded',
ProductListingResultEvent::class => 'onProductListingResultCreated',
ProductSearchResultEvent::class => 'onProductSearchResult',
ProductSuggestResultEvent::class => 'onProductSuggestPageLoaded',
ProductCrossSellingsLoadedEvent::class => 'onCrossSellingLoaded',
CmsPageLoadedEvent::class => 'onCmsPageLoaded',
UnitarticlesEditFormLoadedEvent::class => 'onUnitarticlesEditFormLoaded',
CustomerWishlistProductListingResultEvent::class => 'onCustomerWishlistLoaded'
];
}
public function __construct($priceFactorService)
{
$this->priceFactorService = $priceFactorService;
}
public function onUnitarticlesEditFormLoaded(UnitarticlesEditFormLoadedEvent $event)
{
$this->adjustCustomFields($event->getProduct());
}
public function onPageLoaded(PageLoadedEvent $event)
{
$this->adjustCustomFields($event->getPage()->getProduct());
}
public function onPageletLoaded($event)
{
$this->adjustCustomFields($event->getPagelet()->getProduct());
}
public function onCustomerWishlistLoaded(CustomerWishlistProductListingResultEvent $event)
{
$this->adjustCustomFieldsForProducts($event->getResult()->getEntities());
}
public function onProductListingResultCreated(ProductListingResultEvent $event)
{
$this->adjustCustomFieldsForProducts($event->getResult()->getEntities());
}
public function onProductSearchResult(ProductSearchResultEvent $event)
{
$this->adjustCustomFieldsForProducts($event->getResult()->getEntities());
}
public function onProductSuggestPageLoaded(ProductSuggestResultEvent $event)
{
$this->adjustCustomFieldsForProducts($event->getResult()->getEntities());
}
public function onCrossSellingLoaded(ProductCrossSellingsLoadedEvent $event)
{
foreach ($event->getCrossSellings()->getElements() as $element) {
$this->adjustCustomFieldsForProducts($element->getProducts());
}
}
public function onCmsPageLoaded(CmsPageLoadedEvent $event)
{
/** @var CmsPageEntity $r */
foreach ($event->getResult() as $r) {
foreach ($r->getSections() as $s) {
foreach ($s->getBlocks() as $b) {
foreach ($b->getSlots() as $sl) {
if ($sl->getData() instanceof ProductBoxStruct ||
$sl->getData() instanceof BuyBoxStruct) {
/** @var ProductBoxStruct $productStruct */
$productStruct = $sl->getData();
$this->adjustCustomFields($productStruct->getProduct());
}
if ($sl->getData() instanceof ProductSliderStruct) {
/** @var ProductSliderStruct $productSliderStruct */
$productSliderStruct = $sl->getData();
/** @var ProductEntity $productStruct */
foreach ($productSliderStruct->getProducts() as $productStruct) {
$this->adjustCustomFields($productStruct);
}
}
}
}
}
}
}
/**
* @param $entities
*/
private function adjustCustomFieldsForProducts($entities): void
{
foreach ($entities as $product) {
$this->adjustCustomFields($product);
}
}
/**
* @param SalesChannelProductEntity|ProductEntity $product
*/
private function adjustCustomFields($product): void
{
if ($product !== null && array_key_exists(NeonPlatformUnitarticles::CUSTOMFIELD_ISUNITARTICLE, $product->getCustomFields())) {
$this->addFactorToCustomFields($product);
$this->limitMaxAmountToAvailableStock($product);
}
}
/**
* @param SalesChannelProductEntity|ProductEntity $product
*/
private function addFactorToCustomFields($product)
{
$customFields = $product->getCustomFields();
$customFields[NeonPlatformUnitarticles::CUSTOMFIELD_CALCULATEDPRICEFACTOR] = $this->priceFactorService->calculateWithCustomFields($customFields);
$product->setCustomFields($customFields);
}
/**
* @param SalesChannelProductEntity $product
*/
private function limitMaxAmountToAvailableStock($product)
{
$customFields = $product->getCustomFields();
$maxPurchase = $product->getCalculatedMaxPurchase() / $customFields[NeonPlatformUnitarticles::CUSTOMFIELD_CALCULATEDPRICEFACTOR];
if (array_key_exists(NeonPlatformUnitarticles::CUSTOMFIELD_ISUNITARTICLE, $customFields)
&& (array_key_exists(NeonPlatformUnitarticles::CUSTOMFIELD_HIDEQUANTITYSELECTION, $customFields) && $customFields[NeonPlatformUnitarticles::CUSTOMFIELD_HIDEQUANTITYSELECTION])
&& (array_key_exists(NeonPlatformUnitarticles::CUSTOMFIELD_MAXVALUE, $customFields) && $customFields[NeonPlatformUnitarticles::CUSTOMFIELD_MAXVALUE] > $maxPurchase)) {
$customFields[NeonPlatformUnitarticles::CUSTOMFIELD_MAXVALUE] = $maxPurchase;
$product->setCustomFields($customFields);
}
if (array_key_exists(NeonPlatformUnitarticles::CUSTOMFIELD_MINVALUE, $customFields) &&
array_key_exists(NeonPlatformUnitarticles::CUSTOMFIELD_MAXVALUE, $customFields) &&
$customFields[NeonPlatformUnitarticles::CUSTOMFIELD_MINVALUE] > $customFields[NeonPlatformUnitarticles::CUSTOMFIELD_MAXVALUE]) {
$product->setAvailableStock(0);
}
}
}