Files
Web-Infra-Reports-IT/crossover/GlobalCrossover.php
sva-e025532 10c228f255 Remove test.php and enhance null safety and sorting across components
- Deleted `test.php` as it was no longer in use.
- Enhanced null safety checks in `Inventory.php`, `StdOut-detail.php`, `Backups.php`, and `SwitchsSAN.php` to prevent potential warnings.
- Refactored `SwitchsSAN.php` to improve sorting logic for ports based on errors, vFabric, and Port ID.
- Added seasonal snow effect script in `all.php` with toggle functionality for user engagement.
- Updated navigation bar (`navbar.html`) to include a new VIO page link.
- Introduced a new `VIO.php` page to display VIO monitoring details with table export and sorting features.
2026-03-31 11:33:57 +02:00

451 lines
20 KiB
PHP

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Page Title -->
<title>Web Infra Reports IT</title>
<link rel="shortcut icon" type="image/png" href="/include/favicon-32x32.png">
<!-- JQuery -->
<script src="/js/jquery-3.6.1.min.js"></script>
<!-- Bootstrap -->
<link rel="stylesheet" href="/css/bootstrap.min.css">
<link rel="stylesheet" href="/css/bootstrap-icons/bootstrap-icons.css">
<link rel="stylesheet" href="/css/preloader.css">
<script src="/js/bootstrap.bundle.min.js"></script>
<!-- Bootstrap-tables -->
<link rel="stylesheet" href="/css/bootstrap-table.min.css">
<script src="/js/bootstrap-table.min.js"></script>
<script src="/js/bootstrap-table-fr-FR.min.js"></script>
<script src="/js/tableExport.min.js"></script>
<script src="/js/bootstrap-table-export.min.js"></script>
<script src="/js/libs/js-xlsx/xlsx.core.min.js"></script>
<!-- test -->
</head>
<body class="bg-light text-dark">
<?php include $_SERVER['DOCUMENT_ROOT'] . "/include/all.php"; ?> <!-- Include All -->
<div class="container-fluid">
<div class="row flex-nowrap">
<!-- Left NAVBAR -->
<div class="col-auto col-md-2 col-xl-2 px-sm-2 px-0 bg-dark vh-100 position-sticky top-0" style="-ms-flex: 0 0 230px;flex: 0 0 230px;">
<?php include $_SERVER['DOCUMENT_ROOT'] . "/navbar.html"; ?> <!-- Left Navbar -->
</div>
<!-- Display -->
<div class="col py-3">
<!-- Page Title -->
<h1><span class="badge text-bg-secondary font-weight-bold" style="width:100%;"><?php echo $ti_3; ?></span></h1>
<!-- Main content -->
<div class="row" style="zoom: 80%">
<table class='table table-bordered table-hover table-sm' id='t1' data-toggle="table" data-search="true"
data-show-columns="true" data-export-types="['xlsx','csv','json']"
data-loading-template="loadingTemplate"
data-show-export="true" data-sortable="true">
<thead>
<tr>
<th data-field="Name" data-sortable="true"><?php echo $w_name; ?></th>
<th data-field="OS" data-sortable="true"><?php echo $w_os; ?></th>
<th data-field="Criticity" data-sortable="true"><?php echo $w_crit; ?></th>
<th data-field="AD" data-sortable="true"><?php echo $w_ad; ?></th>
<th data-field="ADlu" data-sortable="true" data-visible="false"><?php echo $w_adlu; ?></th>
<th data-field="GLPI" data-sortable="true">GLPI</th>
<th data-field="GLPIlu" data-sortable="true" data-visible="false" data-footer-formatter="FI"><?php echo $w_filu; ?></th>
<th data-field="SCCM" data-sortable="true">SCCM<br></th>
<th data-field="SCCMlu" data-sortable="true" data-visible="false"><?php echo $w_sccmlu; ?></th>
<th data-field="NESSUS" data-sortable="true">NESSUS</th>
<th data-field="Backup" data-sortable="true"><?php echo $w_backup; ?></th>
<th data-field="NBUlu" data-sortable="true" data-visible="false"><?php echo $w_backuplu; ?></th>
<th data-field="SCOM" data-sortable="true">SCOM</th>
<th data-field="Zabbix" data-sortable="true">Zabbix</th>
<th data-field="S1" data-sortable="true">SentinelOne</th>
<th data-field="S1lu" data-sortable="true" data-visible="false"><?php echo $w_s1lu; ?></th>
</tr>
</thead>
<tbody>
<!-- Display DATAs -->
<?php
$conn = DB_ENTRY02();
// Base query
$sql = "SELECT * FROM GlobalCrossover";
$whereClauses = ["server NOT LIKE 'WS%'"];
$params = [];
$types = "";
// Handle filters securely using prepared statements
if (isset($_GET['filter'])) {
$filter = $_GET['filter'];
$filterTitle = "$w_filter : " . htmlspecialchars($filter) . " $w_nonCompliant";
switch ($filter) {
case "AD":
$whereClauses[] = "AD IS NULL OR (ADlu IS NOT NULL AND DATEDIFF(now(), ADlu) > 45)";
break;
case "OS":
$whereClauses[] = "OS LIKE '%2003%' OR OS LIKE '%2008%'";
break;
case "GLPI":
$whereClauses[] = "GLPI IS NULL OR GLPIlu IS NULL OR DATEDIFF(now(), GLPIlu) > 7";
break;
case "SCCM":
$whereClauses[] = "SCCM IS NULL OR (SCCMlu IS NOT NULL AND DATEDIFF(now(), SCCMlu) > 7)";
break;
case "NESSUS":
$whereClauses[] = "EPO IS NULL";
break;
case "NBU":
$whereClauses[] = "NBU IS NULL OR (NBUlu IS NOT NULL AND DATEDIFF(now(), NBUlu) > 30)";
break;
case "SCOM":
$whereClauses[] = "SCOM IS NULL";
break;
case "zabbix":
$whereClauses[] = "zabbix IS NULL";
break;
case "S1":
$whereClauses[] = "S1 IS NULL OR (S1lu IS NOT NULL AND DATEDIFF(now(), S1lu) > 7)";
break;
default:
$filterTitle = null; // No valid filter
break;
}
if ($filterTitle) {
echo "<h2><div style=\"text-align: center;\"><span class='badge text-bg-danger font-weight-bold'>$filterTitle</span></div></h2>";
}
}
// Combine all WHERE clauses
if (!empty($whereClauses)) {
$sql .= " WHERE " . implode(' AND ', $whereClauses);
}
$sql .= " ORDER BY server";
// Prepare and execute the query
$stmt = $conn->prepare($sql);
// Note: If you had parameters, you would bind them here, e.g., $stmt->bind_param($types, ...$params);
$stmt->execute();
$result = $stmt->get_result();
// --- PART 2: HELPER FUNCTIONS FOR RENDERING ---
/**
* Renders a standard status cell based on a value and its last update date.
* @param string|null $status The status value (e.g., 'Y', 'N').
* @param string|null $lastUpdate The date of the last update.
* @param int $daysThreshold The number of days to be considered "out of date".
* @param string $okText Text to display for OK status (e.g., "OK", "OK (NBU)").
* @return string The generated HTML for two <td> cells.
*/
function renderStatusCellWithDate(?string $status, ?string $lastUpdate, int $daysThreshold, string $okText = 'OK'): string {
// Sanitize output to prevent XSS
$status = htmlspecialchars($status ?? '', ENT_QUOTES, 'UTF-8');
$lastUpdate = htmlspecialchars($lastUpdate ?? '', ENT_QUOTES, 'UTF-8');
$okText = htmlspecialchars($okText, ENT_QUOTES, 'UTF-8');
if ($status === 'Y') {
if (empty($lastUpdate)) {
// Status is OK, but date is missing
return "<td class='text-white' style='background: linear-gradient(90deg, rgba(25,135,84,1) 50%, rgba(255,193,7,1) 100%);'>$okText</td>"
. "<td class='bg-warning text-black'>Missing</td>";
}
try {
$diff = date_diff(date_create($lastUpdate), date_create());
$days = (int) $diff->format("%R%a");
if ($days > $daysThreshold) {
// Out of date
return "<td class='text-white' style='background: linear-gradient(90deg, rgba(25,135,84,1) 50%, rgba(220,53,69,1) 100%);'>$okText</td>"
. "<td class='bg-danger text-white'>$lastUpdate ($days days)</td>";
} else {
// Compliant
return "<td class='bg-success text-white'>$okText</td>"
. "<td class='bg-success text-white'>$lastUpdate</td>";
}
} catch (Exception) {
// Handle invalid date format gracefully
return "<td class='bg-danger text-white'>Invalid Date</td><td class='bg-danger text-white'>$lastUpdate</td>";
}
}
if ($status !== '') {
// Not applicable, non-supported, etc.
return "<td class='bg-secondary'><small>$status</small></td><td class='bg-secondary text-secondary'>&nbsp;</td>";
}
// Missing
return "<td class='bg-warning text-black'>Missing</td><td class='bg-warning text-warning'>&nbsp;</td>";
}
// --- PART 3: CLEAN DATA DISPLAY LOOP ---
// Initialize counters
$counters = [
'total' => 0, 'ok' => 0, 'nOS' => 0, 'nAD' => 0, 'nSCCM' => 0, 'nGLPI' => 0,
'nFI' => 0, 'nNESSUS' => 0, 'nNBU' => 0, 'nDPM' => 0, 'nS1' => 0
];
while ($row = $result->fetch_assoc()) {
$counters['total']++;
// Sanitize server name for URL and display
$serverName = htmlspecialchars($row['Server'], ENT_QUOTES, 'UTF-8');
$serverUrl = urlencode($row['Server']);
// Determine overall row status
$isCompliant = isset($row['AD'], $row['GLPI'], $row['SCCM'], $row['EPO']) && (isset($row['NBU']) || isset($row['DPM'])) && isset($row['SCOM']);
if ($isCompliant) {
$counters['ok']++;
$serverCell = "<td class='bg-success text-white'><b><a href='/crossover/Detail.php?server=$serverUrl' target='_blank' class='link-light'>$serverName</a></b></td>";
} else {
$serverCell = "<td><b><a href='/crossover/Detail.php?server=$serverUrl' target='_blank'>$serverName</a></b></td>";
}
// OS Cell
$osCell = "<td class='bg-warning'>&nbsp;</td>";
if (!empty($row['OS'])) {
$os = htmlspecialchars($row['OS']);
if (preg_match('(XP|2003|2000|2008|Windows 7|2012)', $row['OS'])) {
$osCell = "<td class='bg-warning text-black'>$os</td>";
} else {
$counters['nOS']++;
$osCell = "<td>$os</td>";
}
}
echo "<tr>";
echo $serverCell;
echo $osCell;
echo "<td>" . htmlspecialchars($row['crit'] ?? '') . "</td>";
// Use helper function for status columns
echo renderStatusCellWithDate($row['AD'], $row['ADlu'], 45);
echo renderStatusCellWithDate($row['GLPI'], $row['GLPIlu'], 7);
echo renderStatusCellWithDate($row['SCCM'], $row['SCCMlu'], 7);
// NESSUS (EPO) Cell - Custom logic
if (str_contains($row['EPO'] ?? '', '.')) {
echo "<td class='bg-success text-white'>" . htmlspecialchars($row['EPO']) . "</td>";
} elseif (isset($row['EPO']) && !in_array($row['EPO'], ['Y', 'N'])) {
echo "<td class='bg-secondary'><small>" . htmlspecialchars($row['EPO']) . "</small></td>";
} else {
echo "<td class='bg-warning text-black'>Missing</td>";
$counters['nNESSUS']++;
}
// BACKUP Cell - Custom logic for NBU/DPM
if ($row['NBU'] === 'Y') {
echo renderStatusCellWithDate($row['NBU'], $row['NBUlu'], 30, 'OK (NBU)');
} elseif ($row['DPM'] === 'Y') {
echo renderStatusCellWithDate($row['DPM'], $row['DPMlu'], 30, 'OK (DPM)');
} else {
// Handle non-Y cases for NBU or DPM, or missing
$backupStatus = $row['NBU'] ?? $row['DPM'] ?? null;
echo renderStatusCellWithDate($backupStatus, null, 30);
}
// SCOM Cell - Simple logic
if ($row['SCOM'] === 'Y') {
echo "<td class='bg-success text-white'>OK</td>";
} elseif (isset($row['SCOM'])) {
echo "<td class='bg-secondary'><small>" . htmlspecialchars($row['SCOM']) . "</small></td>";
} else {
echo "<td class='bg-warning text-black'>Missing</td>";
}
// Zabbix Cell - Simple logic
$zabbixStatus = $row['zabbix'] ?? '';
if ($zabbixStatus === 'Y' || str_contains($zabbixStatus, '.')) {
echo "<td class='bg-success text-white'>" . htmlspecialchars(str_replace('Y', 'OK', $zabbixStatus)) . "</td>";
} elseif (isset($row['zabbix'])) {
echo "<td class='bg-secondary'><small>" . htmlspecialchars($zabbixStatus) . "</small></td>";
} else {
echo "<td class='bg-warning text-black'>Missing</td>";
}
// S1 Cell
$s1Status = $row['S1'] ?? '';
$s1Text = ($s1Status === 'Y' || str_contains($s1Status, '.')) ? str_replace('Y', 'OK', $s1Status) : 'OK';
echo renderStatusCellWithDate($s1Status, $row['S1lu'], 7, $s1Text);
echo "</tr>";
}
// You can now use the $counters array to pass data to your JS for the KPIs
// For example:
echo "<script>let kpiData = " . json_encode($counters) . ";</script>";
$stmt->close();
$conn->close();
?>
</tbody>
</table>
</div>
<button id="button" type="button" class="btn btn-primary btn-sm invisible"><i
class="bi bi-arrow-clockwise"></i><b> Generate KPI</b></button>
<div class="row flex-nowrap text-center" style="zoom: 80%">
<div class="col"> <!-- CARTE Devices -->
<div class="card border-secondary mb-3">
<div class="card-header text-dark"><b><?php echo $w_allDevice; ?></b></div>
<a href="/crossover/GlobalCrossover.php">
<div class="card-body">
<h2><span class="badge text-bg-primary font-weight-bold" id="KPIDEVICE"></span></h2>
</div>
</a>
</div>
</div>
<div class="col"> <!-- CARTE OS -->
<div class="card border-secondary mb-3">
<div class="card-header text-dark"><b><?php echo $w_supportedOS; ?></b></div>
<a href="/crossover/GlobalCrossover.php?filter=OS">
<div class="card-body">
<h2><span class="badge text-bg-secondary font-weight-bold" id="KPIOS"></span></h2>
</div>
</a>
</div>
</div>
<div class="col"> <!-- CARTE AD -->
<div class="card border-secondary mb-3">
<div class="card-header text-dark"><b>AD</b></div>
<a href="/crossover/GlobalCrossover.php?filter=AD">
<div class="card-body">
<h2><span class="badge text-bg-secondary font-weight-bold" id="KPIAD"></span></h2>
</div>
</a>
</div>
</div>
<div class="col"> <!-- CARTE GLPI/FI -->
<div class="card border-secondary mb-3">
<div class="card-header text-dark"><b>GLPI/FI</b></div>
<a href="/crossover/GlobalCrossover.php?filter=GLPI">
<div class="card-body">
<h2><span class="badge text-bg-secondary font-weight-bold" id="KPIGLPI"></span></h2>
</div>
</a>
</div>
</div>
<div class="col"> <!-- CARTE SCCM -->
<div class="card border-secondary mb-3">
<div class="card-header text-dark"><b>SCCM</b></div>
<a href="/crossover/GlobalCrossover.php?filter=SCCM">
<div class="card-body">
<h2><span class="badge text-bg-secondary font-weight-bold" id="KPISCCM"></span></h2>
</div>
</a>
</div>
</div>
<div class="col"> <!-- CARTE EPO -->
<div class="card border-secondary mb-3">
<div class="card-header text-dark"><b>NESSUS</b></div>
<a href="/crossover/GlobalCrossover.php?filter=NESSUS">
<div class="card-body">
<h2><span class="badge text-bg-secondary font-weight-bold" id="KPIEPO"></span></h2>
</div>
</a>
</div>
</div>
<div class="col"> <!-- CARTE Backup (NBU + DPM) -->
<div class="card border-secondary mb-3">
<div class="card-header text-dark"><b><?php echo $w_backup; ?></b></div>
<a href="/crossover/GlobalCrossover.php?filter=NBU">
<div class="card-body">
<h2><span class="badge text-bg-secondary font-weight-bold" id="KPINBU"></span></h2>
</div>
</a>
</div>
</div>
<div class="col"> <!-- CARTE SCOM -->
<div class="card border-secondary mb-3">
<div class="card-header text-dark"><b>SCOM</b></div>
<a href="/crossover/GlobalCrossover.php?filter=SCOM">
<div class="card-body">
<h2><span class="badge text-bg-secondary font-weight-bold" id="KPISCOM"></span></h2>
</div>
</a>
</div>
</div>
<div class="col"> <!-- CARTE Zabbix -->
<div class="card border-secondary mb-3">
<div class="card-header text-dark"><b>Zabbix</b></div>
<a href="/crossover/GlobalCrossover.php?filter=zabbix">
<div class="card-body">
<h2><span class="badge text-bg-secondary font-weight-bold" id="KPIzabbix"></span></h2>
</div>
</a>
</div>
</div>
<div class="col"> <!-- CARTE SentinelOne -->
<div class="card border-secondary mb-3">
<div class="card-header text-dark"><b>SentinelOne</b></div>
<a href="/crossover/GlobalCrossover.php?filter=S1">
<div class="card-body">
<h2><span class="badge text-bg-secondary font-weight-bold" id="KPIS1"></span></h2>
</div>
</a>
</div>
</div>
</div>
<!-- End of main content -->
</div>
</div>
</div>
<script src="/js/switch.js"></script>
</body>
<script src="/crossover/Crossover-KPI.js"></script>
<script>
let $table = $('#t1');
const $button = $('#button');
$table.on('search.bs.table', function () {
let $button = $('#button');
$button.click();
})
$(window).on('load', function () {
$('.preloader').addClass('preloader-deactivate');
});
document.addEventListener("DOMContentLoaded", function () { setTimeout(function () { $('#button').click(); }, 1000); });
</script>
<SCRIPT>
$(function() {
// Exécution initiale pour définir la hauteur
adjustTableHeight();
// Événement de redimensionnement
$(window).on('resize', function() {
adjustTableHeight();
});
function adjustTableHeight() {
const table = $('#t1');
const windowHeight = $(window).height();
const tableTop = table.offset().top;
const footerHeight = -50; // Hauteur estimée pour d'éventuels éléments en bas
let availableHeight = windowHeight - tableTop - footerHeight;
// Définir une hauteur minimale
availableHeight = Math.max(availableHeight, 400);
table.bootstrapTable('refreshOptions', {
height: availableHeight
});
}
});
</script>
</HTML>