<?php
namespace Crehler\ListingBanner\Subscriber;
use Crehler\ListingBanner\Core\Content\ListingBanners\SalesChannel\AbstractListingBannersRoute;
use Crehler\ListingBanner\Entity\BannerEntity\BannerEntity;
use Crehler\ListingBanner\Entity\BannerEntity\BannerEntityCollection;
use Crehler\ListingBanner\Event\ProductListingCmsResolverEvent;
use Crehler\ListingBanner\Struct\ProductBannerStruct;
use Shopware\Core\Content\Cms\Events\CmsPageLoadedEvent;
use Shopware\Core\Content\Product\Events\ProductListingCriteriaEvent;
use Shopware\Core\Content\Product\Events\ProductListingResultEvent;
use Shopware\Core\Framework\Context;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class NavigationPageLoadSubscriber implements EventSubscriberInterface
{
public const DEFAULT_LIMIT = 24;
protected AbstractListingBannersRoute $listingBannersRoute;
protected EntityRepository $categoryRepository;
protected ?ProductBannerStruct $productBanner;
/**
* @param AbstractListingBannersRoute $listingBannersRoute
* @param EntityRepository $categoryRepository
*/
public function __construct(
AbstractListingBannersRoute $listingBannersRoute,
EntityRepository $categoryRepository
)
{
$this->listingBannersRoute = $listingBannersRoute;
$this->categoryRepository = $categoryRepository;
$this->productBanner = null;
}
public static function getSubscribedEvents(): array
{
return [
ProductListingCriteriaEvent::class => ['onProductListingCriteria', 100],
ProductListingCmsResolverEvent::class => ['onProductProductListingCmsResolver', 5000],
ProductListingResultEvent::class => ['onProductListingResult', 100],
CmsPageLoadedEvent::class => 'onCmsPageLoadedEvent'
];
}
public function onCmsPageLoadedEvent(CmsPageLoadedEvent $event)
{
if(!$this->productBanner) {
return;
}
$event->getResult()->addExtension('crehlerBanner', $this->productBanner);
}
public function onProductListingResult(ProductListingResultEvent $event): void
{
if(!$this->productBanner) {
return;
}
$event->getResult()->addExtension('crehlerBanner', $this->productBanner);
}
public function onProductProductListingCmsResolver(
ProductListingCmsResolverEvent $event
): void
{
$page = (int) $event->getRequest()->query->get('p', 1);
if ($page > 1) {
return;
}
$categoryId = $event->getRequest()->attributes->get('navigationId');
$salesChannelContext = $event->getSalesChannelContext();
if (!$categoryId || $this->isArrangmentCategory($categoryId, $salesChannelContext->getContext())) {
return;
}
$criteria = (new Criteria());
$banners = $this->listingBannersRoute->load($categoryId, $criteria, $salesChannelContext)->getBanners();
if ($banners->count() === 0) {
return;
}
$bannerArray = $this->buildBanners($banners);
$this->productBanner = $bannerArray;
}
public function onProductListingCriteria(ProductListingCriteriaEvent $event): void
{
if (!$this->productBanner) {
return;
}
$bannerArray = $this->productBanner;
if ($event->getCriteria()->getOffset() === 0) {
$event->getCriteria()->setLimit(self::DEFAULT_LIMIT - count($bannerArray->getDesktopMedia()));
$event->getRequest()->query->set('limit', self::DEFAULT_LIMIT - count($bannerArray->getDesktopMedia()));
} else {
$event->getCriteria()->setOffset($event->getCriteria()->getOffset() - count($bannerArray->getDesktopMedia()));
$event->getRequest()->query->set('offset', $event->getCriteria()->getOffset() - count($bannerArray->getDesktopMedia()));
$event->getRequest()->query->set('bannerCount', count($bannerArray->getDesktopMedia()));
}
$event->getRequest()->request->set('criteriaGap', count($bannerArray->getDesktopMedia()));
}
protected function buildBanners(BannerEntityCollection $banners): ProductBannerStruct
{
$productBanner = new ProductBannerStruct();
foreach ($banners as $banner) {
$this->buildProductBanner($banner, $productBanner);
}
return $productBanner;
}
protected function buildProductBanner(BannerEntity $banner, ProductBannerStruct $productBanner): void
{
foreach ($banner->getMedia()->getElements() as $media) {
if ($media->isDesktop()) {
$productBanner->addDesktopMediaItem($media);
} else {
$productBanner->addMobileMediaItem($media);
}
}
}
protected function isArrangmentCategory(string $categoryId, Context $context): bool
{
return $this->categoryRepository->searchIds(
(new Criteria([$categoryId]))
->addFilter(new EqualsFilter('customFields.crehler_category_is_arrangements', "1")),
$context
)->getTotal() > 0;
}
}