<?php
namespace App\Controller\Website;
use App\Content\BlockDataProvider;
use App\Form\Website\Type\Contact\ContactLayoutType;
use App\Service\SnippetDataDetector;
use App\TranslateVariables\TranslateVariablesService;
use Exception;
use Sulu\Component\Content\Compat\StructureInterface;
use App\Repository\SlideRepository;
class DefaultController extends BaseWebsiteController
{
protected BlockDataProvider $blockDataProvider;
private SnippetDataDetector $snippetDataDetector;
private TranslateVariablesService $translateVariablesService;
private SlideRepository $slideRepository;
public function __construct(
BlockDataProvider $blockDataProvider,
SnippetDataDetector $snippetDataDetector,
TranslateVariablesService $translateVariablesService,
SlideRepository $slideRepository
) {
$this->blockDataProvider = $blockDataProvider;
$this->snippetDataDetector = $snippetDataDetector;
$this->translateVariablesService = $translateVariablesService;
$this->slideRepository = $slideRepository;
}
public function indexAction(StructureInterface $structure, $preview = false, $partial = false)
{
// Site web public - pas de vérification de permission nécessaire
// Détection automatique des snippets utilisés dans la page
$requiredDataTypes = $this->snippetDataDetector->getRequiredDataTypesForStructure($structure);
$needsCruises = false;
$blocksData = null;
try {
$blocksData = $this->blockDataProvider->getBlocksDataForTemplate(
$structure->getPropertyValue('blocks'),
$structure->getWebspaceKey()
);
// Vérifier si des snippets nécessitant des croisières sont présents
if (is_array($blocksData)) {
foreach ($blocksData as $index => $data) {
if (isset($data['type'])) {
$snippetType = $data['type'];
// best_sellers commenté pour améliorer les performances
if (in_array($snippetType, ['best_cruises', 'visited_recently'], true)) {
$needsCruises = true;
break;
}
}
}
}
} catch (Exception $exception) {
// En cas d'erreur, supposer qu'on a besoin des croisières si 'cruises' est demandé
if (in_array('cruises', $requiredDataTypes, true)) {
$needsCruises = true;
}
}
// Si aucun bloc n'a été chargé mais que 'cruises' est dans les types requis, on en a besoin
if (!$needsCruises && in_array('cruises', $requiredDataTypes, true)) {
$needsCruises = true;
}
// Ajouter les types nécessaires pour enrichir les croisières
if ($needsCruises) {
$cruiseRelatedTypes = [
'cruises',
'companies',
'ships',
'itineraries',
'tags',
'special_offers',
'destinations',
'advantages',
'price',
'offer_cruise',
'tag_cruise',
'offer_category',
'cruise_categories'
];
foreach ($cruiseRelatedTypes as $type) {
if (!in_array($type, $requiredDataTypes, true)) {
$requiredDataTypes[] = $type;
}
}
}
// Formulaire sans action spécifique - se soumet à l'URL courante
/** @var \Symfony\Component\Form\FormInterface $contactRequestForm */
$contactRequestForm = $this->createForm(ContactLayoutType::class, null);
// Récupérer les meilleures ventes pour toutes les compagnies
// Le template filtrera ensuite selon les compagnies sélectionnées dans companiesBlocks
// NOTE: Commenté pour améliorer les performances - best_sellers désactivé
$commonBestSellers = null;
$commonBestSellers = [];
$attributes = [
'contactRequestForm' => $contactRequestForm->createView(),
'translateVariablesService' => $this->translateVariablesService,
'common_bestSellers' => $commonBestSellers,
'companiesDatas' => [],
];
// Utiliser les blocs déjà chargés, sinon les charger
if ($blocksData !== null) {
$attributes['blocksData'] = $blocksData;
} else {
try {
$attributes['blocksData'] = $this->blockDataProvider->getBlocksDataForTemplate(
$structure->getPropertyValue('blocks'),
$structure->getWebspaceKey()
);
} catch (Exception $exception) {
$attributes['blocksData'] = null;
}
}
/**
* Récupération des sous destinations
*/
if (!empty($attributes['blocksData'])) {
foreach ($attributes['blocksData'] as $index => $data) {
if (strpos($index, 'destinations-') !== false && !empty($data['data'])) {
$destinationsTop = [];
$destinations = [];
foreach ($data['data'] as $destination) {
// Récupération des destinations
if (count($destinationsTop) < 4) {
$destinationsTop[] = $destination;
} else {
$destinations[] = $destination;
}
// Récupération des sous destinations
if (!empty($destination['children'])) {
foreach ($destination['children'] as $children) {
if ($children['name'] != '/') {
$destinations[] = $children;
}
}
}
}
// Tri du tableau
$order = [];
foreach ($destinations as $key => $value) {
$order[$key] = $value['name'];
}
array_multisort($order, SORT_ASC, $destinations);
$attributes['blocksData'][$index]['data'] = array_merge($destinationsTop, $destinations);
}
}
}
/**
* Récupération des slides par type de fragment et webspace
*/
// Log visible pour vérifier que le code est exécuté
error_log('=== DÉBUT RÉCUPÉRATION SLIDES ===');
$webspaceKey = $structure->getWebspaceKey();
// Fallback: essayer de récupérer le webspace via la requête
if (empty($webspaceKey) && $this->container->has('request_stack')) {
$request = $this->container->get('request_stack')->getCurrentRequest();
if ($request) {
$suluAttributes = $request->attributes->get('_sulu');
if (is_array($suluAttributes) && isset($suluAttributes['webspace'])) {
$webspaceKey = $suluAttributes['webspace'];
}
}
}
// Si toujours vide, utiliser 'main-website' par défaut
if (empty($webspaceKey)) {
$webspaceKey = 'main-website';
error_log('ATTENTION: Webspace non détecté, utilisation de "main-website" par défaut');
}
$slidesByType = [];
// Debug: logger le webspace détecté
error_log('=== Webspace détecté: ' . $webspaceKey . ' ===');
try {
error_log('=== DANS LE TRY - Début détection fragments ===');
// Détecter les types de fragments présents dans la page
$fragmentTypes = [];
// Méthode 1: Détecter via blocksData
if (!empty($attributes['blocksData'])) {
foreach ($attributes['blocksData'] as $index => $data) {
if (isset($data['type'])) {
$snippetType = $data['type'];
// Types de fragments qui peuvent utiliser des slides
if (in_array($snippetType, ['hero_section', 'carousel', 'carousel_destinations'], true)) {
// Normaliser le type (hero_section -> hero-section)
$normalizedType = str_replace('_', '-', $snippetType);
if (!in_array($normalizedType, $fragmentTypes, true)) {
$fragmentTypes[] = $normalizedType;
}
}
}
}
}
// Méthode 2: Détecter via la structure directement (pour les snippets)
// La structure "default" utilise "rows" qui contient des colonnes avec des contentBlocks
try {
$rows = $structure->getPropertyValue('rows');
if (is_array($rows)) {
foreach ($rows as $row) {
if (isset($row['columns']) && is_array($row['columns'])) {
foreach ($row['columns'] as $column) {
if (isset($column['contentBlocks']) && is_array($column['contentBlocks'])) {
foreach ($column['contentBlocks'] as $block) {
// Les snippets ont un type qui correspond au template
if (isset($block['type'])) {
$snippetType = $block['type'];
// Types de fragments qui peuvent utiliser des slides
if (in_array($snippetType, ['hero_section', 'carousel', 'carousel_destinations'], true)) {
// Normaliser le type (hero_section -> hero-section)
$normalizedType = str_replace('_', '-', $snippetType);
if (!in_array($normalizedType, $fragmentTypes, true)) {
$fragmentTypes[] = $normalizedType;
}
}
}
}
}
}
}
}
}
} catch (\Exception $e) {
// Si l'accès à 'rows' échoue, continuer sans cette méthode
error_log('Impossible d\'accéder à rows: ' . $e->getMessage());
}
// Debug: logger les types de fragments détectés
error_log('Types de fragments détectés: ' . implode(', ', $fragmentTypes));
// Si aucun fragment n'est détecté, charger quand même les types courants pour debug
// (on peut retirer cela plus tard si nécessaire)
if (empty($fragmentTypes)) {
$fragmentTypes = ['hero-section', 'carousel', 'carousel1', 'carousel-destinations'];
error_log('Aucun fragment détecté, chargement des types par défaut: ' . implode(', ', $fragmentTypes));
}
// Ajouter carousel1 si carousel est présent (carousel1 est le type stocké en BDD)
if (in_array('carousel', $fragmentTypes, true) && !in_array('carousel1', $fragmentTypes, true)) {
$fragmentTypes[] = 'carousel1';
}
// Récupérer les slides pour chaque type de fragment
foreach ($fragmentTypes as $type) {
try {
// Debug: vérifier d'abord s'il y a des slides de ce type (sans filtre webspace)
$allSlidesOfType = $this->slideRepository->findAllActiveByType($type);
error_log(sprintf('DEBUG: Total slides actives de type "%s" (sans filtre webspace): %d', $type, count($allSlidesOfType)));
if (count($allSlidesOfType) > 0) {
$firstSlide = $allSlidesOfType[0];
error_log(sprintf(
'DEBUG: Première slide trouvée - ID=%d, Type=%s, DistributionMode=%s, isNotMainWebspace=%s, includeWebspaces=%s',
$firstSlide->getId(),
$firstSlide->getType(),
$firstSlide->getDistributionMode(),
$firstSlide->isNotMainWebspace() ? 'true' : 'false',
json_encode($firstSlide->getIncludeWebspaces())
));
}
// Maintenant récupérer avec le filtre webspace
$slides = $this->slideRepository->findActiveByTypeAndWebspace($type, $webspaceKey);
$slidesByType[$type] = $slides;
// Debug: logger le nombre de slides trouvées
error_log(sprintf('Slides trouvées pour type "%s" et webspace "%s": %d', $type, $webspaceKey, count($slides)));
if (count($slides) > 0) {
error_log('Première slide trouvée: ID=' . $slides[0]->getId() . ', Type=' . $slides[0]->getType());
} else if (count($allSlidesOfType) > 0) {
error_log(sprintf('ATTENTION: %d slides de type "%s" existent mais aucune ne correspond au webspace "%s"', count($allSlidesOfType), $type, $webspaceKey));
}
} catch (\Exception $e) {
error_log('Erreur lors du chargement des slides pour le type ' . $type . ': ' . $e->getMessage());
error_log('Stack trace: ' . $e->getTraceAsString());
$slidesByType[$type] = [];
}
}
} catch (\Exception $e) {
// En cas d'erreur, continuer sans les slides
error_log('=== ERREUR lors du chargement des slides: ' . $e->getMessage() . ' ===');
error_log('Stack trace: ' . $e->getTraceAsString());
}
error_log('=== FIN RÉCUPÉRATION SLIDES - Nombre de types: ' . count($slidesByType) . ' ===');
$attributes['slidesByType'] = $slidesByType;
$attributes['webspaceKey'] = $webspaceKey; // Passer le webspace au template pour debug
// Garder aussi l'ancien format pour compatibilité
$attributes['slides'] = [];
foreach ($slidesByType as $type => $slides) {
$attributes['slides'] = array_merge($attributes['slides'], $slides);
}
return $this->renderStructure(
$structure,
$attributes,
$preview,
$partial
);
}
/**
* Extrait les IDs des compagnies sélectionnées depuis les snippets best_sellers de la structure
*
* Note: Sulu stocke le nom de la compagnie dans CommonCompanySelector, pas l'ID
* On doit donc convertir les noms en IDs en utilisant le CompanyService
*
* @param StructureInterface $structure La structure Sulu
* @return array Liste des IDs de compagnies sélectionnées
*/
private function extractCompanyIdsFromBestSellersSnippets(StructureInterface $structure): array
{
$companyIds = [];
$companyNames = [];
try {
$blocks = $structure->getPropertyValue('blocks');
if (!is_array($blocks)) {
return [];
}
foreach ($blocks as $block) {
if (isset($block['type']) && $block['type'] === 'snippet') {
$snippet = $block['settings'] ?? null;
if ($snippet !== null && isset($snippet['template']) && $snippet['template'] === 'best_sellers') {
$companiesBlocks = $snippet['companiesBlocks'] ?? [];
if (is_array($companiesBlocks)) {
foreach ($companiesBlocks as $companyBlock) {
$CommonCompanySelector = $companyBlock['CommonCompanySelector'] ?? null;
if (!empty($CommonCompanySelector)) {
if (is_numeric($CommonCompanySelector)) {
$companyId = (int) $CommonCompanySelector;
if ($companyId > 0 && !in_array($companyId, $companyIds, true)) {
$companyIds[] = $companyId;
}
} else {
$companyNames[] = trim((string) $CommonCompanySelector);
}
}
}
}
}
}
}
} catch (\Exception $e) {
error_log('Erreur lors de l\'extraction des IDs de compagnies: ' . $e->getMessage());
}
return $companyIds;
}
}