<?php
namespace App\Search;
use App\Entity\User;
use App\Event\FilterBehaviourEvent;
use App\Form\Type\Frontend\VehicleSearchType;
use App\Repository\CategoryRepository;
use App\Repository\EnergyRepository;
use App\Repository\SaleEventRepository;
use App\Repository\SaleRepository;
use App\Repository\TransmissionRepository;
use App\Repository\VehicleRepository;
use Gedmo\Sluggable\Util\Urlizer;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
/**
* Provides ways to convert the data from a search or saved search.
*/
class SearchConverter
{
public const SEPARATOR = ', ';
public const CO2 = '< %s g/km CO2';
public function __construct(private readonly SessionInterface $session, private readonly EventDispatcherInterface $dispatcher, private readonly TokenStorageInterface $tokenStorage, private readonly TranslatorInterface $translator, private readonly EnergyRepository $energyRepository, private readonly SaleRepository $saleRepository, private readonly SaleEventRepository $saleEventRepository, private readonly CategoryRepository $categoryRepository, private readonly TransmissionRepository $transmissionRepository, private readonly VehicleRepository $vehicleRepository)
{
}
public function convertToDBCriteria($search, $formType = VehicleSearchType::FORM_DEFAULT)
{
$criteria = [];
$sessionSale = $this->session->get('sale', null);
$sessionEvent = $this->session->get('event', null);
if (isset($search['sale'])) {
if ('all' === $search['sale']) {
$criteria['sale'] = null;
$this->session->remove('sale');
} elseif (null !== $sale = $this->saleRepository->findOneById($search['sale'])) {
$criteria['sale'] = $sale;
$this->session->set('sale', $search['sale']);
}
} elseif (
!empty($sessionSale)
&& (null !== $sale = $this->saleRepository->findOneById($sessionSale))
) {
$criteria['sale'] = $sale;
}
if (isset($search['event'])) {
if ('all' === $search['event']) {
$criteria['event'] = null;
$this->session->remove('event');
} elseif (null !== $event = $this->saleEventRepository->findOneById($search['event'])) {
$criteria['event'] = $event->getId();
$this->session->set('event', $event->getId());
}
} elseif (
!empty($sessionEvent)
&& (null !== $event = $this->saleEventRepository->findOneById($sessionEvent))
) {
$criteria['event'] = $event->getId();
}
if (isset($sale) && null !== $sale) {
$this->dispatcher->dispatch(new FilterBehaviourEvent($this->getUser(), $sale), FilterBehaviourEvent::SALE_BEHAVIOUR);
}
if (isset($search['sort'])) {
$criteria['sortedby'] = VehicleSearchType::FORM_SALE_RESULTS === $formType ?
str_replace('startingPrice', 'finalAmount', $search['sort']) : $search['sort'];
}
if (isset($search['category'])) {
if (is_string($search['category'])) {
$criteria['category'] = explode(',', $search['category']);
} else {
$criteria['category'] = $search['category'];
}
}
$keyPrice = VehicleSearchType::FORM_SALE_RESULTS === $formType ? 'finalAmount' : 'price';
if (isset($search['budget']['min'])) {
$search['budgetMin'] = $search['budget']['min'];
}
if (isset($search['budget']['max'])) {
$search['budgetMax'] = $search['budget']['max'];
}
if (isset($search['budgetMin'])) {
$search['budgetMin'] = floatval($search['budgetMin']);
$criteria[$keyPrice]['min'] = $search['budgetMin'];
$criteria[$keyPrice]['max'] = PHP_INT_MAX;
}
if (isset($search['budgetMax'])) {
$search['budgetMax'] = floatval($search['budgetMax']);
$criteria[$keyPrice]['max'] = $search['budgetMax'];
if (!isset($criteria[$keyPrice]['min'])) {
$criteria[$keyPrice]['min'] = 0;
}
}
if (isset($search['maker'])) {
$criteria['makerSlug'] = array_map(fn ($maker) => Urlizer::urlize($maker), explode(',', (string) $search['maker']));
}
if (isset($search['cityLocation'])) {
foreach (explode(',', (string) $search['cityLocation']) as $cityLocation) {
if (null !== $v = $this->vehicleRepository->findOneByCityLocation(trim($cityLocation))) {
$criteria['cityLocation'][] = $v->getCityLocation();
} elseif (null !== $v = $this->vehicleRepository->findOneByCityLocation(Urlizer::urlize($cityLocation))) {
$criteria['cityLocation'][] = $v->getCityLocation();
}
}
}
if (isset($search['modelGroup'])) {
$criteria['modelGroupSlug'] = array_map(fn ($group) => Urlizer::urlize($group), explode(',', (string) $search['modelGroup']));
}
if (isset($search['segmentSize'])) {
$criteria['segmentSizeSlug'] = array_map(fn ($segmenttaille) => Urlizer::urlize($segmenttaille), explode(',', (string) $search['segmentSize']));
}
if (isset($search['energy'])) {
foreach (explode(',', (string) $search['energy']) as $energy) {
if (null !== $e = $this->energyRepository->findOneByName(trim($energy))) {
$criteria['energy'][] = $e->getCode();
}
}
}
if (isset($search['segmentTransmission'])) {
$criteria['segmentTransmission'] = is_array($search['segmentTransmission']) ? $search['segmentTransmission'] : explode(',', (string) $search['segmentTransmission']);
}
if (isset($search['fourwheeldrive']) && $search['fourwheeldrive']) {
$criteria['driveWheel'] = '4X4';
}
if (!empty($search['options'])) {
$criteria['options'] = array_map(fn ($option) => Urlizer::urlize($option), explode(',', (string) $search['options']));
}
if (isset($search['kilometersMin'])) {
$criteria['kilometers']['min'] = $search['kilometersMin'];
}
if (isset($search['kilometersMax'])) {
$criteria['kilometers']['max'] = $search['kilometersMax'];
}
if (isset($search['kilometers']['min'])) {
$search['kilometersMin'] = $search['kilometers']['min'];
}
if (isset($search['kilometers']['max'])) {
$search['kilometersMax'] = $search['kilometers']['max'];
}
if (isset($search['yearMin'])) {
$criteria['millesime']['min'] = $search['yearMin'];
}
if (isset($search['yearMax'])) {
$criteria['millesime']['max'] = $search['yearMax'];
}
if (isset($search['broken'])) {
$criteria['broken'] = $search['broken'];
}
if (isset($search['highlight'])) {
$criteria['highlight'] = $search['highlight'];
}
if (isset($search['seatCount'])) {
foreach (explode(',', (string) $search['seatCount']) as $key => $item) {
[$criteria['seatCount'][$key]['min'], $criteria['seatCount'][$key]['max']] = explode('-', trim($item));
}
}
if (isset($search['doorCount'])) {
$criteria['doorCount'] = $search['doorCount'];
}
if (isset($search['co2'])) {
$criteria['co2'][] = [
'min' => '0',
'max' => $search['co2'],
];
}
if (isset($search['estimated'])) {
$criteria['estimated'] = true;
}
if (isset($search['critair'])) {
$criteria['critair'] = $search['critair'];
}
return $criteria;
}
public function convertToDisplayableValues($search)
{
$values = [];
$sessionSale = $this->session->get('sale', null);
$sessionEvent = $this->session->get('event', null);
if (isset($search['sale'])) {
if (null !== $sale = $this->saleRepository->findOneById($search['sale'])) {
$values['sale'] = $sale->getDisplayedName();
}
} elseif (
!empty($sessionSale)
&& (null !== $sale = $this->saleRepository->findOneById($sessionSale))
) {
$values['sale'] = $sale->getDisplayedName();
}
if (isset($search['event'])) {
if (null !== $event = $this->saleEventRepository->findOneById($search['event'])) {
$values['sale'] = $event->getSale()->getRoom()->getName();
$values['event'] = sprintf('%s', substr((string) $event->getStartTime(), 0, strrpos((string) $event->getStartTime(), ':')));
}
} elseif (
!empty($sessionEvent)
&& (null !== $event = $this->saleEventRepository->findOneById($sessionEvent))
) {
$values['sale'] = $event->getSale()->getRoom()->getName();
$values['event'] = sprintf('%s', substr((string) $event->getStartTime(), 0, strrpos((string) $event->getStartTime(), ':')));
}
if (isset($search['category'])) {
$categories = is_array($search['category']) ? $search['category'] : explode(',', (string) $search['category']);
foreach ($categories as $category) {
if (null !== $c = $this->categoryRepository->findOneById($category)) {
$values['category'][] = (object) [
'display' => $c->getName(),
'actual' => $c->getId(),
];
}
}
}
if (isset($search['budget']['min'])) {
$search['budgetMin'] = $search['budget']['min'];
}
if (isset($search['budget']['max'])) {
$search['budgetMax'] = $search['budget']['max'];
}
if (isset($search['budgetMin'])) {
if (isset($search['budgetMax'])) {
$values['budget'] = sprintf('%s ~ %s €', $search['budgetMin'], $search['budgetMax']);
} else {
$values['budget'] = sprintf('> %s €', $search['budgetMin']);
}
} elseif (isset($search['budgetMax'])) {
$values['budget'] = sprintf('< %s €', $search['budgetMax']);
}
if (isset($search['maker'])) {
$values['maker'] = explode(',', (string) $search['maker']);
}
if (isset($search['cityLocation'])) {
$values['cityLocation'] = explode(',', (string) $search['cityLocation']);
}
if (isset($search['modelGroup'])) {
$values['modelGroup'] = explode(',', (string) $search['modelGroup']);
}
if (isset($search['segmentSize'])) {
$values['segmentSize'] = explode(',', (string) $search['segmentSize']);
}
if (isset($search['fourwheeldrive']) && $search['fourwheeldrive']) {
$values['driveWheel'] = '4X4';
}
if (isset($search['energy'])) {
$energies = is_array($search['energy']) ? $search['energy'] : explode(',', (string) $search['energy']);
foreach ($energies as $energy) {
if (null !== $e = $this->energyRepository->findOneByName(trim((string) $energy))) {
$values['energy'][] = (object) [
'display' => $e->getName(),
'actual' => $e->getId(),
];
}
}
}
if (isset($search['segmentTransmission'])) {
$transmissions = is_array($search['segmentTransmission']) ? $search['segmentTransmission'] : explode(',', (string) $search['segmentTransmission']);
foreach ($transmissions as $transmission) {
if (null != ($t = $this->transmissionRepository->findOneById($transmission))) {
$values['segmentTransmission'][] = (object) [
'display' => $t->getName(),
'actual' => $t->getId(),
];
}
}
}
if (!empty($search['options'])) {
$values['options'] = explode(',', (string) $search['options']);
}
if (isset($search['kilometers']['min'])) {
$search['kilometersMin'] = $search['kilometers']['min'];
}
if (isset($search['kilometers']['max'])) {
$search['kilometersMax'] = $search['kilometers']['max'];
}
if (isset($search['kilometersMin'])) {
if (isset($search['kilometersMax'])) {
$values['kilometers'] = sprintf('%s ~ %s km', $search['kilometersMin'], $search['kilometersMax']);
} else {
$values['kilometers'] = sprintf('> %s km', $search['kilometersMin']);
}
} elseif (isset($search['kilometersMax'])) {
$values['kilometers'] = sprintf('< %s km', $search['kilometersMax']);
}
if (isset($search['yearMin'])) {
if (isset($search['yearMax'])) {
$values['year'] = sprintf('%s ~ %s', $search['yearMin'], $search['yearMax']);
} else {
$values['year'] = sprintf('> %s', $search['yearMin']);
}
} elseif (isset($search['yearMax'])) {
$values['year'] = sprintf('< %s', $search['yearMax']);
}
if (isset($search['broken']) && true == $search['broken']) {
$values['broken'] = $this->translator->trans('badges.search.broken');
}
if (isset($search['highlight']) && true == $search['highlight']) {
$values['highlight'] = $this->translator->trans('badges.search.highlight');
}
if (isset($search['seatCount'])) {
$values['seatCount'] = sprintf('%s %s', $search['seatCount'], $this->translator->trans('badges.search.seats'));
}
if (isset($search['doorCount'])) {
$values['doorCount'] = sprintf('%s %s', $search['doorCount'], $this->translator->trans('badges.search.doors'));
}
if (isset($search['co2'])) {
$values['co2'] = sprintf(self::CO2, $search['co2']);
}
if (isset($search['estimated'])) {
$values['estimated'] = $this->translator->trans('badges.search.estimated');
}
if (isset($search['critair'])) {
$values['critair'] = sprintf('Crit\'Air %s', $search['critair']);
}
return $values;
}
private function getUser()
{
if (null === $token = $this->tokenStorage->getToken()) {
return null;
}
if (!is_object($user = $token->getUser()) or !$user instanceof User) {
return null;
}
return $user;
}
}