Subversion Repositories eFlore/Projets.eflore-projets

Rev

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

<?php
// declare(encoding='UTF-8');
/**
* Classe implémentant l'API d'eFlore Cartes pour le projet CHORODEP.
*
* @see http://www.tela-botanica.org/wikini/eflore/wakka.php?wiki=EfloreApi01Cartes
*
* @package eFlore/services
* @author Jean-Pascal MILCENT <jpm@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 1.0
* @copyright 1999-2012 Tela Botanica (accueil@tela-botanica.org)
*/
// TODO : Config et Outils sont des classes statiques qui doivent poser des pb pour les tests...
class Cartes {

        private $parametres = array();
        private $ressources = array();
        private $Bdd;

        const CODE_REFTAX_DEFAUT = 'bdtfx';
        const TYPE_ID_DEFAUT = 'nn';
        const CARTE_DEFAUT = 'france_02';
        const FORMAT_DEFAUT = '550';
        const MIME_SVG = 'image/svg+xml';
        const MIME_PNG = 'image/png';

        private $config = array();
        private $cheminCartesBase = '';
        private $formats_supportes = array(self::MIME_SVG, self::MIME_PNG);
        private $UrlNavigation = null;
        private $taxonsDemandes = array();
        private $imgLargeur = 0;
        private $imgHauteur = 0;

        public function __construct(Bdd $bdd = null, Array $config = null, CacheSimple $cache = null) {
                $this->Bdd = is_null($bdd) ? new Bdd() : $bdd;
                $this->config = is_null($config) ? Config::get('Cartes') : $config;
                $this->cheminCartesBase = $this->config['chemin'];
                $cacheOptions = array('mise_en_cache' => $this->config['cache']['miseEnCache'],
                        'stockage_chemin' => $this->config['cache']['stockageChemin'],
                        'duree_de_vie' => $this->config['cache']['dureeDeVie']);
                //die(print_r($this->config, true));
                $this->cache = is_null($cache) ? new CacheSimple($cacheOptions) : $cache;
        }

        public function consulter($ressources, $parametres) {
                //$tpsDebut = microtime(true);
                $this->parametres = $parametres;
                $this->ressources = $ressources;

                $this->definirValeurParDefautDesParametres();
                $this->verifierParametres();
                $this->analyserIdentifiant();

                $resultat = new ResultatService();
                if ($this->parametres['retour'] == self::MIME_SVG) {
                        $svg = $this->genererSVG();
                        $resultat->corps = $svg;
                } else if ($this->parametres['retour'] == self::MIME_PNG) {
                        $svg = $this->genererSVG();
                        $png = $this->convertirEnPNG($svg);
                        $resultat->corps = $png;
                }
                $resultat->mime = $this->parametres['retour'];

                return $resultat;
        }

        private function definirValeurParDefautDesParametres() {
                if (isset($this->parametres['retour']) == false) {
                        $this->parametres['retour'] = self::MIME_SVG;
                }
                if (isset($this->parametres['retour.format']) == false) {
                        $this->parametres['retour.format'] = self::FORMAT_DEFAUT;
                }
        }

        private function verifierParametres() {
                $erreurs = array();

                if ($this->verifierIdentifiants() == false) {
                        $erreurs[] = "L'identifiant de ressource indiqué ne respecte pas le format attendu.";
                }
                if (isset($this->parametres['retour']) == false) {
                        $erreurs[] = "Le paramètre type de retour 'retour' est obligatoire.";
                }
                if ($this->verifierValeurParametreRetour() == false) {
                        $erreurs[] = "Le type de retour '{$this->parametres['retour']}' n'est pas supporté.";
                }
                if (isset($this->parametres['retour.format']) == false) {
                        $erreurs[] = "Le paramètre de format de retour 'retour.format' est obligatoire.";
                }
                if ($this->verifierValeurParametreFormat() == false) {
                        $erreurs[] = "Le type de format '{$this->parametres['retour.format']}' n'est pas supporté.".
                                "Veuillez indiquer un nombre entier correspondant à la largeur désirée pour la carte.";
                }

                if (count($erreurs) > 0) {
                        $message = implode('<br />', $erreurs);
                        $code = RestServeur::HTTP_CODE_MAUVAISE_REQUETE;
                        throw new Exception($message, $code);
                }
        }

        private function verifierIdentifiants() {
                $ok = true;
                if (isset($this->ressources[0])) {
                        $ids = $this->ressources[0];
                        $projetPattern = '(?:(?:[A-Z0-9]+(\.(?:nn|nt)?):)?(?:[0-9]+,)*[0-9]+)';
                        $patternComplet = "/^$projetPattern(?:;$projetPattern)*$/i";
                        $ok = preg_match($patternComplet, $ids) ? true : false;
                }
                return $ok;
        }

        private function verifierValeurParametreRetour() {
                return in_array($this->parametres['retour'], $this->formats_supportes);
        }

        private function verifierValeurParametreFormat() {
                if ($ok = preg_match('/^([0-9]+)$/', $this->parametres['retour.format'], $match)) {
                        $this->imgLargeur = $match[1];
                } else if ($ok = preg_match('/^([0-9]+)x([0-9]+)$/', $this->parametres['retour.format'], $match)) {
                        $this->imgLargeur = $match[1];
                        $this->imgHauteur = $match[2];
                }
                return $ok;
        }

        private function analyserIdentifiant() {
                if (isset($this->ressources[0])) {
                        $ids = $this->ressources[0];
                        if (preg_match('/^[0-9]+$/', $ids)) {
                                $this->taxonsDemandes[self::CODE_REFTAX_DEFAUT]['nn'][] = $ids;
                        } else {
                                // ceci contient potentiellement des formes ref_tax1.nn:1,2;ref_tax2.nt:3,4
                                throw new Exception("A implémenter : ressource id multiples");
                                $projetsListeEtNumNoms = explode(';', $nn);
                                if (count($projetsListeEtNumNoms) > 0) {
                                        foreach ($projetsListeEtNumNoms as $projetEtNumNoms) {
                                                $projetEtNumNoms = (strpos($projetEtNumNoms, ':')) ? $projetEtNumNoms : self::CODE_REFTAX_DEFAUT.':'.$projetEtNumNoms;
                                                list($projet, $numNoms) = explode(':', $projetEtNumNoms);
                                                $this->ref_tax_demande[$projet] = explode(',', $numNoms);
                                        }
                                }
                        }
                } else {
                        throw new Exception("A implémenter : carte proportionnelle ensemble des infos");
                }
        }

        private function genererSVG() {
                $fichierCssBase = $this->cheminCartesBase.self::CARTE_DEFAUT.'.css';
                $css = file_get_contents($fichierCssBase);
                $css .= ".departement2b{fill:#ff0000;}";

                $idCss = $this->getIdFichierCss();
                $fichierCss = $this->config['cache']['stockageChemin'].$idCss.'.css';
                file_put_contents($fichierCss, $css);
                $urlCss = sprintf($this->config['cssUrlTpl'], $idCss);

                $fichierCarteSvg = $this->cheminCartesBase.self::CARTE_DEFAUT.'.svg';

                $dom = new DOMDocument('1.0', 'UTF-8');
                $dom->load($fichierCarteSvg);
                $racineElement = $dom->documentElement;
                $racineElement->setAttribute('width', $this->imgLargeur);
                $piCss = $dom->createProcessingInstruction('xml-stylesheet', 'type="text/css" href="'.$urlCss.'"');
                $dom->insertBefore($piCss, $racineElement);
                $svg = $dom->saveXML();
                return $svg;
        }

        private function chargerDonnees() {
                $refTax = self::CODE_REFTAX_DEFAUT;
                $numNom = $this->Bdd->proteger($this->taxonsDemandes[$refTax]['nn'][0]);

                $requete = 'SELECT   '.
                        'FROM cel_obs_images AS coi '.
                        '       LEFT JOIN cel_inventory AS ci '.
                                        'ON (coi.coi_ce_observation = ci.ordre AND coi.coi_ce_utilisateur = ci.identifiant) '.
                        'WHERE ci.transmission = 1 '.
                        "       AND ci.num_nom_ret IN ($numNom) ";
                $resultat = $this->Bdd->recupererTous($requete);

                if (!is_array($resultat) || count($resultat) <= 0) {
                        $message = "Aucune donnée ne correspond à la ressource demandée";
                        $code = RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE;
                        throw new Exception($message, $code);
                }

        }

        private function getIdFichierCss() {
                $ids = isset($this->ressources[0]) ? $this->ressources[0] : 'globale';
                $idCss = str_replace(array(',', ';', ':'), '-', $ids);
                return $idCss;
        }

        private function convertirEnPNG($svg) {
                $png = null;
                if (extension_loaded('imagick')) {
                        $png = $this->convertirEnPNGAvecImageMagick($svg);
                } else {
                        $message = "Impossible de générer l'image sur le serveur. Extenssion ImageMagick abscente.";
                        $code = RestServeur::HTTP_CODE_ERREUR;
                        throw new Exception($message, $code);
                }
                return $svg;
        }

        private function convertirEnPNGAvecImageMagick($svg) {
                $convertisseur = new Imagick();
                $convertisseur->readImageBlob($svg);
                $convertisseur->setImageFormat("png24");
                $convertisseur->resizeImage($this->imgLargeur, $this->imgHauteur, imagick::FILTER_LANCZOS, 0);
                $png = $convertisseur->getImageBlob();
                $convertisseur->clear();
                $convertisseur->destroy();
                return $png;
        }
}
?>