Subversion Repositories eFlore/Applications.cel

Rev

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