Pour les besoins d'un webmail que je remets à jour j'avais besoin de traiter les tableaux d'objets renvoyés par la fonction imap_fetchstructure. Il existe quelques exemples sur le site de PHP (www.php.net) mais rien en procéduriel, que de l'objet et moi, l'objet, ça me file des boutons! J'ai donc décidé de développé ma propre fonction.
Le principe est de traiter le tableau d'objet par niveau. Le faire de manière naturelle, comme un humain lierait le tableau aurait été beaucoup trop dur pour moi.
Afin de s'y retrouver ma fonction renomme chaque clef en récupérant le nom d'objet de la valeur traitée.
Source / Exemple :
<?php
//$a est un tableau d'objets renvoyé par la fonction imap_fetch_structure
//On liste dans un tableau tous les objets renvoyés par la fonction
$valeurs_objet = array ("type", "encoding", "ifsubtype", "subtype", "ifdescription", "descritpion", "ifid", "id", "lines", "bytes", "ifdisposition", "disposition", "ifdparameters", "dparameters", "ifparameters", "parameters", "parts");
print_r ($a);
echo "<br><br><br>";
//On stocke les chemins amenant à un sous tableau
$stock_tableau = array();
//Tableau de sortie que l'on pourra travailler après
$recup_donnees = array();
//Variable incrémentable pour le premier niveau qui servira a appelé les noms d'objets contenus dans $valeur_objet
$numero = 0;
//On fait tourner la boucle tant que le tableau d'objets $a n'a pas entièrement été lu
while (!$arret_boucle) {
//On traite le 1er niveau
if (empty ($stock_tableau) || empty ($niveau)) {
if ($numero<17) {
//On récupère la valeur courante de $a
$valeur_courante = $a -> $valeurs_objet[$numero];
//Si la valeur courante est un tableau on stocke le chemin dans $stock_tableau
if (is_array ($valeur_courante)) {
array_push ($stock_tableau, $valeurs_objet[$numero]);
} else {
//Si la valeur courante est une simple valeur on la stocke avec le nom d'objet en clef dans le tableau $recup_donnees
if (isset ($valeur_courante)) {
$recup_donnees[$valeurs_objet[$numero]] = $valeur_courante;
}
}
$numero++;
//Si le premier niveau est terminé on met un séparateur et l'on passe au 2ème niveau
} else {
array_push ($stock_tableau, "/,,/");
array_push ($recup_donnees, "/,,/");
$niveau = 1;
}
//On traite les niveaux supérieurs
} else {
$valeur_courante2 = current ($stock_tableau);
next ($stock_tableau);
//Niveau 3 et supérieur
if (is_array ($valeur_courante2)) {
//On compte le nombre de valeurs contenues dans le tableau
$compte_tableau3 = count ($valeur_courante2);
//On copie le tableau pour le triturer afin de ne pas abîmer le tableau original
$resultat2 = $a -> parts;
//On épluche le tableau $resultat2 pour obtenir le morceau désiré
for ($d=0;$d<$compte_tableau3;$d++) {
//La distinction est obligatoire car le compilateur ne reconnaît pas les appels du genre $truc->$a->$b. Il faut préciser $a et $b si ce sont des objets
if ($d%2 == 0) {
//Le +0 est très important sinon le résultat obtenu sera tout autre. On teste la valeur courante appelée afin de déterminer s'il s'agit d'un objet ou d'un tableau
$resultat2 = $resultat2[$valeur_courante2[$d]+0];
} else {
//On définit le saut suivant
if ($valeur_courante2[$d] == "parameters") {
$resultat2 = $resultat2->parameters;
} else if ($valeur_courante2[$d] == "dparameters") {
$resultat2 = $resultat2->dparameters;
} else if ($valeur_courante2[$d] == "parts") {
$resultat2 = $resultat2->parts;
}
}
}
//On compte le nombre de valeurs contenues dans le tableau épluché
$compte_resultat2 = count ($resultat2);
//On compte le nombre de valeurs du tableau contenu dans la variable $valeur_courante2
$compte_valeur_courante2 = count ($valeur_courante2);
//On analyse la valeur courante du tableau $resultat2
for ($e=0;$e<$compte_resultat2;$e++) {
//permet d'incrémenter les différentes clefs attribute et value
$g = $c++;
//On regarde si la valeur courante est parameters ou dparameters afin de récupérer les valeurs de attribute et value avec les noms d'objets en clef indexés
if (strcmp ($valeur_courante2[$compte_valeur_courante2-1], "parameters") == 0 || strcmp ($valeur_courante2[$compte_valeur_courante2-1], "dparameters") == 0) {
$recup_donnees[attribute.$g] = $resultat2[$e] -> attribute;
$recup_donnees[value.$g] = $resultat2[$e] -> value;
//idem pour parts. Dans ce cas on teste toutes les valeurs derrière parts afin de déterminer s'il y a un tableau d'objet ou une simple valeur
} else if (strcmp ($valeur_courante2[$compte_valeur_courante2-1], "parts") == 0) {
for ($i=0;$i<17;$i++) {
//On vérifie que l'objet existe
if (isset ($resultat2[$e] -> $valeurs_objet[$i])) {
//Si la valeur retournée est un tableau on réupère le chemin, on ajoute la dernière clef, on injecte le tout dans un tableau que l'on met dans $stock_tableau
if (is_array ($resultat2[$e] -> $valeurs_objet[$i])) {
$boom = implode (",", $valeur_courante2);
$boom2 = "$boom, $e,$valeurs_objet[$i]";
$colle = explode (",", $boom2);
array_push ($stock_tableau, $colle);
//Si la clef contient une simple valeur on la stocke dans $recup_donnees
} else {
$recup_donnees[$valeurs_objet[$i].$g] = $resultat2[$e] -> $valeurs_objet[$i];
}
}
}
}
}
//Une fois le niveau courant terminé (2ème ou supérieur) on met une séparation et l'on passe au niveau suivant
} else if (empty ($valeur_courante2) || $valeur_courante2 == "/,,/") {
$verif = count ($stock_tableau)-1;
if ($stock_tableau[$verif] != "/,,/") {
array_push ($stock_tableau, "/,,/");
array_push ($recup_donnees, "/,,/");
//Si tout le tableau d'objet a été lu on arrête la boucle
} else {
$arret_boucle = 1;
}
//Niveau 2
} else {
//On récupère la valeur courante
$resultat = $a -> $valeur_courante2;
//On compte le nombre d'éléments contenu dans le tableau
$compte_tableau2 = count ($resultat);
//On teste toutes les clefs du tableau afin de savoir si la valeur est un tableau, un objet ou une simple valeur
for ($c=0;$c<$compte_tableau2;$c++) {
//Si la valeur courante est parameters on stocke son contenu dans $recup_donnees et on met le nom des objets en clefs suivi d'un indice numérique pour ne pas que le compilateur considère
//qu'il n'y ait qu'une seule clef et donc qu'une seule valeur
if ($valeur_courante2 == "parameters") {
$recup_donnees[attribute.$c] = $resultat[$c] -> attribute;
$recup_donnees[value.$c] = $resultat[$c] -> value;
//idem si la valeur courante est dparameters
} else if ($valeur_courante2 == "dparameters") {
$recup_donnees[attribute.$c+1] = $resultat[$c] -> attribute;
$recup_donnees[value.$c+1] = $resultat[$c] -> value;
//Si la valeur courante est parts on recommence à tester toutes les valeurs contenues après parts pour savoir si les clefs contiennent des objets ou de simples valeurs
} else if ($valeur_courante2 == "parts") {
for ($f=0;$f<17;$f++) {
//On vérifie que l'objet courant appelé existe
if (isset ($resultat[$c] -> $valeurs_objet[$f])) {
//Si l'objet courant appelé est un tableau on stocke le chemin dans $stock_tableau, sinon on inscrit la valeur dans $recup_donnees
if (is_array ($resultat[$c] -> $valeurs_objet[$f])) {
array_push ($stock_tableau, array ($c, $valeurs_objet[$f]));
} else {
$recup_donnees[$valeurs_objet[$f].$c] = $resultat[$c] -> $valeurs_objet[$f];
}
}
}
}
}
}
}
}
echo "<br><br><br>";
echo "recup_donnees : ";
print_r ($recup_donnees);
}
?>
Conclusion :
J'espère que cette fonction pourra aider ceux qui veulent utiliser la fonction imap_fetchstructure qui peut renvoyer un tableau d'objet très vite énorme selon le mail analisé (un forward de forward avec pièces jointes, fichiers incorporés, etc...)
Vous n'êtes pas encore membre ?
inscrivez-vous, c'est gratuit et ça prend moins d'une minute !
Les membres obtiennent plus de réponses que les utilisateurs anonymes.
Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.
Le fait d'être membre vous permet d'avoir des options supplémentaires.