db_rapport.php

<?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>