Subversion Repositories eFlore/Applications.cel

Rev

Rev 1640 | Rev 1646 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 1640 Rev 1642
Line 85... Line 85...
85
		"latitude",
85
		"latitude",
86
		"longitude");
86
		"longitude");
Line 87... Line 87...
87
 
87
 
88
	/*
88
	/*
89
	  Ces colonnes:
89
	  Ces colonnes:
90
	  - sont propre à tous les enregistrements uploadés
90
	  - sont propres à l'ensemble des enregistrements uploadés
91
	  - sont indépendantes du numéro de lignes
91
	  - sont indépendantes du numéro de lignes
92
	  - n'ont pas de valeur par défaut dans la structure de la table
92
	  - n'ont pas de valeur par défaut dans la structure de la table
93
	  - nécessitent une initialisation dans le cadre de l'upload
93
	  - nécessitent une initialisation dans le cadre de l'upload
94
	*/
94
	*/
95
	public $colonnes_statiques = Array(
95
	public $colonnes_statiques = Array(
96
		"ce_utilisateur" => NULL,
96
		"ce_utilisateur" => NULL,
97
		"prenom_utilisateur" => NULL,
97
		"prenom_utilisateur" => NULL,
98
		"nom_utilisateur" => NULL,
98
		"nom_utilisateur" => NULL,
Line -... Line 99...
-
 
99
		"courriel_utilisateur" => NULL,
99
		"courriel_utilisateur" => NULL,
100
 
100
 
101
		// fixes (fonction SQL)
101
		// XXX: fixes (mais pourraient varier dans le futur si la mise-à-jour
102
		// XXX future: mais pourraient varier dans le futur si la mise-à-jour
102
		// d'observation est implémentée
103
		// d'observation est implémentée
103
		"date_creation" => NULL, // ne peut initialiser d'une date ici
104
		"date_creation" => "now()",
Line -... Line 105...
-
 
105
		"date_modification" => "now()",
-
 
106
	);
-
 
107
 
-
 
108
	public $id_utilisateur = NULL;
104
		"date_modification" => NULL, // idem, cf initialiser_colonnes_statiques()
109
	// erreurs d'import
105
	);
110
	public $bilan = Array();
106
 
111
 
Line 107... Line 112...
107
	function ExportXLS($config) {
112
	function ExportXLS($config) {
108
		parent::__construct($config);
113
		parent::__construct($config);
109
	}
114
	}
110
 
115
 
111
	function createElement($pairs) {
116
	function createElement($pairs) {
-
 
117
		if(!isset($pairs['utilisateur']) || trim($pairs['utilisateur']) == '') {
Line 112... Line 118...
112
		if(!isset($pairs['utilisateur']) || trim($pairs['utilisateur']) == '') {
118
			echo '0'; exit;
113
			echo '0'; exit;
119
		}
Line 114... Line 120...
114
		}
120
		$id_utilisateur = intval($pairs['utilisateur']);
Line 130... Line 136...
130
		$objReader->setReadDataOnly(true);
136
		$objReader->setReadDataOnly(true);
131
		$objPHPExcel = $objReader->load($infos_fichier['tmp_name']);*/
137
		$objPHPExcel = $objReader->load($infos_fichier['tmp_name']);*/
Line 132... Line 138...
132
 
138
 
Line -... Line 139...
-
 
139
		//var_dump($donnees);
-
 
140
 
-
 
141
		// renomme le fichier pour lui ajouter son extension initiale, ce qui
-
 
142
		// permet (une sorte) d'autodétection du format.
-
 
143
		$fichier = $infos_fichier['tmp_name'];
-
 
144
		$extension = pathinfo($infos_fichier['name'], PATHINFO_EXTENSION);
-
 
145
		if( (strlen($extension) == 3 || strlen($extension) == 4) &&
-
 
146
			(rename($fichier, $fichier . '.' . $extension))) {
-
 
147
			$fichier = $fichier . '.' . $extension;
133
		//var_dump($donnees);
148
		}
134
 
149
 
Line -... Line 150...
-
 
150
		$objReader = PHPExcel_IOFactory::createReaderForFile($fichier);
-
 
151
		$objReader->setReadDataOnly(true);
-
 
152
 
-
 
153
		if(is_a($objReader, 'PHPExcel_Reader_CSV')) {
-
 
154
			$objReader->setDelimiter(',')
-
 
155
				->setEnclosure('"')
-
 
156
				->setLineEnding("\n")
135
		$objReader = PHPExcel_IOFactory::createReader("Excel5");
157
				->setSheetIndex(0);
136
		$objReader->setReadDataOnly(true);
158
		}
137
 
159
 
138
		// on ne conserve que l'en-tête
160
		// on ne conserve que l'en-tête
Line 139... Line 161...
139
		$filtre = new MyReadFilter();
161
		$filtre = new MyReadFilter();
140
		$filtre->def_interval(1, 2);
162
		$filtre->def_interval(1, 2);
141
		$objReader->setReadFilter($filtre);
163
		$objReader->setReadFilter($filtre);
142
 
164
 
Line 143... Line 165...
143
		$objPHPExcel = $objReader->load($infos_fichier['tmp_name']);
165
		$objPHPExcel = $objReader->load($fichier);
144
		$obj_infos = $objReader->listWorksheetInfo($infos_fichier['tmp_name']);
166
		$obj_infos = $objReader->listWorksheetInfo($fichier);
Line 152... Line 174...
152
		$obs_maj = 0;
174
		$obs_maj = 0;
153
		$dernier_ordre = $this->requeter("SELECT MAX(ordre) AS ordre FROM cel_obs WHERE ce_utilisateur = $id_utilisateur");
175
		$dernier_ordre = $this->requeter("SELECT MAX(ordre) AS ordre FROM cel_obs WHERE ce_utilisateur = $id_utilisateur");
154
		$dernier_ordre = intval($dernier_ordre[0]['ordre']) + 1;
176
		$dernier_ordre = intval($dernier_ordre[0]['ordre']) + 1;
155
		if(! $dernier_ordre) $dernier_ordre = 0;
177
		if(! $dernier_ordre) $dernier_ordre = 0;
Line -... Line 178...
-
 
178
 
-
 
179
		// on catch to les trigger_error(E_USER_NOTICE);
-
 
180
		set_error_handler(array($this, 'erreurs_stock'), E_USER_NOTICE);
156
 
181
 
157
		// lecture par morceaux (chunks), NB_LIRE_LIGNE_SIMUL lignes à fois
182
		// lecture par morceaux (chunks), NB_LIRE_LIGNE_SIMUL lignes à fois
158
		// pour aboutir des requêtes SQL d'insert groupés.
183
		// pour aboutir des requêtes SQL d'insert groupés.
159
		for($ligne = 2; $ligne < $nb_lignes + NB_LIRE_LIGNE_SIMUL; $ligne += NB_LIRE_LIGNE_SIMUL) {
184
		for($ligne = 2; $ligne < $nb_lignes + NB_LIRE_LIGNE_SIMUL; $ligne += NB_LIRE_LIGNE_SIMUL) {
160
			$filtre->def_interval($ligne, NB_LIRE_LIGNE_SIMUL);
185
			$filtre->def_interval($ligne, NB_LIRE_LIGNE_SIMUL);
Line 161... Line 186...
161
			$objReader->setReadFilter($filtre);
186
			$objReader->setReadFilter($filtre);
162
 
187
 
163
			/* recharge avec $filtre actif (filtre sur lignes colonnes):
188
			/* recharge avec $filtre actif (filtre sur lignes colonnes):
164
			   - exclue les colonnes inutiles/inutilisables)
189
			   - exclue les colonnes inutiles/inutilisables)
165
			   - ne selectionne que les lignes dans le range [$ligne - $ligne + NB_LIRE_LIGNE_SIMUL] */
190
			   - ne selectionne que les lignes dans le range [$ligne - $ligne + NB_LIRE_LIGNE_SIMUL] */
Line 166... Line 191...
166
			$objPHPExcel = $objReader->load($infos_fichier['tmp_name']);
191
			$objPHPExcel = $objReader->load($fichier);
167
			$donnees = $objPHPExcel->getActiveSheet()->toArray(NULL, FALSE, FALSE, TRUE);
192
			$donnees = $objPHPExcel->getActiveSheet()->toArray(NULL, FALSE, FALSE, TRUE);
Line 168... Line 193...
168
 
193
 
169
			// ici on appel la fonction qui fera effectivement l'insertion multiple
194
			// ici on appel la fonction qui fera effectivement l'insertion multiple
-
 
195
			// à partir des (au plus) NB_LIRE_LIGNE_SIMUL lignes
170
			// à partir des (au plus) NB_LIRE_LIGNE_SIMUL lignes
196
 
-
 
197
			// TODO: passer $this, ne sert que pour appeler des méthodes public qui pourraient être statiques
-
 
198
			// notamment dans RechercheInfosTaxonBeta.php
-
 
199
			list($enregistrements, $images) =
-
 
200
				self::chargerLignes($this, $donnees, $this->colonnes_statiques, $dernier_ordre);
-
 
201
			if(! $enregistrements) break;
-
 
202
 
171
 
203
			$dernier_autoinc = self::stockerEnregistrements($this, $enregistrements);
-
 
204
			$obs_ajouts += count($enregistrements);
172
			// TODO: passer $this, ne sert que pour appeler des méthodes public qui pourraient être statiques
205
			// $obs_maj += count($enregistrements_a_MAJ);
-
 
206
			self::stockerImages($this, $enregistrements, $images, $dernier_autoinc);
-
 
207
		}
-
 
208
 
-
 
209
		restore_error_handler();
173
			// notamment dans RechercheInfosTaxonBeta.php
210
 
Line 174... Line 211...
174
			self::chargerLignes($donnees, $this->colonnes_statiques, $dernier_ordre, $this, $obs_ajouts, $obs_maj);
211
		if($this->bilan) echo implode("\n", $this->bilan) . "\n";
175
		}
212
		// fin: renvoi summary
176
		die('end');
213
		die("$obs_ajouts observations ajoutées");
Line 183... Line 220...
183
			$entete_simple = iconv('UTF-8', 'ASCII//TRANSLIT', strtolower(trim($v)));
220
			$entete_simple = iconv('UTF-8', 'ASCII//TRANSLIT', strtolower(trim($v)));
184
			foreach($cols as $col) {
221
			foreach($cols as $col) {
185
				$entete_officiel_simple = iconv('UTF-8', 'ASCII//TRANSLIT', strtolower(trim($col['nom'])));
222
				$entete_officiel_simple = iconv('UTF-8', 'ASCII//TRANSLIT', strtolower(trim($col['nom'])));
186
				$entete_officiel_abbrev = $col['abbrev'];
223
				$entete_officiel_abbrev = $col['abbrev'];
187
				if($entete_simple == $entete_officiel_simple || $entete_simple == $entete_officiel_abbrev) {
224
				if($entete_simple == $entete_officiel_simple || $entete_simple == $entete_officiel_abbrev) {
188
					// debug echo "define C_" . strtoupper($entete_officiel_abbrev) . ", $k\n";
225
					//debug echo "define C_" . strtoupper($entete_officiel_abbrev) . ", $k ($v)\n";
189
					define("C_" . strtoupper($entete_officiel_abbrev), $k);
226
					define("C_" . strtoupper($entete_officiel_abbrev), $k);
190
					$colonnes_reconnues[$k] = 1;
227
					$colonnes_reconnues[$k] = 1;
191
					break;
228
					break;
192
				}
229
				}
193
			}
230
			}
Line 217... Line 254...
217
	}
254
	}
Line 218... Line 255...
218
 
255
 
219
	/*
256
	/*
220
	 * charge un groupe de lignes
257
	 * charge un groupe de lignes
221
	 */
258
	 */
222
	static function chargerLignes($lignes, $colonnes_statiques, &$dernier_ordre, $cel, &$inserted, &$updated) {
259
	static function chargerLignes($cel, $lignes, $colonnes_statiques, &$dernier_ordre) {
223
		$enregistrement = NULL;
260
		$enregistrement = NULL;
224
		$enregistrements = Array();
261
		$enregistrements = Array();
Line 225... Line 262...
225
		$images = Array();
262
		$toutes_images = Array();
226
 
263
 
227
		foreach($lignes as $ligne) {
264
		foreach($lignes as $ligne) {
-
 
265
			//$ligne = array_filter($ligne, function($cell) { return !is_null($cell); });
-
 
266
			//if(!$ligne) continue;
Line 228... Line 267...
228
			$ligne = array_filter($ligne, function($cell) { return !is_null($cell); });
267
			// on a besoin des NULL pour éviter des notice d'index indéfini
229
			if(!$ligne) continue;
268
			if(! array_filter($ligne, function($cell) { return !is_null($cell); })) continue;
Line 230... Line 269...
230
 
269
 
231
			if( ($enregistrement = self::chargerLigne($ligne, $colonnes_statiques, $dernier_ordre, $cel)) ) {
270
			if( ($enregistrement = self::chargerLigne($ligne, $dernier_ordre, $cel)) ) {
-
 
271
				$enregistrements[] = array_merge($colonnes_statiques, $enregistrement);
232
				$enregistrements[] = $enregistrement;
272
 
233
 
273
				if(isset($enregistrement['_images'])) {
234
				if(isset($enregistrement['_images'])) {
274
					$pos = count($enregistrements) - 1;
235
					$pos = count($enregistrements) - 1;
275
					$last = &$enregistrements[$pos];
236
					// ne dépend pas de cel_obs, et seront insérées *après* les enregistrements
276
					// ne dépend pas de cel_obs, et seront insérées *après* les enregistrements
237
					// mais nous ne voulons pas nous priver de faire des INSERT multiples pour autant
277
					// mais nous ne voulons pas nous priver de faire des INSERT multiples pour autant
238
					$images[] = Array("text" => $enregistrements[$pos]['_images'],
278
					$toutes_images[] = Array("images" => $last['_images'],
239
									  "obs_pos" => $pos);
279
											 "obs_pos" => $pos);
Line 240... Line 280...
240
					// ce champ n'a pas a faire partie de l'insertion dans cel_obs,
280
					// ce champ n'a pas a faire partie de l'insertion dans cel_obs,
241
					// mais est utile pour cel_obs_images
281
					// mais est utile pour cel_obs_images
242
					unset($enregistrements[$pos]['_images']);
282
					unset($last['_images']);
Line -... Line 283...
-
 
283
				}
243
				}
284
 
-
 
285
				$dernier_ordre++;
-
 
286
			}
Line -... Line 287...
-
 
287
		}
244
 
288
 
Line 245... Line -...
245
				$dernier_ordre++;
-
 
246
			}
289
		// XXX future: return Array($enregistrements_a_inserer, $enregistrements_a_MAJ, $toutes_images);
247
		}
290
		return Array($enregistrements, $toutes_images);
-
 
291
	}
-
 
292
 
248
 
293
 
-
 
294
	static function stockerEnregistrements($cel, $enregistrements) {
-
 
295
		$req = '';
-
 
296
 
-
 
297
		foreach($enregistrements as $enregistrement) {
Line 249... Line 298...
249
		if(!$enregistrements) die('AIE // XXX');
298
			$enregistrement = self::sortArrayByArray($enregistrement, self::$ordre_BDD);
250
 
299
			array_walk($enregistrement,
251
		$req = '';
300
					   function(&$item, $k, $obj) { $item = is_null($item) ? "NULL" : $item; },
-
 
301
					   $cel);
-
 
302
			$req .= implode(', ', $enregistrement) . "\n";
-
 
303
		}
-
 
304
		echo "$req\n";
-
 
305
		// TODO: insert
-
 
306
 
-
 
307
		// $cel->executer($req);
-
 
308
		// transactionnel + auto-inc
-
 
309
		return $cel->bdd->lastInsertId();
-
 
310
	}
-
 
311
 
-
 
312
 
252
 
313
	static function stockerImages($cel, $enregistrements, $toutes_images, $lastid) {
253
 
314
		if(! $lastid) $lastid = rand();
254
		foreach($enregistrements as $enregistrement)
315
 
255
			$req .= implode(', ', self::sortArrayByArray($enregistrement, self::$ordre_BDD));
316
		$images_insert =
256
		print_r($req);
317
			'INSERT INTO cel_obs_images (id_image, id_observation) VALUES'
-
 
318
			.' %s '
-
 
319
			.'ON DUPLICATE KEY UPDATE id_image = id_image';
-
 
320
		$images_obs_assoc = Array();
-
 
321
 
-
 
322
		foreach($toutes_images as $images_pour_obs) {
-
 
323
			$obs = $enregistrements[$images_pour_obs["obs_pos"]];
-
 
324
			$id_obs = $lastid // dernier autoinc inséré
-
 
325
				- count($enregistrements) - 1 // correspondrait au premier autoinc
-
 
326
				+ $images_pour_obs["obs_pos"]; // ordre d'insertion = ordre dans le tableau $enregistrements
257
 
327
			foreach($images_pour_obs['images'] as $image) {
258
		// $cel->executer($req);
328
				$images_obs_assoc[] = sprintf('(%d,%d)',
259
		// transactionnel + auto-inc
329
											  $image['id_image'], // intval() useless
Line 260... Line 330...
260
		$lastid = $cel->bdd->lastInsertId();
330
											  $id_obs); // intval() useless
261
		foreach($images as $image) {
331
			}
262
			$obs = $enregistrements[$image["obs_pos"]];
332
		}
263
			$id_obs = $lastid // dernier autoinc inséré
333
 
Line 264... Line 334...
264
				- count($enregistrements) - 1 // correspondrait au premier autoinc
334
		if($images_obs_assoc) {
265
				+ $image["obs_pos"]; // ordre d'insertion = ordre dans le tableau $enregistrements
335
			$requete = sprintf($images_insert, implode(', ', $images_obs_assoc));
-
 
336
			echo "$requete\n";
266
			// TODO: INSERT
337
		}
Line -... Line 338...
-
 
338
	}
-
 
339
 
267
		}
340
 
-
 
341
	static function chargerLigne($ligne, $dernier_ordre, $cel) {
268
	}
342
		// en premier car le résultat est utile pour
269
 
343
		// traiter longitude et latitude (traiterLonLat())
270
 
344
		$referentiel = self::identReferentiel($ligne[C_NOM_REFERENTIEL]);
271
	static function chargerLigne($ligne, $colonnes_statiques, $dernier_ordre, $cel) {
345
 
Line -... Line 346...
-
 
346
		// $espece est rempli de plusieurs informations
272
		// en premier car le résultat est utile pour
347
		$espece = Array(C_NOM_SEL => NULL, C_NOM_SEL_NN => NULL, C_NOM_RET => NULL,
273
		// traiter longitude et latitude (traiterLonLat())
348
						C_NOM_RET_NN => NULL, C_NT => NULL, C_FAMILLE => NULL);
274
		$referentiel = self::identReferentiel($ligne[C_NOM_REFERENTIEL]);
349
		self::traiterEspece($ligne, $espece, $cel);
275
 
350
 
276
		// $espece est rempli de plusieurs informations
351
		// $localisation est rempli à partir de plusieurs champs: C_ZONE_GEO et C_CE_ZONE_GEO
277
		$espece = Array();
352
		$localisation = Array(C_ZONE_GEO => NULL, C_CE_ZONE_GEO => NULL);
Line 278... Line 353...
278
		self::traiterEspece($ligne, $espece, $cel);
353
		self::traiterLocalisation($ligne, $localisation, $cel);
Line -... Line 354...
-
 
354
 
279
 
355
		// Dans ce tableau, seules devraient apparaître les données variable pour chaque ligne.
280
		return array_merge($colonnes_statiques,
356
		// Dans ce tableau, l'ordre des clefs n'importe pas (cf: self::sortArrayByArray())
-
 
357
		$enregistrement = Array(
-
 
358
			"ordre" => $dernier_ordre,
-
 
359
 
-
 
360
			// $this->quoteNonNull() est déjà appliquée dans traiterEspece()
-
 
361
			"nom_sel" => $espece[C_NOM_SEL],
-
 
362
			"nom_sel_nn" => $espece[C_NOM_SEL_NN],
-
 
363
			"nom_ret" => $espece[C_NOM_RET],
-
 
364
			"nom_ret_nn" => $espece[C_NOM_RET_NN],
Line 281... Line -...
281
						   // Dans ce tableau, seules devraient apparaître les données variable pour chaque ligne.
-
 
282
						   // Dans ce tableau, l'ordre des clefs n'importe pas (cf: self::sortArrayByArray())
-
 
283
						   Array(
-
 
284
							   "ordre" => $dernier_ordre,
-
 
285
 
-
 
Line 286... Line 365...
286
							   "nom_sel" => $espece[C_NOM_SEL],
365
			"nt" => $espece[C_NT],
Line -... Line 366...
-
 
366
			"famille" => $espece[C_FAMILLE],
287
							   "nom_sel_nn" => $espece[C_NOM_SEL_NN],
367
 
288
							   "nom_ret" => $espece[C_NOM_RET],
368
			"nom_referentiel" => $cel->quoteNonNull($referentiel),
289
							   "nom_ret_nn" => $espece[C_NOM_RET_NN],
369
 
-
 
370
			// $this->quoteNonNull() est déjà appliquée dans traiterLocalisation()
-
 
371
			"zone_geo" => $localisation[C_ZONE_GEO],
-
 
372
			"ce_zone_geo" => $localisation[C_CE_ZONE_GEO],
-
 
373
 
-
 
374
			// $ligne: uniquement pour les infos en cas de gestion d'erreurs (date incompréhensible)
-
 
375
			"date_observation" => $cel->quoteNonNull(self::traiterDateObs($ligne[C_DATE_OBSERVATION], $ligne)),
-
 
376
 
290
							   "nt" => $espece[C_NT],
377
			"lieudit" => $cel->quoteNonNull(trim($ligne[C_LIEUDIT])),
-
 
378
			"station" => $cel->quoteNonNull(trim($ligne[C_STATION])),
-
 
379
			"milieu" => $cel->quoteNonNull(trim($ligne[C_MILIEU])),
-
 
380
			"commentaire" => $cel->quoteNonNull(trim($ligne[C_COMMENTAIRE])), // TODO: foreign-key
-
 
381
 
-
 
382
 
-
 
383
			"transmission" => in_array(strtolower(trim($ligne[C_TRANSMISSION])), array(1, 'oui')) ? 1 : 0,
-
 
384
 
-
 
385
			// $ligne: uniquement pour les infos en cas de gestion d'erreurs (lon/lat incompréhensible)
-
 
386
			"latitude" => self::traiterLonLat(NULL, $ligne[C_LATITUDE], $referentiel, $ligne),
-
 
387
			"longitude" => self::traiterLonLat($ligne[C_LONGITUDE], NULL, $referentiel, $ligne),
-
 
388
		);
-
 
389
 
Line -... Line 390...
-
 
390
		// passage de $enregistrement par référence, ainsi ['_images'] n'est défini
-
 
391
		// que si des résultats sont trouvés
Line 291... Line 392...
291
							   "famille" => $espece[C_FAMILLE],
392
		// "@" car PHPExcel supprime les colonnes null sur toute la feuille (ou tout le chunk)
Line 292... Line 393...
292
 
393
		if(@$ligne[C_IMAGES]) self::traiterImage($ligne[C_IMAGES], $cel, $enregistrement);
293
							   "nom_referentiel" => $referentiel,
394
 
294
 
395
		return $enregistrement;
295
							   "zone_geo" => TODO,
396
	}
296
							   "ce_zone_geo" => self::traiterDepartement(trim($ligne[C_CE_ZONE_GEO])),
397
 
297
 
398
	static function traiterImage($str, $cel, &$enregistrement) {
298
							   "date_observation" => self::traiterDateObs($ligne[C_DATE_OBSERVATION]),
399
		$liste_images = array_filter(explode("/", $str));
299
							   "lieudit" => trim($ligne[C_LIEUDIT]),
400
		array_walk($liste_images,
-
 
401
				   function($item, $key, $obj) { $item = $obj->quoteNonNull(trim($item)); },
-
 
402
				   $cel);
-
 
403
		$requete = sprintf(
-
 
404
			"SELECT id_image, nom_original FROM cel_images WHERE ce_utilisateur = %d AND nom_original IN (\"%s\")",
300
							   "station" => trim($ligne[C_STATION]),
405
			$cel->id_utilisateur,
Line 301... Line 406...
301
							   "milieu" => trim($ligne[C_MILIEU]),
406
			implode('","', $liste_images));
302
							   "commentaire" => trim($ligne[C_COMMENTAIRE]), // TODO: foreign-key
407
 
303
 
408
		$resultat = $cel->requeter($requete);
Line 330... Line 435...
330
 
435
 
331
			// echo strftime("%Y/%m/%d 00:00:00", $timestamp); // NON
436
			// echo strftime("%Y/%m/%d 00:00:00", $timestamp); // NON
332
		}
437
		}
333
		else {
438
		else {
334
			$timestamp = strtotime($date);
439
			$timestamp = strtotime($date);
-
 
440
			if(! $timestamp) {
-
 
441
				if($date) trigger_error("ligne \"{$ligne[C_NOM_SEL]}\": Attention: date erronée ($date)", E_USER_NOTICE);
-
 
442
				return NULL;
335
			if(!$timestamp) return NULL; // TODO: throw error
443
			}
336
			return strftime("%Y-%m-%d 00:00:00", strtotime($date));
444
			return strftime("%Y-%m-%d 00:00:00", strtotime($date));
337
		}
445
		}
Line 338... Line 446...
338
	}
446
	}
339
 
447
 
340
	static function identReferentiel($referentiel) {
448
	static function identReferentiel($referentiel) {
341
		// SELECT DISTINCT nom_referentiel, COUNT(id_observation) AS count FROM cel_obs GROUP BY nom_referentiel ORDER BY count DESC;
449
		// SELECT DISTINCT nom_referentiel, COUNT(id_observation) AS count FROM cel_obs GROUP BY nom_referentiel ORDER BY count DESC;
342
		if(strpos(strtolower($referentiel), 'bdtfx') !== FALSE) return 'bdtfx:v1.01';
450
		if(strpos(strtolower($referentiel), 'bdtfx') !== FALSE) return 'bdtfx:v1.01';
343
		if(strpos(strtolower($referentiel), 'bdtxa') !== FALSE) return 'bdtxa:v1.00';
451
		if(strpos(strtolower($referentiel), 'bdtxa') !== FALSE) return 'bdtxa:v1.00';
-
 
452
		if(strpos(strtolower($referentiel), 'bdnff') !== FALSE) return 'bdnff:4.02';
-
 
453
		if(strpos(strtolower($referentiel), 'isfan') !== FALSE) return 'isfan:v1.00';
-
 
454
 
-
 
455
		if($referentiel) {
344
		if(strpos(strtolower($referentiel), 'bdnff') !== FALSE) return 'bdnff:4.02';
456
			trigger_error("ligne \"{$ligne[C_NOM_SEL]}\": Attention: référentiel inconnu", E_USER_NOTICE);
345
		if(strpos(strtolower($referentiel), 'isfan') !== FALSE) return 'isfan:v1.00';
457
		}
346
		return NULL;
458
		return NULL;
-
 
459
		/* TODO: cf story,
-
 
460
		   En cas de NULL faire une seconde passe de détection à partir du nom saisi
-
 
461
		   + accepter les n° de version */
-
 
462
	}
-
 
463
 
-
 
464
	static function traiterLonLat($lon = NULL, $lat = NULL, $referentiel = 'bdtfx:v1.01', $ligne) {
-
 
465
		// en CSV ces valeurs sont des string, avec séparateur en français (","; cf défauts dans ExportXLS)
-
 
466
		if($lon && is_string($lon)) $lon = str_replace(',', '.', $lon);
-
 
467
		if($lat && is_string($lat)) $lat = str_replace(',', '.', $lat);
-
 
468
 
-
 
469
		// sprintf applique une précision à 5 décimale (comme le ferait MySQL)
-
 
470
		// tout en uniformisant le format de séparateur des décimales (le ".")
-
 
471
		if($lon && is_numeric($lon) && $lon >= -180 && $lon <= 180) return sprintf('%.5F', $lon);
-
 
472
		if($lat && is_numeric($lat) && $lat >= -90 && $lat <= 90) return sprintf('%.5F', $lat);
-
 
473
 
-
 
474
		if($lon || $lat) {
-
 
475
			trigger_error("ligne \"{$ligne[C_NOM_SEL]}\": " .
347
		/* TODO: cf story,
476
						  "Attention: longitude ou latitude erronée",
-
 
477
						  E_USER_NOTICE);
Line -... Line 478...
-
 
478
		}
348
		   En cas de NULL faire une seconde passe de détection à partir du nom saisie */
479
		return NULL;
349
	}
480
 
350
 
481
		/* limite france métropole si bdtfx ? ou bdtxa ? ...
351
	/* NON!
482
		   NON!
352
	   Un taxon d'un référentiel donné peut être théoriquement observé n'importe où sur le globe.
483
		   Un taxon d'un référentiel donné peut être théoriquement observé n'importe où sur le globe.
353
	   Il n'y a pas lieu d'effectuer des restriction ici.
-
 
354
	   Cependant des erreurs fréquentes (0,0 ou lon/lat inversées) peuvent être détectés ici.
-
 
355
	   TODO */
-
 
356
	static function traiterLonLat($lon = NULL, $lat = NULL, $referentiel = 'bdtfx:v1.01') {
-
 
357
		// verifier format decimal +
484
		   Il n'y a pas lieu d'effectuer des restriction ici.
358
		// + limite france si bdtfx ou bdtxa
485
		   Cependant des erreurs fréquentes (0,0 ou lon/lat inversées) peuvent être détectés ici.
Line 359... Line 486...
359
 
486
		   TODO */
360
		$bbox = self::getReferentielBBox($referentiel);
487
		$bbox = self::getReferentielBBox($referentiel);
Line 370... Line 497...
370
		}
497
		}
371
	}
498
	}
Line 372... Line 499...
372
 
499
 
-
 
500
 
-
 
501
	static function traiterEspece($ligne, Array &$espece, $cel) {
373
 
502
		if(!$ligne[C_NOM_SEL]) return;
Line 374... Line 503...
374
	static function traiterEspece($ligne, Array &$espece, $cel) {
503
 
-
 
504
		$taxon_info_webservice = new RechercheInfosTaxonBeta($cel->config);
375
		$taxon_info_webservice = new RechercheInfosTaxonBeta($cel->config);
505
 
Line 376... Line 506...
376
 
506
		$ascii = iconv('UTF-8', 'ASCII//TRANSLIT', $ligne[C_NOM_SEL]);
377
		$ascii = iconv('UTF-8', 'ASCII//TRANSLIT', $ligne[C_NOM_SEL]);
507
		// FALSE = recherche étendue (LIKE x%)
378
		$resultat_recherche_espece = $taxon_info_webservice->rechercherInfosSurTexteCodeOuNumTax($ligne[C_NOM_SEL]);
508
		$resultat_recherche_espece = $taxon_info_webservice->rechercherInfosSurTexteCodeOuNumTax($ligne[C_NOM_SEL]);
379
 
509
 
380
		// on supprime les noms retenus et renvoi tel quel
-
 
Line -... Line 510...
-
 
510
		// on supprime les noms retenus et renvoi tel quel
381
		// on réutilise les define pour les noms d'indexes, tant qu'à faire
511
		// on réutilise les define pour les noms d'indexes, tant qu'à faire
-
 
512
		if (empty($resultat_recherche_espece['en_id_nom'])) {
382
		if (empty($resultat_recherche_espece['en_id_nom'])) {
513
			$espece[C_NOM_SEL] = $cel->quoteNonNull(trim($ligne[C_NOM_SEL]));
383
			$espece[C_NOM_SEL] = $ligne[C_NOM_SEL];
514
 
384
			$espece[C_NOM_SEL_NN] = $ligne[C_NOM_SEL_NN];
515
			// le reste reste à NULL
385
 
516
			// TODO: si empty(C_NOM_SEL) et !empty(C_NOM_SEL_NN) : recherche info à partir de C_NOM_SEL_NN
Line 386... Line 517...
386
			// TODO: si empty(C_NOM_SEL) et !empty(C_NOM_SEL_NN) : recherche info à partir de C_NOM_SEL_NN
517
			$espece[C_NOM_SEL_NN] = $ligne[C_NOM_SEL_NN];
387
			$espece[C_NOM_RET] = $ligne[C_NOM_RET];
518
			$espece[C_NOM_RET] = $ligne[C_NOM_RET];
Line 388... Line 519...
388
			$espece[C_NOM_RET_NN] = $ligne[C_NOM_RET_NN];
519
			$espece[C_NOM_RET_NN] = $ligne[C_NOM_RET_NN];
389
			$espece[C_NT] = $ligne[C_NT];
520
			$espece[C_NT] = $ligne[C_NT];
390
			$espece[C_FAMILLE] = $ligne[C_FAMILLE];
521
			$espece[C_FAMILLE] = $ligne[C_FAMILLE];
Line 391... Line 522...
391
 
522
 
392
			return;
523
			return;
393
		}
524
		}
394
 
525
 
395
		// succès de la détection, récupération des infos
526
		// succès de la détection, récupération des infos
-
 
527
		$espece[C_NOM_SEL] = $cel->quoteNonNull($resultat_recherche_espece['nom_sel']);
-
 
528
		$espece[C_NOM_SEL_NN] = $cel->quoteNonNull($resultat_recherche_espece['en_id_nom']);
-
 
529
 
-
 
530
		$complement = $taxon_info_webservice->rechercherInformationsComplementairesSurNumNom($resultat_recherche_espece['en_id_nom']);
-
 
531
		$espece[C_NOM_RET] = $cel->quoteNonNull($complement['Nom_Retenu']);
-
 
532
		$espece[C_NOM_RET_NN] = $cel->quoteNonNull($complement['Num_Nom_Retenu']);
-
 
533
		$espece[C_NT] = $cel->quoteNonNull($complement['Num_Taxon']);
-
 
534
		$espece[C_FAMILLE] = $cel->quoteNonNull($complement['Famille']);
396
		$espece[C_NOM_SEL] = $resultat_recherche_espece['nom_sel'];
535
	}
Line -... Line 536...
-
 
536
 
-
 
537
 
-
 
538
	static function traiterLocalisation($ligne, Array &$localisation, $cel) {
397
		$espece[C_NOM_SEL_NN] = $resultat_recherche_espece['en_id_nom'];
539
	    $identifiant_commune = trim($ligne[C_ZONE_GEO]);
-
 
540
		if(!$identifiant_commune) {
-
 
541
			$departement = trim($ligne[C_CE_ZONE_GEO]);
-
 
542
			goto testdepartement;
-
 
543
		}
-
 
544
 
-
 
545
 
-
 
546
		$select = "SELECT DISTINCT nom, code  FROM cel_zones_geo";
-
 
547
	
-
 
548
		if (preg_match('/(.*) \((\d+)\)/', $identifiant_commune, $elements)) {
-
 
549
			// commune + departement : montpellier (34)
-
 
550
			$nom_commune=$elements[1];
-
 
551
			$code_commune=$elements[2];
-
 
552
	 	    $requete = sprintf("%s WHERE nom = %s AND code LIKE %s",
-
 
553
							   $select, $cel->quoteNonNull($nom_commune), $cel->quoteNonNull($code_commune.'%'));
-
 
554
		}
-
 
555
		elseif (preg_match('/^(\d+|(2[ab]\d+))$/i', $identifiant_commune, $elements)) {
-
 
556
			// Code insee seul  
-
 
557
			$code_insee_commune=$elements[1];
-
 
558
	 	    $requete = sprintf("%s WHERE code = %s", $select, $cel->quoteNonNull($code_insee_commune));
-
 
559
		}
-
 
560
		else {
-
 
561
			// Commune seule (le departement sera recupere dans la colonne departement si elle est presente)
-
 
562
			// on prend le risque ici de retourner une mauvaise Commune
-
 
563
			$nom_commune = str_replace(" ", "%", iconv('UTF-8', 'ASCII//TRANSLIT', $identifiant_commune));
-
 
564
	 	    $requete = sprintf("%s WHERE nom LIKE %s", $select, $cel->quoteNonNull($nom_commune.'%'));
-
 
565
		}
-
 
566
	
-
 
567
		$resultat_commune = $cel->requeter($requete);
-
 
568
		// TODO: levenstein sort ?
-
 
569
 
-
 
570
		// cas de la commune introuvable dans le référentiel
-
 
571
		// réinitialisation aux valeurs du fichier XLS
-
 
572
		if(! $resultat_commune) {
398
 
573
			$localisation[C_ZONE_GEO] = trim($ligne[C_ZONE_GEO]);
-
 
574
			$localisation[C_CE_ZONE_GEO] = trim($ligne[C_CE_ZONE_GEO]);
399
		$complement = $taxon_info_webservice->rechercherInformationsComplementairesSurNumNom($resultat_recherche_espece['en_id_nom']);
575
		} else {
400
		$espece[C_NOM_RET] = $complement['Nom_Retenu'];
576
			$localisation[C_ZONE_GEO] = $resultat_commune[0]['nom'];
401
		$espece[C_NOM_RET_NN] = $complement['Num_Nom_Retenu'];
577
			$localisation[C_CE_ZONE_GEO] = $resultat_commune[0]['code'];
402
		$espece[C_NT] = $complement['Num_Taxon'];
578
		}
-
 
579
 
403
		$espece[C_FAMILLE] = $complement['Famille'];
580
		$departement = &$localisation[C_CE_ZONE_GEO];
-
 
581
 
-
 
582
	testdepartement:
-
 
583
		if(strpos($departement, "INSEE-C:", 0) === 0) goto protectloc;
-
 
584
 
404
	}
585
		if(!is_numeric($departement)) goto protectloc; // TODO ?
Line -... Line 586...
-
 
586
		if(strlen($departement) == 4) $departement = "INSEE-C:0" . $departement;
405
 
587
		if(strlen($departement) == 5) $departement = "INSEE-C:" . $departement;
Line 406... Line 588...
406
 
588
		// if(strlen($departement) <= 9) return "INSEE-C:0" . $departement; // ? ... TODO
407
	static function traiterDepartement($departement) { 
589
 
408
		if(strpos($departement, "INSEE-C:", 0) === 0) return $departement;
590
		$departement = trim($departement); // TODO
Line 437... Line 619...
437
			'OUEST' => -5.2); // Ouessan
619
			'OUEST' => -5.2); // Ouessan
438
		return FALSE;
620
		return FALSE;
439
	}
621
	}
Line 440... Line 622...
440
 
622
 
441
 
623
 
442
	public function initialiser_colonnes_statiques($id_utisateur) {
624
	public function initialiser_colonnes_statiques() {
443
		$this->colonnes_statiques = array_merge($this->colonnes_statiques,
625
		$this->colonnes_statiques = array_merge($this->colonnes_statiques,
444
												Array(
626
												Array(
445
													"ce_utilisateur" => $id_utisateur,
627
													"ce_utilisateur" => $this->id_utilisateur,
446
													"prenom_utilisateur" => $this->utilisateur['prenom'],
628
													"prenom_utilisateur" => $this->quoteNonNull($this->utilisateur['prenom']),
447
													"nom_utilisateur" => $this->utilisateur['nom'],
-
 
448
													"courriel_utilisateur" => $this->utilisateur['courriel'],
-
 
449
 
-
 
450
													"date_creation" => date("Y-m-d H:i:s"),
629
													"nom_utilisateur" => $this->quoteNonNull($this->utilisateur['nom']),
Line 451... Line 630...
451
													"date_modification" => date("Y-m-d H:i:s"),
630
													"courriel_utilisateur" => $this->quoteNonNull($this->utilisateur['courriel']),
-
 
631
												));
-
 
632
 
-
 
633
	}
-
 
634
 
-
 
635
	// équivalent à CEL->Bdd->proteger() (qui wrap PDO::quote),
-
 
636
	// sans transformer NULL en ""
-
 
637
	private function quoteNonNull($chaine) {
-
 
638
		if(is_null($chaine)) return "NULL";
-
 
639
		if(!is_string($chaine)) die("erreur __FILE__, __LINE__");
-
 
640
		return $this->bdd->quote($chaine);
-
 
641
	}
-
 
642
 
452
												));
643
	public function erreurs_stock($errno, $errstr) {