<?php
namespace Abas\AbasConnector\Subscribers\Search;
use Abas\AbasConnector\Service\Customer\AbasCustomerItemNumberService;
use RuntimeException;
use Shopware\Core\Content\Product\Events\ProductSearchCriteriaEvent;
use Shopware\Core\Content\Product\Events\ProductSuggestCriteriaEvent;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\ContainsFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsAnyFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Query\ScoreQuery;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class AbasSearchSubscriber implements EventSubscriberInterface
{
/**
* @var AbasCustomerItemNumberService
*/
private AbasCustomerItemNumberService $abasCustomerItemNumberService;
/**
*
* @param AbasCustomerItemNumberService $abasCustomerItemNumberService
*/
public function __construct(AbasCustomerItemNumberService $abasCustomerItemNumberService)
{
$this->abasCustomerItemNumberService = $abasCustomerItemNumberService;
}
/**
* @return string[]
*/
public static function getSubscribedEvents(): array
{
return [
ProductSearchCriteriaEvent::class => 'addSearchCriteria',
ProductSuggestCriteriaEvent::class => 'addSearchSuggestCriteria'
];
}
/**
* @param ProductSearchCriteriaEvent|ProductSuggestCriteriaEvent $event
* @return void
*/
private function handleSearchCriteriaUpdate($event): void
{
$criteria = $event->getCriteria();
$customer = $event->getSalesChannelContext()->getCustomer();
$request = $event->getRequest();
$searchTerm = $request->get('search');
if ($customer === null) {
$this->updateFilters($criteria, $searchTerm);
$this->updateQueries($request->getQueryString(), $criteria, $searchTerm);
} else {
$customerProductList = $this->abasCustomerItemNumberService->loadCustomerItemsByOwnNumber(
$searchTerm,
$customer->getCustomerNumber(),
10
);
if (empty($customerProductList) && !empty($searchTerm)) {
$this->updateFilters($criteria, $searchTerm);
$this->updateQueries($request->getQueryString(), $criteria, $searchTerm);
}
}
}
/**
* @param ProductSearchCriteriaEvent $event
*
* @return void
* @throws RuntimeException
*/
public function addSearchCriteria(ProductSearchCriteriaEvent $event): void
{
$this->handleSearchCriteriaUpdate($event);
}
/**
* @param ProductSuggestCriteriaEvent $event
*
* @return void
* @throws RuntimeException
*/
public function addSearchSuggestCriteria(ProductSuggestCriteriaEvent $event): void
{
$this->handleSearchCriteriaUpdate($event);
}
/**
* @param Criteria $criteria
* @param string $searchTerm
* @return void
*/
protected function updateFilters(Criteria $criteria, string $searchTerm): void
{
$newFilters = null;
$filters = $criteria->getFilters();
foreach ($filters as $filter) {
if ($filter instanceof EqualsAnyFilter && $filter->getField() === "product.searchKeywords.keyword") {
$values = $filter->getValue();
$values[] = $searchTerm;
$newFilters[] = new EqualsAnyFilter("product.searchKeywords.keyword", $values);
} else {
$newFilters[] = $filter;
}
}
if ($newFilters) {
$criteria->resetFilters();
foreach ($newFilters as $filter) {
$criteria->addFilter($filter);
}
}
}
/**
* @param string $origQuery
* @param Criteria $criteria
* @param string $searchTerm
* @return void
*/
protected function updateQueries(string $origQuery, Criteria $criteria, string $searchTerm)
{
$newQueries = null;
$origQuery = explode("=", $origQuery)[1];
$queries = $criteria->getQueries();
foreach ($queries as $query) {
if ($query instanceof ScoreQuery && $query->getQuery()->getField() === "product.searchKeywords.keyword") {
$values[] = $origQuery;
$score = $query->getScore();
$scoreField = $query->getScoreField();
$newQueries[] = new ScoreQuery(
new ContainsFilter(
"product.searchKeywords.keyword",
$searchTerm
),
$score,
$scoreField
);
} else {
$newQueries[] = $query;
}
}
if ($newQueries) {
$criteria->resetQueries();
foreach ($newQueries as $query) {
$criteria->addQuery($query);
}
}
}
}