New file |
0,0 → 1,374 |
<?php |
/** |
* Service fournissant des informations concernant le CEL au format RSS1, RSS2 ou ATOM. |
* Encodage en entrée : utf8 |
* Encodage en sortie : utf8 |
* Format du service : |
* /CelWidgetExport/format |
* /CelWidgetExport/csv |
* |
* Les paramêtres : |
* - "start" indique le numéro du premier item à afficher |
* - "limit" nombre d'items à afficher |
* |
* @author Aurélien Peronnet <aurelien@tela-botanica.org> |
* @license GPL v3 <http://www.gnu.org/licenses/gpl.txt> |
* @license CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt> |
* @version $Id$ |
* @copyright 2012 |
*/ |
|
set_include_path(get_include_path() . PATH_SEPARATOR . dirname(dirname(realpath(__FILE__))) . '/lib'); |
// la sortie est binaire (xls), mais OLE n'est pas compatible E_ALL en PHP-5.4 |
error_reporting(error_reporting() & ~E_STRICT); |
require_once("lib/OLE.php"); |
require_once("lib/Spreadsheet/Excel/Writer.php"); |
|
class CelWidgetExport extends Cel { |
|
private $nom_fichier_export = 'cel_export'; |
// certains paramètres apparaissent plusieurs fois car ils ont des alias |
// dans certains widgets |
private $parametres_autorises = array( |
'id_utilisateur' => 'ce_utilisateur', |
'utilisateur' => 'courriel_utilisateur', |
'courriel_utilisateur' => 'courriel_utilisateur', |
'commune' => 'zone_geo', |
'zone_geo' => 'zone_geo', |
'dept' => 'departement', |
'departement' => 'departement', |
'lieudit' => 'lieudit', |
'station' => 'station', |
'projet' => 'mots_cles', |
'num_taxon' => 'nt', |
'date_debut' => 'date_debut', |
'date_fin' => 'date_fin', |
'taxon' => 'taxon', |
'annee' => 'annee', |
'mois' => 'mois', |
'jour' => 'jour', |
'recherche' => 'recherche', |
'id_mots_cles' => 'id_mots_cles', |
'mots_cles' => 'mots_cles', |
'debut' => 'debut', |
'limite' => 'limite', |
'format' => 'format', |
'colonnes' => 'colonnes', |
'transmission' => 'transmission', |
'obsids' => 'obsids', |
); |
|
private $limite_decoupage_defaut = 9000; |
|
private $format = 'csv'; |
|
public $id_utilisateur = null; |
|
// un cache, initialisé par certaines fonctions de préchargement, à la manière |
// de ce qui est fait par FormateurGroupeColonne |
static $cache = Array(); |
|
public function getRessource() { |
return $this->getElement(array()); |
} |
|
/** |
* Méthode appelée avec une requête de type GET. |
*/ |
public function getElement($params = array()) { |
switch(@strtolower($params[0])) { |
case 'calcul': |
$this->getCalcul(); |
break; |
|
case 'export': |
$this->getExport(); |
break; |
default: |
$this->getExport(); |
} |
} |
|
private function getCalcul() { |
$criteres = $this->traiterParametresAutorises($_GET); |
|
$criteres['transmission'] = 1; |
if($this->doitEtPeutExporterObsPrivees($criteres)) { |
unset($criteres['transmission']); |
$this->id_utilisateur = $criteres['id_utilisateur']; |
} |
$chercheur_observations = new RechercheObservation($this->config); |
|
$numero_page = isset($criteres['debut']) ? $criteres['debut'] : 0; |
$limite = isset($criteres['limite']) ? $criteres['limite'] : 0; |
$colonnes = @FormateurGroupeColonne::colGroupsValidation($criteres['colonnes']); |
|
unset($criteres['limite']); |
unset($criteres['debut']); |
unset($criteres['format']); |
unset($criteres['colonnes']); |
|
$nb_observations = $chercheur_observations->compterObservations(null, $criteres); |
$limite_decoupage = $this->calculerNbLignesMaxParFichier(explode(',', $colonnes)); |
|
$url_telechargements = array(); |
$intervalle = 0; |
|
$params_url = $criteres; |
unset($params_url['transmission']); |
do { |
$base_url = $this->config['settings']['baseURLAbsolu'].'CelWidgetExport/export'; |
$params_url['debut'] = $intervalle; |
$params_url['limite'] = $limite_decoupage; |
$url_telechargement_fichier = $base_url; |
$url_telechargements[] = $base_url.'?'.http_build_query($params_url).'&format='.$this->format.'&colonnes='.$colonnes; |
$intervalle += $limite_decoupage; |
$nb_observations -= $limite_decoupage; |
} while($nb_observations > 0); |
|
$this->envoyerJson($url_telechargements); |
} |
|
private function calculerNbLignesMaxParFichier($colonnes) { |
$limite = $this->limite_decoupage_defaut; |
|
switch($this->format) { |
case 'csv': |
$limite = 20000; |
break; |
case 'xls': |
$limite = 8000; |
break; |
case 'pdf': |
$limite = 300; |
break; |
} |
|
return $limite; |
} |
|
private function getExport() { |
$criteres = $this->traiterParametresAutorises($_GET); |
// ne pas faire de super-requête en cas d'absence de paramètres |
// par exemple "format", au minimum, devrait être défini |
if(!$criteres) die('erreur: pas de paramètre reçu'); |
if(!in_array($this->format, array('pdf','csv','xls'))) die('erreur: format invalide'); |
|
$criteres['transmission'] = 1; |
if($this->doitEtPeutExporterObsPrivees($criteres)) { |
unset($criteres['transmission']); |
$this->id_utilisateur = $criteres['ce_utilisateur']; |
} |
$chercheur_observations = new RechercheObservation($this->config); |
|
$debut = isset($criteres['debut']) ? intval($criteres['debut']) : 0; |
$limite = isset($criteres['limite']) ? intval($criteres['limite']) : 0; |
$groupes = @FormateurGroupeColonne::colGroupsValidation($criteres['colonnes']); |
$groupes .= ',auteur'; |
|
if(!$groupes) die('erreur: Ne peut identifier les groupes de champs demandés.'); |
|
|
if($criteres['obsids']) $criteres['sql_brut'] = sprintf('id_observation IN (%s)', |
implode(',', $criteres['obsids'])); |
|
unset($criteres['limite']); |
unset($criteres['debut']); |
unset($criteres['format']); |
unset($criteres['colonnes']); |
unset($criteres['obsids']); |
|
$observations = $chercheur_observations->rechercherObservations(null, $criteres, $debut, $limite, TRUE)->get(); |
$ids = array(); |
foreach($observations as &$obs) { |
$ids[] = $obs['id_observation']; |
} |
|
if($this->format == 'pdf') { |
$pdf = $this->convertirEnPdf($observations); |
$pdf->pdf->Output('etiquettes.pdf', 'I'); |
exit; |
} |
|
// cas XLS et CSV: on peut avoir besoin des champs étendus, des noms communs et des champs baseflor: |
|
// Obtention des colonnes correspondantes aux groupes de champs |
$colonnes = FormateurGroupeColonne::nomEnsembleVersListeColonnes($groupes); |
|
/* |
Champs étendus et noms communs, si demandés. |
* Pour "nom commun", "preload" retourne NULL, car c'est le cache statique de FormateurGroupeColonne |
qu'il initialise et utilise en interne sans qu'un passage par paramètre dans le contexte de CelWidgetExport |
ne soit nécessaire. |
* Pour les champs étendus, c'est CelWidgetExport::$cache qui est utilisé, aussi bien pour les en-têtes que |
pour les données préchargées, cf self::traiterLigneEtendue() |
*/ |
self::$cache = FormateurGroupeColonne::preload($colonnes, $this, $ids); |
|
// TODO: tous les champs étendus et les paramètres supplémentaires devraient être passés en un seul |
// tableau (et chaque formateur csv, xls etc... pourrait également être dans une classe à part) |
switch($this->format) { |
case 'csv': |
$csv = $this->convertirEnCsv($observations, $colonnes); |
$this->envoyerCsv($csv); |
break; |
case 'xls': |
$xls = $this->convertirEnXls($observations, $colonnes); |
$this->envoyerXls($xls); |
break; |
default: |
} |
} |
|
protected function traiterParametresAutorises(Array $parametres) { |
$parametres_traites = array(); |
$this->format = (isset($parametres['format']) && $parametres['format'] != '') ? $parametres['format'] : $this->format; |
foreach($parametres as $cle => $valeur) { |
if(is_string($valeur) && !trim($valeur)) continue; |
if(isset($this->parametres_autorises[$cle])) { |
$parametres_traites[$this->parametres_autorises[$cle]] = $valeur; |
} |
} |
$parametres_traites['obsids'] = @self::traiterObsIds($parametres['obsids']); |
return $parametres_traites; |
} |
|
private function envoyerCsv($csv) { |
header('Content-Type: text/csv; charset=UTF-8'); |
header('Content-Disposition: attachment;filename='.$this->nom_fichier_export.'.csv'); |
echo $csv; |
exit; |
} |
|
private function envoyerXls($workbook) { |
$workbook->close(); |
exit; |
} |
|
private function convertirEnCsv(&$data, $colonnes) { |
$chemin_temp = "php://temp"; |
$outstream = fopen($chemin_temp, 'r+'); |
|
$intitule_champs = array_merge(FormateurGroupeColonne::getIntitulesColonnes($colonnes)); |
// en premier car utilisé génériquement dans getLigneObservation() |
if(isset($colonnes['baseflor'])) { |
$intitule_champs = array_merge($intitule_champs, FormateurGroupeColonne::$baseflor_col); |
} |
// en second car manuellement appellé plus bas, TODO: utiliser l'API du FormateurGroupeColonne |
if(isset($colonnes['etendu'])) { |
$intitule_champs = array_merge($intitule_champs, array_values(self::$cache['etendu']['header'])); |
} |
|
// header |
fputcsv($outstream, $intitule_champs, ',', '"'); |
// lignes |
foreach($data as &$ligne) { |
$ligne = self::filtrerDonneesSensibles($ligne); |
$ligne = FormateurGroupeColonne::getLigneObservation($ligne, $colonnes, $this); |
fputcsv($outstream, $ligne, ',', '"'); |
} |
rewind($outstream); |
$csv = stream_get_contents($outstream); |
fclose($outstream); |
return $csv; |
} |
|
private function convertirEnXls(&$data, $colonnes) { |
$this->extendSpreadsheetProductor = new SpreadsheetProductor(); |
$this->extendSpreadsheetProductor->initSpreadsheet(); |
|
$workbook = new Spreadsheet_Excel_Writer(); |
// avant la définition du titre de la worksheet ! |
$workbook->setVersion(8); |
|
$worksheet = $workbook->addWorksheet('Liste'); |
$workbook->setTempDir($this->config['cel']['chemin_stockage_temp']); |
$worksheet->setInputEncoding('utf-8'); |
$workbook->send($this->nom_fichier_export.'.xls'); |
|
$nb_lignes = 1; |
|
$intitule_champs = array_merge(FormateurGroupeColonne::getIntitulesColonnes($colonnes)); |
// en premier car utilisé génériquement dans getLigneObservation() |
if(isset($colonnes['baseflor'])) { |
$intitule_champs = array_merge($intitule_champs, FormateurGroupeColonne::$baseflor_col); |
} |
// en second car manuellement appellé plus bas, TODO: utiliser l'API du FormateurGroupeColonne |
if(isset($colonnes['etendu'])) { |
$intitule_champs = array_merge($intitule_champs, array_values(self::$cache['etendu']['header'])); |
} |
|
// header |
$indice = 0; |
foreach ($intitule_champs as &$intitule) { |
$worksheet->write(0,$indice++,$intitule); |
} |
|
foreach($data as &$ligne) { |
$ligne = self::filtrerDonneesSensibles($ligne); |
$ligne = FormateurGroupeColonne::getLigneObservation($ligne, $colonnes, $this); |
$indice = 0; |
foreach($ligne as &$champ) { |
$worksheet->write($nb_lignes,$indice++,$champ); |
} |
$nb_lignes++; |
} |
return $workbook; |
} |
|
private function convertirEnPdf(&$observations) { |
if(count($observations) > 300) die('erreur: trop de données'); |
//require_once('GenerateurPDF.php'); |
$pdf = new GenerateurPDF(); |
$pdf->export($observations); |
return $pdf; |
} |
|
static function filtrerDonneesSensibles($ligne) { |
if(stripos($ligne['mots_cles_texte'], 'sensible') !== false) { |
$ligne['latitude'] = ''; |
$ligne['longitude'] = ''; |
} |
return $ligne; |
} |
|
private function doitEtPeutExporterObsPrivees($criteres) { |
return isset($criteres['ce_utilisateur']) && |
$this->peutExporterObsPrivees($criteres['ce_utilisateur']); |
} |
|
private function peutExporterObsPrivees($id_utilisateur) { |
$gestion_utilisateur = new User($this->config); |
$utilisateur = $gestion_utilisateur->obtenirIdentiteConnectee(); |
return ! empty($utilisateur['id_utilisateur']) && $id_utilisateur == $utilisateur['id_utilisateur']; |
} |
|
static function traiterObsIds($range_param) { |
if (!isset($range_param)) return NULL; |
// trim() car: `POST http://url<<<"range=*"` |
if (trim($range_param) == '*') return NULL; |
return self::rangeToList(trim($range_param)); |
} |
|
/* |
* @param $fieldSets: un range, eg: 1-5,8,32,58-101 |
* @return un tableau trié, eg: 1,2,3,4,5,8,32,58,...,101 |
* http://stackoverflow.com/questions/7698664/converting-a-range-or-partial-array-in-the-form-3-6-or-3-6-12-into-an-arra |
*/ |
static function rangeToList($in = '') { |
$inSets = explode(',', trim($in, ',')); |
$outSets = array(); |
|
foreach($inSets as $inSet) { |
list($start,$end) = explode('-', $inSet . '-' . $inSet); |
// ignore les ranges trop importants |
if($start > 10000000 || $end > 10000000 || abs($start-$end) > 10000) continue; |
$outSets = array_merge($outSets,range($start,$end)); |
} |
$outSets = array_unique($outSets); |
$outSets = array_filter($outSets, 'is_numeric'); |
sort($outSets); |
return $outSets; |
} |
} |
?> |