Files
SkinbaseNova/app/Services/Messaging/MessageNotificationService.php

80 lines
2.3 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Services\Messaging;
use App\Models\Conversation;
use App\Models\ConversationParticipant;
use App\Models\Message;
use App\Models\User;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
class MessageNotificationService
{
public function __construct(
private readonly MessagingPresenceService $presence,
) {}
public function notifyNewMessage(Conversation $conversation, Message $message, User $sender): void
{
if (! DB::getSchemaBuilder()->hasTable('notifications')) {
return;
}
$recipientIds = ConversationParticipant::query()
->where('conversation_id', $conversation->id)
->whereNull('left_at')
->where('user_id', '!=', $sender->id)
->where('is_muted', false)
->where('is_archived', false)
->pluck('user_id')
->all();
if (empty($recipientIds)) {
return;
}
$recipientRows = User::query()
->whereIn('id', $recipientIds)
->get()
->filter(fn (User $recipient) => $recipient->allowsMessagesFrom($sender))
->filter(function (User $recipient): bool {
if (! (bool) config('messaging.notifications.offline_fallback_only', true)) {
return true;
}
return ! $this->presence->isUserOnline((int) $recipient->id);
})
->pluck('id')
->map(fn ($id) => (int) $id)
->values()
->all();
if (empty($recipientRows)) {
return;
}
$preview = Str::limit((string) $message->body, 120, '…');
$now = now();
$rows = array_map(static fn (int $recipientId) => [
'user_id' => $recipientId,
'type' => 'message',
'data' => json_encode([
'conversation_id' => $conversation->id,
'sender_id' => $sender->id,
'sender_name' => $sender->username,
'preview' => $preview,
'message_id' => $message->id,
], JSON_UNESCAPED_UNICODE),
'read_at' => null,
'created_at' => $now,
'updated_at' => $now,
], $recipientRows);
DB::table('notifications')->insert($rows);
}
}