Rev 1029 | Blame | Compare with Previous | Last modification | View Log | RSS feed
<?php//declare(encoding='UTF-8');/*** Exemple de lancement du script : :* /opt/lampp/bin/php cli.php apd -a chargerTous** Base de données des Trachéophytes (trachéo...quoi ?? C'est le truc avec le stylo Bic ?)* d'Afrique de l'Ouest (et Centrale mais faut pas le dire)** @category php 5.2* @package eFlore/Scripts* @author Mathias CHOUET <mathias@tela-botanica.org>* @copyright Copyright (c) 2014, Tela Botanica (accueil@tela-botanica.org)* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL* @license http://www.gnu.org/licenses/gpl.html Licence GNU-GPL*/class Apd extends EfloreScript {private $table = null;private $tableMeta = null;private $pasInsertion = 1000;private $departInsertion = 0;protected $parametres_autorises = array();// Entêtes du nouveau fichier Rtax à produireprotected $entetesRtax = array("num_nom","num_nom_retenu","num_tax_sup","rang","nom_sci","nom_supra_generique","genre","epithete_infra_generique","epithete_sp","type_epithete","epithete_infra_sp","cultivar_groupe","cultivar","nom_commercial","auteur","annee","biblio_origine","notes","nom_addendum","homonyme","num_type","num_basionyme","synonyme_proparte","synonyme_douteux","synonyme_mal_applique","synonyme_orthographique","orthographe_originelle","hybride_parent_01","hybride_parent_01_notes","hybride_parent_02","hybride_parent_02_notes","nom_francais","presence","statut_origine ","statut_introduction","statut_culture","exclure_taxref");public function initialiserProjet($projetNom) {parent::initialiserProjet($projetNom);$this->table = Config::get("apd");$this->tableMeta = Config::get("apdMeta");}public function executer() {try {$this->initialiserProjet('apd');// Lancement de l'action demandée$cmd = $this->getParametre('a');switch ($cmd) {case 'tout' :$ok = $this->productionCsvPourReferentiels();if ($ok === true) {$this->integrationEFlore();}break;case 'ref' : // partie 1 : "referentiels"$this->productionCsvPourReferentiels();break;case 'eflore' : // partie 2 : "eFlore"$this->integrationEFlore();break;case 'nettoyage' :$this->nettoyage();break;case 'chargerStructureSql' ://$this->creerStructure();$this->chargerStructureSql();break;case 'verifierEtGenererCsvRtax' :$this->verifierEtGenererCsvRtax();break;case 'chargerCsvRtax' :$this->chargerCsvRtax();break;case 'changerRangs' :$this->changerRangs();break;case 'completerNumNomRetenu' :$this->completerNumNomRetenu();break;case 'supprimerNumTaxSupPourSynonymes' :$this->supprimerNumTaxSupPourSynonymes();break;case 'subspAutonymes' :$this->subspAutonymes();break;case 'genererNomSupraGenerique' :$this->genererNomSupraGenerique();break;case 'genererEpitheteInfraGenerique' :$this->genererEpitheteInfraGenerique();break;case 'exporterCSVModifie' :$this->exporterCSVModifie();break;case 'genererChpNumTax' :$this->genererChpNumTax();break;case 'genererNomSciHtml' :$this->genererChpNomSciHtml();break;case 'genererChpNomComplet' :$this->genererChpNomComplet();break;case 'genererChpFamille' :$this->genererChpFamille();break;case 'genererChpHierarchie' :$this->genererChpHierarchie();break;default :throw new Exception("Erreur : la commande '$cmd' n'existe pas!");}} catch (Exception $e) {$this->traiterErreur($e->getMessage());}}// Lance la première moitié du boulot, et s'arrête lorsque le fichier CSV// au format Rtax est rempli avec les données amendées - il est prêt à rentrer dans Rtxß.// Retourne true si tout s'est bien passé, false sinonprotected function productionCsvPourReferentiels() {$retour = false;$this->nettoyage();$this->chargerStructureSql();$verifOk = $this->verifierEtGenererCsvRtax();if ($verifOk === true) {$chgtOk = $this->chargerCsvRtax();if ($chgtOk) {$this->changerRangs();$this->completerNumNomRetenu();$this->supprimerNumTaxSupPourSynonymes();$this->subspAutonymes();$this->genererNomSupraGenerique();$this->genererEpitheteInfraGenerique();$this->exporterCSVModifie();$retour = true;}}return $retour;}// Lance la seconde moitié du boulot, et s'arrête lorsque le référentiel// est inséré dans la base eFlore.// Retourne true si tout s'est bien passé, false sinonprotected function integrationEFlore() {$retour = false;$this->genererChpNumTax();$this->genererChpNomSciHtml();$this->genererChpFamille();$this->genererChpNomComplet();$this->genererChpHierarchie();$retour = true;return $retour;}// -------------- partie Rtax -------------// Dézingue tout le bousinprotected function nettoyage() {echo "---- suppression des tables\n";$req = "DROP TABLE IF EXISTS `" . $this->table . "`";$this->getBdd()->requeter($req);$req = "DROP TABLE IF EXISTS `" . $this->tableMeta . "`;";$this->getBdd()->requeter($req);}// Analyse le fichier CSV fourni par le CJBG, le vérifie et écrit un CSV minimal au format Rtaxfunction verifierEtGenererCsvRtax() {$cheminCsvRtax = Config::get('chemins.csvRtax');$cheminCsvCjbg = Config::get('chemins.csvCjbg');$retour = false;echo "---- vérification CSV CJBG [$cheminCsvCjbg] et génération CSV Rtax\n";// Correspondances de colonnes pour le remplissage à minima du fichier CSV Rtax// Clefs: CJBG// Valeurs: Rtax$entetesCjbgVersRtax = array("id_name" => "num_nom","presence" => "presence","statut_introduction" => "statut_introduction","statut_origine" => "statut_origine","nom_addendum" => "nom_addendum","BASIONYME" => "num_basyonyme","NO_RANG" => "rang","auteur" => "auteur","ANNEE" => "annee","type_epithete" => "type_epithete","SYN_mal_applique" => "synonyme_mal_applique","nom_sci" => "nom_sci","num_tax_sup" => "num_tax_sup","num_nom_retenu" => "num_nom_retenu","genre" => "genre","NOTES" => "notes","epithete_sp" => "epithete_sp","epithete_infra_sp" => "epithete_infra_sp",// champs additionnels"NOM_STANDARD2" => false,"STATUT_SYN" => false, // @TODO convertir"hybride_parents" => false, // toujours "x" => ??"FAM APG3" => false,"auth_genre" => false,"auth_esp" => false);$analyseOK = true;$numLigne = 1;$idNames = array();// lecture CSV d'origine$csv = fopen($cheminCsvCjbg, "r");$donneesTransformees = array();if ($csv) {$entetes = fgetcsv($csv);//echo "Entetes: " . print_r($entetes, true) . "\n";while(($ligne = fgetcsv($csv)) !== false) {$numLigne++;$nouvelleLigne = array();if (isset($idNames[$ligne[0]])) {echo "Entrée dupliquée pour id_name [" . $ligne[0] . "]\n";$analyseOK = false;} else if (! is_numeric($ligne[0])) {echo "Ligne $numLigne : la clef [" . $ligne[0] . "] n'est pas un entier\n";$analyseOK = false;} else if ($ligne[0] == 0) {echo "Ligne $numLigne : la clef [" . $ligne[0] . "] vaut zéro\n";$analyseOK = false;} else {$idNames[$ligne[0]] = $ligne[13]; // stockage du nom retenuforeach ($ligne as $idx => $col) {$entete = $entetes[$idx];$ert = $entetesCjbgVersRtax[$entete];if (strpos($col, "\n") > -1) {echo "Info: la colonne $ert de la ligne $numLigne contient des retours chariot. Conversion en espaces.\n";$col = str_replace("\n", " ", $col);}$nouvelleLigne[$ert] = $col;}$donneesTransformees[] = $nouvelleLigne;}}} else {echo "Erreur lors de l'ouverture du fichier\n";}// Vérifications:// - existence des num_nom_retenu et num_tax_sup mentionnés// - réduction des chaînes de synonymie$nnrManquants = array();$ntsManquants = array();$chaineSyn = array();foreach ($donneesTransformees as $ligne) {$taxSup = $ligne['num_tax_sup'];$nomRet = $ligne['num_nom_retenu'];$numNom = $ligne['num_nom'];// Si un nom est retenu, son taxon supérieur doit être mentionné et existerif (($numNom == $nomRet) && $taxSup && (! isset($idNames[$taxSup])) && (! isset($ntsManquants[$taxSup]))) {$ntsManquants[$taxSup] = true;}// Si un nom retenu est mentionné, il doit exister et être un nom retenuif ($nomRet) {if (isset($idNames[$nomRet])) {/*$nrnr = $idNames[$nomRet];echo "Test pour nn $numNom, nr $nomRet, " . $nrnr . "\n";if ($nomRet && $nrnr != $nomRet) {if (! isset($chaineSyn[$nomRet])) {$chaineSyn[$nomRet] = true;}}*/} else {if (! isset($nnrManquants[$nomRet])) {$nnrManquants[$nomRet] = true;}}}}if (count($nnrManquants) > 0) {echo count($nnrManquants) . " Nom(s) retenu(s) absent(s):\n";echo "(" . implode(",", array_keys($nnrManquants)) . ")\n";}if (count($ntsManquants) > 0) {echo count($ntsManquants) . " Taxon(s) supérieur(s) absent(s):\n";echo "(" . implode(",", array_keys($ntsManquants)) . ")\n";}/*if (count($chaineSyn) > 0) {echo count($chaineSyn) . " Synonymes ne sont pas des noms retenus:\n";//echo "(" . implode(",", array_keys($chaineSyn)) . ")\n";}*/if ($analyseOK === true) {// Production CSV de destination$csvDestination = '';$csvDestination .= implode($this->entetesRtax, ',') . "\n";$tailleLigne = count($this->entetesRtax);foreach ($donneesTransformees as $dt) {//$ligne = array();$ligneCsv = '';$i = 0;foreach ($this->entetesRtax as $e) {/*if (isset($dt[$e])) {$ligne[] = $dt[$e];} else {$ligne[] = '';}*/if (isset($dt[$e]) && ($dt[$e] !== '')) {$ligneCsv .= '"' . $dt[$e] . '"';}if ($i < $tailleLigne) {$ligneCsv .= ',';}$i++;}$ligneCsv .= "\n";//$ligneCsv = '"' . implode($ligne, '","') . '"' . "\n"; // met des double guillemets sur les champs vides et /i$csvDestination .= $ligneCsv;}// @TODO créer le répertoire dans /tmp et donner les droits 777file_put_contents($cheminCsvRtax, $csvDestination);$retour = true;} else {echo "L'analyse a mis en évidence des erreurs. Interruption.\n";}return $retour;}// Charge le CSV minimal au format TexRafprotected function chargerCsvRtax() {$cheminCsvRtax = Config::get('chemins.csvRtax');echo "---- chargement du fichier CSV Rtax [$cheminCsvRtax]\n";$req = "LOAD DATA INFILE '" . $cheminCsvRtax . "' INTO TABLE " . $this->table. " FIELDS TERMINATED BY ',' ENCLOSED BY '\"' LINES TERMINATED BY '\n' IGNORE 1 LINES";$retour = $this->getBdd()->requeter($req);return $retour;}// Convertit les rangs du format chaispasquoi au format RexTafprotected function changerRangs() {echo "---- conversion des rangs\n";$rangs = array("0" => "10","1" => "20","2" => "50","3" => "53","4" => "80","5" => "140","6" => "180","7" => "190","8" => "200","9" => "220","10" => "230","11" => "240","12" => "250","13" => "260","14" => "280","15" => "290","16" => "320","17" => "340","18" => "350","19" => "360","20" => "370","26" => "440");foreach ($rangs as $src => $dest) {echo "rang $src => rang $dest\n";$req = "UPDATE " . $this->table . " SET rang=$dest WHERE rang=$src;";$this->getBdd()->requeter($req);}}// Copie num_nom dans num_nom_retenu lorsque ce dernier est videprotected function completerNumNomRetenu() {echo "---- complétion des num_nom_retenu\n";$req = "UPDATE " . $this->table . " SET num_nom_retenu = num_nom WHERE num_nom_retenu='';";$this->getBdd()->requeter($req);}// Supprime le num_tax_sup pour les synonymes// et le met à 1 s'il est égal au num_nomprotected function supprimerNumTaxSupPourSynonymes() {echo "---- suppression de num_tax_sup pour les synonymes et mise à 1 si égal à num_nom\n";$req = "UPDATE " . $this->table . " SET num_tax_sup = '' WHERE num_nom != num_nom_retenu;";$this->getBdd()->requeter($req);$req = "UPDATE " . $this->table . " SET num_tax_sup = 1 WHERE num_nom = num_tax_sup;";$this->getBdd()->requeter($req);}// Pour chaque subsp. autonyme, inscrit l'epithete_infra_spprotected function subspAutonymes() {echo "---- inscription de l'épithète infraspécifique des subsp. autonymes\n";$req = "SELECT num_nom, nom_sci, epithete_infra_sp FROM " . $this->table . " WHERE nom_sci LIKE '%subsp.%'";$res = $this->getBdd()->recupererTous($req);$nbres = count($res);$cpt = 0;$ok = 0;$ids = array();foreach ($res as $subsp) {$ns = $subsp['nom_sci'];$pos = strpos($ns, 'subsp.');$gsp = substr($ns, 0, $pos - 1);$sp = substr($gsp, strrpos($gsp, ' ') + 1);$sub = substr($ns, $pos + 8);if ($sub == $sp) {$cpt++;// @TODO// 1) récupérer l'auteur// 2) intégrer l'auteur avant "subsp." dans le nom_sci//echo "[$sp] || [$sub] || [" . $subsp['epithete_infra_sp'] . "]\n";if ($sub == $subsp['epithete_infra_sp']) {$ok++;} else {$reqMod = "UPDATE " . $this->table . " SET epithete_infra_sp='". $sub . "' WHERE num_nom=" . $subsp['num_nom'];$this->getBdd()->requeter($reqMod);}}}echo "subsp.: $nbres\n";echo "Autonymes: $cpt dont $ok déjà inscrites\n";}// Copie le nom scientifique dans le nom supra générique pour les taxons de rang// supérieur au genreprotected function genererNomSupraGenerique() {echo "---- complétion des noms supragénériques\n";$req = "UPDATE " . $this->table . " SET nom_supra_generique = nom_sci WHERE rang < 220";$res = $this->getBdd()->requeter($req);}// Copie le nom scientifique dans l'épithète infra générique pour les taxons de rang// entre genre et espèceprotected function genererEpitheteInfraGenerique() {echo "---- complétion des épithètes infragénériques\n";$req = "UPDATE " . $this->table . " SET epithete_infra_generique = nom_sci WHERE rang > 220 AND rang < 290";$res = $this->getBdd()->requeter($req);}protected function exporterCSVModifie() {$cheminFichierCsvRtaxModifie = Config::get('chemins.csvRtaxModifie');echo "---- export du CSV Rtax modifié [$cheminFichierCsvRtaxModifie]\n";if (file_exists($cheminFichierCsvRtaxModifie)) {unlink($cheminFichierCsvRtaxModifie);}$req = "SELECT '" . implode("','", $this->entetesRtax) . "'". " UNION ALL ". " SELECT * FROM " . $this->table . " INTO OUTFILE '" . $cheminFichierCsvRtaxModifie . "'". " FIELDS TERMINATED BY ',' ENCLOSED BY '\"' LINES TERMINATED BY '\n'";$res = $this->getBdd()->requeter($req);// Remplacement des cases vides par '' aulieu de '""' (peut faire foirer l'import par la suite)exec("sed -i 's/\"\"//g' " . $cheminFichierCsvRtaxModifie);}// -------------- partie eFlore ------------- copiée depuis le script Bdtfxprivate function genererChpNomSciHtml() {echo "---- génération des noms scientifiques en HTML \n";$this->preparerTablePrChpNomSciHtml();$generateur = new GenerateurNomSciHtml();$nbreTotal = $this->recupererNbTotalTuples();$erreurs = array();$this->departInsertion = 0;while ($this->departInsertion < $nbreTotal) {$resultat = $this->recupererTuplesPrChpNomSciHtml();try {$nomsSciEnHtml = $generateur->generer($resultat);} catch (Exception $e) {$erreurs[] = $e->getMessage();}$this->remplirChpNomSciHtm($nomsSciEnHtml);$this->departInsertion += $this->pasInsertion;$this->afficherAvancement("Insertion des noms scientifique au format HTML dans la base par paquet de {$this->pasInsertion} en cours");}echo "\n";if (count($erreurs) > 0) {echo 'Erreurs lors de la génération HTML des noms scientifiques:\n' . print_r($erreurs, true) . "\n";}}private function preparerTablePrChpNomSciHtml() {echo "---- ajout de la colonne nom_sci_html \n";$requete = "SHOW COLUMNS FROM {$this->table} LIKE 'nom_sci_html' ";$resultat = $this->getBdd()->recuperer($requete);if ($resultat === false) {$requete = "ALTER TABLE {$this->table} ".'ADD nom_sci_html VARCHAR( 500 ) '.'CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL ';$this->getBdd()->requeter($requete);}}private function recupererNbTotalTuples(){$requete = "SELECT count(*) AS nb FROM {$this->table} ";$resultat = $this->getBdd()->recuperer($requete);return $resultat['nb'];}private function recupererTuplesPrChpNomSciHtml() {$requete = 'SELECT num_nom, rang, nom_sci, nom_supra_generique, genre, epithete_infra_generique, '.' epithete_sp, type_epithete, epithete_infra_sp,cultivar_groupe, '.' nom_commercial, cultivar '."FROM {$this->table} "."LIMIT {$this->departInsertion},{$this->pasInsertion} ";$resultat = $this->getBdd()->recupererTous($requete);return $resultat;}private function remplirChpNomSciHtm($nomsSciHtm) {foreach ($nomsSciHtm as $id => $html) {$html = $this->getBdd()->proteger($html);$requete = "UPDATE {$this->table} SET nom_sci_html = $html WHERE num_nom = $id ";$resultat = $this->getBdd()->requeter($requete);if ($resultat === false) {throw new Exception("Erreur d'insertion pour le tuple $id");}}}// Attention c'est over-lent !private function genererChpNumTax() {$this->preparerTablePrChpNumTax();$erreurs = array();$this->departInsertion = 0;$dernier_num_tax = 0;$requete = 'SELECT num_nom '.'FROM '.$this->table.' '.'WHERE num_nom = num_nom_retenu AND num_nom_retenu != 0 '.'ORDER by num_nom_retenu ASC ';$resultat = $this->getBdd()->recupererTous($requete);foreach ($resultat as $taxon) {$dernier_num_tax++;$requete_maj = 'UPDATE '.$this->table.' '.'SET num_taxonomique = '.$dernier_num_tax.' '.'WHERE num_nom_retenu = '.$taxon['num_nom'];$this->getBdd()->requeter($requete_maj);$this->pasInsertion++;$this->afficherAvancement("Insertion des num tax, ".count($resultat)." num tax a traiter");}echo "\n";if (count($erreurs) > 0) {echo 'Erreurs lors de la génération des numéros taxonomiques' . print_r($erreurs, true) . "\n";}}private function preparerTablePrChpNumTax() {$requete = "SHOW COLUMNS FROM {$this->table} LIKE 'num_taxonomique' ";$resultat = $this->getBdd()->recuperer($requete);if ($resultat === false) {$requete = "ALTER TABLE {$this->table} ".'ADD num_taxonomique INT( 9 ) ';$this->getBdd()->requeter($requete);}}private function genererChpNomComplet() {$this->preparerTablePrChpNomComplet();$this->remplirChpNomComplet();}private function preparerTablePrChpNomComplet() {$requete = "SHOW COLUMNS FROM {$this->table} LIKE 'nom_complet' ";$resultat = $this->getBdd()->recuperer($requete);if ($resultat === false) {$requete = "ALTER TABLE {$this->table} ".'ADD nom_complet VARCHAR( 500 ) '.'CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL ';$this->getBdd()->requeter($requete);}}private function remplirChpNomComplet() {echo "---- Attribution du champ nom complet au taxons :\n";$requete = "UPDATE {$this->table} SET nom_complet = CONCAT(nom_sci,' ',auteur)";$resultat = $this->getBdd()->requeter($requete);if ($resultat === false) {echo "Erreur de génération du champ nom complet\n";} else {echo "OK\n";}}private function genererChpFamille() {$this->preparerTablePrChpFamille();$resultats = $this->recupererTuplesPrChpFamille();$noms = array();$introuvables = array();$introuvablesSyno = array();foreach ($resultats as $id => $nom) {$nn = $nom['num_nom'];$nnr = $nom['num_nom_retenu'];$nts = $nom['num_tax_sup'];$rg = $nom['rang'];if ($nnr != '') {if ($rg == '180') {$noms[$nn] = $nom['nom_sci'];} else {if ($nn == $nnr) {// nom retenuif (isset($noms[$nts])) {$noms[$nn] = $noms[$nts];} else {$introuvables[] = $nn;}} else {// nom synonymeif (isset($noms[$nnr])) {$noms[$nn] = $noms[$nnr];} else {$introuvablesSyno[] = $nom;}}}}unset($resultats[$id]);$this->afficherAvancement("Attribution de leur famille aux noms en cours");}echo "\n";foreach ($introuvablesSyno as $id => $nom) {$nn = $nom['num_nom'];$nnr = $nom['num_nom_retenu'];if (isset($noms[$nnr])) {$noms[$nn] = $noms[$nnr];} else {$introuvables[] = $nn;}unset($introuvablesSyno[$id]);$this->afficherAvancement("Attribution de leur famille aux synonymes en cours");}echo "\n";if (count($introuvables) > 0) {echo count($introuvables) . ' familles sont introuvables : ' . implode(',', $introuvables) . "\n";}$this->remplirChpFamille($noms);}private function preparerTablePrChpFamille() {$requete = "SHOW COLUMNS FROM {$this->table} LIKE 'famille' ";$resultat = $this->getBdd()->recuperer($requete);if ($resultat === false) {$requete = "ALTER TABLE {$this->table} ".'ADD famille VARCHAR(255) '.'CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL ';$this->getBdd()->requeter($requete);}}private function recupererTuplesPrChpFamille() {$requete = 'SELECT num_nom, num_nom_retenu, num_tax_sup, rang, nom_sci '."FROM {$this->table} "."WHERE rang >= 180 "."ORDER BY rang ASC, num_tax_sup ASC, num_nom_retenu DESC ";$resultat = $this->getBdd()->recupererTous($requete);return $resultat;}private function remplirChpFamille($noms) {foreach ($noms as $id => $famille) {$famille = $this->getBdd()->proteger($famille);$requete = "UPDATE {$this->table} SET famille = $famille WHERE num_nom = $id ";$resultat = $this->getBdd()->requeter($requete);if ($resultat === false) {throw new Exception("Erreur d'insertion pour le tuple $id");}$this->afficherAvancement("Insertion des noms de famille dans la base en cours");}echo "\n";}private function genererChpHierarchie() {$this->preparerTablePrChpHierarchie();$table = Config::get('tables.isfan');$requete = "UPDATE {$this->table} SET hierarchie = NULL ";$mise_a_jour = $this->getBdd()->requeter($requete);$requete_hierarchie = "SELECT num_nom, num_nom_retenu, num_tax_sup FROM " . $this->table . " ORDER BY rang DESC";$resultat = $this->getBdd()->recupererTous($requete_hierarchie);$num_nom_a_num_sup = array();foreach($resultat as &$taxon) {$num_nom_a_num_sup[$taxon['num_nom']] = $taxon['num_tax_sup'];}$chemin_taxo = "";foreach($resultat as &$taxon) {$chemin_taxo = $this->traiterHierarchieNumTaxSup($taxon['num_nom_retenu'], $num_nom_a_num_sup).'-';$requete = "UPDATE {$this->table} SET hierarchie = ".$this->getBdd()->proteger($chemin_taxo)." WHERE num_nom = ".$taxon['num_nom']." ";$mise_a_jour = $this->getBdd()->requeter($requete);$this->afficherAvancement("Insertion de la hierarchie taxonomique en cours");}echo "\n";}private function traiterHierarchieNumTaxSup($num_nom_retenu, &$num_nom_a_num_sup) {$chaine_hierarchie = "";if(isset($num_nom_a_num_sup[$num_nom_retenu])) {$num_tax_sup = $num_nom_a_num_sup[$num_nom_retenu];$chaine_hierarchie = '-'.$num_tax_sup;if($num_tax_sup != 0 && $num_tax_sup != '') {$chaine_hierarchie = $this->traiterHierarchieNumTaxSup($num_tax_sup, $num_nom_a_num_sup).$chaine_hierarchie;}}return $chaine_hierarchie;}private function preparerTablePrChpHierarchie() {$requete = "SHOW COLUMNS FROM {$this->table} LIKE 'hierarchie' ";$resultat = $this->getBdd()->recuperer($requete);if ($resultat === false) {$requete = "ALTER TABLE {$this->table} ".'ADD hierarchie VARCHAR(1000) '.'CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL ';$this->getBdd()->requeter($requete);}}}?>