even, "fcs1" -> odd, ... function fcs_parity($fcs) { if (preg_match('/(\d+)\s*$/', strtolower(trim((string)$fcs)), $m)) { return (intval($m[1]) % 2 === 0) ? 'even' : 'odd'; } return 'unknown'; } $rawRows = Invoke_Infra("SELECT * FROM x_cmdb_VIO"); if (!$rawRows) $rawRows = []; // Grouping $groupedData = []; foreach ($rawRows as $row) { $key = $row['clintname']; if (empty($key)) $key = "[No Client Name]"; if (!isset($groupedData[$key])) $groupedData[$key] = []; $groupedData[$key][] = $row; } // Flattening for Display (1 Row per Client) $displayRows = []; foreach ($groupedData as $clientKey => $rows) { // 1. Sort by date desc usort($rows, function($a, $b) { return strcmp($b['ts'], $a['ts']); }); // 2. Keep max 2 if (count($rows) > 2) { $rows = array_slice($rows, 0, 2); } $names = []; $inerrs = []; $vfcs = []; $vios = []; $clintids = []; $fcnames = []; $tss = []; $vioerrs = []; $parities = []; $hasError = false; $maxVioErr = 0; foreach ($rows as $r) { if ($r['inerr'] != 0 && $r['inerr'] != '0') $hasError = true; // Track VIOErr $errVal = (int)($r['VIOErr'] ?? 0); if ($errVal > $maxVioErr) $maxVioErr = $errVal; // Format VIOErr for display (Red badge if > 0) $vioerrs[] = ($errVal > 0) ? "$errVal" : $errVal; $names[] = $r['name'] ?? '-'; $inerrs[] = $r['inerr'] ?? '-'; $vfcs[] = $r['vfcclientname'] ?? '-'; $vios[] = $r['vio'] ?? '-'; $clintids[] = $r['clintid'] ?? '-'; $fcnames[] = $r['fcname'] ?? '-'; $tss[] = $r['ts'] ?? '-'; // Redundancy check is on the physical fc port (fcname). $parities[] = fcs_parity($r['fcname'] ?? ''); } // Parity issue = exactly 2 known fcs parities and they are identical // (both even or both odd -> no fabric redundancy). $hasParityIssue = false; $knownParities = array_values(array_filter($parities, fn($p) => $p !== 'unknown')); if (count($knownParities) === 2 && $knownParities[0] === $knownParities[1]) { $hasParityIssue = true; } $displayRows[] = [ 'clintname' => $clientKey, 'hasError' => $hasError, 'hasParityIssue' => $hasParityIssue, 'maxVioErr' => $maxVioErr, 'name' => implode('
', $names), 'inerr' => implode('
', $inerrs), 'vfc' => implode('
', $vfcs), 'vio' => implode('
', $vios), 'clintid' => implode('
', $clintids), 'fcname' => implode('
', $fcnames), 'ts' => implode('
', $tss), 'vioerr' => implode('
', $vioerrs), ]; } // 4. Final Sort: // 1. Top tier: InErr (table-warning) OR parity issue (table-danger) // 2. VIOErr > 0 // 3. Alpha usort($displayRows, function($a, $b) { // Priority 1: warning OR parity issue -> floated to the top, same standing $aTop = $a['hasError'] || $a['hasParityIssue']; $bTop = $b['hasError'] || $b['hasParityIssue']; if ($aTop && !$bTop) return -1; if (!$aTop && $bTop) return 1; // Priority 2: VIOErr count if ($a['maxVioErr'] > 0 && $b['maxVioErr'] == 0) return -1; if ($a['maxVioErr'] == 0 && $b['maxVioErr'] > 0) return 1; if ($a['maxVioErr'] != $b['maxVioErr']) return $b['maxVioErr'] - $a['maxVioErr']; // Priority 3: Alphabetical return strcasecmp($a['clintname'], $b['clintname']); }); ?>

Clint Name VIOErr InErr VFC Client Name VIO ClintID FC Name

même parité