<?php
namespace App\Controller\Website;
use App\Helper\Cruise\CruiseHelper;
use App\Helper\Partner\PartnerHelper;
use App\Helper\SuluHelper;
use Croisiland\CommonBundle\Form\CruiseSearchFullFormType;
use Croisiland\CommonBundle\Model\CruiseSearchModel;
use Croisiland\CommonBundle\Repository\CruiseSearchRepository;
use Croisiland\CommonBundle\Service\CruiseSearchService;
use Croisiland\CommonBundle\Serializer\CruiseSearchModelSerializer;
use Doctrine\ORM\NonUniqueResultException;
use Doctrine\ORM\NoResultException;
use Sulu\Component\Content\Compat\StructureInterface;
use Symfony\Component\HttpFoundation\Response;
class ListController extends BaseWebsiteController
{
const string BASE_PATH = '/croisieres';
public function __construct(
private readonly CruiseSearchService $cruiseSearchService,
private readonly CruiseSearchModelSerializer $cruiseSearchModelSerializer,
private readonly CruiseSearchRepository $cruiseSearchRepository,
private readonly CruiseHelper $cruiseHelper,
private readonly SuluHelper $suluHelper,
private readonly PartnerHelper $partnerHelper,
) {
}
/**
* @throws NonUniqueResultException
* @throws NoResultException
*/
public function indexAction(StructureInterface $structure, $preview = false, $partial = false): Response
{
$partner = $this->partnerHelper->getCurrentPartner();
$request = $this->container->get('request_stack')->getCurrentRequest();
$attributes = $this->getSharedLayoutFormViews();
$searchUrl = null;
$cruiseSearch = $this->cruiseSearchModelSerializer->fromRequest($request);
$cruiseSearch->setPartner($partner);
$hasInitialParameters = $this->cruiseSearchService->hasSearchParameters($cruiseSearch);
$form = $this->createForm(CruiseSearchFullFormType::class, $cruiseSearch, [
'visible_fields' => CruiseListSearchFormConfiguration::visibleFields(),
]);
$form->handleRequest($request);
$cruiseSearch->setPerPage(CruiseListSearchFormConfiguration::perPage());
$result = $this->cruiseSearchService->search($cruiseSearch);
$result = $this->applyFilteredCruiseCount($result, $cruiseSearch);
if (($form->isSubmitted() && $form->isValid()) || $hasInitialParameters) {
$searchUrl = $this->suluHelper->generateUrlWithQueryParams(self::BASE_PATH, $result['search_url_parameters']);
}
$attributes['form'] = $form->createView();
$attributes['cruiseSearchResult'] = $result;
$attributes['searchUrl'] = $searchUrl;
$attributes['searchMainSubjectInfos'] = $this->cruiseHelper->getSearchMainSubjectInfos($cruiseSearch);
return $this->renderStructure(
$structure,
$attributes,
$preview,
$partial
);
}
/**
* Le décompte du bundle (`countSearchResults`) est lancé sans les filtres :
* le total reste celui du catalogue alors que les cartes sont filtrées.
* On recalcule le total à partir des identifiants qui passent les filtres.
*
* @param array<string, mixed> $result
*
* @return array<string, mixed>
*/
private function applyFilteredCruiseCount(array $result, CruiseSearchModel $cruiseSearch): array
{
if (!$this->hasUserSearchFilters($cruiseSearch)) {
return $result;
}
$filteredCount = count(
$this->cruiseSearchRepository->getCruisesIdsFromCruiseSearchModel($cruiseSearch, false)
);
$perPage = (int) ($result['pagination']['per_page'] ?? 0);
if ($perPage < 1) {
$perPage = 1;
}
$currentPage = (int) ($result['pagination']['current_page'] ?? 1);
$totalPages = (int) ceil($filteredCount / $perPage);
$result['pagination']['total_count'] = $filteredCount;
$result['pagination']['total_pages'] = $totalPages;
$result['pagination']['has_next_page'] = $currentPage < $totalPages;
$result['pagination']['has_previous_page'] = $currentPage > 1;
return $result;
}
private function hasUserSearchFilters(CruiseSearchModel $cruiseSearch): bool
{
if (!$cruiseSearch->getCompanies()->isEmpty()) {
return true;
}
if (!$cruiseSearch->getShips()->isEmpty()) {
return true;
}
if (!$cruiseSearch->getDeparturePorts()->isEmpty()) {
return true;
}
if (!$cruiseSearch->getDestinationsMain()->isEmpty()) {
return true;
}
if (!$cruiseSearch->getDestinationsSecondary()->isEmpty()) {
return true;
}
if (!$cruiseSearch->getTags()->isEmpty()) {
return true;
}
if (!$cruiseSearch->getOffers()->isEmpty()) {
return true;
}
if ($cruiseSearch->getPeriodStartDate() !== null || $cruiseSearch->getPeriodEndDate() !== null) {
return true;
}
if ($cruiseSearch->getPriceMinimum() !== null || $cruiseSearch->getPriceMaximum() !== null) {
return true;
}
if (trim((string) $cruiseSearch->getKeywords()) !== '') {
return true;
}
if (trim((string) $cruiseSearch->getCruiseCode()) !== '') {
return true;
}
if ($cruiseSearch->getDurations() !== []) {
return true;
}
return $cruiseSearch->getWorldTour() !== null;
}
}