Files
admin-netmonster-db/admin/operator_sites.php
T
2026-10-21 22:00:44 +02:00

185 lines
6.7 KiB
PHP

<?php
/**
* admin/operator_sites.php
*
* Vue en lecture seule des antennes par operateur. Aucune ecriture en
* base : uniquement des filtres GET et des requetes preparees en
* lecture. Protegee par require_admin_auth() comme toutes les pages du
* dossier /admin.
*
* Hypothese de schema :
* operators(id, name, mcc, mnc, country_id)
* countries(id, name, iso_code)
* sites(id, name, lat, lon, operator_id, country_id)
* cells(id, site_id, technology, band, frequency, azimuth, enb, cell_id)
*/
declare(strict_types=1);
require_once __DIR__ . '/admin_auth.php';
require_once __DIR__ . '/../lib/db.php';
require_admin_auth();
$db = pdo();
$countries = $db->query('SELECT id, name FROM countries ORDER BY name')->fetchAll(PDO::FETCH_ASSOC);
$countryId = filter_input(INPUT_GET, 'country_id', FILTER_VALIDATE_INT) ?: null;
$operatorsSql = 'SELECT id, name, mcc, mnc, country_id FROM operators';
$operatorsParams = [];
if ($countryId) {
$operatorsSql .= ' WHERE country_id = ?';
$operatorsParams[] = $countryId;
}
$operatorsSql .= ' ORDER BY name';
$stmt = $db->prepare($operatorsSql);
$stmt->execute($operatorsParams);
$operators = $stmt->fetchAll(PDO::FETCH_ASSOC);
$operatorId = filter_input(INPUT_GET, 'operator_id', FILTER_VALIDATE_INT) ?: null;
$page = max(1, filter_input(INPUT_GET, 'page', FILTER_VALIDATE_INT) ?: 1);
$perPage = 50;
$offset = ($page - 1) * $perPage;
$sites = [];
$totalSites = 0;
$stats = null;
if ($operatorId) {
$countStmt = $db->prepare('SELECT COUNT(*) FROM sites WHERE operator_id = ?');
$countStmt->execute([$operatorId]);
$totalSites = (int)$countStmt->fetchColumn();
$stmt = $db->prepare(
'SELECT s.id, s.name, s.lat, s.lon,
(SELECT COUNT(*) FROM cells c WHERE c.site_id = s.id) AS cell_count
FROM sites s
WHERE s.operator_id = ?
ORDER BY s.name
LIMIT :limit OFFSET :offset'
);
$stmt->bindValue(1, $operatorId, PDO::PARAM_INT);
$stmt->bindValue(':limit', $perPage, PDO::PARAM_INT);
$stmt->bindValue(':offset', $offset, PDO::PARAM_INT);
$stmt->execute();
$sites = $stmt->fetchAll(PDO::FETCH_ASSOC);
$statStmt = $db->prepare(
"SELECT c.technology, COUNT(*) AS total
FROM cells c
INNER JOIN sites s ON s.id = c.site_id
WHERE s.operator_id = ?
GROUP BY c.technology
ORDER BY total DESC"
);
$statStmt->execute([$operatorId]);
$stats = $statStmt->fetchAll(PDO::FETCH_ASSOC);
}
$totalPages = max(1, (int)ceil($totalSites / $perPage));
$user = current_admin_username();
?>
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<title>Antennes par opé··rateur — NetMonster Admin</title>
<link rel="stylesheet" href="assets/theme.css">
</head>
<body>
<?php render_admin_nav('operator_sites.php', $user); ?>
<main class="container">
<h1>Antennes par opé··rateur</h1>
<p>Vue de consultation, sans action d'ecriture. Filtrez par pays puis par operateur pour lister les sites et leur nombre de cellules.</p>
<section class="card">
<form method="get" class="filters">
<label>Pays
<select name="country_id" onchange="this.form.submit()">
<option value="">Tous</option>
<?php foreach ($countries as $c): ?>
<option value="<?= (int)$c['id'] ?>" <?= $countryId === (int)$c['id'] ? 'selected' : '' ?>>
<?= htmlspecialchars((string)$c['name'], ENT_QUOTES, 'UTF-8') ?>
</option>
<?php endforeach; ?>
</select>
</label>
<label>Opé··rateur
<select name="operator_id" onchange="this.form.submit()">
<option value="">— Choisir —</option>
<?php foreach ($operators as $op): ?>
<option value="<?= (int)$op['id'] ?>" <?= $operatorId === (int)$op['id'] ? 'selected' : '' ?>>
<?= htmlspecialchars((string)$op['name'], ENT_QUOTES, 'UTF-8') ?>
(MCC <?= htmlspecialchars((string)$op['mcc'], ENT_QUOTES, 'UTF-8') ?> / MNC <?= htmlspecialchars((string)$op['mnc'], ENT_QUOTES, 'UTF-8') ?>)
</option>
<?php endforeach; ?>
</select>
</label>
</form>
</section>
<?php if ($operatorId): ?>
<section class="card">
<h2>Ré··partition par technologie</h2>
<?php if (empty($stats)): ?>
<p>Aucune cellule pour cet opé··rateur.</p>
<?php else: ?>
<table class="table">
<thead><tr><th>Technologie</th><th>Nombre de cellules</th></tr></thead>
<tbody>
<?php foreach ($stats as $s): ?>
<tr>
<td><?= htmlspecialchars((string)$s['technology'], ENT_QUOTES, 'UTF-8') ?></td>
<td><?= (int)$s['total'] ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php endif; ?>
</section>
<section class="card">
<h2>Sites (<?= $totalSites ?>)</h2>
<table class="table">
<thead>
<tr>
<th>Nom</th>
<th>Latitude</th>
<th>Longitude</th>
<th>Cellules</th>
<th>Dé··tail</th>
</tr>
</thead>
<tbody>
<?php foreach ($sites as $site): ?>
<tr>
<td><?= htmlspecialchars((string)$site['name'], ENT_QUOTES, 'UTF-8') ?></td>
<td><?= htmlspecialchars((string)$site['lat'], ENT_QUOTES, 'UTF-8') ?></td>
<td><?= htmlspecialchars((string)$site['lon'], ENT_QUOTES, 'UTF-8') ?></td>
<td><?= (int)$site['cell_count'] ?></td>
<td><a class="btn btn-secondary" href="edit_site.php?id=<?= (int)$site['id'] ?>">Ouvrir</a></td>
</tr>
<?php endforeach; ?>
<?php if (empty($sites)): ?>
<tr><td colspan="5">Aucun site pour cet opé··rateur.</td></tr>
<?php endif; ?>
</tbody>
</table>
<nav class="pagination">
<?php for ($p = 1; $p <= $totalPages; $p++): ?>
<a href="operator_sites.php?operator_id=<?= (int)$operatorId ?>&country_id=<?= (int)$countryId ?>&page=<?= $p ?>" class="<?= $p === $page ? 'active' : '' ?>"><?= $p ?></a>
<?php endfor; ?>
</nav>
</section>
<?php else: ?>
<section class="card">
<p>Sé··lectionnez un opé··rateur pour afficher ses sites.</p>
</section>
<?php endif; ?>
</main>
</body>
</html>