<?php
namespace App\Controller;
use App\Entity\About;
use App\Entity\Actuality;
use App\Entity\ActualityCategory;
use App\Entity\ActualityPage;
use App\Entity\Composition;
use App\Entity\Contact;
use App\Entity\ContactPage;
use App\Entity\DefinitionPage;
use App\Entity\Departement;
use App\Entity\FullMemberPage;
use App\Entity\Join;
use App\Entity\ManuelPage;
use App\Entity\Newsletter;
use App\Entity\Page;
use App\Entity\PartenairePage;
use App\Entity\Publication;
use App\Entity\PublicationPage;
use App\Entity\ThemePublication;
use App\Entity\These;
use App\Entity\ThesePage;
use App\Form\ContactFormType;
use App\Form\NewsletterType;
use App\Repository\AboutRepository;
use App\Repository\ActualityCategoryRepository;
use App\Repository\ActualityLabelRepository;
use App\Repository\ActualityPageRepository;
use App\Repository\ActualityRepository;
use App\Repository\CompositionRepository;
use App\Repository\ContactPageRepository;
use App\Repository\DefinitionPageRepository;
use App\Repository\DefinitionRepository;
use App\Repository\DepartementRepository;
use App\Repository\FullMemberPageRepository;
use App\Repository\HomepageRepository;
use App\Repository\JoinRepository;
use App\Repository\ManuelPageRepository;
use App\Repository\PageRepository;
use App\Repository\PartenairePageRepository;
use App\Repository\PublicationPageRepository;
use App\Repository\PublicationRepository;
use App\Repository\ThemePublicationRepository;
use App\Repository\ThemeRepository;
use App\Repository\ThesePageRepository;
use App\Repository\TheseRepository;
use App\Service\DataImportCsv;
use Cofondateur\SocleTechniqueBundle\Sitemap\SitemapService;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\Persistence\ManagerRegistry;
use GuzzleHttp\Client;
use Pagerfanta\Adapter\ArrayAdapter;
use Pagerfanta\Doctrine\ORM\QueryAdapter;
use Pagerfanta\Exception\NotValidCurrentPageException;
use Pagerfanta\Pagerfanta;
use Psr\Log\LoggerInterface;
use SendinBlue\Client\Api\ContactsApi;
use SendinBlue\Client\ApiException;
use SendinBlue\Client\Configuration;
use SendinBlue\Client\Model\CreateContact;
use SendinBlue\Client\Model\CreateList;
use Symfony\Bridge\Twig\Mime\TemplatedEmail;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Mailer\Exception\TransportExceptionInterface;
use Symfony\Component\Mailer\MailerInterface;
use Symfony\Component\Mime\Address;
use Symfony\Component\Routing\Annotation\Route;
class FrontController extends AbstractController
{
/** @var ManagerRegistry */
private $em;
public function __construct(ManagerRegistry $em)
{
$this->em = $em;
}
/**
* @Route("/", name="app_homepage")
*/
public function index(HomepageRepository $homepageRepository): Response
{
$homepage = $homepageRepository->findUnique();
return $this->render('front/index.html.twig', [
'homepage' => $homepage,
]);
}
/**
* @Route("/association/a-propos", name="app_about_index")
*/
public function about(Request $request): Response
{
/** @var AboutRepository $repo */
$repo = $this->em->getRepository(About::class);
$page = $repo->findUnique();
return $this->render('front/About/index.html.twig', array('page' => $page));
}
/**
* @Route("/association/composition", name="app_composition_index")
*/
public function composition(Request $request): Response
{
/** @var CompositionRepository $repo */
$repo = $this->em->getRepository(Composition::class);
$page = $repo->findUnique();
return $this->render('front/Composition/index.html.twig', array('page' => $page));
}
/**
* @Route("/association/membres-titulaires", name="app_full_member_page_index")
*/
public function fullMemberPage(Request $request): Response
{
/** @var FullMemberPageRepository $repo */
$repo = $this->em->getRepository(FullMemberPage::class);
$page = $repo->findUnique();
return $this->render('front/FullMemberPage/index.html.twig', array('page' => $page));
}
/**
* @Route("/association/departements", name="app_departement_index")
*/
public function departement(Request $request): Response
{
/** @var DepartementRepository $repo */
$repo = $this->em->getRepository(Departement::class);
$page = $repo->findUnique();
return $this->render('front/Departement/index.html.twig', array('page' => $page));
}
/**
* @Route("/associations/partenaire", name="app_partenaire_page_index")
*/
public function partenairePage(Request $request): Response
{
/** @var PartenairePageRepository $repo */
$repo = $this->em->getRepository(PartenairePage::class);
$page = $repo->findUnique();
return $this->render('front/PartenairePage/index.html.twig', array('page' => $page));
}
/**
* @Route("/theme/{slugTheme}/{slugPage}", name="app_page_show")
*/
public function showPage(Request $request, string $slugTheme, string $slugPage, ThemeRepository $themeRepository, PageRepository $pageRepository, ThemePublicationRepository $themePublicationRepository): Response
{
if ($slugTheme !== 'publication') {
$theme = $themeRepository->findOneBy(['slug' => $slugTheme]);
$page = $pageRepository->findOneBy(['theme' => $theme, 'slug' => $slugPage]);
if (!$theme || !$page || $page->getTheme()->getId() !== $theme->getId()) {
throw $this->createNotFoundException();
}
} else {
$page = $pageRepository->findOneBy(['slug' => $slugPage, 'themePublication' => true]);
$theme = $themePublicationRepository->findUnique();
if (!$page) {
throw $this->createNotFoundException();
}
}
return $this->render('front/Page/show.html.twig', array(
'page' => $page,
'theme' => $theme
));
}
/**
* @Route("/publications/detail/{slug}", name="app_publication_show")
*/
public function showPublication(Request $request, Publication $publication): Response
{
return $this->render('front/Publication/show.html.twig', array('page' => $publication));
}
/**
* @Route("/publications/{page}", name="app_publication_list", requirements={"page"="\d+"}, defaults={"page": 1})
*/
public function listPublications(Request $request, $page): Response
{
/** @var PublicationRepository $repo */
$repo = $this->em->getRepository(Publication::class);
$qb = $repo->createQueryBuilder('e');
$qb->andWhere('e.activate = true');
$publications = new Pagerfanta(new QueryAdapter($qb->orderBy('e.date', 'DESC')));
$publications->setMaxPerPage(10);
$publications->setCurrentPage($page);
$pageNb = $page;
/** @var PublicationPageRepository $repo */
$repo = $this->em->getRepository(PublicationPage::class);
$page = $repo->findUnique();
return $this->render('front/Publication/list.html.twig', array(
'publications' => $publications,
'page' => $page,
'openTab' => $pageNb > 1
));
}
/**
* @Route("/theses/detail/{slug}", name="app_these_show")
*/
public function showThese(Request $request, These $these): Response
{
return $this->render('front/These/show.html.twig', array('page' => $these));
}
/**
* @Route("/theses/{page}", name="app_these_list", requirements={"page"="\d+"}, defaults={"page": 1})
*/
public function listTheses(Request $request, $page): Response
{
/** @var TheseRepository $repo */
$repo = $this->em->getRepository(These::class);
$qb = $repo->createQueryBuilder('e');
$qb->andWhere('e.activate = true');
$qb->orderBy('e.date', 'DESC');
$theses = new Pagerfanta(new QueryAdapter($qb));
$theses->setMaxPerPage(10);
$theses->setCurrentPage($page);
$pageNb = $page;
/** @var ThesePageRepository $repo */
$repo = $this->em->getRepository(ThesePage::class);
$page = $repo->findUnique();
return $this->render('front/These/list.html.twig', array(
'theses' => $theses,
'page' => $page,
'openTab' => $pageNb > 1
));
}
/**
* @Route("/actualites/detail/{slug}", name="app_actuality_show")
*/
public function showActuality(Request $request, Actuality $actuality): Response
{
return $this->render('front/Actuality/show.html.twig', array('page' => $actuality));
}
/**
* @Route("/actualites/{page}/{category}", name="app_actuality_list", requirements={"page"="\d+"}, defaults={"page": 1, "category": null})
*/
public function listActualitys(Request $request, $page, $category, ActualityCategoryRepository $actualityCategoryRepository, ActualityLabelRepository $actualityLabelRepository): Response
{
/** @var ActualityRepository $repo */
$repo = $this->em->getRepository(Actuality::class);
$qb = $repo->createQueryBuilder('e');
$qb->andWhere('e.activate = true');
$categoryActive = null;
if ($category !== null) {
$qb->leftJoin('e.category', 'c')
->addSelect('c')
->andWhere('c.slug = :category')
->setParameter('category', $category);
$categoryActive = $actualityCategoryRepository->findOneBy(['slug' => $category]);
}
$label = $request->query->get('label');
$labelActive = null;
if ($label !== null) {
$qb->leftJoin('e.labels', 'l')
->addSelect('l')
->andWhere('l.slug = :label')
->setParameter('label', $label);
$labelActive = $actualityLabelRepository->findOneBy(['slug' => $label]);
}
$actualitys = new Pagerfanta(new QueryAdapter($qb->orderBy('e.createdAt', 'DESC')));
$actualitys->setMaxPerPage(10);
$actualitys->setCurrentPage($page);
/** @var ActualityPageRepository $repo */
$repo = $this->em->getRepository(ActualityPage::class);
$page = $repo->findUnique();
return $this->render('front/Actuality/list.html.twig', array(
'actualities' => $actualitys,
'page' => $page,
'categoryActive' => $categoryActive,
'labelActive' => $labelActive,
));
}
/**
* @Route("/definitions", name="app_definition_page_index")
*/
public function definitionPage(Request $request, DefinitionRepository $definitionRepository): Response
{
/** @var DefinitionPageRepository $repo */
$repo = $this->em->getRepository(DefinitionPage::class);
$page = $repo->findUnique();
$definitions = $definitionRepository->findBy([], ['letter' => "ASC"]);
// Grouper les définitions par lettre
$letters = array_reduce($definitions, function ($acc, $definition) {
$letter = strtoupper($definition->getLetter());
if (!isset($acc[$letter])) {
$acc[$letter] = [];
}
$acc[$letter][] = $definition;
return $acc;
}, []);
// Trier chaque groupe de définitions par le champ `name`
foreach ($letters as &$group) {
usort($group, function ($a, $b) {
return strcmp($a->getName(), $b->getName());
});
}
return $this->render('front/DefinitionPage/index.html.twig', [
'page' => $page,
'letters' => $letters,
]);
}
/**
* @Route("/adherer", name="app_join_index")
*/
public function join(Request $request): Response
{
/** @var JoinRepository $repo */
$repo = $this->em->getRepository(Join::class);
$page = $repo->findUnique();
return $this->render('front/Join/index.html.twig', array('page' => $page));
}
/**
* @Route("/contact", name="app_contact_show")
*/
public function showContact(Request $request, EntityManagerInterface $em, MailerInterface $mailer, LoggerInterface $logger): Response
{
/** @var ContactPageRepository $repo */
$repo = $this->em->getRepository(ContactPage::class);
$page = $repo->findUnique();
$contact = new Contact;
$form = $this->createForm(ContactFormType::class, $contact);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$contact->setCreatedAt(new \DateTime());
$em->persist($contact);
$em->flush();
$recipients = $_ENV['MAIL_RECIPIENT'];
$recipients = explode(',', $recipients);
$datasMail = [
'name' => $contact->getFirstname() . ' ' . $contact->getName(),
'job' => $contact->getJob(),
'email' => $contact->getEmail(),
'phone' => $contact->getPhone(),
'message' => $contact->getMessage(),
'date' => $contact->getCreatedAt()->format('d/m/Y H:i'),
];
$email = (new TemplatedEmail())
->from(new Address($_ENV['MAIL_SENDER'], 'SFMG'))
->to(...$recipients)
->subject("Vous avez reçu une nouvelle demande de contact")
// path of the Twig template to render
->htmlTemplate('mail/contact.html.twig')
// pass variables (name => value) to the template
->context(["data" => $datasMail]);
try {
$mailer->send($email);
$this->addFlash('successContact', 'Merci nous avons reçu votre demande. Nous vous répondrons dans les plus brefs délais.');
} catch (TransportExceptionInterface $e) {
$this->addFlash('errorContact', 'Une erreur est survenue lors de l\'envoi du message. Merci de réessayer.');
$logger->error('Error sending contact email: ' . $e->getMessage());
}
}
return $this->render('front/Contact/show.html.twig', array(
'page' => $page,
'form' => $form->createView(),
));
}
/**
* @Route("/search", name="app_search_index")
*/
public function search(Request $request, ActualityRepository $actualityRepository, PageRepository $pageRepository, TheseRepository $theseRepository, PublicationRepository $publicationRepository, DefinitionRepository $definitionRepository): Response
{
$query = $request->get('query', ''); // Get the search query, default to an empty string
// Default to 1 if no specific page parameter is provided
$pageActualities = $request->query->getInt('actualities_page', 1);
$pagePages = $request->query->getInt('pages_page', 1);
$pageTheses = $request->query->getInt('theses_page', 1);
$pagePublications = $request->query->getInt('publications_page', 1);
$pagesDefined = [
'actualities' => $request->query->getInt('actualities_page'),
'pages' => $request->query->getInt('pages_page'),
'theses' => $request->query->getInt('theses_page'),
'publications' => $request->query->getInt('publications_page'),
];
$maxPerPage = 10; // Set the number of items per page
$result = [];
$result['actualities'] = [
'title' => 'Actualités',
];
$result['pages'] = [
'title' => 'Pages',
];
$result['theses'] = [
'title' => 'Thèses',
];
$result['publications'] = [
'title' => 'Publications',
];
$result['definitions'] = [
'title' => 'Définitions',
];
$result['lengthTotal'] = 0;
try {
// Actualities pagination
$qbActualities = $actualityRepository->createQueryBuilder('p')
->andWhere('p.title LIKE :query OR p.resume LIKE :query')
// Filtrer les actualités activées
->andWhere('p.activate = true')
// Joindre les sections liées à Actuality
->leftJoin('p.sections', 's')
->addSelect('s')
// Rechercher dans s.title
->orWhere('s.title LIKE :query')
// Joindre les paragraphs liés aux sections
->leftJoin('s.paragraphs', 'par')
->addSelect('par')
// Rechercher dans les propriétés de Paragraph
->orWhere('par.subTitle LIKE :query')
->orWhere('par.title LIKE :query')
->orWhere('par.text LIKE :query')
->orWhere('par.secondSubTitle LIKE :query')
->orWhere('par.secondTitle LIKE :query')
->orWhere('par.secondText LIKE :query')
->setParameter('query', '%' . $query . '%');
$actualities = $qbActualities->getQuery()->getResult();
$result['actualities']['data'] = $actualities;
$result['actualities']['length'] = count($actualities);
$result['lengthTotal'] += $result['actualities']['length'];
// Pages pagination
$pages = $pageRepository->createQueryBuilder('p')
->andWhere('p.title LIKE :query')
->andWhere('p.activate = true')
->andWhere('p.theme IS NOT NULL OR p.themePublication = true')
// Joindre les sections liées à Actuality
->leftJoin('p.sections', 's')
->addSelect('s')
// Rechercher dans s.title
->orWhere('s.title LIKE :query')
// Joindre les paragraphs liés aux sections
->leftJoin('s.paragraphs', 'par')
->addSelect('par')
// Rechercher dans les propriétés de Paragraph
->orWhere('par.subTitle LIKE :query')
->orWhere('par.title LIKE :query')
->orWhere('par.text LIKE :query')
->orWhere('par.secondSubTitle LIKE :query')
->orWhere('par.secondTitle LIKE :query')
->orWhere('par.secondText LIKE :query')
->setParameter('query', '%' . $query . '%')->getQuery()->getResult();
$result['pages']['data'] = $pages;
$result['pages']['length'] = count($pages);
$result['lengthTotal'] += $result['pages']['length'];
// Theses pagination
$qbThese = $theseRepository->createQueryBuilder('p')
->andWhere('p.title LIKE :query OR p.author LIKE :query')
->andWhere('p.activate = true')
// Joindre les sections liées à Actuality
->leftJoin('p.sections', 's')
->addSelect('s')
// Rechercher dans s.title
->orWhere('s.title LIKE :query')
// Joindre les paragraphs liés aux sections
->leftJoin('s.paragraphs', 'par')
->addSelect('par')
// Rechercher dans les propriétés de Paragraph
->orWhere('par.subTitle LIKE :query')
->orWhere('par.title LIKE :query')
->orWhere('par.text LIKE :query')
->orWhere('par.secondSubTitle LIKE :query')
->orWhere('par.secondTitle LIKE :query')
->orWhere('par.secondText LIKE :query')
->setParameter('query', '%' . $query . '%');
$theses = $qbThese->getQuery()->getResult();
$result['theses']['data'] = $theses;
$result['theses']['length'] = count($theses);
$result['lengthTotal'] += $result['theses']['length'];
// Publications pagination
$qbPublication = $publicationRepository->createQueryBuilder('p')
->andWhere('p.title LIKE :query OR p.author LIKE :query')
->andWhere('p.activate = true')
// Joindre les sections liées à Actuality
->leftJoin('p.sections', 's')
->addSelect('s')
// Rechercher dans s.title
->orWhere('s.title LIKE :query')
// Joindre les paragraphs liés aux sections
->leftJoin('s.paragraphs', 'par')
->addSelect('par')
// Rechercher dans les propriétés de Paragraph
->orWhere('par.subTitle LIKE :query')
->orWhere('par.title LIKE :query')
->orWhere('par.text LIKE :query')
->orWhere('par.secondSubTitle LIKE :query')
->orWhere('par.secondTitle LIKE :query')
->orWhere('par.secondText LIKE :query')
->setParameter('query', '%' . $query . '%');
$publications = $qbPublication->getQuery()->getResult();
$result['publications']['data'] = $publications;
$result['publications']['length'] = count($publications);
$result['lengthTotal'] += $result['publications']['length'];
$qbDefinition = $definitionRepository->createQueryBuilder('p')
->andWhere('p.name LIKE :query OR p.definition LIKE :query')
->setParameter('query', '%' . $query . '%');
$definitions = $qbDefinition->getQuery()->getResult();
$result['definitions']['data'] = $definitions;
$result['definitions']['length'] = count($definitions);
$result['lengthTotal'] += $result['definitions']['length'];
} catch (NotValidCurrentPageException $e) {
// Handle the case where the current page is not valid
return $this->redirectToRoute('app_search_index', ['query' => $query, 'actualities_page' => 1, 'pages_page' => 1, 'theses_page' => 1, 'publications_page' => 1]);
}
return $this->render('front/Search/index.html.twig', [
'result' => $result,
'query' => $query,
'pageDefined' => $pagesDefined,
]);
}
/**
* @Route("subsribe-newsletter", name="app_subscribe_newsletter")
*/
public function subscribe(Request $request, EntityManagerInterface $em, MailerInterface $mailer, LoggerInterface $logger): Response
{
$newsletter = new Newsletter();
$form = $this->createForm(NewsletterType::class, $newsletter);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$newsletter->setCreatedAt(new \DateTimeImmutable());
$em->persist($newsletter);
$em->flush();
$email = $newsletter->getEmail();
$name = $newsletter->getName();
if (empty($email)) {
return $this->redirectToRoute('app_homepage');
}
$config = Configuration::getDefaultConfiguration()->setApiKey('api-key', 'your-api-key');
$contactsApi = new ContactsApi(new Client(), $config);
try {
$contactsApi->getContactInfo($email);
$this->addFlash('successNewsletter', "Votre email est déjà inscrit.");
} catch (ApiException $e) {
$listId = 128;
$createContact = new CreateContact([
'email' => $email,
'listIds' => [$listId],
'attributes' => ['LASTNAME' => $name],
'updateEnabled' => true
]);
try {
$contactsApi->createContact($createContact);
$recipients = explode(',', $_ENV['MAIL_RECIPIENT']);
$datasMail = ['name' => $name, 'email' => $email, 'date' => (new \DateTime())->format('d/m/Y H:i')];
$email = (new TemplatedEmail())
->from(new Address($_ENV['MAIL_SENDER'], 'SFMG'))
->to(...$recipients)
->subject("Une nouvelle personne s'est inscrite à la newsletter")
->htmlTemplate('mail/newsletter.html.twig')
->context(["data" => $datasMail]);
$mailer->send($email);
$this->addFlash('successNewsletter', 'L\'email ' . $email . " a bien été ajouté à notre newsletter.");
} catch (\Exception $e) {
$this->addFlash('errorNewsletter', "Une erreur s'est produite, merci de réessayer.");
}
}
return $this->redirectToRoute('app_homepage');
}
return $this->redirectToRoute('app_homepage');
}
public function getNewsletterForm(): Response
{
$newsletter = new Newsletter();
$form = $this->createForm(NewsletterType::class, null, [
'confidentiality_path' => $this->generateUrl('app_confidentiality'),
]);
return $this->render('commons/_newsletter_form.html.twig', [
'newsletterForm' => $form->createView(),
]);
}
/**
* @Route("/publications/manuels", name="app_manuel_page_index")
*/
public function manuelPage(Request $request): Response
{
/** @var ManuelPageRepository $repo */
$repo = $this->em->getRepository(ManuelPage::class);
$page = $repo->findUnique();
return $this->render('front/ManuelPage/index.html.twig', array('page' => $page));
}
/**
* @Route("/sitemap.{_format}", name="app_sitemap_front", format="html")
*/
public function sitemap(Request $request, SitemapService $sitemapService): Response
{
$format = $request->getRequestFormat();
$links = $sitemapService->generateSitemap();
$template = 'front/';
if ($format === 'xml') {
$template .= 'sitemap/index.xml.twig';
} else {
$template .= 'sitemap/index.html.twig';
}
return $this->render($template, [
'sitemapLinkGroups' => $links
]);
}
/**
* @Route("/mentions-legales", name="app_legal_terms")
*/
public function legalTerms(): Response
{
return $this->render('front/legalTerms.html.twig');
}
/**
* @Route("/confidentialite", name="app_confidentiality")
*/
public function confidentiality(): Response
{
return $this->render('front/confidentiality.html.twig',array(
'siteName' => $_ENV['SITENAME'],
'hostname' => $_ENV['HOSTNAME']
));
}
}