Subversion Repositories eFlore/Applications.cel

Rev

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

Rev Author Line No. Line
1654 aurelien 1
<?php
2461 jpm 2
// declare(encoding='UTF-8');
1656 raphael 3
/**
2461 jpm 4
 * Classe métier de mise en forme des groupes de colonnes pour les exports.
5
 *
6
 * @internal   Mininum PHP version : 5.2
7
 * @category   CEL
8
 * @package    Services
9
 * @subpackage Bibliothèques
10
 * @version    0.1
11
 * @author     Mathias CHOUET <mathias@tela-botanica.org>
12
 * @author     Raphaël Droz <raphael@tela-botania.org>
13
 * @author     Jean-Pascal MILCENT <jpm@tela-botanica.org>
14
 * @author     Aurelien PERONNET <aurelien@tela-botanica.org>
15
 * @license    GPL v3 <http://www.gnu.org/licenses/gpl.txt>
16
 * @license    CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt>
17
 * @copyright  1999-2014 Tela Botanica <accueil@tela-botanica.org>
18
 */
19
define('SEPARATEUR_IMAGES', ' / ');
20
define('PREFIX_CHAMPS_ETENDUS', 'ext:');
1835 raphael 21
// utilisé par formaterUrlUser() [ nécessaire pour le widget d'export)
22
define('USER_BASEURL', 'http://www.tela-botanica.org/profil:%d');
1656 raphael 23
 
2461 jpm 24
class FormateurGroupeColonne {
1656 raphael 25
 
1702 raphael 26
	// cache pour les données des fonctions
1656 raphael 27
	static $cache = Array();
28
 
1702 raphael 29
	// test sur la table cel_references, mis à TRUE si la table existe
30
	static $is_table = false;
31
 
1714 raphael 32
	// les groupes de champs utilisables
33
	static $fieldGroups = array(
34
		'standard',
3134 delphine 35
		'standardexport',
1714 raphael 36
		'avance',
37
		'etendu',
1835 raphael 38
		'baseflor',
39
		'auteur'
1714 raphael 40
	);
41
 
1702 raphael 42
	// les données baseflor à récupérer: colonnes présentes dans cel_references
43
	// et intitulés associés
44
	static $baseflor_col = array(
2461 jpm 45
		've_lumiere' => 'Lumière',
46
		've_temperature' => 'Température',
47
		've_continentalite' => 'Continentalité',
48
		've_humidite_atmos' => 'Humidité Atmosphérique',
49
		've_humidite_edaph' => 'Humidité',
50
		've_reaction_sol' => 'Réaction (pH)',
51
		've_nutriments_sol' => 'Nutriments',
52
		've_salinite' => 'Salinité',
53
		've_texture_sol' => 'Texture' ,
54
		've_mat_org_sol' => 'Matière Organique',
55
		'catminat_code' => 'Code Catminat',
56
		'syntaxon' => 'Syntaxon',
1702 raphael 57
	);
58
 
1741 raphael 59
	// TODO: dirty, ordre des champs étendus... souhaité pour florilèges:
60
	static $ordre_champ_etendus_Florileges = array(
2461 jpm 61
		'personneStructure',
62
		'personneService',
63
		'personneFonction',
64
		'adresse',
65
		'latitudeDebutRue',
66
		'longitudeDebutRue',
67
		'latitudeFinRue',
68
		'longitudeFinRue',
69
		'typoUrbaine',
70
		'revetementSol',
71
		'presenceZoneVegetalise',
72
		'hauteurBatimentAvoisinant',
73
		'intensiteGestion',
74
		'periodiciteTraitementPhyto',
75
		'dateArretTraitementPhyto',
76
		'itineraireGestion',
77
		'dateDerniereIntervention',
78
		'hauteurPlante',
79
		'resistanceTraitementPhyto',
80
		'vitesseCroissance',
81
		'perceptionTechnicien',
82
		'perceptionRiverainMauvaise',
1741 raphael 83
	);
84
 
3134 delphine 85
	static function colGroupsValidation($groupe_de_champs = 'standard,avance', $programme = "") {
2461 jpm 86
		if (! $groupe_de_champs) return FALSE;
87
		if (is_string($groupe_de_champs)) {
1714 raphael 88
			$groupe_de_champs = array_flip(explode(',', $groupe_de_champs));
2461 jpm 89
		} elseif(is_array($groupe_de_champs)) {
1714 raphael 90
			$groupe_de_champs = array_flip($groupe_de_champs);
2461 jpm 91
		} else {
92
			return null;
1714 raphael 93
		}
2461 jpm 94
		$groupe_de_champs = array_intersect_key(array_flip(self::$fieldGroups), $groupe_de_champs);
95
		if (!$groupe_de_champs) {
96
			return false;
1714 raphael 97
		}
3134 delphine 98
		if ($programme != "") {
99
			$groupe_de_champs['avance'] = true;
100
			$groupe_de_champs['etendu'] = true;
101
		}
1714 raphael 102
		// toujours ajouter standard
2461 jpm 103
		$groupe_de_champs['standard'] = true;
1714 raphael 104
		return implode(',', array_keys($groupe_de_champs));
105
	}
106
 
1654 aurelien 107
	/*
108
	* @param $fieldSets: un liste de noms de colonnes ou de sets de colonnes
109
	*		séparés par des virgules
110
	* 		eg: "espece" ou "champs-etendus", ...
111
	*
112
	* @return: un tableau associatif déjà ordonné
113
	* 		clé: abbrev [machine-name] de la colonne (eg: "espece" ou "mot-clef")
114
	* 		valeur: des données relative à cette colonne, cf GenColInfo
115
	*
1757 raphael 116
	* Si la colonne n'utilise pas de fonction de récupération particulière
117
	* (ie: si le champ exportés [ou importé] correspond exactement au champ dans la base de donnée)
118
	* Alors 'abbrev' doit avoir la même valeur que le nom de la colonne dans la table mysql `cel_obs`.
1654 aurelien 119
	*/
120
	static function nomEnsembleVersListeColonnes($groupe_de_champs = 'standard') {
2461 jpm 121
		if (! $groupe_de_champs) {
122
			$groupe_de_champs = 'standard';
123
		}
124
		if (is_string($groupe_de_champs)) {
1711 raphael 125
			$groupe_de_champs = array_flip(explode(',', $groupe_de_champs));
2461 jpm 126
		} elseif(is_array($groupe_de_champs)) {
1711 raphael 127
			$groupe_de_champs = array_flip($groupe_de_champs);
2461 jpm 128
		} else {
129
			return null;
1711 raphael 130
		}
2461 jpm 131
		$groupe_de_champs = array_intersect_key(array_flip(self::$fieldGroups), $groupe_de_champs);
132
		if (!$groupe_de_champs) {
133
			return null;
1711 raphael 134
		}
135
 
2461 jpm 136
		$colonnes = array();
3134 delphine 137
		if (isset($groupe_de_champs['standardexport'])) {
1654 aurelien 138
			$colonnes += Array(
3134 delphine 139
				'guid'			=> self::GenColInfo(Array('abbrev' => 'guid',
140
																'nom' => 'Identifiant unique')),
3467 delphine 141
			    'id_observation'	=> self::GenColInfo(Array('abbrev' => 'id_observation',
142
                                            			        'nom' => 'Identifiant',
143
                                            			        'extra' => 1,
144
                                            			        'importable' => FALSE)),
1757 raphael 145
				'nom_sel'			=> self::GenColInfo(Array('abbrev' => 'nom_sel',
146
															  'nom' => 'Espèce')),
147
				'nom_sel_nn'		=> self::GenColInfo(Array('abbrev' => 'nom_sel_nn',
148
															  'nom' => 'Numéro nomenclatural',
149
															  'importable' => FALSE)),
150
				'nom_ret'			=> self::GenColInfo(Array('abbrev' => 'nom_ret',
151
															  'nom' => 'Nom retenu',
152
															  'importable' => FALSE)),
153
				'nom_ret_nn'		=> self::GenColInfo(Array('abbrev' => 'nom_ret_nn',
154
															  'nom' => 'Numéro nomenclatural nom retenu',
155
															  'importable' => FALSE)),
156
				'nt'				=> self::GenColInfo(Array('abbrev' => 'nt',
157
															  'nom' => 'Numéro taxonomique',
158
															  'importable' => FALSE)),
159
				'famille'			=> self::GenColInfo(Array('abbrev' => 'famille',
160
															  'nom' => 'Famille',
161
															  'importable' => FALSE)),
162
				'nom_referentiel'	=> self::GenColInfo(Array('abbrev' => 'nom_referentiel',
163
															  'nom' => 'Referentiel taxonomique')),
3467 delphine 164
			    'certitude'			=> self::GenColInfo(Array('abbrev' => 'certitude',
165
			                                                 'nom' => 'Certitude')),
166
			    'type_donnees'		=> self::GenColInfo(Array('abbrev' => 'type_donnees',
167
			                                                 'nom' => 'Type d\'observation')),
168
			    'source'			=> self::GenColInfo(Array('abbrev' => 'source',
169
			                                                 'nom' => 'Source de la saisie')),
170
			    'spontaneite'			=> self::GenColInfo(Array('abbrev' => 'spontaneite',
171
			                                                 'nom' => 'Spontanéité')),
172
			    'latitude'			=> self::GenColInfo(Array('abbrev' => 'latitude',
173
			        'nom' => 'Latitude',
174
			        'extra' => 1)),
175
			    'longitude'			=> self::GenColInfo(Array('abbrev' => 'longitude',
176
			        'nom' => 'Longitude',
177
			        'extra' => 1)),
178
 
179
			    'geodatum'			=> self::GenColInfo(Array('abbrev' => 'geodatum',
180
			        'nom' => 'Référentiel Géographique',
181
			        'extra' => 1,
182
			        'importable' => FALSE)),
183
 
184
			    'pays'				=> self::GenColInfo(Array('abbrev' => 'pays',
2538 aurelien 185
															  'nom' => 'Pays')),
1757 raphael 186
				'zone_geo'			=> self::GenColInfo(Array('abbrev' => 'zone_geo',
187
															  'nom' => 'Commune')),
188
				'ce_zone_geo'		=> self::GenColInfo(Array('abbrev' => 'ce_zone_geo',
3467 delphine 189
															  'nom' => 'Identifiant Commune')),
190
			    'localisation_floutage'	=> self::GenColInfo(Array('abbrev' => 'localisation_floutage',
191
			                                                 'nom' => 'Floutage (niveau de localisation diffusé)')),
192
			    'altitude'			=> self::GenColInfo(Array('abbrev' => 'altitude',
193
                                        			        'nom' => 'Altitude',
194
                                        			        'extra' => 1)), // pas de trim0 car INT(5) en DB
195
			    'lieudit'			=> self::GenColInfo(Array('abbrev' => 'lieudit',
1757 raphael 196
															  'nom' => 'Lieu-dit')),
197
				'milieu'			=> self::GenColInfo(Array('abbrev' => 'milieu',
198
															  'nom' => 'Milieu')),
3467 delphine 199
			    'date_observation'	=> self::GenColInfo(Array('abbrev' => 'date_observation',
200
			                                                 'nom' => 'Date',
201
			                                                 'fonction' => 'formaterDate')),
202
			    'commentaire'		=> self::GenColInfo(Array('abbrev' => 'commentaire',
1757 raphael 203
															  'nom' => 'Notes')),
3134 delphine 204
				'programme'			=> self::GenColInfo(Array('abbrev' => 'programme',
3142 delphine 205
																'nom' => 'Programme de sciences participatives ou observatoire citoyen',
206
																'importable' => FALSE)),
207
				'mots_cles_texte'	=> self::GenColInfo(Array('abbrev' => 'mots_cles_texte',
208
																'nom' => 'Mots Clés',
209
																'importable' => FALSE)),
210
				'url_identiplante'			=> self::GenColInfo(Array('abbrev' => 'url_identiplante',
211
															'nom' => "Lien vers l'observation sur IdentiPlante",
212
															'importable' => FALSE)),
3467 delphine 213
			    'image'			=> self::GenColInfo(Array('abbrev' => 'image',
214
			        'nom' => 'Image(s)',
215
			        'extra' => 1)),
216
 
217
			    );
3134 delphine 218
		} elseif (isset($groupe_de_champs['standard'])) {
219
			$colonnes += Array(
3467 delphine 220
			    'guid'			=> self::GenColInfo(Array('abbrev' => 'guid',
221
			        'nom' => 'Identifiant unique')),
222
			    'id_observation'	=> self::GenColInfo(Array('abbrev' => 'id_observation',
223
			        'nom' => 'Identifiant',
224
			        'extra' => 1,
225
			        'importable' => FALSE)),
226
			    'nom_sel'			=> self::GenColInfo(Array('abbrev' => 'nom_sel',
227
			        'nom' => 'Espèce')),
228
			    'nom_sel_nn'		=> self::GenColInfo(Array('abbrev' => 'nom_sel_nn',
229
			        'nom' => 'Numéro nomenclatural',
230
			        'importable' => FALSE)),
231
			    'nom_ret'			=> self::GenColInfo(Array('abbrev' => 'nom_ret',
232
			        'nom' => 'Nom retenu',
233
			        'importable' => FALSE)),
234
			    'nom_ret_nn'		=> self::GenColInfo(Array('abbrev' => 'nom_ret_nn',
235
			        'nom' => 'Numéro nomenclatural nom retenu',
236
			        'importable' => FALSE)),
237
			    'nt'				=> self::GenColInfo(Array('abbrev' => 'nt',
238
			        'nom' => 'Numéro taxonomique',
239
			        'importable' => FALSE)),
240
			    'famille'			=> self::GenColInfo(Array('abbrev' => 'famille',
241
			        'nom' => 'Famille',
242
			        'importable' => FALSE)),
243
			    'nom_referentiel'	=> self::GenColInfo(Array('abbrev' => 'nom_referentiel',
244
			        'nom' => 'Referentiel taxonomique')),
245
			    'certitude'			=> self::GenColInfo(Array('abbrev' => 'certitude',
246
			        'nom' => 'Certitude')),
247
			    'type_donnees'		=> self::GenColInfo(Array('abbrev' => 'type_donnees',
248
			        'nom' => 'Type d\'observation')),
249
			    'source'			=> self::GenColInfo(Array('abbrev' => 'source',
250
			        'nom' => 'Source de la saisie')),
251
			    'spontaneite'			=> self::GenColInfo(Array('abbrev' => 'spontaneite',
252
			        'nom' => 'Spontanéité')),
253
			    'latitude'			=> self::GenColInfo(Array('abbrev' => 'latitude',
254
			        'nom' => 'Latitude',
255
			        'extra' => 1)),
256
			    'longitude'			=> self::GenColInfo(Array('abbrev' => 'longitude',
257
			        'nom' => 'Longitude',
258
			        'extra' => 1)),
259
 
260
			    'geodatum'			=> self::GenColInfo(Array('abbrev' => 'geodatum',
261
			        'nom' => 'Référentiel Géographique',
262
			        'extra' => 1,
263
			        'importable' => FALSE)),
264
 
265
			    'pays'				=> self::GenColInfo(Array('abbrev' => 'pays',
266
			        'nom' => 'Pays')),
267
			    'zone_geo'			=> self::GenColInfo(Array('abbrev' => 'zone_geo',
268
			        'nom' => 'Commune')),
269
			    'ce_zone_geo'		=> self::GenColInfo(Array('abbrev' => 'ce_zone_geo',
270
			        'nom' => 'Identifiant Commune')),
271
			    'localisation_floutage'	=> self::GenColInfo(Array('abbrev' => 'localisation_floutage',
272
			        'nom' => 'Floutage (niveau de localisation diffusé)')),
273
			    'altitude'			=> self::GenColInfo(Array('abbrev' => 'altitude',
274
			        'nom' => 'Altitude',
275
			        'extra' => 1)), // pas de trim0 car INT(5) en DB
276
			    'lieudit'			=> self::GenColInfo(Array('abbrev' => 'lieudit',
277
			        'nom' => 'Lieu-dit')),
278
			    'milieu'			=> self::GenColInfo(Array('abbrev' => 'milieu',
279
			        'nom' => 'Milieu')),
280
			    'date_observation'	=> self::GenColInfo(Array('abbrev' => 'date_observation',
281
			        'nom' => 'Date',
282
			        'fonction' => 'formaterDate')),
283
			    'commentaire'		=> self::GenColInfo(Array('abbrev' => 'commentaire',
284
			        'nom' => 'Notes')),
285
			    'programme'			=> self::GenColInfo(Array('abbrev' => 'programme',
286
			        'nom' => 'Programme de sciences participatives ou observatoire citoyen',
287
			        'importable' => FALSE)),
288
			    'mots_cles_texte'	=> self::GenColInfo(Array('abbrev' => 'mots_cles_texte',
289
			        'nom' => 'Mots Clés',
290
			        'importable' => FALSE)),
291
 
292
			    'image'			=> self::GenColInfo(Array('abbrev' => 'image',
293
			        'nom' => 'Image(s)',
294
			        'extra' => 1)),
295
			    'url_identiplante'			=> self::GenColInfo(Array('abbrev' => 'url_identiplante',
296
			        'nom' => "Lien vers l'observation sur IdentiPlante",
297
			        'importable' => FALSE)),
298
 
3134 delphine 299
					);
1654 aurelien 300
		}
2143 jpm 301
 
1654 aurelien 302
		if(isset($groupe_de_champs['avance'])) {
1656 raphael 303
			$colonnes += array(
3467 delphine 304
			    'localisation_coherence' => self::GenColInfo(Array('abbrev' => 'localisation_coherence',
305
			        'nom' => 'Cohérence entre la localité et les coordonnées GPS')),
306
			    'localisation_precision' => self::GenColInfo(Array('abbrev' => 'localisation_precision',
307
			        'nom' => 'Précision de la localisation')),
308
			    'station'			=> self::GenColInfo(Array('abbrev' => 'station',
309
			        'nom' => 'Station')),
310
			    'validation_identiplante'			=> self::GenColInfo(Array('abbrev' => 'validation_identiplante',
311
			        'nom' => 'Détermination validée sur IdentiPlante',
312
			        'importable' => FALSE)),
313
			    'score_identiplante'			=> self::GenColInfo(Array('abbrev' => 'score_identiplante',
314
			        'nom' => 'Détermination validée sur IdentiPlante',
315
			        'importable' => FALSE)),
316
			    'abondance'			=> self::GenColInfo(Array('abbrev' => 'abondance',
317
			        'nom' => 'Abondance',
318
			        'extra' => 1)),
319
			    'phenologie'		=> self::GenColInfo(Array('abbrev' => 'phenologie',
320
			        'nom' => 'Phénologie',
321
			        'extra' => 1)),
322
			    'herbier'			=> self::GenColInfo(Array('abbrev' => 'herbier',
323
			        'nom' => 'Présence d\'un échantillon d\'herbier',
324
			        'extra' => 1)),
325
 
1757 raphael 326
				// TODO: importable = FALSE car pas de merge de données importées
327
				'date_creation'		=> self::GenColInfo(Array('abbrev' => 'date_creation',
328
															  'nom' => 'Date Création',
329
															  'extra' => 1,
330
															  'importable' => FALSE)),
331
				'date_modification'	=> self::GenColInfo(Array('abbrev' => 'date_modification',
332
															  'nom' => 'Date Modification',
333
															  'extra' => 1,
334
															  'importable' => FALSE)),
1656 raphael 335
 
1757 raphael 336
				// rappel transmission = 1, signifie simplement "public"
337
				// des données importées peuvent être d'emblée "publiques"
338
				// "importable" = TRUE
339
				'transmission'		=> self::GenColInfo(Array('abbrev' => 'transmission',
340
															  'nom' => 'Transmis',
341
															  'extra' => 1,
342
															  'fonction' => 'boolOuiNon')),
343
				'date_transmission'	=> self::GenColInfo(Array('abbrev' => 'date_transmission',
344
															  'nom' => 'Date Transmission',
345
															  'extra' => 1,
346
															  'importable' => FALSE)),
2143 jpm 347
 
1656 raphael 348
 
1757 raphael 349
				/* 'nom_commun'			=> self::GenColInfo(Array('abbrev' => 'nom_commun',
350
				   'nom' => 'Nom Commun',
351
				   'extra' => 1,
352
				   'fonction_data' => 'getNomCommun',
353
				   'importable' => FALSE),
1685 raphael 354
 
1757 raphael 355
				   'nom-commun'			=> self::GenColInfo(Array('abbrev' => 'nom-commun',
356
				   'nom' => 'Nom Commun',
357
				   'extra' => 1,
358
				   'fonction_data' => 'getNomCommun_v2'),
359
 
360
				   'nom-commun'			=> self::GenColInfo(Array('abbrev' => 'nom-commun',
361
				   'nom' => 'Nom Commun',
362
				   'extra' => 1,
363
				   'fonction_data' => 'getNomCommun_v3'),
3467 delphine 364
				   'importable' => FALSE), */ /* cas particu 'getNomCommun_v4' */
365
				/*'nom-commun' => self::GenColInfo(array(
2461 jpm 366
					'abbrev' => 'nom-commun',
367
					'nom' => 'Nom Commun',
368
					'extra' => 1,
3467 delphine 369
					'fonction_data' => null ,
370
					'preload' => array(__CLASS__, 'getNomCommun_preload')))*/
1702 raphael 371
			);
372
		}
1685 raphael 373
 
1702 raphael 374
		if(isset($groupe_de_champs['baseflor'])) {
375
			$colonnes += array(
376
				// champ dynamique
2461 jpm 377
				'baseflor' => self::GenColInfo(array(
378
					'abbrev' => 'baseflor',
379
					'nom' => '',
380
					'extra' => 1,
381
					'importable' => false,
382
					'preload' => array(__CLASS__, 'baseflor_preload'),
383
					'dyna' => array(__CLASS__, 'baseflor_ligne'))),
1654 aurelien 384
			);
1702 raphael 385
		}
1656 raphael 386
 
2461 jpm 387
		if (isset($groupe_de_champs['etendu'])) {
1714 raphael 388
			$colonnes += array(
389
				// champ dynamique
2461 jpm 390
				'etendu' => self::GenColInfo(array(
391
					'abbrev' => 'etendu',
392
					'nom' => '',
393
					'extra' => 1,
394
					'importable' => false,
395
					'preload' => array(__CLASS__, 'champsEtendus_preload'),
396
					'dyna' => array(__CLASS__, 'champsEtendus_ligne'))),
1714 raphael 397
			);
398
		}
1835 raphael 399
 
2461 jpm 400
		if (isset($groupe_de_champs['auteur'])) {
1835 raphael 401
			$colonnes += array(
2461 jpm 402
				'observateur' => self::GenColInfo(array(
3467 delphine 403
					'abbrev' => 'pseudo_utilisateur',
404
					'nom' => 'Auteur',
2461 jpm 405
					'extra' => 1,
406
					'importable' => false)),
1835 raphael 407
			);
408
		}
1654 aurelien 409
		return $colonnes;
410
	}
1694 raphael 411
 
412
	static function preload($colonnes, $cel, $ids) {
413
		$result = array();
2461 jpm 414
		foreach ($colonnes as $abbrev => $colonne) {
415
			if (!$colonne['preload']) {
416
				continue;
417
			}
1702 raphael 418
			$result[$abbrev] = call_user_func($colonne['preload'], $cel, $ids);
1694 raphael 419
		}
420
		return $result;
421
	}
2143 jpm 422
 
1656 raphael 423
	public static function getIntitulesColonnes($colonnes) {
1702 raphael 424
		// array_filter pour supprimer les colonnes "dynamique" n'ayant pas défini $nom (cf GenColInfo())
425
		return array_filter(array_map(array('FormateurGroupeColonne', 'retournerNomItem'), $colonnes));
1654 aurelien 426
	}
2143 jpm 427
 
1671 aurelien 428
	public static function retournerNomItem(&$item) {
429
		return $item['nom'];
430
	}
1694 raphael 431
 
1656 raphael 432
	public static function getLigneObservation(&$obs, &$colonnes, $cel = false) {
1654 aurelien 433
		$ligne_formatee = array();
434
		foreach($colonnes as $abbrev => $colonne) {
435
			$valeur = null;
2461 jpm 436
			if ($colonne['extra'] == 2 || ! is_null($colonne['dyna'])) {
437
				continue;
438
			}
2143 jpm 439
 
1835 raphael 440
			// valeur directe depuis cel_obs ?
2461 jpm 441
			if (isset($obs[$abbrev])) {
442
				$valeur = $obs[$abbrev];
443
			}
2143 jpm 444
 
1835 raphael 445
			// pré-processeur des champs
2461 jpm 446
			if (function_exists($colonne['fonction'])) {
1654 aurelien 447
				$valeur = $colonne['fonction']($valeur);
2461 jpm 448
			} else if(method_exists(__CLASS__, $colonne['fonction'])) {
1654 aurelien 449
				$valeur = call_user_func(array(__CLASS__, $colonne['fonction']), $valeur);
2461 jpm 450
			} else if($colonne['fonction']) {
1654 aurelien 451
				die("méthode {$colonne['fonction']} introuvable");
2461 jpm 452
			} else if(function_exists($colonne['fonction_data'])) {// fonction pour obtenir des champs (étendus)
1654 aurelien 453
				$valeur = $colonne['fonction_data']($obs);
2461 jpm 454
			} else if(method_exists(__CLASS__, $colonne['fonction_data'])) {
1654 aurelien 455
				$valeur = call_user_func(array(__CLASS__, $colonne['fonction_data']), $obs);
456
			}
2143 jpm 457
 
3467 delphine 458
 
1765 raphael 459
			// ici à cause du passage de $cel ($this->utilisateur)
3467 delphine 460
 
2461 jpm 461
			if ($abbrev == 'nom-commun') {
1765 raphael 462
				$valeur = FormateurGroupeColonne::getNomCommun_v4($obs);
1685 raphael 463
			}
2143 jpm 464
 
2461 jpm 465
			if ($valeur == null) {
466
				$valeur = '';
1654 aurelien 467
			}
2143 jpm 468
 
2461 jpm 469
			// fin de section "cas particuliers"
1654 aurelien 470
			$ligne_formatee[] = $valeur;
471
		}
1694 raphael 472
 
1835 raphael 473
		// uniquement les champs dynamiques
1702 raphael 474
		foreach($colonnes as $abbrev => $colonne) {
475
			$valeur = null;
2461 jpm 476
			if (is_null($colonne['dyna'])) {
477
				continue;
478
			}
479
			call_user_func_array($colonne['dyna'], array($obs, &$ligne_formatee));
1702 raphael 480
		}
1654 aurelien 481
		return $ligne_formatee;
482
	}
2143 jpm 483
 
1654 aurelien 484
	/*
485
	* Wrapper générant un tableau associatif:
1694 raphael 486
	* Ne pas changer les valeurs par défaut du prototype sans réflexion sur l'implication pour nomEnsembleVersListeColonnes()
2143 jpm 487
 
1654 aurelien 488
	* @param $abbrev (obligatoire): nom court de colonne, largement utilisé lors de l'import.
489
	*		  En effet chaque ligne importée est accessible à l'aide du `define` de $abbrev en majuscule, préfixé de "C_"
490
	*		  Exemple: $ligne[C_LONGITUDE] pour "longitude".
491
	*		  cf: ImportXLS::detectionEntete()
2143 jpm 492
 
1654 aurelien 493
	* @param $nom (obligatoire): nom complet de colonne (utilisé pour la ligne d'en-tête)
1702 raphael 494
	*		  Les définition de champs dynamique (correspondant à de multiples colonnes) doivent laisser cette valeur
495
	*		  vide afin de ne pas créer une colonne supplémentaire erronée.
2143 jpm 496
 
1654 aurelien 497
	* @param $is_extra:
498
	* Si 0, la colonne est une colonne standard
499
	* Si 1, la colonne est extra [le plus souvent générée automatiquement]
500
	*		 (auquel cas une bordure bleue entoure son nom dans la ligne d'entête)
501
	* Si 2, la colonne n'est pas traité à l'export, mais une définition peut lui être donnée
502
	*		 qui pourra être utilisée à l'import, exemple: "image"
2143 jpm 503
 
1654 aurelien 504
	* @param $fonction (optionnel): un nom d'un fonction de préprocessing
505
	* 		  $fonction doit prendre comme seul argument la valeur d'origine et retourner la valeur transformée
2143 jpm 506
 
1654 aurelien 507
	* @param $fonction_data (optionnel): une *méthode* d'obtention de donnée
508
	* 		  $fonction_data doit prendre comme premier argument le tableau des champs de l'enregistrement existant
509
	*		  $fonction_data doit retourner une valeur
2143 jpm 510
 
1654 aurelien 511
	* @param $importable (optionnel): défini si la colonne est traitée (ou absolument ignorée par PHPExcel) lors de
512
	*		  l'import.
1694 raphael 513
 
514
	* @param $preload (optionnel): défini une fonction de préchargement massif de donnée potentiellement utilisable par $fonction_data.
515
	*		  Utile, notamment, dans le cadre de l'export
1702 raphael 516
 
517
	* @param $fonction_dynamique (optionnel): défini une fonction ajoutant un nombre arbitraire de colonnes à une ligne donnée
518
	*		  Utile, notamment, dans le cadre de l'export des champs étendus ou des données baseflor
519
	*		  La fonction doit TOUJOURS alterer la ligne en lui ajoutant une nombre CONSTANT d'éléments (NULL ou non)
1765 raphael 520
	*		  La fonction doit prendre comme arguments ($obs, &$ligne_formatee)
1654 aurelien 521
	*/
1757 raphael 522
	static function GenColInfo($args) {
2461 jpm 523
		$default = array(
524
			'abbrev' => null,
525
			'nom' => null,
526
			'extra' => 0,
527
			'fonction' => null,
528
			'fonction_data' => null,
529
			'importable' => true,
530
			'preload' => null,
531
			'dyna' => null);
1757 raphael 532
		$ret = array_intersect_key($args, $default);
533
		return array_merge($default, $ret);
1654 aurelien 534
	}
2143 jpm 535
 
1656 raphael 536
	static function formaterDate($date_heure_mysql) {
1671 aurelien 537
		//return "";
2461 jpm 538
		if (!$date_heure_mysql || $date_heure_mysql == "0000-00-00 00:00:00") {
539
			return null;
540
		}
1671 aurelien 541
		// malheureusement pas disponible en php < 5.3
542
		//$date_format = DateTime::createFromFormat("Y-m-d H:i:s", $date_heure_mysql);
543
		$val = explode(' ', $date_heure_mysql);
544
		$date = explode('-', $val[0]);
545
		$heure = explode(':', $val[1]);
546
		$timestamp = mktime((int) $heure[0], (int) $heure[1], (int) $heure[2], (int) $date[1], (int) $date[2], (int) $date[0]);
2461 jpm 547
		if (!$timestamp) {
548
			return null;
549
		}
1656 raphael 550
		// TODO: les widgets ne font malheureusement pas usage de l'heure dans le CEL
551
		// TODO: si modification, ne pas oublier de modifier le format d'import correspondant
1698 raphael 552
		//	dans ImportXLS, traiterDateObs() (actuellement: "Y/m/d" car utilisation de strtotime() qui ne lit pas tout)
553
		// $date_formatee = strftime('%d/%m/%Y', $timestamp);
554
		$date_formatee = strftime('%Y/%m/%d', $timestamp);
2461 jpm 555
		if (!$date_formatee) {
556
			return '00/00/0000';
557
		}
1654 aurelien 558
		return $date_formatee;
559
	}
1757 raphael 560
 
1835 raphael 561
 
1759 raphael 562
 
563
 
2143 jpm 564
 
2730 mathias 565
	/**
566
	 * Enlève les zéros excédentaires (devenus nomades) au début et à la fin d'une
567
	 * latitude ou longitude, en prenant garde à ne pas foirer les nombres 0.xyz
568
	 */
1757 raphael 569
	public static function trim0($lonlat) {
2730 mathias 570
		$retour = trim($lonlat, "0");
571
		// si on a trop enlevé de zéros à gauche, on en remet un (mode synthobois)
572
		if (substr($retour, 0, 1) == ".") {
573
			$retour = "0" . $retour;
574
		}
575
		return $retour;
1757 raphael 576
	}
577
 
578
	public static function boolOuiNon($transmission) {
579
		return $transmission ? 'oui' : '';
580
	}
2143 jpm 581
 
582
 
3467 delphine 583
 
1654 aurelien 584
	// TODO: référentiel ne devrait pas être généré au moment d'un Config::get,
585
	// comme dans Config::get('nomsVernaRechercheLimiteeTpl')
586
	// Par exemple, la variable pour "nva" ?
587
	function getNomCommun($obs) {
588
		$langue = 'fra';
589
		list($referentiel) = explode(':', strtolower($obs['nom_referentiel']));
590
		if($referentiel == 'bdtfx') $referentiel = 'nvjfl';
591
		else return '';
2143 jpm 592
 
1654 aurelien 593
		$cache_id = $referentiel . '-' . $obs['nt'] . '-' . $langue;
1657 raphael 594
		if(isset(self::$cache['getNomCommun'][$cache_id])) {
1656 raphael 595
			//debug: error_log("require url_service_nom_attribution: OK ! (pour \"{$obs['nom_ret']}\")");
1657 raphael 596
			return self::$cache['getNomCommun'][$cache_id];
1654 aurelien 597
		}
598
		// pas de cache:
599
		//debug: error_log("require url_service_nom_attribution pour \"{$obs['nom_ret']}\"");
2143 jpm 600
 
1654 aurelien 601
		// pour bdtfx:
602
		// /service:eflore:0.1/nvjfl/noms-vernaculaires/attributions?masque.nt=X&masque.lg=fra&retour.champs=num_statut
603
		// /projet/services/modules/0.1/nvjfl/NomsVernaculaires.php
604
		$url = str_replace(Array('{referentiel}', '{valeur}', '{langue}'),
1656 raphael 605
						   Array($referentiel, $obs['nt'], $langue),
1657 raphael 606
						   self::$config['eflore']['url_service_nom_attribution']) . // TODO !
1656 raphael 607
			"&retour.champs=num_statut";
1654 aurelien 608
		$noms = @json_decode(file_get_contents($url));
609
		if(! $noms) return '';
1673 raphael 610
		$noms = array_filter((array)($noms->resultat), array($this, retournerNumStatutUn)); // XXX: php 5.3
1654 aurelien 611
		$nom = array_pop($noms)->nom_vernaculaire;
2143 jpm 612
 
1654 aurelien 613
		// cache
1657 raphael 614
		self::$cache['getNomCommun'][$cache_id] = $nom;
1654 aurelien 615
		return $nom;
616
	}
2143 jpm 617
 
1671 aurelien 618
	private function retournerNumStatutUn(&$item) {
619
		return ($item->num_statut == 1);
620
	}
1673 raphael 621
 
622
	private function retournerNumStatutUnArr(&$item) {
623
		return ($item['num_statut'] == 1);
624
	}
2143 jpm 625
 
1656 raphael 626
	// si getNomCommun_v2 ou getNomCommun_v3 sont utilisés
627
	/* require_once('/home/raphael/eflore/framework/framework/Framework.php');
628
	Framework::setCheminAppli("/home/raphael/eflore/projets/services/index.php");
629
	Framework::setInfoAppli(Config::get('info'));
630
	require_once('/home/raphael/eflore/projets/services/modules/0.1/Projets.php');*/
2143 jpm 631
 
1654 aurelien 632
	/* Tente de bootstraper le framework au plus court et d'initialiser une instance de
1656 raphael 633
	   NomsVernaculaires pour obtenir le nom commun */
1654 aurelien 634
	function getNomCommun_v2($obs) {
635
		static $service;
1656 raphael 636
		$service = new Projets();
2143 jpm 637
 
1654 aurelien 638
		$langue = 'fra';
639
		list($referentiel) = explode(':', strtolower($obs['nom_referentiel']));
640
		if($referentiel == 'bdtfx') $referentiel = 'nvjfl';
641
		else return '';
2143 jpm 642
 
1654 aurelien 643
		$cache_id = $referentiel . '-' . $obs['nt'] . '-' . $langue;
1657 raphael 644
		if(isset(self::$cache['getNomCommun'][$cache_id])) {
1656 raphael 645
			error_log("require NomsVernaculaires.php: OK ! (pour \"{$obs['nom_ret']}\")");
1657 raphael 646
			return self::$cache['getNomCommun'][$cache_id];
1654 aurelien 647
		}
648
		// pas de cache:
649
		error_log("require NomsVernaculaires.php pour \"{$obs['nom_ret']}\"");
2143 jpm 650
 
1656 raphael 651
		$donnees = Array('masque.nt' => $obs['nt'],
652
						 'masque.lg' => $langue,
653
						 'retour.champs' => 'num_statut');
1654 aurelien 654
		$noms = $service->consulter(Array('nvjfl', 'noms-vernaculaires'), $donnees);
2143 jpm 655
 
1654 aurelien 656
		if(! $noms) return '';
1673 raphael 657
		$noms = array_filter((array)($noms->resultat), array($this, retournerNumStatutUn)); // XXX: php 5.3
1654 aurelien 658
		$nom = array_pop($noms)->nom_vernaculaire;
2143 jpm 659
 
1656 raphael 660
		// cache
1657 raphael 661
		self::$cache['getNomCommun'][$cache_id] = $nom;
1654 aurelien 662
		return $nom;
663
	}
2143 jpm 664
 
665
 
1654 aurelien 666
	/* Effectue un bootstraping plus sage que ci-dessus, mais le gain d'efficacité
1656 raphael 667
	   n'est pas aussi retentissant qu'espéré */
1654 aurelien 668
	static $service;
669
	function getNomCommun_v3($obs) {
670
		if(! $this->service) $this->service = new Projets();
2143 jpm 671
 
1654 aurelien 672
		$langue = 'fra';
673
		list($referentiel) = explode(':', strtolower($obs['nom_referentiel']));
674
		if($referentiel == 'bdtfx') $referentiel = 'nvjfl';
675
		else return '';
2143 jpm 676
 
1654 aurelien 677
		$cache_id = $referentiel . '-' . $obs['nt'] . '-' . $langue;
1657 raphael 678
		if(isset(self::$cache['getNomCommun'][$cache_id])) {
1656 raphael 679
			error_log("require NomsVernaculaires.php: OK ! (pour \"{$obs['nom_ret']}\")");
1657 raphael 680
			return self::$cache['getNomCommun'][$cache_id];
1654 aurelien 681
		}
682
		// pas de cache:
1656 raphael 683
		error_log("require NomsVernaculaires.php pour \"{$obs['nom_ret']}\"");
2143 jpm 684
 
1654 aurelien 685
		$donnees = Array('masque.nt' => $obs['nt'],
1656 raphael 686
						 'masque.lg' => $langue,
687
						 'retour.champs' => 'conseil_emploi');
688
		$this->service->initialiserRessourcesEtParametres(Array('nvjfl', 'noms-vernaculaires', 'attributions'), $donnees);
1654 aurelien 689
		try {
1656 raphael 690
			$noms = $this->service->traiterRessources();
2143 jpm 691
		} catch(Exception $e) {
1656 raphael 692
			return '';
1654 aurelien 693
		}
1656 raphael 694
		if(! $noms) return '';
1673 raphael 695
		$noms = array_filter($noms['resultat'], array($this, retournerNumStatutUnArr)); // XXX: php 5.3
1656 raphael 696
		$premier_nom = array_pop($noms);
1654 aurelien 697
		$nom = $premier_nom['nom_vernaculaire'];
2143 jpm 698
 
1654 aurelien 699
		// cache
1657 raphael 700
		self::$cache['getNomCommun'][$cache_id] = $nom;
1654 aurelien 701
		return $nom;
702
	}
1685 raphael 703
 
1694 raphael 704
 
1702 raphael 705
 
2143 jpm 706
 
3467 delphine 707
 
1765 raphael 708
	static function getNomCommun_v4($obs) {
2446 jpm 709
		// Attention la fonction suppose que l'on ait fait appel à getNomCommun_preload avant
2281 aurelien 710
		// d'être appelée
1685 raphael 711
		if(! $obs['nt']) return NULL;
1765 raphael 712
		if(! self::referenceTableExiste()) return NULL;
1689 raphael 713
 
1685 raphael 714
		$langue = 'fra';
715
		list($referentiel) = explode(':', strtolower($obs['nom_referentiel']));
716
		$cache_id = $referentiel . '-' . $obs['nt'] . '-' . $langue;
717
 
2281 aurelien 718
		$nom = null;
1757 raphael 719
		// cache:
2281 aurelien 720
		if(isset(self::$cache['getNomCommun'])) {
1757 raphael 721
			if(isset(self::$cache['getNomCommun'][$cache_id])) return self::$cache['getNomCommun'][$cache_id];
722
			// XXX: problème de valeurs NULL ?
2281 aurelien 723
			if(array_key_exists($cache_id, self::$cache['getNomCommun'])) {
724
				$nom = self::$cache['getNomCommun'][$cache_id];
725
			}
1757 raphael 726
		}
1685 raphael 727
 
728
		return $nom;
729
	}
1702 raphael 730
 
731
 
732
	/* Cette fonction initialise le cache des données baseflor en 1 fois, sur la liste des observations à exporter.
733
	   Ainsi, les appels successifs à baseflor_ligne() ne sont pas couteux (pas de requête SQL) */
734
	static function baseflor_preload($cel, $obsids) {
735
		if(!$obsids) return;
1765 raphael 736
		if(!self::referenceTableExiste()) return NULL;
1702 raphael 737
 
2254 aurelien 738
		// Attention (en attendant de faire une meilleure table et une meilleure requete) le distinct est très important
739
		$req = sprintf("SELECT DISTINCT referentiel, num_nom_retenu, %s FROM cel_references r" .
2297 mathias 740
						" INNER JOIN cel_obs c ON (r.num_nom_retenu = c.nom_ret_nn)" .
741
						" AND r.referentiel = IF(LOCATE(':', c.nom_referentiel) = 0, c.nom_referentiel, SUBSTR(c.nom_referentiel FROM 1 FOR LOCATE(':', c.nom_referentiel) - 1))" .
742
						" WHERE c.id_observation IN (%s)",
743
						//" AND catminat_code IS NOT NULL", // TODO: suppression des NULL ici signifie que le cache sera partiel...
744
						implode(',', array_keys(self::$baseflor_col)),
745
						implode(',', $obsids));
1765 raphael 746
		$res = Cel::db()->requeter($req);
1706 raphael 747
		if(!$res) return NULL;
1702 raphael 748
 
749
		foreach($res as $v) {
750
			$data = $v;
751
			unset($data['referentiel']); // non nécessaire
752
			unset($data['num_nom_retenu']); // non nécessaire
2446 jpm 753
 
2244 aurelien 754
			// Des fois les synonymes ont des valeurs pour baseflor et pas le nom retenu et vice versa
2446 jpm 755
			// on les fusionne pour avoir le maximum d'infos, en attendant de repenser la table référence
2244 aurelien 756
			if(isset(self::$cache['getBaseflor'][$v['referentiel'] . '-' . $v['num_nom_retenu']])) {
2446 jpm 757
				$orig  = array_filter(self::$cache['getBaseflor'][$v['referentiel'] . '-' . $v['num_nom_retenu']], 'strlen');
758
				$data  = array_filter($data , 'strlen');
2244 aurelien 759
				$data = array_merge($orig, $data);
760
			}
2446 jpm 761
 
1702 raphael 762
			self::$cache['getBaseflor'][$v['referentiel'] . '-' . $v['num_nom_retenu']] = $data;
763
		}
764
 
765
		return NULL;
766
	}
1685 raphael 767
 
2446 jpm 768
	/**
2312 mathias 769
	 * Attention la fonction suppose que l'on ait fait appel à baseflor_preload avant
770
	 * d'être appelée
771
	 * @CASSECOUILLES elle pourrait le détecter et le faire elle-même
772
	 */
1765 raphael 773
	static function baseflor_ligne($obs, &$ligne) {
2312 mathias 774
		$clefsBF = array_keys(self::$baseflor_col);
775
		// par défaut des colonnes vides pour ne pas décaler le bousin
776
		$donneesBF = array_fill_keys($clefsBF, "");
1702 raphael 777
 
2312 mathias 778
		// s'il y a des données baseflor
779
		if ($obs['nom_ret_nn'] && self::referenceTableExiste() && count(self::$cache['getBaseflor']) > 0) {
780
			// l'astuce à un franc vingt
781
			list($referentiel) = explode(':', strtolower($obs['nom_referentiel']));
782
			$cache_id = $referentiel . '-' . $obs['nom_ret_nn'];
1702 raphael 783
 
2312 mathias 784
			// si les données baseflor existent dans le cache pour ce nom_ret_nn
785
			if (array_key_exists($cache_id, self::$cache['getBaseflor'])) {
786
				$donneesBFATrous = self::$cache['getBaseflor'][$cache_id];
787
				foreach($clefsBF as $colbf) { // remplit les trous tout en préservant l'ordre
788
					if(array_key_exists($colbf, $donneesBFATrous)) {
789
						$donneesBF[$colbf] = $donneesBFATrous[$colbf];
790
					} else {
791
						$donneesBF[$colbf] = "";
792
					}
793
				}
794
			}
1702 raphael 795
		}
2312 mathias 796
 
797
		// Quand les données sont prêtes, on les fusionne
798
		$ligne = array_merge($ligne, $donneesBF);
1702 raphael 799
	}
2446 jpm 800
 
1715 raphael 801
	static function champsEtendus_preload($cel, $obsids) {
2446 jpm 802
		$gestion_champs_etendus = new GestionChampsEtendus($cel->config, 'obs');
1718 raphael 803
		$colonnes_champs_supp_par_obs = $gestion_champs_etendus->consulterClesParLots($obsids);
2446 jpm 804
 
805
		// Supprime les champs étendus considérés comme privés dans le cas de l'export public en chargeant
2403 aurelien 806
		// le catalogue et en excluant ceux qui sont explicitement privés
807
		if(!$cel->export_prive) {
808
			$indices_a_supprimer = array();
809
			$catalogue_champs_etendus = $gestion_champs_etendus->consulterCatalogueChampsEtendusPredefinis();
810
			foreach($catalogue_champs_etendus as $champ_catalogue) {
811
				if($champ_catalogue['options']['prive'] == 1) {
2446 jpm 812
					// Les champs étendus peuvent avoir des variantes lorsqu'ils apparaissent de multiples fois.
2407 aurelien 813
					// Vont donc matcher monChamp mais aussi monChamp:1, monChamp:2 ou bien monChamp1, monChamp: etc...
814
					// pour plus de sécurité (ce filtra n'est affectué qu'une fois au début de l'export donc on ne s'en prive pas)
815
					$entrees = preg_grep("/".$champ_catalogue['cle']."(?::?\d*)?$/", $colonnes_champs_supp_par_obs);
2403 aurelien 816
					$indices_a_supprimer = array_merge($indices_a_supprimer, array_keys($entrees));
817
				}
818
			}
819
			// les champs étendus sont renvoyés dans l'export suivant les colonnes présentes dans ce tableau
820
			// les éliminer de la liste des colonnes suffit à les faire ignorer par l'export
2446 jpm 821
			foreach($indices_a_supprimer as $indice_supp) {
822
				unset($colonnes_champs_supp_par_obs[$indice_supp]);
2403 aurelien 823
			}
824
		}
2446 jpm 825
 
1741 raphael 826
		// ces deux lignes réordonnent l'ordre des colonnes des champs étendus en fonction de l'ordre (très spécifique)
827
		// de self::$ordre_champ_etendus_Florileges, les champs non-mentionnés sont ajoutés à la fin.
828
		$colonnes_champs_supp_par_obs = self::sortArrayByArray(array_flip($colonnes_champs_supp_par_obs),
829
															   self::$ordre_champ_etendus_Florileges);
830
		$colonnes_champs_supp_par_obs = array_keys($colonnes_champs_supp_par_obs);
831
 
1718 raphael 832
		// si le SELECT des clefs ne retourne rien, une autre requêtes est inutile
833
		// TODO: optimize, 1 seule requête
834
		if(!$colonnes_champs_supp_par_obs) return Array('header' => array(), 'data' => array());
835
 
1715 raphael 836
		$champs_supp_par_obs = $gestion_champs_etendus->consulterParLots($obsids);
1741 raphael 837
 
1791 raphael 838
		self::$cache['champsEtendus']['header'] = self::champsEtendus_prefixHeader($colonnes_champs_supp_par_obs);
839
 
1715 raphael 840
		foreach($champs_supp_par_obs as &$v) {
841
			$v = self::champsEtendus_aplatir($v);
842
		}
843
		self::$cache['champsEtendus']['data'] = $champs_supp_par_obs;
844
		// ce return est temporaire,
845
		// le temps que toutes les fonctions bougent ici et utilise plutôt le cache statique
1716 raphael 846
		// encore utilisé pour les entêtes (self::$cache['champsEtendus']['header'])
1715 raphael 847
		return self::$cache['champsEtendus'];
848
	}
849
 
850
	// XXX: PHP-5.3, fonction anonyme + array_map
1791 raphael 851
	static function champsEtendus_prefixHeader($array) {
852
		return array_map(create_function('$v', 'return "' . PREFIX_CHAMPS_ETENDUS . '".$v;'), $array);
853
	}
854
 
855
	// XXX: PHP-5.3, fonction anonyme + array_map
1715 raphael 856
	static function champsEtendus_aplatir($ligne_champs_etendus) {
857
		$champs_etendus_fmt = array();
858
		if(!$ligne_champs_etendus) return $champs_etendus_fmt;
859
		foreach($ligne_champs_etendus as $champ) {
1791 raphael 860
			$champs_etendus_fmt[PREFIX_CHAMPS_ETENDUS . $champ->cle] = $champ->valeur;
1715 raphael 861
		}
862
		return $champs_etendus_fmt;
863
	}
1716 raphael 864
 
1765 raphael 865
	static function champsEtendus_ligne($obs, &$ligne) {
1716 raphael 866
		// si header n'est pas défini, aucune observation ne possède de champ étendu
867
		// et nous n'ajoutons ni colonnes, ni valeurs.
868
		if(! isset(self::$cache['champsEtendus']['header'])) return;
1736 raphael 869
		$ligne_etendue_aplatie = @self::$cache['champsEtendus']['data'][$obs['id_observation']];
1716 raphael 870
 
871
		$ligne_supp = array_fill(0, count(self::$cache['champsEtendus']['header']), '');
872
		$ligne_etendue_fmt = array();
873
 
874
		// si, cependant cette seule observation n'a pas de champs étendus,
875
		// nous devons rajouter des blancs (notamment dans le cas ou d'autres
876
		// champs viennent à être ajoutés en aval à l'avenir
877
		// cf: $fonction_dynamique dans FormateurGroupeColonne::GenColInfo()
878
		if(! $ligne_etendue_aplatie) {
879
			$ligne = array_merge($ligne, $ligne_supp);
880
			return;
881
		}
882
 
883
		foreach(self::$cache['champsEtendus']['header'] as $colonne) {
884
			if(!isset($ligne_etendue_aplatie[$colonne])) {
2143 jpm 885
				$ligne_etendue_fmt[$colonne] = '';
1716 raphael 886
			} else {
887
				$ligne_etendue_fmt[$colonne] = $ligne_etendue_aplatie[$colonne];
888
			}
889
		}
890
 
891
		// XXX/ array_merge() ?
892
		$ligne += $ligne_etendue_fmt;
893
	}
1741 raphael 894
 
895
	/* HELPERS */
896
 
897
	// http://stackoverflow.com/questions/348410/sort-an-array-based-on-another-array
898
	// XXX; redéfinition, utilisé aussi par ExportXLS
899
	static function sortArrayByArray($array, $orderArray) {
900
		$ordered = array();
901
		foreach($orderArray as $key) {
902
			if(array_key_exists($key, $array)) {
903
				$ordered[$key] = $array[$key];
904
				unset($array[$key]);
905
			}
906
		}
907
		return $ordered + $array;
908
	}
2461 jpm 909
}