src/Controller/ChatFormationController.php line 82

Open in your IDE?
  1. <?php
  2. namespace App\Controller;
  3. use App\Entity\ChatFormation;
  4. use App\Entity\FormationElearning;
  5. use App\Form\ChatFormationType;
  6. use App\Repository\ChatFormationRepository;
  7. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  8. use Symfony\Component\HttpFoundation\Request;
  9. use Symfony\Component\HttpFoundation\Response;
  10. use Symfony\Component\Routing\Annotation\Route;
  11. use App\Repository\FormationElearningRepository;
  12. use App\Repository\SettingRepository;
  13. use App\Repository\UserRepository;
  14. use DateTimeZone;
  15. use Doctrine\ORM\EntityManagerInterface;
  16. use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
  17. use Symfony\Component\HttpFoundation\JsonResponse;
  18. #[Route('/chat/formation')]
  19. class ChatFormationController extends AbstractController
  20. {
  21.     #[Route('/chat/unread-count'name'app_chat_unread_count'methods: ['GET'])]
  22.     public function getUnreadCount(
  23.         EntityManagerInterface $em,
  24.     ): JsonResponse {
  25.         $user $this->getUser();
  26.         if (!$user) {
  27.             return new JsonResponse(['count' => 0]);
  28.         }
  29.         $roles $user->getRoles();
  30.         if (in_array('ROLE_ADMIN'$roles)) {
  31.             // Admin voit les messages non lus envoyés par les students
  32.             $count $em->createQueryBuilder()
  33.                 ->select('COUNT(c.id)')
  34.                 ->from(ChatFormation::class, 'c')
  35.                 ->where('c.isRead = false OR c.isRead IS NULL')
  36.                 ->andWhere('c.senderRole = :role')
  37.                 ->setParameter('role''student')
  38.                 ->getQuery()
  39.                 ->getSingleScalarResult();
  40.         } elseif (in_array('ROLE_STUDENT'$roles)) {
  41.             // Student voit les messages admin non lus
  42.             // dans les formations où il a lui-même participé
  43.             $subQb $em->createQueryBuilder()
  44.                 ->select('IDENTITY(sub.formation)')
  45.                 ->from(ChatFormation::class, 'sub')
  46.                 ->where('sub.sender = :user')
  47.                 ->setParameter('user'$user);
  48.             $count $em->createQueryBuilder()
  49.                 ->select('COUNT(c.id)')
  50.                 ->from(ChatFormation::class, 'c')
  51.                 ->where('c.isRead = false OR c.isRead IS NULL')
  52.                 ->andWhere('c.senderRole = :role')
  53.                 ->andWhere(
  54.                     $em->createQueryBuilder()->expr()->in(
  55.                         'IDENTITY(c.formation)',
  56.                         $subQb->getDQL()
  57.                     )
  58.                 )
  59.                 ->setParameter('role''admin')
  60.                 ->setParameter('user'$user)
  61.                 ->getQuery()
  62.                 ->getSingleScalarResult();
  63.         } else {
  64.             $count 0;
  65.         }
  66.         return new JsonResponse(['count' => (int)$count]);
  67.     }
  68.     #[Route('/chat/recent-messages'name'app_chat_recent_messages'methods: ['POST'])]
  69.     public function getRecentMessages(EntityManagerInterface $em): JsonResponse
  70.     {
  71.         $user $this->getUser();
  72.         if (!$user) {
  73.             return new JsonResponse([]);
  74.         }
  75.         $roles $user->getRoles();
  76.         if (in_array('ROLE_ADMIN'$roles)) {
  77.             $messages $em->createQueryBuilder()
  78.                 ->select('c''u''f')
  79.                 ->from(ChatFormation::class, 'c')
  80.                 ->join('c.sender''u')
  81.                 ->join('c.formation''f')
  82.                 ->where('c.senderRole = :role')
  83.                 ->andWhere('c.isRead = false OR c.isRead IS NULL')
  84.                 ->andWhere('c.parentMessage IS NULL')
  85.                 ->setParameter('role''student')
  86.                 ->orderBy('c.isRead''ASC')
  87.                 ->addOrderBy('c.createdAt''DESC')
  88.                 ->getQuery()
  89.                 ->getResult();
  90.         } elseif (in_array('ROLE_STUDENT'$roles)) {
  91.             $formationIds $em->createQueryBuilder()
  92.                 ->select('IDENTITY(sub.formation)')
  93.                 ->from(ChatFormation::class, 'sub')
  94.                 ->where('sub.sender = :user')
  95.                 ->setParameter('user'$user)
  96.                 ->getQuery()
  97.                 ->getSingleColumnResult();
  98.             if (empty($formationIds)) {
  99.                 return new JsonResponse([]);
  100.             }
  101.             $messages $em->createQueryBuilder()
  102.                 ->select('c''u''f')
  103.                 ->from(ChatFormation::class, 'c')
  104.                 ->join('c.sender''u')
  105.                 ->join('c.formation''f')
  106.                 ->where('c.senderRole = :role')
  107.                 ->andWhere('c.formation IN (:formations)')
  108.                 ->andWhere('c.isRead = false OR c.isRead IS NULL')
  109.                 ->setParameter('role''admin')
  110.                 ->setParameter('formations'$formationIds)
  111.                 ->orderBy('c.isRead''ASC')
  112.                 ->addOrderBy('c.createdAt''DESC')
  113.                 ->getQuery()
  114.                 ->getResult();
  115.         } else {
  116.             return new JsonResponse([]);
  117.         }
  118.         // === Filtrer pour ne garder qu'un message par (sender + formation) ===
  119.         $filtered = [];
  120.         $seen = [];
  121.         foreach ($messages as $msg) {
  122.             $key $msg->getSender()?->getId() . '_' $msg->getFormation()?->getId();
  123.             if (!isset($seen[$key])) {
  124.                 $seen[$key] = true;
  125.                 $filtered[] = $msg;
  126.             }
  127.         }
  128.         // Limiter à 10 résultats après filtrage
  129.         $filtered array_slice($filtered010);
  130.         $data = [];
  131.         foreach ($filtered as $msg) {
  132.             $data[] = [
  133.                 'id'             => $msg->getId(),
  134.                 'message'        => mb_substr(strip_tags($msg->getMessage()), 080),
  135.                 'studentId'      => $msg->getSender()?->getId(),
  136.                 'prenom'         => $msg->getSender()?->getPrenom(),
  137.                 'nom'            => $msg->getSender()?->getNom(),
  138.                 'formation'      => $msg->getFormation()?->getTitre(),
  139.                 'formationSlug'  => $msg->getFormation()?->getSlug(),
  140.                 'formationId'    => $msg->getFormation()?->getId(),
  141.                 'isRead'         => $msg->isRead(),
  142.                 'role'           => in_array('ROLE_ADMIN'$roles) ? 'admin' 'student',
  143.                 'datee'          => $msg->getCreatedAt()?->format('d/m/Y H:i'),
  144.             ];
  145.         }
  146.         return new JsonResponse($data);
  147.     }
  148.     #[Route('/{id}'name'app_chat_formation'methods: ['GET'])]
  149.     #[Security("is_granted('ROLE_STUDENT') or is_granted('ROLE_ADMIN')")]
  150.     public function index(
  151.         int $id,
  152.         FormationElearningRepository $formationRepo,
  153.         ChatFormationRepository      $chatRepo,
  154.         SettingRepository            $settingRepo,
  155.         EntityManagerInterface       $entityManager
  156.     ): Response {
  157.         $formation $formationRepo->find($id);
  158.         if (!$formation) {
  159.             throw $this->createNotFoundException('Formation introuvable.');
  160.         }
  161.         $user $this->getUser();
  162.         // Récupère les messages du thread
  163.         $messages $chatRepo->createQueryBuilder('c')
  164.             ->where('c.formation = :formation')
  165.             ->andWhere('(c.sender = :user) 
  166.         OR (c.senderRole = :adminRole AND c.parentMessage IN (
  167.             SELECT m FROM App\Entity\ChatFormation m 
  168.             WHERE m.sender = :user AND m.formation = :formation
  169.         ))')
  170.             ->setParameter('formation'$formation)
  171.             ->setParameter('user'$user)
  172.             ->setParameter('adminRole''admin')
  173.             ->orderBy('c.createdAt''ASC')
  174.             ->getQuery()
  175.             ->getResult();
  176.         // Marque les messages non-lus comme lus
  177.         foreach ($messages as $msg) {
  178.             if ($msg->getSenderRole() === 'admin' && !$msg->isRead()) {
  179.                 $msg->setIsRead(true);
  180.             }
  181.         }
  182.         // On applique les changements en base de données (Uniquement les updates ici)
  183.         $entityManager->flush();
  184.         return $this->render('chat_formation/chat.html.twig', [
  185.             'formation' => $formation,
  186.             'messages'  => $messages,
  187.             'setting'   => $settingRepo->find(1),
  188.         ]);
  189.     }
  190.     /**
  191.      * Envoyer un message (AJAX POST) – côté stagiaire.
  192.      * URL : /chat/formation/{id}/send
  193.      */
  194.     #[Route('/{id}/send'name'app_chat_formation_send'methods: ['POST'])]
  195.     #[Security("is_granted('ROLE_STUDENT') or is_granted('ROLE_ADMIN')")]
  196.     public function send(
  197.         int                          $id,
  198.         Request                      $request,
  199.         FormationElearningRepository $formationRepo,
  200.         ChatFormationRepository      $chatRepo,
  201.         EntityManagerInterface       $em
  202.     ): JsonResponse {
  203.         $formation $formationRepo->find($id);
  204.         if (!$formation) {
  205.             return $this->json(['success' => false'message' => 'Formation introuvable.'], 404);
  206.         }
  207.         $data    json_decode($request->getContent(), true);
  208.         $message trim($data['message'] ?? '');
  209.         if (empty($message)) {
  210.             return $this->json(['success' => false'message' => 'Message vide.'], 400);
  211.         }
  212.         $user $this->getUser();
  213.         $chat = new ChatFormation();
  214.         $chat->setMessage($message);
  215.         $chat->setSender($user);
  216.         $chat->setFormation($formation);
  217.         $chat->setCreatedAt(new \DateTime('now', new DateTimeZone('Africa/Tunis')));
  218.         $chat->setIsRead(false);
  219.         $chat->setSenderRole(in_array('ROLE_ADMIN'$user->getRoles()) ? 'admin' 'student');
  220.         $em->persist($chat);
  221.         $em->flush();
  222.         return $this->json([
  223.             'success'    => true,
  224.             'id'         => $chat->getId(),
  225.             'message'    => $chat->getMessage(),
  226.             'senderName' => $user->getPrenom() . ' ' $user->getNom(),
  227.             'senderRole' => $chat->getSenderRole(),
  228.             'avatar'     => $user->getLogo(),
  229.             'createdAt'  => $chat->getCreatedAt()->format('d/m/Y H:i'),
  230.         ]);
  231.     }
  232.     /**
  233.      * Récupère les nouveaux messages (polling AJAX).
  234.      * URL : /chat/formation/{id}/poll?after={lastId}
  235.      */
  236.     #[Route('/{id}/poll'name'app_chat_formation_poll'methods: ['GET'])]
  237.     #[Security("is_granted('ROLE_STUDENT') or is_granted('ROLE_ADMIN')")]
  238.     public function poll(
  239.         int                          $id,
  240.         Request                      $request,
  241.         FormationElearningRepository $formationRepo,
  242.         ChatFormationRepository      $chatRepo,
  243.         EntityManagerInterface       $em
  244.     ): JsonResponse {
  245.         $formation $formationRepo->find($id);
  246.         if (!$formation) {
  247.             return $this->json([]);
  248.         }
  249.         $lastId = (int) $request->query->get('after'0);
  250.         $user   $this->getUser();
  251.         $newMessages $chatRepo->createQueryBuilder('c')
  252.             ->where('c.formation = :formation')
  253.             ->andWhere('c.id > :lastId')
  254.             ->andWhere('c.sender = :user OR c.senderRole = :adminRole')
  255.             ->setParameter('formation'$formation)
  256.             ->setParameter('lastId'$lastId)
  257.             ->setParameter('user'$user)
  258.             ->setParameter('adminRole''admin')
  259.             ->orderBy('c.createdAt''ASC')
  260.             ->getQuery()
  261.             ->getResult();
  262.         $result = [];
  263.         foreach ($newMessages as $msg) {
  264.             if ($msg->getSenderRole() === 'admin' && !$msg->isRead()) {
  265.                 $msg->setIsRead(true);
  266.             }
  267.             $result[] = [
  268.                 'id'         => $msg->getId(),
  269.                 'message'    => $msg->getMessage(),
  270.                 'senderName' => $msg->getSender()->getPrenom() . ' ' $msg->getSender()->getNom(),
  271.                 'senderRole' => $msg->getSenderRole(),
  272.                 'avatar'     => $msg->getSender()->getLogo(),
  273.                 'createdAt'  => $msg->getCreatedAt()->format('d/m/Y H:i'),
  274.             ];
  275.         }
  276.         $em->flush();
  277.         return $this->json($result);
  278.     }
  279.     // ─────────────────────────────────────────────────────────────────
  280.     //  ADMIN : liste des conversations par formation
  281.     // ─────────────────────────────────────────────────────────────────
  282.     /**
  283.      * Liste toutes les formations ayant des messages (admin).
  284.      * URL : /chat/formation/admin/list
  285.      */
  286.     // 1. LA LISTE DES DISCUSSIONS
  287.     #[Route('/admin/list'name'app_chat_admin_list'methods: ['GET'])]
  288.     #[Security("is_granted('ROLE_ADMIN')")]
  289.     public function adminList(SettingRepository $settingRepoChatFormationRepository $chatRepo): Response
  290.     {
  291.         return $this->render('chat_formation/admin_list.html.twig', [
  292.             'threads' => $chatRepo->findAllThreadsForAdmin(), // Utilise une méthode propre au repository
  293.             'setting' => $settingRepo->find(1),
  294.         ]);
  295.     }
  296. // 2. LA VUE DU CHAT DÉTAILLÉE (C'est ici qu'on définit 'student')
  297.     #[Route('/admin/chat/{formationId}/{studentId}'name'app_chat_admin_view'methods: ['GET'])]
  298.     public function adminView(
  299.         int $formationId,
  300.         int $studentId,
  301.         FormationElearningRepository $fRepo,
  302.         UserRepository $uRepo,
  303.         ChatFormationRepository $chatRepo,
  304.         EntityManagerInterface $entityManager,
  305.         Request $request
  306.     ): Response {
  307.         $formation $fRepo->find($formationId);
  308.         $student $uRepo->find($studentId);
  309.         if (!$formation || !$student) throw $this->createNotFoundException();
  310.         $messages $chatRepo->findAllMessagesForThread($formation$student);
  311.         foreach ($messages as $message) {
  312.             if ($message->getSenderRole() === 'student' && !$message->isRead()) {
  313.                 $message->setIsRead(true);
  314.             }
  315.             $entityManager->flush();
  316.         }
  317.         // Si c'est une requête AJAX (clic à gauche), on rend un template partiel
  318.         if ($request->isXmlHttpRequest()) {
  319.             return $this->render('chat_formation/_admin_chat_content.html.twig', [
  320.                 'formation' => $formation,
  321.                 'student'   => $student,
  322.                 'messages'  => $messages,
  323.             ]);
  324.         }
  325.         // Sinon on rend la page complète (premier chargement)
  326.         return $this->render('chat_formation/admin_list.html.twig', [
  327.             'formation' => $formation,
  328.             'student'   => $student,
  329.             'messages'  => $messages,
  330.             'threads'   => $chatRepo->findAllThreadsForAdmin(),
  331.         ]);
  332.     }
  333.     /**
  334.      * Liste des stagiaires ayant écrit pour une formation (admin).
  335.      * URL : /chat/formation/admin/{id}/students
  336.      */
  337.     #[Route('/admin/{id}/students'name'app_chat_admin_students'methods: ['GET'])]
  338.     #[Security("is_granted('ROLE_ADMIN')")]
  339.     public function adminStudents(
  340.         int                          $id,
  341.         FormationElearningRepository $formationRepo,
  342.         ChatFormationRepository      $chatRepo,
  343.         UserRepository               $userRepo,
  344.         SettingRepository            $settingRepo
  345.     ): Response {
  346.         $formation $formationRepo->find($id);
  347.         if (!$formation) {
  348.             throw $this->createNotFoundException();
  349.         }
  350.         // Récupère les IDs distincts des stagiaires ayant envoyé un message
  351.         $rows $chatRepo->createQueryBuilder('c')
  352.             ->select('IDENTITY(c.sender) as sid')
  353.             ->where('c.formation = :f')
  354.             ->andWhere('c.senderRole = :role')
  355.             ->setParameter('f'$formation)
  356.             ->setParameter('role''student')
  357.             ->groupBy('c.sender')
  358.             ->getQuery()
  359.             ->getArrayResult();
  360.         $students = [];
  361.         foreach ($rows as $row) {
  362.             $student $userRepo->find($row['sid']);
  363.             if ($student) {
  364.                 $unread $chatRepo->createQueryBuilder('c')
  365.                     ->select('COUNT(c.id)')
  366.                     ->where('c.formation = :f')
  367.                     ->andWhere('c.sender = :s')
  368.                     ->andWhere('c.isRead = false')
  369.                     ->andWhere('c.senderRole = :role')
  370.                     ->setParameter('f'$formation)
  371.                     ->setParameter('s'$student)
  372.                     ->setParameter('role''student')
  373.                     ->getQuery()
  374.                     ->getSingleScalarResult();
  375.                 $students[] = ['student' => $student'unread' => (int) $unread];
  376.             }
  377.         }
  378.         return $this->render('chat_formation/adminStudents.html.twig', [
  379.             'formation' => $formation,
  380.             'students'  => $students,
  381.             'setting'   => $settingRepo->find(1),
  382.         ]);
  383.     }
  384.     /**
  385.      * Thread admin ↔ stagiaire pour une formation.
  386.      * URL : /chat/formation/admin/{formationId}/thread/{studentId}
  387.      */
  388.     #[Route('/admin/{formationId}/thread/{studentId}'name'app_chat_admin_thread'methods: ['GET'])]
  389.     #[Security("is_granted('ROLE_ADMIN')")]
  390.     public function adminThread(
  391.         int                          $formationId,
  392.         int                          $studentId,
  393.         FormationElearningRepository $formationRepo,
  394.         ChatFormationRepository      $chatRepo,
  395.         UserRepository               $userRepo,
  396.         SettingRepository            $settingRepo,
  397.         EntityManagerInterface       $em
  398.     ): Response {
  399.         $formation $formationRepo->find($formationId);
  400.         $student   $userRepo->find($studentId);
  401.         if (!$formation || !$student) {
  402.             throw $this->createNotFoundException();
  403.         }
  404.         // Récupère tous les messages de ce thread
  405.         $messages $chatRepo->createQueryBuilder('c')
  406.             ->where('c.formation = :f')
  407.             ->andWhere('c.sender = :s OR (c.senderRole = :adminRole AND c.parentMessage IS NOT NULL)')
  408.             ->setParameter('f'$formation)
  409.             ->setParameter('s'$student)
  410.             ->setParameter('adminRole''admin')
  411.             ->orderBy('c.createdAt''ASC')
  412.             ->getQuery()
  413.             ->getResult();
  414.         // Marque les messages du stagiaire comme lus
  415.         foreach ($messages as $msg) {
  416.             if ($msg->getSenderRole() === 'student' && !$msg->isRead()) {
  417.                 $msg->setIsRead(true);
  418.             }
  419.         }
  420.         $em->flush();
  421.         return $this->render('chat_formation/adminThread.html.twig', [
  422.             'formation' => $formation,
  423.             'student'   => $student,
  424.             'messages'  => $messages,
  425.             'setting'   => $settingRepo->find(1),
  426.         ]);
  427.     }
  428.     #[Route('/admin/chatlist/formation/{id}'name'app_chat_formation_admin_list')]
  429.     public function adminList2(
  430.         SettingRepository $settingRepository,
  431.         FormationElearning $formation,
  432.         ChatFormationRepository $chatRepo,
  433.         Request $request,
  434.         UserRepository $userRepo,
  435.         EntityManagerInterface $em
  436.     ): Response {
  437.         $studentId $request->query->get('studentId'); // optionnel
  438.         $conversations $chatRepo->findLatestConversationsByFormation($formation);
  439.         $student null;
  440.         $messages null;
  441.         if ($studentId) {
  442.             $student $userRepo->find($studentId);
  443.             if ($student) {
  444.                 $messages $chatRepo->findAllMessagesForThread($formation$student);
  445.                 // Marquer les messages comme lus
  446.                 foreach ($messages as $msg) {
  447.                     if ($msg->getSenderRole() === 'student' && !$msg->isRead()) {
  448.                         $msg->setIsRead(true);
  449.                     }
  450.                 }
  451.                 // Sauvegarde en base
  452.                 $em->flush();
  453.             }
  454.         }
  455.         return $this->render('chat_formation/admin_list.html.twig', [
  456.             'formation' => $formation,
  457.             'threads'   => $conversations,
  458.             'student'   => $student,
  459.             'messages'  => $messages,
  460.             'setting'   => $settingRepository->find(1),
  461.         ]);
  462.     }
  463.     /**
  464.      * Admin répond à un message (AJAX POST).
  465.      * URL : /chat/formation/admin/{formationId}/reply/{studentId}
  466.      */
  467.     #[Route('/admin/reply/{formationId}/{studentId}'name'app_chat_admin_reply'methods: ['POST'])]
  468.     public function adminReply(
  469.         int $formationId,
  470.         int $studentId,
  471.         Request $request,
  472.         EntityManagerInterface $em,
  473.         FormationElearningRepository $fRepo,
  474.         UserRepository $uRepo,
  475.         ChatFormationRepository $chatRepo
  476.     ): JsonResponse {
  477.         $data json_decode($request->getContent(), true);
  478.         $messageContent $data['message'] ?? '';
  479.         if (empty(trim($messageContent))) {
  480.             return $this->json(['success' => false'error' => 'Message vide'], 400);
  481.         }
  482.         $formation $fRepo->find($formationId);
  483.         $student $uRepo->find($studentId);
  484.         // On récupère le dernier message du stagiaire pour le lier (parentMessage)
  485.         $lastStudentMsg $chatRepo->findOneBy(
  486.             ['formation' => $formation'sender' => $student'senderRole' => 'student'],
  487.             ['createdAt' => 'DESC']
  488.         );
  489.         $chat = new ChatFormation();
  490.         $chat->setMessage($messageContent);
  491.         $chat->setFormation($formation);
  492.         $chat->setSender($this->getUser()); // Admin connecté
  493.         $chat->setSenderRole('admin');
  494.         $chat->setCreatedAt(new \DateTime('now', new \DateTimeZone('Africa/Tunis')));
  495.         $chat->setParentMessage($lastStudentMsg);
  496.         $chat->setIsRead(false);
  497.         $em->persist($chat);
  498.         $em->flush();
  499.         return $this->json([
  500.             'success'    => true,
  501.             'id'         => $chat->getId(),
  502.             'message'    => $chat->getMessage(),
  503.             'senderName' => 'Vous',
  504.             'createdAt'  => $chat->getCreatedAt()->format('H:i')
  505.         ]);
  506.     }
  507.     /**
  508.      * Polling admin : nouveaux messages du stagiaire.
  509.      * URL : /chat/formation/admin/{formationId}/poll/{studentId}?after={lastId}
  510.      */
  511.     #[Route('/admin/{formationId}/poll/{studentId}'name'app_chat_admin_poll'methods: ['GET'])]
  512.     #[Security("is_granted('ROLE_ADMIN')")]
  513.     public function adminPoll(
  514.         int                          $formationId,
  515.         int                          $studentId,
  516.         Request                      $request,
  517.         FormationElearningRepository $formationRepo,
  518.         ChatFormationRepository      $chatRepo,
  519.         UserRepository               $userRepo,
  520.         EntityManagerInterface       $em
  521.     ): JsonResponse {
  522.         $formation $formationRepo->find($formationId);
  523.         $student   $userRepo->find($studentId);
  524.         if (!$formation || !$student) return $this->json([]);
  525.         $lastId = (int) $request->query->get('after'0);
  526.         $newMessages $chatRepo->createQueryBuilder('c')
  527.             ->where('c.formation = :f')
  528.             ->andWhere('c.id > :lastId')
  529.             ->andWhere('c.sender = :s OR c.senderRole = :adminRole')
  530.             ->setParameter('f'$formation)
  531.             ->setParameter('lastId'$lastId)
  532.             ->setParameter('s'$student)
  533.             ->setParameter('adminRole''admin')
  534.             ->orderBy('c.createdAt''ASC')
  535.             ->getQuery()
  536.             ->getResult();
  537.         $result = [];
  538.         foreach ($newMessages as $msg) {
  539.             if ($msg->getSenderRole() === 'student' && !$msg->isRead()) {
  540.                 $msg->setIsRead(true);
  541.             }
  542.             $result[] = [
  543.                 'id'         => $msg->getId(),
  544.                 'message'    => $msg->getMessage(),
  545.                 'senderName' => $msg->getSender()->getPrenom() . ' ' $msg->getSender()->getNom(),
  546.                 'senderRole' => $msg->getSenderRole(),
  547.                 'avatar'     => $msg->getSender()->getLogo(),
  548.                 'createdAt'  => $msg->getCreatedAt()->format('d/m/Y H:i'),
  549.             ];
  550.         }
  551.         $em->flush();
  552.         return $this->json($result);
  553.     }
  554. }