101 lines
3.6 KiB
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']);
|
|
}
|
|
}
|