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 stocker
private $famille = ''; //permet de stocker le nom de la famille surlaquelle on travaille
protected $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);
}
}
?>