New file |
0,0 → 1,265 |
<?php |
|
/** |
* @category PHP |
* @package jrest |
* @author Raphaël Droz <raphael@tela-botania.org> |
* @copyright 2013 Tela-Botanica |
* @license http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL |
* @license GPL v3 <http://www.gnu.org/licenses/gpl.txt> |
*/ |
|
/** |
* Service d'export de données d'observation du CEL au format XLS |
* |
* Format du service : |
* POST /ExportXLS |
* POST /ExportXLS/<Utilisateur> |
* TODO: GET /ExportXLS/<Utilisateur> [ sans "range" ? ] |
* |
* Les données POST acceptées sont: |
* range (obligatoire): un range d'id_observation sous la forme d'entier ou d'intervalles d'entiers |
* séparés par des virgules ou bien '*' (pour toutes) |
* TODO: limit |
* TODO: départ |
* TODO: sets (ou colonnes, ou extended) |
* TODO: + les critères supportés par fabriquerSousRequeteRecherche() |
* |
* Si <Utilisateur> est fourni, celui-ci doit être authentifié |
* TODO: export des données public et non-sensible d'un utilisateur |
* |
* Si <Utilisateur> est fourni, le observations seront le résultat de l'intersection des 2 contraintes |
* |
*/ |
set_include_path(get_include_path() . PATH_SEPARATOR . dirname(dirname(realpath(__FILE__))) . '/lib'); |
require_once('lib/PHPExcel/Classes/PHPExcel.php'); |
|
class ExportXLS extends Cel { |
|
function ExportXLS($config) { |
parent::__construct($config); |
} |
|
/* |
* Process $_POST et $_GET |
* TODO: changer JRest pour pouvoir disposer d'un nom de méthode plus représentatif que "updateXXX" |
* en POST |
*/ |
function updateElement($uid, $pairs) { |
$params = Array('uid' => $uid); |
// TODO: pas de range mais un utilisateur: possible |
if(!isset($_POST['range'])) { |
header('HTTP/1.0 204 No Content'); |
exit; |
} |
elseif($_POST['range'] == '*') { |
$records = Array('*'); |
} |
else { |
$records = self::rangeToList($_POST['range']); |
} |
$this->export($records, NULL, $params); |
exit; |
} |
|
/* |
* $param: Tableau associatif, indexes supportés: |
* - widget: le nom du widget d'origine (utilisé pour les méta-données du tableur) |
* |
*/ |
function export(Array $records, String $fieldSets = NULL, Array $params = Array()) { |
$colonnes = self::fieldSetsToColumns($fieldSets); |
$columnSlugs = array_keys($colonnes); |
$chercheur_observations = new RechercheObservation($this->config); |
|
$objPHPExcel = new PHPExcel(); |
|
|
// TODO: $params['part'] pour le multi-part |
$params['widget'] = isset($params['widget']) ? $params['widget'] : 'CEL'; |
// TODO: controleUtilisateur() |
if( /* REMOVE*/ true || ! $params['uid'] || ! $this->controleUtilisateur($params['uid'])) { |
$params['uid'] = NULL; |
} |
|
$criteres = Array(); |
if(count($records) == 1 && $records[0] == '*') { |
unset($criteres['raw']); |
} |
else { |
$criteres = Array('raw' => |
sprintf('id_observation IN (%s)', implode(',', $records))); |
} |
|
$criteres['debut'] = isset($_GET['debut']) ? intval($_GET['debut']) : 0; |
$criteres['limite'] = isset($_GET['limite']) ? intval($_GET['limite']) : 0; |
$observations = $chercheur_observations->rechercherObservations($params['uid'], |
$criteres, |
$criteres['debut'], |
$criteres['limite']); |
|
// XXX: malheureusement l'instance de JRest n'est pas accessible ici |
if(!$observations) { |
header('HTTP/1.0 204 No Content'); |
exit; |
} |
|
$objPHPExcel->getProperties()->setCreator($params['widget']) // ou $uid ? |
->setLastModifiedBy("XX") // TODO: $uid |
->setTitle("YY") // TODO |
->setSubject("ZZ") // TODO |
->setDescription("Export blah"); |
//->setKeywords("office PHPExcel php") |
//->setCategory("Test result file") |
|
$objPHPExcel->getActiveSheet()->setTitle("Observations"); |
$sheet = $objPHPExcel->setActiveSheetIndex(0); |
$colid = 0; |
foreach($colonnes as $colonne) { |
$sheet->setCellValueByColumnAndRow($colid, 1, $colonne['nom']); |
if($colonne['extra']) { |
$sheet->getStyleByColumnAndRow($colid, 1)->getBorders()->applyFromArray( |
array( |
'allborders' => array( |
'style' => PHPExcel_Style_Border::BORDER_DASHDOT, |
'color' => array('rgb' => PHPExcel_Style_Color::COLOR_BLUE) |
) |
) |
); |
} |
$colid++; |
} |
|
$objPHPExcel->getActiveSheet()->getDefaultColumnDimension()->setWidth(12); |
|
$row = 2; |
foreach ($observations as $obs) { |
$colid = 0; |
foreach($colonnes as $slug => $colonne) { |
$valeur = $obs[$slug]; |
|
// pré-processeur des champs |
if(function_exists($colonne['function'])) |
$valeur = $colonne['function']($valeur); |
elseif(method_exists(__CLASS__, $colonne['function'])) |
$valeur = call_user_func(array(__CLASS__, $colonne['function']), $valeur); |
elseif($colonne['function']) { |
die("méthode {$colonne['function']} introuvable"); |
} |
|
// // cette section devrait être vide: |
// // cas particuliers ingérable avec l'architecture actuelle: |
if(false && $slug == 'date_observation' && $valeur == "0000-00-00") { /* blah */ } |
// // fin de section "cas particuliers" |
|
$sheet->setCellValueByColumnAndRow($colid, $row, $valeur); |
$colid++; |
} |
$row++; |
} |
|
header("Content-Type: application/vnd.ms-excel"); |
header("Content-Disposition: attachment; filename=\"liste.xls\"; charset=utf-8"); |
header("Cache-Control: max-age=0"); |
// Le format Excel2007 utilise un fichier temporaire |
$objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007'); |
// $objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel5'); |
$objWriter->save('php://output'); |
exit; |
} |
|
/* |
* @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 |
*/ |
static function rangeToList($in = '') { |
$inSets = explode(',', $in); |
$outSets = array(); |
foreach($inSets as $inSet) { |
list($start,$end) = explode('-', $inSet . '-' . $inSet); |
$outSets = array_merge($outSets,range($start,$end)); |
} |
$outSets = array_unique($outSets); |
$outSets = array_filter($outSets, 'is_numeric'); |
sort($outSets); |
return $outSets; |
} |
|
/* |
* @param $fieldSets: un liste de noms de colonnes ou de sets de colonnes |
* séparés par des virgules |
* eg: "espece" ou "champs-etendus", ... |
* |
* @return: un tableau associatif déjà ordonné |
* clé: slug [machine-name] de la colonne (eg: "espece" ou "mot-clef") |
* valeur: des données relative à cette colonne, cf GenColInfo |
* |
* @TODO: fonction commune à la génération en CSV |
*/ |
static function fieldSetsToColumns($fieldSets = 'standard') { |
if(! $fieldSets) $fieldSets = 'standard'; |
$fieldSets = array_flip(explode(',', $fieldSets)); |
$colonnes = Array(); |
|
if(isset($fieldSets['standard'])) { |
$colonnes += Array( |
'nom_sel' => self::GenColInfo('nom_sel', 'Espèce'), |
'nom_sel_nn' => self::GenColInfo('nom_sel_nn', 'Numero nomenclatural'), |
'nom_ret' => self::GenColInfo('nom_ret', 'Nom retenu'), |
'nom_ret_nn' => self::GenColInfo('nom_ret_nn', 'Numero nomenclatural nom retenu'), |
'nt' => self::GenColInfo('nt', 'Numero taxonomique'), |
'famille' => self::GenColInfo('famille', 'Famille'), |
'nom_referentiel' => self::GenColInfo('nom_referentiel', 'Referentiel taxonomique'), |
'zone_geo' => self::GenColInfo('zone_geo', 'Commune'), |
'ce_zone_geo' => self::GenColInfo('ce_zone_geo', 'Identifiant Commune', 0, 'convertirCodeZoneGeoVersDepartement'), |
'date_observation' => self::GenColInfo('date_observation', 'Date', 0, 'formaterDate'), |
'lieudit' => self::GenColInfo('lieudit', 'Lieu-dit'), |
'station' => self::GenColInfo('station', 'Station'), |
'milieu' => self::GenColInfo('milieu', 'Milieu'), |
'commentaire' => self::GenColInfo('commentaire', 'Notes'), |
'latitude' => self::GenColInfo('latitude', 'Latitude', 1), |
'longitude' => self::GenColInfo('longitude', 'Longitude', 1), |
'geodatum' => self::GenColInfo('geodatum', 'Referentiel Geographique', 1), |
|
'ordre' => self::GenColInfo('ordre', 'Ordre', 1), |
'id_observation' => self::GenColInfo('id_observation', 'Identifiant', 1), |
|
'mots_cles_texte' => self::GenColInfo('mots_cles_texte', 'Mots Clés', 1), |
'commentaire' => self::GenColInfo('commentaire', 'Commentaires', 1), |
'date_creation' => self::GenColInfo('date_creation', 'Date Création', 1), |
'date_modification' => self::GenColInfo('date_modification', 'Date Modification', 1), |
'date_transmission' => self::GenColInfo('date_transmission', 'Date Transmission', 1), |
'abondance' => self::GenColInfo('abondance', 'Abondance', 1), |
'certitude' => self::GenColInfo('certitude', 'Certitude', 1), |
'phenologie' => self::GenColInfo('phenologie', 'Phénologie', 1), |
|
); |
} |
|
return $colonnes; |
} |
|
/* |
* Wrapper générant un tableau associatif: |
* @param $is_extra: défini si la colonne est extra (auquelle une bordure bleue entoure son nom dans la première ligne |
* @param $function: un nom optionnel d'un fonction de préprocessing |
* $function doit prendre comme argument la valeur et retourner la valeur transformée |
*/ |
static function GenColInfo($slug, $nom, $is_extra = 0, $function = NULL) { |
return Array('slug' => $slug, |
'nom' => $nom, |
'extra' => $is_extra ? 1 : 0, |
'function' => $function |
); |
} |
|
protected function formaterDate($date_heure_mysql, $format = NULL) { |
if (!$date_heure_mysql || $date_heure_mysql == "0000-00-00 00:00:00") return "00/00/0000"; |
$timestamp = DateTime::createFromFormat("Y-m-d H:i:s", $date_heure_mysql); |
if(!$timestamp) return "00/00/0000"; |
// TODO: les widget ne font malheureusement pas usage de l'heure dans le CEL |
$date_formatee = strftime('%A %d %B %Y', $timestamp->getTimestamp()); |
if(!$date_formatee) return "00/00/0000"; |
return $date_formatee; |
} |
} |