69 lines
1.9 KiB
PHP
69 lines
1.9 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Http\Middleware;
|
|
|
|
use Closure;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Schema;
|
|
use Symfony\Component\HttpFoundation\Response;
|
|
|
|
final class UpdateLastVisit
|
|
{
|
|
private const SESSION_KEY = 'last_visit.logged_at';
|
|
|
|
private const THROTTLE_SECONDS = 300;
|
|
|
|
private static ?bool $usersTableHasLastVisitAt = null;
|
|
|
|
public function handle(Request $request, Closure $next): Response
|
|
{
|
|
$response = $next($request);
|
|
|
|
$user = $request->user();
|
|
if (! $user) {
|
|
return $response;
|
|
}
|
|
|
|
if (! $this->usersTableHasLastVisitAt()) {
|
|
return $response;
|
|
}
|
|
|
|
$now = now();
|
|
$session = $request->hasSession() ? $request->session() : null;
|
|
$lastLoggedAt = $session?->get(self::SESSION_KEY);
|
|
|
|
if (is_numeric($lastLoggedAt) && ((int) $lastLoggedAt + self::THROTTLE_SECONDS) > $now->getTimestamp()) {
|
|
return $response;
|
|
}
|
|
|
|
$lastVisitAt = $user->last_visit_at;
|
|
if ($lastVisitAt !== null && method_exists($lastVisitAt, 'getTimestamp')) {
|
|
if (($lastVisitAt->getTimestamp() + self::THROTTLE_SECONDS) > $now->getTimestamp()) {
|
|
$session?->put(self::SESSION_KEY, $lastVisitAt->getTimestamp());
|
|
|
|
return $response;
|
|
}
|
|
}
|
|
|
|
DB::table('users')
|
|
->where('id', $user->id)
|
|
->update([
|
|
'last_visit_at' => $now,
|
|
'updated_at' => $now,
|
|
]);
|
|
|
|
$user->forceFill(['last_visit_at' => $now]);
|
|
$session?->put(self::SESSION_KEY, $now->getTimestamp());
|
|
|
|
return $response;
|
|
}
|
|
|
|
private function usersTableHasLastVisitAt(): bool
|
|
{
|
|
return self::$usersTableHasLastVisitAt ??= Schema::hasColumn('users', 'last_visit_at');
|
|
}
|
|
}
|