src/Controller/Front/MessageController.php line 682

Open in your IDE?
  1. <?php
  2. namespace App\Controller\Front;
  3. use DateTimeZone;
  4. use Mobile_Detect;
  5. use App\Entity\Message;
  6. use App\Entity\AttachedFile;
  7. use App\Entity\Conversation;
  8. use App\Service\ImageOptimizer;
  9. use App\Mercure\CookieGenerator;
  10. use App\EmailNotification\ToUser;
  11. use App\Entity\Trainee;
  12. use App\Repository\UserRepository;
  13. use Symfony\Component\WebLink\Link;
  14. use App\Repository\CourseRepository;
  15. use App\Service\ConversationService;
  16. use App\Repository\MessageRepository;
  17. use Symfony\Component\Mercure\Update;
  18. use Doctrine\Persistence\ObjectManager;
  19. use Symfony\Component\Mercure\Discovery;
  20. use App\Repository\AttachedFileRepository;
  21. use App\Repository\ConversationRepository;
  22. use Symfony\Component\Mercure\HubInterface;
  23. use Symfony\Component\Mercure\Authorization;
  24. use Symfony\Component\HttpFoundation\Request;
  25. use Symfony\Component\HttpFoundation\Response;
  26. use Symfony\Component\Routing\Annotation\Route;
  27. use Symfony\Component\HttpFoundation\JsonResponse;
  28. use Symfony\Component\Messenger\MessageBusInterface;
  29. use Symfony\Contracts\Translation\TranslatorInterface;
  30. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  31. use Symfony\Component\Intl\Countries;
  32. #[Route(path'/{_locale}')]
  33. class MessageController extends AbstractController
  34. {
  35.     private $translator;
  36.     private $imageOptimizer;
  37.     public function __construct(TranslatorInterface $translatorImageOptimizer $imageOptimizer)
  38.     {
  39.         $this->translator $translator;
  40.         $this->imageOptimizer $imageOptimizer;
  41.     }
  42.     
  43.     private function generateUniqueFileName()
  44.     {
  45.         return md5(uniqid());
  46.     }
  47.     #[Route(path'/messages'name'message')]
  48.     public function message(ConversationRepository $conversationRepoConversationService $conversationService): Response
  49.     {
  50.         $user $this->getUser();
  51.         $detect = new Mobile_Detect;
  52.         
  53.         if ($detect->isMobile()) {
  54.             
  55.             $conversationsList $conversationService->userConversationList($user);
  56.             if ($conversationsList) {
  57.                 
  58.                 return $this->render('front/message/responsive-conversation-list.html.twig', [
  59.                     'conversations' => $conversationsList,
  60.                     'chat' => false
  61.                 ]);
  62.             }
  63.             return $this->render('front/message/empty-message.html.twig', [
  64.                 'chat' => false
  65.             ]);
  66.         }
  67.         else {
  68.             $recentConversation $conversationRepo->findLastConversation($user);
  69.             if ($recentConversation) {
  70.                 
  71.                 return $this->redirectToRoute('read_message', [
  72.                     'token' => $recentConversation->getToken(),
  73.                     'chat' => false,
  74.                 ]);
  75.             }
  76.             return $this->render('front/message/empty-message.html.twig', [
  77.                 'chat' => false
  78.             ]);
  79.         }        
  80.     }
  81.     #[Route(path'/messages/{token}'name'read_message')]
  82.     public function readMessage($tokenConversationRepository $conversationRepoMessageRepository $messageRepoConversationService $conversationServiceObjectManager $manager): Response
  83.     {
  84.         $user $this->getUser();
  85.         $conversation $conversationRepo->findOneBy(['token' => $token]);
  86.         if ($conversation == null) {
  87.             
  88.             return $this->redirectToRoute('message');
  89.         }
  90.         $groupedMessages = [];
  91.         
  92.         $messages $conversation->getMessages();
  93.         foreach($messages as $message) {
  94.             $messageDate $conversationService->formatMessagesDay($message->getCreatedAt());
  95.             //$groupedKey = $message->getCreatedAt()->format('d/m/Y');
  96.             $groupedMessages[$messageDate][] = $message;
  97.         
  98.         }
  99.         $lastMessage $conversation->getLastMessage();
  100.         if ($lastMessage->getSender() != $user) {
  101.             $lastMessage->setIsReaded(true);
  102.         }
  103.         $manager->persist($lastMessage);
  104.         $manager->flush();
  105.         $other $conversationService->getOther($conversation$user);        
  106.         $bookings $conversationService->conversationBookings($conversation);
  107.         $options = [
  108.             'chat' => false,
  109.             'conversation' => $conversation,
  110.             'other' => $other,
  111.             'bookings' => $bookings,
  112.             'type' => $conversationService->userType($other),
  113.             'messages' => $conversation->getMessages(),
  114.             'groupedMessages' => $groupedMessages,
  115.             'menu' => 'messages',
  116.         ];
  117.         $detect = new Mobile_Detect;
  118.         if ($detect->isMobile()) {
  119.             return $this->render('front/message/responsive-conversation-content.html.twig'$options);
  120.         }
  121.         else {
  122.             $conversationsList $conversationService->userConversationList($user);
  123.             $options['conversations'] = $conversationsList;
  124.             return $this->render('front/message/desktop-messaging.html.twig'$options);
  125.         }
  126.     }
  127.     #[Route(path'/conversations-list'name'conversations_list')]
  128.     public function conversationsList(ConversationService $conversationService): Response
  129.     {
  130.         \sleep(1);
  131.         $user $this->getUser();
  132.             
  133.         $conversationsList $conversationService->userConversationList($user);
  134.         if (count($conversationsList) > 0) {
  135.             return new JsonResponse([
  136.                 'conversations' => $conversationsList
  137.                 'message' => 'Ok'
  138.             ]);
  139.         }   
  140.         
  141.         else {
  142.             return new JsonResponse([
  143.                 'conversations' => $conversationsList
  144.                 'message' => $this->translator->trans('messaging.empty_message.no_conversations_yet')
  145.             ]);
  146.         }
  147.     }
  148.     #[Route(path'/conversation-content/{token}'name'conversation_content')]
  149.     public function getConversationContent(Conversation $conversationCourseRepository $courseRepoConversationService $conversationServiceAttachedFileRepository $attachedFileRepoObjectManager $managerRequest $request): Response
  150.     {
  151.         $user $this->getUser();
  152.         $lastMessage $conversation->getLastMessage();
  153.         if ($lastMessage->getSender() != $user) {
  154.             $lastMessage->setIsReaded(true);
  155.         }
  156.         $manager->persist($lastMessage);
  157.         $manager->flush();
  158.         $other $conversationService->getOther($conversation$user);
  159.         if ($other->getIsPro()) {
  160.             $name $other->getProInfo()->getFullname();
  161.         }
  162.         else {
  163.             $name $other->getFirstname() .' '$other->getLastname();
  164.         }
  165.         
  166.         $infos = [
  167.             'token' => $conversation->getToken(),
  168.             'profile' => $other->getPhoto(),
  169.             'status' => $other->getStatus(),
  170.             'noUser' => $this->translator->trans('messaging.no_user'),
  171.             'type' => $conversationService->userType($other),
  172.             'name' => $name,
  173.             'slug' => $other->getSlug()
  174.         ];
  175.         // get conversation messages, bookings, payement requests and files
  176.         $groupedMessages = [];
  177.         $files = [];
  178.         $booking null;
  179.         $note null;
  180.         //$paymentRequest = null;
  181.         $messagesBrut $conversation->getMessages();
  182.         foreach($messagesBrut as $messageBrut) {
  183.             $me false;
  184.             $paymentRequest false;
  185.             if ($messageBrut->getSender() == $user ) {
  186.                 $me true;
  187.             }
  188.             $type 'text';
  189.             if ($messageBrut->getType() != null) {
  190.                 $type $messageBrut->getType();
  191.             }
  192.             $messageContent $messageBrut->getContent();
  193.             if ($type == 'files') {
  194.                 
  195.                 $filesBrut $attachedFileRepo->findBy(['message' => $messageBrut->getId()]);
  196.                 foreach($filesBrut as $fileBrut) {
  197.                     $file = [
  198.                         'path' => $fileBrut->getPath(),
  199.                         'name' => $fileBrut->getName(),
  200.                         'type' => $fileBrut->getType(),
  201.                         'extension' => $fileBrut->getExtension()
  202.                     ];
  203.                     $files[] = $file;
  204.                 }
  205.             }
  206.             else if ($type == 'booking') {
  207.                 $bookingBrut $messageBrut->getBooking();
  208.                 $messageContent $this->translator->trans('messaging.'$messageBrut->getContent());
  209.                 $showAction false;
  210.                 $link '';
  211.                 if ($bookingBrut->getStatus() == 'pending' && $user->getIsPro()) {
  212.                 
  213.                     $showAction true;
  214.                     $link $this->generateUrl('read_message', array('token' => $conversation->getToken()));
  215.                 }
  216.                 $booking = [
  217.                     'course' => $bookingBrut->getCourse()->getTranslatedContent($request->getLocale())->getName(),
  218.                     'courseToken' => $bookingBrut->getCourse()->getToken(),
  219.                     'bookingId' => $bookingBrut->getId(),
  220.                     'photo' => $bookingBrut->getCourse()->getCover() ?? "default.png",
  221.                     'adult' => $bookingBrut->getAdult(),
  222.                     'teen' => $bookingBrut->getTeen(),
  223.                     'child' => $bookingBrut->getChild(),
  224.                     'total' => $bookingBrut->getTotal(),
  225.                     'begin' => $bookingBrut->getBegin(),
  226.                     'end' => $bookingBrut->getEnd(),
  227.                     'status' => $bookingBrut->getStatus(),
  228.                     'statusText' =>  $this->translator->trans('messaging.'$bookingBrut->getStatus()),
  229.                     'payment' => $bookingBrut->getPaymentMethod(),
  230.                     'paid' => $bookingBrut->getIsPaid(),
  231.                     'showAction' => $showAction,
  232.                     'link' => $link,
  233.                     'address' => $bookingBrut->getCourse()->getAddress()->getCity() .", " Countries::getName($bookingBrut->getCourse()->getAddress()->getCountryCode())
  234.                 ];
  235.             }
  236.             else if ($type == 'notification') {
  237.                 $messageContent $this->translator->trans('messaging.'.$messageBrut->getContent());
  238.                 if ($messageBrut->getPaymentRequest()) {
  239.                     $paymentAction false;
  240.                     if (!$user->getIsPro()) {
  241.                         $paymentAction true;
  242.                     }
  243.                     
  244.                     $status $messageBrut->getPaymentRequest()->getStatus();
  245.                     $paymentRequest = [
  246.                         'id' => $messageBrut->getPaymentRequest()->getId(),
  247.                         'title' => $this->translator->trans('messaging.stripe_payment_request'),
  248.                         'textButton' => $this->translator->trans('messaging.pay'),
  249.                         'status' => $status,
  250.                         'statusText' => $this->translator->trans('messaging.'$status),
  251.                         'paymentAction' => $paymentAction,
  252.                         'link' => '/' $request->getLocale() . '/prepare-booking-checkout',
  253.                     ];
  254.                 }
  255.             }
  256.             else if ($type == 'rate') {
  257.                 $action true;
  258.                 $messageText $this->translator->trans('messaging.notation_message');
  259.                 if ($user->getIsPro()) {
  260.                     $action false;
  261.                     $messageText $this->translator->trans('messaging.rate_sent');
  262.                 }
  263.                 $messageContent $this->translator->trans('messaging.'.$messageBrut->getContent());
  264.                 $courseToken $messageBrut->getToRate();
  265.                 $course $courseRepo->findOneBy(['token' => $courseToken]);
  266.                 $note = [
  267.                     'title' => $this->translator->trans('messaging.notation_title'),
  268.                     'message' => $messageText,
  269.                     'course' => $course->getTranslatedContent($request->getLocale())->getName(),
  270.                     'textBtn' => $this->translator->trans('messaging.notation_btn'),
  271.                     'showAction' => $action
  272.                 ];
  273.                 if ($messageBrut->getNote() != null) {
  274.                     
  275.                     $noteInfo $messageBrut->getNote();
  276.                     $note['organizationText'] = $this->translator->trans('messaging.organizationText');
  277.                     $note['organization'] = $noteInfo->getEducation();
  278.                     $note['educationText'] = $this->translator->trans('messaging.educationText');
  279.                     $note['education'] = $noteInfo->getEducation();
  280.                     $note['commentText'] = $this->translator->trans('messaging.commentText');
  281.                     $note['comment'] = $noteInfo->getComment();
  282.                     $note['isNoted'] = true;
  283.                 }
  284.                 else {
  285.                     $note['link'] = $this->generateUrl('trainee_note_pending');
  286.                     $note['isNoted'] = false;
  287.                 }
  288.             }
  289.             $messageDate $conversationService->formatMessagesDay($messageBrut->getCreatedAt());
  290.             //$messageDate = $messageBrut->getCreatedAt()->format('d/m/Y');  
  291.             /**
  292.              * @var DateTime $messageHour
  293.              */
  294.             $messageHour $messageBrut->getCreatedAt();
  295.             $messageHour->setTimezone(new DateTimeZone($user->getTimezone()));
  296.             if ($messageBrut->getSender() == $user) {
  297.                 $senderName 'Vous'
  298.             }
  299.             else {
  300.                 if ($messageBrut->getSender()->getIsPro()) {
  301.                     $senderName $messageBrut->getSender()->getProInfo()->getFullname();
  302.                 }
  303.                 else {
  304.                     $senderName $messageBrut->getSender()->getFirstName() .' '$messageBrut->getSender()->getLastName();
  305.                 }
  306.             }
  307.             $message = [
  308.                 'sender' => $senderName,
  309.                 'date' => $messageHour->format('H:i'),
  310.                 'content' => $messageContent,
  311.                 'me' => $me,
  312.                 'type' => $type,
  313.                 'files' => $files,
  314.                 'booking' => $booking,
  315.                 'paymentRequest' => $paymentRequest,
  316.                 'note' => $note
  317.             ];
  318.             $groupedMessages[$messageDate][] = $message;
  319.         }
  320.         return new JsonResponse([
  321.             'infos' => $infos,
  322.             'groupedMessages' => $groupedMessages
  323.         ]);
  324.     }
  325.     #[Route(path'/publish'name'publish')]
  326.     public function publish(HubInterface $hubRequest $request)
  327.     {
  328.         $update = new Update(
  329.             'http://example.com/ping',
  330.             json_encode(['status' => 'Reussite'])
  331.         );
  332.         $hub($update);
  333.         return new Response('published!');
  334.     
  335.     }
  336.     
  337.     #[Route(path'/send-message'name'send_message')]
  338.     public function sendMessage(ConversationRepository $conversationRepoObjectManager $managerMessageBusInterface $busHubInterface $hubConversationService $conversationServiceToUser $toUserRequest $request)
  339.     {
  340.         $user $this->getUser();
  341.         if (isset($_POST['conversationId'])) {
  342.             $conversationId $_POST['conversationId'];
  343.             $messageContent $_POST['message'];
  344.             $countFiles $_POST['countedFiles'];    
  345.         }
  346.         else {
  347.             $data json_decode($request->getContent(), true);
  348.             $conversationId $data['conversationId'];
  349.             $messageContent $data['messageContent'];
  350.             $countFiles 0;    
  351.         }
  352.         $filesToReturn = [];
  353.         $conversation $conversationRepo->find($conversationId);
  354.         $date = new \Datetime;
  355.         $other $conversationService->getOther($conversation$user);
  356.         $oldLastActivity $conversation->getLastActivity();
  357.         $message = new Message();
  358.         
  359.         $message->setContent($messageContent)
  360.                 ->setIsReaded(false)
  361.                 ->setSender($user)
  362.                 ->setConversation($conversation)
  363.                 ->setCreatedAt($date);
  364.         if ($countFiles 0) {
  365.             $message->setType('files');
  366.             $files $_FILES;
  367.             foreach ($files as $file) {
  368.                 $originalName $file['name'];
  369.                 $ext pathinfo($originalNamePATHINFO_EXTENSION);
  370.                 $fileName $this->generateUniqueFileName() . '.' $ext;
  371.                 $directory $this->getParameter('attached_files');
  372.                 if (str_contains($file['type'], 'image')) {
  373.                     $type 'image';
  374.                     $this->imageOptimizer->resizeImageFull($file["tmp_name"], $fileName800800'attached_files');
  375.                 }
  376.                 else {
  377.                     $type 'other';
  378.                     move_uploaded_file($file["tmp_name"], "$directory/" $fileName);
  379.                 }
  380.                 $file = new AttachedFile;
  381.                 $file->setPath($fileName)
  382.                     ->setName($originalName)
  383.                     ->setType($type)
  384.                     ->setExtension($ext)
  385.                     ->setMessage($message);
  386.                 $manager->persist($file);
  387.                 $filesToReturn[] = [
  388.                     'path' => $fileName,
  389.                     'name' => $originalName,
  390.                     'type' => $type,
  391.                     'extension' => $ext
  392.                 ];
  393.                 
  394.             }
  395.         }
  396.         $manager->persist($message);            
  397.         $conversation->setLastMessage($message)
  398.                      ->setLastActivity($date);
  399.         $manager->persist($conversation);
  400.         $manager->flush();
  401.         $interval abs($date->getTimestamp() - $oldLastActivity->getTimestamp()) / 60;
  402.         if ($interval ) {
  403.             // Send email to other
  404.             $toUser->newMessage($other$user$message->getContent(), $conversation->getToken());
  405.         }
  406.         $diff $date->diff($oldLastActivity);
  407.         $days $diff->format('%a');
  408.         if ($days 0) {
  409.             $sameDate false;
  410.         }
  411.         else {
  412.             $sameDate true;
  413.         }
  414.         
  415.         $messageDate $conversationService->formatMessagesDay($date);
  416.         $timeSender = clone $date
  417.         $timeRecipient = clone $date
  418.         $timeSenderFormatted $timeSender->setTimezone(new DateTimeZone($user->getTimezone()));
  419.         $timeRecipientFormatted $timeRecipient->setTimezone(new DateTimeZone($other->getTimezone()));
  420.         $messageToReturn = [
  421.             'sender' => 'Vous',
  422.             'content' => $messageContent,
  423.             'date' => $timeSenderFormatted->format('H:i'),
  424.             'type' => $message->getType(),
  425.             'files' => $filesToReturn,
  426.             'sameDate' => $sameDate,
  427.             'messageDate' => $messageDate
  428.         ];
  429.         // Publish to mercure
  430.         
  431.         $messageToPublish = [
  432.             'sender' => $user->getFirstname() .' '$user->getLastname(),
  433.             'content' => $messageContent,
  434.             'date' => $timeRecipientFormatted->format('H:i'),
  435.             'conversation' => $conversation->getId(),
  436.             'token' => $conversation->getToken(),
  437.             'type' => $message->getType(),
  438.             'files' => $filesToReturn,
  439.             'sameDate' => $sameDate,
  440.             'messageDate' => $message
  441.         ];   
  442.         $recipient $other->getId();
  443.         $url "http://example.com/books";
  444.         if(str_contains($request->getHost(), "racket-trip.com")) {
  445.             $url "http://example-2.com/books";
  446.         }
  447.         $update = new Update(
  448.             $url "/" $recipient,
  449.             json_encode($messageToPublish)
  450.         );
  451.         try {
  452.             $bus->dispatch($update);
  453.         } catch (\Throwable $th) {
  454.             //throw $th;
  455.         }
  456.         
  457.         return new JsonResponse(['message' => $messageToReturn]);    
  458.     }
  459.     #[Route(path'/attach-files'name'attach_files')]
  460.     public function attachFiles(ObjectManager $managerMessageRepository $messageRepo)
  461.     {
  462.         $message $messageRepo->find($_POST['messageId']);
  463.         $files $_FILES;
  464.         $filesToReturn = [];
  465.         foreach ($files as $file) {
  466.             $originalName $file['name'];
  467.             $ext pathinfo($originalNamePATHINFO_EXTENSION);
  468.             if (str_contains($file['type'], 'image')) {
  469.                 $type 'image';
  470.             }
  471.             else {
  472.                 $type 'other';
  473.             }
  474.             $fileName $this->generateUniqueFileName() . '.' $ext;
  475.             $directory $this->getParameter('attached_files');
  476.             $isFileUploaded move_uploaded_file($file["tmp_name"], "$directory/" $fileName);
  477.             if ($isFileUploaded) {
  478.                 $file = new AttachedFile;
  479.                 $file->setPath($fileName)
  480.                     ->setName($originalName)
  481.                     ->setType($type)
  482.                     ->setExtension($ext)
  483.                     ->setMessage($message);
  484.                 $manager->persist($file);
  485.                 $filesToReturn[] = [
  486.                     'path' => $fileName,
  487.                     'name' => $originalName,
  488.                     'type' => $type,
  489.                     'extension' => $ext
  490.                 ];
  491.             }
  492.             
  493.         }
  494.         
  495.         $manager->flush();
  496.         $messageWithFiles = [
  497.             'id' => $message->getId(),
  498.             'sender' => 'Vous',
  499.             'content' => $message->getContent(),
  500.             'date' => $message->getCreatedAt()->format('H:i'),
  501.             'files' => $filesToReturn
  502.         ];
  503.         return new JsonResponse($messageWithFiles);
  504.     }
  505.     #[Route('/discover'name'discover')]
  506.     public function discover(Request $requestDiscovery $discoveryAuthorization $authorization)
  507.     {
  508.         // Link: <https://hub.example.com/.well-known/mercure>; rel="mercure"
  509.         $discovery->addLink($request);
  510.         $authorization->setCookie($request, ['*']);
  511.         return $this->json([true]);
  512.     }
  513.     /* Old Discover
  514.     #[Route(path: '/discover', name: 'discover')]
  515.     public function discover(Request $request, CookieGenerator $cookieGenerator)
  516.     {
  517.         $user = $this->getUser();
  518.         // This parameter is automatically created by the MercureBundle
  519.         $hubUrl = $this->getParameter('mercure.default_hub');
  520.         //$hubUrl = "https://localhost:3000/.well-known/mercure";
  521.         // Link: <http://localhost:3000/.well-known/mercure>; rel="mercure"
  522.         $this->addLink($request, new Link('mercure', $hubUrl));
  523.         $response = $this->json('Done !');
  524.         $cookie = $cookieGenerator->generate($user);
  525.         $response->headers->setCookie($cookie);
  526.         
  527.         return $response;
  528.     }
  529.     */
  530.     #[Route(path'/contact-pro/{from}'name'contact_pro')]
  531.     public function contactPro($fromUserRepository $userRepoConversationService $conversationServiceObjectManager $managerTranslatorInterface $translatorToUser $toUser): Response
  532.     {
  533.         $trainee $this->getUser();
  534.         if (isset($_POST['contact'])) {
  535.             
  536.             $proId $_POST['user_id'];
  537.             $pro $userRepo->find($proId);
  538.             $messageContent $_POST['message'];
  539.             $conversation $conversationService->conversationBetween($trainee$pro);
  540.             $message = new Message;
  541.             $message->setSender($trainee)
  542.                     ->setContent($messageContent)
  543.                     ->setCreatedAt(new \Datetime)
  544.                     ->setIsReaded(false)
  545.                     ->setConversation($conversation);
  546.             $conversation->setLastMessage($message)
  547.                          ->setLastActivity(new \DateTime());
  548.             $manager->persist($conversation);
  549.             $manager->persist($message);
  550.             $manager->flush();
  551.             $this->addFlash(
  552.                 'success',
  553.                 $translator->trans("flashes.message_controller.message_send")
  554.             );
  555.             $toUser->newMessage($pro$trainee$messageContent$conversation->getToken());
  556.             if ($from == 'pro') {
  557.                 
  558.                 return $this->redirectToRoute('view_pro', [
  559.                     'type' => $conversationService->userType($pro),
  560.                     'slug' => $pro->getSlug()
  561.                 ]);
  562.             }
  563.             else {
  564.                 return $this->redirectToRoute('view_course', [
  565.                     'token' => $from
  566.                 ]);
  567.             }
  568.         }
  569.         
  570.         return $this->render('front/message/desktop-messaging.html.twig');
  571.     }
  572. }