Subversion Repositories eFlore/Applications.cel

Rev

Rev 1200 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1149 gduche 1
<?php
1198 jpm 2
// declare(encoding='UTF-8');
3
/**
4
 * Script de migration des Mots Clés de la version 1 de la base de données du CEL à la v2.
1224 jpm 5
 * Utilisation : /opt/lampp/bin/php cli.php MigrationMotsCles
1198 jpm 6
 *
7
 * @category	php 5.2
8
 * @package		Cel/Scripts
1224 jpm 9
 * @author		Aurelien PERONNET <aurelien@tela-botanica.org>
1198 jpm 10
 * @author		Jean-Pascal MILCENT <jpm@tela-botanica.org>
11
 * @copyright	Copyright (c) 2012, Tela Botanica (accueil@tela-botanica.org)
1224 jpm 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$
1198 jpm 15
 */
1224 jpm 16
class MigrationMotsCles {
1149 gduche 17
 
1198 jpm 18
	const SEPARATEUR_MOT_CLE_TEXTE = ',';
19
	const truncate = true; //Doit on vider les tables de destination ?
20
	const dry_run = false;
21
 
1224 jpm 22
	private $bdd = null;
23
	private $script = null;
1198 jpm 24
	private $nouvellesTables = array('cel_mots_cles_obs', 'cel_mots_cles_images', 'cel_images_mots_cles', 'cel_obs_mots_cles');
1161 aurelien 25
	public static $bdd_cel_migration;
26
	public static $bdd_utilisateurs;
1149 gduche 27
	private $tableau_utilisateurs = array();
28
 
29
	/** Tableau associatif permettant de stocker l'avancement dans une boucle.
30
	* La clé est un md5 du message à afficher au démarrage de la boucle.
31
	* @var array
32
	*/
33
	private static $avancement = array();
1198 jpm 34
 
1224 jpm 35
	public function __construct(Conteneur $conteneur) {
36
		$bddMigration = $conteneur->getParametre('database_cel.database_migration');
37
		if ($bddMigration == null || $bddMigration == '') {
1161 aurelien 38
			echo 'Attention la variable de configuration database_migration dans la section database_cel, contenant la base de données d\'arrivée, doit être remplie '."\n";
39
			exit;
40
		}
1224 jpm 41
		$bddIdentification = $conteneur->getParametre('database_ident.database');
42
		if ($bddIdentification == null || $bddIdentification == '') {
1161 aurelien 43
			echo 'Attention la variable de configuration database dans la section database_ident, contenant la base de données utilisateurs, doit être remplie '."\n";
44
			exit;
45
		}
1198 jpm 46
 
1224 jpm 47
		self::$bdd_cel_migration = $conteneur->getParametre('database_cel.database_migration');
48
		self::$bdd_utilisateurs = $conteneur->getParametre('database_ident.database');
49
		$this->bdd = $conteneur->getBdd();
50
		$this->script = $conteneur->getScript();
51
	}
1198 jpm 52
 
1224 jpm 53
	/**
54
	 * Méthode appelée pour executer le script.
55
	 */
56
	public function executer($params) {
1161 aurelien 57
		echo "--MIGRATION DES MOTS CLES --------------------------------------\n";
58
		if (self::truncate) {
1199 jpm 59
			echo "-------------------------------------------------------------------\n";
1224 jpm 60
			echo "  ETAPE 0. Vider les tables ... \n";
1199 jpm 61
			echo "-------------------------------------------------------------------\n";
1198 jpm 62
			$this->viderTables();
1161 aurelien 63
		}
1198 jpm 64
 
1199 jpm 65
		echo "-------------------------------------------------------------------\n";
66
		echo "  ETAPE 1. Paramétrage ... \n";
67
		echo "-------------------------------------------------------------------\n";
1149 gduche 68
		$this->getUtilisateurs();
1224 jpm 69
 
1199 jpm 70
		echo "-------------------------------------------------------------------\n";
71
		echo "  ETAPE 2. Migration des mots clés ... \n";
72
		echo "-------------------------------------------------------------------\n";
1149 gduche 73
		$this->migrerTableMotsClesObs();
74
		$this->migrerTableMotsClesImages();
1224 jpm 75
 
1199 jpm 76
		echo "-------------------------------------------------------------------\n";
77
		echo "  ETAPE 3. Migration des liaisons mots clés ... \n";
78
		echo "-------------------------------------------------------------------\n";
1149 gduche 79
		$this->migrerLiaisonsMotsClesObs();
80
		$this->migrerLiaisonsMotsClesImages();
1198 jpm 81
 
1199 jpm 82
		echo "-------------------------------------------------------------------\n";
83
		echo "  ETAPE 4. Génération des index des mots clés ... \n";
84
		echo "-------------------------------------------------------------------\n";
1161 aurelien 85
		$this->genererIndexTexteMotsClesObs();
86
		$this->genererIndexTexteMotsClesImages();
1200 jpm 87
		$this->mettreANullMotsClesTxtVide();
1149 gduche 88
	}
1198 jpm 89
 
90
	private function viderTables() {
91
		foreach ($this->nouvellesTables as $nomTable) {
92
			echo 'Vider la table '.$nomTable.'...';
93
			$requete = 'TRUNCATE TABLE '.self::$bdd_cel_migration.'.'.$nomTable;
1224 jpm 94
			$resultat = $this->bdd->executer($requete);
1198 jpm 95
			echo "ok \n";
96
		}
97
	}
98
 
1224 jpm 99
	private function executerRequeteSimple($requete) {
1149 gduche 100
		// Fonction de commodité pour afficher les requetes au lieu de les executer
1198 jpm 101
		if (self::dry_run) {
102
			echo str_replace('),','),'."\n", $requete);
1149 gduche 103
			return true;
104
		} else {
1224 jpm 105
			return $this->bdd->executer($requete);
1149 gduche 106
		}
107
 
108
	}
1198 jpm 109
 
110
 
1149 gduche 111
	private function getUtilisateurs() {
1224 jpm 112
		echo "SELECTION DES UTILISATEURS\n";
1198 jpm 113
 
114
		$requete = 'SELECT U_ID as id, U_MAIL as mail, U_NAME as nom, U_SURNAME as prenom, U_PASSWD as pass '.
115
			'FROM '.self::$bdd_utilisateurs.'.annuaire_tela';
1224 jpm 116
		$tableau_utilisateurs = $this->bdd->requeter($requete);
1198 jpm 117
 
1149 gduche 118
		foreach( $tableau_utilisateurs as &$utilisateur) {
119
			$this->tableau_utilisateurs[$utilisateur['mail']] = $utilisateur;
120
		}
1198 jpm 121
 
1224 jpm 122
		echo count($this->tableau_utilisateurs)." utilisateurs sélectionnés \n";
1149 gduche 123
	}
1198 jpm 124
 
1149 gduche 125
	private function migrerTableMotsClesObs() {
126
		$this->migrerTableMotsCles('obs');
127
	}
1198 jpm 128
 
1149 gduche 129
	private function migrerTableMotsClesImages() {
130
		$this->migrerTableMotsCles('images');
131
	}
1198 jpm 132
 
1149 gduche 133
	private function migrerTableMotsCles($image_ou_obs) {
1224 jpm 134
		echo "MIGRATION DES MOTS CLES $image_ou_obs\n";
1149 gduche 135
		$pas = 1;
1198 jpm 136
 
1149 gduche 137
		//limite des mots clés
138
		$requeteNbMotsCles = 'SELECT count(*) as nb FROM cel_mots_cles_'.$image_ou_obs;
1224 jpm 139
		$nbMotsCles = (int) $this->bdd->requeter($requeteNbMotsCles, Bdd::SQL_RETOUR_COLONNE);
140
 
1198 jpm 141
		for ($i = 0; $i < $nbMotsCles; $i += $pas) {
142
			$requete = 'SELECT * '.
143
				'FROM cel_mots_cles_'.$image_ou_obs.' '.
144
				'ORDER BY cmc_niveau '.
145
				"LIMIT $i,$pas ";
1224 jpm 146
			$arbres_mots_cles = $this->bdd->requeter($requete);
1198 jpm 147
 
148
			if (count($arbres_mots_cles) > 0) {
149
				$champ_parent = ($image_ou_obs == "obs") ? 'ce_mot_cle_obs_parent' : 'ce_mot_cle_image_parent';
150
				$champ_id = ($image_ou_obs == "obs") ? 'id_mot_cle_obs' : 'id_mot_cle_image';
151
				$requete = 'INSERT INTO '.self::$bdd_cel_migration.".cel_mots_cles_$image_ou_obs ".
1199 jpm 152
					"($champ_id, id_utilisateur, mot_cle, md5, bg, bd, niveau, $champ_parent) ".
153
					'VALUES ';
1198 jpm 154
 
155
				$sous_requete = array();
156
				foreach ($arbres_mots_cles as $arbre_mot_cle) {
157
					$sous_requete[] = $this->construireSousRequeteInsertionArbresMotsCles('cmc_', $arbre_mot_cle);
1149 gduche 158
				}
1198 jpm 159
				$sous_requete = implode(',', $sous_requete);
160
				$requete .= $sous_requete;
161
 
162
				$migration = $this->executerRequeteSimple($requete);
163
				if (!$migration) {
164
					echo  "La migration des mots cles $image_ou_obs a échoué ! "."\n";
1149 gduche 165
				} else {
1224 jpm 166
					$this->script->afficherAvancement("Migration des mots clés $image_ou_obs (par $pas)");
1149 gduche 167
				}
168
			}
169
		}
1224 jpm 170
		echo "\n";
1149 gduche 171
	}
1198 jpm 172
 
1149 gduche 173
	private function construireSousRequeteInsertionArbresMotsCles($prefixe, $ligne) {
174
		$id_proprietaire_mot_cle = $ligne[$prefixe.'id_proprietaire'];
1181 aurelien 175
		$id_proprietaire_mot_cle = $this->renvoyerIdPourMigration($id_proprietaire_mot_cle);
1198 jpm 176
 
1224 jpm 177
		$sous_requete = '('.$this->bdd->proteger($ligne[$prefixe.'id_mot_cle_utilisateur']).','.
178
			$this->bdd->proteger($id_proprietaire_mot_cle).','.
179
			$this->bdd->proteger($ligne[$prefixe.'mot_cle']).','.
180
			$this->bdd->proteger($ligne[$prefixe.'id_mot_cle_general']).','.
181
			$this->bdd->proteger($ligne[$prefixe.'bg']).','.
182
			$this->bdd->proteger($ligne[$prefixe.'bd']).','.
183
			$this->bdd->proteger($ligne[$prefixe.'niveau']).','.
184
			$this->bdd->proteger($ligne[$prefixe.'id_parent']).
1198 jpm 185
			')';
186
		return $sous_requete;
1149 gduche 187
	}
1198 jpm 188
 
189
	private function renvoyerIdPourMigration($utilisateur) {
190
		// si tout les test suivant échouent, on garde l'utilisateur tel quel
191
		// (cas de la chaine de session des utilisateur anonymes)
192
		$retour = $utilisateur;
193
		// si le mail correspond a un utilisateur de la bdd
194
		if (isset($this->tableau_utilisateurs[$utilisateur])) {
195
			// on renvoie son id
196
			$retour =  $this->tableau_utilisateurs[$utilisateur]['id'];
197
		} else {
198
			// sinon si c'est un mail inconnu, on garde le md5
199
			if ($this->mailValide($utilisateur)) {
200
				$retour = md5($utilisateur);
201
			}
202
		}
203
		return $retour;
204
	}
205
 
1224 jpm 206
	private function mailValide($mail) {
1198 jpm 207
		// vérification bidon mais ça suffit pour ici
1224 jpm 208
		return !(strpos($mail, '@') === false);
1198 jpm 209
	}
210
 
211
	private function migrerLiaisonsMotsClesObs() {
212
		$requete = 'SELECT mots_cles AS mots_cles, id AS id, identifiant AS id_utilisateur '.
213
				'FROM cel_inventory '.
1199 jpm 214
				'WHERE mots_cles != "" '.
215
				'	AND mots_cles != "NULL" '.
216
				'	AND mots_cles != "null" '.
1198 jpm 217
				'	AND mots_cles IS NOT NULL '.
218
				'ORDER BY identifiant ';
1224 jpm 219
		$mots_cles_obs = $this->bdd->requeter($requete);
1198 jpm 220
 
221
		$requete = 'INSERT INTO '.self::$bdd_cel_migration.'.cel_obs_mots_cles '.
222
				'(id_observation, id_mot_cle_obs, id_utilisateur) '.
223
				'VALUES '.
224
				$this->construireSousRequeteInsertionLiaisons($mots_cles_obs, ';');
225
 
226
		$insertion = $this->executerRequeteSimple($requete);
227
		if (!$insertion) {
228
			echo 'La migration des mots cles obs a échoué ! '."\n";
229
		} else {
1224 jpm 230
			echo "Migration des mots cles obs : OK\n";
1198 jpm 231
		}
232
	}
233
 
234
	private function migrerLiaisonsMotsClesImages() {
235
		$requete = 'SELECT ci_meta_mots_cles AS mots_cles, ci_id_image AS id, ci_ce_utilisateur AS id_utilisateur '.
236
				'FROM cel_images '.
1199 jpm 237
				'WHERE ci_meta_mots_cles != "" '.
238
				'	AND ci_meta_mots_cles != "NULL" '.
239
				'	AND ci_meta_mots_cles != "null" '.
1198 jpm 240
				'	AND ci_meta_mots_cles IS NOT NULL '.
241
				'ORDER BY ci_ce_utilisateur';
1224 jpm 242
		$mots_cles_images = $this->bdd->requeter($requete);
1198 jpm 243
 
244
		$requete = 'INSERT INTO '.self::$bdd_cel_migration.'.cel_images_mots_cles '.
245
				'(id_image, id_mot_cle_image, id_utilisateur) '.
246
				'VALUES '.
247
				$this->construireSousRequeteInsertionLiaisons($mots_cles_images, ',');
248
 
249
		$insertion = $this->executerRequeteSimple($requete);
250
 
251
		if (!$insertion) {
252
			echo 'La migration des mots cles images a échoué ! '."\n";
253
		} else {
1224 jpm 254
			echo "Migration des mots cles images : OK\n";
1198 jpm 255
		}
256
	}
257
 
258
	private function construireSousRequeteInsertionLiaisons($tableau_mots_cles, $separateur) {
259
		$sous_requete = array();
260
		foreach ($tableau_mots_cles as $element) {
261
			$mots_cles_ids = $this->parserMotsCles($element['mots_cles'], $separateur);
262
			foreach ($mots_cles_ids as $mot_cle_id) {
1224 jpm 263
				$id = $this->bdd->proteger($element['id']);
264
				$id_mot_cle = $this->bdd->proteger($mot_cle_id);
265
				$id_utilisateur = $this->bdd->proteger($this->renvoyerIdPourMigration($element['id_utilisateur']));
1198 jpm 266
				$sous_requete[] = "($id, $id_mot_cle, $id_utilisateur)";
1149 gduche 267
			}
268
		}
1198 jpm 269
		$sous_requete_chaine = implode(',', $sous_requete);
270
		return $sous_requete_chaine;
1149 gduche 271
	}
1198 jpm 272
 
1149 gduche 273
	private function parserMotsCles($mot_cles, $separateur = ',') {
1199 jpm 274
		$mot_cles = trim($mot_cles, $separateur);
1198 jpm 275
		$tableau_mots_cles = explode($separateur, $mot_cles);
276
 
1149 gduche 277
		$tableau_mots_cles_formates = array();
1198 jpm 278
		foreach ($tableau_mots_cles as $mot_cle) {
279
			$mot_cle = str_replace($separateur.$separateur, '', $mot_cle);
280
			$mot_cle = str_replace('null', '', $mot_cle);
1199 jpm 281
			$mot_cle = trim($mot_cle);
1198 jpm 282
 
283
			if ($this->estUnIdentifiantMotCle($mot_cle)) {
1149 gduche 284
				// certains mots clés mal formatés contiennent des virgules
1198 jpm 285
				if (strpos($mot_cle, ',') !== false) {
286
					$tab_mot_cle_mal_formate = explode(',', $mot_cle);
287
 
1149 gduche 288
					foreach ( $tab_mot_cle_mal_formate as $mot_cle_mal_formate) {
1198 jpm 289
						if ($this->estUnIdentifiantMotCle($mot_cle_mal_formate)) {
1149 gduche 290
							$tableau_mots_cles_formates[$mot_cle_mal_formate] = $mot_cle_mal_formate;
291
						}
1198 jpm 292
					}
1149 gduche 293
				} else {
294
					// on met le mot clé dans sa propre case afin d'éviter
1198 jpm 295
					// facilement les doublons provoqués par de mauvais formatages
1149 gduche 296
					$tableau_mots_cles_formates[$mot_cle] = $mot_cle;
297
				}
1199 jpm 298
			} else if ($mot_cle != '') {
299
				echo "N'est pas un mot clé : $mot_cle\n";
1149 gduche 300
			}
301
		}
302
		return $tableau_mots_cles_formates;
303
	}
1198 jpm 304
 
1149 gduche 305
	private function estUnIdentifiantMotCle($chaine) {
1199 jpm 306
		return preg_match('/^(?:[-][0-9]+[.][0-9]+|[-_a-z0-9]+(?:[.][-_a-z0-9]+)*)$/i', $chaine);
1149 gduche 307
	}
1198 jpm 308
 
1161 aurelien 309
	private function genererIndexTexteMotsClesObs() {
1199 jpm 310
		$requete = 'SELECT DISTINCT id_observation, id_utilisateur '.
311
			'FROM '.self::$bdd_cel_migration.'.cel_obs_mots_cles ';
1224 jpm 312
		$obs_a_mots_cles = $this->bdd->requeter($requete);
1198 jpm 313
 
314
		foreach ($obs_a_mots_cles as $obs) {
1199 jpm 315
			$mots_cles_texte = $this->obtenirMotsClesTexte($obs['id_observation'], $obs['id_utilisateur'], 'obs');
1161 aurelien 316
			if (is_array($mots_cles_texte) && count($mots_cles_texte) > 0) {
317
				$mots_cles_texte_chaine = implode(',', $mots_cles_texte);
1199 jpm 318
				$mise_a_jour_index = $this->executerRequeteMiseAJourMotCleTexte($mots_cles_texte_chaine, $obs['id_observation'], $obs['id_utilisateur'], 'obs');
1224 jpm 319
				$this->script->afficherAvancement('Génération des index mots clés obs (par 1)');
1161 aurelien 320
			}
321
		}
1224 jpm 322
		echo "\n";
1161 aurelien 323
	}
1198 jpm 324
 
1161 aurelien 325
	private function genererIndexTexteMotsClesImages() {
1199 jpm 326
		$requete = 'SELECT DISTINCT id_image, id_utilisateur '.
327
			'FROM '.self::$bdd_cel_migration.'.cel_images_mots_cles ';
1224 jpm 328
		$images_a_mots_cles = $this->bdd->requeter($requete);
1198 jpm 329
 
330
		foreach ($images_a_mots_cles as $image) {
1199 jpm 331
			$mots_cles_texte = $this->obtenirMotsClesTexte($image['id_image'], $image['id_utilisateur'], 'images');
1161 aurelien 332
			$mots_cles_texte_chaine = '';
333
			if (is_array($mots_cles_texte) && count($mots_cles_texte) > 0) {
334
				$mots_cles_texte_chaine = implode(',', $mots_cles_texte);
1199 jpm 335
				$mise_a_jour_index = $this->executerRequeteMiseAJourMotCleTexte($mots_cles_texte_chaine, $image['id_image'], $image['id_utilisateur'], 'images');
1224 jpm 336
				$this->script->afficherAvancement('Génération des index mots clés images (par 1)');
1161 aurelien 337
			}
338
		}
1224 jpm 339
		echo "\n";
1161 aurelien 340
	}
1198 jpm 341
 
1199 jpm 342
	private function obtenirMotsClesTexte($id_image_ou_obs, $id_utilisateur, $mode) {
343
		$bdd = self::$bdd_cel_migration;
344
		$champ_id_mot_cle = ($mode == 'obs') ? 'id_mot_cle_obs' : 'id_mot_cle_image';
345
		$champ_id_obs_ou_img = ($mode == 'obs') ? 'id_observation' : 'id_image';
1224 jpm 346
		$id_image_ou_obs = $this->bdd->proteger($id_image_ou_obs);
347
		$id_utilisateur = $this->bdd->proteger($id_utilisateur);
1198 jpm 348
 
1199 jpm 349
		$requete = 'SELECT mot_cle '.
350
				"FROM $bdd.cel_mots_cles_$mode AS a ".
351
				"	INNER JOIN $bdd.cel_{$mode}_mots_cles AS b ".
352
				"	ON (a.$champ_id_mot_cle = b.$champ_id_mot_cle AND a.id_utilisateur = b.id_utilisateur) ".
353
				"WHERE b.$champ_id_obs_ou_img = $id_image_ou_obs ".
354
				"	AND a.id_utilisateur = $id_utilisateur ";
1224 jpm 355
		$resultats = $this->bdd->requeter($requete);
1198 jpm 356
 
1161 aurelien 357
		$mots_cles = array();
1198 jpm 358
		foreach ($resultats as $resultat) {
1161 aurelien 359
			$mots_cles[] = $resultat['mot_cle'];
360
		}
1198 jpm 361
 
1161 aurelien 362
		return $mots_cles;
363
	}
1199 jpm 364
 
365
	private function executerRequeteMiseAJourMotCleTexte($mots_cles_texte_chaine, $id_image_ou_obs, $id_utilisateur, $mode_image_ou_obs) {
366
		$bdd = self::$bdd_cel_migration;
367
		$table = ($mode_image_ou_obs == 'obs') ? 'cel_obs' : 'cel_images';
368
		$chp_id_obs_ou_img = ($mode_image_ou_obs == 'obs') ? 'id_observation' : 'id_image';
1224 jpm 369
		$id_image_ou_obs = $this->bdd->proteger($id_image_ou_obs);
370
		$mots_cles_texte = $this->bdd->proteger($mots_cles_texte_chaine);
371
		$ce_utilisateur = $this->bdd->proteger($id_utilisateur);
1199 jpm 372
 
373
		$requete = 	"UPDATE $bdd.$table ".
374
			"SET mots_cles_texte = $mots_cles_texte ".
375
			"WHERE $chp_id_obs_ou_img = $id_image_ou_obs ".
1224 jpm 376
			"	AND ce_utilisateur = $ce_utilisateur ";
1199 jpm 377
 
1224 jpm 378
		return $this->bdd->executer($requete);
1199 jpm 379
	}
1200 jpm 380
 
381
	private function mettreANullMotsClesTxtVide() {
382
		$bdd = self::$bdd_cel_migration;
383
		$tables = array('cel_obs', 'cel_images');
384
 
385
		foreach ($tables as $table) {
386
			$requete = 	"UPDATE $bdd.$table ".
387
				'SET mots_cles_texte = NULL '.
388
				"WHERE mots_cles_texte = '' ";
1224 jpm 389
			$this->bdd->executer($requete);
1200 jpm 390
		}
391
	}
1149 gduche 392
}