1630 |
raphael |
1 |
<?php
|
2458 |
jpm |
2 |
// declare(encoding='UTF-8');
|
1630 |
raphael |
3 |
/**
|
2458 |
jpm |
4 |
* Service d'export de données d'observation du CEL au format XLS.
|
1630 |
raphael |
5 |
*
|
|
|
6 |
* Format du service :
|
|
|
7 |
* POST /ExportXLS
|
|
|
8 |
* POST /ExportXLS/<Utilisateur>
|
|
|
9 |
* TODO: GET /ExportXLS/<Utilisateur> [ sans "range" ? ]
|
|
|
10 |
*
|
|
|
11 |
* Les données POST acceptées sont:
|
|
|
12 |
* range (obligatoire): un range d'id_observation sous la forme d'entier ou d'intervalles d'entiers
|
2458 |
jpm |
13 |
* séparés par des virgules ou bien '*' (pour toutes)
|
1630 |
raphael |
14 |
* TODO: limit
|
|
|
15 |
* TODO: départ
|
|
|
16 |
* TODO: sets (ou colonnes, ou extended)
|
|
|
17 |
* TODO: + les critères supportés par fabriquerSousRequeteRecherche()
|
|
|
18 |
*
|
|
|
19 |
* Si <Utilisateur> est fourni, celui-ci doit être authentifié
|
|
|
20 |
* TODO: export des données public et non-sensible d'un utilisateur
|
|
|
21 |
*
|
|
|
22 |
* Si <Utilisateur> est fourni, le observations seront le résultat de l'intersection des 2 contraintes
|
|
|
23 |
*
|
2458 |
jpm |
24 |
* @internal Mininum PHP version : 5.2
|
|
|
25 |
* @category CEL
|
|
|
26 |
* @package Services
|
|
|
27 |
* @subpackage Observations
|
|
|
28 |
* @version 0.1
|
|
|
29 |
* @author Mathias CHOUET <mathias@tela-botanica.org>
|
|
|
30 |
* @author Raphaël Droz <raphael@tela-botania.org>
|
|
|
31 |
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
|
|
|
32 |
* @author Aurelien PERONNET <aurelien@tela-botanica.org>
|
|
|
33 |
* @license GPL v3 <http://www.gnu.org/licenses/gpl.txt>
|
|
|
34 |
* @license CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt>
|
|
|
35 |
* @copyright 1999-2014 Tela Botanica <accueil@tela-botanica.org>
|
1630 |
raphael |
36 |
*/
|
|
|
37 |
set_include_path(get_include_path() . PATH_SEPARATOR . dirname(dirname(realpath(__FILE__))) . '/lib');
|
1634 |
raphael |
38 |
ini_set('html_errors', 0);
|
|
|
39 |
ini_set('xdebug.cli_color', 2);
|
2458 |
jpm |
40 |
require_once 'lib/PHPExcel/Classes/PHPExcel.php';
|
|
|
41 |
require_once 'lib/FormateurGroupeColonne.php';
|
1630 |
raphael |
42 |
|
|
|
43 |
class ExportXLS extends Cel {
|
|
|
44 |
|
1639 |
raphael |
45 |
private $id_utilisateur = NULL;
|
2458 |
jpm |
46 |
private $parametres_defaut = array('range' => '*', 'format' => 'CSV');
|
|
|
47 |
|
1645 |
aurelien |
48 |
private $filtres_autorises = array(
|
2458 |
jpm |
49 |
'id_utilisateur' => 'id_utilisateur',
|
|
|
50 |
'utilisateur' => 'courriel_utilisateur',
|
|
|
51 |
'commune' => 'zone_geo',
|
|
|
52 |
'dept' => 'departement',
|
|
|
53 |
'projet' => 'mots_cles',
|
|
|
54 |
'num_taxon' => 'nt',
|
|
|
55 |
'date_debut' => 'date_debut',
|
|
|
56 |
'date_fin' => 'date_fin',
|
|
|
57 |
'taxon' => 'taxon'
|
1645 |
aurelien |
58 |
);
|
1633 |
raphael |
59 |
|
2458 |
jpm |
60 |
public function __construct($config) {
|
1630 |
raphael |
61 |
parent::__construct($config);
|
|
|
62 |
}
|
2458 |
jpm |
63 |
|
|
|
64 |
public function getRessource() {
|
1644 |
aurelien |
65 |
return $this->getElement(array());
|
|
|
66 |
}
|
2458 |
jpm |
67 |
|
|
|
68 |
public function getElement($uid) {
|
|
|
69 |
$parametres_format = $this->traiterParametresFormat($uid, $_GET);
|
1644 |
aurelien |
70 |
$filtres = $this->traiterFiltres($_GET);
|
|
|
71 |
$this->export($parametres_format, $filtres);
|
2458 |
jpm |
72 |
exit();
|
1644 |
aurelien |
73 |
}
|
2458 |
jpm |
74 |
|
|
|
75 |
private function traiterParametresFormat($uid, $params) {
|
1644 |
aurelien |
76 |
$parametres = $this->parametres_defaut;
|
2458 |
jpm |
77 |
if (isset($params['format'])) {
|
1644 |
aurelien |
78 |
if($params['format'] == 'csv') $parametres['format'] = 'CSV';
|
|
|
79 |
if($params['format'] == 'xls') $parametres['format'] = 'Excel5';
|
|
|
80 |
if($params['format'] == 'xlsx') $parametres['format'] = 'Excel2007';
|
1658 |
raphael |
81 |
if($params['format'] == 'pdf') $parametres['format'] = 'pdf';
|
1630 |
raphael |
82 |
}
|
1644 |
aurelien |
83 |
// TODO: $params['part'] pour le multi-part
|
2458 |
jpm |
84 |
$parametres['widget'] = isset($params['widget']) ? $params['widget'] : 'CEL';
|
1644 |
aurelien |
85 |
$parametres['debut'] = isset($params['debut']) ? intval($params['debut']) : 0;
|
|
|
86 |
$parametres['limite'] = isset($params['limite']) ? intval($params['limite']) : 0;
|
|
|
87 |
$parametres['id_utilisateur'] = $this->traiterIdUtilisateur($uid);
|
1755 |
raphael |
88 |
$parametres['groupe_champs'] = isset($params['colonnes']) ? $params['colonnes'] : 'standard,avance';
|
2458 |
jpm |
89 |
|
1644 |
aurelien |
90 |
return $parametres;
|
|
|
91 |
}
|
2458 |
jpm |
92 |
|
|
|
93 |
private function traiterIdUtilisateur($uid) {
|
1644 |
aurelien |
94 |
$id_utilisateur = null;
|
|
|
95 |
// TODO: controleUtilisateur()
|
2458 |
jpm |
96 |
if (isset($uid[0])) {
|
1644 |
aurelien |
97 |
$id_utilisateur = intval($uid[0]);
|
1630 |
raphael |
98 |
}
|
1644 |
aurelien |
99 |
return $id_utilisateur;
|
|
|
100 |
}
|
2458 |
jpm |
101 |
|
|
|
102 |
private function traiterFiltres($params) {
|
1644 |
aurelien |
103 |
$obs_ids = $this->traiterObsIds($params);
|
|
|
104 |
$filtres = array();
|
2458 |
jpm |
105 |
if (!$obs_ids || count($obs_ids) == 1 && $obs_ids[0] == '*') {
|
1644 |
aurelien |
106 |
unset($filtres['sql_brut']);
|
2458 |
jpm |
107 |
} else {
|
1644 |
aurelien |
108 |
$filtres = Array('sql_brut' =>
|
|
|
109 |
sprintf('id_observation IN (%s)', implode(',', $obs_ids)));
|
1630 |
raphael |
110 |
}
|
2458 |
jpm |
111 |
foreach ($params as $cle => $valeur) {
|
|
|
112 |
if (trim($valeur) != '' && isset($this->filtres_autorises[$cle])) {
|
1645 |
aurelien |
113 |
$filtres[$this->filtres_autorises[$cle]] = $valeur;
|
|
|
114 |
}
|
|
|
115 |
}
|
1644 |
aurelien |
116 |
return $filtres;
|
1630 |
raphael |
117 |
}
|
2458 |
jpm |
118 |
|
|
|
119 |
private function traiterObsIds($params) {
|
1644 |
aurelien |
120 |
$obs_ids = Array('*');
|
|
|
121 |
if (isset($params['range']) && trim($params['range']) != '*') {
|
|
|
122 |
// trim() car: `POST http://url<<<"range=*"`
|
|
|
123 |
$obs_ids = self::rangeToList(trim($params['range']));
|
|
|
124 |
}
|
|
|
125 |
return $obs_ids;
|
|
|
126 |
}
|
1630 |
raphael |
127 |
|
|
|
128 |
/*
|
|
|
129 |
* $param: Tableau associatif, indexes supportés:
|
2458 |
jpm |
130 |
* - widget: le nom du widget d'origine (utilisé pour les méta-données du tableur)
|
1630 |
raphael |
131 |
*
|
|
|
132 |
*/
|
2458 |
jpm |
133 |
private function export(Array $parametres_format = Array(),Array $filtres = array()) {
|
1630 |
raphael |
134 |
$chercheur_observations = new RechercheObservation($this->config);
|
|
|
135 |
|
1632 |
raphael |
136 |
$observations = $chercheur_observations
|
1644 |
aurelien |
137 |
->rechercherObservations($parametres_format['id_utilisateur'], $filtres, $parametres_format['debut'], $parametres_format['limite'], TRUE)
|
1632 |
raphael |
138 |
->get();
|
|
|
139 |
// debug //echo ($chercheur_observations->requete_selection_observations);
|
1630 |
raphael |
140 |
// XXX: malheureusement l'instance de JRest n'est pas accessible ici
|
2458 |
jpm |
141 |
if (!$observations) {
|
1630 |
raphael |
142 |
header('HTTP/1.0 204 No Content');
|
2458 |
jpm |
143 |
exit();
|
1630 |
raphael |
144 |
}
|
1656 |
raphael |
145 |
|
2458 |
jpm |
146 |
if ($parametres_format['format'] == 'pdf') {
|
|
|
147 |
if (count($observations) > 300) {
|
|
|
148 |
die('too much');
|
|
|
149 |
}
|
1658 |
raphael |
150 |
require_once('GenerateurPDF.php');
|
|
|
151 |
|
|
|
152 |
$pdf = new GenerateurPDF();
|
|
|
153 |
$pdf->export($observations);
|
|
|
154 |
//$pdf->export1($observations);
|
|
|
155 |
//$pdf->export2($observations);
|
|
|
156 |
$pdf->pdf->Output('etiquettes.pdf', 'I');
|
2458 |
jpm |
157 |
die();
|
1658 |
raphael |
158 |
}
|
|
|
159 |
|
1656 |
raphael |
160 |
$colonnes = FormateurGroupeColonne::nomEnsembleVersListeColonnes($parametres_format['groupe_champs']);
|
1644 |
aurelien |
161 |
// $colonne_abbrev = array_keys($colonnes);
|
|
|
162 |
$objPHPExcel = $this->gerenerFeuilleImportFormatee($parametres_format);
|
|
|
163 |
$feuille = $objPHPExcel->setActiveSheetIndex(0);
|
|
|
164 |
// attention formaterColonnesFeuille prend ses 2 premiers paramètres par référence
|
|
|
165 |
$this->formaterColonnesFeuille($feuille, $colonnes, $parametres_format);
|
|
|
166 |
$objPHPExcel->getActiveSheet()->getDefaultColumnDimension()->setWidth(12);
|
1630 |
raphael |
167 |
|
1644 |
aurelien |
168 |
$no_ligne = 2;
|
|
|
169 |
foreach ($observations as $obs) {
|
|
|
170 |
// attention traiterLigneObservation prend ses 3 premiers paramètres par référence
|
|
|
171 |
$this->traiterLigneObservation($obs, $colonnes, $feuille, $no_ligne);
|
|
|
172 |
$no_ligne++;
|
|
|
173 |
}
|
1630 |
raphael |
174 |
|
1644 |
aurelien |
175 |
$this->envoyerFeuille($objPHPExcel, $parametres_format);
|
|
|
176 |
}
|
2458 |
jpm |
177 |
|
1644 |
aurelien |
178 |
private function envoyerFeuille($objPHPExcel, $parametres_format) {
|
2458 |
jpm |
179 |
header('Content-Type: application/vnd.ms-excel');
|
|
|
180 |
header('Content-Disposition: attachment; filename="liste.xls"; charset=utf-8');
|
|
|
181 |
header('Cache-Control: max-age=0');
|
|
|
182 |
|
1644 |
aurelien |
183 |
// csv|xls|xlsx => CSV|Excel5|Excel2007
|
|
|
184 |
// Note: le format Excel2007 utilise un fichier temporaire
|
|
|
185 |
$generateur = PHPExcel_IOFactory::createWriter($objPHPExcel, $parametres_format['format']);
|
|
|
186 |
$generateur->save('php://output');
|
|
|
187 |
exit;
|
|
|
188 |
}
|
2458 |
jpm |
189 |
|
|
|
190 |
private function traiterLigneObservation(&$obs, &$colonnes, &$feuille, $no_ligne) {
|
1644 |
aurelien |
191 |
$no_colonne = 0;
|
2458 |
jpm |
192 |
foreach ($colonnes as $abbrev => $colonne) {
|
1644 |
aurelien |
193 |
$valeur = null;
|
2458 |
jpm |
194 |
if ($colonne['extra'] == 2 || ! is_null($colonne['dyna'])) {
|
|
|
195 |
continue;
|
|
|
196 |
}
|
|
|
197 |
|
1644 |
aurelien |
198 |
// valeur direct depuis cel_obs ?
|
2458 |
jpm |
199 |
if (isset($obs[$abbrev])) {
|
|
|
200 |
$valeur = $obs[$abbrev];
|
|
|
201 |
}
|
1685 |
raphael |
202 |
|
1644 |
aurelien |
203 |
// pré-processeur de la champs
|
2458 |
jpm |
204 |
if (function_exists($colonne['fonction'])) {
|
1644 |
aurelien |
205 |
$valeur = $colonne['fonction']($valeur);
|
2458 |
jpm |
206 |
} else if (method_exists('FormateurGroupeColonne', $colonne['fonction'])) {
|
1656 |
raphael |
207 |
$valeur = call_user_func(array('FormateurGroupeColonne', $colonne['fonction']), $valeur);
|
2458 |
jpm |
208 |
} else if (method_exists(__CLASS__, $colonne['fonction'])) {
|
1644 |
aurelien |
209 |
$valeur = call_user_func(array(__CLASS__, $colonne['fonction']), $valeur);
|
2458 |
jpm |
210 |
} else if ($colonne['fonction']) {
|
1644 |
aurelien |
211 |
die("méthode {$colonne['fonction']} introuvable");
|
2458 |
jpm |
212 |
} else if (function_exists($colonne['fonction_data'])) { // fonction pour obtenir des champs (étendus)
|
1644 |
aurelien |
213 |
$valeur = $colonne['fonction_data']($obs);
|
2458 |
jpm |
214 |
} else if (method_exists(__CLASS__, $colonne['fonction_data'])) {
|
1644 |
aurelien |
215 |
$valeur = call_user_func(array(__CLASS__, $colonne['fonction_data']), $obs);
|
|
|
216 |
}
|
2458 |
jpm |
217 |
|
1644 |
aurelien |
218 |
// // cette section devrait être vide:
|
|
|
219 |
// // cas particuliers ingérable avec l'architecture actuelle:
|
2458 |
jpm |
220 |
if (false && $abbrev == 'date_observation' && $valeur == "0000-00-00") {
|
|
|
221 |
/* blah */
|
1644 |
aurelien |
222 |
}
|
2458 |
jpm |
223 |
if ($abbrev == 'images') {
|
1656 |
raphael |
224 |
$valeur = FormateurGroupeColonne::getImages($obs, $this->id_utilisateur, $this);
|
|
|
225 |
}
|
2458 |
jpm |
226 |
if ($abbrev == 'nom-commun') {
|
1685 |
raphael |
227 |
$valeur = FormateurGroupeColonne::getNomCommun_v4($obs, $this);
|
|
|
228 |
}
|
1656 |
raphael |
229 |
|
1644 |
aurelien |
230 |
// // fin de section "cas particuliers"
|
|
|
231 |
$feuille->setCellValueByColumnAndRow($no_colonne, $no_ligne, $valeur);
|
|
|
232 |
$no_colonne++;
|
|
|
233 |
}
|
|
|
234 |
}
|
2458 |
jpm |
235 |
|
1644 |
aurelien |
236 |
private function gerenerFeuilleImportFormatee($parametres_format) {
|
|
|
237 |
$objPHPExcel = new PHPExcel();
|
2458 |
jpm |
238 |
|
1644 |
aurelien |
239 |
$objPHPExcel->getProperties()->setCreator($parametres_format['widget']) // ou $uid ?
|
2458 |
jpm |
240 |
->setLastModifiedBy("XX") // TODO: $uid
|
|
|
241 |
->setTitle("Export des observation du carnet en ligne") // TODO
|
|
|
242 |
->setSubject("Export") // TODO
|
|
|
243 |
->setDescription("Export");
|
|
|
244 |
|
1630 |
raphael |
245 |
$objPHPExcel->getActiveSheet()->setTitle("Observations");
|
1644 |
aurelien |
246 |
return $objPHPExcel;
|
|
|
247 |
}
|
2458 |
jpm |
248 |
|
1644 |
aurelien |
249 |
private function formaterColonnesFeuille(&$feuille, &$colonnes, $parametres_format) {
|
1630 |
raphael |
250 |
$colid = 0;
|
2458 |
jpm |
251 |
foreach ($colonnes as $colonne) {
|
|
|
252 |
if ($colonne['extra'] == 2) {
|
|
|
253 |
continue;
|
|
|
254 |
}
|
|
|
255 |
|
1638 |
raphael |
256 |
$feuille->setCellValueByColumnAndRow($colid, 1, $colonne['nom']);
|
2458 |
jpm |
257 |
if ($colonne['extra'] == 1) {
|
1638 |
raphael |
258 |
$feuille->getStyleByColumnAndRow($colid, 1)->getBorders()->applyFromArray(
|
1630 |
raphael |
259 |
array(
|
|
|
260 |
'allborders' => array(
|
|
|
261 |
'style' => PHPExcel_Style_Border::BORDER_DASHDOT,
|
|
|
262 |
'color' => array('rgb' => PHPExcel_Style_Color::COLOR_BLUE)
|
|
|
263 |
)
|
|
|
264 |
)
|
|
|
265 |
);
|
|
|
266 |
}
|
2458 |
jpm |
267 |
if (! $colonne['importable']) {
|
1642 |
raphael |
268 |
$feuille->getStyleByColumnAndRow($colid, 1)->getFill()->applyFromArray(
|
|
|
269 |
array(
|
|
|
270 |
'type' => PHPExcel_Style_Fill::FILL_SOLID,
|
|
|
271 |
'color' => array('rgb' => PHPExcel_Style_Color::COLOR_YELLOW)
|
|
|
272 |
)
|
|
|
273 |
);
|
|
|
274 |
}
|
1630 |
raphael |
275 |
$colid++;
|
|
|
276 |
}
|
|
|
277 |
}
|
|
|
278 |
|
|
|
279 |
/*
|
|
|
280 |
* @param $fieldSets: un range, eg: 1-5,8,32,58-101
|
|
|
281 |
* @return un tableau trié, eg: 1,2,3,4,5,8,32,58,...,101
|
1638 |
raphael |
282 |
* http://stackoverflow.com/questions/7698664/converting-a-range-or-partial-array-in-the-form-3-6-or-3-6-12-into-an-arra
|
1630 |
raphael |
283 |
*/
|
|
|
284 |
static function rangeToList($in = '') {
|
|
|
285 |
$inSets = explode(',', $in);
|
|
|
286 |
$outSets = array();
|
1632 |
raphael |
287 |
|
2458 |
jpm |
288 |
foreach ($inSets as $inSet) {
|
1630 |
raphael |
289 |
list($start,$end) = explode('-', $inSet . '-' . $inSet);
|
1634 |
raphael |
290 |
// ignore les ranges trop importants
|
2458 |
jpm |
291 |
if ($start > 10000000 || $end > 10000000 || abs($start-$end) > 10000) {
|
|
|
292 |
continue;
|
|
|
293 |
}
|
1630 |
raphael |
294 |
$outSets = array_merge($outSets,range($start,$end));
|
|
|
295 |
}
|
|
|
296 |
$outSets = array_unique($outSets);
|
|
|
297 |
$outSets = array_filter($outSets, 'is_numeric');
|
|
|
298 |
sort($outSets);
|
|
|
299 |
return $outSets;
|
|
|
300 |
}
|
1656 |
raphael |
301 |
}
|