Subversion Repositories eFlore/Applications.cel

Rev

Rev 1638 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

<?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'import de données d'observation du CEL au format XLS
 */

// sont define()'d commme n° de colonne tous les slugs retournés par ExportXLS::fieldSetsToColumns()
// préfixés par C_  cf: detectionEntete()

set_include_path(get_include_path() . PATH_SEPARATOR . dirname(dirname(realpath(__FILE__))) . '/lib');
// TERM
error_reporting(-1);
ini_set('html_errors', 0);
ini_set('xdebug.cli_color', 2);
require_once('lib/PHPExcel/Classes/PHPExcel.php');
require_once('ExportXLS.php');

class MyReadFilter implements PHPExcel_Reader_IReadFilter {
        public $excludes = array();
        public function __construct() {}
    public function readCell($column, $row, $worksheetName = '') {
                if(@$this->excludes[$column]) return false;
                if($row == 1) return false;
                return true;
    } 
} 

class ImportXLS extends Cel  {

        static $ordre_BDD = Array(
                "ce_utilisateur",
                "prenom_utilisateur",
                "nom_utilisateur",
                "courriel_utilisateur",
                "ordre",
                "nom_sel",
                "nom_sel_nn",
                "nom_ret",
                "nom_ret_nn",
                "nt",
                "famille",
                "nom_referentiel",
                "zone_geo",
                "ce_zone_geo",
                "date_observation",
                "lieudit",
                "station",
                "milieu",
                "commentaire",
                "transmission",
                "date_creation",
                "date_modification",
                "latitude",
                "longitude");

        function ExportXLS($config) {
                parent::__construct($config);
        }

        function createElement($pairs) {
                if(!isset($pairs['utilisateur']) || trim($pairs['utilisateur']) == '') {
                        echo '0'; exit;
                }
                if(!isset($_SESSION)) session_start();
        $this->controleUtilisateur($pairs['utilisateur']);

        $this->utilisateur = $this->getInfosComplementairesUtilisateur($pairs['utilisateur']);

                $infos_fichier = array_pop($_FILES);
                
                /*$objPHPExcel = PHPExcel_IOFactory::load($infos_fichier['tmp_name']);
                  $sheetData = $objPHPExcel->getActiveSheet()->toArray(NULL,FALSE,FALSE,TRUE);*/

                /*$objReader = PHPExcel_IOFactory::createReader("Excel5");
                $objReader->setReadDataOnly(true);
                $objPHPExcel = $objReader->load($infos_fichier['tmp_name']);*/

                //var_dump($sheetData);

                $objReader = PHPExcel_IOFactory::createReader("Excel5");
                $objReader->setReadDataOnly(true);
                $objPHPExcel = $objReader->load($infos_fichier['tmp_name']);
                $sheetData = $objPHPExcel->getActiveSheet()->toArray(NULL,FALSE,FALSE,TRUE);

                $filterSubset = new MyReadFilter();
                $filterSubset->excludes = self::detectionEntete($sheetData[1]);
                $objReader->setReadFilter($filterSubset);

                // recharge avec le filtre sur colonnes actif
                // (exclue les colonnes inutiles/inutilisables)
                $objPHPExcel = $objReader->load($infos_fichier['tmp_name']);
                $sheetData = $objPHPExcel->getActiveSheet()->toArray(NULL,FALSE,FALSE,TRUE);
                self::charger($sheetData);
        }

        static function detectionEntete($entete) {
                $colonnes_reconnues = Array();
                $cols = ExportXLS::fieldSetsToColumns('standard');
                foreach($entete as $k => $v) {
                        $entete_simple = iconv('UTF-8', 'ASCII//TRANSLIT', strtolower(trim($v)));
                        foreach($cols as $col) {
                                $entete_officiel_simple = iconv('UTF-8', 'ASCII//TRANSLIT', strtolower(trim($col['nom'])));
                                $entete_officiel_slug = $col['slug'];
                                if($entete_simple == $entete_officiel_simple || $entete_simple == $entete_officiel_slug) {
                                        define("C_" . strtoupper($entete_officiel_slug), $k);
                                        $colonnes_reconnues[$k] = 1;
                                        break;
                                }
                        }
                }

                // eg: 'I' => "rien"
                $colonnesID_non_reconnues = array_diff_key($entete, $colonnes_reconnues);

                $colonnes_automatiques = array_filter($cols, function($v) {     return !$v['importable']; });
                // ne conserve que le nom long pour matcher avec la ligne XLS d'entête
                array_walk($colonnes_automatiques, function(&$v) {      $v = $v['nom']; });
                $colonnesID_a_exclure = array_intersect($entete, $colonnes_automatiques);
                // TODO: pourquoi ne pas comparer avec les slugs aussi

                return array_merge($colonnesID_non_reconnues, $colonnesID_a_exclure);
        }

        static function charger($donnees) {     
                // TODO: chunkfilter
                $chunks = 30;
                $i = 2;
                $end = $i + $chunks;
                while($i < $end && isset($donnees[$i])) {
                        $record = self::chargerLigne($donnees[$i]);
                        $req = implode(', ', self::sortArrayByArray($record, self::$ordre_BDD));
                        $i++;
                }
        }

        // TODO: bouger les valeurs fixes comme valeurs de self::$ordre_BDD
        // et compter sur un array_merge()

        // TODO, théoriquement, l'ordre des index peut-être changé si nécessaire car
        // nous utilisons self::sortArrayByArray()
        static function chargerLigne($ligne) {
                // en premier car le résultat est utile pour
                // traiter longitude et latitude (traiterLonLat())
                $referentiel = self::identReferentiel($ligne[C_REFERENTIEL]);

                return Array(
                        "ce_utilisateur" => XXX,
                        "prenom_utilisateur" => XXX,
                        "nom_utilisateur" => XXX,
                        "courriel_utilisateur" => XXX,
                        "ordre" => YYY,
                        "nom_sel" => TODO,
                        "nom_sel_nn" => TODO,
                        "nom_ret" => TODO,
                        "nom_ret_nn" => TODO,
                        "nt" => TODO,
                        "famille" => TODO,
                        "nom_referentiel" => $referentiel,
                        "zone_geo" => TODO,
                        "ce_zone_geo" => TODO,
                        "date_observation" => self::traiterDateObs($ligne[C_DATE_OBSERVATION]),
                        "lieudit" => trim($ligne[C_LIEUDIT]),
                        "station" => trim($ligne[C_STATION]),
                        "milieu" => trim($ligne[C_MILIEU]),
                        "commentaire" => trim($ligne[C_COMMENTAIRE]),

                        // XXX: fixe
                        "transmission" => 0, // cf commentaire dans ExportXLS::fieldSetsToColumns()
                        "date_creation" => date("Y-m-d H:i:s"),
                        "date_modification" => date("Y-m-d H:i:s"),

                        "latitude" => self::traiterLonLat(NULL, $ligne[C_LATITUDE], $referentiel),
                        "longitude" => self::traiterLonLat($ligne[C_LONGITUDE], NULL, $referentiel)
                );
        }

        static function traiterDateObs($date) {
                return NULL; // TODO
        }

        static function identReferentiel($referentiel) {
                return NULL; // TODO
        }

        static function traiterLonLat($lon = NULL, $lat = NULL, $referentiel = 'bdtfx:v1.01') {
                // verifier format decimal +
                // + limite france si bdtfx ou bdtxa
        }

        // http://stackoverflow.com/questions/348410/sort-an-array-based-on-another-array
        static function sortArrayByArray($array,$orderArray) {
                $ordered = array();
                foreach($orderArray as $key) {
                        if(array_key_exists($key, $array)) {
                                $ordered[$key] = $array[$key];
                                unset($array[$key]);
                        }
                }
                return $ordered + $array;
        }
}