97 lines
2.9 KiB
PHP
97 lines
2.9 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Services;
|
|
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Schema;
|
|
|
|
final class FollowAnalyticsService
|
|
{
|
|
public function recordFollow(int $actorId, int $targetId): void
|
|
{
|
|
if (! Schema::hasTable('user_follow_analytics')) {
|
|
return;
|
|
}
|
|
|
|
$this->increment($actorId, 'follows_made');
|
|
$this->increment($targetId, 'followers_gained');
|
|
}
|
|
|
|
public function recordUnfollow(int $actorId, int $targetId): void
|
|
{
|
|
if (! Schema::hasTable('user_follow_analytics')) {
|
|
return;
|
|
}
|
|
|
|
$this->increment($actorId, 'unfollows_made');
|
|
$this->increment($targetId, 'followers_lost');
|
|
}
|
|
|
|
public function summaryForUser(int $userId, int $currentFollowersCount = 0): array
|
|
{
|
|
if (! Schema::hasTable('user_follow_analytics')) {
|
|
return $this->emptySummary();
|
|
}
|
|
|
|
$today = now()->toDateString();
|
|
$weekStart = now()->subDays(6)->toDateString();
|
|
|
|
$todayRow = DB::table('user_follow_analytics')
|
|
->where('user_id', $userId)
|
|
->whereDate('date', $today)
|
|
->first();
|
|
|
|
$weekly = DB::table('user_follow_analytics')
|
|
->where('user_id', $userId)
|
|
->whereBetween('date', [$weekStart, $today])
|
|
->selectRaw('COALESCE(SUM(followers_gained), 0) as gained, COALESCE(SUM(followers_lost), 0) as lost')
|
|
->first();
|
|
|
|
$dailyGained = (int) ($todayRow->followers_gained ?? 0);
|
|
$dailyLost = (int) ($todayRow->followers_lost ?? 0);
|
|
$weeklyGained = (int) ($weekly->gained ?? 0);
|
|
$weeklyLost = (int) ($weekly->lost ?? 0);
|
|
$weeklyNet = $weeklyGained - $weeklyLost;
|
|
$baseline = max(1, $currentFollowersCount - $weeklyNet);
|
|
|
|
return [
|
|
'daily' => [
|
|
'gained' => $dailyGained,
|
|
'lost' => $dailyLost,
|
|
'net' => $dailyGained - $dailyLost,
|
|
],
|
|
'weekly' => [
|
|
'gained' => $weeklyGained,
|
|
'lost' => $weeklyLost,
|
|
'net' => $weeklyNet,
|
|
'growth_rate' => round(($weeklyNet / $baseline) * 100, 1),
|
|
],
|
|
];
|
|
}
|
|
|
|
private function increment(int $userId, string $column): void
|
|
{
|
|
DB::table('user_follow_analytics')->updateOrInsert(
|
|
[
|
|
'user_id' => $userId,
|
|
'date' => now()->toDateString(),
|
|
],
|
|
[
|
|
$column => DB::raw("COALESCE({$column}, 0) + 1"),
|
|
'updated_at' => now(),
|
|
'created_at' => now(),
|
|
]
|
|
);
|
|
}
|
|
|
|
private function emptySummary(): array
|
|
{
|
|
return [
|
|
'daily' => ['gained' => 0, 'lost' => 0, 'net' => 0],
|
|
'weekly' => ['gained' => 0, 'lost' => 0, 'net' => 0, 'growth_rate' => 0.0],
|
|
];
|
|
}
|
|
}
|