ultimatepos/Modules/Communication/Services/ChatRoomService.php

101 lines
3.6 KiB
PHP

<?php
namespace Modules\Communication\Services;
use App\User;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\ValidationException;
use Modules\Communication\Entities\ChatRoom;
class ChatRoomService
{
public function findOrCreateDirectRoom(int $businessId, User $user, int $otherUserId): ChatRoom
{
$this->assertColleague($businessId, $otherUserId);
$existing = ChatRoom::where('business_id', $businessId)
->where('type', 'direct')
->whereHas('members', fn ($q) => $q->where('users.id', $user->id))
->whereHas('members', fn ($q) => $q->where('users.id', $otherUserId))
->first();
if ($existing) {
return $existing->load(['members', 'latestMessage.user']);
}
return DB::transaction(function () use ($businessId, $user, $otherUserId) {
$room = ChatRoom::create([
'business_id' => $businessId,
'type' => 'direct',
'created_by' => $user->id,
]);
$room->members()->attach([$user->id, $otherUserId]);
return $room->load(['members', 'latestMessage.user']);
});
}
public function createGroupRoom(int $businessId, User $user, string $name, array $memberIds): ChatRoom
{
$memberIds = array_values(array_unique(array_map('intval', array_merge($memberIds, [$user->id]))));
foreach ($memberIds as $memberId) {
$this->assertColleague($businessId, $memberId);
}
return DB::transaction(function () use ($businessId, $user, $name, $memberIds) {
$room = ChatRoom::create([
'business_id' => $businessId,
'type' => 'group',
'name' => $name,
'created_by' => $user->id,
]);
$room->members()->attach($memberIds);
return $room->load(['members', 'latestMessage.user']);
});
}
public function assertRoomMember(ChatRoom $room, User $user): void
{
if (! $room->members()->where('users.id', $user->id)->exists()) {
throw ValidationException::withMessages(['room' => __('communication::lang.not_room_member')]);
}
}
public function assertColleague(int $businessId, int $userId): void
{
$exists = User::where('business_id', $businessId)->where('id', $userId)->exists();
if (! $exists) {
throw ValidationException::withMessages(['user_id' => __('communication::lang.user_not_in_business')]);
}
}
public function addMember(ChatRoom $room, int $businessId, User $actor, int $memberId): ChatRoom
{
$this->assertRoomMember($room, $actor);
if ($room->type !== 'group') {
throw ValidationException::withMessages(['room' => __('communication::lang.group_only')]);
}
$this->assertColleague($businessId, $memberId);
if (! $room->members()->where('users.id', $memberId)->exists()) {
$room->members()->attach($memberId);
}
return $room->load(['members', 'latestMessage.user']);
}
public function removeMember(ChatRoom $room, User $actor, int $memberId): ChatRoom
{
$this->assertRoomMember($room, $actor);
if ($room->type !== 'group') {
throw ValidationException::withMessages(['room' => __('communication::lang.group_only')]);
}
if ($memberId !== $actor->id && (int) $room->created_by !== (int) $actor->id) {
abort(403, 'Unauthorized action.');
}
$room->members()->detach($memberId);
return $room->load(['members', 'latestMessage.user']);
}
}