<?php declare(strict_types=1);namespace Acris\CmsPreview\Subscriber;use Acris\CmsPreview\Components\Struct\CmsPreviewPageStruct;use Shopware\Core\Content\Product\SalesChannel\ProductAvailableFilter;use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\MultiFilter;use Shopware\Core\System\SalesChannel\Event\SalesChannelProcessCriteriaEvent;use Shopware\Core\System\SystemConfig\SystemConfigService;use Symfony\Component\EventDispatcher\EventSubscriberInterface;class SalesChannelProductCriteriaSubscriber implements EventSubscriberInterface{ private SystemConfigService $systemConfigService; public function __construct(SystemConfigService $systemConfigService) { $this->systemConfigService = $systemConfigService; } public static function getSubscribedEvents(): array { return [ 'sales_channel.product.process.criteria' => 'onProductCriteriaLoaded' ]; } public function onProductCriteriaLoaded(SalesChannelProcessCriteriaEvent $event): void { $salesChannelContext = $event->getSalesChannelContext(); if($salesChannelContext->hasExtension(CmsPreviewPageStruct::EXTENSION_CMS_PREVIEW_PAGE) === true && $salesChannelContext->getExtension(CmsPreviewPageStruct::EXTENSION_CMS_PREVIEW_PAGE) instanceof CmsPreviewPageStruct) { /** @var CmsPreviewPageStruct $cmsPagePreviewStruct */ $cmsPagePreviewStruct = $salesChannelContext->getExtension(CmsPreviewPageStruct::EXTENSION_CMS_PREVIEW_PAGE); $criteria = $event->getCriteria(); $showInactiveProducts = $this->systemConfigService->get('AcrisCmsPreviewCS.config.showInactiveProductsInCategory', $salesChannelContext->getSalesChannelId()); // plugin config: show inactive products for category preview if ($showInactiveProducts === true && empty($cmsPagePreviewStruct->getProductId()) === true) { if ($this->hasAvailableFilter($criteria) === true) { $newCriteriaFilters = []; foreach ($criteria->getFilters() as $filter) { if (!$filter instanceof ProductAvailableFilter) { array_push($newCriteriaFilters, $filter); } if ($filter instanceof ProductAvailableFilter) { foreach ($filter->getQueries() as $query) { if (!empty($query->getField()) && $query->getField() !== 'product.active') { array_push($newCriteriaFilters, $query); } } } } if (!empty($newCriteriaFilters)) { $criteria->resetFilters(); $criteria->addFilter(new MultiFilter( MultiFilter::CONNECTION_OR, [ new EqualsFilter('product.active', true), new EqualsFilter('product.active', false) ] )); foreach ($newCriteriaFilters as $key => $filter) { if ($filter instanceof EqualsFilter) { $criteria->addFilter(new EqualsFilter($filter->getField(), $filter->getValue())); } } } } $originalLimit = $criteria->getLimit(); $modifiedLimit = $originalLimit ?? 20; $criteria->setLimit($modifiedLimit); } // always show inactive products (and variant) in previews if (!empty($cmsPagePreviewStruct->getProductId())) { if (empty($criteria->getTitle()) === true || strpos($criteria->getTitle(), 'product-detail-route') === true || $criteria->getTitle() === 'product-detail-route') { $criteria->resetFilters(); } } } } private function hasAvailableFilter(Criteria $criteria): bool { foreach ($criteria->getFilters() as $filter) { if ($filter instanceof ProductAvailableFilter) { return true; } } return false; }}