* @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 à produire protected $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 sinon protected 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 sinon protected function integrationEFlore() { $retour = false; $this->genererChpNumTax(); $this->genererChpNomSciHtml(); $this->genererChpFamille(); $this->genererChpNomComplet(); $this->genererChpHierarchie(); $retour = true; return $retour; } // -------------- partie Rtax ------------- // Dézingue tout le bousin protected 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 Rtax function 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 retenu foreach ($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 exister if (($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 retenu if ($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 777 file_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 TexRaf protected 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 RexTaf protected 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 vide protected 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_nom protected 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_sp protected 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 genre protected 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èce protected 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 Bdtfx private 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 retenu if (isset($noms[$nts])) { $noms[$nn] = $noms[$nts]; } else { $introuvables[] = $nn; } } else {// nom synonyme if (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); } } } ?>