Subversion Repositories eFlore/Applications.cel

Rev

Rev 3139 | 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) {
3146 delphine 185
			unset($criteres['transmission']);
1755 raphael 186
			$this->id_utilisateur = $criteres['ce_utilisateur'];
1654 aurelien 187
		}
3146 delphine 188
 
189
		// critère standard correspond au format de données standard défini dans widget sinon cel
3134 delphine 190
		if (isset($criteres['standard']) && $criteres['standard'] == 1) {
191
			$chercheur_observations = new RechercheObservationExport($this->config);
192
		} else {
193
			$chercheur_observations = new RechercheObservation($this->config);
194
		}
1679 raphael 195
		$debut = isset($criteres['debut']) ? intval($criteres['debut']) : 0;
196
		$limite = isset($criteres['limite']) ? intval($criteres['limite']) : 0;
1714 raphael 197
		$groupes = @FormateurGroupeColonne::colGroupsValidation($criteres['colonnes']);
1835 raphael 198
		$groupes .= ',auteur';
3131 delphine 199
 
1714 raphael 200
		if(!$groupes) die('erreur: Ne peut identifier les groupes de champs demandés.');
3131 delphine 201
 
202
 
3139 killian 203
		if(isset($criteres['obsids'])) $criteres['sql_brut'] = sprintf('id_observation IN (%s)',
3131 delphine 204
				implode(',', $criteres['obsids']));
205
 
1625 aurelien 206
		unset($criteres['limite']);
207
		unset($criteres['debut']);
208
		unset($criteres['format']);
1654 aurelien 209
		unset($criteres['colonnes']);
1679 raphael 210
		unset($criteres['obsids']);
3131 delphine 211
 
1679 raphael 212
		$observations = $chercheur_observations->rechercherObservations(null, $criteres, $debut, $limite, TRUE)->get();
1659 aurelien 213
		$ids = array();
214
		foreach($observations as &$obs) {
215
			$ids[] = $obs['id_observation'];
216
		}
3131 delphine 217
 
1703 raphael 218
		if($this->format == 'pdf') {
219
			$pdf = $this->convertirEnPdf($observations);
220
			$pdf->pdf->Output('etiquettes.pdf', 'I');
221
			exit;
1662 aurelien 222
		}
3131 delphine 223
 
1703 raphael 224
		// cas XLS et CSV: on peut avoir besoin des champs étendus, des noms communs et des champs baseflor:
3131 delphine 225
 
1715 raphael 226
		// Obtention des colonnes correspondantes aux groupes de champs
1714 raphael 227
		$colonnes = FormateurGroupeColonne::nomEnsembleVersListeColonnes($groupes);
3131 delphine 228
 
1715 raphael 229
		/*
3131 delphine 230
		 Champs étendus et noms communs, si demandés.
231
		 * Pour "nom commun", "preload" retourne NULL, car c'est le cache statique de FormateurGroupeColonne
232
		 qu'il initialise et utilise en interne sans qu'un passage par paramètre dans le contexte de CelWidgetExport
233
		 ne soit nécessaire.
234
		 * Pour les champs étendus, c'est CelWidgetExport::$cache qui est utilisé, aussi bien pour les en-têtes que
235
		 pour les données préchargées, cf self::traiterLigneEtendue()
236
		 */
1715 raphael 237
		self::$cache = FormateurGroupeColonne::preload($colonnes, $this, $ids);
3131 delphine 238
 
239
		// TODO: tous les champs étendus et les paramètres supplémentaires devraient être passés en un seul
240
		// tableau (et chaque formateur csv, xls etc... pourrait également être dans une classe à part)
1625 aurelien 241
		switch($this->format) {
3131 delphine 242
			case 'csv':
243
				$csv = $this->convertirEnCsv($observations, $colonnes);
244
				$this->envoyerCsv($csv);
245
				break;
246
			case 'xls':
247
				$xls = $this->convertirEnXls($observations, $colonnes);
248
				$this->envoyerXls($xls);
249
				break;
250
			default:
1402 aurelien 251
		}
1374 aurelien 252
	}
3131 delphine 253
 
1611 raphael 254
	protected function traiterParametresAutorises(Array $parametres) {
1376 aurelien 255
		$parametres_traites = array();
1402 aurelien 256
		$this->format = (isset($parametres['format']) && $parametres['format'] != '') ? $parametres['format'] : $this->format;
1376 aurelien 257
		foreach($parametres as $cle => $valeur) {
1711 raphael 258
			if(is_string($valeur) && !trim($valeur)) continue;
259
			if(isset($this->parametres_autorises[$cle])) {
1376 aurelien 260
				$parametres_traites[$this->parametres_autorises[$cle]] = $valeur;
261
			}
262
		}
263
		return $parametres_traites;
264
	}
3131 delphine 265
 
1374 aurelien 266
	private function envoyerCsv($csv) {
267
		header('Content-Type: text/csv; charset=UTF-8');
1408 aurelien 268
		header('Content-Disposition: attachment;filename='.$this->nom_fichier_export.'.csv');
1374 aurelien 269
		echo $csv;
1376 aurelien 270
		exit;
1374 aurelien 271
	}
3131 delphine 272
 
1402 aurelien 273
	private function envoyerXls($workbook) {
274
		$workbook->close();
275
		exit;
276
	}
3131 delphine 277
 
1715 raphael 278
	private function convertirEnCsv(&$data, $colonnes) {
1374 aurelien 279
		$chemin_temp = "php://temp";
280
		$outstream = fopen($chemin_temp, 'r+');
3131 delphine 281
 
1711 raphael 282
		$intitule_champs = array_merge(FormateurGroupeColonne::getIntitulesColonnes($colonnes));
1703 raphael 283
		// en premier car utilisé génériquement dans getLigneObservation()
1711 raphael 284
		if(isset($colonnes['baseflor'])) {
1703 raphael 285
			$intitule_champs = array_merge($intitule_champs, FormateurGroupeColonne::$baseflor_col);
286
		}
287
		// en second car manuellement appellé plus bas, TODO: utiliser l'API du FormateurGroupeColonne
1715 raphael 288
		if(isset($colonnes['etendu'])) {
289
			$intitule_champs = array_merge($intitule_champs, array_values(self::$cache['etendu']['header']));
290
		}
3131 delphine 291
 
1690 raphael 292
		// header
2459 jpm 293
		fputcsv($outstream, $intitule_champs, ',', '"');
1690 raphael 294
		// lignes
1617 aurelien 295
		foreach($data as &$ligne) {
1692 raphael 296
			$ligne = self::filtrerDonneesSensibles($ligne);
1711 raphael 297
			$ligne = FormateurGroupeColonne::getLigneObservation($ligne, $colonnes, $this);
1374 aurelien 298
			fputcsv($outstream, $ligne, ',', '"');
299
		}
300
		rewind($outstream);
301
		$csv = stream_get_contents($outstream);
302
		fclose($outstream);
303
		return $csv;
304
	}
3131 delphine 305
 
1715 raphael 306
	private function convertirEnXls(&$data, $colonnes) {
1402 aurelien 307
		$this->extendSpreadsheetProductor = new SpreadsheetProductor();
308
		$this->extendSpreadsheetProductor->initSpreadsheet();
3131 delphine 309
 
1402 aurelien 310
		$workbook = new Spreadsheet_Excel_Writer();
1804 raphael 311
		// avant la définition du titre de la worksheet !
312
		$workbook->setVersion(8);
3131 delphine 313
 
1625 aurelien 314
		$worksheet = $workbook->addWorksheet('Liste');
315
		$workbook->setTempDir($this->config['cel']['chemin_stockage_temp']);
1612 raphael 316
		$worksheet->setInputEncoding('utf-8');
1408 aurelien 317
		$workbook->send($this->nom_fichier_export.'.xls');
3131 delphine 318
 
1402 aurelien 319
		$nb_lignes = 1;
3131 delphine 320
 
1711 raphael 321
		$intitule_champs = array_merge(FormateurGroupeColonne::getIntitulesColonnes($colonnes));
1703 raphael 322
		// en premier car utilisé génériquement dans getLigneObservation()
1711 raphael 323
		if(isset($colonnes['baseflor'])) {
1703 raphael 324
			$intitule_champs = array_merge($intitule_champs, FormateurGroupeColonne::$baseflor_col);
325
		}
326
		// en second car manuellement appellé plus bas, TODO: utiliser l'API du FormateurGroupeColonne
1715 raphael 327
		if(isset($colonnes['etendu'])) {
328
			$intitule_champs = array_merge($intitule_champs, array_values(self::$cache['etendu']['header']));
329
		}
3131 delphine 330
 
1690 raphael 331
		// header
332
		$indice = 0;
2459 jpm 333
		foreach ($intitule_champs as &$intitule) {
1692 raphael 334
			$worksheet->write(0,$indice++,$intitule);
1690 raphael 335
		}
3131 delphine 336
 
1617 aurelien 337
		foreach($data as &$ligne) {
1692 raphael 338
			$ligne = self::filtrerDonneesSensibles($ligne);
1711 raphael 339
			$ligne = FormateurGroupeColonne::getLigneObservation($ligne, $colonnes, $this);
1402 aurelien 340
			$indice = 0;
1617 aurelien 341
			foreach($ligne as &$champ) {
1692 raphael 342
				$worksheet->write($nb_lignes,$indice++,$champ);
1402 aurelien 343
			}
344
			$nb_lignes++;
345
		}
346
		return $workbook;
347
	}
3131 delphine 348
 
1662 aurelien 349
	private function convertirEnPdf(&$observations) {
1715 raphael 350
		if(count($observations) > 300) die('erreur: trop de données');
1662 aurelien 351
		//require_once('GenerateurPDF.php');
352
		$pdf = new GenerateurPDF();
353
		$pdf->export($observations);
354
		return $pdf;
355
	}
3131 delphine 356
 
1692 raphael 357
	static function filtrerDonneesSensibles($ligne) {
1429 aurelien 358
		if(stripos($ligne['mots_cles_texte'], 'sensible') !== false) {
359
			$ligne['latitude'] = '';
360
			$ligne['longitude'] = '';
361
		}
362
		return $ligne;
363
	}
3131 delphine 364
 
1654 aurelien 365
	private function doitEtPeutExporterObsPrivees($criteres) {
2459 jpm 366
		return isset($criteres['ce_utilisateur']) &&
3131 delphine 367
		$this->peutExporterObsPrivees($criteres['ce_utilisateur']);
1654 aurelien 368
	}
3131 delphine 369
 
1654 aurelien 370
	private function peutExporterObsPrivees($id_utilisateur) {
2806 aurelien 371
		$gestion_utilisateur = new GestionUtilisateur($this->config);
1654 aurelien 372
		$utilisateur = $gestion_utilisateur->obtenirIdentiteConnectee();
1703 raphael 373
		return ! empty($utilisateur['id_utilisateur']) && $id_utilisateur == $utilisateur['id_utilisateur'];
1654 aurelien 374
	}
3131 delphine 375
 
3134 delphine 376
 
1374 aurelien 377
}
3139 killian 378
?>