185 lines
6.7 KiB
PHP
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>
|