db = new FlatFileDB($logFile); $this->maxEntries = $maxEntries; // Initialize logs array if not exists if (!$this->db->exists('logs')) { $this->db->set('logs', []); } } /** * Add a log entry * * @param string $level Log level (info, warning, error, success) * @param string $action Action performed * @param string $message Log message * @param string|null $user User who performed the action * @param array $context Additional context data * @return bool */ public function log(string $level, string $action, string $message, ?string $user = null, array $context = []): bool { if (!in_array($level, $this->validLevels)) { $level = 'info'; } $logs = $this->db->get('logs') ?? []; $entry = [ 'id' => uniqid('log_'), 'timestamp' => date('c'), 'level' => $level, 'action' => $action, 'message' => $message, 'user' => $user ?? ($_SESSION['user']['username'] ?? 'system'), 'ip' => $_SERVER['REMOTE_ADDR'] ?? 'unknown', 'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? 'unknown', 'context' => $context, ]; array_unshift($logs, $entry); // Trim logs to max entries if (count($logs) > $this->maxEntries) { $logs = array_slice($logs, 0, $this->maxEntries); } return $this->db->set('logs', $logs); } /** * Log info level message * * @param string $action * @param string $message * @param array $context * @return bool */ public function info(string $action, string $message, array $context = []): bool { return $this->log('info', $action, $message, null, $context); } /** * Log warning level message * * @param string $action * @param string $message * @param array $context * @return bool */ public function warning(string $action, string $message, array $context = []): bool { return $this->log('warning', $action, $message, null, $context); } /** * Log error level message * * @param string $action * @param string $message * @param array $context * @return bool */ public function error(string $action, string $message, array $context = []): bool { return $this->log('error', $action, $message, null, $context); } /** * Log success level message * * @param string $action * @param string $message * @param array $context * @return bool */ public function success(string $action, string $message, array $context = []): bool { return $this->log('success', $action, $message, null, $context); } /** * Get all logs * * @param int|null $limit * @param int $offset * @return array */ public function getLogs(?int $limit = null, int $offset = 0): array { $logs = $this->db->get('logs') ?? []; if ($limit !== null) { return array_slice($logs, $offset, $limit); } return $logs; } /** * Get logs by level * * @param string $level * @param int|null $limit * @return array */ public function getByLevel(string $level, ?int $limit = null): array { $logs = $this->db->get('logs') ?? []; $filtered = array_filter($logs, fn($log) => $log['level'] === $level); if ($limit !== null) { return array_slice($filtered, 0, $limit); } return array_values($filtered); } /** * Get logs by user * * @param string $user * @param int|null $limit * @return array */ public function getByUser(string $user, ?int $limit = null): array { $logs = $this->db->get('logs') ?? []; $filtered = array_filter($logs, fn($log) => $log['user'] === $user); if ($limit !== null) { return array_slice($filtered, 0, $limit); } return array_values($filtered); } /** * Get logs by action * * @param string $action * @param int|null $limit * @return array */ public function getByAction(string $action, ?int $limit = null): array { $logs = $this->db->get('logs') ?? []; $filtered = array_filter($logs, fn($log) => strpos($log['action'], $action) !== false); if ($limit !== null) { return array_slice($filtered, 0, $limit); } return array_values($filtered); } /** * Get logs by date range * * @param string $startDate * @param string $endDate * @return array */ public function getByDateRange(string $startDate, string $endDate): array { $logs = $this->db->get('logs') ?? []; $start = strtotime($startDate); $end = strtotime($endDate); return array_values(array_filter($logs, function($log) use ($start, $end) { $logTime = strtotime($log['timestamp']); return $logTime >= $start && $logTime <= $end; })); } /** * Search logs * * @param string $query * @param int|null $limit * @return array */ public function search(string $query, ?int $limit = null): array { $logs = $this->db->get('logs') ?? []; $query = strtolower($query); $filtered = array_filter($logs, function($log) use ($query) { return strpos(strtolower($log['message']), $query) !== false || strpos(strtolower($log['action']), $query) !== false || strpos(strtolower($log['user']), $query) !== false; }); if ($limit !== null) { return array_slice($filtered, 0, $limit); } return array_values($filtered); } /** * Get total log count * * @return int */ public function count(): int { $logs = $this->db->get('logs') ?? []; return count($logs); } /** * Clear all logs * * @return bool */ public function clear(): bool { return $this->db->set('logs', []); } /** * Export logs to JSON * * @return string */ public function exportJson(): string { $logs = $this->db->get('logs') ?? []; return json_encode($logs, JSON_PRETTY_PRINT); } /** * Export logs to CSV * * @return string */ public function exportCsv(): string { $logs = $this->db->get('logs') ?? []; $output = "ID,Timestamp,Level,Action,Message,User,IP\n"; foreach ($logs as $log) { $output .= sprintf( '"%s","%s","%s","%s","%s","%s","%s"' . "\n", $log['id'], $log['timestamp'], $log['level'], str_replace('"', '""', $log['action']), str_replace('"', '""', $log['message']), $log['user'], $log['ip'] ); } return $output; } }