<?php
/**
* db_import.php
* Import des SMS/MMS depuis un fichier NDJSON (dans un ZIP) vers la BDD
*/
// =============================================================================
// Mapping JSON => PDO
// clé = nom du champ dans le JSON
// valeur = nom de la colonne en BDD
// =============================================================================
$id_name_sms = [
"date_sent" => "date_send",
"address" => "tel",
"date" => "date_received",
"__display_name" => "user_name",
"type" => "direction",
"body" => "msg_text_content"
];
$id_name_mms = [
"date" => "date_received",
"__display_name" => "user_name",
"msg_box" => "direction",
];
// Champs obligatoires — si l'un manque, la ligne est skippée
$requis_sms = ['address', 'date', 'type'];
$requis_mms = ['date'];
/**
* get_zip_path
* Vérifie que le fichier ZIP existe et retourne son chemin absolu
* @param string $zip_name
* @return string|false
*/
function get_zip_path(string $zip_name): string|false
{
$zip_path = dirname(__DIR__) . '/bkup_messages/' . basename($zip_name);
if (empty($zip_name) || !file_exists($zip_path)) return false;
return $zip_path;
}
/**
* import_bdd
* Ouvre le ZIP, lit le NDJSON ligne par ligne,
* vérifie les données et retourne un rapport
* @param PDO $pdo
* @param string $zip_name
* @return array $rapport
*/
function import_bdd(PDO $pdo, string $zip_name): array
{
global $id_name_sms, $id_name_mms, $requis_sms, $requis_mms;
// =========================================================================
// ÉTAPE 1 — Vérification et ouverture du ZIP
// Si ça plante ici, on stoppe tout et on retourne une erreur
// =========================================================================
$zip_path = get_zip_path($zip_name);
if ($zip_path === false) {
return ['erreur' => "L'archive '{$zip_name}' est introuvable."];
}
$zip = new ZipArchive();
if ($zip->open($zip_path) !== true) {
return ['erreur' => "Impossible d'ouvrir l'archive."];
}
$contenu = $zip->getFromName('messages.ndjson');
$zip->close();
if ($contenu === false) {
return ['erreur' => "Impossible de lire messages.ndjson."];
}
// =========================================================================
// ÉTAPE 2 — Initialisation du rapport
// C'est ce tableau qui sera retourné à la fin avec toutes les infos
// =========================================================================
$rapport = [
'nb_sms' => 0, // nombre de SMS détectés
'nb_mms' => 0, // nombre de MMS détectés
'nb_importes' => 0, // nombre de lignes importées avec succès
'nb_skipped' => 0, // nombre de lignes ignorées
'erreurs_json' => [], // lignes non décodables en JSON
'err_pre_check_bdd' => [], // lignes avec champs manquants ou vides
'erreurs_bdd' => [], // lignes qui ont planté à l'insertion
];
// =========================================================================
// ÉTAPE 3 — Boucle ligne par ligne sur le NDJSON
// =========================================================================
foreach (explode("\n", trim($contenu)) as $k => $line) {
// On ignore les lignes vides
if ($line === '') continue;
// ---------------------------------------------------------------------
// Décodage JSON
// Si la ligne n'est pas du JSON valide, on note l'erreur et on passe
// à la ligne suivante — pas la peine d'aller plus loin sur cette ligne
// ---------------------------------------------------------------------
$json = json_decode($line, true);
if (json_last_error() !== JSON_ERROR_NONE || !is_array($json)) {
$rapport['erreurs_json'][$k] = json_last_error_msg();
$rapport['nb_skipped']++;
continue; // ligne suivante
}
// ---------------------------------------------------------------------
// Détection SMS ou MMS
// SMS : pas de __sender_address ni __recipient_addresses
// MMS : présence de __sender_address ou __recipient_addresses
// ---------------------------------------------------------------------
$is_sms = !isset($json['__sender_address']) && !isset($json['__recipient_addresses']);
$mapping = $is_sms ? $id_name_sms : $id_name_mms;
$requis = $is_sms ? $requis_sms : $requis_mms;
if ($is_sms) {
$rapport['nb_sms']++;
} else {
$rapport['nb_mms']++;
}
// ---------------------------------------------------------------------
// Vérification des champs via le mapping
// Pour chaque champ attendu, on vérifie s'il existe et s'il est valide
// ---------------------------------------------------------------------
$fields = []; // données valides prêtes pour la BDD
$erreurs = []; // erreurs détectées sur cette ligne
foreach ($mapping as $k_json => $k_out) {
// Cas 1 : le champ n'existe pas dans le JSON
if (!isset($json[$k_json])) {
$erreurs[$k_json] = "Champ '{$k_json}' non défini à la ligne {$k}";
// Cas 2 : le champ existe mais il est vide
} elseif (empty($json[$k_json])) {
$erreurs[$k_json] = "Champ '{$k_json}' vide à la ligne {$k}";
// Cas 3 : tout est ok, on récupère la valeur
} else {
$fields[$k_out] = $json[$k_json];
}
}
// ---------------------------------------------------------------------
// Vérification des champs obligatoires
// Si un champ requis est absent de $fields, on ajoute une erreur
// ---------------------------------------------------------------------
foreach ($requis as $champ) {
if (empty($fields[$champ])) {
$erreurs[$champ] = "Champ requis '{$champ}' manquant à la ligne {$k}";
}
}
// ---------------------------------------------------------------------
// Si des erreurs ont été détectées sur cette ligne,
// on les enregistre dans le rapport et on passe à la ligne suivante
// ---------------------------------------------------------------------
if (!empty($erreurs)) {
$rapport['err_pre_check_bdd'][$k] = $erreurs;
$rapport['nb_skipped']++;
continue; // ligne suivante
}
// ---------------------------------------------------------------------
// Ici, $fields contient des données valides et complètes
// L'insertion en BDD se fera ici — à venir
// ---------------------------------------------------------------------
$rapport['nb_importes']++;
}
// =========================================================================
// ÉTAPE 4 — Retour du rapport complet
// =========================================================================
return $rapport;
}
