$type, 'message' => $message]; } public static function pullFlash(): array { $messages = $_SESSION['flash'] ?? []; unset($_SESSION['flash']); return is_array($messages) ? $messages : []; } public static function audit(PDO $pdo, ?int $userId, string $action, ?string $entityType = null, ?int $entityId = null, array $metadata = []): void { $statement = $pdo->prepare( 'INSERT INTO audit_logs (user_id, action, entity_type, entity_id, metadata) VALUES (:user_id, :action, :entity_type, :entity_id, :metadata)' ); $statement->execute([ 'user_id' => $userId, 'action' => $action, 'entity_type' => $entityType, 'entity_id' => $entityId, 'metadata' => $metadata === [] ? null : json_encode($metadata, JSON_UNESCAPED_SLASHES), ]); } public static function trackVisit(PDO $pdo, string $route): void { if ($_SERVER['REQUEST_METHOD'] !== 'GET') { return; } $ip = (string) ($_SERVER['REMOTE_ADDR'] ?? 'local'); $agent = (string) ($_SERVER['HTTP_USER_AGENT'] ?? 'unknown'); $hash = hash('sha256', date('Y-m-d') . '|' . $ip . '|' . $agent); $statement = $pdo->prepare('INSERT INTO visits (route, visitor_hash) VALUES (:route, :visitor_hash)'); $statement->execute(['route' => $route, 'visitor_hash' => $hash]); } }