src/Controller/API/MessageController.php line 360

Open in your IDE?
  1. <?php
  2. namespace App\Controller\API;
  3. use App\Entity\Campaign;
  4. use App\Entity\DiscussionGroup;
  5. use App\Entity\FileMessage;
  6. use App\Entity\Message;
  7. use App\Entity\MessageReaction;
  8. use App\Entity\Mission;
  9. use App\Entity\User;
  10. use App\Event\Chat\GroupedMessageSentEvent;
  11. use App\Event\Chat\MessageSentEvent;
  12. use App\Event\User\UserReactionEvent;
  13. use App\Form\MessageType;
  14. use App\Repository\DiscussionGroupRepository;
  15. use App\Repository\MessageReactionRepository;
  16. use App\Repository\MessageRepository;
  17. use App\Repository\UserRepository;
  18. use App\Service\CampaignApiService;
  19. use App\Service\ChatService;
  20. use Doctrine\ORM\EntityManagerInterface;
  21. use FOS\RestBundle\Controller\Annotations as Rest;
  22. use Nelmio\ApiDocBundle\Annotation\Model;
  23. use OpenApi\Attributes as OA;
  24. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  25. use Symfony\Component\EventDispatcher\EventDispatcherInterface;
  26. use Symfony\Component\HttpFoundation\JsonResponse;
  27. use Symfony\Component\HttpFoundation\Request;
  28. use Symfony\Component\HttpFoundation\Response;
  29. use App\Service\GoogleStorageService;
  30. use App\Service\MessageService;
  31. use App\Service\MissionApiService;
  32. use App\Service\MissionParticipantService;
  33. use App\Service\WorkflowStepService;
  34. use Psr\Log\LoggerInterface;
  35. use Symfony\Component\Mercure\HubInterface;
  36. use Symfony\Component\Mercure\Update;
  37. use Symfony\Component\Serializer\SerializerInterface;
  38. use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
  39. class MessageController extends AbstractController
  40. {
  41.     
  42.     
  43.     public function __construct(
  44.         private EntityManagerInterface $entityManager
  45.         private GoogleStorageService $googleStorageService,
  46.         private MessageService $messageService,
  47.         private LoggerInterface $logger,
  48.         private MessageReactionRepository $messageReactionRepository,
  49.         private EventDispatcherInterface $dispatcher
  50.         private HubInterface $hub
  51.         private SerializerInterface $serializer
  52.         private ChatService $chatService
  53.         private DiscussionGroupRepository $discussionGroupRepository,
  54.     ){}
  55.     /**
  56.      * Add a message to a campaign
  57.      *
  58.      * @param Campaign $campaign
  59.      * @param Request $request
  60.      * @param EntityManagerInterface $entityManager
  61.      * @return Message|\Symfony\Component\Form\FormInterface
  62.      */
  63.     #[Rest\Post('/api/v2/campaigns/{id}/messages')]
  64.     #[Rest\View(statusCodeResponse::HTTP_CREATEDserializerGroups: ['message_write'])]
  65.     #[OA\Tag(name'Campaigns')]
  66.     #[OA\Parameter(
  67.         name'content',
  68.         description'The message\'s content',
  69.         in'query',
  70.         requiredtrue,
  71.         schema: new OA\Schema(type'string'),
  72.     )]
  73.     #[OA\Response(
  74.         responseResponse::HTTP_CREATED,
  75.         description'The message has been created',
  76.         content: new OA\JsonContent(
  77.             type'array',
  78.             items: new OA\Items(ref: new Model(typeMessage::class, groups: ['message_write']))
  79.         )
  80.     )]
  81.     #[OA\Response(
  82.         responseResponse::HTTP_BAD_REQUEST,
  83.         description'The form is invalid and contains errors',
  84.         content: new OA\JsonContent(
  85.             type'array',
  86.             items: new OA\Items(properties: [
  87.                 new OA\Property(property'code'type'integer'),
  88.                 new OA\Property(property'message'type'string'),
  89.                 new OA\Property(property'errors'type'array'items: new OA\Items(properties: [
  90.                     new OA\Property(property'children'type'array'items: new OA\Items(properties: [])),
  91.                 ])),
  92.             ], type'object')
  93.         )
  94.     )]
  95.     #[OA\Response(
  96.         responseResponse::HTTP_UNAUTHORIZED,
  97.         description'Unauthorized - the user isn\'t logged in',
  98.         content: new OA\JsonContent(
  99.             type'array',
  100.             items: new OA\Items(properties: [
  101.                 new OA\Property(property'code'type'integer'),
  102.                 new OA\Property(property'message'type'string'),
  103.             ], type'object')
  104.         )
  105.     )]
  106.     #[OA\Response(
  107.         responseResponse::HTTP_NOT_FOUND,
  108.         description'The campaign doesn\'t exists',
  109.     )]
  110.     public function postMessage(Mission $missionRequest $request,EventDispatcherInterface $dispatcherEntityManagerInterface $entityManagerDiscussionGroupRepository $discussionGroupRepository)
  111.     {
  112.         
  113.         $group $discussionGroupRepository->findOneBy(['id'=>$request->query->get('groupId')]);
  114.       
  115.         $message = (new Message())
  116.             ->setUser($this->getUser())
  117.             ->setCampaign($mission->getCampaign())
  118.             ->setMission($mission)
  119.             ->setUserListWhoRead([$this->getUser()->getId()])
  120.             ->setDiscussionGroup($group);
  121.             ;
  122.         $form $this->createForm(MessageType::class, $message, ['csrf_protection' => false]);
  123.         $form->handleRequest($request);
  124.         if ($form->isSubmitted()) {
  125.             $path 'file_message_directory';
  126.             $idMessageToEdit $request->query->get('id-edit-message') ;
  127.             $idMessageToReply  $request->query->get('id-reply-message');
  128.             $dateOffSetHour $request->query->get('time-zone'0);
  129.             
  130.             $files = []; 
  131.             $newMessage $this->messageService->addMessage($mission$message,$files$idMessageToReply$idMessageToEdit$path);
  132.          
  133.             $renderPlanning $this->chatService->getHtmlToRenderPlanning($mission);
  134.             $typeMessage $idMessageToEdit != "" && $idMessageToEdit!=null 'update''insert';
  135.             
  136.     
  137.             $this->chatService->publishMessageNotificationCampaign(
  138.                 $mission->getId(),
  139.                 [
  140.                 'message'=>$this->serializer->normalize($newMessagenull, [AbstractNormalizer::GROUPS => ['message_read']]),
  141.                 'html'=>$this->chatService->getHtmlToRenderInViewForLastMessage($mission,$newMessage,$dateOffSetHour),
  142.                 'type'=>$typeMessage,
  143.                 'planning' => $renderPlanning,
  144.                 'currentUser' => $this->getUser()->getId(),
  145.                 
  146.             ], $group);
  147.             $this->chatService->publishNotificationMessageUnread("message-send-end-not-read", [
  148.                     "message" => "",
  149.                     'idMission' => $mission->getId(),
  150.                     'group' => !is_null($group) ? $group->getId() : "",
  151.                     'type' => 'message-unread'
  152.                 ]);
  153.     
  154.             $files $form->get('fileMessages')->getData();
  155.             foreach ($files as $file) {
  156.                 $newMessage = new Message();
  157.                 $newMessage->setUser($this->getUser())
  158.                     ->setCampaign($mission->getCampaign())
  159.                     ->setMission($mission)
  160.                     ->setUserListWhoRead([$this->getUser()->getId()]);
  161.                 
  162.                 if (!is_null($group)) {
  163.                     $newMessage->setDiscussionGroup($group);
  164.                 }
  165.     
  166.     
  167.                 $nameSplitByDot explode('.'$file->getClientOriginalName());
  168.                 $extension sizeof($nameSplitByDot) > end($nameSplitByDot) : $file->guessExtension();
  169.                 $type preg_replace('/\/[a-zA-Z-_,.]*\s?/',"",$file->getMimeType());
  170.                 $nameUniqueCompany strtolower("company-" $mission->getCampaign()->getCompany()->getId());
  171.                 $originalFilename pathinfo($file->getClientOriginalName(), PATHINFO_FILENAME);
  172.                 $newFilename $originalFilename '-' uniqid() . '.' $extension;
  173.                 //upload file in google storage
  174.                 $this->googleStorageService->uploadFile($nameUniqueCompany$file$newFilename'Campaigns/' $mission->getCampaign()->getId());
  175.                 $fileMessage = new FileMessage();
  176.                 $fileMessage->setName($newFilename);
  177.                 $fileMessage->setIsNew(1);
  178.                 $fileMessage->setType($type);
  179.                 $fileMessage->setIsNotInfected(true); 
  180.                 $newMessage->addFileMessage($fileMessage);
  181.                 $this->entityManager->persist($newMessage);
  182.     
  183.                 $this->messageService->sendEmailForParticipantMentionedInTchat($mission$newMessage);
  184.     
  185.                 $renderPlanning $this->chatService->getHtmlToRenderPlanning($mission);
  186.                
  187.                 $this->chatService->publishMessageNotificationCampaign(
  188.                     $mission->getId(),
  189.                     [
  190.                         'message' => $this->serializer->normalize($newMessagenull, [AbstractNormalizer::GROUPS => ['message_read']]),
  191.                         'html' => $this->chatService->getHtmlToRenderInViewForLastMessage($mission$newMessage$dateOffSetHour),
  192.                         'type' => 'insert',
  193.                         'planning' => $renderPlanning,
  194.                         'currentUser' => $this->getUser()->getId(),
  195.                     ],
  196.                     $group
  197.                 );
  198.     
  199.                 $this->chatService->publishNotificationMessageUnread("message-send-end-not-read", [
  200.                     "message" => "",
  201.                     'idMission' => $mission->getId(),
  202.                     'group' => !is_null($group) ? $group->getId() : "",
  203.                     'type' => 'message-unread'
  204.                 ]);
  205.     
  206.                 $this->entityManager->flush();
  207.                     
  208.             }   
  209.             return  $newMessage ;
  210.             
  211.         } else {
  212.             return $form;
  213.         }
  214.         
  215.     }
  216.     #[Rest\Get('/api/v2/message/public/discussion/{id}')]
  217.     #[Rest\View(serializerGroups: ['message_read'])]
  218.     #[OA\Response(
  219.         response200,
  220.         description'Get all the details about a mission',
  221.         content: new OA\JsonContent(
  222.             type'array',
  223.             items: new OA\Items(ref: new Model(typeMission::class, groups: ['message_read']))
  224.         )
  225.     )]
  226.     #[OA\Response(
  227.         response401,
  228.         description'Unauthorized - the user isn\'t logged in',
  229.         content: new OA\JsonContent(
  230.             type'array',
  231.             items: new OA\Items(properties: [
  232.                 new OA\Property(property'code'type'integer'),
  233.                 new OA\Property(property'message'type'string'),
  234.             ], type'object')
  235.         )
  236.     )]
  237.     #[OA\Response(
  238.         response404,
  239.         description'The mission with id doesn\'t exists',
  240.     )]
  241.     public function getListDiscussionGroupe(Mission $missionDiscussionGroupRepository $discussionGroupRepositoryMessageService $messageService)
  242.     {   
  243.         $nbrMessageUreadInGroup $messageService->getNumberMessageUnread($missionnull);
  244.         $additionnedDiscussion = new DiscussionGroup(); 
  245.         $additionnedDiscussion->setId('group');
  246.         $additionnedDiscussion->setName('Groupe');
  247.         $additionnedDiscussion->setNbrUnreadMessage($nbrMessageUreadInGroup);
  248.         $additionnedDiscussion->setCampaign($mission->getCampaign());
  249.         $discussionGroupe $discussionGroupRepository->getAllDiscussionGroup($mission->getCampaign());
  250.         
  251.         foreach ($discussionGroupe as $key => $group) {
  252.              $nbrMessageUread $messageService->getNumberMessageUnread($mission$group);
  253.              $group->setNbrUnreadMessage($nbrMessageUread); 
  254.         }
  255.         return [ $additionnedDiscussion,...$discussionGroupe];
  256.     }
  257.     #[Rest\POST('/api/v2/message/toggle-pinned/{id}')]
  258.     #[Rest\View(serializerGroups: ['message_read'])]
  259.     #[OA\Response(
  260.         response200,
  261.         description'Get all the details about a mission',
  262.         content: new OA\JsonContent(
  263.             type'array',
  264.             items: new OA\Items(ref: new Model(typeMission::class, groups: ['message_read']))
  265.         )
  266.     )]
  267.     #[OA\Response(
  268.         response401,
  269.         description'Unauthorized - the user isn\'t logged in',
  270.         content: new OA\JsonContent(
  271.             type'array',
  272.             items: new OA\Items(properties: [
  273.                 new OA\Property(property'code'type'integer'),
  274.                 new OA\Property(property'message'type'string'),
  275.             ], type'object')
  276.         )
  277.     )]
  278.     #[OA\Response(
  279.         response404,
  280.         description'The mission with id doesn\'t exists',
  281.     )]
  282.     public function toggleMessagePinned(Message $message)
  283.     {   
  284.          $userAlreadyPinnedAMessage false
  285.          $currentUser $this->getUser(); 
  286.          foreach ($message->getPinnedByUsers() as $user) {
  287.                 if($user->getId() == $currentUser->getId()){
  288.                      $userAlreadyPinnedAMessage true
  289.                      break;
  290.                 }
  291.          }
  292.          $userAlreadyPinnedAMessage $message->removePinnedByUser$currentUser) :  $message->addPinnedByUser$currentUser);;
  293.          $this->entityManager->flush();
  294.          $this->chatService->publishOnMessagePinned($message); 
  295.           return $message
  296.     }
  297.     #[Rest\Get('/api/v2/message/pinned/{id}/{idGroup}')]
  298.     #[Rest\View(serializerGroups: ['message_read'])]
  299.     #[OA\Response(
  300.         response200,
  301.         description'Get all the details about a mission',
  302.         content: new OA\JsonContent(
  303.             type'array',
  304.             items: new OA\Items(ref: new Model(typeMission::class, groups: ['message_read']))
  305.         )
  306.     )]
  307.     #[OA\Response(
  308.         response401,
  309.         description'Unauthorized - the user isn\'t logged in',
  310.         content: new OA\JsonContent(
  311.             type'array',
  312.             items: new OA\Items(properties: [
  313.                 new OA\Property(property'code'type'integer'),
  314.                 new OA\Property(property'message'type'string'),
  315.             ], type'object')
  316.         )
  317.     )]
  318.     #[OA\Response(
  319.         response404,
  320.         description'The mission with id doesn\'t exists',
  321.     )]
  322.     public function getAllMessagePinned(Mission $mission,string $idGroupMissionApiService $missionApiService,  MessageService $messageServiceMessageRepository $messageRepository,string $page ="0"string $loadMore "0")
  323.     {   
  324.        
  325.  
  326.            $group $idGroup =='group' null $this->discussionGroupRepository->findOneBy(['id'=>$idGroup]);
  327.            $messages $messageRepository->pinnedMessage($mission->getCampaign(), $group$this->getUser()) ;
  328.            usort($messages, function($a$b) {
  329.                     $dateA $a->getCreatedAt()->getTimestamp();
  330.                     $dateB $b->getCreatedAt()->getTimestamp();
  331.                     return   $dateA $dateB 
  332.             });
  333.            $messages $this->addAddionalData($messages,$mission) ; 
  334.         
  335.           return $messages
  336.     }
  337.     #[Rest\Get('/api/v2/message/discussion/{idGroup}/{id}/{page}')]
  338.     #[Rest\View(serializerGroups: ['message_read'])]
  339.     #[OA\Response(
  340.         response200,
  341.         description'Get all the details about a mission',
  342.         content: new OA\JsonContent(
  343.             type'array',
  344.             items: new OA\Items(ref: new Model(typeMission::class, groups: ['message_read']))
  345.         )
  346.     )]
  347.     #[OA\Response(
  348.         response401,
  349.         description'Unauthorized - the user isn\'t logged in',
  350.         content: new OA\JsonContent(
  351.             type'array',
  352.             items: new OA\Items(properties: [
  353.                 new OA\Property(property'code'type'integer'),
  354.                 new OA\Property(property'message'type'string'),
  355.             ], type'object')
  356.         )
  357.     )]
  358.     #[OA\Response(
  359.         response404,
  360.         description'The mission with id doesn\'t exists',
  361.     )]
  362.     public function getAllMessageInGroup(Mission $missionMissionApiService $missionApiService,  MessageService $messageServiceMessageRepository $messageRepositorystring $idGroup,string $page ="0"string $loadMore "0")
  363.     {   
  364.        
  365.            $fileMessage= [];
  366.            $group $idGroup =='group' null $this->discussionGroupRepository->findOneBy(['id'=>$idGroup]);
  367.            $nbrElementPerPage 10;   
  368.            $initialPage $page
  369.           
  370.           $maxPage 5
  371.           $listMessageUnread= [];
  372.           $messages=[];
  373.           $i=0;
  374.           
  375.           while($i<$maxPage){
  376.                 $limite $page == 'all' ?  null :  intval($page) * $nbrElementPerPage
  377.                 $messages $messageRepository->getAllMessage($mission->getCampaign(), $limite$group);
  378.                 if($initialPage == 'all' || intval($initialPage) > || count($messages) == 0){
  379.                     break; 
  380.                 }
  381.                 $listMessageUnread $this->getMessageUnread($messages);
  382.                 if( count($messages) > count($listMessageUnread)){
  383.                      break;
  384.                 }
  385.                 $page++;
  386.                 $i++;
  387.           }
  388.           foreach ($mission->getCampaign()->getFileMissions() as $file) {
  389.                 $nameOfFileinBucket "Campaigns/{$mission->getCampaign()->getId()}/{$file->getName()}";
  390.                 $nameOfBucket "company-{$mission->getCampaign()->getCompany()->getId()}";
  391.                 $fileMessage= [...$fileMessage, [
  392.                     'id'=>$file->getId(), 
  393.                     'name'=>$file->getName(), 
  394.                     'link'=>$this->googleStorageService->getUrlBucket(strtolower($nameOfBucket),$nameOfFileinBucket),
  395.                 ]];
  396.             }
  397.         
  398.            $nbrMessages $messageRepository->nbAllMessage($mission->getCampaign(),$group)['nb'];
  399.            usort($messages, function($a$b) {
  400.                     $dateA $a->getCreatedAt()->getTimestamp();
  401.                     $dateB $b->getCreatedAt()->getTimestamp();
  402.                     return   $dateA $dateB 
  403.             });
  404.             $tempMessages = [];
  405.             foreach ($messages as $message) {
  406.                  if($message->getContent() != null || ($message->getContent()==null && $this->haveFileNotDeleted($message))){
  407.                      $tempMessages = [...$tempMessages$message];
  408.                  }
  409.             }
  410.            $idLastMessageUnred sizeof($listMessageUnread) != end($listMessageUnread)->getId() : null;
  411.            $messages $this->addAddionalData($tempMessages,$mission$idLastMessageUnred) ; 
  412.            $messageService->marqueAllInMissionMessageReadWithGroup($mission$this->getUser(), $group );
  413.            
  414.           return [
  415.                         'messages'=> $messages,
  416.                         'initialBrief'=> $mission->getCampaign()->getBrief(),
  417.                         'nbrMessages'=> $nbrMessages,
  418.                         'idLastMessageUread'=>$idLastMessageUnred,
  419.                         'fileMessage'=> $fileMessage,
  420.                         'page'=>$page,
  421.                         'user_typing'=>[...$this->messageService->calculaTimeTypingOfEachUser($this->messageService->getUserTypingWithoutCurrentUser($mission))]
  422.                     ]
  423.                 ;
  424.     }
  425.      
  426.     public function getMessageUnread(array $messages)
  427.     {
  428.             $currentUserId $this->getUser()->getId(); 
  429.             $listMessageUnread = []; 
  430.             foreach ($messages as $message) {
  431.                 $userIds  array_map(function($item){
  432.                      if($item instanceof User ){
  433.                          return $item->getId(); 
  434.                      }
  435.                      return $item
  436.                  }, $message->getUserListWhoRead());
  437.                 
  438.                  if(!in_array($currentUserId$userIds)){
  439.                     $listMessageUnread[] =  $message
  440.                  }
  441.             }
  442.         return  $listMessageUnread
  443.     }    
  444. private function haveFileNotDeleted(Message $message){
  445.          
  446.         foreach ($message->getFileMessages() as $fileMessage) {
  447.               if($fileMessage->getIsDeleted() != true){
  448.                 return true
  449.               }
  450.         }
  451.         return false
  452.    }
  453.     #[Rest\Get('/api/v2/message/public/{id}/{page}')]
  454.     #[Rest\View(serializerGroups: ['message_read'])]
  455.     #[OA\Response(
  456.         response200,
  457.         description'Get all the details about a mission',
  458.         content: new OA\JsonContent(
  459.             type'array',
  460.             items: new OA\Items(ref: new Model(typeMission::class, groups: ['message_read']))
  461.         )
  462.     )]
  463.     #[OA\Response(
  464.         response401,
  465.         description'Unauthorized - the user isn\'t logged in',
  466.         content: new OA\JsonContent(
  467.             type'array',
  468.             items: new OA\Items(properties: [
  469.                 new OA\Property(property'code'type'integer'),
  470.                 new OA\Property(property'message'type'string'),
  471.             ], type'object')
  472.         )
  473.     )]
  474.     #[OA\Response(
  475.         response404,
  476.         description'The mission with id doesn\'t exists',
  477.     )]
  478.     public function getPublicMessage(Mission $missionMissionApiService $missionApiService,  MessageService $messageServiceMessageRepository $messageRepository,string $page ="0"string $loadMore "0")
  479.     {   
  480.            $userSetPicture=[];
  481.            $messageService->marqueAllInMissionMessageRead($mission$this->getUser());
  482.            $fileMessage=[];
  483.           
  484.            if($page == 'all'){
  485.               $messages $messageRepository->finMessageByCampaign($mission->getCampaign()) ;
  486.               foreach ($mission->getCampaign()->getFileMissions() as $file) {
  487.                     $nameOfFileinBucket "Campaigns/{$mission->getCampaign()->getId()}/{$file->getName()}";
  488.                     $nameOfBucket "company-{$mission->getCampaign()->getCompany()->getId()}";
  489.                      $fileMessage= [...$fileMessage, [
  490.                         'id'=>$file->getId(), 
  491.                         'name'=>$file->getName(), 
  492.                         'link'=>$this->googleStorageService->getUrlBucket(strtolower($nameOfBucket),$nameOfFileinBucket),
  493.                      ]];
  494.               }
  495.               
  496.            }
  497.            else{
  498.               $messages $messageRepository->getAllMessage($mission->getCampaign(), $page 10) ;
  499.            }
  500.            usort($messages, function($a$b) {
  501.                     $dateA $a->getCreatedAt()->getTimestamp();
  502.                     $dateB $b->getCreatedAt()->getTimestamp();
  503.                     return   $dateA $dateB 
  504.             });
  505.            $messages $this->addAddionalData($messages,$mission) ; 
  506.            
  507.         return [ 
  508.                     'messages'=> $messages,
  509.                     'initialBrief'=> $mission->getCampaign()->getBrief(),
  510.                     'fileMessage'=> $fileMessage,
  511.                     'user_typing'=>[...$this->messageService->calculaTimeTypingOfEachUser($this->messageService->getUserTypingWithoutCurrentUser($mission))],
  512.                     
  513.                 ];
  514.     }
  515.     #[Rest\get('/api/v2/message/campaign-state/{id}')]
  516.     #[Rest\View(serializerGroups: ['mission_list','mission_read','step_write','message_read'])]
  517.     #[OA\Response(
  518.         response200,
  519.         description'Returns all the missions for the authenticated user',
  520.         content: new OA\JsonContent(
  521.             type'array',
  522.             items: new OA\Items(ref: new Model(typeMission::class, groups: ['mission_list','message_read','mission_read','step_write']))
  523.         )
  524.     )]
  525.     
  526.     public function campaignState(Mission $mission,MissionParticipantService $missionParticipantServiceWorkflowStepService $workflowStepService,CampaignApiService $campaignApiService,  MissionApiService $missionApiService){
  527.          
  528.         $stateCampaign $missionApiService->getCampaignState($mission->getCampaign()); 
  529.         $notification $this->getNotification($mission$stateCampaign$this->getUser()); 
  530.         $step $workflowStepService->getWorkflowActiveStepBy($mission);
  531.         $responsables $campaignApiService->getWorkflowActiveStepByCampaing($mission->getCampaign());
  532.         $participants =[];
  533.         $listMissionParticipants $missionParticipantService->getParticipants($mission->getCampaign());
  534.         
  535.         $userAlreadyIn = [];
  536.         foreach ($listMissionParticipants as $user) {
  537.                 if($user->getId() != $this->getUser()->getId() && !in_array($user->getId(), $userAlreadyIn)){
  538.                         $participants=[...$participants,[
  539.                             'user'=>[
  540.                                 'id'=> $user->getId(), 
  541.                                 'firstname'=> $user->getFirstname(),
  542.                                 'lastname'=> $user->getLastname(),
  543.                                 'fullname'=>$user->getFullname(), 
  544.                                 'pictureName'=>$user->getPictureName(),
  545.                                 'identifier'=>$user->getIdentifier(), 
  546.                             ]                            
  547.                         ]
  548.                     ] ;
  549.                     $userAlreadyIn =[... $userAlreadyIn$user->getId()]; 
  550.                 }
  551.          }
  552.         return new JsonResponse([
  553.             'state'=>$stateCampaign
  554.             'notifications'=> $notification
  555.             'step'=> $step,
  556.             'future_actions' => $missionParticipantService->getUniqByFutureActions($mission->getCampaign()->getId(),$this->getUser()->getId()),
  557.             'participants'=>  $participants
  558.             'subcontractors_not_evaluate'=>$campaignApiService->getSubcontractorNoEstimatedIncome($mission->getCampaign()),
  559.             'responsable_step'=> $responsables
  560.             'user_typing'=>[...$this->messageService->calculaTimeTypingOfEachUser($this->messageService->getUserTypingWithoutCurrentUser($mission))],
  561.         ]);
  562.     }
  563.     #[Rest\Post('/api/v2/campaigns/delete/filemessages/{id}')]
  564.     #[OA\Response(
  565.         response200,
  566.         description'Returns all the missions for the authenticated user',
  567.         content: new OA\JsonContent(
  568.             type'array',
  569.             items: new OA\Items(ref: new Model(typeMission::class, groups: ['mission_list']))
  570.         )
  571.     )]
  572.     public function deleteFilMessage(FileMessage $fileMessage)
  573.     {   
  574.         $message $fileMessage->getMessages();
  575.         //delete file if in storage
  576.         $company $message->getCampaign()->getCompany();
  577.         $campaign $message->getCampaign();
  578.         $bucketName "company-" strtolower($company->getId());
  579.         $fileName "Campaigns/" $campaign->getId() . "/" $fileMessage->getName();
  580.         //end delete in google storage
  581.         $fileMessage->setIsDeleted(true); 
  582.         $this->entityManager->flush();
  583.         $file $this->messageService->getFileMissionUrl($fileMessage->getMessages()->getMission(), $fileMessage->getName());
  584.         if ($message->getContent() == null && sizeof($fileMessage->getMessages()->getFileMessages()) == 0) {
  585.             $message->setIsDeleted(true);
  586.             $this->entityManager->flush();
  587.         }
  588.         try {
  589.             $this->filesystem->remove($file);
  590.         } catch (\Throwable $th) {
  591.             $this->logger->error("can't delete file in $file");
  592.         }
  593.         $this->googleStorageService->deleteFile($bucketName$fileName);
  594.             $mission $message->getMission();
  595.             $renderContent $this->chatService->getHtmlContentToRenderInViewForLastMessage($mission,$message,0);
  596.             $this->chatService->publishNotificationMessageUnread("message-send-end-not-read", [
  597.                         "message" => "",
  598.                         'idMission' => $message->getMission()->getId(),
  599.                         'group' => $message->getDiscussionGroup(),
  600.                         'type' => 'message-unread'
  601.                     ]);
  602.             
  603.             $this->chatService->publishMessageNotificationCampaign($mission->getId(),[
  604.                 'message'=>$this->serializer->normalize($messagenull, [AbstractNormalizer::GROUPS => ['message_read']],),
  605.                 'html'=>$renderContent,
  606.                 'type'=>'update',
  607.             ]);
  608.         return new JsonResponse([
  609.             'status'=>'ok'
  610.         ]);
  611.     }
  612.     #[Rest\Get('/api/v2/message/un-read-message-per-discussion/{id}')]
  613.     #[OA\Response(
  614.         response200,
  615.         description'Returns all the missions for the authenticated user',
  616.         content: new OA\JsonContent(
  617.             type'array',
  618.             items: new OA\Items(ref: new Model(typeMission::class, groups: ['mission_list']))
  619.         )
  620.     )]
  621.     
  622.     public function getMessageUnreadPerDiscussion(Mission $missionDiscussionGroupRepository $discussionGroupRepositoryMessageService $messageService)
  623.     {   
  624.         $temp=[
  625.             [
  626.                 'id'=> 'group',
  627.                 'nbrMessageUnread'=>$messageService->getNumberMessageUnread($missionnull)
  628.             ]
  629.         ];
  630.         $discussionGroupe $discussionGroupRepository->getAllDiscussionGroup($mission->getCampaign()); 
  631.         foreach ($discussionGroupe as $key => $group) {
  632.             $discussion=[
  633.                 'id'=> $group->getId(),
  634.                 'nbrMessageUnread'=>$messageService->getNumberMessageUnread($mission$group)
  635.             ] ;
  636.             $temp=[...$temp,$discussion];
  637.         }
  638.        
  639.         return new JsonResponse($temp);
  640.     }
  641.     #[Rest\Post('/api/v2/campaigns/delete/messages/{id}')]
  642.     #[OA\Response(
  643.         response200,
  644.         description'Returns all the missions for the authenticated user',
  645.         content: new OA\JsonContent(
  646.             type'array',
  647.             items: new OA\Items(ref: new Model(typeMission::class, groups: ['mission_list']))
  648.         )
  649.     )]
  650.     
  651.     public function deleteMessage(Message $message)
  652.     {   
  653.         $message->setIsDeleted(true);
  654.         $this->entityManager->flush();
  655.         $this->chatService->publishMessageNotificationCampaign($message->getMission()->getId(),['message'=>$message->getId(),'type'=>'deleted'],$message->getDiscussionGroup());
  656.          $this->chatService->publishNotificationMessageUnread("message-send-end-not-read", [
  657.                     "message" => "",
  658.                     'idMission' => $message->getMission()->getId(),
  659.                     'group' => $message->getDiscussionGroup(),
  660.                     'type' => 'message-unread'
  661.                 ]);
  662.         return new JsonResponse([
  663.             'status'=>'ok'
  664.         ]);
  665.     }
  666.  
  667.     #[Rest\Post('/api/v2/message/emoji/{id}')]
  668.     #[OA\Response(
  669.         response200,
  670.         description'Returns all the missions for the authenticated user',
  671.         content: new OA\JsonContent(
  672.             type'array',
  673.             items: new OA\Items(ref: new Model(typeMission::class, groups: ['mission_list']))
  674.         )
  675.     )]
  676.     
  677.     public function addEmoji(Request $requestMessage $message)
  678.     {  
  679.             $emoji $request->request->get('smiley');
  680.             $emojiId $request->request->get('id');
  681.             $campaignOfMessage $message->getCampaign();
  682.             $user $this->getUser();
  683.             $messageReaction $this->messageReactionRepository->findReactionByUser(messageId$message->getId(), userId$user->getId(), emojiId$emojiId);
  684.             if ($messageReaction != null) {
  685.                 $message->removeMessageReaction($messageReaction[0]);
  686.                 $this->entityManager->remove($messageReaction[0]);
  687.                 $this->entityManager->flush();
  688.             } else {
  689.                 $newReaction = new MessageReaction();
  690.                 $newReaction->setEmoji($emoji);
  691.                 $newReaction->setUser($user);
  692.                 $newReaction->setEmojiId(intval($emojiId));
  693.                 $newReaction->setMessage($message);
  694.                 $message->addMessageReaction($newReaction);
  695.                 $this->entityManager->persist($newReaction);
  696.                 $this->entityManager->flush();
  697.                 $event = new UserReactionEvent($message->getUser(), $this->getUser(), $message$newReaction->getEmoji(),$campaignOfMessage);
  698.                 $this->dispatcher->dispatch($eventUserReactionEvent::NAME);
  699.             }
  700.             $mission $message->getMission();
  701.             $renderContent $this->chatService->getHtmlContentToRenderInViewForLastMessage($mission,$message,0);
  702.            
  703.             $this->chatService->publishMessageNotificationCampaign($mission->getId(),[
  704.                 'message'=>$this->serializer->normalize($messagenull, [AbstractNormalizer::GROUPS => ['message_read']],),
  705.                 'html'=>$renderContent,
  706.                 'type'=>'update',
  707.             ]);
  708.         return new JsonResponse(['status'=>$emoji]); 
  709.     }
  710.     #[Rest\Post('/api/v2/messages/user/isTyping/{id}')]
  711.     #[OA\Response(
  712.         response200,
  713.         description'Returns all the missions for the authenticated user',
  714.         content: new OA\JsonContent(
  715.             type'array',
  716.             items: new OA\Items(ref: new Model(typeMission::class, groups: ['mission_list']))
  717.         )
  718.     )]
  719.     
  720.     public function userStartTyping(Mission $mission,Request $request)
  721.     {   
  722.         
  723.          
  724.         $groupId $request->query->get('groupId');
  725.         $group null;
  726.         if (!empty($groupId) && !is_null($groupId)) {
  727.             $group $this->discussionGroupRepository->findOneBy(['id'=>$groupId]);
  728.         }
  729.         $user $this->getUser();
  730.         $this->chatService->publishMessageNotificationCampaign($mission->getId(),[
  731.                 'message'=>"",
  732.                 'type'=>'isTyping',
  733.                 'currentUser' => $user->getId(),
  734.                 'missionIds'=>array_map(function($item){
  735.                     return  $item->getId(); 
  736.                  }, $mission->getCampaign()->getMissions()->toArray()),
  737.                 'typingRender' => $this->chatService->userTyping($user),
  738.                 'user'=> $this->serializer->normalize($usernull, [AbstractNormalizer::GROUPS => ['message_read']])
  739.             ],$group);
  740.         return new JsonResponse([
  741.             'status'=> 'ok',
  742.         ]);
  743.     }
  744.     #[Rest\Post('/api/v2/messages/user/isStopTyping/{id}')]
  745.     #[OA\Response(
  746.         response200,
  747.         description'Returns all the missions for the authenticated user',
  748.         content: new OA\JsonContent(
  749.             type'array',
  750.             items: new OA\Items(ref: new Model(typeMission::class, groups: ['mission_list']))
  751.         )
  752.     )]
  753.     
  754.     public function useFinichedTyping(Mission $mission,Request $request)
  755.     {   
  756.         
  757.         $groupId $request->query->get('groupId');
  758.         $group null;
  759.         if (!empty($groupId) && !is_null($groupId)) {
  760.             $group $this->discussionGroupRepository->findOneBy(['id'=>$groupId]);
  761.         }
  762.         $user $this->getUser();
  763.         $this->chatService->publishMessageNotificationCampaign($mission->getId(),[
  764.                 'message'=>"",
  765.                 'type'=>'isStopTyping',
  766.                 'currentUser' => $user->getId(),
  767.                 'user'=> $this->serializer->normalize($usernull, [AbstractNormalizer::GROUPS => ['message_read']])
  768.             ],$group);
  769.         return new JsonResponse([
  770.             'status'=>'ok'
  771.         ]);
  772.     }
  773.     #[Rest\Post('/api/v2/messages/add/discussion/{id}')]
  774.     #[OA\Response(
  775.         response200,
  776.         description'Returns all the missions for the authenticated user',
  777.         content: new OA\JsonContent(
  778.             type'array',
  779.             items: new OA\Items(ref: new Model(typeMission::class, groups: ['mission_list']))
  780.         )
  781.     )]
  782.     
  783.     public function newDiscussionGroup(Request $request,Campaign $campaignUserRepository $userRepository)
  784.     {   
  785.             $nameDiscussion $request->request->get('newNameDiscussionGroup'null); 
  786.             $userIds $request->request->get('userIdsSelected'); 
  787.             $discussionGroup = new DiscussionGroup(); 
  788.             
  789.             $discussionGroup->setName($nameDiscussion);
  790.             $discussionGroup->setCreatedBy($this->getUser());
  791.             $discussionGroup->setCampaign($campaign);
  792.             $discussionGroup->addUser($this->getUser());
  793.           
  794.         
  795.             foreach ($userIds as $key => $userId) {
  796.                 $user $userRepository->findOneBy(['id'=>$userId]); 
  797.                 if($user instanceof User){
  798.                     $discussionGroup->addUser($user); 
  799.                     if($this->getUser()->getId() != $user->getId()){
  800.                         $event = new GroupedMessageSentEvent($discussionGroup,$user);
  801.                         $this->dispatcher->dispatch($eventGroupedMessageSentEvent::NAME);
  802.                     }
  803.                 }
  804.             }
  805.             $this->entityManager->persist($discussionGroup); 
  806.             $this->entityManager->flush(); 
  807.             $this->chatService->publishOnDiscussionGroupUpdate('add',$discussionGroup); 
  808.             $this->chatService->publishNotificationMessageUnread("message-send-end-not-read", [
  809.                 "message" => "",
  810.                 'idMission' => $campaign->getMissions()->first()->getId(),
  811.                 'group' => !is_null($discussionGroup) ? $discussionGroup->getId() : "",
  812.                 'type' => 'message-unread'
  813.             ]);
  814.         return new JsonResponse([
  815.             'status'=>'ok'
  816.         ]);
  817.     }
  818.     #[Rest\Post('/api/v2/messages/delete/discussion/{id}')]
  819.     #[Rest\View(serializerGroups: ['message_read'])]
  820.     #[OA\Response(
  821.         response200,
  822.         description'Returns all the missions for the authenticated user',
  823.         content: new OA\JsonContent(
  824.             type'array',
  825.             items: new OA\Items(ref: new Model(typeMission::class, groups: ['mission_list']))
  826.         )
  827.     )]
  828.     
  829.     public function deleteDiscussionGroup(Request $requestDiscussionGroup $discussionGroup)
  830.     {   
  831.         
  832.         $message null;
  833.         foreach ($discussionGroup->getMessages() as $message) {
  834.             $message->setIsDeleted(true);
  835.             $this->entityManager->persist($message);
  836.             $this->entityManager->flush();
  837.         }
  838.         $discussionGroup->setDeleted(true);
  839.         $this->entityManager->persist($discussionGroup);
  840.         $this->entityManager->flush();
  841.         if ( null != $message ) {
  842.          $this->chatService->publishNotificationMessageUnread("message-send-end-not-read", [
  843.                     "message" => "",
  844.                     'idMission' => $message->getMission()->getId(),
  845.                     'group' => $discussionGroup,
  846.                     'type' => 'message-unread'
  847.                 ]);
  848.         }
  849.         $this->chatService->publishOnDiscussionGroupUpdate('delete',$discussionGroup); 
  850.      
  851.         return  $discussionGroup;
  852.     }
  853.     #[Rest\Post('/api/v2/messages/discussion/{id}')]
  854.     #[Rest\View(serializerGroups: ['message_read'])]
  855.     #[OA\Response(
  856.         response200,
  857.         description'Returns all the missions for the authenticated user',
  858.         content: new OA\JsonContent(
  859.             type'array',
  860.             items: new OA\Items(ref: new Model(typeMission::class, groups: ['mission_list']))
  861.         )
  862.     )]
  863.     
  864.     public function editDiscussionGroup(Request $requestDiscussionGroup $discussionGroupUserRepository $userRepository)
  865.     {   
  866.         
  867.         $nameDiscussion $request->request->get('newNameDiscussionGroup'null); 
  868.         $userIds $request->request->get('userIdsSelected'); 
  869.         
  870.   
  871.         foreach ($discussionGroup->getUsers() as  $user) {
  872.                 $discussionGroup->removeUser($user);
  873.         }
  874.         if( $nameDiscussion != null){
  875.              $discussionGroup->setName($nameDiscussion); 
  876.         }
  877.         if($userIds!=null){
  878.             foreach ($userIds as $key => $userId) {
  879.                 $user $userRepository->findOneBy(['id'=>$userId]); 
  880.                 if($user instanceof User){
  881.                     $discussionGroup->addUser($user); 
  882.                 }
  883.             }
  884.         }
  885.     
  886.         $this->entityManager->flush(); 
  887.         $this->chatService->publishOnDiscussionGroupUpdate('edit',$discussionGroup); 
  888.      
  889.         return  $discussionGroup;
  890.     }
  891.     #[Rest\Post('/api/v2/message/marque-to-be-read/{id}')]
  892.     #[OA\Response(
  893.        response200,
  894.        description'Returns all the missions for the authenticated user',
  895.        content: new OA\JsonContent(
  896.            type'array',
  897.            items: new OA\Items(ref: new Model(typeMission::class, groups: ['mission_list']))
  898.        )
  899.    )]
  900.    public function marqueUserToReadMessage(Message $message){
  901.         $userWhoReadMessage $message->getUserListWhoRead(); 
  902.         if(!in_array($this->getUser()->getId(),$userWhoReadMessage)){
  903.              $message->setUserListWhoRead([...$message->getUserListWhoRead(), $this->getUser()->getId()]); 
  904.              $this->entityManager->flush(); 
  905.         }
  906.         $this->chatService->publishUserReadMessage($message); 
  907.          $this->chatService->publishMessageNotificationCampaign(
  908.             $message->getCampaign()->getMissions()->first()->getId(),
  909.             [
  910.                 'message' => $this->serializer->normalize($messagenull, [AbstractNormalizer::GROUPS => ['message_read']]),
  911.                 'type' => "userWhoRead",
  912.                 'userId' => $this->getUser()->getId(),
  913.             ],
  914.             $message?->getDiscussionGroup()
  915.         );
  916.         return new JsonResponse([
  917.             'status'=>'ok'
  918.         ]);
  919.    }
  920.    #[Rest\Post('/api/v2/message/user-enter-in-discussion/{id}')]
  921.    #[OA\Response(
  922.       response200,
  923.       description'Returns all the missions for the authenticated user',
  924.       content: new OA\JsonContent(
  925.           type'array',
  926.           items: new OA\Items(ref: new Model(typeMission::class, groups: ['mission_list']))
  927.       )
  928.   )]
  929.   public function onUserEnterInDiscussion(Message $message){
  930.       
  931.        $this->chatService->publishUserEnterInDiscussion($message); 
  932.        return new JsonResponse([
  933.            'status'=>'ok'
  934.        ]);
  935.   }
  936.     public function addAddionlDataForOneMessage($message$mission){
  937.                 // $userWhoReadMessage = $this->messageService->getBullUsersWhoReadMessage($message, $nextMessage); 
  938.                 // $message->setUserListWhoRead($userWhoReadMessage); 
  939.                 foreach ($message->getFileMessages() as $fileMessage) {
  940.                     if($fileMessage->isIsNew()){
  941.                         $nameOfFileinBucket "Campaigns/{$mission->getCampaign()->getId()}/{$fileMessage->getName()}";
  942.                         $nameOfBucket "company-{$mission->getCampaign()->getCompany()->getId()}";
  943.                         $link $this->googleStorageService->getUrlBucket(strtolower($nameOfBucket),$nameOfFileinBucket);;
  944.                     }
  945.                     else{
  946.                         $link "{$this->getParameter('back_website_url')}/{$this->messageService->getFileMissionUrl$mission$fileMessage->getName())}";
  947.                     } 
  948.                     $fileMessage->setName("$link;=;{$fileMessage->getName()}");
  949.                 }
  950.                 $reactions $message->getMessageReactions(); 
  951.                 
  952.                 $message->setReactionListApi($this->formateReactionList($reactions)); 
  953.     }
  954.     public function addAddionalData(Array $messagesMission $mission$idLastMessageUread=null){
  955.         foreach ($messages as $key => $message) {
  956.                 $nextMessage =  sizeof($messages) - != $key  $messages[$key 1] : null 
  957.                 $userWhoReadMessage $this->messageService->getBullUsersWhoReadMessage($message$nextMessage); 
  958.                 $message->setUserListWhoRead($userWhoReadMessage); 
  959.                 if($idLastMessageUread != null && $idLastMessageUread == $message->getId()){
  960.                     $message->setLastMessageUread($idLastMessageUread);
  961.                 }
  962.                 // foreach ($message->getFileMessages() as $fileMessage) {
  963.                 //     if($fileMessage->isIsNew()){
  964.                 //         $nameOfFileinBucket = "Campaigns/{$mission->getCampaign()->getId()}/{$fileMessage->getName()}";
  965.                 //         $nameOfBucket = "company-{$mission->getCampaign()->getCompany()->getId()}";
  966.                 //         $link = $this->googleStorageService->getUrlBucket(strtolower($nameOfBucket),$nameOfFileinBucket);;
  967.                 //     }
  968.                 //     else{
  969.                 //         $link = "{$this->getParameter('back_website_url')}/{$this->messageService->getFileMissionUrl( $mission, $fileMessage->getName())}";
  970.                 //     } 
  971.                 //     $fileMessage->setName("$link;=;{$fileMessage->getName()}");
  972.                 // }
  973.                
  974.         }
  975.         return $messages;
  976.     }
  977.     public function formateReactionList($reactions){
  978.         $newReactionType =[]; 
  979.         foreach ($reactions as $key => $reaction) {
  980.             $newReactionType = [... $newReactionType, [
  981.                 'id'=> $reaction->getId(), 
  982.                 'emojy'=> $reaction->getEmoji()
  983.             ]];
  984.         }
  985.         return $newReactionType
  986.     }
  987.     private function getNotification(Mission $mission,Array $stateCampaignUser $user){
  988.         $state $stateCampaign['state']; 
  989.         switch (true) {
  990.             case  in_array('ROLE_SUBCONTRACTOR'$user->getRoles()): {
  991.                 if($state == "waiting_resend"){
  992.                     return "Mission en attente de resoumission au client"
  993.                 }
  994.                 if($state == "waiting_validation"){
  995.                     return "Le client a été notifié pour valider votre proposition"
  996.                 }
  997.             }
  998.             
  999.             default:
  1000.                return ""
  1001.         }
  1002.     }
  1003. }