src/Controller/Website/DefaultController.php line 317

Open in your IDE?
  1. <?php
  2. namespace App\Controller\Website;
  3. use App\Content\BlockDataProvider;
  4. use App\Form\Website\Type\Contact\ContactLayoutType;
  5. use App\Service\SnippetDataDetector;
  6. use App\TranslateVariables\TranslateVariablesService;
  7. use Exception;
  8. use Sulu\Component\Content\Compat\StructureInterface;
  9. use App\Repository\SlideRepository;
  10. class DefaultController extends BaseWebsiteController
  11. {
  12. protected BlockDataProvider $blockDataProvider;
  13. private SnippetDataDetector $snippetDataDetector;
  14. private TranslateVariablesService $translateVariablesService;
  15. private SlideRepository $slideRepository;
  16. public function __construct(
  17. BlockDataProvider $blockDataProvider,
  18. SnippetDataDetector $snippetDataDetector,
  19. TranslateVariablesService $translateVariablesService,
  20. SlideRepository $slideRepository
  21. ) {
  22. $this->blockDataProvider = $blockDataProvider;
  23. $this->snippetDataDetector = $snippetDataDetector;
  24. $this->translateVariablesService = $translateVariablesService;
  25. $this->slideRepository = $slideRepository;
  26. }
  27. public function indexAction(StructureInterface $structure, $preview = false, $partial = false)
  28. {
  29. // Site web public - pas de vérification de permission nécessaire
  30. // Détection automatique des snippets utilisés dans la page
  31. $requiredDataTypes = $this->snippetDataDetector->getRequiredDataTypesForStructure($structure);
  32. $needsCruises = false;
  33. $blocksData = null;
  34. try {
  35. $blocksData = $this->blockDataProvider->getBlocksDataForTemplate(
  36. $structure->getPropertyValue('blocks'),
  37. $structure->getWebspaceKey()
  38. );
  39. // Vérifier si des snippets nécessitant des croisières sont présents
  40. if (is_array($blocksData)) {
  41. foreach ($blocksData as $index => $data) {
  42. if (isset($data['type'])) {
  43. $snippetType = $data['type'];
  44. // best_sellers commenté pour améliorer les performances
  45. if (in_array($snippetType, ['best_cruises', 'visited_recently'], true)) {
  46. $needsCruises = true;
  47. break;
  48. }
  49. }
  50. }
  51. }
  52. } catch (Exception $exception) {
  53. // En cas d'erreur, supposer qu'on a besoin des croisières si 'cruises' est demandé
  54. if (in_array('cruises', $requiredDataTypes, true)) {
  55. $needsCruises = true;
  56. }
  57. }
  58. // Si aucun bloc n'a été chargé mais que 'cruises' est dans les types requis, on en a besoin
  59. if (!$needsCruises && in_array('cruises', $requiredDataTypes, true)) {
  60. $needsCruises = true;
  61. }
  62. // Ajouter les types nécessaires pour enrichir les croisières
  63. if ($needsCruises) {
  64. $cruiseRelatedTypes = [
  65. 'cruises',
  66. 'companies',
  67. 'ships',
  68. 'itineraries',
  69. 'tags',
  70. 'special_offers',
  71. 'destinations',
  72. 'advantages',
  73. 'price',
  74. 'offer_cruise',
  75. 'tag_cruise',
  76. 'offer_category',
  77. 'cruise_categories'
  78. ];
  79. foreach ($cruiseRelatedTypes as $type) {
  80. if (!in_array($type, $requiredDataTypes, true)) {
  81. $requiredDataTypes[] = $type;
  82. }
  83. }
  84. }
  85. // Formulaire sans action spécifique - se soumet à l'URL courante
  86. /** @var \Symfony\Component\Form\FormInterface $contactRequestForm */
  87. $contactRequestForm = $this->createForm(ContactLayoutType::class, null);
  88. // Récupérer les meilleures ventes pour toutes les compagnies
  89. // Le template filtrera ensuite selon les compagnies sélectionnées dans companiesBlocks
  90. // NOTE: Commenté pour améliorer les performances - best_sellers désactivé
  91. $commonBestSellers = null;
  92. $commonBestSellers = [];
  93. $attributes = [
  94. 'contactRequestForm' => $contactRequestForm->createView(),
  95. 'translateVariablesService' => $this->translateVariablesService,
  96. 'common_bestSellers' => $commonBestSellers,
  97. 'companiesDatas' => [],
  98. ];
  99. // Utiliser les blocs déjà chargés, sinon les charger
  100. if ($blocksData !== null) {
  101. $attributes['blocksData'] = $blocksData;
  102. } else {
  103. try {
  104. $attributes['blocksData'] = $this->blockDataProvider->getBlocksDataForTemplate(
  105. $structure->getPropertyValue('blocks'),
  106. $structure->getWebspaceKey()
  107. );
  108. } catch (Exception $exception) {
  109. $attributes['blocksData'] = null;
  110. }
  111. }
  112. /**
  113. * Récupération des sous destinations
  114. */
  115. if (!empty($attributes['blocksData'])) {
  116. foreach ($attributes['blocksData'] as $index => $data) {
  117. if (strpos($index, 'destinations-') !== false && !empty($data['data'])) {
  118. $destinationsTop = [];
  119. $destinations = [];
  120. foreach ($data['data'] as $destination) {
  121. // Récupération des destinations
  122. if (count($destinationsTop) < 4) {
  123. $destinationsTop[] = $destination;
  124. } else {
  125. $destinations[] = $destination;
  126. }
  127. // Récupération des sous destinations
  128. if (!empty($destination['children'])) {
  129. foreach ($destination['children'] as $children) {
  130. if ($children['name'] != '/') {
  131. $destinations[] = $children;
  132. }
  133. }
  134. }
  135. }
  136. // Tri du tableau
  137. $order = [];
  138. foreach ($destinations as $key => $value) {
  139. $order[$key] = $value['name'];
  140. }
  141. array_multisort($order, SORT_ASC, $destinations);
  142. $attributes['blocksData'][$index]['data'] = array_merge($destinationsTop, $destinations);
  143. }
  144. }
  145. }
  146. /**
  147. * Récupération des slides par type de fragment et webspace
  148. */
  149. // Log visible pour vérifier que le code est exécuté
  150. error_log('=== DÉBUT RÉCUPÉRATION SLIDES ===');
  151. $webspaceKey = $structure->getWebspaceKey();
  152. // Fallback: essayer de récupérer le webspace via la requête
  153. if (empty($webspaceKey) && $this->container->has('request_stack')) {
  154. $request = $this->container->get('request_stack')->getCurrentRequest();
  155. if ($request) {
  156. $suluAttributes = $request->attributes->get('_sulu');
  157. if (is_array($suluAttributes) && isset($suluAttributes['webspace'])) {
  158. $webspaceKey = $suluAttributes['webspace'];
  159. }
  160. }
  161. }
  162. // Si toujours vide, utiliser 'main-website' par défaut
  163. if (empty($webspaceKey)) {
  164. $webspaceKey = 'main-website';
  165. error_log('ATTENTION: Webspace non détecté, utilisation de "main-website" par défaut');
  166. }
  167. $slidesByType = [];
  168. // Debug: logger le webspace détecté
  169. error_log('=== Webspace détecté: ' . $webspaceKey . ' ===');
  170. try {
  171. error_log('=== DANS LE TRY - Début détection fragments ===');
  172. // Détecter les types de fragments présents dans la page
  173. $fragmentTypes = [];
  174. // Méthode 1: Détecter via blocksData
  175. if (!empty($attributes['blocksData'])) {
  176. foreach ($attributes['blocksData'] as $index => $data) {
  177. if (isset($data['type'])) {
  178. $snippetType = $data['type'];
  179. // Types de fragments qui peuvent utiliser des slides
  180. if (in_array($snippetType, ['hero_section', 'carousel', 'carousel_destinations'], true)) {
  181. // Normaliser le type (hero_section -> hero-section)
  182. $normalizedType = str_replace('_', '-', $snippetType);
  183. if (!in_array($normalizedType, $fragmentTypes, true)) {
  184. $fragmentTypes[] = $normalizedType;
  185. }
  186. }
  187. }
  188. }
  189. }
  190. // Méthode 2: Détecter via la structure directement (pour les snippets)
  191. // La structure "default" utilise "rows" qui contient des colonnes avec des contentBlocks
  192. try {
  193. $rows = $structure->getPropertyValue('rows');
  194. if (is_array($rows)) {
  195. foreach ($rows as $row) {
  196. if (isset($row['columns']) && is_array($row['columns'])) {
  197. foreach ($row['columns'] as $column) {
  198. if (isset($column['contentBlocks']) && is_array($column['contentBlocks'])) {
  199. foreach ($column['contentBlocks'] as $block) {
  200. // Les snippets ont un type qui correspond au template
  201. if (isset($block['type'])) {
  202. $snippetType = $block['type'];
  203. // Types de fragments qui peuvent utiliser des slides
  204. if (in_array($snippetType, ['hero_section', 'carousel', 'carousel_destinations'], true)) {
  205. // Normaliser le type (hero_section -> hero-section)
  206. $normalizedType = str_replace('_', '-', $snippetType);
  207. if (!in_array($normalizedType, $fragmentTypes, true)) {
  208. $fragmentTypes[] = $normalizedType;
  209. }
  210. }
  211. }
  212. }
  213. }
  214. }
  215. }
  216. }
  217. }
  218. } catch (\Exception $e) {
  219. // Si l'accès à 'rows' échoue, continuer sans cette méthode
  220. error_log('Impossible d\'accéder à rows: ' . $e->getMessage());
  221. }
  222. // Debug: logger les types de fragments détectés
  223. error_log('Types de fragments détectés: ' . implode(', ', $fragmentTypes));
  224. // Si aucun fragment n'est détecté, charger quand même les types courants pour debug
  225. // (on peut retirer cela plus tard si nécessaire)
  226. if (empty($fragmentTypes)) {
  227. $fragmentTypes = ['hero-section', 'carousel', 'carousel1', 'carousel-destinations'];
  228. error_log('Aucun fragment détecté, chargement des types par défaut: ' . implode(', ', $fragmentTypes));
  229. }
  230. // Ajouter carousel1 si carousel est présent (carousel1 est le type stocké en BDD)
  231. if (in_array('carousel', $fragmentTypes, true) && !in_array('carousel1', $fragmentTypes, true)) {
  232. $fragmentTypes[] = 'carousel1';
  233. }
  234. // Récupérer les slides pour chaque type de fragment
  235. foreach ($fragmentTypes as $type) {
  236. try {
  237. // Debug: vérifier d'abord s'il y a des slides de ce type (sans filtre webspace)
  238. $allSlidesOfType = $this->slideRepository->findAllActiveByType($type);
  239. error_log(sprintf('DEBUG: Total slides actives de type "%s" (sans filtre webspace): %d', $type, count($allSlidesOfType)));
  240. if (count($allSlidesOfType) > 0) {
  241. $firstSlide = $allSlidesOfType[0];
  242. error_log(sprintf(
  243. 'DEBUG: Première slide trouvée - ID=%d, Type=%s, DistributionMode=%s, isNotMainWebspace=%s, includeWebspaces=%s',
  244. $firstSlide->getId(),
  245. $firstSlide->getType(),
  246. $firstSlide->getDistributionMode(),
  247. $firstSlide->isNotMainWebspace() ? 'true' : 'false',
  248. json_encode($firstSlide->getIncludeWebspaces())
  249. ));
  250. }
  251. // Maintenant récupérer avec le filtre webspace
  252. $slides = $this->slideRepository->findActiveByTypeAndWebspace($type, $webspaceKey);
  253. $slidesByType[$type] = $slides;
  254. // Debug: logger le nombre de slides trouvées
  255. error_log(sprintf('Slides trouvées pour type "%s" et webspace "%s": %d', $type, $webspaceKey, count($slides)));
  256. if (count($slides) > 0) {
  257. error_log('Première slide trouvée: ID=' . $slides[0]->getId() . ', Type=' . $slides[0]->getType());
  258. } else if (count($allSlidesOfType) > 0) {
  259. error_log(sprintf('ATTENTION: %d slides de type "%s" existent mais aucune ne correspond au webspace "%s"', count($allSlidesOfType), $type, $webspaceKey));
  260. }
  261. } catch (\Exception $e) {
  262. error_log('Erreur lors du chargement des slides pour le type ' . $type . ': ' . $e->getMessage());
  263. error_log('Stack trace: ' . $e->getTraceAsString());
  264. $slidesByType[$type] = [];
  265. }
  266. }
  267. } catch (\Exception $e) {
  268. // En cas d'erreur, continuer sans les slides
  269. error_log('=== ERREUR lors du chargement des slides: ' . $e->getMessage() . ' ===');
  270. error_log('Stack trace: ' . $e->getTraceAsString());
  271. }
  272. error_log('=== FIN RÉCUPÉRATION SLIDES - Nombre de types: ' . count($slidesByType) . ' ===');
  273. $attributes['slidesByType'] = $slidesByType;
  274. $attributes['webspaceKey'] = $webspaceKey; // Passer le webspace au template pour debug
  275. // Garder aussi l'ancien format pour compatibilité
  276. $attributes['slides'] = [];
  277. foreach ($slidesByType as $type => $slides) {
  278. $attributes['slides'] = array_merge($attributes['slides'], $slides);
  279. }
  280. return $this->renderStructure(
  281. $structure,
  282. $attributes,
  283. $preview,
  284. $partial
  285. );
  286. }
  287. /**
  288. * Extrait les IDs des compagnies sélectionnées depuis les snippets best_sellers de la structure
  289. *
  290. * Note: Sulu stocke le nom de la compagnie dans CommonCompanySelector, pas l'ID
  291. * On doit donc convertir les noms en IDs en utilisant le CompanyService
  292. *
  293. * @param StructureInterface $structure La structure Sulu
  294. * @return array Liste des IDs de compagnies sélectionnées
  295. */
  296. private function extractCompanyIdsFromBestSellersSnippets(StructureInterface $structure): array
  297. {
  298. $companyIds = [];
  299. $companyNames = [];
  300. try {
  301. $blocks = $structure->getPropertyValue('blocks');
  302. if (!is_array($blocks)) {
  303. return [];
  304. }
  305. foreach ($blocks as $block) {
  306. if (isset($block['type']) && $block['type'] === 'snippet') {
  307. $snippet = $block['settings'] ?? null;
  308. if ($snippet !== null && isset($snippet['template']) && $snippet['template'] === 'best_sellers') {
  309. $companiesBlocks = $snippet['companiesBlocks'] ?? [];
  310. if (is_array($companiesBlocks)) {
  311. foreach ($companiesBlocks as $companyBlock) {
  312. $CommonCompanySelector = $companyBlock['CommonCompanySelector'] ?? null;
  313. if (!empty($CommonCompanySelector)) {
  314. if (is_numeric($CommonCompanySelector)) {
  315. $companyId = (int) $CommonCompanySelector;
  316. if ($companyId > 0 && !in_array($companyId, $companyIds, true)) {
  317. $companyIds[] = $companyId;
  318. }
  319. } else {
  320. $companyNames[] = trim((string) $CommonCompanySelector);
  321. }
  322. }
  323. }
  324. }
  325. }
  326. }
  327. }
  328. } catch (\Exception $e) {
  329. error_log('Erreur lors de l\'extraction des IDs de compagnies: ' . $e->getMessage());
  330. }
  331. return $companyIds;
  332. }
  333. }