Files
animexe/app/Support/ActivityLogger.php
T
2026-07-14 00:01:48 +03:00

78 lines
2.8 KiB
PHP

<?php
namespace App\Support;
use App\Models\UserActivityLog;
use Illuminate\Http\Request;
class ActivityLogger
{
public static function log(
string $action,
?int $userId = null,
?string $subjectType = null,
?int $subjectId = null,
?array $meta = null,
?Request $request = null
): void {
try {
$req = $request ?? request();
$ip = $req->ip();
$ua = $req->userAgent() ?? '';
$isBot = (bool) $req->attributes->get('is_bot', false);
$geo = cache()->remember("geo_{$ip}", 3600, fn() => self::geoIp($ip));
UserActivityLog::create([
'user_id' => $userId ?? auth()->id(),
'session_id' => session()->getId(),
'action' => $action,
'subject_type' => $subjectType,
'subject_id' => $subjectId,
'ip' => $ip,
'country' => $geo['country'] ?? null,
'city' => $geo['city'] ?? null,
'device' => self::device($ua),
'browser' => self::browser($ua),
'user_agent' => mb_substr($ua, 0, 500),
'is_bot' => $isBot,
'meta' => $meta,
'created_at' => now(),
]);
} catch (\Throwable) {
// never break the app
}
}
private static function geoIp(string $ip): array
{
try {
if (in_array($ip, ['127.0.0.1', '::1']) || str_starts_with($ip, '192.168.') || str_starts_with($ip, '10.')) {
return ['country' => 'Local', 'city' => null];
}
$r = \Illuminate\Support\Facades\Http::timeout(2)->get("http://ip-api.com/json/{$ip}?fields=country,city,status");
$d = $r->json();
return ($d['status'] ?? '') === 'success' ? ['country' => $d['country'], 'city' => $d['city']] : [];
} catch (\Throwable) {
return [];
}
}
private static function device(string $ua): string
{
$ua = strtolower($ua);
if (str_contains($ua, 'mobile') || str_contains($ua, 'android') || str_contains($ua, 'iphone')) return 'mobile';
if (str_contains($ua, 'tablet') || str_contains($ua, 'ipad')) return 'tablet';
return 'desktop';
}
private static function browser(string $ua): string
{
if (str_contains($ua, 'Chrome')) return 'Chrome';
if (str_contains($ua, 'Firefox')) return 'Firefox';
if (str_contains($ua, 'Safari')) return 'Safari';
if (str_contains($ua, 'Edge')) return 'Edge';
if (str_contains($ua, 'Opera')) return 'Opera';
return 'Other';
}
}