Subversion Repositories Applications.referentiel

Rev

Rev 263 | Rev 266 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

<?php
// Encodage : UTF-8
// +-------------------------------------------------------------------------------------------------------------------+
/**
* Tests de référentiels de nomenclature et taxonomie
*
* Description : classe permettant de tester les référentiels selon le manuel technique
* Utilisation : php script.php tests -p bdnff -a tout
*
//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$
*/
// +-------------------------------------------------------------------------------------------------------------------+
// TODO : supprimer l'utilisation du paramêtres 'p' et chercher les infos depuis la bdd
class Tests extends ScriptCommande {
        
        const SCRIPT_NOM = 'tests';
        const MANUEL_VERSION = '4.3';
        
        private $projet = null;
        private $traitement = null;
        
        private $manuel = null;
        private $manuel_nom = null;
        private $manuel_chemin = null;
        private $tests = null;
        private $colonnes = null;
        private $analyses = null;
        private $noms = null;
        
        private $resultatDao = null;
        private $traitementDao = null;
        private $tableStructureDao = null;
        private $referentielDao = null;
        
        public function executer() {
                $this->manuel_nom = 'mtpr_v'.str_replace('.', '_', self::MANUEL_VERSION).'.pdf';
                $this->manuel_chemin = Config::get('chemin_appli').DS.'..'.DS.'configurations'.DS;
                
                $manuel_config_nom = 'referentiel_v'.self::MANUEL_VERSION.'.ini';
                $this->manuel = parse_ini_file($this->manuel_chemin.$manuel_config_nom);
                
                $this->definirConstantes();
                $this->tests = parse_ini_file($this->getModuleChemin().DS.'configurations'.DS.'tests.ini', true);
                
                $this->resultatDao = new ResultatDao();
                $this->traitementDao = new TraitementDao();
                Debug::printr('Dans le script test');
                // Récupération du dernier traitement demandé
                $this->traitement = $this->traitementDao->getDernierTraitement('tout', self::SCRIPT_NOM);
                if (isset($this->traitement)) {
                        $this->projet = $this->traitement['referentiel_code']; // Récupération du nom de projet
                        Debug::printr($this->traitement);
                        // Écriture de la date de début du traitement
                        Debug::printr('Debute:'.$this->traitementDao->debuterTraitement($this->traitement['id_traitement']));
                        
                        // Nettoyage des traitements obsolètes
                        $traitements_obsoletes = $this->traitementDao->getTraitementsObsoletes($this->projet, self::SCRIPT_NOM);
                        if (isset($traitements_obsoletes)) {
                                Debug::printr('Supp. obsoletes:'.$this->traitementDao->supprimer($traitements_obsoletes));
                        }
                        
                        $this->tableStructureDao = new TableStructureDao();
                        $this->referentielDao = new ReferentielDao();
                        
                        // Lancement du test demandé
                        $cmd = $this->getParam('a');
                switch ($cmd) {
                                case 'tout' :
                                        Debug::printr('Départ lancement test:');
                                        $this->recupererDonnees();
                                        $this->lancerTestsAuto();
                                        break;
                                case 'test11' :
                                        $this->recupererDonnees();
                                        Debug::printr('Départ lancement test 11 :');
                                        $this->testerExitenceTaxonSuperieurTransmis();
                                        break;
                                default :
                                        $this->traiterErreur('Erreur : la commande "%s" n\'existe pas!', array($cmd));
                        }
                        // Écriture de la date de fin du traitement
                        Debug::printr('Termine:'.$this->traitementDao->terminerTraitement($this->traitement['id_traitement']));
                } else {
                        Debug::printr("Aucun dernier traitement trouvé pour le script '".self::SCRIPT_NOM."' !");
                }
    }
    
    /**
     * Cette méthode définie des constantes qui peuvent ensuite être utilisée dans les fichier ini.
     * Surtout utile pour le fichier tests.ini
     */
    private function definirConstantes() {
        define('RANG_GENRE', $this->manuel['rang_genre']);
        define('RANG_SP', $this->manuel['rang_sp']);
        date_default_timezone_set('Europe/Berlin');
        define('ANNEE_EN_COURS', date('Y'));
        define('ANNEE_MINIMUM', 1753);
    }
    
    public function recupererDonnees() {
                // Récupération des données à tester
                $this->colonnes = $this->tableStructureDao->getColonnes($this->projet);
                $this->analyses = $this->tableStructureDao->getAnalyse($this->projet);
                $this->noms = $this->referentielDao->getTout($this->projet);
                Debug::printr('Nbre noms :'.count($this->noms));
    }
    
    public function lancerTestsAuto() {
                $resultats = array();

                // Lancement des tests unitaires
                Debug::printr('Lancement des tests unitaires');
                $tests_numeros = array_keys($this->tests);
                Debug::printr($tests_numeros);
        foreach ($tests_numeros as &$numero) {
                        $info = $this->getInfosTest($numero);
                
                if ($numero < 5) {
                        // Tests spéciaux vérifiant la structure de la table
                        $resultats[] = $this->lancerTestUnitaire($info);
                } else if ($numero >= 5 && $this->verifierResultats($resultats)) {              
                                // Si la structure est bonne nous lançons les autres tests
                                $this->lancerTestUnitaire($info);
                }
                }
    }
        
    private function getInfosTest($numero) {
                $info = $this->tests[$numero];
                $info['methode'] = 'tester'.implode('', explode(' ', ucwords($info['abr'])));
                $info['numero'] = $numero;
                $info['nom'] = '#'.$numero.' - '.$info['nom'];
                $info['resultat'] = false;
                return $info;
        }
    
    public function lancerTestUnitaire($info) {
                Debug::printr($info['numero'].'::'.$info['methode']);
        $methodeDeTest = $info['methode'];
        $erreurs = $this->$methodeDeTest();
        
        // Analyse des résultats
        if (isset($erreurs['special'])) {
                $info = $erreurs;
        } else {
                if (count($erreurs) > 0) {
                                $info['message']['entete'] = explode(',', $info['entete']);
                                if (isset($info['title'])) {
                                        $info['message']['title'] = explode(';', $info['title']);
                                }
                                $info['message']['lignes'] = $erreurs;
                                unset($erreurs);
                        } else {
                                $info['resultat'] = true;
                        }
        }
        
                $this->traiterResultatTest($info);
                
                if ($info['numero'] < 5) {
                        return ($info['resultat'] ? '1' : '0');
                }
    }
        
        private function verifierResultats(&$resultats) {
                $ok = true;
                foreach ($resultats as $resultat) {
                        if ($resultat == '0') {
                                $ok = false;
                                break;
                        }
                }
                return $ok;
        }
        
        private function traiterResultatTest($info) {
                if (isset($info['message'])) {
                        if (is_array($info['message'])) {
                                $erreurs_nbre = count($info['message']['lignes']);
                                $erreurs_max = 1000;
                                if ($erreurs_nbre > $erreurs_max) {
                                        $info['message']['lignes'] = array_slice($info['message']['lignes'], 0, $erreurs_max);
                                        $info['erreur'] = "$erreurs_nbre erreurs ont été détectées seules les $erreurs_max premières sont affichées";
                                }
                                $info['message'] = $this->getVue('tests/squelettes/message_table', $info);
                        } else {
                                $info['message'] = $this->getVue('tests/squelettes/message_p', $info);
                        }
                }
                Debug::printr($this->resultatDao->ajouter($this->traitement['id_traitement'], $info));
                $info = null;
        }
        
        //+--------------------------------------------------------------------------------------------------------------+//
        // TESTS
        
        /**
         * Test #01
         */
        private function testerNombreDeChamps() {
                $info = $this->getInfosTest(1);
                $info['special'] = true;
                
                $nbre_colonnes = count($this->colonnes);
                $info['message'] = $nbre_colonnes;
                if ($nbre_colonnes >= 35) {
                        $info['resultat'] = true;
                }
                
                return $info;
        }
        
        /**
         * Test #02
         */
        private function testerNomDesChamps() {
                $info = $this->getInfosTest(2);
                $info['special'] = true;
                
                $champs_attendus = explode(',', $this->manuel['champs']);
                $champs_presents = array();
                foreach ($this->colonnes as &$colonne) {
                        $champs_presents[$colonne['Field']] = $colonne;
                }
                
                $ok = true;
                $champs_manquant = array(); 
                foreach ($champs_attendus as &$champ_attendu) {
                        if (!isset($champs_presents[$champ_attendu])) {
                                $champs_manquant[] = $champ_attendu; 
                                $ok = false;
                        }
                }
                
                $info['resultat'] = $ok;
                if (!$ok) {
                        $info['message'] = sprintf($info['message'], implode(', ', $champs_manquant));
                }
                
                return $info;
        }
        
        /**
         * Test #03
         */
        private function testerTypeDesChamps() {
                $champs_attendus = explode(',', $this->manuel['champs_type']);
                $champs_presents = array();
                foreach ($this->colonnes as &$colonne) {
                        $champs_presents[$colonne['Field']] = $colonne['Type'];
                }
                
                // Recercherche des erreurs
                $champs_erreur = array(); 
                foreach ($champs_attendus as &$champ_attendu) {
                        list($champ_attendu_nom, $champ_attendu_type_taille) = explode('=', trim($champ_attendu));
                        list($champ_attendu_type, $champ_attendu_taille) = explode('|', trim($champ_attendu_type_taille));
                        
                        if (isset($champs_presents[$champ_attendu_nom])) {
                                $champs_present_type = $champs_presents[$champ_attendu_nom];
                                
                                if (($champ_attendu_type == 'VARCHAR' && strstr($champs_present_type, 'varchar') === false)
                                        || ($champ_attendu_type == 'TEXT' && strstr($champs_present_type, 'text') === false)
                                        || ($champ_attendu_type == 'INT' && strstr($champs_present_type, 'int') === false) 
                                        || ($champ_attendu_type == 'BOOL' && preg_match('/(?:bool|boolean|tinyint\(1\))/i', $champs_present_type) === false)) {
                                        $champs_erreur[] = array($champ_attendu, $champ_attendu_type, $champs_present_type);
                                }
                        }
                }
                return $champs_erreur;
        }
        
        /**
         * Test #04
         */
        private function testerNumNomClePrimaire() {
                $info = $this->getInfosTest(4);
                $info['special'] = true;
                
                foreach ($this->colonnes as &$colonne) {
                        if ($colonne['Field'] == 'num_nom' && $colonne['Key'] == 'PRI') {
                                $info['resultat'] = true;
                                break;
                        }
                }
                return $info;
        }
        
        
        /**
         * Test #05
         */
        private function testerTailleDesChamps() {
                $tailles_champs_maxi = array();
                foreach ($this->colonnes as &$colonne) {
                        if (preg_match('/^varchar\(([0-9]+)\)$/', $colonne['Type'], $match)) {
                                $tailles_champs_maxi[$colonne['Field']] = $match[1];
                        }
                }
                
                $tailles_trouvees = array();
                foreach ($this->analyses as &$analyse) {
                        if (preg_match('/\.([^.]+)$/', $analyse['Field_name'], $match)) {
                                $tailles_trouvees[$match[1]] = $analyse['Max_length'];
                        }
                }
                
                $champs_erreur = array();
                $champs_attendus = explode(',', $this->manuel['champs']);
                foreach ($champs_attendus as &$champ_attendu) {
                        if (isset($tailles_champs_maxi[$champ_attendu]) && isset($tailles_trouvees[$champ_attendu])) {
                                if ($tailles_champs_maxi[$champ_attendu] == $tailles_trouvees[$champ_attendu]) {
                                        $champs_erreur[] = array($champ_attendu, $tailles_champs_maxi[$champ_attendu], $tailles_trouvees[$champ_attendu]);
                                }
                        }
                }
                return $champs_erreur;
        }
                
        /**
         * Test #06
         */
        private function testerNumNomSuperieurAZero() {
                $noms_erreur = array();
                foreach ($this->noms as &$nom) {
                        if ($nom['num_nom'] <= 0) {
                                $noms_erreur[] = array($nom['num_nom']);
                        }
                }
                return $noms_erreur;
        }
        
        /**
         * Test #07
         */
        private function testerNumNomRetenuSuperieurAZero() {
                $noms_erreur = array();
                foreach ($this->noms as &$nom) {
                        if ($nom['num_nom_retenu'] != '' && $nom['num_nom_retenu'] <= 0) {
                                $noms_erreur[] = array($nom['num_nom'], $nom['num_nom_retenu']);
                        }
                }
                return $noms_erreur;
        }
        
        /**
         * Test #08
         */
        private function testerExistenceNumNomRetenu() {
                $noms_erreur = array();
                foreach ($this->noms as &$nom) {
                        if ($nom['num_nom_retenu'] != '' && $nom['num_nom_retenu'] != $nom['num_nom']) {
                                if ($nom['num_nom_retenu'] != 0 && !isset($this->noms[$nom['num_nom_retenu']])) {
                                        $noms_erreur[] = array($nom['num_nom'], $nom['num_nom_retenu'], $nom['exclure_taxref']);
                                } 
                        }
                }
                return $noms_erreur;
        }
        
        /**
         * Test #09
         */
        private function testerTransmissionNumNomRetenu() {
                $noms_erreur = array();
                foreach ($this->noms as &$nom) {
                        if ($nom['num_nom_retenu'] != $nom['num_nom'] && $nom['exclure_taxref'] == 0) {
                                if ($nom['num_nom_retenu'] != 0 && isset($this->noms[$nom['num_nom_retenu']])) {
                                        if ($this->noms[$nom['num_nom_retenu']]['exclure_taxref'] != 0) {
                                                $noms_erreur[] = array($nom['num_nom'], $nom['num_nom_retenu'], $this->noms[$nom['num_nom_retenu']]['exclure_taxref']);
                                        }
                                } 
                        }
                }
                return $noms_erreur;
        }
        
        /**
         * Test #10
         */
        private function testerSynonymeNumNomRetenu() {
                $noms_erreur = array();
                foreach ($this->noms as &$nom) {
                        if ($nom['num_nom_retenu'] != $nom['num_nom']) {
                                if ($nom['num_nom_retenu'] != 0 && isset($this->noms[$nom['num_nom_retenu']])) {
                                        if ($this->noms[$nom['num_nom_retenu']]['num_nom'] != $this->noms[$nom['num_nom_retenu']]['num_nom_retenu']) {
                                                $noms_erreur[] = array($nom['num_nom'], $nom['num_nom_retenu'], $this->noms[$nom['num_nom_retenu']]['num_nom_retenu']);
                                        }
                                } 
                        }
                }
                return $noms_erreur;
        }
        
        
        /**
         * Test #11
         */
        private function testerNumTaxSupEgalZeroUnique() {
                $noms_erreur = array();
                foreach ($this->noms as &$nom) {
                        if (preg_match('/^0$/', $nom['num_tax_sup'])) {
                                $noms_erreur[] = array($nom['num_nom'], $nom['num_tax_sup']);
                        }
                }
                // Ce test est spécial car le nombre de noms en erreurs doit être supérieur à 1 et non à 0 pour être KO.
                if (count($noms_erreur) == 1) {
                        $noms_erreur = array();
                }
                return $noms_erreur;
        }
        
        /**
         * Test #12
         */
        private function testerTaxSupPourTaxon() {
                $noms_erreur = array();
                foreach ($this->noms as &$nom) {
                        if ($nom['num_nom_retenu'] != $nom['num_nom'] && $nom['num_tax_sup'] != '') {
                                $noms_erreur[] = array($nom['num_nom'], $nom['num_tax_sup'], $nom['exclure_taxref']); 
                        }
                }
                return $noms_erreur;
        }
        
        /**
         * Test #13
         */
        private function testerExistenceTaxonSuperieur() {
                $noms_erreur = array();
                foreach ($this->noms as &$nom) {
                        if ($nom['num_nom_retenu'] == $nom['num_nom']) {
                                if ($nom['num_tax_sup'] != 0 && !isset($this->noms[$nom['num_tax_sup']])) {
                                        $noms_erreur[] = array($nom['num_nom'], $nom['num_tax_sup'], $nom['exclure_taxref']);
                                } 
                        }
                }
                return $noms_erreur;
        }
        
        /**
         * Test #14
         */
        private function testerTransmissionTaxonSuperieur() {
                $noms_erreur = array();
                foreach ($this->noms as &$nom) {
                        if ($nom['num_nom_retenu'] == $nom['num_nom'] && $nom['exclure_taxref'] == 0) {
                                if ($nom['num_tax_sup'] != 0 && isset($this->noms[$nom['num_tax_sup']])) {
                                        if ($this->noms[$nom['num_tax_sup']]['exclure_taxref'] != 0) {
                                                $noms_erreur[] = array($nom['num_nom'], $nom['num_tax_sup'], $this->noms[$nom['num_tax_sup']]['exclure_taxref']);
                                        }
                                } 
                        }
                }
                return $noms_erreur;
        }
        
        
        /**
         * Test #15
         */
        private function testerClassificationRang() {
                $noms_erreur = array();
                foreach ($this->noms as &$nom) {
                        if ($nom['num_nom_retenu'] == $nom['num_nom']) {
                                if (isset($this->noms[$nom['num_tax_sup']])) {
                                        $nom_sup = $this->noms[$nom['num_tax_sup']];
                                        if ($nom_sup['rang'] >= $nom['rang']) {
                                                // Prise en compte de l'exception des clades
                                                if (! ($nom_sup['rang'] == 70 && $nom['rang'] == 70)) {
                                                        $noms_erreur[] = array($nom['num_nom'], $nom['rang'], $nom_sup['num_nom'], $nom_sup['rang'], $nom['exclure_taxref']);
                                                }
                                        }
                                }
                        }
                }
                return $noms_erreur;
        }
        
        /**
         * Test #16
         */
        private function testerClassification() {
                $noms_erreur = array();
                $this->noms_ok = array();
                foreach ($this->noms as &$nom) {
                        if ($nom['num_nom_retenu'] == $nom['num_nom']) {
                                if (isset($this->noms_ok[$nom['num_tax_sup']])) {
                                        $this->noms_ok[$nom['num_nom']] = true;
                                } else {
                                        $this->detection_boucle_infini = array();
                                        $classif_ok = $this->remonterClassif($nom);
                                        unset($this->detection_boucle_infini); 
                                        
                                        if ($classif_ok === true) {
                                                $this->noms_ok[$nom['num_nom']] = $classif_ok;
                                        } else {
                                                $noms_erreur[] = array($nom['num_nom'], $classif_ok, $nom['exclure_taxref']);
                                        }
                                }
                        }
                }
                unset($this->noms_ok);
                return $noms_erreur;
        }
        
        private function remonterClassif(&$nom) {
                $this->detection_boucle_infini[$nom['num_nom']] = true;
                if (preg_match('/^[0-9]*$/', $nom['num_tax_sup'])) {
                        if (isset($this->noms_ok[$nom['num_tax_sup']])) {
                                $this->noms_ok[$nom['num_nom']] = true;
                                return true;
                        } else if (!isset($this->noms[$nom['num_tax_sup']]) && $nom['num_tax_sup'] == '0') {
                                $this->noms_ok[$nom['num_nom']] = true;
                                return true;
                        } else if (!isset($this->noms[$nom['num_tax_sup']]) && $nom['num_tax_sup'] != '0') {
                                return 'Hiérarchie avec le taxon #'.$nom['num_nom'].' ayant un taxon superieur #'.$nom['num_tax_sup'].' inexistant';
                        } else if (isset($this->detection_boucle_infini[$nom['num_tax_sup']])) {
                                return 'Boucle infinie pour le taxon #'.$nom['num_tax_sup'];
                        } else {
                                $retour = $this->remonterClassif($this->noms[$nom['num_tax_sup']]);
                                if ($retour === true) {
                                        $this->noms_ok[$nom['num_tax_sup']] = true;
                                }
                                return $retour;
                        }
                } else {
                        return 'Valeur num_tax_sup incorrecte : '.$nom['num_tax_sup'];
                }
        }
        
        /**
         * Test #17
         */
        private function testerRang() {
                $rangs = array_flip(explode(',', $this->manuel['rangs']));
                
                // Réalisation du test
                $noms_erreur = array();
                foreach ($this->noms as &$nom) {
                        if (!isset($rangs[$nom['rang']])) {
                                $noms_erreur[] = array($nom['num_nom'], $nom['rang'], $nom['exclure_taxref']);
                        }
                }
                return $noms_erreur;
        }
        
        /**
         * Test #18
         */
        private function testerNomCompletSupraGenerique() {
                $noms_erreur = array();
                foreach ($this->noms as &$nom) {
                        if ($nom['rang'] < $this->manuel['rang_genre']) {
                                $suffixe_plte_cultivee = $this->construireSuffixeNomPltCultivee($nom);
                                $nom_sci_ideal = $this->formaterStyleNomGenre($nom['nom_supra_generique']);
                                $nom_sci_ideal .= ($suffixe_plte_cultivee != '' ? ' '.$suffixe_plte_cultivee : '');
                                if ($nom['nom_sci'] != $nom_sci_ideal) {
                                        $nom_sci_traite = $this->repererEspace($nom['nom_sci']);
                                        $noms_erreur[] = array($nom['num_nom'], $nom_sci_traite, $nom_sci_ideal, $nom['exclure_taxref']);
                                }
                        }
                }
                return $noms_erreur;
        }
        
        /**
         * Test #19
         */
        private function testerNomCompletGenre() {
                $noms_erreur = array();
                foreach ($this->noms as &$nom) {
                        if ($nom['rang'] == $this->manuel['rang_genre']) {
                                $suffixe_plte_cultivee = $this->construireSuffixeNomPltCultivee($nom);
                                $nom_sci_ideal = $this->formaterStyleNomGenre($nom['genre']);
                                $nom_sci_ideal .= ($suffixe_plte_cultivee != '' ? ' '.$suffixe_plte_cultivee : '');
                                if ($nom['nom_sci'] != $nom_sci_ideal) {
                                        $nom_sci_traite = $this->repererEspace($nom['nom_sci']);
                                        $noms_erreur[] = array($nom['num_nom'], $nom_sci_traite, $nom_sci_ideal, $nom['exclure_taxref']);
                                }
                        }
                }
                return $noms_erreur;
        }
        
        /**
         * Test #20
         */
        private function testerNomCompletInfraGenre() {
                $noms_erreur = array();
                foreach ($this->noms as &$nom) {
                        if ($nom['rang'] > $this->manuel['rang_genre'] && $nom['rang'] < $this->manuel['rang_sp']) {
                                $suffixe_plte_cultivee = $this->construireSuffixeNomPltCultivee($nom);
                                $nom_sci_ideal = '';
                                if ($nom['type_epithete'] == 'agg.') {
                                        $nom_sci_ideal = $this->formaterStyleNomGenre($nom['genre']).' '.
                                                $this->formaterStyleNomGenre($nom['epithete_infra_generique']).' '.
                                                $nom['type_epithete'];
                                } else {
                                        $nom_sci_ideal = $this->formaterStyleNomGenre($nom['genre']).' '.
                                                $nom['type_epithete'].' '.
                                                $this->formaterStyleNomGenre($nom['epithete_infra_generique']);
                                }
                                $nom_sci_ideal .= ($suffixe_plte_cultivee != '' ? ' '.$suffixe_plte_cultivee : '');
                                if ($nom['nom_sci'] != $nom_sci_ideal) {
                                        $nom_sci_traite = $this->repererEspace($nom['nom_sci']);
                                        $noms_erreur[] = array($nom['num_nom'], $nom_sci_traite, $nom_sci_ideal, $nom['exclure_taxref']);
                                }
                        }
                }
                return $noms_erreur;
        }
        
        /**
         * Test #21
         */
        private function testerNomCompletEspece() {
                $noms_erreur = array();
                $erreur = '';
                foreach ($this->noms as &$nom) {
                        if ($nom['rang'] == $this->manuel['rang_sp']) {
                                $suffixe_plte_cultivee = $this->construireSuffixeNomPltCultivee($nom);
                                $nom_sci_ideal = $this->formaterStyleNomGenre($nom['genre']).' ';
                                if (strstr($nom['nom_sci'] , ' x ') != false) {
                                        list($nom_sci_ideal, $erreur) = $this->formaterStyleEpitheteSpHybride($nom_sci_ideal, $nom['epithete_sp']);
                                } else {
                                        $nom_sci_ideal .= utf8_encode(strtolower(utf8_decode($nom['epithete_sp'])));
                                }
                                $nom_sci_ideal .= ($suffixe_plte_cultivee != '' ? ' '.$suffixe_plte_cultivee : '');
                                $nom_sci_ideal = trim($nom_sci_ideal);
                                if ($nom['nom_sci'] != $nom_sci_ideal) {
                                        $nom_sci_traite = $this->repererEspace($nom['nom_sci']);
                                        $noms_erreur[] = array($nom['num_nom'], $nom_sci_traite, $nom_sci_ideal, $erreur, $nom['exclure_taxref']);
                                }
                        }
                }
                return $noms_erreur;
        }
        
        /**
         * Test #22
         */
        private function testerNomCompletInfraSpecifique() {
                $noms_erreur = array();
                $erreur = null;
                foreach ($this->noms as &$nom) {
                        if ($nom['rang'] > $this->manuel['rang_sp']) {
                                $nom_sci_ideal = $this->formaterStyleNomGenre($nom['genre']).' '.
                                        utf8_encode(strtolower(utf8_decode($nom['epithete_sp']))).' '.
                                        utf8_encode(strtolower(utf8_decode($nom['type_epithete']))).' ';
                                $suffixe_plte_cultivee = $this->construireSuffixeNomPltCultivee($nom);
                                if (strstr($nom['nom_sci'] , ' x ') != false) {
                                        list($nom_sci_ideal, $erreur) = $this->formaterStyleEpitheteInfraSpHybride($nom_sci_ideal, $nom['epithete_infra_sp'], $nom['genre']);
                                } else {
                                        $nom_sci_ideal .= utf8_encode(strtolower(utf8_decode($nom['epithete_infra_sp'])));
                                }
                                $nom_sci_ideal = trim($nom_sci_ideal);
                                $nom_sci_ideal .= ($suffixe_plte_cultivee != '' ? ' '.$suffixe_plte_cultivee : '');
                                if ($nom['nom_sci'] != $nom_sci_ideal) {
                                        $nom_sci_traite = $this->repererEspace($nom['nom_sci']);
                                        $noms_erreur[] = array($nom['num_nom'], $nom_sci_traite, $nom_sci_ideal, $erreur, $nom['exclure_taxref']);
                                }
                        }
                }
                return $noms_erreur;
        }
        
        /**
         * Test #23
         */
        private function testerNomSupraGeneriqueEspaces() {
                $noms_erreur = array();
                foreach ($this->noms as &$nom) {
                        if ($nom['nom_supra_generique'] != '') {
                                if (preg_match('/(?:^\s+(?!:\s+)|(?!:\s+)\s+$)/', $nom['nom_supra_generique'])) {
                                        $nom_supra_generique_traite = $this->repererEspace($nom['nom_supra_generique']);
                                        $noms_erreur[] = array($nom['num_nom'], $nom_supra_generique_traite, $nom['exclure_taxref']);
                                }
                        }
                }
                return $noms_erreur;
        }
        
        /**
         * Test #24
         */
        private function testerNomSupraGeneriqueSyntaxe() {
                $noms_erreur = array();
                foreach ($this->noms as &$nom) {
                        if ($nom['nom_supra_generique'] != '') {
                                if (!preg_match('/^[A-ZÄËḦÏÖÜẄẌŸ][-a-zäëḧïöẗüẅẍÿ]+$/', $nom['nom_supra_generique'])) {
                                        $nom_supra_generique_traite = $this->repererEspace($nom['nom_supra_generique']);
                                        $noms_erreur[] = array($nom['num_nom'], $nom_supra_generique_traite, $nom['exclure_taxref']);
                                }
                        }
                }
                return $noms_erreur;
        }
        
        /**
         * Test #25
         */
        private function testerNomSupraGeneriqueRang() {
                $noms_erreur = array();
                foreach ($this->noms as &$nom) {
                        if ($nom['nom_supra_generique'] != '') {
                                if ($nom['rang'] >= $this->manuel['rang_genre']) {
                                        $noms_erreur[] = array($nom['num_nom'], $nom['nom_sci'], $nom['rang'], $nom['exclure_taxref']);
                                }
                        }
                }
                return $noms_erreur;
        }
        
        /**
         * Test #26
         */
        private function testerGenreEspaces() {
                $noms_erreur = array();
                foreach ($this->noms as &$nom) {
                        if ($nom['genre'] != '') {
                                if (preg_match('/(?:^\s+(?!:\s+)|(?!:\s+)\s{2,}(?!:\s+)|(?!:\s+)\s+$)/', $nom['genre'])) {
                                        $nom_traite = $this->repererEspace($nom['genre']);
                                        $noms_erreur[] = array($nom['num_nom'], $nom_traite, $nom['exclure_taxref']);
                                }
                        }
                }
                return $noms_erreur;
        }
        
        /**
         * Test #27
         */
        private function testerGenreSyntaxe() {
                $noms_erreur = array();
                foreach ($this->noms as &$nom) {
                        if ($nom['genre'] != '') {
                                $mots = explode(' ', $nom['genre']);
                                foreach ($mots as $mot) {
                                        if (!(preg_match('/^[+x]$/', $mot) || $this->verifierEpitheteGenre($mot))) {
                                                $nom_traite = $this->repererEspace($nom['genre']);
                                                $noms_erreur[] = array($nom['num_nom'], $nom_traite, $nom['exclure_taxref']);
                                                break;
                                        }
                                }
                        }
                }
                return $noms_erreur;
        }
        
        /**
         * Test #28
         */
        private function testerGenreRang() {
                $noms_erreur = array();
                foreach ($this->noms as &$nom) {
                        if ($nom['genre'] != '') {
                                if ($nom['rang'] < $this->manuel['rang_genre']) {
                                        $noms_erreur[] = array($nom['num_nom'], $nom['nom_sci'], $nom['rang'], $nom['exclure_taxref']);
                                }
                        }
                }
                return $noms_erreur;
        }
                
        /**
         * Test #29
         */
        private function testerEpitheteInfraGeneriqueSyntaxe() {
                $noms_erreur = array();
                foreach ($this->noms as &$nom) {
                        if ($nom['epithete_infra_generique'] != '') {
                                if (!preg_match('/^[A-ZÄËḦÏÖÜẄẌŸ][-a-zäëḧïöẗüẅẍÿ]+/', $nom['epithete_infra_generique'])) {
                                        $epithete_traite = $this->repererEspace($nom['epithete_infra_generique']);
                                        $noms_erreur[] = array($nom['num_nom'], $epithete_traite, $nom['exclure_taxref']);
                                }
                        }
                }
                return $noms_erreur;
        }
        
        /**
         * Test #30
         */
        private function testerEpitheteInfraGeneriqueRang() {
                $noms_erreur = array();
                foreach ($this->noms as &$nom) {
                        if ($nom['epithete_infra_generique'] != '') {
                                if ($nom['rang'] <= $this->manuel['rang_genre'] || $nom['rang'] >= $this->manuel['rang_sp']) {
                                        $noms_erreur[] = array($nom['num_nom'], $nom['nom_sci'], $nom['rang'], $nom['exclure_taxref']);
                                }
                        }
                }
                return $noms_erreur;
        }
        
        /**
         * Test #31
         */
        private function testerEpitheteInfraGeneriqueEspaces() {
                $noms_erreur = array();
                foreach ($this->noms as &$nom) {
                        if ($nom['epithete_infra_generique'] != '') {
                                if (preg_match('/(?:^\s+(?!:\s+)|(?!:\s+)\s{2,}(?!:\s+)|(?!:\s+)\s+$)/', $nom['epithete_infra_generique'])) {
                                        $epithete_traite = $this->repererEspace($nom['epithete_infra_generique']);
                                        $noms_erreur[] = array($nom['num_nom'], $epithete_traite, $nom['exclure_taxref']);
                                }
                        }
                }
                return $noms_erreur;
        }
        
        /**
         * Test #32
         */
        private function testerEpitheteSpEspaces() {
                $noms_erreur = array();
                foreach ($this->noms as &$nom) {
                        if ($nom['epithete_sp'] != '') {
                                if (preg_match('/(?:^\s+(?!:\s+)|(?!:\s+)\s{2,}(?!:\s+)|(?!:\s+)\s+$)/', $nom['epithete_sp'])) {
                                        $epithete_traite = $this->repererEspace($nom['epithete_sp']);
                                        $noms_erreur[] = array($nom['num_nom'], $epithete_traite, $nom['exclure_taxref']);
                                }
                        }
                }
                return $noms_erreur;
        }
        
        /**
         * Test #33
         */
        private function testerEpitheteSpSyntaxe() {
                $noms_erreur = array();
                foreach ($this->noms as &$nom) {
                        if ($nom['epithete_sp'] != '') {
                                $formule_hybridite = (strpos($nom['epithete_sp'], ' x ') !== false);
                                $mots = explode(' ', $nom['epithete_sp']);
                                foreach ($mots as $mot) {
                                        // TODO: créer un test qui vérifie la formule d'hybridité en la reconstruisant à partir des parents
                                        // afin que seuls des formules valides parviennent à la fonction
                                        if (!(preg_match('/^[+x]$/', $mot) || $this->verifierEpitheteSp($mot) ||
                                                ($formule_hybridite && $this->verifierEpitheteGenre($mot) && !$this->verifierEstAbbreviationInfraSp($mot)))) {
                                                $epithete_traite = $this->repererEspace($nom['epithete_sp']);
                                                $noms_erreur[] = array($nom['num_nom'], $epithete_traite, $nom['exclure_taxref']);
                                                break;
                                        }
                                }
                        }
                }
                return $noms_erreur;
        }
        
        /**
         * Test #34
         */
        private function testerEpitheteSpRang() {
                $noms_erreur = array();
                foreach ($this->noms as &$nom) {
                        if ($nom['epithete_sp'] != '') {
                                if ($nom['rang'] < $this->manuel['rang_sp']) {
                                        $noms_erreur[] = array($nom['num_nom'], $nom['nom_sci'], $nom['rang'], $nom['exclure_taxref']);
                                }
                        }
                }
                return $noms_erreur;
        }
        
        /**
         * Test #35
         */
        private function testerTypeEpitheteEspaces() {
                $noms_erreur = array();
                foreach ($this->noms as &$nom) {
                        if ($nom['type_epithete'] != '') {
                                if (preg_match('/\s+/', $nom['type_epithete'])) {
                                        $valeur_traitee = $this->repererEspace($nom['epithete_sp']);
                                        $noms_erreur[] = array($nom['num_nom'], $valeur_traitee, $nom['exclure_taxref']);
                                }
                        }
                }
                return $noms_erreur;
        }
        
        /**
         * Test #36
         */
        private function testerTypeEpitheteSyntaxe() {
                $noms_erreur = array();
                foreach ($this->noms as &$nom) {
                        if ($nom['type_epithete'] != '') {
                                if (!$this->verifierTypeEpithete($nom['type_epithete'])) {
                                        $noms_erreur[] = array($nom['num_nom'],  $nom['type_epithete'], $nom['exclure_taxref']);
                                }
                        }
                }
                return $noms_erreur;
        }
        
        /**
         * Test #37
         */
        private function testerTypeEpitheteHybridite() {
                $noms_erreur = array();
                foreach ($this->noms as &$nom) {
                        if ($nom['type_epithete'] != '') {
                                if (preg_match('/^(?:n-|notho-)/', $nom['type_epithete'])) {
                                        $noms_erreur[] = array($nom['num_nom'], $nom['type_epithete'], $nom['exclure_taxref']);
                                }
                        }
                }
                return $noms_erreur;
        }
        
        /**
         * Test #38
         */
        private function testerEpitheteInfraSpEspaces() {
                $noms_erreur = array();
                foreach ($this->noms as &$nom) {
                        if ($nom['epithete_infra_sp'] != '') {
                                if (preg_match('/(?:^\s+(?!:\s+)|(?!:\s+)\s{2,}(?!:\s+)|(?!:\s+)\s+$)/', $nom['epithete_infra_sp'])) {
                                        $epithete_traite = $this->repererEspace($nom['epithete_infra_sp']);
                                        $noms_erreur[] = array($nom['num_nom'], $epithete_traite, $nom['exclure_taxref']);
                                }
                        }
                }
                return $noms_erreur;
        }
        
        /**
         * Test #39
         */
        private function testerEpitheteInfraSpSyntaxe() {
                $noms_erreur = array();
                foreach ($this->noms as &$nom) {
                        if ($nom['epithete_infra_sp'] != '') {
                                $mots = explode(' ', $nom['epithete_infra_sp']);
                                $hybride_contient_abbreviation_infra_sp = false;
                                $formule_hybridite = (strpos($nom['epithete_infra_sp'], ' x ') !== false);                              
                                foreach ($mots as $mot) {
                                        if($formule_hybridite && $this->verifierEstAbbreviationInfraSp($mot)) {
                                                $hybride_contient_abbreviation_infra_sp = true;
                                        }
                                        $formule_hybridite_valide = $this->verifierEpitheteGenre($mot) || $this->verifierEpitheteSp($mot) || $hybride_contient_abbreviation_infra_sp;
                                        if (!(preg_match('/^[+x]$/', $mot) || $this->verifierTypeEpithete($mot) || $this->verifierEpitheteSp($mot) ||
                                                $formule_hybridite_valide)) {
                                                $epithete_traite = $this->repererEspace($nom['epithete_infra_sp']);
                                                $noms_erreur[] = array($nom['num_nom'], $epithete_traite, $nom['exclure_taxref']);
                                                break;
                                        }
                                }
                                
                                if($formule_hybridite && !$hybride_contient_abbreviation_infra_sp) {
                                        $epithete_traite = $this->repererEspace($nom['epithete_infra_sp']);
                                        $noms_erreur[] = array($nom['num_nom'], $epithete_traite, $nom['exclure_taxref']);
                                }
                        }
                }
                return $noms_erreur;
        }
        
        /**
         * Test #40
         */
        private function testerEpitheteInfraSpRang() {
                $noms_erreur = array();
                foreach ($this->noms as &$nom) {
                        if ($nom['epithete_infra_sp'] != '') {
                                if ($nom['rang'] < $this->manuel['rang_sp']) {
                                        $noms_erreur[] = array($nom['num_nom'], $nom['nom_sci'], $nom['rang'], $nom['exclure_taxref']);
                                }
                        }
                }
                return $noms_erreur;
        }
        
        /**
         * Test #41
         */
        private function testerGroupeCultivarSyntaxe() {
                $noms_erreur = array();
                foreach ($this->noms as &$nom) {
                        if ($nom['cultivar_groupe'] != '') {
                                if (!$this->verifierEpitheteGroupeCultivar($nom['cultivar_groupe'])) {
                                        $epithete_traite = $this->repererEspace($nom['cultivar_groupe']);
                                        $noms_erreur[] = array($nom['num_nom'], $epithete_traite, $nom['exclure_taxref']);
                                }
                        }
                }
                return $noms_erreur;
        }
        
        /**
         * Test #42
         */
        private function testerGroupeCultivarRang() {
                $noms_erreur = array();
                foreach ($this->noms as &$nom) {
                        if ($nom['cultivar_groupe'] != '') {
                                if ($nom['rang'] < $this->manuel['rang_genre']) {
                                        $noms_erreur[] = array($nom['num_nom'], $nom['nom_sci'], $nom['rang'], $nom['exclure_taxref']);
                                }
                        }
                }
                return $noms_erreur;
        }
        
        /**
         * Test #43
         */
        private function testerCultivarSyntaxe() {
                $noms_erreur = array();
                foreach ($this->noms as &$nom) {
                        if ($nom['cultivar'] != '') {
                                if (!$this->verifierEpitheteCultivar($nom['cultivar'])) {
                                        $epithete_traite = $this->repererEspace($nom['cultivar']);
                                        $noms_erreur[] = array($nom['num_nom'], $epithete_traite, $nom['exclure_taxref']);
                                }
                        }
                }
                return $noms_erreur;
        }
        
        /**
         * Test #44
         */
        private function testerCultivarRang() {
                $noms_erreur = array();
                foreach ($this->noms as &$nom) {
                        if ($nom['cultivar'] != '') {
                                if ($nom['rang'] < $this->manuel['rang_genre']) {
                                        $noms_erreur[] = array($nom['num_nom'], $nom['nom_sci'], $nom['rang'], $nom['exclure_taxref']);
                                }
                        }
                }
                return $noms_erreur;
        }
        
        /**
         * Test #45
         */
        private function testerNomCommercialSyntaxe() {
                $noms_erreur = array();
                foreach ($this->noms as &$nom) {
                        if ($nom['nom_commercial'] != '') {
                                if (!$this->verifierNomCommercial($nom['nom_commercial'])) {
                                        $epithete_traite = $this->repererEspace($nom['nom_commercial']);
                                        $noms_erreur[] = array($nom['num_nom'], $epithete_traite, $nom['exclure_taxref']);
                                }
                        }
                }
                return $noms_erreur;
        }
        
        /**
         * Test #46
         */
        private function testerNomCommercialPresenceCultivar() {
                $noms_erreur = array();
                foreach ($this->noms as &$nom) {
                        if ((isset($nom['nom_commercial']) && $nom['nom_commercial'] != '') && ($nom['cultivar'] == '' && $nom['cultivar_groupe'] == '')) {
                                $noms_erreur[] = array($nom['num_nom'], $nom['nom_sci'], $nom['exclure_taxref']);
                        }
                }
                return $noms_erreur;
        }
        
        /**
         * Test #47
         */
        private function testerAuteurSyntaxe() {
                $noms_erreur = array();
                foreach ($this->noms as &$nom) {
                        if ($nom['auteur'] != '') {
                                if (!$this->verifierAuteur($nom['auteur'])) {
                                        $intitule_traite = $this->repererEspace($nom['auteur']);
                                        $noms_erreur[] = array($nom['num_nom'], $intitule_traite, $nom['exclure_taxref']);
                                }
                        }
                }
                return $noms_erreur;
        }
        
        /**
         * Test #48
         */
        private function testerAnneeSyntaxe() {
                $noms_erreur = array();
                foreach ($this->noms as &$nom) {
                        if ($nom['annee'] != '') {
                                if (!$this->verifierAnnee($nom['annee'])) {
                                        $noms_erreur[] = array($nom['num_nom'], $nom['annee'], $nom['exclure_taxref']);
                                }
                        }
                }
                return $noms_erreur;
        }
        
        /**
         * Test #49
         */
        private function testerBiblioOrigineSyntaxe() {
                $noms_erreur = array();
                foreach ($this->noms as &$nom) {
                        if ($nom['biblio_origine'] != '') {
                                if (!$this->verifierBiblioOrigine($nom['biblio_origine'])) {
                                        $biblio_traite = $this->repererEspace($nom['biblio_origine']);
                                        $noms_erreur[] = array($nom['num_nom'], $biblio_traite, $nom['exclure_taxref']);
                                }
                        }
                }
                return $noms_erreur;
        }
        
        /**
         * Test #50
         */
        private function testerHomonymieSyntaxe() {
                $noms_erreur = array();
                foreach ($this->noms as &$nom) {
                        if ($nom['homonyme'] != '') {
                                if (!$this->verifierBooleen($nom['homonyme'])) {
                                        $noms_erreur[] = array($nom['num_nom'], $nom['homonyme'], $nom['exclure_taxref']);
                                }
                        }
                }
                return $noms_erreur;
        }
        
        /**
         * Test #51
         */
        private function testerHomonymieExistence() {
                $noms_homonymie = $this->classerNomsParNomComplet();
                
                $noms_erreur = array();
                foreach ($this->noms as &$nom) {
                        if ($nom['homonyme'] != '0' && $nom['homonyme'] != '') {
                                if ($noms_homonymie[$nom['nom_sci']] <= 1) {
                                        $noms_erreur[] = array($nom['num_nom'], $nom['nom_sci'], $nom['exclure_taxref']);
                                }
                        }
                }
                $noms_homonymie = null;
                return $noms_erreur;
        }
        
        /**
         * Test #52
         */
        private function testerBasionymeSyntaxe() {
                $noms_erreur = array();
                foreach ($this->noms as &$nom) {
                        if ($nom['basionyme'] != '') {
                                if (!$this->verifierNombre($nom['basionyme'])) {
                                        $noms_erreur[] = array($nom['num_nom'], $nom['basionyme'], $nom['exclure_taxref']);
                                }
                        }
                }
                return $noms_erreur;
        }

        /**
         * Test #53
         */
        private function testerBasionymeExistence() {
                $noms_erreur = array();
                foreach ($this->noms as &$nom) {
                        if ($nom['basionyme'] != '') {
                                if (!isset($this->noms[$nom['basionyme']])) {
                                        $noms_erreur[] = array($nom['num_nom'], $nom['basionyme'], $nom['exclure_taxref']);
                                }
                        }
                }
                return $noms_erreur;
        }
        
        /**
         * Test #54
         */
        private function testerSynonymeProparteSyntaxe() {
                $noms_erreur = array();
                foreach ($this->noms as &$nom) {
                        if ($nom['synonyme_proparte'] != '') {
                                if (!$this->verifierNombreSuite($nom['synonyme_proparte'])) {
                                        $noms_erreur[] = array($nom['num_nom'], $nom['synonyme_proparte'], $nom['exclure_taxref']);
                                }
                        }
                }
                return $noms_erreur;
        }
        
        /**
         * Test #55
         */
        private function testerSynonymeProparteExistence() {
                $noms_erreur = array();
                foreach ($this->noms as &$nom) {
                        if ($nom['synonyme_proparte'] != '') {
                                $num_nom_a_verifier = explode(',', $nom['synonyme_proparte']);
                                $num_nom_en_erreur = array();
                                foreach ($num_nom_a_verifier as $num_nom) {
                                        if (!isset($this->noms[$num_nom])) {
                                                $num_nom_en_erreur[] = $num_nom;
                                        }
                                }
                                if (count($nbre_en_erreur) > 0) {
                                        $noms_erreur[] = array($nom['num_nom'], implode(',', $num_nom_en_erreur), $nom['exclure_taxref']);
                                }
                        }
                }
                return $noms_erreur;
        }
        
        /**
         * Test #56
         */
        private function testerSynonymeDouteuxSyntaxe() {
                $noms_erreur = array();
                foreach ($this->noms as &$nom) {
                        if ($nom['synonyme_douteux'] != '') {
                                if (!$this->verifierBooleen($nom['synonyme_douteux'])) {
                                        $noms_erreur[] = array($nom['num_nom'], $nom['synonyme_douteux'], $nom['exclure_taxref']);
                                }
                        }
                }
                return $noms_erreur;            
        }
        
        /**
         * Test #57
         */
        private function testerSynonymeDouteuxNumNomRetenu() {
                $noms_erreur = array();
                foreach ($this->noms as &$nom) {
                        if ($nom['synonyme_douteux'] == 1 && !$this->verifierNombre($nom['num_nom_retenu'])) {
                                $noms_erreur[] = array($nom['num_nom'], $nom['synonyme_douteux'], $nom['exclure_taxref']);
                        }
                }
                return $noms_erreur;
        }
        
        /**
         * Test #58
         */
        private function testerSynonymeMalAppliqueSyntaxe() {
                $noms_erreur = array();
                foreach ($this->noms as &$nom) {
                        if ($nom['synonyme_mal_applique'] != '') {
                                if (!$this->verifierBooleen($nom['synonyme_mal_applique'])) {
                                        $noms_erreur[] = array($nom['num_nom'], $nom['synonyme_mal_applique'], $nom['exclure_taxref']);
                                }
                        }
                }
                return $noms_erreur;
        }
        
        /**
         * Test #59
         */
        private function testerSynonymeOrthographiqueSyntaxe() {
                $noms_erreur = array();
                foreach ($this->noms as $nom) {
                        if ($nom['synonyme_orthographique'] != '') {
                                if (!$this->verifierNombre($nom['synonyme_orthographique'])) {
                                        $noms_erreur[] = array($nom['num_nom'], $nom['synonyme_orthographique'], $nom['exclure_taxref']);
                                }
                        }
                }
                return $noms_erreur;
        }
        
        /**
         * Test #60
         */
        private function testerSynonymeOrthographiqueExistence() {
                $noms_erreur = array();
                foreach ($this->noms as &$nom) {
                        if ($nom['synonyme_orthographique'] != '') {
                                if (!isset($this->noms[$nom['synonyme_orthographique']])) {
                                        $noms_erreur[] = array($nom['num_nom'], $nom['synonyme_orthographique'], $nom['exclure_taxref']);
                                }
                        }
                }
                return $noms_erreur;
        }
        
        /**
         * Test #61
         */
        private function testerHybrideParent01Syntaxe() {
                $noms_erreur = array();
                foreach ($this->noms as &$nom) {
                        if ($nom['hybride_parent_01'] != '') {
                                if (!$this->verifierNombre($nom['hybride_parent_01'])) {
                                        $noms_erreur[] = array($nom['num_nom'], $this->repererEspace($nom['hybride_parent_01']), $nom['exclure_taxref']);
                                }
                        }
                }
                return $noms_erreur;
        }
        
        /**
         * Test #62
         */
        private function testerHybrideParent01Existence() {
                $noms_erreur = array();
                foreach ($this->noms as &$nom) {
                        if ($nom['hybride_parent_01'] != '' && $nom['hybride_parent_01'] != '0') {
                                if (!isset($this->noms[$nom['hybride_parent_01']])) {
                                        $noms_erreur[] = array($nom['num_nom'], $this->repererEspace($nom['hybride_parent_01']), $nom['exclure_taxref']);
                                }
                        }
                }
                return $noms_erreur;
        }
        
        /**
         * Test #63
         */
        private function testerHybrideParent02Syntaxe() {
                $noms_erreur = array();
                foreach ($this->noms as &$nom) {
                        if ($nom['hybride_parent_02'] != '') {
                                if (!$this->verifierNombre($nom['hybride_parent_02'])) {
                                        $noms_erreur[] = array($nom['num_nom'], $this->repererEspace($nom['hybride_parent_02']), $nom['exclure_taxref']);
                                }
                        }
                }
                return $noms_erreur;
        }
        
        /**
         * Test #64
         */
        private function testerHybrideParent02Existence() {
                $noms_erreur = array();
                foreach ($this->noms as &$nom) {
                        if ($nom['hybride_parent_02'] != '') {
                                if (!isset($this->noms[$nom['hybride_parent_02']]) && $nom['hybride_parent_02'] != '0') {
                                        $noms_erreur[] = array($nom['num_nom'], $this->repererEspace($nom['hybride_parent_02']), $nom['exclure_taxref']);
                                }
                        }
                }
                return $noms_erreur;
        }
        
        /**
         * Test #65
         */
        private function testerPresenceSyntaxe() {
                $noms_erreur = array();
                foreach ($this->noms as &$nom) {
                        if ($nom['presence'] != '') {
                                if (!$this->verifierPresence($nom['presence'])) {
                                        $noms_erreur[] = array($nom['num_nom'], $nom['presence'], $nom['exclure_taxref']);
                                }
                        }
                }
                return $noms_erreur;
        }
        
        /**
         * Test #66
         */
        private function testerStatutOrigineSyntaxe() {
                $noms_erreur = array();
                foreach ($this->noms as &$nom) {
                        if ($nom['statut_origine'] != '') {
                                if (!$this->verifierStatutOrigine($nom['statut_origine'])) {
                                        $noms_erreur[] = array($nom['num_nom'], $nom['statut_origine'], $nom['exclure_taxref']);
                                }
                        }
                }
                return $noms_erreur;
        }
        
        /**
         * Test #67
         */
        private function testerStatutIntroductionSyntaxe() {
                $noms_erreur = array();
                foreach ($this->noms as &$nom) {
                        if ($nom['statut_introduction'] != '') {
                                if (!$this->verifierStatutIntroduction($nom['statut_introduction'])) {
                                        $noms_erreur[] = array($nom['num_nom'], $nom['statut_introduction'], $nom['exclure_taxref']);
                                }
                        }
                }
                return $noms_erreur;
        }
        
        /**
         * Test #68
         */
        private function testerStatutCultureSyntaxe() {
                $noms_erreur = array();
                foreach ($this->noms as &$nom) {
                        if ($nom['statut_culture'] != '') {
                                if (!$this->verifierStatutCulture($nom['statut_culture'])) {
                                        $noms_erreur[] = array($nom['num_nom'], $nom['statut_culture'], $nom['exclure_taxref']);
                                }
                        }
                }
                return $noms_erreur;
        }
        
        /**
         * Test #69
         */
        private function testerExclureTaxRefSyntaxe() {
                $noms_erreur = array();
                foreach ($this->noms as &$nom) {
                        if ($nom['exclure_taxref'] != '' && $nom['exclure_taxref'] != null) {
                                if (!preg_match('/^(?:0|1|9)$/', $nom['exclure_taxref'])) {
                                        $noms_erreur[] = array($nom['num_nom'], $nom['exclure_taxref']);
                                }
                        }
                }
                return $noms_erreur;
        }
        
        /**
        * Test #70
        */
        private function testerNomFrancaisUnique() {
                $noms_erreur = array();
                foreach ($this->noms as &$nom) {
                        if ($nom['nom_francais'] != '' && $nom['nom_francais'] != null) {
                                if (strpbrk($nom['nom_francais'],',;')) {
                                        $noms_erreur[] = array($nom['num_nom'], $this->repererCaracteresInvalidesNomFrancais($nom['nom_francais']));
                                }
                        }
                }
                return $noms_erreur;
        }
        
        /**
        * Test #71
        */
        private function testerExclureTaxRefPresence() {
                $noms_erreur = array();
                foreach ($this->noms as &$nom) {
                        if ($nom['num_nom_retenu'] == $nom['num_nom'] && $nom['exclure_taxref'] == 0) {
                                if($nom['presence'] == '' || !$this->verifierPresence($nom['presence'])) {
                                        if(($nom['statut_origine'] == '' || !$this->verifierStatutOrigine($nom['statut_origine'])) && 
                                           ($nom['statut_introduction'] == '' || !$this->verifierStatutIntroduction($nom['statut_introduction'])) && 
                                           ($nom['statut_culture'] == '' || !$this->verifierStatutCulture($nom['statut_culture']))) 
                                        {
                                                $noms_erreur[] = array($nom['num_nom'], $nom['nom_sci'], 
                                                                                                $this->mettreEnValeurAvertissement($nom['presence']), 
                                                                                                $this->mettreEnValeurAvertissement($nom['statut_origine']), 
                                                                                                $this->mettreEnValeurAvertissement($nom['statut_introduction']), 
                                                                                                $this->mettreEnValeurAvertissement($nom['statut_culture'])
                                                                                );
                                        } else {
                                                //TODO: le comportement est identique mais il faudrait pouvoir afficher un avertissement
                                                // si le champ présence n'est pas rempli mais que l'une des colonne de statut l'est
                                                $noms_erreur[] = array($nom['num_nom'], $nom['nom_sci'], 
                                                                                                $nom['presence'], 
                                                                                                $this->mettreEnValeurAvertissement($nom['statut_origine']), 
                                                                                                $this->mettreEnValeurAvertissement($nom['statut_introduction']), 
                                                                                                $this->mettreEnValeurAvertissement($nom['statut_culture'])
                                                                                );
                                        }
                                }
                        }
                }
                return $noms_erreur;
        }

        //+--------------------------------------------------------------------------------------------------------------+//
        // MÉTHODES COMMUNES aux TESTS
        
        private function verifierPresence(&$valeur) {
                $codes = $this->manuel['codes_presence'];
                $ok = $this->verifierStatuts($valeur, $codes);
                return $ok;
        }
        
        private function verifierStatutOrigine(&$valeur) {
                $codes = $this->manuel['codes_statuts_origine'];
                $ok = $this->verifierStatuts($valeur, $codes);
                return $ok;
        }
        
        private function verifierStatutIntroduction(&$valeur) {
                $codes = $this->manuel['codes_statuts_introduction'];
                $ok = $this->verifierStatuts($valeur, $codes);
                return $ok;
        }
        
        private function verifierStatutCulture(&$valeur) {
                $codes = $this->manuel['codes_statuts_culture'];
                $ok = $this->verifierStatuts($valeur, $codes);
                return $ok;
        }
        
        private function verifierStatuts(&$valeur, &$codes) {
                $ok = true;
                if (!preg_match("/^(?:|-|[$codes](?:-[A-Z])?)$/", $valeur)) {
                        $ok = false;
                }
                return $ok;
        }
        
        private function verifierBooleen(&$valeur) {
                $ok = true;
                if (!preg_match('/^1$/', $valeur)) {
                        $ok = false;
                }
                return $ok;
        }
        
        private function verifierNombre(&$valeur) {
                $ok = true;
                if (!preg_match('/^[0-9]+$/', $valeur)) {
                        $ok = false;
                }
                return $ok;
        }
        
        private function verifierNombreSuite(&$valeur) {
                $ok = true;
                if (!preg_match('/^(?:[0-9]+, ?)*[0-9]+$/', $valeur)) {
                        $ok = false;
                }
                return $ok;
        }
        
        private function verifierTypeEpithete(&$type) {
                $ok = false;
                $rejetes = $this->manuel['type_epithete_rejetes'];
                if (preg_replace("/^(?:$rejetes)$/", '', $type) == '') {
                        $ok = false;
                } else if (preg_match('/^[a-z][-a-z]*[.]?$/', $type)) {
                        $ok = true;
                }
                return $ok;
        }
        
        private function verifierBiblioOrigine(&$intitule) {
                $ok = true;
                if (preg_match('/(?:^\s+|\s{2,}|\s+$)/', $intitule)) {
                        $ok = false;// Contient des espaces en trop
                } else if (!preg_match('/^(?:in [^;]+[;]|)[^,]+?(?:[,][^:]+|)(?:[:].+|)$/', $intitule)) {
                        $ok = false;
                } else if (preg_match('/(?:(?:^|[,:])\s*(?:[:,]|$))/', $intitule)) {
                        $ok = false;// Contient une mauvaise suite de caractères
                }
                return $ok;
        }
        
        private function verifierAnnee(&$annee) {
                $ok = true;
                if (!preg_match('/^[0-9]{4}$/', $annee)) {
                        $ok = false;
                } else if ($annee < ANNEE_MINIMUM) {
                        $ok = false;
                } else if ($annee > ANNEE_EN_COURS) {
                        $ok = false;
                }
                return $ok;
        }
        
        private function verifierAuteur(&$intitule) {
                $ok = true;
                $acceptes = $this->manuel['auteur_acceptes'];
                if (!preg_match("/^(?:$acceptes)$/", $intitule)) {
                        if (preg_match('/(?:^\s+|\s{2,}|\s+$)/', $intitule)) {
                                $ok = false;// Contient des espaces en trop
                        } else {
                                $mots_rejetes = $this->manuel['auteur_mots_rejetes'];
                                $mots = explode(' ', $intitule);
                                foreach ($mots as $position => $mot) {
                                        if (preg_match("/^(?:$mots_rejetes)$/i", $mot)) {
                                                $ok = false;// Mot rejeté
                                        } else if (preg_match("/^(?:(?:\p{L}|[.'\(\),-])+|[&])$/u", $mot)) {
                                                continue;// Mot de l'intitulé auteur
                                        } else {
                                                $ok = false;
                                        }
                                }
                        }
                }
                return $ok;
        }
        
        private function verifierNomCommercial(&$epithete) {
                $ok = false;
                if (preg_match("/^[[:upper:][:punct:][:digit:][:space:]]+$/", $epithete)) {
                        $ok = true;
                }
                return $ok;
        }
        
        private function verifierEpitheteCultivar(&$epithete) {
                $ok = true;
                $acceptes = $this->manuel['cultivar_acceptes'];
                if (!preg_match("/^(?:$acceptes)$/", $epithete)) {
                        if (preg_match('/(?:^\s+|\s{2,}|\s+$)/', $epithete)) {
                                $ok = false;// Contient des espaces en trop
                        } else {
                                $mots_rejetes = $this->manuel['cultivar_mots_rejetes'];
                                $mots_mineurs = $this->manuel['mots_mineurs'];
                                $mots = explode(' ', $epithete);
                                foreach ($mots as $position => $mot) {
                                        if (preg_match("/^(?:$mots_rejetes)$/i", $mot)) {
                                                $ok = false;// Mot rejeté
                                        } else if ($position > 0 && preg_match("/^(?:$mots_mineurs)$/", $mot)) {
                                                continue;// Mot mineur en minuscule qui n'est pas en 1ère position
                                        } else {
                                                $mots_tiret = explode('-', $mot);
                                                foreach ($mots_tiret as $position_tiret => $mot_tiret) {
                                                        if ($position_tiret > 0 && preg_match("/^(?:$mots_mineurs)$/", $mot_tiret)) {
                                                                continue;// Mot-tiret mineur en minuscule qui n'est pas en 1ère position
                                                        } else if (preg_match('/^[[:upper:]][[:lower:]]+$/', $mot_tiret)) {
                                                                continue;//Mot (ou 'mot-tiret') avec lettre initiale majuscule
                                                        } else if ($position_tiret == count($mots_tiret) && preg_match('/^[:upper:][:lower:]+[:punct:]?$/', $mot_tiret)) {
                                                                continue;//Dernier mot (ou 'mot-tiret') avec lettre initiale majuscule, suivi d'un éventuel signe de ponctuation
                                                        } else {
                                                                $ok = false;
                                                        }
                                                }
                                        }
                                }
                        }
                }
                return $ok;
        }
        
        private function verifierEpitheteGroupeCultivar(&$epithete) {
                $ok = true;
                $acceptes = $this->manuel['cultivar_gp_acceptes'];
                if (!preg_match("/^(?:$acceptes)$/", $epithete)) {
                        if (preg_match('/(?:^\s+|\s{2,}|\s+$)/', $epithete)) {
                                $ok = false;// Contient des espaces en trop
                        } else {
                                $mots_acceptes = $this->manuel['cultivar_gp_mots_acceptes'];
                                $mots_rejetes = $this->manuel['cultivar_gp_mots_rejetes'];
                                $mots_mineurs = $this->manuel['mots_mineurs'];
                                $mots = explode(' ', $epithete);
                                foreach ($mots as $position => $mot) {
                                        if (preg_match("/^(?:$mots_acceptes)$/i", $mot)) {
                                                continue;// Mot accepté
                                        } else if (preg_match("/^(?:$mots_rejetes)$/i", $mot)) {
                                                $ok = false;// Mot rejeté
                                        } else if ($position > 0 && preg_match("/^(?:$mots_mineurs)$/", $mot)) {
                                                continue;// Mot mineur en minuscule qui n'est pas en 1ère position
                                        } else {
                                                $mots_tiret = explode('-', $mot);
                                                foreach ($mots_tiret as $position_tiret => $mot_tiret) {
                                                        if ($position_tiret > 0 && preg_match("/^(?:$mots_mineurs)$/", $mot_tiret)) {
                                                                continue;// Mot-tiret mineur en minuscule qui n'est pas en 1ère position dans le mot
                                                        } else if (preg_match('/^[[:upper:]][[:lower:]]+$/', $mot_tiret)) {
                                                                continue;// Mot (ou 'mot-tiret') avec lettre initiale majuscule
                                                        } else if ($position_tiret == count($mots_tiret) && preg_match('/^[:upper:][:lower:]+[:punct:]?$/', $mot_tiret)) {
                                                                continue;// Dernier mot (ou 'mot-tiret') avec lettre initiale majuscule, suivi d'un éventuel signe de ponctuation
                                                        } else {
                                                                $ok = false;
                                                        }
                                                }
                                        }
                                }
                        }
                }
                return $ok;
        }
        
        private function verifierEpitheteSp(&$epithete) {
                $ok = false;
                if (preg_match('/^[a-zäëḧïöẗüẅẍÿ][-a-zäëḧïöẗüẅẍÿ]+$/', $epithete)) {
                        $ok = true;
                } else if (preg_match('/^sp\.(?:[A-Z]|[1-9][0-9]*)$/', $epithete)) {
                        $ok = true;
                }
                return $ok;
        }
        
        private function verifierEpitheteGenre(&$epithete) {
                $ok = false;
                if (preg_match('/^[A-ZÄËḦÏÖÜẄẌŸ](?:[-a-zäëḧïöẗüẅẍÿ]+|[a-zäëḧïöẗüẅẍÿ]+-[A-ZÄËḦÏÖÜẄẌŸ][a-zäëḧïöẗüẅẍÿ]+)$/', $epithete)) {
                        $ok = true;
                }
                return $ok;
        }
        
        private function verifierEstAbbreviationInfraSp($mot) {
                $ok = false;
                if(preg_match($this->manuel['abbr_rangs_infra_specifique'], $mot)) {
                        $ok = true;
                }
                return $ok;
        }
        
        private function formaterStyleNomGenre(&$genre) {
                $genre_fmt = '';
                if (preg_match('/^\s*([x+])\s+(.+)$/i', $genre, $match)) {
                        $genre_fmt = utf8_encode(strtolower(utf8_decode($match[1]))).' '.utf8_encode(ucfirst(strtolower(utf8_decode($match[2]))));
                } elseif (preg_match('/^(.+)\s+([x+])\s+(.+)$/i', $genre, $match)) {
                        $genre_fmt = utf8_encode(ucfirst(strtolower(utf8_decode($match[1])))).' '.
                                utf8_encode(strtolower(utf8_decode($match[2]))).' '.utf8_encode(ucfirst(strtolower(utf8_decode($match[3]))));
                } else {
                        $genre_fmt = utf8_encode(ucfirst(strtolower(utf8_decode($genre))));
                }
                return $genre_fmt;
        }
        
        private function formaterStyleEpitheteSpHybride(&$genre, &$epithete) {
                $nom_fmt = '';
                $erreur = '';
                if (trim($genre) == '') {
                        if ($epithete != '') {
                                $nom_fmt = $this->formaterFormuleHybridite($epithete);
                        } else {
                                $erreur = "Formule d'hybridité sans épithéte spécifique";
                        }
                } else {
                        $nom_fmt = $this->formaterNomHybride($genre, $epithete);
                }
                return array($nom_fmt, $erreur);
        }
        
        private function formaterStyleEpitheteInfraSpHybride(&$nom_sci, &$infra, &$genre = null) {              
                $nom_fmt = '';
                $erreur = '';
                if (trim($genre) == '') {
                        if (trim($nom_sci) == '') {
                                if (trim($infra) != '') {
                                        $nom_fmt = $this->formaterFormuleHybridite($infra);
                                } else {
                                        $erreur = "Formule d'hybridité sans épithéte infraspécifique";
                                }
                        } else {
                                $erreur = "Formule d'hybridité avec épithéte spécifique";
                        }
                } else {
                        $nom_fmt = $this->formaterNomHybride($nom_sci, $infra);
                }
                return array($nom_fmt, $erreur);
        }
        
        private function formaterNomHybride(&$nom_sci, &$epithete) {
                if (preg_match('/^(.+)\s+([x+])\s+(.+)$/i', $epithete, $match) != '') {
                        $nom_fmt = $nom_sci.utf8_encode(ucfirst(strtolower(utf8_decode($match[1])))).' '.
                                utf8_encode(strtolower(utf8_decode($match[2]))).' '.
                                utf8_encode(ucfirst(strtolower(utf8_decode($match[3]))));
                } elseif (preg_match('/^([x+])\s+(.+)$/i', $epithete, $match) != '') {
                        $nom_fmt = $nom_sci.utf8_encode(strtolower(utf8_decode($match[1]))).' '.
                                utf8_encode(strtolower(utf8_decode($match[2])));
                } else {
                        $nom_fmt = $nom_sci.utf8_encode(strtolower(utf8_decode($epithete)));
                }
                return $nom_fmt;
        }
        
        private function formaterFormuleHybridite(&$epithete) {
                $liste_parents = explode(' x ', $epithete);
                if (count($liste_parents) == 2) {
                        $nom_fmt = utf8_encode(ucfirst(strtolower(utf8_decode($liste_parents[0])))).' x '.
                        utf8_encode(ucfirst(strtolower(utf8_decode($liste_parents[1]))));
                } else {
                        for ($i=0; $i<count($liste_parents); $i++) {
                                if (strstr(trim($liste_parents[$i]), ' ') == false) {
                                        $nom[] = utf8_encode(ucfirst(strtolower(utf8_decode(trim($liste_parents[$i]))))).' x '.
                                        utf8_encode(strtolower(utf8_decode(trim($liste_parents[$i+1]))));
                                        $i++;
                                } else {
                                        $nom[] = utf8_encode(ucfirst(strtolower(utf8_decode($liste_parents[$i]))));
                                }
                        }
                        $nom_fmt = implode(' x ', $nom);
                }
                return $nom_fmt;
        }
        
        private function repererEspace($nom_sci) {
                $nom_sci = str_replace(' ', '<span class="espace">&nbsp;</span>', $nom_sci);
                return $nom_sci;
        }
        
        private function repererCaracteresInvalidesNomFrancais($nom_verna) {
                $nom_verna = str_replace(',', '<span class="espace">,</span>', $nom_verna);
                $nom_verna = str_replace(';', '<span class="espace">;</span>', $nom_verna);
                return $nom_verna;
        }
        
        private function mettreEnValeurAvertissement($chaine) {
                $chaine = '<span class="espace">'.$chaine.'</span>';
                return $chaine;
        }
        
        private function construireSuffixeNomPltCultivee(&$nom) {
                $suffixe = array();
                $suffixe[] = $this->construireNomCultivarGroupe($nom);
                $suffixe[] = $this->construireNomCommercial($nom);
                $suffixe[] = $this->construireNomCultivar($nom);
                $suffixe = array_filter($suffixe);
                return implode(' ', $suffixe);
        }
        
        private function construireNomCultivarGroupe(&$nom) {
                $nom_groupe_cultivar = '';
                if ($nom['cultivar_groupe'] != '') {
                        if (preg_match('/ gx$/', $nom['cultivar_groupe'])) {
                                $nom_groupe_cultivar =  '('.$nom['cultivar_groupe'].')';
                        } else {
                                $nom_groupe_cultivar =  '('.$nom['cultivar_groupe'].' Gp)';
                        }
                }
                return $nom_groupe_cultivar;
        }
        
        private function construireNomCommercial(&$nom) {
                $nom_commercial = '';
                if ($nom['nom_commercial'] != '') {
                        $nom_commercial =  strtoupper($nom['nom_commercial']);
                }
                return $nom_commercial;
        }
        
        private function construireNomCultivar(&$nom) {
                $nom_cultivar = '';
                if ($nom['cultivar'] != '') {
                        $nom_cultivar =  "'".$nom['cultivar']."'";
                }
                return $nom_cultivar;
        }
        
        private function classerNomsParNomComplet() {
                $noms_classes = array();
                foreach ($this->noms as &$nom) {
                        if (!isset($noms_classes[$nom['nom_sci']])) {
                                $noms_classes[$nom['nom_sci']] = 1;
                        } else {
                                $noms_classes[$nom['nom_sci']]++;
                        }
                }
                return $noms_classes;
        }
}
?>