<?php
declare(strict_types=1);
/**
* LeopardSearchExtension
* Copyright (c) Die Leoparden GmbH
*/
namespace LeopardSearchExtension\Subscriber;
use LeopardSearchExtension\LeopardSearchExtension;
use LeopardSearchExtension\Util\IdStruct;
use Shopware\Core\Content\Product\Events\ProductListingCriteriaEvent;
use Shopware\Core\Content\Product\Events\ProductListingResolvePreviewEvent;
use Shopware\Core\Content\Product\Events\ProductSuggestCriteriaEvent;
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\Filter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\NotFilter;
use Shopware\Core\System\SalesChannel\Event\SalesChannelProcessCriteriaEvent;
class ProductSuggestCriteriaSubscriber extends AbstractSubscriber
{
/**
* {@inheritDoc}
*/
public static function getSubscribedEvents(): array
{
return [
ProductSuggestCriteriaEvent::class => 'onProductSuggestCriteria',
'sales_channel.product.process.criteria' => 'onSalesChannelProcessCriteria',
ProductListingResolvePreviewEvent::class => 'onProductListingResolvePreview',
];
}
/**
* @param ProductListingCriteriaEvent $event
*/
public function onProductSuggestCriteria(ProductListingCriteriaEvent $event): void
{
$productEntity = $this->onSearchCriteria($event);
if (is_null($productEntity)) {
return;
}
$event->getContext()->addExtension(LeopardSearchExtension::SUGGEST_EXTENSION_PRODUCT_ID, new IdStruct($productEntity->getId()));
$event->getRequest()->query->set('search', $productEntity->getProductNumber());
$criteria = $event->getCriteria();
$this->filterNonAvailableFilter($criteria);
$criteria->addFilter(
new EqualsFilter(
'productNumber',
$productEntity->getProductNumber()
)
);
}
public function onSalesChannelProcessCriteria(SalesChannelProcessCriteriaEvent $event): void
{
if (!$event->getContext()->hasExtension(LeopardSearchExtension::SUGGEST_EXTENSION_PRODUCT_ID)) {
return;
}
$this->removeDisplayGroupFilter($event->getCriteria());
}
public function onProductListingResolvePreview(ProductListingResolvePreviewEvent $event): void
{
/** @var IdStruct|null $idStruct */
$idStruct = $event->getContext()->getExtension(LeopardSearchExtension::SUGGEST_EXTENSION_PRODUCT_ID);
if (!$idStruct instanceof IdStruct) {
return;
}
// Affects variant product
// Set mapping of product to self instead of chosen variant of "Storefront presentation" configuration
$productId = $idStruct->id;
$event->replace($productId, $productId);
// Last use of the extension
$event->getContext()->removeExtension(LeopardSearchExtension::SUGGEST_EXTENSION_PRODUCT_ID);
}
/**
* For variant products remove the displayGroup filter
* ??? Something to do with the "Storefront presentation" configuration
*
* @param Criteria $criteria
*
* @return void
*/
private function removeDisplayGroupFilter(Criteria $criteria): void
{
$filters = $criteria->getFilters();
$criteria->resetFilters();
foreach ($filters as $filter) {
if (!($filter instanceof NotFilter)) {
$criteria->addFilter($filter);
continue;
}
$add = true;
foreach ($filter->getQueries() as $query) {
if ($query instanceof EqualsFilter && $query->getField() === 'displayGroup') {
$add = false;
break;
}
}
if ($add) {
$criteria->addFilter($filter);
}
}
}
/**
* @param Criteria $criteria
*
* @return void
*/
private function filterNonAvailableFilter(Criteria $criteria): void
{
/** @var Filter[] $filters_original */
$filters_original = $criteria->getFilters();
$criteria->resetQueries();
$criteria->resetFilters();
/** @var Filter $filter */
foreach ($filters_original as $filter) {
if ($filter instanceof ProductAvailableFilter) {
$criteria->addFilter($filter);
}
}
}
}