<?php
namespace App\Controller\Front;
use App\Entity\Discussion;
use App\Entity\Message;
use App\Entity\User;
use App\Form\MessageType;
use App\Helper\ControllerHelper;
use App\Repository\CommentRepository;
use App\Repository\DiscussionRepository;
use App\Repository\MessageRepository;
use App\Repository\ModuleInscriptionRepository;
use App\Repository\ProgramRepository;
use App\Repository\SubjectRepository;
use App\Repository\UserRepository;
use App\Utils\Constants;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Console\Helper\Helper;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Mercure\HubInterface;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Mercure\PublisherInterface;
use Symfony\Component\Mercure\Update;
use Symfony\Component\String\Slugger\SluggerInterface;
class MessageController extends AbstractController
{
use ControllerHelper;
private $hub;
private $slugger;
public function __construct(HubInterface $hub, SluggerInterface $slugger)
{
$this->hub = $hub;
$this->slugger = $slugger;
}
/**
* @Route("/chat", name="app_front_message_chat", methods={"GET", "POST"})
* @param Request $request
* @param MessageRepository $messageRepository
* @return JsonResponse
* @throws Exception
*/
public function chat(Request $request, MessageRepository $messageRepository, DiscussionRepository $discussionRepository, ProgramRepository $programRepository, SubjectRepository $subjectRepository, CommentRepository $commentRepository, ModuleInscriptionRepository $moduleInscriptionRepository, HubInterface $hub)
{
/** @var User $currentUser */
$currentUser = $this->getUser();
$myTopics = [];
$subsidiaryCompany = $currentUser->getSubsidiaryCompany();
if ($subsidiaryCompany !== null) {
$programs = $programRepository->findProgramsBySubsidiaryCompany($subsidiaryCompany);
foreach ($programs as $program) {
$topic = $this->slugger->slug(strtolower('program_'.$program->getLabel().'_'.$currentUser->getId()))->toString();
$myTopics [] = $topic;
}
}
$subjects = $subjectRepository->findBy(['createdBy' => $currentUser]);
foreach ($subjects as $subject) {
$topic = $this->slugger->slug(strtolower('subject_'.$subject->getTitle().'_'.$currentUser->getId()))->toString();
$myTopics [] = $topic;
}
$comments = $commentRepository->findBy(['createdBy' => $currentUser]);
foreach ($comments as $comment) {
$topic = $this->slugger->slug(strtolower('comment_'.$comment->getId().'_'.$currentUser->getId()))->toString();
$myTopics [] = $topic;
}
$topic = [
'chat_'.$currentUser->getId().'_{id}',
'chat_{id}_'.$currentUser->getId(),
'program-{program_name}-'.$currentUser->getId(),
'module-{module_name}-'.$currentUser->getId(),
'subject-{subject_title}-'.$currentUser->getId(),
'comment-{comment_id}-'.$currentUser->getId(),
'quote-{quote_title}-'.$currentUser->getId(),
Constants::DEFAULT_TOPIC.'/1'
];
$message = new Message();
$form = $this->createForm(MessageType::class, $message);
$form->handleRequest($request);
if ($form->isSubmitted()) {
if ($form->isValid()) {
$receiver = $message->getReceiver();
$discussion = $discussionRepository->findOneBy(['createdBy' => $currentUser, 'receiver' => $receiver]);
if ($discussion === null) {
$discussion = new Discussion();
$discussion->setReceiver($receiver);
$discussionRepository->add($discussion, true);
}
$message->setDiscussion($discussion);
$messageRepository->add($message, true);
$data = [
'createdById' => $currentUser->getId(),
'receiverId' => $receiver->getId(),
'photo' => ($currentUser->getPhoto() !== null) ? '/files/images/'.$currentUser->getPhoto()->getFileName() : "",
'fullName' => $currentUser->getFullname(),
'profileColor' => $currentUser->getProfileColor(),
'time' => $this->getHumanTiming($message->getCreatedAt()->getTimestamp(), 'long'),
'content' => $message->getContent(),
'visibility' => $message->getVisibility(),
'action' => 'add'
];
$topic = [
'chat_'.$currentUser->getId().'_'.$receiver->getId(),
'chat_'.$receiver->getId().'_'.$currentUser->getId(),
'program-{program_name}-'.$currentUser->getId(),
'module-{module_name}-'.$currentUser->getId(),
'subject-{subject_title}-'.$currentUser->getId(),
'comment-{comment_id}-'.$currentUser->getId(),
'quote-{quote_title}-'.$currentUser->getId(),
Constants::DEFAULT_TOPIC.'/1'
];
$update = new Update(
$topic,
json_encode($data)
);
$hub->publish($update);
// $this->publish($topic, $data);
return new JsonResponse($data);
} else {
return new JsonResponse([
'errors' => $this->getErrorMessages($form)
], Response::HTTP_OK);
}
}
return $this->render('front/components/messenger.html.twig', [
'form' => $form->createView(),
'config' => [
'topics' => (!empty($topic)) ? $topic : [],
'publishRoute' => $this->generateUrl('app_front_message_chat'),
'mercureHubUrl' => $_ENV['MERCURE_URL'],
'myTopics' => $myTopics
]
]);
}
/**
* @Route("/messages-chat", name="app_front_message_list", methods={"GET", "POST"})
* @param Request $request
* @return JsonResponse
*/
public function list(Request $request, MessageRepository $messageRepository)
{
$messages = $messageRepository->findAll();
$topic = $request->get('topic');
$publishRoute = $this->generateUrl('app_front_message_chat', ['topic' => $topic]);
$data = [];
foreach ($messages as $message) {
$createdBy = $message->getCreatedBy();
$data ['messages'][] = [
'createdById' => $message->getCreatedBy()->getId(),
'photo' => ($createdBy->getPhoto() !== null) ? '/files/images/'.$createdBy->getPhoto()->getFileName() : "",
'fullName' => $createdBy->getFullname(),
'profileColor' => $createdBy->getProfileColor(),
'time' => $this->getHumanTiming($message->getCreatedAt()->getTimestamp(), 'long'),
'content' => $message->getContent(),
'visibility' => $message->getVisibility(),
'action' => 'add'
];
}
$data['publishRoute'] = $publishRoute;
return new JsonResponse($data);
}
/**
* @Route("/messages-discussion/{id}", name="app_front_message_discussion", methods={"GET"})
* @param Request $request
* @return JsonResponse
*/
public function discussion(MessageRepository $messageRepository, User $receiver)
{
/** Check if current user is allowed to see discussions */
if ($receiver === null) return new JsonResponse([]);
/** @var User $currentUser */
$currentUser = $this->getUser();
$messages = $messageRepository->findMessages($currentUser, $receiver);
$data = [];
foreach ($messages as $message) {
if($message->getReceiver() == $currentUser) {
$message->setIsRead(true);
$messageRepository->add($message, true);
}
$data [] = [
'id' => $message->getId(),
'isReceive' => ($message->getCreatedBy() !== $currentUser),
'message' => $message->getContent(),
'date' => $this->getHumanTiming($message->getCreatedAt()->getTimestamp(), 'long')
];
}
return new JsonResponse($data);
}
/**
* @Route("/find-users", name="app_front_message_find_user", methods={"POST"})
* @param Request $request
* @return JsonResponse
*/
public function findUser(Request $request, UserRepository $userRepository)
{
$searchKey = $request->get('search_key');
if ($searchKey === null || empty($searchKey)) return new JsonResponse([]);
$users = $userRepository->findUsersBySearchKey($this->getUser(), $searchKey);
$data = [];
foreach ($users as $user) {
$customPhoto = '<div style="width: 60px; height: 60px"><div class="rounded-circle shadow-sm position-relative img-profile-pic d-flex align-items-center justify-content-center bg-danger" style="width: 100%; height: 100%; background-color: '.$user["profileColor"].' !important;"><p class="fw-bold text-white" style="margin: auto; font-size: 1.1rem !important;">'.substr($user["firstname"], 0, 1).' '.substr($user["lastname"], 0, 1).'</p></div></div>';
$data [] = [
'id' => $user['id'],
'photo' => ($user['filename'] !== null) ? '/files/images/'.$user['filename'] : "",
'custom_photo' => $customPhoto,
'lastname' => $user['lastname'],
'firstname' => $user['firstname'],
'profileColor' => $user['profileColor'],
'message' => '',
'text' => $user['firstname'].' '.$user['lastname'],
'is_new_message' => false
];
}
return new JsonResponse($data);
}
/**
* @Route("/find-user-data", name="app_find_user_data", methods={"GET"})
* @param Request $request
* @return JsonResponse
*/
public function findUserData(Request $request, UserRepository $userRepository)
{
$searchKey = $request->query->get('search_key');
if ($searchKey === null || empty($searchKey)) return new JsonResponse([]);
$users = $userRepository->findUsersBySearchKey($this->getUser(), $searchKey);
$data = [];
foreach ($users as $user) {
$customPhoto = '<div style="width: 60px; height: 60px"><div class="rounded-circle shadow-sm position-relative img-profile-pic d-flex align-items-center justify-content-center bg-danger" style="width: 100%; height: 100%; background-color: '.$user["profileColor"].' !important;"><p class="fw-bold text-white" style="margin: auto; font-size: 1.1rem !important;">'.substr($user["firstname"], 0, 1).' '.substr($user["lastname"], 0, 1).'</p></div></div>';
$data['results'] [] = [
'id' => $user['id'],
'photo' => ($user['filename'] !== null) ? '/files/images/'.$user['filename'] : "",
'custom_photo' => $customPhoto,
'lastname' => $user['lastname'],
'firstname' => $user['firstname'],
'profileColor' => $user['profileColor'],
'message' => '',
'text' => $user['firstname'].' '.$user['lastname'],
'is_new_message' => false
];
}
return new JsonResponse($data);
}
/**
* @Route("/my-contacts", name="app_front_message_my_contact", methods={"GET"})
* @param Request $request
* @return JsonResponse
*/
public function myContact(Request $request, MessageRepository $messageRepository, DiscussionRepository $discussionRepository)
{
// $searchKey = $request->get('search_key');
// if ($searchKey === null || empty($searchKey)) return new JsonResponse([]);
/** @var User $currentUser */
$currentUser = $this->getUser();
$discussions = (!$currentUser->getSenderDiscussions()->isEmpty()) ? $currentUser->getSenderDiscussions() : $currentUser->getReceiverDiscussions();
//$discussions = $discussionRepository->findDiscussions($currentUser);
$data = [];
foreach ($discussions as $discussion) {
$receiver = $discussion->getReceiver();
$myContact = ($receiver === $currentUser) ? $discussion->getCreatedBy() : $discussion->getReceiver();
//$lastMessage = (!$myContact->getMessages()->isEmpty()) ? $myContact->getMessages()->last() : null;
$discussion = $discussionRepository->findOneBy(['createdBy' => $currentUser, 'receiver' => $receiver]);
$discussionReverse = $discussionRepository->findOneBy(['createdBy' => $receiver, 'receiver' => $currentUser]);
$lastMessage = $discussion ? $messageRepository->findOneBy(array('discussion' => [$discussion, $discussionReverse]), array('createdAt' => 'DESC')) : null;
//$lastMessage = count($lastMessage) > 0 ? $lastMessage = $lastMessage->first() : null;
$data [] = [
'id' => $myContact->getId(),
'photo' => ($myContact->getPhoto() !== null) ? '/files/images/'.$myContact->getPhoto()->getFileName() : "",
'firstname' => $myContact->getFirstname(),
'profileColor' => $myContact->getProfileColor(),
'lastname' => $myContact->getLastname(),
'message' => ($lastMessage !== null) ? $lastMessage->getContent() : "",
'is_new_message' => false,
'new_messages_count' => $myContact->getMessages()->filter(function($message) use($currentUser) {
return (!$message->isIsRead() && $message->getReceiver() == $currentUser);
})->count()
];
}
//dd($data);
return new JsonResponse($data);
}
public function publish(String $topic, array $data): void
{
$update = new Update(
$topic,
json_encode($data)
);
// Publisher's JWT must contain this topic, a URI template it matches or * in mercure.publish or you'll get a 401
// Subscriber's JWT must contain this topic, a URI template it matches or * in mercure.subscribe to receive the update
$this->hub->publish($update);
}
}