Subversion Repositories eFlore/Projets.eflore-projets

Rev

Rev 1144 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1144 delphine 1
<?php
2
//declare(encoding='UTF-8');
3
/**
4
 * Exemple de lancement du script : :
1146 aurelien 5
 * /opt/lampp/bin/php cli.php lbf -a chargerTous
1144 delphine 6
 *
7
 * @category	php 5.2
8
 * @package		eFlore/Scripts
1146 aurelien 9
 * @author		Delphine Cauquil <delphine@tela-botanica.org>
10
 * @author		Aurélien PERONNET <aurelien@tela-botanica.org>
11
 * @copyright	Copyright (c) 2014, Tela Botanica (accueil@tela-botanica.org)
1144 delphine 12
 * @license		http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
13
 * @license		http://www.gnu.org/licenses/gpl.html Licence GNU-GPL
14
 * @version		$Id$
15
 */
1146 aurelien 16
class Lbf extends EfloreScript {
1144 delphine 17
 
18
	private $table = null;
19
	private $pasInsertion = 1000;
20
	private $departInsertion = 0;
21
 
22
	protected $parametres_autorises = array(
23
		'-t' => array(false, false, 'Permet de tester le script sur un jeu réduit de données (indiquer le nombre de lignes).'));
24
 
25
	public function executer() {
26
		try {
1146 aurelien 27
			$this->initialiserProjet('lbf');
1144 delphine 28
 
29
			// Lancement de l'action demandée
30
			$cmd = $this->getParametre('a');
31
			switch ($cmd) {
32
				case 'chargerTous' :
33
					$this->chargerStructureSql();
1146 aurelien 34
					$this->chargerlbf();
1144 delphine 35
					$this->genererChpNomSciHtml();
36
					$this->genererChpFamille();
37
					//$this->genererChpHierarchie();
38
					break;
39
				case 'chargerStructureSql' :
40
					$this->chargerStructureSql();
41
					break;
1146 aurelien 42
				case 'chargerlbf' :
43
					$this->chargerlbf();
1144 delphine 44
					break;
45
				case 'genererNomSciHtml' :
46
					$this->genererChpNomSciHtml();
47
					break;
48
				case 'genererChpFamille' :
49
					$this->genererChpFamille();
50
					break;
51
				case 'supprimerTous' :
52
					$this->supprimerTous();
53
					break;
54
				default :
55
					throw new Exception("Erreur : la commande '$cmd' n'existe pas!");
56
			}
57
		} catch (Exception $e) {
58
			$this->traiterErreur($e->getMessage());
59
		}
60
	}
61
 
1146 aurelien 62
	private function chargerlbf() {
63
		$chemin = Config::get('chemins.lbf');
64
		$table = Config::get('tables.lbf');
1144 delphine 65
		$requete = "LOAD DATA INFILE '$chemin' ".
66
				"REPLACE INTO TABLE $table ".
67
				'CHARACTER SET utf8 '.
68
				'FIELDS '.
69
				"	TERMINATED BY '\t' ".
70
				"	ENCLOSED BY '' ".
71
				"	ESCAPED BY '\\\' ".
72
				'IGNORE 1 LINES';
73
		$this->getBdd()->requeter($requete);
74
	}
75
 
76
	private function genererChpNomSciHtml() {
77
		$this->initialiserGenerationChamps();
78
		$this->preparerTablePrChpNomSciHtml();
79
		$generateur = new GenerateurNomSciHtml();
80
		$nbreTotal = $this->recupererNbTotalTuples();
81
		$erreurs = array();
82
		$this->departInsertion = 0;
83
		while ($this->departInsertion < $nbreTotal) {
84
			$resultat = $this->recupererTuplesPrChpNomSciHtml();
85
 
86
			try {
87
				$nomsSciEnHtml = $generateur->generer($resultat);
88
			} catch (Exception $e) {
89
				$erreurs[] = $e->getMessage();
90
			}
91
 
92
			$this->remplirChpNomSciHtm($nomsSciEnHtml);
93
			$this->departInsertion += $this->pasInsertion;
94
			$this->afficherAvancement("Insertion des noms scientifique au format HTML dans la base par paquet de {$this->pasInsertion} en cours");
95
			if ($this->stopperLaBoucle($this->getParametre('t'))) break;
96
		}
97
		echo "\n";
98
 
99
		$this->creerFichierLog('Erreurs lors de la génération HTML des noms scientifiques', $erreurs, 'erreurs_noms_sci_html');
100
	}
101
 
102
	private function initialiserGenerationChamps() {
1146 aurelien 103
		$this->table = Config::get('tables.lbf');
1144 delphine 104
	}
105
 
106
	private function preparerTablePrChpNomSciHtml() {
107
		$requete = "SHOW COLUMNS FROM {$this->table} LIKE 'nom_sci_html' ";
108
		$resultat = $this->getBdd()->recuperer($requete);
109
		if ($resultat === false) {
110
			$requete = 	"ALTER TABLE {$this->table} ".
111
				'ADD nom_sci_html VARCHAR( 500 ) '.
112
				'CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL ';
113
			$this->getBdd()->requeter($requete);
114
		}
115
	}
116
 
117
	private function recupererNbTotalTuples(){
118
		$requete = "SELECT count(*) AS nb FROM {$this->table} ";
119
		$resultat = $this->getBdd()->recuperer($requete);
120
		return $resultat['nb'];
121
	}
122
 
123
	private function recupererTuplesPrChpNomSciHtml() {
124
		$requete = 'SELECT 	num_nom, rang, nom_sci, nom_supra_generique, genre, epithete_infra_generique, '.
125
			'	epithete_sp, type_epithete, epithete_infra_sp,cultivar_groupe, '.
126
			'	nom_commercial, cultivar '.
127
			"FROM {$this->table} ".
128
			"LIMIT {$this->departInsertion},{$this->pasInsertion} ";
129
		$resultat = $this->getBdd()->recupererTous($requete);
130
		return $resultat;
131
	}
132
 
133
	private function remplirChpNomSciHtm($nomsSciHtm) {
134
		foreach ($nomsSciHtm as $id => $html) {
135
			$html = $this->getBdd()->proteger($html);
136
			$requete = "UPDATE {$this->table} SET nom_sci_html = $html WHERE num_nom = $id ";
137
			$resultat = $this->getBdd()->requeter($requete);
138
			if ($resultat === false) {
139
				throw new Exception("Erreur d'insertion pour le tuple $id");
140
			}
141
		}
142
	}
143
 
144
	private function traiterResultatsFamille(&$resultats, &$noms, &$introuvables, &$introuvablesSyno) {
145
		foreach ($resultats as $id => $nom) {
146
			$nn = $nom['num_nom'];
147
			$nnr = $nom['num_nom_retenu'];
148
			$nts = $nom['num_tax_sup'];
149
			$rg = $nom['rang'];
150
			if ($nnr != '') {
151
				if ($rg == '180') {
152
					$noms[$nn] = $nom['nom_sci'];
153
				} else {
154
					if ($nn == $nnr) {// nom retenu
155
						if (isset($noms[$nts])) {
156
							// signifie que recupererTuplesPrChpFamille() devrait
157
							// récupérer ce record *avant*
158
							$noms[$nn] = $noms[$nts];
159
						} else {
160
							$introuvables[] = $nn;
161
						}
162
					} else {// nom synonyme
163
						if (isset($noms[$nnr])) {
164
							// signifie que recupererTuplesPrChpFamille() devrait
165
							// récupérer ce record *avant*
166
							$noms[$nn] = $noms[$nnr];
167
						} else {
168
							$introuvablesSyno[] = $nom;
169
						}
170
					}
171
				}
172
			}
173
			unset($resultats[$id]);
174
			$this->afficherAvancement("Attribution de leur famille aux noms en cours");
175
			if ($this->stopperLaBoucle($this->getParametre('t'))) break;
176
		}
177
	}
178
 
179
	private function genererChpFamille() {
180
		$this->initialiserGenerationChamps();
181
		$this->preparerTablePrChpFamille();
182
		$resultats = $this->recupererTuplesPrChpFamille();
183
		$noms = array();
184
		$introuvables = array();
185
		$introuvablesSyno = array();
186
		$i = 1;
187
 
188
		while(true) {
189
			printf("passe n°%d:\n", $i);
190
			$this->traiterResultatsFamille($resultats, $noms, $introuvables, $introuvablesSyno);
191
			echo "\n\n";
192
			// printf("noms: %d, introuvables: %d, introuvablesSyno: %d\n", count($noms), count($introuvables), count($introuvablesSyno));
193
			// XXX, au 22/07/2013, 3 passes sont suffisantes
194
			// TODO: MySQL procédure stockée !
195
			if($i++ == 3) break;
196
			$resultats = array_merge($resultats, $introuvables, $introuvablesSyno);
197
			$introuvables = $introuvablesSyno = array();
198
		}
199
 
200
		foreach ($introuvablesSyno as $id => $nom) {
201
			$nn = $nom['num_nom'];
202
			$nnr = $nom['num_nom_retenu'];
203
			if (isset($noms[$nnr])) {
204
				$noms[$nn] = $noms[$nnr];
205
			} else {
206
				$introuvables[] = $nn;
207
			}
208
			unset($introuvablesSyno[$id]);
209
			$this->afficherAvancement("Attribution de leur famille aux synonymes en cours");
210
		}
211
		echo "\n";
212
 
213
		$msg = 'Plusieurs familles sont introuvables';
214
		$this->creerFichierLog($msg, $introuvables, 'famille_introuvable');
215
 
216
		$this->remplirChpFamille($noms);
217
	}
218
 
219
	private function preparerTablePrChpFamille() {
220
		$requete = "SHOW COLUMNS FROM {$this->table} LIKE 'famille' ";
221
		$resultat = $this->getBdd()->recuperer($requete);
222
		if ($resultat === false) {
223
			$requete = 	"ALTER TABLE {$this->table} ".
224
				'ADD famille VARCHAR(255) '.
225
				'CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL ';
226
			$this->getBdd()->requeter($requete);
227
		}
228
	}
229
 
230
	private function recupererTuplesPrChpFamille() {
231
		$requete = 'SELECT num_nom, num_nom_retenu, num_tax_sup, rang, nom_sci '.
232
				"FROM {$this->table} ".
233
				"WHERE rang >= 180 ".
234
				"ORDER BY rang ASC, num_tax_sup ASC, num_nom_retenu DESC ";
235
		$resultat = $this->getBdd()->recupererTous($requete);
236
		return $resultat;
237
	}
238
 
239
	private function remplirChpFamille($noms) {
240
		foreach ($noms as $id => $famille) {
241
			$famille = $this->getBdd()->proteger($famille);
242
			$requete = "UPDATE {$this->table} SET famille = $famille WHERE num_nom = $id ";
243
			$resultat = $this->getBdd()->requeter($requete);
244
			if ($resultat === false) {
245
				throw new Exception("Erreur d'insertion pour le tuple $id");
246
			}
247
			$this->afficherAvancement("Insertion des noms de famille dans la base en cours");
248
		}
249
		echo "\n";
250
	}
251
 
252
	private function genererChpHierarchie() {
253
		$this->initialiserGenerationChamps();
254
		$this->preparerTablePrChpHierarchie();
1146 aurelien 255
		$table = Config::get('tables.lbf');
1144 delphine 256
 
257
		$requete = "UPDATE $table SET hierarchie = NULL ";
258
		$mise_a_jour = $this->getBdd()->requeter($requete);
259
 
260
		$requete_hierarchie = "SELECT num_nom, num_nom_retenu, num_tax_sup FROM ".$table." ORDER BY rang DESC";
261
 
262
		$resultat = $this->getBdd()->recupererTous($requete_hierarchie);
263
		$num_nom_a_num_sup = array();
264
		foreach($resultat as &$taxon) {
265
			$num_nom_a_num_sup[$taxon['num_nom']] = $taxon['num_tax_sup'];
266
		}
267
		$chemin_taxo = "";
268
		foreach($resultat as &$taxon) {
269
			$chemin_taxo = $this->traiterHierarchieNumTaxSup($taxon['num_nom_retenu'], $num_nom_a_num_sup).'-';
270
			$requete = "UPDATE $table SET hierarchie = ".$this->getBdd()->proteger($chemin_taxo)." WHERE num_nom = ".$taxon['num_nom']." ";
271
			$mise_a_jour = $this->getBdd()->requeter($requete);
272
			$this->afficherAvancement("Insertion de la hierarchie taxonomique en cours");
273
		}
274
		echo "\n";
275
	}
276
 
277
	private function traiterHierarchieNumTaxSup($num_nom_retenu, &$num_nom_a_num_sup) {
278
		$chaine_hierarchie = "";
279
		if(isset($num_nom_a_num_sup[$num_nom_retenu])) {
280
			$num_tax_sup = $num_nom_a_num_sup[$num_nom_retenu];
281
			$chaine_hierarchie = '-'.$num_tax_sup;
282
			if($num_tax_sup != 0 && $num_tax_sup != '') {
283
				$chaine_hierarchie = $this->traiterHierarchieNumTaxSup($num_tax_sup, $num_nom_a_num_sup).$chaine_hierarchie;
284
			}
285
		}
286
		return $chaine_hierarchie;
287
	}
288
 
289
	private function preparerTablePrChpHierarchie() {
290
		$requete = "SHOW COLUMNS FROM {$this->table} LIKE 'hierarchie' ";
291
		$resultat = $this->getBdd()->recuperer($requete);
292
		if ($resultat === false) {
293
			$requete = 	"ALTER TABLE {$this->table} ".
294
					'ADD hierarchie VARCHAR(1000) '.
295
					'CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL ';
296
			$this->getBdd()->requeter($requete);
297
		}
298
	}
299
 
300
	private function genererDonneesTestMultiVersion() {
301
		$contenuSql = $this->recupererContenu(Config::get('chemins.structureSqlTest'));
302
		$this->executerScripSql($contenuSql);
303
 
1146 aurelien 304
		$table = Config::get('tables.lbf');
305
		$tableTest = Config::get('tables.lbfTest');
1144 delphine 306
		$requete = "INSERT INTO $tableTest SELECT * FROM $table";
307
		$this->getBdd()->requeter($requete);
308
	}
309
 
310
	private function supprimerDonneesTestMultiVersion() {
1146 aurelien 311
		$tableMeta = Config::get('tables.lbfMeta');
312
		$requete = "DELETE FROM $tableMeta WHERE guid = 'urn:lsid:tela-botanica.org:lbf:1.02'";
1144 delphine 313
		$this->getBdd()->requeter($requete);
314
 
1146 aurelien 315
		$tableTest = Config::get('tables.lbfTest');
1144 delphine 316
		$requete = "DROP TABLE IF EXISTS $tableTest";
317
		$this->getBdd()->requeter($requete);
318
	}
319
 
320
	private function supprimerTous() {
1146 aurelien 321
		$requete = "DROP TABLE IF EXISTS lbf_meta, lbf_v1_00";
1144 delphine 322
		$this->getBdd()->requeter($requete);
323
	}
324
 
325
	private function creerFichierLog($message, $lignes, $nomFichier) {
326
		$lignesNbre = count($lignes);
327
		if ($lignesNbre != 0) {
328
			echo "$message. Voir le log de $lignesNbre lignes :\n";
329
 
330
			$logContenu = implode(", \n", $lignes);
331
			$logFichier = realpath(dirname(__FILE__))."/log/$nomFichier.log";
332
			echo $logFichier."\n";
333
					file_put_contents($logFichier, $logContenu);
334
		}
335
	}
336
}
337
?>