src/Controller/PageController.php line 39

Open in your IDE?
  1. <?php
  2. namespace App\Controller;
  3. use App\Entity\Page;
  4. use App\Repository\PageRepository;
  5. use App\Repository\BlockRepository;
  6. use App\Repository\ServiceRepository;
  7. use App\Repository\SettingRepository;
  8. use App\Service\SiteOwnerResolver;
  9. use Symfony\Component\HttpFoundation\Response;
  10. use Symfony\Component\Routing\Annotation\Route;
  11. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  12. class PageController extends AbstractController
  13. {
  14.     public function __construct(
  15.         private SettingRepository $settingRepository,
  16.         private ServiceRepository $serviceRepository,
  17.         private PageRepository $pageRepository,
  18.         private BlockRepository $blockRepository,
  19.         private SiteOwnerResolver $siteOwnerResolver,
  20.     ) {}
  21.     #[Route('/'name'public_home')]
  22.     public function home(): Response
  23.     {
  24.         return $this->redirectToRoute('react_app', ['reactRouting' => 'accueil'], Response::HTTP_MOVED_PERMANENTLY);
  25.     }
  26.     #[Route(
  27.         '/{reactRouting}',
  28.         name'react_app',
  29.         requirements: [
  30.             'reactRouting' => '^(?!admin|login|logout|reset-password).*'
  31.         ],
  32.         defaults: ['reactRouting' => null]
  33.     )]
  34.     public function index($reactRouting): Response
  35.     {
  36.         $page $this->pageRepository->findPublishedBySlug($reactRouting$this->siteOwnerResolver->getSiteOwner());
  37.         $initialData $this->getInitialData();
  38.         if ($page) {
  39.             $initialData['page'] = [
  40.                 'id' => $page->getId(),
  41.                 'title' => $page->getTitle(),
  42.                 'slug' => $page->getSlug(),
  43.                 'seoTitle' => $page->getSeoTitle(),
  44.                 'seoDescription' => $page->getSeoDescription(),
  45.                 'blocks' => $this->buildBlocksData($page),
  46.             ];
  47.         }
  48.             
  49.         return $this->render('public/react_page.html.twig', [
  50.             'initialData' => $initialData,
  51.         ]);
  52.     }
  53.     #[Route(
  54.         '/{slug}',
  55.         name'page_show',
  56.         requirements: [
  57.             'slug' => '^(?!admin|login|logout|reset-password|api).*'
  58.         ]
  59.     )]
  60.     public function page(string $slug): Response
  61.     {
  62.         $page $this->pageRepository->findPublishedBySlug($slug$this->siteOwnerResolver->getSiteOwner());
  63.         if (!$page) {
  64.             throw $this->createNotFoundException('Page introuvable');
  65.         }
  66.         return $this->render('public/react_page.html.twig', [
  67.             'page' => $page,
  68.             'initialData' => array_merge($this->getInitialData()),
  69.         ]);
  70.     }
  71.     /**
  72.      * Build initial data to inject into the HTML so React can render instantly
  73.      */
  74.     private function getInitialData(): array
  75.     {
  76.         return [
  77.             'compagnie' => $this->BuildCompanyData()['company'],
  78.             'menu' => $this->buildMenuData(),
  79.             'footer' => $this->buildFooterData(),
  80.             'services' => $this->buildServicesData(),
  81.             'contact' => $this->buildContactData(),
  82.         ];
  83.     }
  84.     private function buildMenuData(): array
  85.     {
  86.         $defaultItems = [
  87.             ['id' => 1'name' => 'Accueil''href' => '/accueil''visible' => true'order' => 1],
  88.             ['id' => 2'name' => 'Services''href' => '/services''visible' => true'order' => 2],
  89.             ['id' => 3'name' => 'Secteurs''href' => '/secteurs''visible' => true'order' => 3],
  90.             ['id' => 4'name' => 'Références''href' => '/references''visible' => true'order' => 4],
  91.             ['id' => 5'name' => 'À propos''href' => '/a-propos''visible' => true'order' => 5],
  92.             ['id' => 6'name' => 'FAQ''href' => '/faq''visible' => true'order' => 6],
  93.             ['id' => 7'name' => 'Contact''href' => '/contact''visible' => true'order' => 7],
  94.         ];
  95.         $defaultStyle = [
  96.             'position' => 'fixed',
  97.             'backgroundColor' => '#ffffff',
  98.             'textColor' => '#1f2937',
  99.             'hoverColor' => '#2563eb',
  100.             'logoText' => 'NovaCraft Cleaning',
  101.             'imgLogo' => '°',
  102.             'showPhone' => true,
  103.             'phoneNumber' => '01 84 25 36 78',
  104.             'showDevisButton' => true,
  105.         ];
  106.         $menuItems $this->settingRepository->get('menu_items'$defaultItems$this->siteOwnerResolver->getSiteOwner());
  107.         $menuStyle $this->settingRepository->get('menu_style'$defaultStyle$this->siteOwnerResolver->getSiteOwner());
  108.         $companyName $this->settingRepository->get('companyName'null$this->siteOwnerResolver->getSiteOwner());
  109.         if ($companyName && empty($menuStyle['logoText'])) {
  110.             $menuStyle['logoText'] = $companyName;
  111.         }
  112.         $companyPhone $this->settingRepository->get('companyPhone'null$this->siteOwnerResolver->getSiteOwner());
  113.         if ($companyPhone && empty($menuStyle['phoneNumber'])) {
  114.             $menuStyle['phoneNumber'] = $companyPhone;
  115.         }
  116.         $companyLogo $this->settingRepository->get('companyLogo'null$this->siteOwnerResolver->getSiteOwner());
  117.         if ($companyPhone && empty($menuStyle['imgLogo'])) {
  118.             $menuStyle['imgLogo'] = $companyLogo;
  119.         }
  120.         $visibleItems array_filter($menuItems, fn($item) => $item['visible'] ?? true);
  121.         usort($visibleItems, fn($a$b) => ($a['order'] ?? 0) <=> ($b['order'] ?? 0));
  122.         return [
  123.             'items' => array_values($visibleItems),
  124.             'style' => $menuStyle,
  125.         ];
  126.     }
  127.     private Function BuildCompanyData(): array
  128.     {
  129.         $companyKeys = [
  130.             'companyName''companySlogan''companyDescription''companyLogo',
  131.             'companyEmail''companyPhone''companyPhone2',
  132.             'companyAddress''companyCity''companyPostalCode''companyCountry',
  133.             'companyRegion''companyLatitude''companyLongitude',
  134.             'companyHours''companyOpeningHours',
  135.             'companySiret''companyVatNumber',
  136.             'companySeoDescription''companyKeywords''companyOgImage''serviceArea',
  137.             'facebook''instagram''linkedin''twitter''youtube'
  138.         ];
  139.         $allSettings $this->settingRepository->getAllAsArray($this->siteOwnerResolver->getSiteOwner());
  140.         $company array_intersect_key($allSettingsarray_flip($companyKeys));
  141.         return [
  142.             'company' => $company
  143.         ];
  144.     }
  145.     private Function buildContactData(): array
  146.     {
  147.         $companyKeys = [
  148.             'companyName''companyLogo',
  149.             'companyEmail''companyPhone''companyPhone2',
  150.             'companyAddress''companyCity''companyPostalCode''companyCountry',
  151.             'companyRegion''companyLatitude''companyLongitude',
  152.             'companyHours''companyOpeningHours',
  153.             'companySiret''companyVatNumber'
  154.         ];
  155.         $allSettings $this->settingRepository->getAllAsArray($this->siteOwnerResolver->getSiteOwner());
  156.         $contact array_intersect_key($allSettingsarray_flip($companyKeys));
  157.         return [
  158.             'contact' => $contact
  159.         ];
  160.     }
  161.     private function buildFooterData(): array
  162.     {
  163.         $companyKeys = [
  164.             'companyName''companySlogan''companyDescription''companyLogo',
  165.             'companyEmail''companyPhone''companyPhone2',
  166.             'companyAddress''companyCity''companyPostalCode''companyCountry',
  167.             'companyRegion''companyLatitude''companyLongitude',
  168.             'companyHours''companyOpeningHours',
  169.             'companySiret''companyVatNumber',
  170.             'companySeoDescription''companyKeywords''companyOgImage''serviceArea',
  171.             'facebook''instagram''linkedin''twitter''youtube'
  172.         ];
  173.         $allSettings $this->settingRepository->getAllAsArray($this->siteOwnerResolver->getSiteOwner());
  174.         $company array_intersect_key($allSettingsarray_flip($companyKeys));
  175.         $defaultFooterConfig = [
  176.             'showCta' => true,
  177.             'ctaTitle' => 'Besoin d\'un devis personnalisé ?',
  178.             'ctaDescription' => 'Contactez-nous dès aujourd\'hui pour obtenir une estimation gratuite et sans engagement.',
  179.             'ctaButtonText' => 'Demander un devis gratuit',
  180.             'ctaButtonLink' => '/devis',
  181.             'columns' => [
  182.                 ['id' => 1'title' => 'Nos services''type' => 'services''links' => []],
  183.                 ['id' => 2'title' => 'Entreprise''type' => 'custom''links' => [
  184.                     ['name' => 'À propos''href' => '/a-propos'],
  185.                     ['name' => 'FAQ''href' => '/faq'],
  186.                     ['name' => 'Contact''href' => '/contact']
  187.                 ]]
  188.             ],
  189.             'showContact' => true,
  190.             'showHours' => true,
  191.             'legalLinks' => [
  192.                 ['name' => 'Mentions légales''href' => '/mentions-legales'],
  193.                 ['name' => 'Politique de confidentialité''href' => '/politique-confidentialite']
  194.             ],
  195.             'copyrightText' => ''
  196.         ];
  197.         $footerConfig $this->settingRepository->get('footer'$defaultFooterConfig$this->siteOwnerResolver->getSiteOwner());
  198.         $services $this->serviceRepository->findAllPublished($this->siteOwnerResolver->getSiteOwner());
  199.         $pages $this->pageRepository->findAllPublished($this->siteOwnerResolver->getSiteOwner());
  200.         $columns = [];
  201.         foreach ($footerConfig['columns'] ?? [] as $column) {
  202.             $processedColumn = [
  203.                 'id' => $column['id'],
  204.                 'title' => $column['title'],
  205.                 'type' => $column['type'],
  206.                 'links' => []
  207.             ];
  208.             if ($column['type'] === 'services') {
  209.                 $processedColumn['links'] = array_map(fn($s) => [
  210.                     'name' => $s->getTitle(),
  211.                     'href' => '/services/' $s->getSlug()
  212.                 ], array_slice($services06));
  213.             } elseif ($column['type'] === 'pages') {
  214.                 $processedColumn['links'] = array_map(fn($p) => [
  215.                     'name' => $p->getTitle(),
  216.                     'href' => '/page/' $p->getSlug()
  217.                 ], array_slice($pages06));
  218.             } else {
  219.                 $processedColumn['links'] = $column['links'] ?? [];
  220.             }
  221.             $columns[] = $processedColumn;
  222.         }
  223.         return [
  224.             'company' => $company,
  225.             'config' => [
  226.                 'showCta' => $footerConfig['showCta'] ?? true,
  227.                 'ctaTitle' => $footerConfig['ctaTitle'] ?? 'Besoin d\'un devis personnalisé ?',
  228.                 'ctaDescription' => $footerConfig['ctaDescription'] ?? 'Contactez-nous dès aujourd\'hui pour obtenir une estimation gratuite.',
  229.                 'ctaButtonText' => $footerConfig['ctaButtonText'] ?? 'Demander un devis gratuit',
  230.                 'ctaButtonLink' => $footerConfig['ctaButtonLink'] ?? '/devis',
  231.                 'showContact' => $footerConfig['showContact'] ?? true,
  232.                 'showHours' => $footerConfig['showHours'] ?? true,
  233.                 'legalLinks' => $footerConfig['legalLinks'] ?? [
  234.                     ['name' => 'Mentions légales''href' => '/mentions-legales'],
  235.                     ['name' => 'Politique de confidentialité''href' => '/politique-confidentialite']
  236.                 ],
  237.                 'copyrightText' => $footerConfig['copyrightText'] ?? '',
  238.                 'template' => $footerConfig['template'] ?? 'standard',
  239.             ],
  240.             'columns' => $columns,
  241.         ];
  242.     }
  243.     private function buildServicesData(): array
  244.     {
  245.         $services $this->serviceRepository->findAllPublished($this->siteOwnerResolver->getSiteOwner());
  246.         return array_map(fn($s) => [
  247.             'id' => $s->getId(),
  248.             'title' => $s->getTitle(),
  249.             'slug' => $s->getSlug(),
  250.             'excerpt' => $s->getExcerpt(),
  251.             'image' => $s->getImage(),
  252.         ], $services);
  253.     }
  254.     private function buildBlocksData(?Page $page null): array
  255.     {
  256.         if (!$page) {
  257.             return [];
  258.         }
  259.         $blocks $this->blockRepository->findVisibleByPage($page);
  260.         return array_map(function($block) {
  261.             $data $block->getData() ?? [];
  262.             
  263.             // Si le bloc a un BlockType, enrichir avec les métadonnées
  264.             $blockTypeData = [];
  265.             if ($block->getBlockType()) {
  266.                 $blockType $block->getBlockType();
  267.                 $blockTypeData = [
  268.                     'blockTypeName' => $blockType->getName(),
  269.                     'blockTypeSlug' => $blockType->getSlug(),
  270.                     'blockTypeCategory' => $blockType->getCategory(),
  271.                 ];
  272.             }
  273.             return [
  274.                 'id' => $block->getId(),
  275.                 'type' => $block->getType(),
  276.                 'data' => $data,
  277.                 'layoutWidth' => $block->getLayoutWidth() ?? 12,
  278.                 'name' => $block->getName(),
  279.                 'position' => $block->getPosition(),
  280.                 ...$blockTypeData
  281.             ];
  282.         }, $blocks);
  283.     }
  284. }