<?php
declare(strict_types=1);
namespace App\Controller\Shop;
use App\Assigner\NoResultSearchAssigner;
use App\Entity\Statistics\NoResultSearch;
use App\Events\ProductViewItemListEvent;
use App\Repository\Statistics\NoResultSearchRepository;
use App\Service\SpecialCharactersService;
use Doctrine\ORM\EntityManagerInterface;
use MonsieurBiz\SyliusSearchPlugin\Exception\UnknownRequestTypeException;
use MonsieurBiz\SyliusSearchPlugin\Model\Documentable\DocumentableInterface;
use MonsieurBiz\SyliusSearchPlugin\Search\Request\RequestConfiguration;
use MonsieurBiz\SyliusSearchPlugin\Search\Request\RequestInterface;
use MonsieurBiz\SyliusSearchPlugin\Search\Search;
use MonsieurBiz\SyliusSettingsPlugin\Settings\SettingsInterface;
use Sylius\Bundle\ResourceBundle\Controller\Parameters;
use Sylius\Bundle\ResourceBundle\Controller\ParametersParserInterface;
use Sylius\Component\Channel\Context\ChannelContextInterface;
use Sylius\Component\Currency\Context\CurrencyContextInterface;
use Sylius\Component\Locale\Context\LocaleContextInterface;
use Sylius\Component\Registry\ServiceRegistryInterface;
use Sylius\Component\Taxonomy\Repository\TaxonRepositoryInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Intl\Currencies;
class SearchController extends AbstractController
{
private TaxonRepositoryInterface $taxonRepository;
private Search $search;
private CurrencyContextInterface $currencyContext;
private LocaleContextInterface $localeContext;
private ChannelContextInterface $channelContext;
private SettingsInterface $searchSettings;
private ServiceRegistryInterface $documentableRegistry;
private ParametersParserInterface $parametersParser;
private NoResultSearchAssigner $noResultSearchAssigner;
private NoResultSearchRepository $noResultSearchRepository;
private SpecialCharactersService $specialCharactersService;
private EntityManagerInterface $entityManager;
private EventDispatcherInterface $eventDispatcher;
public function __construct(TaxonRepositoryInterface $taxonRepository, Search $search, CurrencyContextInterface $currencyContext, LocaleContextInterface $localeContext, ChannelContextInterface $channelContext, SettingsInterface $searchSettings, ServiceRegistryInterface $documentableRegistry, ParametersParserInterface $parametersParser, NoResultSearchAssigner $noResultSearchAssigner, NoResultSearchRepository $noResultSearchRepository, SpecialCharactersService $specialCharactersService, EntityManagerInterface $entityManager, EventDispatcherInterface $eventDispatcher)
{
$this->taxonRepository = $taxonRepository;
$this->search = $search;
$this->currencyContext = $currencyContext;
$this->localeContext = $localeContext;
$this->channelContext = $channelContext;
$this->searchSettings = $searchSettings;
$this->documentableRegistry = $documentableRegistry;
$this->parametersParser = $parametersParser;
$this->noResultSearchAssigner = $noResultSearchAssigner;
$this->noResultSearchRepository = $noResultSearchRepository;
$this->specialCharactersService = $specialCharactersService;
$this->entityManager = $entityManager;
$this->eventDispatcher = $eventDispatcher;
}
public function searchAction(Request $request, string $query): Response
{
/** @var DocumentableInterface $documentable */
$documentable = $this->documentableRegistry->get('search.documentable.monsieurbiz_product');
$requestConfiguration = new RequestConfiguration(
$request,
RequestInterface::SEARCH_TYPE,
$documentable,
$this->searchSettings,
$this->channelContext
);
$result = $this->search->search($requestConfiguration);
if (count($result) === 0) {
$this->noResultSearchAssigner->assign(urldecode($query));
// relancer la recherche avec une query associée si elle existe
/** @var NoResultSearch $noResultSearch */
$noResultSearch = $this->noResultSearchRepository->findOneBy(['search' => trim($this->specialCharactersService->replaceAccentedCharacters(urldecode($query)))]);
if ($noResultSearch && $noResultSearch->getAssociatedWord()) {
return $this->redirectToRoute('monsieurbiz_search_search', ['query' => $noResultSearch->getAssociatedWord()]);
}
} else {
// rechercher si une noresultsearch existe et la supprimer car il y a maintenant des résultats
/** @var NoResultSearch $noResultSearch */
$noResultSearch = $this->noResultSearchRepository->findOneBy(['search' => trim($this->specialCharactersService->replaceAccentedCharacters(urldecode($query)))]);
if ($noResultSearch) {
$this->entityManager->remove($noResultSearch);
$this->entityManager->flush();
}
}
return $this->render('@MonsieurBizSyliusSearchPlugin/Search/result.html.twig', [
'documentable' => $result->getDocumentable(),
'requestConfiguration' => $requestConfiguration,
'query' => urldecode($query),
'query_url' => $query,
'result' => $result,
'currencySymbol' => Currencies::getSymbol($this->currencyContext->getCurrencyCode(), $this->localeContext->getLocaleCode()),
]);
}
/**
* Post search.
*/
public function postAction(Request $request): RedirectResponse
{
$query = $request->request->get('query');
return $this->redirect(
$this->generateUrl(
'monsieurbiz_search_search',
['query' => str_replace('%2F', '/', urlencode($query))]
)
);
}
/**
* Perform the instant search action & display results.
*/
public function instantAction(Request $request): Response
{
$results = [];
/** @var DocumentableInterface $documentable */
foreach ($this->documentableRegistry->all() as $documentable) {
if (!(bool) $this->searchSettings->getCurrentValue($this->channelContext->getChannel(), null, 'instant_search_enabled__' . $documentable->getIndexCode())) {
continue;
}
$requestConfiguration = new RequestConfiguration(
$request,
RequestInterface::INSTANT_TYPE,
$documentable,
$this->searchSettings,
$this->channelContext,
new Parameters($this->parametersParser->parseRequestValues($request->attributes->get('_sylius', []), $request))
);
try {
$results[] = $this->search->search($requestConfiguration);
} catch (UnknownRequestTypeException $e) {
continue;
}
}
$bNoResult = true;
if (!empty($results)) {
foreach ($results as $result) {
if ($result->count() == 0) {
} else {
$bNoResult = false;
}
}
}
if ($bNoResult == true) {
$query = $request->get('query') ?? '';
if ($query != '') {
$this->noResultSearchAssigner->assign(urldecode($query));
$noResultSearch = $this->noResultSearchRepository->findOneBy(['search' => trim($this->specialCharactersService->replaceAccentedCharacters(urldecode($query)))]);
if ($noResultSearch && $noResultSearch->getAssociatedWord()) {
$request->request->set('query', $noResultSearch->getAssociatedWord());
foreach ($this->documentableRegistry->all() as $documentable) {
$requestConfiguration = new RequestConfiguration(
$request,
RequestInterface::INSTANT_TYPE,
$documentable,
$this->searchSettings,
$this->channelContext,
new Parameters($this->parametersParser->parseRequestValues($request->attributes->get('_sylius', []), $request))
);
try {
$results[] = $this->search->search($requestConfiguration);
} catch (UnknownRequestTypeException $e) {
continue;
}
}
}
}
}
return $this->render('@MonsieurBizSyliusSearchPlugin/Instant/result.html.twig', [
'results' => $results,
'currencySymbol' => Currencies::getSymbol($this->currencyContext->getCurrencyCode(), $this->localeContext->getLocaleCode()),
]);
}
public function taxonAction(Request $request): Response
{
/** @var DocumentableInterface $documentable */
$documentable = $this->documentableRegistry->get('search.documentable.monsieurbiz_product');
$requestConfiguration = new RequestConfiguration(
$request,
RequestInterface::TAXON_TYPE,
$documentable,
$this->searchSettings,
$this->channelContext,
new Parameters($this->parametersParser->parseRequestValues($request->attributes->get('_sylius', []), $request))
);
$result = $this->search->search($requestConfiguration);
$taxon = $this->taxonRepository->findOneBySlug(
$request->get('slug'),
$this->localeContext->getLocaleCode()
);
if ($result && $result->count() > 0) {
$arrayAllProductsGTM = []; //utilisé uniquement pour les event GTM
foreach ($result as $productES) {
$arrayAllProductsGTM['result'][$productES->getId()] = $productES->getId();
}
$arrayAllProductsGTM['currentCategory'] = $taxon;
$event = new ProductViewItemListEvent($arrayAllProductsGTM);
$this->eventDispatcher->dispatch($event, ProductViewItemListEvent::NAME);
}
return $this->render('@MonsieurBizSyliusSearchPlugin/Taxon/result.html.twig', [
'taxon' => $taxon,
'requestConfiguration' => $requestConfiguration,
'result' => $result,
'currencySymbol' => Currencies::getSymbol($this->currencyContext->getCurrencyCode(), $this->localeContext->getLocaleCode()),
]);
}
}