<?php
/**
* db_rapport.php
* Fonctions métier pour l'analyse du fichier NDJSON contenu dans le ZIP
*/
/**
* get_zip_path
* Vérifie que le fichier ZIP existe et retourne son chemin absolu
* @param string $zip_name — nom du fichier ZIP
* @return string|false — chemin absolu ou false si introuvable
*/
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;
}
/**
* get_rapport
* Ouvre le ZIP, analyse le NDJSON et retourne les données du rapport
* @param string $zip_name — nom du fichier ZIP
* @return array — tableau contenant les données du rapport ou une clé 'erreur'
*/
function get_rapport(string $zip_name): array {
// === VÉRIFICATION DU ZIP ===
$zip_path = get_zip_path($zip_name);
if ($zip_path === false) {
return ['erreur' => 'Fichier ZIP introuvable.'];
}
// === OUVERTURE DU ZIP ===
$zip = new ZipArchive();
if ($zip->open($zip_path) !== TRUE) {
return ['erreur' => 'Impossible d\'ouvrir le ZIP.'];
}
// === VÉRIFICATION DU NDJSON ===
if ($zip->locateName('messages.ndjson') === false) {
$zip->close();
return ['erreur' => 'messages.ndjson introuvable dans l\'archive.'];
}
// === LECTURE DU NDJSON ===
$arr_ndjson = explode("\n", trim($zip->getFromName("messages.ndjson")));
// === INITIALISATION DES COMPTEURS ===
$nb_sms = 0; // nombre de SMS
$nb_mms = 0; // nombre de MMS
$nb_pj = 0; // nombre de pièces jointes référencées dans le NDJSON
$nb_pj_absentes = 0; // nombre de pièces jointes absentes du dossier data/ du ZIP
$date_min = PHP_INT_MAX; // timestamp le plus ancien — initialisé au max pour la comparaison
$date_max = 0; // timestamp le plus récent
$err_not_json = []; // lignes non décodables par json_decode
// === ANALYSE LIGNE PAR LIGNE ===
foreach ($arr_ndjson as $k => $line) {
$json = json_decode($line, true);
// Ligne JSON invalide — on la stocke et on passe à la suivante
if ($json === null) {
$err_not_json[] = ['l' => $k, 'c' => $line];
continue;
}
// --- Détection SMS / MMS ---
// SMS : pas de __sender_address ni __recipient_addresses
// MMS : présence de __sender_address ou __recipient_addresses
if (!isset($json['__sender_address']) && !isset($json['__recipient_addresses'])) {
$nb_sms++;
// SMS : date en millisecondes → on enlève les millisecondes pour conserver en secondes
$date = (int) substr($json['date'], 0, -3);
} else {
$nb_mms++;
// MMS : date déjà en secondes
$date = (int) $json['date'];
// --- Comptage et vérification des pièces jointes ---
// Seuls les __parts avec _data sont de vraies pièces jointes
if (isset($json['__parts'])) {
foreach ($json['__parts'] as $part) {
if (isset($part['_data'])) {
$nb_pj++;
// On vérifie que le fichier est bien présent dans data/ du ZIP
$nom_fichier = 'data/' . basename($part['_data']);
if ($zip->locateName($nom_fichier) === false) {
$nb_pj_absentes++;
}
}
}
}
}
// --- Calcul date_min / date_max ---
// On compare tous les timestamps normalisés en secondes
if ($date < $date_min) $date_min = $date;
if ($date > $date_max) $date_max = $date;
}
$zip->close();
// === RETOUR DU RAPPORT ===
return [
'nb_sms' => $nb_sms,
'nb_mms' => $nb_mms,
'nb_pj' => $nb_pj,
'nb_pj_absentes' => $nb_pj_absentes,
'date_debut' => date('Y-m-d H:i:s', $date_min),
'date_fin' => date('Y-m-d H:i:s', $date_max),
'err_not_json' => $err_not_json,
];
}
Et voici un EXEMPLE de fichier view pour le rapport débarassé de tout code métier
le code métier, c’est get_rapport qui s’en occupe
<?php
require_once dirname(__DIR__) . '/src/db_rapport.php';
$rapport = get_rapport($_GET['zip'] ?? '');
if (isset($rapport['erreur'])) {
// ici je fais un header mais on peut afficher l'erreur rencontrée aussi
header('Location: index.php?page=list_zip');
exit;
}
?>
<li>SMS : <?= $rapport['nb_sms'] ?></li>
<li>MMS : <?= $rapport['nb_mms'] ?></li>
<li>Premier message : <?= $rapport['date_debut'] ?></li>
<li>Dernier message : <?= $rapport['date_fin'] ?></li>
