<?php
namespace App\Controller;
use App\Datatable\CommunicationDesabonnementTable;
use App\Datatable\MailingCommunicationTable;
use App\Entity\AccountingFirm;
use App\Entity\CommunicationDesabonnement;
use App\Entity\CommunicationImage;
use App\Entity\MailingCommunication;
use App\Entity\MailingTask;
use App\Form\CommunicationCampaignAccountingFirmsType;
use App\Form\CommunicationCampaignDateType;
use App\Form\CommunicationCampaignFiltersType;
use App\Form\CommunicationCampaignMailType;
use App\Form\CommunicationCampaignNameType;
use App\Message\MailingProcessMessage;
use App\Repository\AccountingFirmRepository;
use App\Repository\CommunicationDesabonnementRepository;
use App\Repository\MailingCommunicationRepository;
use App\Repository\ModuleTypeRepository;
use App\Repository\ModuleTypeValueRepository;
use App\Services\Mailing;
use App\Services\SellsyService;
use DateTimeZone;
use Doctrine\ORM\EntityManagerInterface;
use Psr\Cache\CacheItemPoolInterface;
use Qferrer\Mjml\Twig\MjmlExtension;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Component\Messenger\MessageBusInterface;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Serializer\SerializerInterface;
use Vich\UploaderBundle\Storage\StorageInterface;
use Vich\UploaderBundle\Templating\Helper\UploaderHelper;
class CommunicationController extends AbstractController
{
protected $sellsyService;
protected $messageBus;
public function __construct(ParameterBagInterface $parameterBag, EntityManagerInterface $em, MessageBusInterface $messageBus, SellsyService $sellsyService)
{
$this->sellsyService = $sellsyService;
$this->messageBus = $messageBus;
}
#[Route('/communication/update-types', name: 'app_communication_update_types')]
#[IsGranted('ROLE_ADMIN')]
public function updateTypes()
{
$this->sellsyService->getCustomFields();
$this->addFlash('success', 'Les filtres ont été mis à jour depuis Sellsy');
return $this->redirectToRoute("communication_campagnes");
}
#[Route('/communication/update-all-accountingfirm/{id}', name: 'app_communication_update_all_accoutingfirm', defaults: ['id' => null])]
#[IsGranted('ROLE_ADMIN')]
public function updateAllAccountingFirm(int $id): \Symfony\Component\HttpFoundation\RedirectResponse
{
$this->sellsyService->synchroModuleSellsyAllAccountingFirm();
$this->addFlash('success', 'Les modules des cabinets ont été mis à jour depuis Sellsy');
if ($id != null) {
return $this->redirectToRoute("communication_campagnes_create_filters", ['id' => $id]);
}
return $this->redirectToRoute("communication_campagnes");
}
#[Route('/communication/update-one-accountingfirm/{id}', name: 'app_communication_update_one_accoutingfirm')]
#[IsGranted('ROLE_ADMIN')]
public function updateOneAccountingFirm(AccountingFirm $accountingFirm)
{
$this->sellsyService->synchroModuleSellsyOneAccountingFirm($accountingFirm);
$this->addFlash('success', 'Les modules du cabinet '. $accountingFirm->getName() .' ont été mis à jour depuis Sellsy');
return $this->redirectToRoute("communication_campagnes");
}
#[Route('/communication/search/{idSellsy}', name: 'app_communication_search')]
#[IsGranted('ROLE_ADMIN')]
public function searchAccountingFirm(Int $idSellsy, ModuleTypeRepository $moduleTypeRepository): Response
{
$moduleType = $moduleTypeRepository->findBy(['idSellsy' => $idSellsy])[0];
$this->sellsyService->searchAccountingFirmByCustomField([['id' => $moduleType->getId()]]);
return $this->render('communication/index.html.twig', [
'controller_name' => 'CommunicationController',
]);
}
#[Route(path: '/communication/desabonnement/listing', name: 'communication_desabonnement_list', methods: ['GET', 'POST'])]
#[IsGranted('ROLE_ADMIN')]
public function desabonnementList(Request $request, CommunicationDesabonnementTable $datatable): Response
{
$table = $datatable->buildTable();
$table->handleRequest($request);
if ($table->isCallback()) {
return $table->getResponse();
}
return $this->render('communication_desabonnement/index.html.twig', [
'datatable' => $table
]);
}
#[Route(path: '/communication/desabonnement/delete/{id}', name: 'communication_desabonnement_delete', methods: ['POST'])]
#[IsGranted('ROLE_ADMIN')]
public function delete(Request $request, CommunicationDesabonnement $communicationDesabonnement): Response
{
if ($this->isCsrfTokenValid('delete' . $communicationDesabonnement->getId(), $request->request->get('_token'))) {
$entityManager = $this->getDoctrine()->getManager();
$entityManager->remove($communicationDesabonnement);
$entityManager->flush();
}
return $this->redirectToRoute('communication_desabonnement_list');
}
#[Route(path: '/communication/campagnes/', name: 'communication_campagnes')]
#[IsGranted('ROLE_ADMIN')]
public function campagnes(Request $request, MailingCommunicationTable $mailingCommunicationTable): Response
{
$table = $mailingCommunicationTable->buildTable();
$table->handleRequest($request);
if ($table->isCallback()) {
return $table->getResponse();
}
return $this->render('communication/index.html.twig', [
'datatable' => $table
]);
}
#[Route(path: '/communication/delete/{id}', name: 'communication_delete', methods: ['POST'])]
#[IsGranted('ROLE_ADMIN')]
public function deleteCampaign(Request $request, MailingCommunication $mailingCommunication): Response
{
if ($this->isCsrfTokenValid('delete' . $mailingCommunication->getId(), $request->request->get('_token'))) {
$entityManager = $this->getDoctrine()->getManager();
$tasks = $mailingCommunication->getMailingTasks();
foreach ($tasks as $task) {
$task->setMailingCommunication(null);
$entityManager->persist($task);
}
$entityManager->remove($mailingCommunication);
$entityManager->flush();
}
return $this->redirectToRoute('communication_campagnes');
}
#[Route(path: '/communication/campagnes/create/name/{id}', name: 'communication_campagnes_create_name', defaults: ['id' => null] )]
#[IsGranted('ROLE_ADMIN')]
public function campagnesCreateName(Request $request, EntityManagerInterface $em, ?int $id = null, MailingCommunicationRepository $mailingCommunicationRepository): Response
{
$campaign = null;
if ($id != null) {
$campaign = $mailingCommunicationRepository->findOneBy(['id' => $id]);
}
if (!$campaign) {
$campaign = new MailingCommunication;
}
$form = $this->createForm(CommunicationCampaignNameType::class, $campaign, [
'user' => $this->getUser()
]);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$campaign->setStatus("ON_CREATE");
$em->persist($campaign);
$em->flush();
return $this->redirectToRoute('communication_campagnes_create_filters', ['id' => $campaign->getId()]);
}
return $this->render('communication/create_campaign_name.html.twig', [
'form' => $form->createView()
]);
}
#[Route(path: '/communication/campagnes/create/filters/{id}', name: 'communication_campagnes_create_filters' )]
#[IsGranted('ROLE_ADMIN')]
public function campagnesCreateSelectFilters(Request $request, EntityManagerInterface $em, int $id, MailingCommunicationRepository $mailingCommunicationRepository, ModuleTypeRepository $moduleTypeRepository): Response
{
if ($id == null) {
$this->addFlash('error', 'Aucune campagne n\'a été trouvé.');
return $this->redirectToRoute("communication_campagnes");
}
$campaign = $mailingCommunicationRepository->findOneBy(['id' => $id]);
if ($campaign == null) {
$this->addFlash('error', 'Aucune campagne n\'a été trouvé avec cet identifiant.');
return $this->redirectToRoute("communication_campagnes");
}
$widgets = $moduleTypeRepository->findBy(['parentName' => "Widgets"]);
$modules = $moduleTypeRepository->findBy(['parentName' => "Modules"]);
$services = $moduleTypeRepository->findBy(['parentName' => "Services"]);
$cabinetAge = $moduleTypeRepository->findBy(['parentName' => "L'âge du cabinet"]);
$partenariat = $moduleTypeRepository->findBy(['parentName' => "Partenariats"]);
$acquisition = $moduleTypeRepository->findBy(['parentName' => "Acquisition"]);
$others = [];
//Offre
$others[] = $moduleTypeRepository->findOneBy(['idSellsy' => 3858901]);
//Date de création
$others[] = $moduleTypeRepository->findOneBy(['idSellsy' => 125538]);
// tout les cabinets de lagence
$others[] = $moduleTypeRepository->findOneBy(['idSellsy' => 3412593]);
// sites interne
$others[] = $moduleTypeRepository->findOneBy(['idSellsy' => 4008187]);
// sites externe
$others[] = $moduleTypeRepository->findOneBy(['idSellsy' => 4008188]);
// tutoiement
$others[] = $moduleTypeRepository->findOneBy(['idSellsy' => 275413]);
$form = $this->createForm(CommunicationCampaignFiltersType::class, $campaign);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$filtersJson = $form->get('filtersJson')->getData();
$filtersArray = json_decode($filtersJson, true);
$campaign->setFilters($filtersArray);
$em->persist($campaign);
$em->flush();
return $this->redirectToRoute('communication_campagnes_create_accounting_firm', ['id' => $campaign->getId()]);
}
return $this->render('communication/select.html.twig', [
'widgets' => $widgets,
'modules' => $modules,
'services' => $services,
'cabinetAge' => $cabinetAge,
'partenariats' => $partenariat,
'acquisitions' => $acquisition,
'others' => $others,
'form' => $form->createView(),
'campaign' => $campaign,
]);
}
#[Route(path: '/communication/campagnes/create/accounting-firms/{id}', name: 'communication_campagnes_create_accounting_firm' )]
#[IsGranted('ROLE_ADMIN')]
public function campagnesCreateSelectAccountingFirms(Request $request, EntityManagerInterface $em, int $id, MailingCommunicationRepository $mailingCommunicationRepository, CommunicationDesabonnementRepository $communicationDesabonnementRepository): Response
{
if ($id == null) {
$this->addFlash('error', 'Aucune campagne n\'a été trouvé.');
return $this->redirectToRoute("communication_campagnes");
}
$campaign = $mailingCommunicationRepository->findOneBy(['id' => $id]);
if ($campaign == null) {
$this->addFlash('error', 'Aucune campagne n\'a été trouvé avec cet identifiant.');
return $this->redirectToRoute("communication_campagnes");
}
//récupération des cabinets répondants aux critères
$accountingFirms = $this->sellsyService->getAccountingFirmFromFilters($campaign->getFilters());
// on enlève les cabinets qui se sont désabonnées
$desabonnements = $communicationDesabonnementRepository->findAll();
$desabonnementsEmails = array_map(function($desabonnement) {
return $desabonnement->getEmail();
}, $desabonnements);
$form = $this->createForm(CommunicationCampaignAccountingFirmsType::class, $campaign);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$WithAccountingFirmJson = $form->get('accountingFirmsSelectedJson')->getData();
$WithoutAccountingFirmJson = $form->get('accountingFirmsUnselectedJson')->getData();
$WithAccountingFirmArray = json_decode($WithAccountingFirmJson, true);
$WithoutAccountingFirmArray = json_decode($WithoutAccountingFirmJson, true);
$campaign->setIdsAccountingFirmSelected($WithAccountingFirmArray);
$campaign->setIdsAccountingFirmUnselected($WithoutAccountingFirmArray);
$em->persist($campaign);
$em->flush();
return $this->redirectToRoute('communication_campagnes_create_mail_editor', ['id' => $campaign->getId()]);
}
return $this->render('communication/selectAccountingFirms.html.twig', [
'accountingFirms' => $accountingFirms,
'desabonnements' => $desabonnementsEmails,
'form' => $form->createView(),
'campaign' => $campaign
]);
}
#[Route(path: '/communication/campagnes/create/mail-editor/{id}', name: 'communication_campagnes_create_mail_editor' )]
#[IsGranted('ROLE_ADMIN')]
public function campagnesCreateMailEditor(Request $request, EntityManagerInterface $em, int $id, MailingCommunicationRepository $mailingCommunicationRepository, KernelInterface $kernel, StorageInterface $vichStorage, AccountingFirmRepository $accountingFirmRepository): Response
{
if ($id == null) {
$this->addFlash('error', 'Aucune campagne n\'a été trouvé.');
return $this->redirectToRoute("communication_campagnes");
}
$campaign = $mailingCommunicationRepository->findOneBy(['id' => $id]);
if ($campaign == null) {
$this->addFlash('error', 'Aucune campagne n\'a été trouvé avec cet identifiant.');
return $this->redirectToRoute("communication_campagnes");
}
if ($kernel->getEnvironment() == 'dev') {
$mediaViewerUrl = "https://actucontent.loc:8000/";
// $mediaViewerUrl = "https://actucontent.lagence.expert/";
} else {
$mediaViewerUrl = "https://actucontent.lagence.expert/";
}
$accountingFirm = $this->getUser()->getAccountingFirm();
$filePath = $vichStorage->resolvePath($accountingFirm, 'tmpMailingHeader');
$base64Img = null;
if (file_exists($filePath)) {
$mimeType = mime_content_type($filePath);
$fileContent = file_get_contents($filePath);
$base64Img = 'data:' . $mimeType . ';base64,' . base64_encode($fileContent);
}
$accountingFirmJson = null;
if ($accountingFirm) {
$accountingFirmTmp = $accountingFirmRepository->findOneBy(['id' => $accountingFirm->getId()]);
// Nettoyage des valeurs pour éviter les problèmes de JSON
$address = trim(preg_replace('/\s+/', ' ', $accountingFirmTmp->getAddress() . " " . $accountingFirmTmp->getZipCode() . " " . $accountingFirmTmp->getCity()));
$url = trim($accountingFirmTmp->getUrl());
$phone = trim(preg_replace('/\s+/', ' ', $accountingFirmTmp->getPhone()));
$accountingFirmArray = [
'id' => $accountingFirmTmp->getId(),
'name' => trim($accountingFirmTmp->getName()),
'logo' => $base64Img,
'address' => $address,
'email' => trim($accountingFirmTmp->getEmail()),
'phone' => $phone,
'site' => $url,
];
$accountingFirmJson = json_encode($accountingFirmArray, JSON_HEX_QUOT | JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_UNESCAPED_UNICODE);
$accountingFirmJson = base64_encode($accountingFirmJson);
}
$form = $this->createForm(CommunicationCampaignMailType::class, $campaign);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$mjmlStructure = json_decode($form->get('mjmlStructure')->getData(), true);
$tmpMjmlStructure = $mjmlStructure;
foreach ($mjmlStructure as $key => $part) {
if ($part['type'] == 'image' && strpos($part['data']['image'], 'data:image') === 0) {
$base64Image = $part['data']['image']; // Récupérer la partie base64 de l'image
$imageData = base64_decode(preg_replace('#^data:image/\w+;base64,#i', '', $base64Image)); // Suppri mer le préfixe et décoder la base64
$imageName = uniqid() . '.png'; // Générer un nom de fichier unique
$destinationPath = 'images/communication/' . $imageName; // Spécifier le chemin de destination pour sauvegarder l'image
// Enregistrer les données binaires dans un fichier sur le serveur
if (file_put_contents($destinationPath, $imageData)) {
$tmpMjmlStructure[$key]['data']['image'] = $destinationPath;
}
}
}
$mjmlStructure = $tmpMjmlStructure;
$campaign->setmjmlStructure($mjmlStructure);
$em->persist($campaign);
$em->flush();
return $this->redirectToRoute('communication_campagnes_create_sending_options', ['id' => $campaign->getId()]);
}
return $this->render('communication/create_mail.html.twig', [
'form' => $form->createView(),
'campaign' => $campaign,
'mediaViewerUrl' => $mediaViewerUrl,
'accountingFirmJson' => $accountingFirmJson,
]);
}
#[Route(path: '/communication/campagnes/create/sending-options/{id}', name: 'communication_campagnes_create_sending_options' )]
#[IsGranted('ROLE_ADMIN')]
public function campagnesCreateSendingOptions(Request $request, EntityManagerInterface $em, int $id, MailingCommunicationRepository $mailingCommunicationRepository, AccountingFirmRepository $accountingFirmRepository): Response
{
if ($id == null) {
$this->addFlash('error', 'Aucune campagne n\'a été trouvé.');
return $this->redirectToRoute("communication_campagnes");
}
$campaign = $mailingCommunicationRepository->findOneBy(['id' => $id]);
if ($campaign == null) {
$this->addFlash('error', 'Aucune campagne n\'a été trouvé avec cet identifiant.');
return $this->redirectToRoute("communication_campagnes");
}
$accountingFirms = $accountingFirmRepository->findBy(['id' => $campaign->getIdsAccountingFirmSelected()]);
$accountingFirmsArray = [];
foreach ($accountingFirms as $accountingFirm) {
$tmp = [];
$tmp['name'] = $accountingFirm->getName();
$admins = [];
$partners = [];
foreach ($accountingFirm->getUsers() as $user) {
$roles = $user->getRoles();
if (in_array('ROLE_ADMIN_FIRM', $roles, true)) {
$admins[] = $user;
} elseif (in_array('ROLE_FIRM_PARTNER', $roles, true)) {
$partners[] = $user;
}
}
// Priorité : admin cabinet, sinon associé, sinon null
$targetUser = $admins[0] ?? $partners[0] ?? null;
$tmp['email'] = $targetUser ? $targetUser->getEmail() : null;
$accountingFirmsArray[] = $tmp;
}
$form = $this->createForm(CommunicationCampaignDateType::class, $campaign);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$campaign->setStatus("PROGRAMMED");
$em->persist($campaign);
$em->flush();
$dateDisplay = $campaign->getSendDate()->format('d/m/Y');
$this->addFlash('successSendCommunication', "Votre campagne a bien été programmée, elle sera envoyée le ". $dateDisplay .".");
return $this->redirectToRoute('communication_campagnes');
}
return $this->render('communication/finalisation.html.twig', [
'form' => $form->createView(),
'campaign' => $campaign,
'accountingFirms' => $accountingFirmsArray
]);
}
#[Route(path: '/communication/campagnes/create/sending-now/{id}', name: 'communication_campagnes_create_sending_now' )]
#[IsGranted('ROLE_ADMIN')]
public function campagnesCreateSendingNow(Request $request, EntityManagerInterface $em, int $id, MailingCommunicationRepository $mailingCommunicationRepository, AccountingFirmRepository $accountingFirmRepository, Mailing $mailingService): Response
{
if ($id == null) {
$this->addFlash('error', 'Aucune campagne n\'a été trouvé.');
return $this->redirectToRoute("communication_campagnes");
}
$campaign = $mailingCommunicationRepository->findOneBy(['id' => $id]);
if ($campaign == null) {
$this->addFlash('error', 'Aucune campagne n\'a été trouvé avec cet identifiant.');
return $this->redirectToRoute("communication_campagnes");
}
$dateSend = new \DateTime();
$dateSend->setTimezone(new DateTimeZone('Europe/Paris'));
$dateSend->setTime($dateSend->format('H') + 1, 0, 0);
$campaign->setSendDate($dateSend);
$campaign->setStatus("PROGRAMMED");
$em->persist($campaign);
$cabinet = $accountingFirmRepository->findBy(['id' => 2])[0];
$task = new MailingTask();
$task->setAccountingFirm($cabinet);
$task->setType("COMMUNICATION");
$task->setStatus("PENDING");
$task->setMailingCommunication($campaign);
$em->persist($task);
$em->flush();
$mailingService->createMailingLog($task, "Initialisation de l'envoi.", "INIT");
$this->messageBus->dispatch(new MailingProcessMessage(intval($task->getId())));
$this->addFlash('successSendCommunication', "Votre campagne a bien été ajoutée à la file d'attente, elle sera envoyée dès que possible.");
return $this->redirectToRoute('communication_campagnes');
}
#[Route(path: '/communication/campagnes/duplicate/{id}', name: 'communication_campagnes_duplicate' )]
#[IsGranted('ROLE_ADMIN')]
public function campagnesDuplicate(Request $request, EntityManagerInterface $em, int $id, MailingCommunicationRepository $mailingCommunicationRepository): Response
{
$campaign = null;
if ($id != null) {
$campaign = $mailingCommunicationRepository->findOneBy(['id' => $id]);
}
if ($campaign == null) {
$this->addFlash('error', 'Aucune campagne n\'a été trouvé avec cet identifiant.');
return $this->redirectToRoute("communication_campagnes");
}
$newCampain = new MailingCommunication;
$newCampain->setCampaignName($campaign->getCampaignName())
->setCategory($campaign->getCategory())
->setFilters($campaign->getFilters())
->setIdsAccountingFirmSelected($campaign->getIdsAccountingFirmSelected())
->setIdsAccountingFirmUnselected($campaign->getIdsAccountingFirmUnselected())
->setObjectMail($campaign->getObjectMail())
->setMjmlStructure($campaign->getMjmlStructure())
->setStatus("ON_CREATE");
$em->persist($newCampain);
$em->flush();
return $this->redirectToRoute('communication_campagnes_create_name', ['id' => $newCampain->getId()]);
}
#[Route(path: '/communication/campagnes/continue/{id}', name: 'communication_campagnes_continue' )]
#[IsGranted('ROLE_ADMIN')]
public function campagnesContinue(Request $request, EntityManagerInterface $em, int $id, MailingCommunicationRepository $mailingCommunicationRepository): Response
{
$campaign = null;
if ($id != null) {
$campaign = $mailingCommunicationRepository->findOneBy(['id' => $id]);
}
if ($campaign == null) {
$this->addFlash('error', 'Aucune campagne n\'a été trouvé avec cet identifiant.');
return $this->redirectToRoute("communication_campagnes");
}
if ($campaign->getSendDate() == null && $campaign->getmjmlStructure() != null) {
return $this->redirectToRoute("communication_campagnes_create_sending_options", ['id' => $campaign->getId()]);
} elseif ($campaign->getmjmlStructure() == null && $campaign->getIdsAccountingFirmSelected() != null) {
return $this->redirectToRoute("communication_campagnes_create_mail_editor", ['id' => $campaign->getId()]);
} elseif ($campaign->getIdsAccountingFirmSelected() == null && $campaign->getFilters() != null) {
return $this->redirectToRoute("communication_campagnes_create_accounting_firm", ['id' => $campaign->getId()]);
} elseif ($campaign->getFilters() == null && $campaign->getCampaignName() != null) {
return $this->redirectToRoute("communication_campagnes_create_filters", ['id' => $campaign->getId()]);
}
return $this->redirectToRoute("communication_campagnes_create_name", ['id' => $campaign->getId()]);
}
#[Route(path: '/communication/campagnes/preview/{id}', name: 'communication_campagnes_preview' )]
#[IsGranted('ROLE_ADMIN')]
public function campagnesPreview(int $id, MailingCommunicationRepository $mailingCommunicationRepository, MjmlExtension $mjmlRenderer, AccountingFirmRepository $accountingFirmRepository): Response
{
$campaign = null;
if ($id != null) {
$campaign = $mailingCommunicationRepository->findOneBy(['id' => $id]);
}
if ($campaign == null) {
$this->addFlash('error', 'Aucune campagne n\'a été trouvé avec cet identifiant.');
return $this->redirectToRoute("communication_campagnes");
}
$mjmlStructure = $campaign->getmjmlStructure();
$mediaViewerUrl = "https://actucontent.loc:8000/";
if ($this->getParameter('kernel.environment') === 'prod') {
$mediaViewerUrl = "https://actucontent.lagence.expert/";
}
$render_data = [
'mjmlCode' => $mjmlStructure,
'cabinet' => $accountingFirmRepository->findBy(['id' => 2])[0],
'serverUrl' => $mediaViewerUrl
];
return new Response($mjmlRenderer->render($this->render('mjml/communication/communication.mjml', $render_data)));
}
}