Subversion Repositories eFlore/Applications.cel

Rev

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

Rev Author Line No. Line
1374 aurelien 1
<?php
2462 jpm 2
// declare(encoding='UTF-8');
1374 aurelien 3
/**
2462 jpm 4
 * Service fournissant des exports des données publiques du CEL pour le widget.
5
 *
6
 * Format du service :
7
 * /CelWidgetExport/format
8
 * /CelWidgetExport/csv
9
 *
10
 * Les paramêtres :
11
 *  - "start" indique le numéro du premier item à afficher
12
 *  - "limit" nombre d'items à afficher
13
 *
14
 * @internal   Mininum PHP version : 5.2
15
 * @category   CEL
16
 * @package    Services
17
 * @subpackage Widget
18
 * @version    0.1
19
 * @author     Mathias CHOUET <mathias@tela-botanica.org>
20
 * @author     Jean-Pascal MILCENT <jpm@tela-botanica.org>
21
 * @author     Aurelien PERONNET <aurelien@tela-botanica.org>
22
 * @license    GPL v3 <http://www.gnu.org/licenses/gpl.txt>
23
 * @license    CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt>
24
 * @copyright  1999-2014 Tela Botanica <accueil@tela-botanica.org>
25
 */
1610 raphael 26
set_include_path(get_include_path() . PATH_SEPARATOR . dirname(dirname(realpath(__FILE__))) . '/lib');
27
// la sortie est binaire (xls), mais OLE n'est pas compatible E_ALL en PHP-5.4
1700 raphael 28
error_reporting(error_reporting() & ~E_STRICT);
2459 jpm 29
require_once 'lib/OLE.php';
30
require_once 'lib/Spreadsheet/Excel/Writer.php';
1610 raphael 31
 
1374 aurelien 32
class CelWidgetExport extends Cel {
3131 delphine 33
 
1408 aurelien 34
	private $nom_fichier_export = 'cel_export';
1671 aurelien 35
	// certains paramètres apparaissent plusieurs fois car ils ont des alias
36
	// dans certains widgets
1376 aurelien 37
	private $parametres_autorises = array(
3131 delphine 38
			'id_utilisateur' => 'ce_utilisateur',
39
			'utilisateur' => 'courriel_utilisateur',
40
			'courriel_utilisateur' => 'courriel_utilisateur',
41
			'pays' => 'pays',
42
			'commune' => 'zone_geo',
43
			'zone_geo' => 'zone_geo',
44
			'dept' => 'departement',
45
			'departement' => 'departement',
46
			'lieudit' => 'lieudit',
47
			'station' => 'station',
48
			'projet' => 'mots_cles',
49
			'programme' => 'programme',
50
			'num_taxon' => 'nt',
51
			'date_debut' => 'date_debut',
52
			'date_fin' => 'date_fin',
53
			'taxon' => 'taxon',
54
			'identiplante' => 'validation_identiplante',
55
			'validation_identiplante' => 'validation_identiplante',
56
			'annee' => 'annee',
57
			'mois' => 'mois',
58
			'jour' => 'jour',
59
			'recherche' => 'recherche',
60
			'id_mots_cles' => 'id_mots_cles',
61
			'mots_cles' => 'mots_cles',
62
			'debut' => 'debut',
63
			'limite' => 'limite',
64
			'format' => 'format',
65
			'colonnes' => 'colonnes',
66
			'transmission' => 'transmission',
67
			'obsids' => 'obsids',
3134 delphine 68
			'standard' => 'standard',
1376 aurelien 69
	);
3131 delphine 70
 
2459 jpm 71
	private $limite_decoupage_defaut = 9000;
3131 delphine 72
 
1402 aurelien 73
	private $format = 'csv';
3131 delphine 74
 
1659 aurelien 75
	public $id_utilisateur = null;
3131 delphine 76
 
2403 aurelien 77
	public $export_prive = false;
3131 delphine 78
 
1715 raphael 79
	// un cache, initialisé par certaines fonctions de préchargement, à la manière
80
	// de ce qui est fait par FormateurGroupeColonne
81
	static $cache = Array();
3131 delphine 82
 
1579 aurelien 83
	public function getRessource() {
84
		return $this->getElement(array());
85
	}
3131 delphine 86
 
1374 aurelien 87
	/**
88
	 * Méthode appelée avec une requête de type GET.
89
	 */
1709 raphael 90
	public function getElement($params = array()) {
1711 raphael 91
		switch(@strtolower($params[0])) {
3131 delphine 92
			case 'calcul':
93
				$this->getCalcul();
94
				break;
95
 
96
			case 'export':
97
				$this->getExport();
98
				break;
99
			default:
100
				$this->getExport();
1625 aurelien 101
		}
102
	}
3131 delphine 103
 
1625 aurelien 104
	private function getCalcul() {
1611 raphael 105
		$criteres = $this->traiterParametresAutorises($_GET);
3134 delphine 106
		if (!isset($criteres['standard'])) {
107
				$criteres['transmission'] = 1;
108
		} else {
109
			unset($criteres['transmission']);
110
		}
2403 aurelien 111
		// Définit si l'on exporte les obs privées ainsi que les champs étendus privés
112
		$this->export_prive = $this->doitEtPeutExporterObsPrivees($criteres);
113
		if($this->export_prive) {
1654 aurelien 114
			unset($criteres['transmission']);
1659 aurelien 115
			$this->id_utilisateur = $criteres['id_utilisateur'];
1654 aurelien 116
		}
3134 delphine 117
		if (isset($criteres['standard']) && $criteres['standard'] == 1) {
118
			$chercheur_observations = new RechercheObservationExport($this->config);
119
		} else {
120
			$chercheur_observations = new RechercheObservation($this->config);
121
		}
1379 aurelien 122
		$numero_page = isset($criteres['debut']) ? $criteres['debut'] : 0;
123
		$limite = isset($criteres['limite']) ? $criteres['limite'] : 0;
3134 delphine 124
		$colonnes = @FormateurGroupeColonne::colGroupsValidation($criteres['colonnes'], $criteres['programme']);
3131 delphine 125
 
1374 aurelien 126
		unset($criteres['limite']);
127
		unset($criteres['debut']);
1625 aurelien 128
		unset($criteres['format']);
1654 aurelien 129
		unset($criteres['colonnes']);
3131 delphine 130
 
1625 aurelien 131
		$nb_observations = $chercheur_observations->compterObservations(null, $criteres);
2250 aurelien 132
		$limite_decoupage = $this->calculerNbLignesMaxParFichier(explode(',', $colonnes));
3131 delphine 133
 
1625 aurelien 134
		$url_telechargements = array();
135
		$intervalle = 0;
3131 delphine 136
 
1625 aurelien 137
		$params_url = $criteres;
138
		unset($params_url['transmission']);
139
		do {
140
			$base_url = $this->config['settings']['baseURLAbsolu'].'CelWidgetExport/export';
141
			$params_url['debut'] = $intervalle;
142
			$params_url['limite'] = $limite_decoupage;
143
			$url_telechargement_fichier = $base_url;
1654 aurelien 144
			$url_telechargements[] = $base_url.'?'.http_build_query($params_url).'&format='.$this->format.'&colonnes='.$colonnes;
1625 aurelien 145
			$intervalle += $limite_decoupage;
146
			$nb_observations -= $limite_decoupage;
2190 mathias 147
		} while($nb_observations > 0);
3131 delphine 148
 
1625 aurelien 149
		$this->envoyerJson($url_telechargements);
150
	}
3131 delphine 151
 
2250 aurelien 152
	private function calculerNbLignesMaxParFichier($colonnes) {
2459 jpm 153
		$limite = $this->limite_decoupage_defaut;
3131 delphine 154
 
1402 aurelien 155
		switch($this->format) {
156
			case 'csv':
1625 aurelien 157
				$limite = 20000;
158
				break;
159
			case 'xls':
160
				$limite = 8000;
161
				break;
1660 raphael 162
			case 'pdf':
163
				$limite = 300;
164
				break;
1625 aurelien 165
		}
3131 delphine 166
 
2253 aurelien 167
		return $limite;
1625 aurelien 168
	}
3131 delphine 169
 
1625 aurelien 170
	private function getExport() {
171
		$criteres = $this->traiterParametresAutorises($_GET);
1711 raphael 172
		// ne pas faire de super-requête en cas d'absence de paramètres
173
		// par exemple "format", au minimum, devrait être défini
1715 raphael 174
		if(!$criteres) die('erreur: pas de paramètre reçu');
175
		if(!in_array($this->format, array('pdf','csv','xls'))) die('erreur: format invalide');
3131 delphine 176
 
3134 delphine 177
		if (!isset($criteres['standard'])) {
178
			$criteres['transmission'] = 1;
179
		} else {
180
			unset($criteres['transmission']);
181
		}
2403 aurelien 182
		// Définit si l'on exporte les obs privées ainsi que les champs étendus privés
183
		$this->export_prive = $this->doitEtPeutExporterObsPrivees($criteres);
184
		if($this->export_prive) {
3131 delphine 185
			//unset($criteres['transmission']);
1755 raphael 186
			$this->id_utilisateur = $criteres['ce_utilisateur'];
1654 aurelien 187
		}
3134 delphine 188
		if (isset($criteres['standard']) && $criteres['standard'] == 1) {
189
			$chercheur_observations = new RechercheObservationExport($this->config);
190
		} else {
191
			$chercheur_observations = new RechercheObservation($this->config);
192
		}
1679 raphael 193
		$debut = isset($criteres['debut']) ? intval($criteres['debut']) : 0;
194
		$limite = isset($criteres['limite']) ? intval($criteres['limite']) : 0;
1714 raphael 195
		$groupes = @FormateurGroupeColonne::colGroupsValidation($criteres['colonnes']);
1835 raphael 196
		$groupes .= ',auteur';
3131 delphine 197
 
1714 raphael 198
		if(!$groupes) die('erreur: Ne peut identifier les groupes de champs demandés.');
3131 delphine 199
 
200
 
1679 raphael 201
		if($criteres['obsids']) $criteres['sql_brut'] = sprintf('id_observation IN (%s)',
3131 delphine 202
				implode(',', $criteres['obsids']));
203
 
1625 aurelien 204
		unset($criteres['limite']);
205
		unset($criteres['debut']);
206
		unset($criteres['format']);
1654 aurelien 207
		unset($criteres['colonnes']);
1679 raphael 208
		unset($criteres['obsids']);
3131 delphine 209
 
1679 raphael 210
		$observations = $chercheur_observations->rechercherObservations(null, $criteres, $debut, $limite, TRUE)->get();
1659 aurelien 211
		$ids = array();
212
		foreach($observations as &$obs) {
213
			$ids[] = $obs['id_observation'];
214
		}
3131 delphine 215
 
1703 raphael 216
		if($this->format == 'pdf') {
217
			$pdf = $this->convertirEnPdf($observations);
218
			$pdf->pdf->Output('etiquettes.pdf', 'I');
219
			exit;
1662 aurelien 220
		}
3131 delphine 221
 
1703 raphael 222
		// cas XLS et CSV: on peut avoir besoin des champs étendus, des noms communs et des champs baseflor:
3131 delphine 223
 
1715 raphael 224
		// Obtention des colonnes correspondantes aux groupes de champs
1714 raphael 225
		$colonnes = FormateurGroupeColonne::nomEnsembleVersListeColonnes($groupes);
3131 delphine 226
 
1715 raphael 227
		/*
3131 delphine 228
		 Champs étendus et noms communs, si demandés.
229
		 * Pour "nom commun", "preload" retourne NULL, car c'est le cache statique de FormateurGroupeColonne
230
		 qu'il initialise et utilise en interne sans qu'un passage par paramètre dans le contexte de CelWidgetExport
231
		 ne soit nécessaire.
232
		 * Pour les champs étendus, c'est CelWidgetExport::$cache qui est utilisé, aussi bien pour les en-têtes que
233
		 pour les données préchargées, cf self::traiterLigneEtendue()
234
		 */
1715 raphael 235
		self::$cache = FormateurGroupeColonne::preload($colonnes, $this, $ids);
3131 delphine 236
 
237
		// TODO: tous les champs étendus et les paramètres supplémentaires devraient être passés en un seul
238
		// tableau (et chaque formateur csv, xls etc... pourrait également être dans une classe à part)
1625 aurelien 239
		switch($this->format) {
3131 delphine 240
			case 'csv':
241
				$csv = $this->convertirEnCsv($observations, $colonnes);
242
				$this->envoyerCsv($csv);
243
				break;
244
			case 'xls':
245
				$xls = $this->convertirEnXls($observations, $colonnes);
246
				$this->envoyerXls($xls);
247
				break;
248
			default:
1402 aurelien 249
		}
1374 aurelien 250
	}
3131 delphine 251
 
1611 raphael 252
	protected function traiterParametresAutorises(Array $parametres) {
1376 aurelien 253
		$parametres_traites = array();
1402 aurelien 254
		$this->format = (isset($parametres['format']) && $parametres['format'] != '') ? $parametres['format'] : $this->format;
1376 aurelien 255
		foreach($parametres as $cle => $valeur) {
1711 raphael 256
			if(is_string($valeur) && !trim($valeur)) continue;
257
			if(isset($this->parametres_autorises[$cle])) {
1376 aurelien 258
				$parametres_traites[$this->parametres_autorises[$cle]] = $valeur;
259
			}
260
		}
261
		return $parametres_traites;
262
	}
3131 delphine 263
 
1374 aurelien 264
	private function envoyerCsv($csv) {
265
		header('Content-Type: text/csv; charset=UTF-8');
1408 aurelien 266
		header('Content-Disposition: attachment;filename='.$this->nom_fichier_export.'.csv');
1374 aurelien 267
		echo $csv;
1376 aurelien 268
		exit;
1374 aurelien 269
	}
3131 delphine 270
 
1402 aurelien 271
	private function envoyerXls($workbook) {
272
		$workbook->close();
273
		exit;
274
	}
3131 delphine 275
 
1715 raphael 276
	private function convertirEnCsv(&$data, $colonnes) {
1374 aurelien 277
		$chemin_temp = "php://temp";
278
		$outstream = fopen($chemin_temp, 'r+');
3131 delphine 279
 
1711 raphael 280
		$intitule_champs = array_merge(FormateurGroupeColonne::getIntitulesColonnes($colonnes));
1703 raphael 281
		// en premier car utilisé génériquement dans getLigneObservation()
1711 raphael 282
		if(isset($colonnes['baseflor'])) {
1703 raphael 283
			$intitule_champs = array_merge($intitule_champs, FormateurGroupeColonne::$baseflor_col);
284
		}
285
		// en second car manuellement appellé plus bas, TODO: utiliser l'API du FormateurGroupeColonne
1715 raphael 286
		if(isset($colonnes['etendu'])) {
287
			$intitule_champs = array_merge($intitule_champs, array_values(self::$cache['etendu']['header']));
288
		}
3131 delphine 289
 
1690 raphael 290
		// header
2459 jpm 291
		fputcsv($outstream, $intitule_champs, ',', '"');
1690 raphael 292
		// lignes
1617 aurelien 293
		foreach($data as &$ligne) {
1692 raphael 294
			$ligne = self::filtrerDonneesSensibles($ligne);
1711 raphael 295
			$ligne = FormateurGroupeColonne::getLigneObservation($ligne, $colonnes, $this);
1374 aurelien 296
			fputcsv($outstream, $ligne, ',', '"');
297
		}
298
		rewind($outstream);
299
		$csv = stream_get_contents($outstream);
300
		fclose($outstream);
301
		return $csv;
302
	}
3131 delphine 303
 
1715 raphael 304
	private function convertirEnXls(&$data, $colonnes) {
1402 aurelien 305
		$this->extendSpreadsheetProductor = new SpreadsheetProductor();
306
		$this->extendSpreadsheetProductor->initSpreadsheet();
3131 delphine 307
 
1402 aurelien 308
		$workbook = new Spreadsheet_Excel_Writer();
1804 raphael 309
		// avant la définition du titre de la worksheet !
310
		$workbook->setVersion(8);
3131 delphine 311
 
1625 aurelien 312
		$worksheet = $workbook->addWorksheet('Liste');
313
		$workbook->setTempDir($this->config['cel']['chemin_stockage_temp']);
1612 raphael 314
		$worksheet->setInputEncoding('utf-8');
1408 aurelien 315
		$workbook->send($this->nom_fichier_export.'.xls');
3131 delphine 316
 
1402 aurelien 317
		$nb_lignes = 1;
3131 delphine 318
 
1711 raphael 319
		$intitule_champs = array_merge(FormateurGroupeColonne::getIntitulesColonnes($colonnes));
1703 raphael 320
		// en premier car utilisé génériquement dans getLigneObservation()
1711 raphael 321
		if(isset($colonnes['baseflor'])) {
1703 raphael 322
			$intitule_champs = array_merge($intitule_champs, FormateurGroupeColonne::$baseflor_col);
323
		}
324
		// en second car manuellement appellé plus bas, TODO: utiliser l'API du FormateurGroupeColonne
1715 raphael 325
		if(isset($colonnes['etendu'])) {
326
			$intitule_champs = array_merge($intitule_champs, array_values(self::$cache['etendu']['header']));
327
		}
3131 delphine 328
 
1690 raphael 329
		// header
330
		$indice = 0;
2459 jpm 331
		foreach ($intitule_champs as &$intitule) {
1692 raphael 332
			$worksheet->write(0,$indice++,$intitule);
1690 raphael 333
		}
3131 delphine 334
 
1617 aurelien 335
		foreach($data as &$ligne) {
1692 raphael 336
			$ligne = self::filtrerDonneesSensibles($ligne);
1711 raphael 337
			$ligne = FormateurGroupeColonne::getLigneObservation($ligne, $colonnes, $this);
1402 aurelien 338
			$indice = 0;
1617 aurelien 339
			foreach($ligne as &$champ) {
1692 raphael 340
				$worksheet->write($nb_lignes,$indice++,$champ);
1402 aurelien 341
			}
342
			$nb_lignes++;
343
		}
344
		return $workbook;
345
	}
3131 delphine 346
 
1662 aurelien 347
	private function convertirEnPdf(&$observations) {
1715 raphael 348
		if(count($observations) > 300) die('erreur: trop de données');
1662 aurelien 349
		//require_once('GenerateurPDF.php');
350
		$pdf = new GenerateurPDF();
351
		$pdf->export($observations);
352
		return $pdf;
353
	}
3131 delphine 354
 
1692 raphael 355
	static function filtrerDonneesSensibles($ligne) {
1429 aurelien 356
		if(stripos($ligne['mots_cles_texte'], 'sensible') !== false) {
357
			$ligne['latitude'] = '';
358
			$ligne['longitude'] = '';
359
		}
360
		return $ligne;
361
	}
3131 delphine 362
 
1654 aurelien 363
	private function doitEtPeutExporterObsPrivees($criteres) {
2459 jpm 364
		return isset($criteres['ce_utilisateur']) &&
3131 delphine 365
		$this->peutExporterObsPrivees($criteres['ce_utilisateur']);
1654 aurelien 366
	}
3131 delphine 367
 
1654 aurelien 368
	private function peutExporterObsPrivees($id_utilisateur) {
2806 aurelien 369
		$gestion_utilisateur = new GestionUtilisateur($this->config);
1654 aurelien 370
		$utilisateur = $gestion_utilisateur->obtenirIdentiteConnectee();
1703 raphael 371
		return ! empty($utilisateur['id_utilisateur']) && $id_utilisateur == $utilisateur['id_utilisateur'];
1654 aurelien 372
	}
3131 delphine 373
 
3134 delphine 374
 
1374 aurelien 375
}
376
?>