Subversion Repositories eFlore/Applications.cel

Rev

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