<?php
declare(strict_types=1);
namespace App\Controller\Buzz;
use App\Helper\Utils;
use App\Controller\EntityUsingController;
use App\Form\Models\NewslettersInscription;
use App\Form\Type\NewslettersInscriptionType;
use App\Services\ManagerEntity\UtilisateursNewsletterManagers;
use App\Services\MetaTag;
use App\Services\Buzz\CanonicalUrlService;
use App\Repository\Buzz\BuzzActualitesRepository;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
class NewslettersController extends EntityUsingController
{
private const DEFAULT_LANG = 'fr';
private const DEFAULT_ID_PAYS = '33';
private const DEFAULT_LIMIT = 25;
private const MONTHS_BACK = 2;
private const BASE_NEWSLETTER_URL = 'https://www.fusacq.com/buzz/newsletter';
private const ID_PAYS_MAP = [
'fr' => '33',
'be' => '32',
'ch' => '41',
'ca' => '01',
];
private MetaTag $metaTag;
private BuzzActualitesRepository $buzzActualitesRepository;
private CanonicalUrlService $canonicalUrlService;
/**
* Constructeur du contrôleur des newsletters Buzz
*
* @param MetaTag $metaTag
* @param BuzzActualitesRepository $buzzActualitesRepository
* @param CanonicalUrlService $canonicalUrlService
*/
public function __construct(
MetaTag $metaTag,
BuzzActualitesRepository $buzzActualitesRepository,
CanonicalUrlService $canonicalUrlService
) {
$this->metaTag = $metaTag;
$this->buzzActualitesRepository = $buzzActualitesRepository;
$this->canonicalUrlService = $canonicalUrlService;
}
/**
* Affiche le formulaire d'abonnement à la newsletter et gère la soumission
*
* @param Request $request
* @param string $codePays
* @param UtilisateursNewsletterManagers $unm
* @return Response Réponse HTTP
*/
public function inscription(Request $request, string $codePays, UtilisateursNewsletterManagers $unm): Response
{
$cleanCodePays = $this->cleanCodePays($codePays);
$codePaysWithUnderScore = '_' . $cleanCodePays . '_';
$routeName = (string) $request->attributes->get('_route');
$metaTag = $this->buildMetaTagInscription($cleanCodePays)
->setTitle("S'inscrire à la newsletter Fusacq | Actualités fusion-acquisition et reprise d'entreprise")
->setDescription("Inscrivez-vous gratuitement à la newsletter Fusacq et recevez les dernières opportunités et actualités du marché de la fusion-acquisition, cession et reprise d'entreprise en France.");
$hreflangLinks = $this->canonicalUrlService->getBuzzHreflangLinks(
'buzz_newsletters_inscription',
[],
null,
$cleanCodePays
);
$model = $this->createNewsletterModel($request);
$form = $this->createForm(NewslettersInscriptionType::class, $model, [
'action' => $this->generateUrl($routeName, ['codePays' => $codePaysWithUnderScore]),
'method' => 'POST',
]);
$form->handleRequest($request);
if ($form->isSubmitted()) {
if ($form->isValid()) {
$data = $form->getData();
$unm->inscription($data);
$this->addFlash("success_inscri_news", "votre inscription a nos newsletters a bien ete prise en compte");
} else {
$this->addFlash("error_inscri_news", "votre inscription a nos newsletters a echoue");
}
}
return $this->render('buzz/newsletters/inscription.html.twig', [
'form' => $form->createView(),
'metaTag' => $metaTag,
'codePays' => $cleanCodePays,
'codePaysWithUnderScore' => $codePaysWithUnderScore,
'lang' => self::DEFAULT_LANG,
'currentRoute' => $routeName,
'authFrom' => (string) $request->query->get('authFrom', ''),
'hreflangLinks' => $hreflangLinks,
]);
}
/**
* Affiche la liste des archives de newsletters
*
* @param Request $request
* @param string $codePays
* @param UtilisateursNewsletterManagers $unm
* @return Response Réponse HTTP
*/
public function liste(Request $request, string $codePays): Response
{
$cleanCodePays = $this->cleanCodePays($codePays);
$routeName = (string) $request->attributes->get('_route');
$metaTag = $this->buildMetaTagListe($cleanCodePays);
$hreflangLinks = $this->canonicalUrlService->getBuzzHreflangLinks(
'buzz_newsletters_liste',
[],
null,
$cleanCodePays
);
$idPays = $this->getIdPays($codePays, $request);
$dateRange = $this->getDateRange();
$page = max(1, (int) $request->query->get('id_page', 1));
$offset = ($page - 1) * self::DEFAULT_LIMIT;
$total = $this->buzzActualitesRepository->countNewslettersInterval(
$dateRange['debut'],
$dateRange['fin'],
$idPays
);
$rows = $this->buzzActualitesRepository->getNewslettersInterval(
$dateRange['debut'],
$dateRange['fin'],
self::DEFAULT_LIMIT,
$offset,
$idPays
);
$totalPages = (int) ceil($total / self::DEFAULT_LIMIT);
$paginationLinks = $this->buildPaginationLinks(
$cleanCodePays,
$page,
$totalPages,
$idPays,
$dateRange
);
$rows = $this->formatNewsletterRows($rows, $codePays, $idPays);
return $this->render('buzz/newsletters/liste.html.twig', [
'metaTag' => $metaTag,
'codePays' => $cleanCodePays,
'codePaysWithUnderScore' => $codePays,
'lang' => self::DEFAULT_LANG,
'currentRoute' => $routeName,
'authFrom' => (string) $request->query->get('authFrom', ''),
'id_pays' => $idPays,
'date_debut_affichage' => $this->formatDateForDisplay($dateRange['debut']),
'date_fin_affichage' => $this->formatDateForDisplay($dateRange['fin']),
'rows' => $rows,
'hreflangLinks' => $hreflangLinks,
'paginationLinks' => $paginationLinks,
'page' => $page,
'last_page' => $totalPages,
'show_pagination' => $total > self::DEFAULT_LIMIT,
'total' => $total,
]);
}
/**
* Nettoie le code pays en retirant les underscores
*
* @param string $codePays
* @return string Code
*/
private function cleanCodePays(string $codePays): string
{
return str_replace('_', '', $codePays);
}
/**
* Construit les meta tags pour la page d'inscription
*
* @param string $cleanCodePays
* @return MetaTag Instance
*/
private function buildMetaTagInscription(string $cleanCodePays): MetaTag
{
$canonicalUrl = $this->canonicalUrlService->getBuzzNewslettersInscriptionCanonical($cleanCodePays);
return $this->metaTag
->setTitle("Newsletters FUSACQ Buzz - Inscription")
->setDescription("Inscrivez-vous aux newsletters FUSACQ Buzz (quotidienne et internationale).")
->setCanonical($canonicalUrl);
}
/**
* Construit les meta tags pour la page de liste
*
* @param string $cleanCodePays
* @return MetaTag Instance
*/
private function buildMetaTagListe(string $cleanCodePays): MetaTag
{
$canonicalUrl = $this->canonicalUrlService->getBuzzNewslettersListeCanonical($cleanCodePays);
return $this->metaTag
->setTitle("Newsletters FUSACQ Buzz - Archives")
->setDescription("Consultez les archives des newsletters quotidiennes FUSACQ Buzz.")
->setCanonical($canonicalUrl);
}
/**
* Crée le modèle d'inscription newsletter avec l'email depuis l'URL si présent
*
* @param Request $request
* @return NewslettersInscription
*/
private function createNewsletterModel(Request $request): NewslettersInscription
{
$model = new NewslettersInscription();
$emailFromUrl = $request->query->get('email');
if ($emailFromUrl !== null) {
$model->mail = (string) $emailFromUrl;
}
return $model;
}
/**
* Récupère l'ID pays à partir du code pays ou de la requête
*
* @param string $codePays
* @param Request $request
* @return string ID pays
*/
private function getIdPays(string $codePays, Request $request): string
{
$cleanCodePays = strtolower($this->cleanCodePays($codePays));
$idPays = self::ID_PAYS_MAP[$cleanCodePays] ?? self::DEFAULT_ID_PAYS;
return (string) $request->query->get('id_pays', $idPays);
}
/**
* Récupère la plage de dates pour les archives (2 derniers mois)
*
* @return array{debut: string, fin: string}
*/
private function getDateRange(): array
{
$dateFin = date('Ymd');
$dateDebut = (new \DateTimeImmutable())
->modify('-' . self::MONTHS_BACK . ' months')
->format('Ymd');
return [
'debut' => $dateDebut,
'fin' => $dateFin,
];
}
/**
* Construit les liens de pagination
*
* @param string $cleanCodePays
* @param int $page
* @param int $totalPages
* @param string $idPays
* @param array{debut: string, fin: string}
* @return array
*/
private function buildPaginationLinks(
string $cleanCodePays,
int $page,
int $totalPages,
string $idPays,
array $dateRange
): array {
$queryParams = [
'id_pays' => $idPays,
'date_debut' => $dateRange['debut'],
'date_fin' => $dateRange['fin'],
];
return $this->canonicalUrlService->getBuzzPaginationLinksWithQuery(
'buzz_newsletters_liste',
[],
null,
$cleanCodePays,
$page,
$totalPages,
$queryParams
);
}
/**
* Formate les lignes de newsletters pour l'affichage
*
* @param array $rows
* @param string $codePaysWithUnderscore
* @param string $idPays
* @return array Lignes formatées
*/
private function formatNewsletterRows(array $rows, string $codePaysWithUnderscore = '_fr_', string $idPays = '33'): array
{
foreach ($rows as &$row) {
$row['date_affichage'] = $this->formatDateForDisplay($row['date_envoi'], '/');
$pattern = "/Le buzz du ([0-9a-zA-Zéüû ]*) :/";
$titre = preg_replace($pattern, "", $row['titre']);
$row['titre'] = $titre;
$slug = Utils::slugify($row['titre']);
$slug = str_replace('-.', '.', $slug);
$url = $this->generateUrl('buzz_newsletter_show', [
'idNewsletter' => $row['id_newsletter'],
'slug' => $slug,
'codePays' => $codePaysWithUnderscore
], UrlGeneratorInterface::ABSOLUTE_URL);
// Ajouter id_pays dans l'URL si différent du pays par défaut
if ($idPays !== self::DEFAULT_ID_PAYS) {
$url .= '?id_pays=' . $idPays;
}
$row['url'] = $url;
}
unset($row);
return $rows;
}
/**
* Affiche une newsletter individuelle par son ID
*
* @param Request $request
* @param int $idNewsletter
* @param string $codePays
* @return Response
*/
public function show(Request $request, int $idNewsletter, string $codePays = '_fr_'): Response
{
$idPays = $this->getIdPays($codePays, $request);
$newsletter = $this->buzzActualitesRepository->findNewsletterByIdAndPays($idNewsletter, $idPays);
if (!$newsletter) {
throw $this->createNotFoundException('Newsletter introuvable');
}
$contenuHtml = $newsletter['contenu_html'] ?? '';
if (empty($contenuHtml)) {
throw $this->createNotFoundException('Contenu de la newsletter introuvable');
}
if ($idNewsletter <= 1728) {
$contenuHtml = str_replace(
"https://www.fusacq.com/buzz/images/logo_bleu.png",
"https://content.fusacq.com/static/dev-fusacq/buzz/images/logo_bleu.png",
$contenuHtml
);
}
if (isset($newsletter['date_envoi']) && $newsletter['date_envoi']) {
$dateEnvoi = \DateTime::createFromFormat('Ymd', $newsletter['date_envoi']);
if ($dateEnvoi) {
$dateSuivante = clone $dateEnvoi;
$dateSuivante->modify('+1 day');
$dateSuivanteYmd = $dateSuivante->format('Ymd');
$urlActualitesDateSuivante = $this->generateUrl('buzz_actualite_par_date', [
'date' => $dateSuivanteYmd,
'codePays' => $codePays
], UrlGeneratorInterface::ABSOLUTE_URL);
$contenuHtml = str_replace('${urlActualitesDateSuivante}', $urlActualitesDateSuivante, $contenuHtml);
$contenuHtml = str_replace('<!--###urlActualitesDateSuivante###-->', $urlActualitesDateSuivante, $contenuHtml);
}
}
return new Response($contenuHtml, Response::HTTP_OK, [
'Content-Type' => 'text/html; charset=utf-8',
]);
}
/**
* Convertit le code pays en ID pays
*
* @param string $codePays
* @return string
*/
private function getIdPaysFromCodePays(string $codePays): string
{
return self::ID_PAYS_MAP[$codePays] ?? self::DEFAULT_ID_PAYS;
}
/**
* Formate une date au format Ymd pour l'affichage
*
* @param string $dateYmd
* @param string $separator
* @return string Date formatée
*/
private function formatDateForDisplay(string $dateYmd, string $separator = '-'): string
{
return substr($dateYmd, 6, 2) . $separator . substr($dateYmd, 4, 2) . $separator . substr($dateYmd, 0, 4);
}
}