Subversion Repositories Applications.referentiel

Rev

Rev 337 | Blame | Compare with Previous | Last modification | View Log | RSS feed

<?php
// Encodage : UTF-8
// +-------------------------------------------------------------------------------------------------------------------+
/**
* Importation d'un fichier ref-tax dans une bdnt
*
* Description : classe permettant de versionner les référentiels selon le manuel technique
* Utilisation : php script.php comparaison -r bdnff -a tout -f fichier.txt
*
//Auteur original :
* @author       Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @copyright    Tela-Botanica 1999-2010
* @link                 http://www.tela-botanica.org/wikini/RTaxMethodo/wakka.php?wiki=MaNuel
* @licence              GPL v3 & CeCILL v2
* @version              $Id$
*/
// +-------------------------------------------------------------------------------------------------------------------+
class Importation extends ScriptCommande {
        
        const SCRIPT_NOM = 'importation';
        const MANUEL_VERSION = '4.3';
        
        private $referentiel = null;
        /*public $parametres = array(
                '-r' => array(true, true, 'referentiel de base'),
                '-f' => array(true, true, 'fichier à comparer'));*/
        private $noms_supprimes = null;
        private $noms_colonnes = array();
        private $rangs_bdnt_taxref = null;
        private $statuts_bdnt_taxref = null;
        private $correspondance_colonnes = array("CD_NOM" => "", "CD_SUP" => "", "CD_REF" => "",
                "RANG" => "rang", "LB_NOM" => "nom_sci", "LB_AUTEUR" => array("auteur","annee"),
                "FR" => "presence",
                "FR-FRA" => "presence_Ga", "FR-COR" => "presence_Co", "REU" => "presence",
                "GUA" => "presence_Guadeloupe", "SMSB" => array("presence_Saint_Martin", "presence_Saint_Barthelemy"), 
                "SM" => "presence_Saint_Martin", "SB" => "presence_Saint_Barthelemy",  "MAR" => "presence_Martinique",
                "GF" => "presence", "MAY" => "presence_Mayotte", "TAAF" => "presence_Taaf",
                "SPM" => "presence_Guadeloupe", "PF" => "presence_Polynesie", "NC" => "presence_Nouvelle_Caledonie",
                "BIBLIO" => "biblio_origine", "BDNGM" => "num_nom", "NUM_NOM" => "num_nom", "NOM_VERN" => "nom_francais");
        
        private $sans_correspondance = array(
                        "FG_VALIDITE", "habitat", "WF", "CLI", "EPA",
                        "EU", "WLD", "ORACLE",
                        "DATE_CREA", "ORIGINE_CREA",
                        "NOM_COMPLET", "NOM_COMPLET_HTML",
                        "GENRE", "ESPECE", "SOUS_ESPECE", "ANNEE");
        
        /*public function executer() {
                $this->referentiel = $this->getParam('r');
                // Lancement du test demandé
                $fichier = $this->getParam('f');
                if (file_exists($fichier)) {
                        $manuel_chemin = Config::get('chemin_appli').DS.'..'.DS.'configurations'.DS;
                        $manuel_config_nom = 'referentiel_v'.self::MANUEL_VERSION.'.ini';
                        $this->manuel = parse_ini_file($manuel_chemin.$manuel_config_nom);
                        $this->creerCorrespondanceRangBdntTaxref();
                        $donnees = $this->traiterFichierTaxref($fichier);
                        Debug::printr("Fin du traitement du fichier.");
                        $this->connecterPDO();
                        $this->creerTableTaxref();
                        $this->ajouterColonneCDNOM();
                        Debug::printr("Fin de la création de la table.");
                        $this->ajouterDonneesTaxRef($donnees);
                        Debug::printr("Fin de l'insertion des données.");
                        $this->creerTableComparaison();
                        Debug::printr("Fin de la création de la table comparaison.");
                }
        }*/
        
        public function executer() {
                // Récupération du dernier traitement demandé
                $this->traitementDao = new TraitementDao();
                $this->traitement = $this->traitementDao->getDernierTraitement('tout', self::SCRIPT_NOM);
                if (isset($this->traitement)) {
                        $this->referentiel = $this->traitement['referentiel_code']; // Récupération du nom de projet
                        $fichier = $this->traitement['script_parametres'];
                        if (file_exists($fichier)) {
                                Debug::printr('Debute:'.$this->traitementDao->debuterTraitement($this->traitement['id_traitement']));
                                // Nettoyage des traitements obsolètes
                                $traitements_obsoletes = $this->traitementDao->getTraitementsObsoletes($this->referentiel, self::SCRIPT_NOM);
                                if (isset($traitements_obsoletes)) {
                                        Debug::printr('Supp. obsoletes:'.$this->traitementDao->supprimer($traitements_obsoletes));
                                }
                                Debug::printr("Début du traitement du fichier.");
                                $manuel_chemin = Config::get('chemin_appli').DS.'..'.DS.'configurations'.DS;
                                $manuel_config_nom = 'referentiel_v'.self::MANUEL_VERSION.'.ini';
                                $this->manuel = parse_ini_file($manuel_chemin.$manuel_config_nom);
                                $this->creerCorrespondanceRangBdntTaxref();
                                $donnees = $this->traiterFichierTaxref($fichier);
                                Debug::printr("Fin du traitement du fichier.");
                                $this->connecterPDO();
                                $this->creerTableTaxref();
                                $this->ajouterColonneCDNOM();
                                Debug::printr("Fin de la création de la table.");
                                $this->ajouterDonneesTaxRef($donnees);
                                Debug::printr("Fin de l'insertion des données.");
                                $this->decouperNomSciTaxRef();
                                $this->creerTableComparaison();
                                Debug::printr("Fin de la création de la table comparaison.");
                                Debug::printr('Termine:'.$this->traitementDao->terminerTraitement($this->traitement['id_traitement']));
                        } else {
                                Debug::printr("Fichier introuvable".$fichier);
                                Debug::printr('Termine:'.$this->traitementDao->terminerTraitement($this->traitement['id_traitement']));
                        }
                } else {
                        Debug::printr("Pas de traitement");
                }
        }
        

// +-------------------------------------------------------------------------------------------------------------------+
        private function creerTableTaxref() {
                $requete = "DROP TABLE IF EXISTS {$this->referentiel}_taxref; ".
                        "CREATE TABLE  {$this->referentiel}_taxref AS SELECT * FROM {$this->referentiel};".
                        "ALTER TABLE  {$this->referentiel}_taxref ADD PRIMARY KEY (num_nom);";
                $resultat = $this->executerRequeter($requete);
        }
        
        private function ajouterColonneCDNOM() {
                $requete = "ALTER TABLE  {$this->referentiel}_taxref ADD ".
                        "`CD_NOM` INT( 15 ) NULL DEFAULT NULL COMMENT 'numéro correspondant dans la base taxref.';";
                $resultat = $this->executerRequeter($requete);
        }
        
        private function ajouterDonneesTaxRef($liste_noms) {
                $i = 0; $j = 0; $requete = "";
                foreach ($liste_noms as $nom) { $i++;
                        $requete .= "UPDATE  {$this->referentiel}_taxref SET ".implode(' , ', $nom).
                                        " WHERE {$nom['num_nom']} ;";//echo $requete;
                        if ($i == 1000 || ($j*1000+$i) == count($liste_noms) ) { $j++;
                                $resultat = $this->executerRequeter($requete.'commit;');
                                if ($resultat == null) {
                                        $resultat = $this->executerRequeter($requete.'commit;');
                                }
                                $i = 0; $requete = "";
                        }
                }
        }
        
        private function creerTableComparaison() {
                foreach ($this->noms_colonnes as $colonne) {
                        if (isset($this->correspondance_colonnes[$colonne]) && $this->correspondance_colonnes[$colonne] != "") {
                                $nom_champ = $this->correspondance_colonnes[$colonne];
                                if (is_array($nom_champ)) {
                                        foreach ($nom_champ as $nom) {
                                                $champs_tax[] = "t.{$nom} AS tax_{$nom}";
                                                $champs_tax[] = "b.{$nom} AS {$nom}";
                                                $concat[] = "IF(t.{$nom} != b.{$nom}, '{$nom}, ', '')";
                                        }
                                } else {
                                        $champs_tax[] = "t.{$nom_champ} AS tax_{$nom_champ}";
                                        $champs_tax[] = "b.{$nom_champ} AS {$nom_champ}";
                                        $concat[] = "IF(t.{$nom_champ} != b.{$nom_champ}, '{$nom_champ}, ', '')";
                                }
                        }
                }
                date_default_timezone_set('Europe/London');
                $requete = "CREATE TABLE  {$this->referentiel}_comparaison_".date("Y_m_d_H_i_s")." AS".
                                        " SELECT CONCAT(".implode(', ', $concat).") AS difference, ".implode(', ', $champs_tax).
                                        " FROM {$this->referentiel} b, {$this->referentiel}_taxref t".
                                        " WHERE b.num_nom = t.num_nom AND (b.nom_sci != t.nom_sci or b.auteur != t.auteur or b.annee != t.annee);";
                //echo $requete;
                $resultat = $this->executerRequeter($requete);
        }
        
// +-------------------------------------------------------------------------------------------------------------------+
        private function traiterFichierTaxref($fichier) {
                $donnees = array();
                if (($pointeur = fopen($fichier, "r")) !== FALSE) {
                        $this->noms_colonnes = fgetcsv($pointeur, 1000, chr(9));
                        $num_nom = 0;//print_r($this->noms_colonnes);
                        while (($ligne = fgetcsv($pointeur, 1000, chr(9))) !== FALSE) {
                                $nombreChamps = count($ligne);
                                $taxref[$ligne[0]] = $ligne;//print_r($ligne);
                                for ($c=0; $c < $nombreChamps; $c++) {
                                        if (isset($this->correspondance_colonnes[$this->noms_colonnes[$c]])) {
                                                if (is_array($this->correspondance_colonnes[$this->noms_colonnes[$c]])) {
                                                        if ($this->noms_colonnes[$c] == 'LB_AUTEUR') {
                                                                if (preg_match('/(.*), +([0-9]{4})/', utf8_encode($ligne[$c]), $matches) == 1) {
                                                                        $nom['auteur'] = 'auteur="'.$matches[1].'"';
                                                                        $nom['annee'] = 'annee="'.trim($matches[2]).'"';
                                                                } else {
                                                                        $nom['auteur'] = 'auteur="'.utf8_encode($ligne[$c]).'"';
                                                                        $nom['annee'] = 'annee=""';
                                                                }
                                                        } else {
                                                                foreach ($this->correspondance_colonnes[$this->noms_colonnes[$c]] as $a=>$nom_colonne) {
                                                                        $nom[$nom_colonne] = $nom_colonne.'="'.$ligne[$c].'"';
                                                                }
                                                        }
                                                } elseif ($this->correspondance_colonnes[$this->noms_colonnes[$c]] == "") {
                                                        $nom[$this->noms_colonnes[$c]] = $ligne[$c];
                                                } else {
                                                        if ($this->correspondance_colonnes[$this->noms_colonnes[$c]] == "rang") {
                                                                $rang = $this->rangs_bdnt_taxref[$ligne[$c]];
                                                                // à remettre si on décide de prendre les rangs taxref
                                                                //$nom[$this->correspondance_colonnes[$this->noms_colonnes[$c]]] = 
                                                                        //$this->correspondance_colonnes[$this->noms_colonnes[$c]].'="'.$this->rangs_bdnt_taxref[$ligne[$c]].'"';
                                                        } elseif ($this->correspondance_colonnes[$this->noms_colonnes[$c]] == "num_nom") {
                                                                $num_nom = $ligne[$c];
                                                                $nom[$this->correspondance_colonnes[$this->noms_colonnes[$c]]] = 
                                                                        $this->correspondance_colonnes[$this->noms_colonnes[$c]].'="'.$ligne[$c].'"';
                                                        } elseif ($this->correspondance_colonnes[$this->noms_colonnes[$c]] == "nom_sci") {
                                                                $nom_sci = $ligne[$c];
                                                                $nom[$this->correspondance_colonnes[$this->noms_colonnes[$c]]] =
                                                                        $this->correspondance_colonnes[$this->noms_colonnes[$c]].'="'.trim($ligne[$c]).'"';
                                                        } else  {
                                                                $nom[$this->correspondance_colonnes[$this->noms_colonnes[$c]]] = 
                                                                        $this->correspondance_colonnes[$this->noms_colonnes[$c]].'="'.trim(utf8_encode($ligne[$c])).'"';
                                                        }
                                                }
                                        }
                                }
                                $nom['exclure_taxref'] = 'exclure_taxref="0"';
                                $donnees[$num_nom] = $nom;
                                $correspondance_taxref_bdnt[$nom['CD_NOM']] = $num_nom;
                        }
                        fclose($pointeur);
                        $donnees = $this->changerNumerotation($donnees, $correspondance_taxref_bdnt, $taxref);
                }
                return $donnees;
        }
        
        private function changerNumerotation($donnees, $correspondance, $taxref) {
                $i=0;$j=0;$k=0;
                foreach ($donnees as $num_nom=>$infos) {
                        if (isset($correspondance[$infos['CD_SUP']])) {
                                $donnees[$num_nom]['num_tax_sup'] = "num_tax_sup=".$correspondance[$infos['CD_SUP']];
                                $i++;
                        } elseif ($infos['CD_SUP'] != '') {
                                $donnees[$num_nom]['num_tax_sup'] = "num_tax_sup=''";
                                //$sup[$infos['CD_NOM']] = $taxref[$infos['CD_NOM']];
                                $sup[$infos['CD_SUP']] = $infos['CD_SUP'];
                        }
                        unset($donnees[$num_nom]['CD_SUP']);
                        if (isset($correspondance[$infos['CD_REF']])) {
                                $donnees[$num_nom]['num_nom_retenu'] = "num_nom_retenu=".$correspondance[$infos['CD_REF']];
                                $j++;
                        } elseif ($infos['CD_REF'] != '') {$k++;
                                $donnees[$num_nom]['num_nom_retenu'] = "num_nom_retenu=''";
                                //$ref[$infos['CD_NOM']] = $taxref[$infos['CD_NOM']];
                                $ref[$infos['CD_REF']] = $infos['CD_REF'];
                        } else {
                                Debug::printr($infos['CD_NOM']."n'a pas de valeur pour CD_REF");
                        }
                        unset($donnees[$num_nom]['CD_REF']);
                        $donnees[$num_nom]['CD_NOM'] = 'CD_NOM='.$donnees[$num_nom]['CD_NOM'];
                }echo "les ".count($sup)." taxons supérieurs manquants :".implode(" ,", $sup)." \nles "."retenus ".implode(" ,", $ref);
                //$this->ecrireFichierCsv($ref, './retenu_absent.csv');
                //$this->ajouterTaxonAbsent($abs);
                //$this->ecrireFichierCsv($sup, './superieur_absent.csv');
                echo "$j correspondance pour nom retenu $i correspondance pour nom sup $k non pas de correspondance retenu";
                return $donnees;
        }
        
        // rechercher dans reftax les numéros absent dans la base
        // modifier les tableaux ref et sup pour modifier $donnees (ajout + modif)
        private function ajouterTaxonAbsent($abs) {
                $requete = "SELECT ".implode(",", $this->noms_colonnes)." FROM taxref_v5 where CD_NOM IN (".implode(",", $abs).")";
                echo $requete;
        }
        
        private function creerCorrespondanceRangBdntTaxref() {
                $rangs = explode(',', $this->manuel['rangs_bdnt_taxref']);
                foreach ($rangs as $rang) {
                        list($id_bdnt, $code_taxref) = explode(':', trim($rang));
                        $this->rangs_bdnt_taxref[$code_taxref] = $id_bdnt;
                }
        }
        
// +-------------------------------------------------------------------------------------------------------------------+
        private function decouperNomSciTaxRef() {
                $requete = "SELECT num_nom, nom_sci, rang, type_epithete FROM {$this->referentiel}_taxref WHERE CD_NOM != ''";
                $resultats = $this->executerRequeter($requete);
                foreach ($resultats as $nom) {
                        extract($nom);
                        $nomen =array('nom_supra_generique' => 'nom_supra_generique=""', 'genre' => 'genre=""', 
                                'epithete_infra_generique' => 'epithete_infra_generique=""', 'epithete_sp' => 'epithete_sp=""', 
                                'type_epithete' => 'type_epithete=""', 'epithete_infra_sp' => 'epithete_infra_sp=""', 
                                'cultivar_groupe' => 'cultivar_groupe=""', 'cultivar' => 'cultivar=""', 'nom_commercial' => 'nom_commercial=""');
                        $parties_noms = explode(' ', $nom_sci);
                        if ($rang < 220) {
                                $nomen['nom_supra_generique'] = 'nom_supra_generique="'.$nom_sci.'"';
                        } elseif ($rang == 220) {
                                $nomen['genre'] = 'genre="'.trim($nom_sci).'"';
                        } elseif ($rang < 290) {
                                $nomen['genre'] = 'genre="'.$parties_noms[0].'"';
                                $nomen['epithete_infra_generique'] = 'epithete_infra_generique="'.$parties_noms[1].'"';
                        } else {
                                $nomen = array_merge($nomen, $this->decouperEspece($parties_noms));
                                $hybride = $this->etreHybride($parties_noms);
                                if (isset($parties_noms[2]) && ($hybride === false || $hybride > 2)) {
                                        $nomen = array_merge($nomen, $this->decouperSousEspece($parties_noms));
                                }
                        }
                        $update = "UPDATE {$this->referentiel}_taxref SET ".implode(' , ', $nomen)." WHERE num_nom = ".$num_nom;
                        $resultat = $this->executerRequeter($update);
                }
                return $nomen;
        }
        
        private function decouperSousEspece($parties_noms) {
                if ($this->etreTypeSousEpithete($parties_noms[2]) == true) {
                        $nomen['type_epithete'] = 'type_epithete="'.$parties_noms[2].'"';
                        $nomen['epithete_infra_sp'] = 'epithete_infra_sp="'.$parties_noms[3].'"';
                } elseif (strpos($parties_noms[2], '(') === 0) {
                        $nomen['cultivar_groupe'] = 'cultivar_groupe="'.trim($parties_noms[2], "(").'"';
                } elseif (strpos($parties_noms[2], "'") === 0) {
                        $nomen['cultivar'] = 'cultivar="'.trim($parties_noms[2], "'").'"';
                } elseif (ctype_upper($parties_noms[2]) === true) {
                        $nomen['nom_commercial'] = 'nom_commercial="'.$parties_noms[2].'"';
                } else {
                        $nomen['epithete_infra_sp'] = 'epithete_infra_sp="'.$parties_noms[2].'"';
                }
                return $nomen;
        }
        
        private function etreTypeSousEpithete($chaine) {
                $type = false;
                $types_epithete = array('subsp.', 'infra-sp.', 'var.', 'subvar.', 'f.', 'subf.', 'f. sp.', 'race', 'proles');
                if (in_array(utf8_encode($chaine), $types_epithete)) {
                        $type = true;
                }
                return $type;
        }
        
        private function decouperEspece($parties_noms) {
                $nomen['genre'] = 'genre="'.$parties_noms[0].'"';
                $nomen['epithete_sp'] = 'epithete_sp="'.$parties_noms[1].'"';
                $hybride = $this->etreHybride($parties_noms);
                $chimere = array_search('+', $parties_noms);
                if ($hybride != false || $hybride===0) {
                        $nomen = $this->decouperEspeceHybride($hybride, $parties_noms);
                }
                return $nomen;
        }
        
        private function etreHybride($parties_noms) {
                $hybride = array_search('x', $parties_noms);
                return $hybride;
        }
        
        private function decouperEspeceHybride($hybride, $parties_noms) {
                if ($hybride == 0) {
                        $nomen['genre'] = 'genre="'.$parties_noms[0].' '.$parties_noms[1].'"';
                        $nomen['epithete_sp'] = 'epithete_sp="'.$parties_noms[2].'"';
                } elseif ($hybride == 1 && count($parties_noms) == 4) {
                        $nomen['genre'] = 'genre="'.$parties_noms[0].' '.$parties_noms[1].' '.$parties_noms[2].'"';
                        $nomen['epithete_sp'] = 'epithete_sp="'.$parties_noms[3].'"';
                } elseif ($hybride == 1 && count($parties_noms) == 3) {
                        $nomen['genre'] = 'genre="'.$parties_noms[0].'"';
                        $nomen['epithete_sp'] = 'epithete_sp="'.$parties_noms[1].' '.$parties_noms[2].'"';
                } elseif ($hybride == 2) {
                        $nomen['genre'] = 'genre="'.$parties_noms[0].'"';
                        $nomen['epithete_sp'] = 'epithete_sp="'.$parties_noms[1].' '.$parties_noms[2].' '.$parties_noms[3].'"';
                }
                return $nomen;
        }
        
// +-------------------------------------------------------------------------------------------------------------------+
        private function ecrireFichierCsv(&$contenu, $fichier) {
                $retour = true;
                $fichier = fopen($fichier, "w");
                fputcsv($fichier, $this->noms_colonnes, chr('9'));
                foreach ($contenu as $ligne) {
                        if (fputcsv($fichier, $ligne, chr('9')) == false) {
                                $e = "Une erreur est survenu lors de l'écriture du fichier : $fichier";
                                Debug::printr($e);
                                $retour = false;
                        }
                }
                $contenu = null;
                return $retour;
        }
        
        
        private function connecterPDO() {
                Config::charger('./configurations/bdd.ini');
                try {
                        $dsn = Config::get('bdd_type').':dbname='.Config::get('bdd_nom').';host='.
                                Config::get('bdd_hote');
                        //$dsn = "mysql:dbname=referentiels;host=localhost";
                        $this->bdd = new PDO($dsn, Config::get('bdd_utilisateur'), Config::get('bdd_mot_de_passe'));
                } catch (PDOException $e) {
                        print_r($e);
                        echo 'La connexion à la base de donnée via PDO a échouée : ' . $e->getMessage();
                }
                // Passe en UTF-8 la connexion à la BDD
                $this->bdd->exec("SET NAMES 'utf8'");
                // Affiche les erreurs détectées par PDO (sinon mode silencieux => aucune erreur affiché)
                $this->bdd->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        }
        
        protected function executerRequeter($requete) {
                $infos = null;
                try {
                        $infos = $this->bdd->query($requete);
                        if ($infos === false) {
                                echo $requete;
                        }
                } catch (PDOException $e) {
                        echo sprintf($e->getFile(), $e->getLine(), $e->getMessage(), $e->getCode(), $requete);
                }
                return $infos;
        }
}
?>