Blame | Last modification | View Log | RSS feed
<?php/*** Exemple de lancement :* /opt/lampp/bin/php cli.php coste/cles -a parser -d /home/jpm/eflore/donnees/coste/cles/html -v 3* Classe analysant les clés de Coste en HTML.** @category php 5.2* @package eflore/scripts/coste* @author Jennifer DHÉ <jennifer@tela-botanica.org>* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>* @copyright Copyright (c) 2011, Tela Botanica (accueil@tela-botanica.org)* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL* @license http://www.gnu.org/licenses/gpl.html Licence GNU-GPL* @version $Id$*/class Cles extends Script {private $bdd = null;private $fichier = null;private $ligneNumero = null;private $contenu = null;private $pages = array();private $stats = array('nbreDsc' => 0, 'nbreCle' => 0, 'nbreGenre' => 0, 'nbreFamille' => 0, 'nbreDscClasse' => 0, 'nbrCleClasse' => 0);protected $parametres_autorises = array('-d' => array(false, null, 'nom du dossier à analyser'),'-f' => array(false, null, 'nom du fichier à analyser'));private $table_triples = array(); //permet de stockerprivate $famille = ''; //permet de stocker le nom de la famille surlaquelle on travailleprotected $indexGpFG = array();protected $table_espece = array();protected $table_num_nom = array();protected $projet_coste = array();protected $nb_fichier = 0;protected $nb_pages = 0;protected $table_coste;public function initialiser() {$this->bdd = new Bdd();}public function executer() {$this->initialiser();$cmd = $this->getParametre('a');switch ($cmd) {case 'tester' :$this->test();break;case 'parser' :$this->recupererTableCoste();$this->chargerIndexGpFG();$this->parserFichiers();break;default :$this->traiterErreur('Erreur : la commande "%s" n\'existe pas!', array($cmd));}}private function test() {//on recupère les textes$this->fichier = $this->getParametre('f');$this->parserFichier();$fichier_test = str_replace('.html', '-test.html', $this->getParametre('f'));file_put_contents($fichier_test, $this->contenu);}private function parserFichiers() {$nomDossier = $this->getParametre('d');$tableaux = null;if (file_exists($nomDossier) === true) {if (is_dir($nomDossier)) {if ($dossierOuvert = opendir($nomDossier) ) {while ( ($nomFichier = readdir($dossierOuvert)) !== false) {if (!is_dir($nomFichier) ) {$this->fichier = $nomDossier.DS.$nomFichier;$this->parserFichier();}}$this->traiterInfo('Nb de fichier : '.$this->nb_fichier);$this->traiterInfo('Nb de pages : '.$this->nb_pages);closedir($dossierOuvert);} else {$this->traiterErreur("Le dossier $nomDossier n'a pas pu être ouvert.");}} else {$this->traiterErreur("$nomDossier n'est pas un dossier.");}} else {$this->traiterErreur("Le dossier $nomDossier est introuvable.");}$this->afficherStats();}private function parserFichier() {$this->nb_fichier++;$contenu = $this->recupererContenuFichier($this->fichier);$contenu = $this->nettoyerHtml($contenu);$contenu = $this->supprimerDescriptionSp($contenu);$contenu = $this->nettoyerTexte($contenu);$this->contenu = $contenu;$this->analyserCle($contenu);$this->nettoyerParType();$this->insererDansWikini();$this->nb_pages += count($this->pages);$this->pages = array();$this->table_triples = array();}private function recupererContenuFichier($nomFichier) {$contenu = null;if (file_exists($nomFichier)) {if (!$contenu = file_get_contents($nomFichier)) {$this->traiterErreur("Le fichier $nomFichier n'a pas pu être ouvert.");}} else {$this->traiterErreur("Le fichier $nomFichier est introuvable.");}return $contenu;}private function chargerIndexGpFG() {$requete = 'SELECT * '.'FROM coste_index_general ';$resultat = $this->bdd->recupererTous($requete);foreach ($resultat as $nom) {$nom_coste = ($nom['nom_coste'] == '') ? $this->transliterer($nom['nom_sci']) : $this->transliterer($nom['nom_coste']);$nom_sci = $this->transliterer($nom['nom_sci']);$tome = $nom['tome'];$page = $nom['page'];$num_tax_sup_coste = $nom['num_tax_sup_coste'];$num_nom_coste = $nom['num_nom_coste'];$rang = $nom['rang'];$this->indexGpFG[$nom_coste] = array( 'nom_sci' => $nom_sci,'rang' => $rang,'tome' => $tome,'page' => $page,'nom_coste' => $nom_coste,'num_nom_coste' => $num_nom_coste,'num_tax_sup_coste' => $num_tax_sup_coste);}}private function transliterer($txt) {$txt = ucwords(strtolower(Chaine::supprimerAccents($txt)));return trim($txt);}private function nettoyerHtml($contenu) {$contenu = strip_tags($contenu, '<b><i><table><title>');$expressions = array('/<b>\s*<\/b>/','/<i>\s*<\/i>/','/<title>[^<]+<\/title>/','/­/');$remplacements = '';$contenu = preg_replace($expressions, $remplacements, $contenu);return $contenu;}private function supprimerDescriptionSp($contenu) {//on supprime les tables contenant les images et les descriptions des espèces$contenu = preg_replace('/<table.+?<\/table>/uis', '', $contenu);return $contenu;}private function nettoyerTexte($contenu) {$remplacement = array('F\MILLE' => 'FAMILLE');$contenu = strtr($contenu, $remplacement);$expressions = array('/(?:\s*(?:\n|\r\n|\r))+/uis','/\n\s+<b>/uis','/^[ ]+/u','/[ ]{2,}/','/[.]\n[.]/us');$remplacements = array("\n","\t<b>",'',' ',".\n");$contenu = preg_replace($expressions, $remplacements, $contenu);return $contenu;}private function analyserCle($contenu) {//creation des tags et des pages pour la table coste_page$lignes = preg_split('/[\n]+/', $contenu);$nom = '';$texte = '';$tag_wiki = '';$nbre_lignes = count($lignes);$num_famille = '';foreach ($lignes as $this->ligneNumero => $ligne) {$ligne = $ligne."\n";if (preg_match('/^FAMILLE ([0-9]+)(?:[.]| ) (?:- |)([^ .$]+)/iu', strip_tags($ligne), $match)) {//Description de la famille$this->ajouterPage($tag_wiki, $texte);$nom = $match[2];$this->stats['nbreFamille']++;$num_famille = $match[1];$this->famille = $this->transliterer($match[2]);$this->famille = $this->corrigerNom($this->famille);$tag_wiki = $this->creerTagWiki($nom, 'Dsc');$texte = $ligne;} else if (preg_match('/^TABLEAU DES GENRES$/u', strip_tags($ligne))) {//Clé de la famille$this->ajouterPage($tag_wiki, $texte);$tag_wiki = $this->creerTagWiki($nom, 'Cle');$texte = $ligne;} else if (preg_match('/^\s*(?:Genre|Cenre)\s*([0-9]+)(?:[.;]|)\s+(?:--|-|_|)\s*([^ ]+)\s+/ui', strip_tags($ligne), $match)) {//Description des genres$this->ajouterPage($tag_wiki, $texte);$nom = $match[2];$this->stats['nbreGenre']++;$tag_wiki = $this->creerTagWiki($nom, 'Dsc');$texte = $ligne;$this->recupererDonneesGenre($ligne, $nom);} else if (preg_match('/^TABLEAU DES ESP[ÈÉE]CES$/u', strip_tags($ligne))) {//Clé du genre$this->ajouterPage($tag_wiki, $texte);$tag_wiki = $this->creerTagWiki($nom, 'Cle');$texte = $ligne;} else if (preg_match('/^<b>TABLE ANALYTIQUE DES FAMILLES<\/b>$/u', $ligne)) {//recuperation des Groupes$nom = 'Plantae';$tag_wiki = $this->creerTagWiki($nom, 'Cle');$texte = $ligne;} else if (preg_match('/^<b>(?:1|[IV]+).\s+(?:-\s+){0,1}([A-ZÉÈ]+)[.]<\/b>$/u', $ligne, $match)) {//recuperation pour chaque groupe la clé des familles$this->ajouterPage($tag_wiki, $texte);$nom = $match[1];$tag_wiki = $this->creerTagWiki($nom, 'Cle');$texte = $ligne;} else if (preg_match('/^<b>ORDRE DES FAMILLES<\/b>$/u', $ligne)) {//récupère les ordres des familles par groupe$this->ajouterPage($tag_wiki, $texte);$tag_wiki = 'OrdreFamilles';$texte = $ligne;//rajout des descriptions des classes (il y en a trois au total)} else if (strrpos($ligne, 'Classe') !== false || strrpos($ligne, 'CRYPTOGAMES-VASCULAIRES') !== false || strrpos($ligne, 'MONOCOTYLÉDONES') !== false) {if (strrpos($ligne, 'CRYPTOGAME') !== false) {$this->ajouterPage($tag_wiki, $texte);$nom = 'cryptogames';$this->stats['nbreDscClasse']++;$tag_wiki = $this->creerTagWiki($nom, 'Dsc');;$texte = $ligne;} elseif (strrpos($ligne, 'MONOCOTYLÉDONES') !== false) {$this->ajouterPage($tag_wiki, $texte);$nom = 'monocotylédones';$this->stats['nbreDscClasse']++;$tag_wiki = $this->creerTagWiki($nom, 'Dsc');$texte = $ligne;} else {preg_match('/^(?:<i>){0,1}(?:Première|Deuxième)? Classe[.][-\s]*[^b]*b>([A-Z]+)<\/b>[.]?/ui', $ligne, $match);$this->ajouterPage($tag_wiki, $texte);if (isset($match[1])) {$nom = $match[1];$tag_wiki = $this->creerTagWiki($nom, 'Dsc');$this->stats['nbreDscClasse']++;$texte = $ligne;} else {$this->traiterErreur("Classe non repérée dans la ligne \"$ligne\" du fichier $this->fichier ! Modifier l'expression regulière");}}} else if ($nbre_lignes == ($this->ligneNumero + 1)) {$texte .= $ligne;$this->ajouterPage($tag_wiki, $texte);} else {$texte .= $ligne;}}}private function recupererDonneesGenre($ligne, $nom) {if (preg_match('/^\s*(?:Genre|Cenre)\s*(?:<i>)?[0-9]+(?:[.;]|)\s+(?:--|-|_|)\s*[^ ]+(.*)?$\s+/ui', strip_tags($ligne, '<i>'), $donnees)) {$donnees_genre = array('nom_coste' => $nom, 'auteur' => '', 'nom_verna' => '');if (isset($donnees[1]) && !empty($donnees[1])) {// cas possible : <i>L. - Passerage.</i>if (preg_match('/^(?:(?:^\s*<i>([^-]+)-([^-]+)))/ui', $donnees[1], $don)) {if (isset($don[1])) {$auteur = $don[1];$donnees_genre['auteur'] = $auteur;}if (isset($don[2])) {$nom_verna = $don[2];$donnees_genre['nom_verna'] = $nom_verna;}} elseif (preg_match('/^(?:(^\s*[^-<>]*)(?:[-\s]*)(?:<i>(?:[-\s]*)([^<>]*))?)/ui', $donnees[1], $don)) {if (isset($don[1])) {$auteur = $don[1];$donnees_genre['auteur'] = $auteur;}if (isset($don[2])) {$nom_verna = $don[2];$donnees_genre['nom_verna'] = $nom_verna;}} else{$this->traiterErreur("Les donnees : $donnees[1] ne sont pas reconnues par l'expression régulière");}}} else {$this->traiterErreur("Le genre $ligne n'est pas reconnu par l'expression régulière");}//print_r($donnees_genre);$this->insererDonneesGenre($donnees_genre);}private function insererDonneesGenre($donnees_genre) {$nom_coste = $this->bdd->proteger($donnees_genre['nom_coste']);$auteur = $this->bdd->proteger($donnees_genre['auteur']);$nom_francais = $this->bdd->proteger($donnees_genre['nom_verna']);$requete = 'UPDATE coste_v0_1 SET '.'auteur = '.$auteur.', nom_francais = '.$nom_francais.' WHERE nom_coste = '.$nom_coste;$res = $this->bdd->requeter($requete);if (!$res) {$e = 'Les données du genre '.$nom_coste.' n\'ont pas été insérée via la requete '.$requete;$this->traiterErreur($e);}}private function ajouterPage($tag, $txt) {if ($txt != '' && $tag != '') {$txt = $this->formaterSyntaxeWikini($txt);$this->pages[$tag] = $txt;}}private function formaterSyntaxeWikini($txt) {$remplacements = array('<b>' => '**', '</b>' => '**','<i>' => '//', '</i>' => '//');$txt = strtr($txt, $remplacements);return $txt;}private function creerTagWiki($nom, $type) {$tag = '';$page = null;$tome = null;$nom_sci = '';$groupe = array('Thalamiflores', 'Caliciflores', 'Monopetales', 'Monochlamydees', 'Gymnospermes', 'Monocotyledones', 'Cryptogames');$nom = $this->transliterer($nom);$nom = $this->corrigerNom($nom);if (in_array($nom, $groupe) && $type == 'Cle') {$pages = array('1', '4', '5', '9', '12', '12', '14');$page = str_replace($groupe, $pages, $nom);$page = sprintf('%04d', $page);$tome = 1;$tag = "{$type}Coste1937T{$tome}P{$page}$nom";$this->stats['nbreCle']++;$this->stats['nbrCleClasse']++;} else {if ($type == 'Dsc') {$this->stats['nbreDsc']++;} else if ($type == 'Cle') {$this->stats['nbreCle']++;}if (array_key_exists($nom, $this->indexGpFG)) {$tome = $this->indexGpFG[$nom]['tome'];$page = $this->indexGpFG[$nom]['page'];$nom_sci = $this->indexGpFG[$nom]['nom_sci'];} else {$this->traiterErreur("Impossible de trouver le nom $nom dans l'index pour le fichier $this->fichier à la ligne $this->ligneNumero.");}if (!is_null($page) && !is_null($tome)) {$page = sprintf('%04d', $page);$tome = strtr($tome, array('I' => 1, 'II' => 2, 'III' => 3, ));$tag = "{$type}Coste1937T{$tome}P{$page}$nom_sci";}}$this->creerTriples($tag, $nom, $tome, $page);return $tag;}public function creerTriples($tag, $nom, $tome, $page) {if (array_key_exists($nom, $this->indexGpFG)) {$this->table_triples[] = array ('resource' => $tag,'property' => 'titre','value' => $this->creerTitre($nom, $tag));if (isset($this->table_coste[$nom])) {$num_nom = $this->table_coste[$nom];$this->table_triples[] = array ('resource' => $tag,'property' => 'num_nom','value' => $num_nom);} else {$this->traiterErreur("Impossible de trouver le nom $nom dans la table coste");}} else {$this->traiterErreur("Impossible de trouver le nom $nom dans l'index ");}}private function recupererTableCoste() {$table_coste = array();$req = 'SELECT num_nom, nom_coste FROM coste_v0_1 WHERE rang != "290" ';$res = $this->bdd->recupererTous($req);if ($res) {foreach ($res as $donnees) {$this->table_coste[$donnees['nom_coste']] = $donnees['num_nom'];}} else {$this->traiterErreur('Erreur dans la requete '.$req);}}private function creerTitre($nom, $tag) {$titre = '';if (array_key_exists($nom, $this->indexGpFG)) {$num_nom_coste = $this->indexGpFG[$nom]['num_nom_coste'];$tome = $this->indexGpFG[$nom]['tome'];if (preg_match('/^(?:Cle|Dsc)Coste1937T[1-3]{1}P[0]*([1-9]*).+$/', $tag, $match_page)) { //on recherche dans le tag puisque les clés et les descriprtions ont des pages différentes pour les classes par ex$page = $match_page[1];} else {$this->traiterErreur('La page n\'est pas reconnu dans le tag '.$tag);}if ($num_nom_coste == 'R') {$titre = "Coste $num_nom_coste - $nom - T$tome.p$page";} else {$num_tax_sup = $this->indexGpFG[$nom]['num_tax_sup_coste'];$nom_tax_sup = $this->recupererNom($num_tax_sup);$titre = "Coste $num_nom_coste - $nom - $num_tax_sup, $nom_tax_sup - T$tome.p$page";}} else {$this->traiterErreur("Impossible de trouver le nom $nom dans l'index pour créer le titre");}return $titre;}private function recupererNom($id_coste) {foreach ($this->indexGpFG as $donnees) {if ($donnees['num_nom_coste'] == $id_coste) {$nom = $donnees['nom_sci'];break;}}return $nom;}private function corrigerNom($nom) {$remplacements = array('Ceraniacees' => 'Geraniacees','Sucowia' => 'Succowia','Tilla' => 'Tilia');$nom = strtr($nom, $remplacements);$nom = trim($nom);return $nom;}private function nettoyerParType() {foreach ($this->pages as $tag => $txt) {if (preg_match('/^Cle/', $tag)) {$txt = $this->nettoyerCle($txt);}$this->pages[$tag] = $txt;}}private function nettoyerCle($txt) {$txt = preg_replace('/([*]{2})(\s+)([A-Z])/u', '$2$1$3', $txt);$txt = preg_replace('/(\w)\t(\w)/ui', '$1 $2', $txt);$txt = preg_replace('/(\w)\s+([.])/ui', '$1$2', $txt);$txt = preg_replace('/\n\s+(\(|[\*]{2}|[[:alpha:]éèàê]+|[0-9]+-[0-9]+ )/Uuis', ' $1', $txt);$txt = preg_replace('/([.])\s+([\*]{2}|\(part.\))/ui', "$1\t$2", $txt);$txt = preg_replace('/(n)oe(ud[s]?)/ui', "$1œ$2", $txt);return $txt;}private function insererDansWikini() {// Mise à jour éventuelle des pages existantes/*$requete = 'DELETE FROM coste_pages '.'WHERE tag LIKE '.$tag;// ' OR tag LIKE "Cle%" '.// ' OR tag LIKE "OrdreFamilles" ';$this->bdd->requeter($requete);*///--------------insertion des pages-----------------------$this->supprimerPagesExistantes();$this->reinitialiserAutoIncrement('coste_pages');$this->reinitialiserAutoIncrement('coste_triples');foreach ($this->pages as $tag => $txt) {$tag = $this->bdd->proteger($tag);$time = 'NOW()';$txt = $this->bdd->proteger($txt);$latest = $this->bdd->proteger('Y');$perimee = $this->bdd->proteger('N');// Mise à jour éventuelle des pages existantes/*$requete = 'UPDATE coste_pages '."SET latest = $perimee "."WHERE tag = $tag ";$this->bdd->requeter($requete);*/// Insertion du nouveau contenu$requete = 'INSERT INTO coste_pages '.'(tag, time, body, latest) '."VALUES ($tag, $time, $txt, $latest)";$res = $this->bdd->requeter($requete);if ($res) {//$this->afficherAvancement('Insertion des pages du fichier '.$this->fichier);} else {$this->afficherAvancement('Erreur d\'insertion des pages du fichier '.$this->fichier);}}//-----------insertions des triples-----------------------foreach ($this->table_triples as $triple) {$resource = $this->bdd->proteger($triple['resource']);$property = $this->bdd->proteger($triple['property']);$value = $this->bdd->proteger($triple['value']);$requete_triple = "INSERT INTO coste_triples (resource, property, value) VALUES ($resource,$property ,$value)";$res_triple = $this->bdd->requeter($requete_triple);if ($res_triple) {//$this->afficherAvancement('Insertion des triples du fichier '.$this->fichier);} else {$this->afficherAvancement('Erreur d\'insertion des triples du fichier '.$this->fichier);}}}public function supprimerPagesExistantes() {foreach ($this->pages as $tag => $txt) {$tag = $this->bdd->proteger($tag);//suppression des tuples déjà existants$requete = 'DELETE FROM coste_pages '.'WHERE tag = '.$tag;// ' OR tag LIKE "Cle%" '.// ' OR tag LIKE "OrdreFamilles" ';$this->bdd->requeter($requete);$requete = 'DELETE FROM coste_triples '.'WHERE resource LIKE '.$tag;// ' OR tag LIKE "Cle%" '.// ' OR tag LIKE "OrdreFamilles" ';$this->bdd->requeter($requete);}}private function reinitialiserAutoIncrement($table) {$requete_max_id = 'SELECT max(id) from '.$table;$id_max = $this->bdd->recuperer($requete_max_id);$id_max = $id_max['max(id)'];$id_max = $id_max+1;$requete_pages = 'ALTER TABLE '.$table.' AUTO_INCREMENT = '.$id_max;$this->bdd->requeter($requete_pages);}private function afficherStats() {print_r($this->stats);}private function creerFichier($fichier, $tab, $chemin = null) {if (!$chemin) {$chemin = Config::get('chemin_test');}$intitule = '';$nom_fichier = fopen($chemin.$fichier, 'w+');foreach ($tab as $key => $val) {if (is_array($val)) {foreach ($val as $k => $v) {$intitule .= $k."\t";}fwrite($nom_fichier, trim($intitule)."\n");break;}}foreach ($tab as $key => $val) {if (is_array($val)) {fwrite($nom_fichier, implode("\t", $val)."\n");} else {fwrite($nom_fichier, "\t$val\n");}}fclose($nom_fichier);}}?>