Files
SkinbaseNova/app/Services/UserMentionSyncService.php

79 lines
2.3 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Services;
use App\Models\ArtworkComment;
use App\Models\User;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
final class UserMentionSyncService
{
public function syncForComment(ArtworkComment $comment): void
{
if (! Schema::hasTable('user_mentions')) {
return;
}
$usernames = $this->extractMentions((string) ($comment->raw_content ?? $comment->content ?? ''));
$mentionedIds = $usernames === []
? []
: User::query()
->whereIn(DB::raw('LOWER(username)'), $usernames)
->where('is_active', true)
->whereNull('deleted_at')
->pluck('id')
->map(fn ($id) => (int) $id)
->all();
DB::transaction(function () use ($comment, $mentionedIds): void {
DB::table('user_mentions')
->where('comment_id', (int) $comment->id)
->delete();
if ($mentionedIds === []) {
return;
}
$rows = collect($mentionedIds)
->reject(fn (int $id) => $id === (int) $comment->user_id)
->unique()
->map(fn (int $mentionedUserId) => [
'user_id' => (int) $comment->user_id,
'mentioned_user_id' => $mentionedUserId,
'artwork_id' => (int) $comment->artwork_id,
'comment_id' => (int) $comment->id,
'created_at' => $comment->created_at ?? now(),
])
->values()
->all();
if ($rows !== []) {
DB::table('user_mentions')->insert($rows);
}
});
}
public function deleteForComment(int $commentId): void
{
if (! Schema::hasTable('user_mentions')) {
return;
}
DB::table('user_mentions')->where('comment_id', $commentId)->delete();
}
private function extractMentions(string $content): array
{
preg_match_all('/(^|[^A-Za-z0-9_])@([A-Za-z0-9_-]{3,20})/', $content, $matches);
return collect($matches[2] ?? [])
->map(fn ($username) => strtolower((string) $username))
->unique()
->values()
->all();
}
}