23))) {
http_response_code(400);
exit('Invalid hour');
}
// Pagination
$page = isset($_GET['page']) ? filter_var($_GET['page'], FILTER_VALIDATE_INT) : 1;
if ($page === false || $page < 1) { $page = 1; }
$pageSize = isset($_GET['page_size']) ? filter_var($_GET['page_size'], FILTER_VALIDATE_INT) : 50;
if ($pageSize === false) { $pageSize = 50; }
// Bound page size to prevent huge result sets
if ($pageSize < 1) { $pageSize = 1; }
if ($pageSize > 100) { $pageSize = 100; }
$limit = $pageSize;
$offset = ($page - 1) * $pageSize;
// Use mysqli with exceptions and UTF-8
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
try {
$conn = new mysqli($servername, $username, $password, $dbname);
$conn->set_charset('utf8mb4');
} catch (mysqli_sql_exception $e) {
error_log('DB connect failed: ' . $e->getMessage());
http_response_code(500);
exit('Service temporarily unavailable.');
}
// Build WHERE clause and bind parameters safely
$where = 'Date = ?';
$bindTypesCount = 's';
$bindValuesCount = [$date];
if ($hour !== 99) {
$where .= ' AND Hour = ?';
$bindTypesCount .= 'i';
$bindValuesCount[] = $hour;
}
// Count query for total rows (for display/pagination info)
try {
$sqlCount = "SELECT COUNT(*) AS total FROM SummaryLogs WHERE $where";
$stmtCount = $conn->prepare($sqlCount);
$stmtCount->bind_param($bindTypesCount, ...$bindValuesCount);
$stmtCount->execute();
$resultCount = $stmtCount->get_result();
$rowCount = $resultCount->fetch_assoc();
$totalRows = (int)$rowCount['total'];
$stmtCount->close();
} catch (mysqli_sql_exception $e) {
error_log('Count query failed: ' . $e->getMessage());
http_response_code(500);
exit('Service temporarily unavailable.');
}
// Data query with ORDER and LIMIT/OFFSET
try {
$sql = "SELECT id, logData FROM SummaryLogs WHERE $where ORDER BY id DESC LIMIT ? OFFSET ?";
// Bind types: existing where types + limit (i) + offset (i)
$bindTypesData = $bindTypesCount . 'ii';
$bindValuesData = $bindValuesCount;
$bindValuesData[] = $limit;
$bindValuesData[] = $offset;
$stmt = $conn->prepare($sql);
$stmt->bind_param($bindTypesData, ...$bindValuesData);
$stmt->execute();
$result = $stmt->get_result();
} catch (mysqli_sql_exception $e) {
error_log('Data query failed: ' . $e->getMessage());
http_response_code(500);
exit('Service temporarily unavailable.');
}
function generateLogDataTable($logData) {
// Defensive decode with substitution for invalid UTF-8
$data = json_decode($logData, true, 512, JSON_INVALID_UTF8_SUBSTITUTE);
if (!is_array($data)) {
return 'Invalid JSON data';
}
// Remove entries with key 'logterse' and entries with empty values
foreach ($data as $key => $value) {
if ($key === 'logterse' || $value === '' || $value === null) {
unset($data[$key]);
}
}
// Merge adjacent duplicates by value
$mergedData = [];
$previousValue = null;
foreach ($data as $key => $value) {
// Normalize non-scalar values for display
if (is_array($value) || is_object($value)) {
$value = json_encode($value, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
}
$valueStr = (string)$value;
if ($valueStr === $previousValue) {
end($mergedData);
$lastKey = key($mergedData);
$newKey = $lastKey . '/' . $key;
$mergedData[$newKey] = $valueStr;
unset($mergedData[$lastKey]);
} else {
$mergedData[$key] = $valueStr;
}
$previousValue = $valueStr;
}
// Optional truncation to keep rendering safe
$maxValueLen = 500;
foreach ($mergedData as $k => $v) {
if (mb_strlen($v, 'UTF-8') > $maxValueLen) {
$mergedData[$k] = mb_substr($v, 0, $maxValueLen, 'UTF-8') . '…';
}
}
$keys = array_keys($mergedData);
$values = array_values($mergedData);
$output = '
';
// Divide keys and values into sets of 6
$chunks = array_chunk($keys, 6);
foreach ($chunks as $chunkIndex => $chunk) {
$output .= '';
foreach ($chunk as $key) {
$output .= '' . e($key) . ' | ';
}
$output .= '
';
foreach ($chunk as $i => $key) {
$val = $values[$chunkIndex * 6 + $i];
$output .= '' . e($val) . ' | ';
}
$output .= '
';
}
$output .= '
';
return $output;
}
?>
Summary Logs
Summary Logs for Date: = e($date) ?>
= $hour === 99 ? ' (All Hours)' : ' at Hour: ' . e($hour) ?>
0 ? ($offset + 1) : 0;
$endRow = min($offset + $limit, $totalRows);
?>
Found = e($totalRows) ?> records. Showing = e($startRow) ?>–= e($endRow) ?>.
Id |
Details |
Log Data |
num_rows > 0): ?>
fetch_assoc()): ?>
= e($id) ?> |
View details |
= generateLogDataTable($row['logData']) ?> |
No records found for the specified date and hour. |
$date,
'hour' => $hour,
'page_size' => $pageSize
];
$prevPage = $page > 1 ? $page - 1 : null;
$nextPage = ($offset + $limit) < $totalRows ? $page + 1 : null;
?>
close(); }
if (isset($conn) && $conn instanceof mysqli) { $conn->close(); }
?>