getMessage()) n'est plus affiche a l'ecran ; il est * journalise via error_log() et un message generique est montre a * l'administrateur. */ declare(strict_types=1); require_once __DIR__ . '/admin_auth.php'; require_once __DIR__ . '/../lib/db.php'; require_once __DIR__ . '/../lib/ntm_import_to_staging.php'; require_once __DIR__ . '/_nav.php'; require_admin_auth(); $db = pdo(); $user = current_admin_username(); $successMessage = null; $errorMessage = null; $importStats = null; $previewGroups = []; $lastImportId = null; /** * Meme logique de regroupement que admin/review.php, dupliquee ici * volontairement pour ne pas creer de dependance croisee entre pages * admin. Si vous ajustez le decalage de bits ou la logique de * regroupement dans review.php, reportez le changement ici aussi. */ function deriveSiteKeyForPreview(array $row): string { $mcc = $row['mcc']; $mnc = $row['mnc']; if ($row['tech'] === '4G' && !empty($row['sub_id2'])) { return "enb:{$mcc}:{$mnc}:{$row['area_code']}:{$row['sub_id2']}"; } $latR = $row['lat'] !== null ? round((float)$row['lat'], 4) : 'na'; $lonR = $row['lon'] !== null ? round((float)$row['lon'], 4) : 'na'; return "geo:{$mcc}:{$mnc}:{$row['area_code']}:{$latR}:{$lonR}"; } const MAX_UPLOAD_SIZE_BYTES = 10 * 1024 * 1024; // 10 Mo, garde-fou raisonnable pour un fichier .ntm if ($_SERVER['REQUEST_METHOD'] === 'POST') { require_csrf_token(); $countryId = (int)($_POST['country_id'] ?? 0); if (!$countryId) { $errorMessage = "Selectionnez un pays avant d'importer."; } elseif (empty($_FILES['ntm_file']) || $_FILES['ntm_file']['error'] !== UPLOAD_ERR_OK) { $uploadErrors = [ UPLOAD_ERR_INI_SIZE => "Le fichier depasse la taille maximale autorisee par le serveur (php.ini).", UPLOAD_ERR_FORM_SIZE => "Le fichier depasse la taille maximale autorisee par le formulaire.", UPLOAD_ERR_PARTIAL => "Le fichier n'a ete que partiellement televerse. Reessayez.", UPLOAD_ERR_NO_FILE => "Aucun fichier selectionne.", ]; $code = $_FILES['ntm_file']['error'] ?? UPLOAD_ERR_NO_FILE; $errorMessage = $uploadErrors[$code] ?? "Erreur lors du televersement du fichier."; } else { $tmpPath = $_FILES['ntm_file']['tmp_name']; $originalName = $_FILES['ntm_file']['name']; $fileSize = $_FILES['ntm_file']['size']; $extension = strtolower(pathinfo($originalName, PATHINFO_EXTENSION)); if ($extension !== 'ntm') { $errorMessage = "Seuls les fichiers .ntm sont acceptes (extension detectee : ." . htmlspecialchars($extension, ENT_QUOTES, 'UTF-8') . ")."; } elseif ($fileSize > MAX_UPLOAD_SIZE_BYTES) { $errorMessage = "Le fichier depasse la limite de " . (MAX_UPLOAD_SIZE_BYTES / 1024 / 1024) . " Mo."; } elseif (!is_uploaded_file($tmpPath)) { $errorMessage = "Televersement invalide (fichier non reconnu comme upload legitime)."; } else { $safeFilename = preg_replace('/[^A-Za-z0-9._-]/', '_', $originalName); $uploadsDir = __DIR__ . '/../uploads'; if (!is_dir($uploadsDir)) { mkdir($uploadsDir, 0750, true); } $destPath = $uploadsDir . '/' . uniqid('ntm_', true) . '_' . $safeFilename; if (!move_uploaded_file($tmpPath, $destPath)) { $errorMessage = "Impossible d'enregistrer le fichier televerse sur le serveur."; } else { try { $importStats = importNtmFileToStaging($destPath, $safeFilename, $countryId); $successMessage = "Import termine : {$importStats['staged']} ligne(s) placee(s) en validation" . ($importStats['already_known'] > 0 ? ", dont {$importStats['already_known']} deja connue(s) en base" : "") . ($importStats['error'] > 0 ? ", {$importStats['error']} erreur(s)" : "") . "."; // Recupere l'ID de l'import qui vient d'etre cree pour l'apercu de regroupement $lastImportId = (int)$db->query('SELECT MAX(id) FROM imports')->fetchColumn(); $previewStmt = $db->prepare(' SELECT sc.*, o.brand AS operator_brand FROM staging_cells sc LEFT JOIN operators o ON o.id = sc.operator_guess WHERE sc.import_id = ? '); $previewStmt->execute([$lastImportId]); $importedRows = $previewStmt->fetchAll(PDO::FETCH_ASSOC); foreach ($importedRows as $row) { $key = deriveSiteKeyForPreview($row); $previewGroups[$key]['cells'][] = $row; $previewGroups[$key]['operator_brand'] = $row['operator_brand']; $previewGroups[$key]['lat'] = $previewGroups[$key]['lat'] ?? $row['lat']; $previewGroups[$key]['lon'] = $previewGroups[$key]['lon'] ?? $row['lon']; } } catch (Throwable $e) { error_log('[import_ntm] ' . $e->getMessage()); $errorMessage = "Une erreur est survenue lors du traitement du fichier. Consultez les journaux du serveur."; } } } } } $countries = $db->query('SELECT id, iso2, name FROM countries ORDER BY name')->fetchAll(PDO::FETCH_ASSOC); $importHistory = $db->query(' SELECT i.*, c.name AS country_name FROM imports i LEFT JOIN countries c ON c.id = i.country_id ORDER BY i.uploaded_at DESC LIMIT 20 ')->fetchAll(PDO::FETCH_ASSOC); ?>
Deposez un fichier .ntm pour l'analyser et placer ses antennes en file de validation. Rien n'est ecrit dans la base finale sans validation manuelle.
= htmlspecialchars($successMessage, ENT_QUOTES, 'UTF-8') ?>
= htmlspecialchars($errorMessage, ENT_QUOTES, 'UTF-8') ?>
Verification rapide que les cellules d'un meme site (meme eNB pour la 4G, ou meme position GPS pour les autres technos) sont bien reunies ensemble.
| Fichier | Pays | Date | Lignes | En validation | Erreurs | Statut |
|---|---|---|---|---|---|---|
| = htmlspecialchars($imp['filename'], ENT_QUOTES, 'UTF-8') ?> | = htmlspecialchars($imp['country_name'] ?? '?', ENT_QUOTES, 'UTF-8') ?> | = htmlspecialchars(date('d/m/Y H:i', strtotime($imp['uploaded_at'])), ENT_QUOTES, 'UTF-8') ?> | = (int)$imp['total_lines'] ?> | = (int)$imp['staged_count'] ?> | = (int)$imp['error_count'] ?> | = htmlspecialchars($imp['status'], ENT_QUOTES, 'UTF-8') ?> |
| Aucun import pour le moment. | ||||||