better filtering and searching

This commit is contained in:
2026-01-09 11:20:27 -05:00
parent f9d9c775fb
commit 962724d811
10 changed files with 1388 additions and 9 deletions

View File

@@ -321,4 +321,123 @@ class AuditLogModel {
$stmt->close();
return $timeline;
}
/**
* Get filtered audit logs with advanced search
*
* @param array $filters Associative array of filter criteria
* @param int $limit Maximum number of logs to return
* @param int $offset Offset for pagination
* @return array Array containing logs and total count
*/
public function getFilteredLogs($filters = [], $limit = 50, $offset = 0) {
$whereConditions = [];
$params = [];
$paramTypes = '';
// Action type filter
if (!empty($filters['action_type'])) {
$actions = explode(',', $filters['action_type']);
$placeholders = str_repeat('?,', count($actions) - 1) . '?';
$whereConditions[] = "al.action_type IN ($placeholders)";
$params = array_merge($params, $actions);
$paramTypes .= str_repeat('s', count($actions));
}
// Entity type filter
if (!empty($filters['entity_type'])) {
$entities = explode(',', $filters['entity_type']);
$placeholders = str_repeat('?,', count($entities) - 1) . '?';
$whereConditions[] = "al.entity_type IN ($placeholders)";
$params = array_merge($params, $entities);
$paramTypes .= str_repeat('s', count($entities));
}
// User filter
if (!empty($filters['user_id'])) {
$whereConditions[] = "al.user_id = ?";
$params[] = (int)$filters['user_id'];
$paramTypes .= 'i';
}
// Entity ID filter (for specific ticket/comment)
if (!empty($filters['entity_id'])) {
$whereConditions[] = "al.entity_id = ?";
$params[] = $filters['entity_id'];
$paramTypes .= 's';
}
// Date range filters
if (!empty($filters['date_from'])) {
$whereConditions[] = "DATE(al.created_at) >= ?";
$params[] = $filters['date_from'];
$paramTypes .= 's';
}
if (!empty($filters['date_to'])) {
$whereConditions[] = "DATE(al.created_at) <= ?";
$params[] = $filters['date_to'];
$paramTypes .= 's';
}
// IP address filter
if (!empty($filters['ip_address'])) {
$whereConditions[] = "al.ip_address LIKE ?";
$params[] = '%' . $filters['ip_address'] . '%';
$paramTypes .= 's';
}
// Build WHERE clause
$whereClause = '';
if (!empty($whereConditions)) {
$whereClause = 'WHERE ' . implode(' AND ', $whereConditions);
}
// Get total count for pagination
$countSql = "SELECT COUNT(*) as total FROM audit_log al $whereClause";
$countStmt = $this->conn->prepare($countSql);
if (!empty($params)) {
$countStmt->bind_param($paramTypes, ...$params);
}
$countStmt->execute();
$totalResult = $countStmt->get_result();
$totalCount = $totalResult->fetch_assoc()['total'];
$countStmt->close();
// Get filtered logs
$sql = "SELECT al.*, u.username, u.display_name
FROM audit_log al
LEFT JOIN users u ON al.user_id = u.user_id
$whereClause
ORDER BY al.created_at DESC
LIMIT ? OFFSET ?";
$stmt = $this->conn->prepare($sql);
// Add limit and offset parameters
$params[] = $limit;
$params[] = $offset;
$paramTypes .= 'ii';
if (!empty($params)) {
$stmt->bind_param($paramTypes, ...$params);
}
$stmt->execute();
$result = $stmt->get_result();
$logs = [];
while ($row = $result->fetch_assoc()) {
if ($row['details']) {
$row['details'] = json_decode($row['details'], true);
}
$logs[] = $row;
}
$stmt->close();
return [
'logs' => $logs,
'total' => $totalCount,
'pages' => ceil($totalCount / $limit)
];
}
}