add chat system
This commit is contained in:
parent
6a4254050d
commit
532ca041f6
40
hesabixCore/migrations/Version20241220000000.php
Normal file
40
hesabixCore/migrations/Version20241220000000.php
Normal file
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DoctrineMigrations;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
final class Version20241220000000 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'Add memberCount field to chat_channel table';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
// Add memberCount column to chat_channel table
|
||||
$this->addSql('ALTER TABLE chat_channel ADD member_count INT NOT NULL DEFAULT 0');
|
||||
|
||||
// Update existing channels with correct member count
|
||||
$this->addSql('
|
||||
UPDATE chat_channel c
|
||||
SET member_count = (
|
||||
SELECT COUNT(*)
|
||||
FROM chat_channel_member m
|
||||
WHERE m.channel_id = c.id AND m.is_active = 1
|
||||
)
|
||||
');
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
$this->addSql('ALTER TABLE chat_channel DROP member_count');
|
||||
}
|
||||
}
|
|
@ -54,6 +54,7 @@ class ChatController extends AbstractController
|
|||
'isPublic' => $channel->isPublic(),
|
||||
'avatar' => $channel->getAvatar(),
|
||||
'messageCount' => $channel->getMessageCount(),
|
||||
'memberCount' => $channel->getMemberCount(),
|
||||
'lastMessageAt' => $channel->getLastMessageAt()?->format('Y-m-d H:i:s'),
|
||||
'createdAt' => $channel->getCreatedAt()->format('Y-m-d H:i:s'),
|
||||
'isAdmin' => $this->chatService->isUserAdmin($channel, $user),
|
||||
|
@ -128,7 +129,7 @@ class ChatController extends AbstractController
|
|||
'description' => $channel->getDescription(),
|
||||
'isPublic' => $channel->isPublic(),
|
||||
'messageCount' => $channel->getMessageCount(),
|
||||
'memberCount' => $this->chatService->getChannelStats($channel)['memberCount'],
|
||||
'memberCount' => $channel->getMemberCount(),
|
||||
'lastMessageAt' => $channel->getLastMessageAt()?->format('Y-m-d H:i:s'),
|
||||
];
|
||||
}
|
||||
|
@ -387,10 +388,13 @@ class ChatController extends AbstractController
|
|||
], Response::HTTP_FORBIDDEN);
|
||||
}
|
||||
|
||||
$limit = (int) $request->query->get('limit', 50);
|
||||
$limit = (int) $request->query->get('limit', 30);
|
||||
$offset = (int) $request->query->get('offset', 0);
|
||||
|
||||
$messages = $this->chatService->getChannelMessages($channel, $limit, $offset);
|
||||
|
||||
// Get total message count for pagination info
|
||||
$totalMessages = $this->chatService->getChannelMessageCount($channel);
|
||||
|
||||
$data = [];
|
||||
foreach ($messages as $message) {
|
||||
|
@ -418,7 +422,13 @@ class ChatController extends AbstractController
|
|||
|
||||
return $this->json([
|
||||
'success' => true,
|
||||
'data' => $data
|
||||
'data' => $data,
|
||||
'pagination' => [
|
||||
'limit' => $limit,
|
||||
'offset' => $offset,
|
||||
'total' => $totalMessages,
|
||||
'hasMore' => ($offset + $limit) < $totalMessages
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -478,6 +488,11 @@ class ChatController extends AbstractController
|
|||
'id' => $message->getSender()->getId(),
|
||||
'fullName' => $message->getSender()->getFullName(),
|
||||
],
|
||||
'quotedMessage' => $message->getQuotedMessage() ? [
|
||||
'id' => $message->getQuotedMessage()->getId(),
|
||||
'content' => $message->getQuotedMessage()->getContent(),
|
||||
'sender' => $message->getQuotedMessage()->getSender()->getFullName(),
|
||||
] : null,
|
||||
]
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
|
@ -564,6 +579,44 @@ class ChatController extends AbstractController
|
|||
}
|
||||
}
|
||||
|
||||
#[Route('/messages/{messageId}/reactions', name: 'chat_remove_reaction', methods: ['DELETE'])]
|
||||
public function removeReaction(int $messageId, Request $request): JsonResponse
|
||||
{
|
||||
$message = $this->messageRepository->find($messageId);
|
||||
if (!$message) {
|
||||
return $this->json([
|
||||
'success' => false,
|
||||
'message' => 'پیام یافت نشد'
|
||||
], Response::HTTP_NOT_FOUND);
|
||||
}
|
||||
|
||||
$data = json_decode($request->getContent(), true);
|
||||
|
||||
if (!isset($data['emoji']) || empty($data['emoji'])) {
|
||||
return $this->json([
|
||||
'success' => false,
|
||||
'message' => 'ایموجی الزامی است'
|
||||
], Response::HTTP_BAD_REQUEST);
|
||||
}
|
||||
|
||||
/** @var User $user */
|
||||
$user = $this->security->getUser();
|
||||
|
||||
$success = $this->chatService->removeReaction($message, $user, $data['emoji']);
|
||||
|
||||
if ($success) {
|
||||
return $this->json([
|
||||
'success' => true,
|
||||
'message' => 'واکنش حذف شد'
|
||||
]);
|
||||
} else {
|
||||
return $this->json([
|
||||
'success' => false,
|
||||
'message' => 'خطا در حذف واکنش'
|
||||
], Response::HTTP_BAD_REQUEST);
|
||||
}
|
||||
}
|
||||
|
||||
#[Route('/users/search', name: 'chat_search_users', methods: ['GET'])]
|
||||
public function searchUsers(Request $request): JsonResponse
|
||||
{
|
||||
|
|
|
@ -52,6 +52,9 @@ class ChatChannel
|
|||
#[ORM\Column]
|
||||
private int $messageCount = 0;
|
||||
|
||||
#[ORM\Column]
|
||||
private int $memberCount = 0;
|
||||
|
||||
#[ORM\Column(nullable: true)]
|
||||
private ?\DateTimeImmutable $lastMessageAt = null;
|
||||
|
||||
|
@ -236,6 +239,17 @@ class ChatChannel
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function getMemberCount(): int
|
||||
{
|
||||
return $this->memberCount;
|
||||
}
|
||||
|
||||
public function setMemberCount(int $memberCount): static
|
||||
{
|
||||
$this->memberCount = $memberCount;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getLastMessageAt(): ?\DateTimeImmutable
|
||||
{
|
||||
return $this->lastMessageAt;
|
||||
|
|
|
@ -130,13 +130,28 @@ class ChatMessageRepository extends ServiceEntityRepository
|
|||
->getResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get total message count for a channel
|
||||
*/
|
||||
public function getChannelMessageCount(ChatChannel $channel): int
|
||||
{
|
||||
return $this->createQueryBuilder('m')
|
||||
->select('COUNT(m.id)')
|
||||
->where('m.channel = :channel')
|
||||
->andWhere('m.isDeleted = :isDeleted')
|
||||
->setParameter('channel', $channel)
|
||||
->setParameter('isDeleted', false)
|
||||
->getQuery()
|
||||
->getSingleScalarResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get message statistics for a channel
|
||||
*/
|
||||
public function getChannelMessageStats(ChatChannel $channel): array
|
||||
{
|
||||
$qb = $this->createQueryBuilder('m')
|
||||
->select('COUNT(m.id) as total, COUNT(CASE WHEN m.messageType = :emoji THEN 1 END) as emoji_count')
|
||||
->select('COUNT(m.id) as total, SUM(CASE WHEN m.messageType = :emoji THEN 1 ELSE 0 END) as emoji_count')
|
||||
->where('m.channel = :channel')
|
||||
->andWhere('m.isDeleted = :isDeleted')
|
||||
->setParameter('channel', $channel)
|
||||
|
|
|
@ -34,6 +34,7 @@ class ChatService
|
|||
$channel->setDescription($description);
|
||||
$channel->setIsPublic($isPublic);
|
||||
$channel->setCreatedBy($creator);
|
||||
$channel->setMemberCount(1); // Creator is the first member
|
||||
|
||||
// Add creator as admin member
|
||||
$member = new ChatChannelMember();
|
||||
|
@ -72,6 +73,10 @@ class ChatService
|
|||
$member->setIsAdmin(false);
|
||||
|
||||
$this->entityManager->persist($member);
|
||||
|
||||
// Update channel member count
|
||||
$channel->setMemberCount($channel->getMemberCount() + 1);
|
||||
|
||||
$this->entityManager->flush();
|
||||
|
||||
return true;
|
||||
|
@ -88,6 +93,10 @@ class ChatService
|
|||
}
|
||||
|
||||
$member->setIsActive(false);
|
||||
|
||||
// Update channel member count
|
||||
$channel->setMemberCount($channel->getMemberCount() - 1);
|
||||
|
||||
$this->entityManager->flush();
|
||||
|
||||
return true;
|
||||
|
@ -120,6 +129,10 @@ class ChatService
|
|||
}
|
||||
|
||||
$member->setIsActive(false);
|
||||
|
||||
// Update channel member count
|
||||
$channel->setMemberCount($channel->getMemberCount() - 1);
|
||||
|
||||
$this->entityManager->flush();
|
||||
|
||||
return true;
|
||||
|
@ -258,6 +271,14 @@ class ChatService
|
|||
return $this->messageRepository->findChannelMessages($channel, $limit, $offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get total message count for a channel
|
||||
*/
|
||||
public function getChannelMessageCount(ChatChannel $channel): int
|
||||
{
|
||||
return $this->messageRepository->getChannelMessageCount($channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Search public channels
|
||||
*/
|
||||
|
@ -279,7 +300,10 @@ class ChatService
|
|||
*/
|
||||
public function getChannelStats(ChatChannel $channel): array
|
||||
{
|
||||
return $this->channelRepository->getChannelStats($channel);
|
||||
return [
|
||||
'memberCount' => $channel->getMemberCount(),
|
||||
'messageCount' => $channel->getMessageCount()
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue