query('SELECT id, iso2, name FROM countries ORDER BY name')->fetchAll(PDO::FETCH_ASSOC); $operators = $db->query('SELECT id, mcc, mnc, brand FROM operators ORDER BY brand')->fetchAll(PDO::FETCH_ASSOC); $siteWhere = ' WHERE 1=1 '; $siteParams = []; if ($countryFilter !== '') { $siteWhere .= ' AND c.iso2 = ?'; $siteParams[] = $countryFilter; } if ($operatorFilter !== '') { $siteWhere .= ' AND o.id = ?'; $siteParams[] = (int)$operatorFilter; } $siteSql = ' SELECT s.id AS site_id, s.lat, s.lon, s.location_desc, s.address_desc, o.brand AS operator_brand, o.mcc AS operator_mcc, o.mnc AS operator_mnc, c.name AS country_name, COUNT(cl.id) AS cell_count FROM sites s JOIN operators o ON o.id = s.operator_id JOIN countries c ON c.id = s.country_id LEFT JOIN cells cl ON cl.site_id = s.id ' . $siteWhere . ' GROUP BY s.id, s.lat, s.lon, s.location_desc, s.address_desc, o.brand, o.mcc, o.mnc, c.name ORDER BY s.id'; $siteStmt = $db->prepare($siteSql); $siteStmt->execute($siteParams); $siteRows = $siteStmt->fetchAll(PDO::FETCH_ASSOC); $cellWhere = ' WHERE 1=1 '; $cellParams = []; if ($countryFilter !== '') { $cellWhere .= ' AND c.iso2 = ?'; $cellParams[] = $countryFilter; } if ($operatorFilter !== '') { $cellWhere .= ' AND o.id = ?'; $cellParams[] = (int)$operatorFilter; } $cellSql = ' SELECT cl.id AS cell_pk, cl.site_id, cl.tech, cl.mcc AS cell_mcc, cl.mnc AS cell_mnc, cl.cell_id, cl.area_code, cl.sub_id, cl.sub_id2, cl.band, cl.frequency, cl.azimuth, cl.bandwidth, cl.arfcn, o.brand AS operator_brand, o.mcc AS operator_mcc, o.mnc AS operator_mnc, c.name AS country_name FROM cells cl JOIN sites s ON s.id = cl.site_id JOIN operators o ON o.id = s.operator_id JOIN countries c ON c.id = s.country_id ' . $cellWhere . ' ORDER BY cl.site_id, cl.tech, cl.sub_id2, cl.cell_id'; $cellStmt = $db->prepare($cellSql); $cellStmt->execute($cellParams); $cellRows = $cellStmt->fetchAll(PDO::FETCH_ASSOC); $issues = []; foreach ($siteRows as $site) { $siteId = (int)$site['site_id']; $lat = (float)$site['lat']; $lon = (float)$site['lon']; $cellCount = (int)$site['cell_count']; $location = $site['address_desc'] ?: $site['location_desc']; if ($cellCount === 0) { addIssue($issues, 'site_without_cells', 'warning', [ 'site_id' => $siteId, 'cell_pk' => null, 'operator_brand' => $site['operator_brand'], 'country_name' => $site['country_name'], 'tech' => null, 'cell_id' => null, 'sub_id2' => null, 'band' => null, 'frequency' => null, 'azimuth' => null, 'message' => 'Le site ne contient aucune cellule.', 'location' => $location, ]); } if ($lat === 0.0 || $lon === 0.0) { addIssue($issues, 'invalid_coordinates', 'error', [ 'site_id' => $siteId, 'cell_pk' => null, 'operator_brand' => $site['operator_brand'], 'country_name' => $site['country_name'], 'tech' => null, 'cell_id' => null, 'sub_id2' => null, 'band' => null, 'frequency' => null, 'azimuth' => null, 'message' => 'Latitude ou longitude egale a 0.', 'location' => $location, ]); } if ($lat < -90 || $lat > 90 || $lon < -180 || $lon > 180) { addIssue($issues, 'invalid_coordinates', 'error', [ 'site_id' => $siteId, 'cell_pk' => null, 'operator_brand' => $site['operator_brand'], 'country_name' => $site['country_name'], 'tech' => null, 'cell_id' => null, 'sub_id2' => null, 'band' => null, 'frequency' => null, 'azimuth' => null, 'message' => 'Coordonnees hors des plages GPS valides.', 'location' => $location, ]); } } foreach ($cellRows as $cell) { $base = [ 'site_id' => (int)$cell['site_id'], 'cell_pk' => (int)$cell['cell_pk'], 'operator_brand' => $cell['operator_brand'], 'country_name' => $cell['country_name'], 'tech' => $cell['tech'], 'cell_id' => $cell['cell_id'], 'sub_id2' => $cell['sub_id2'], 'band' => $cell['band'], 'frequency' => $cell['frequency'], 'azimuth' => $cell['azimuth'], 'location' => null, ]; if ($cell['azimuth'] !== null && $cell['azimuth'] !== '') { $azimuth = (int)$cell['azimuth']; if ($azimuth < 0 || $azimuth > 359) { addIssue($issues, 'invalid_azimuth', 'error', $base + [ 'message' => 'Azimut hors de la plage 0-359 degres.', ]); } } if ( normalizeCode($cell['cell_mcc']) !== normalizeCode($cell['operator_mcc']) || normalizeCode($cell['cell_mnc']) !== normalizeCode($cell['operator_mnc']) ) { addIssue($issues, 'mcc_mnc_mismatch', 'error', $base + [ 'message' => 'Le MCC/MNC de la cellule ne correspond pas a son operateur.', ]); } if ( technologyNeedsNode((string)$cell['tech']) && ($cell['sub_id2'] === null || trim((string)$cell['sub_id2']) === '') ) { addIssue($issues, 'missing_enb', 'warning', $base + [ 'message' => 'eNB/RNC absent pour cette technologie.', ]); } if ($cell['band'] === null || trim((string)$cell['band']) === '') { addIssue($issues, 'missing_band', 'warning', $base + [ 'message' => 'Bande radio absente.', ]); } if ($cell['frequency'] === null || trim((string)$cell['frequency']) === '') { addIssue($issues, 'missing_frequency', 'warning', $base + [ 'message' => 'Frequence absente.', ]); } if ($cell['bandwidth'] === null || trim((string)$cell['bandwidth']) === '') { addIssue($issues, 'missing_bandwidth', 'info', $base + [ 'message' => 'Largeur de bande absente.', ]); } } $issueTypes = [ 'site_without_cells' => 'Site sans cellule', 'invalid_coordinates' => 'Coordonnees invalides', 'invalid_azimuth' => 'Azimut invalide', 'mcc_mnc_mismatch' => 'MCC/MNC incoherent', 'missing_enb' => 'eNB/RNC absent', 'missing_band' => 'Bande absente', 'missing_frequency' => 'Frequence absente', 'missing_bandwidth' => 'Largeur de bande absente', ]; if ($typeFilter !== '') { $issues = array_values(array_filter($issues, static fn(array $issue): bool => $issue['type'] === $typeFilter)); } $errors = count(array_filter($issues, static fn(array $issue): bool => $issue['severity'] === 'error')); $warnings = count(array_filter($issues, static fn(array $issue): bool => $issue['severity'] === 'warning')); $infos = count(array_filter($issues, static fn(array $issue): bool => $issue['severity'] === 'info')); $countSiteSql = 'SELECT COUNT(*) FROM sites s JOIN operators o ON o.id = s.operator_id JOIN countries c ON c.id = s.country_id' . $siteWhere; $countCellSql = 'SELECT COUNT(*) FROM cells cl JOIN sites s ON s.id = cl.site_id JOIN operators o ON o.id = s.operator_id JOIN countries c ON c.id = s.country_id' . $cellWhere; $countSiteStmt = $db->prepare($countSiteSql); $countSiteStmt->execute($siteParams); $siteCount = (int)$countSiteStmt->fetchColumn(); $countCellStmt = $db->prepare($countCellSql); $countCellStmt->execute($cellParams); $cellCount = (int)$countCellStmt->fetchColumn(); ?>
Cette page est en lecture seule : elle signale les anomalies sans modifier la base.
Base filtree controlee : = $siteCount ?> site(s), = $cellCount ?> cellule(s).
| Gravite | Type | Operateur | Site | Technologie | eNB/RNC | Cell ID | Bande | Frequence | Azimut | Message | Actions |
|---|---|---|---|---|---|---|---|---|---|---|---|
| = h(ucfirst($issue['severity'])) ?> | = h($issueTypes[$issue['type']] ?? $issue['type']) ?> | = h($issue['operator_brand'] ?? '') ?> | = (int)$issue['site_id'] ?> | = h($issue['tech'] ?? '') ?> | = h($issue['sub_id2'] ?? '') ?> | = h($issue['cell_id'] ?? '') ?> | = h($issue['band'] ?? '') ?> | = h($issue['frequency'] ?? '') ?> | = $issue['azimuth'] === null || $issue['azimuth'] === '' ? '' : h($issue['azimuth']) . '°' ?> | = h($issue['message']) ?> |