Subversion Repositories eFlore/Projets.eflore-projets

Rev

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

<?php

/**
* Classe CommunGraphiques.php regroupement de fonctions pour les graphiques
*  graphiques/#typegraphique/#bdnt.nn:#num_nomen --> renvoie un graphique avec les données connues
*
*
* @package eflore-projets
* @author Jean-Pascal MILCENT <jpm@tela-botanica.org>
* @author Mathilde SALTHUN-LASSALLE <mathilde@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-2011 Tela Botanica (accueil@tela-botanica.org)
*/

abstract class CommunGraphiques extends Commun{

        protected $parametres = array();
        protected $ressources = array();

        protected $Bdd;
        protected $config;
        protected $cache;
        protected $metadonnees;
        protected $version;
        protected $serviceNom = 'Graphiques';

        protected $graduations_id = array();
        protected  $champs_ontologiques =  array();
        protected $nomGraphique = array();

        protected $table = '';
        protected $requete_condition = "";
        protected $requete_champs;

        protected $convertisseur;
        protected $cheminGraphBase;
        protected $valeurs_en_pourcentage = array();
        protected $dom;
        protected $largeurSVG = "500";
        protected $hauteurSVG;
        protected $valeurs_champs;



        public function consulter($ressources, $parametres) {
                $this->ressources = $ressources;
                $this->parametres = $parametres;
                $this->verifierParametres();
                $this->initialiserConfiguration();
                $resultats = '';
                $this->traiterRessources();

                $req = $this->assemblerLaRequete();
                $resultat = $this->resultat = $this->Bdd->recupererTous($req);
                $versionResultat = $this->obtenirResultat($resultat);
                return $versionResultat;
        }


        //+--------------------------initialisation de paramètres  -------------------------------------------+

        private function initialiserConfiguration() {
                $conteneur = new Conteneur();
                $this->Bdd = $conteneur->getBdd();
                $this->config = $conteneur->getParametre('Graphiques');
                $this->convertisseur = $this->config['convertisseur'];
                $this->graduations_id = $this->getParametreTableau('Paramètres.graduations_id');
                $this->champs_ontologiques = $this->getParametreTableau('Paramètres.champs_ontologiques');
                $this->cheminGraphBase = $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']);
                $this->cache = $conteneur->getCacheSimple($cacheOptions);
                $this->definirVersion();
                $this->definirFormat();
                $this->definirTable($this->version);
        }



        abstract function definirTable($version);


        private function getParametreTableau($cle) {
                $tableau = array();
                $parametre = Config::get($cle);
                if (empty($parametre) === false) {
                        $tableauPartiel = explode(',', $parametre);
                        $tableauPartiel = array_map('trim', $tableauPartiel);
                        foreach ($tableauPartiel as $champ) {
                                if (strpos($champ, '=') !== false && strlen($champ) >= 3) {
                                        list($cle, $val) = explode('=', $champ);
                                        $tableau[trim($cle)] = trim($val);
                                } else {
                                        $tableau[] = trim($champ);
                                }
                        }
                }
                return $tableau;
        }

        //+--------------------------traitement ressources ou paramètres  -------------------------------------------+

        //+---- paramètres ----+

        private function verifierParametres() {
                if (isset($this->parametres)) {
                        $parametres_dispo = array('retour', 'retour.format', 'version.projet');
                        $parametres = array_keys($this->parametres);
                        foreach ($parametres as $param) {
                                if (!in_array($param, $parametres_dispo)) {
                                        $erreur = "Erreur : Le paramètre $param est inconnu.";
                                        $code = RestServeur::HTTP_CODE_MAUVAISE_REQUETE;
                                        throw new Exception($erreur, $code);
                                }
                        }
                }

        }

        //on n'affiche qu'une version de graphique à la fois ( la dernière ou celle demandée )
        private function definirVersion() {
                $this->chargerVersions();
                if (!isset($this->parametres['version.projet']) ) {
                        $this->version = $this->metadonnees[0]['version'];
                } elseif ($this->parametres['version.projet'] == '+') {
                                 $this->version = $this->metadonnees[0]['version'];
                } else {
                        if($this->verifierVersion($this->parametres['version.projet'])) {
                                $this->version = $this->parametres['version.projet'];
                        }else {
                                $erreur = "Erreur : La version est inconnue.";
                                $code = RestServeur::HTTP_CODE_MAUVAISE_REQUETE;
                                throw new Exception($erreur, $code);
                        }
                }
        }

        private function verifierVersion($version){
                $retour = false;
                foreach ($this->metadonnees as $vers) {
                        if ($vers['version'] == $version ) {
                                $retour = true;
                        }
                }
                return $retour;
        }
        private function definirFormat() {
                if (isset($this->parametres['retour.format']) ){
                        if (preg_match("/^[0-9]+$/", $this->parametres['retour.format'])){
                                if ($this->parametres['retour.format'] > 0) {
                                        $this->largeurSVG = $this->parametres['retour.format'];
                                } else {
                                        $erreur = "Erreur : valeur pour retour.format négative ou égale à 0.";
                                        $code = RestServeur::HTTP_CODE_MAUVAISE_REQUETE;
                                        throw new Exception($erreur, $code);
                                }
                        }else {
                                $erreur = "Erreur : valeur inconnue. Entrez la largeur voulue (en pixels) pour le paramètre retour.format.";
                                $code = RestServeur::HTTP_CODE_MAUVAISE_REQUETE;
                                throw new Exception($erreur, $code);
                        }
                }
                if (!isset($this->parametres['retour']) ){
                        $this->parametres['retour'] = 'image/svg+xml';

                }else {
                        if (( $this->parametres['retour'] != 'image/svg+xml')&& ( $this->parametres['retour'] != 'image/png')){
                                $erreur = "Erreur : valeur inconnue. Choisissez le format de retour pour le paramètre retour : image/svg%2Bxml ou image/png.";
                                $code = RestServeur::HTTP_CODE_MAUVAISE_REQUETE;
                                throw new Exception($erreur, $code);
                        }
                }
        }



        private function chargerVersions() {
                $requete = "SELECT version ".
                                                        "FROM ".Config::get('bdd_table_meta')." ".
                                                        "ORDER BY date_creation DESC ";
                $resultats = $this->Bdd->recupererTous($requete);
                if (!is_array($resultats) || count($resultats) <= 0) {
                        $message = "Les méta-données n'ont pu être chargée pour la ressource demandée";
                        $code = RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE;
                        throw new Exception($message, $code);
                }

                $this->metadonnees = $resultats;
        }

        //+----- ressources -----+


        public function traiterRessources() {
                if(isset($this->ressources)) {
                        $this->traiterTypeGraphique();
                        $this->traiterReferentielEtNum();
                } else {
                        $e = 'Erreur dans l\'url de votre requête : </br> ressources insuffisantes.';
                        throw new Exception( $e, RestServeur::HTTP_CODE_MAUVAISE_REQUETE);
                }
        }

        abstract function traiterReferentielEtNum();
        abstract function traiterTypeGraphique();

        //+--------------------------FONCTIONS D'ASSEMBLAGE DE LA REQUETE-------------------------------------------+

        public function assemblerLaRequete() {
                return ' SELECT '.$this->requete_champs.'  FROM '.$this->table.' '.Informations::retournerRequeteCondition($this->requete_condition);
        }

        public  function retournerRequeteCondition() {
                $condition = '';
                if ($this->requete_condition !== "") {
                        $condition = ' WHERE '.implode(' AND ', $this->requete_condition);
                }
                return $condition;
        }

        //+-------------------------- formatage du résultat  -------------------------------------------+

        public function obtenirResultat($resultat) {
                if ($resultat == '') {
                        throw new Exception(
                'La requête SQL formée comporte une erreur!',
                RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE);
                } elseif ($resultat) {
                        if ((count($this->ressources)) != 0) {
                                //$Atraiter = array_filter($resultat[0],function($var){return ($var != '');});
                                foreach ($resultat[0] as $champs => $valeur) {
                                        if ($valeur !== null && $valeur !== '') {
                                                $Atraiter[$champs] = $valeur;
                                        }
                                }
                                if (!empty($Atraiter)) {
                                        $this->traiterValeursEcologiques($Atraiter);
                                        $svg = $this->genererSVG($this->cheminGraphBase.$this->nomGraphique.".svg");
                                        $resultat = new ResultatService();
                                        $resultat->corps = ($this->parametres['retour'] == 'image/png') ? $this->convertirEnPNG($svg) : $svg;
                                        $resultat->mime = $this->parametres['retour'];
                                } else {
                                        $resultat = null;
                                }
                        }
                } else {
                        $resultat = null;
                }
                return $resultat;
        }




        //+----- modification svg -----+



        public function traiterValeursEcologiques($valeur) {
                $this->valeurs_champs = $valeur;

                foreach($this->valeurs_champs as $cle => $val){
                        if ($val === null) {
                                $this->valeurs_en_pourcentage[$cle] = null;
                        } else {
                                if (preg_match("/ve_humidite_edaph/", $cle)) {
                                        $this->valeurs_en_pourcentage[$cle] = round($val/13,1);
                                } elseif (preg_match("/ve_salinite/", $cle)) {
                                        $this->valeurs_en_pourcentage[$cle] = round(($val+1)/11,1);
                                } else {
                                        $this->valeurs_en_pourcentage[$cle] = round($val/10,1);
                                }
                        }
                }
        }

        public function donnerHauteur($ancienne_largeur, $ancienne_hauteur) {
                $nouvelle_largeur = $this->largeurSVG;
                $ancienne_largeur = str_replace('px','',$ancienne_largeur);
                $ancienne_hauteur = str_replace('px','',$ancienne_hauteur);
                $rapport =   $nouvelle_largeur / $ancienne_largeur ;
                $nouvelle_hauteur = $ancienne_hauteur * $rapport;
                $this->hauteurSVG = $nouvelle_hauteur;
        }

        public function ajusterFormatSVG(){
                $svg = $this->dom->getElementsByTagName("svg")->item(0);
                $largeur = $svg->getAttribute('width');
                $hauteur = $svg->getAttribute('height');
                $this->donnerHauteur($largeur , $hauteur);
                $svg->setAttribute('width',round($this->largeurSVG).'px');
                $svg->setAttribute('height',round($this->hauteurSVG).'px');

        }

        public function genererSVG($fichierSvg){
                $svg = null;
                $this->dom = new DOMDocument('1.0', 'UTF-8');
                $this->dom->validateOnParse = true;
                $this->dom->load($fichierSvg);
                $this->changerValeursSVG();
                return $this->dom->saveXML();
        }

        abstract function changerValeursSVG();

        public function recupererOntologies($valeur, $champs){
                $url = $this->ajouterHref('ontologies',$this->champs_ontologiques[$champs].':'.urlencode(urlencode($valeur)));
                try {
                        $val = $this->getBdd()->recuperer(sprintf(
                                "SELECT a.nom FROM baseflor_ontologies a LEFT JOIN baseflor_ontologies b ON a.id = b.id LEFT JOIN baseflor_ontologies c ON b.classe_id = c.id WHERE".
                                " b.code = BINARY '%s' AND c.code = BINARY '%s' LIMIT 0, 100",
                                $valeur,
                                $this->champs_ontologiques[$champs]),
                                Bdd::MODE_OBJET);
                } catch (Exception $e) {
                        $val = false;
                }
                return $val;
        }

        public function traiterIntermediaires($valeurTexte,$champsOntologie, $champsTable){
                if (preg_match("/(?:I|i)nterm(?:é|e)diaire(?:s)*/", $valeurTexte )) {
                        $prec = $this->recupererOntologies(($this->valeurs_champs[$champsTable]-1), $champsOntologie );
                        $suiv = $this->recupererOntologies(($this->valeurs_champs[$champsTable]+1), $champsOntologie );
                        $valeurTexte = "Intermédiaires entre $prec->nom et $suiv->nom ";
                }
                return $valeurTexte;
        }

        /// +---- convertir png ----+

        public function convertirEnPNG($svg) {
                $png = null;

                if (isset($this->convertisseur)) {
                        if ($this->convertisseur == 'imagick') {
                                if (extension_loaded('imagick')) {
                                        $png = $this->convertirEnPNGAvecImageMagick($svg);
                                } else {
                                        $message = "Impossible de générer l'image sur le serveur. Extension ImageMagick absente.";
                                        $code = RestServeur::HTTP_CODE_ERREUR;
                                        throw new Exception($message, $code);
                                }
                        } else if ($this->convertisseur == 'rsvg') {
                                $png = $this->convertirGraphiqueEnPNGAvecRsvg($svg);
                        } else {
                                $message = "Le convertisseur indiqué '{$this->convertisseur}' ne fait pas partie de la liste ".
                                                                "des convertisseurs disponibles : imagick, rsvg.";
                                $code = RestServeur::HTTP_CODE_ERREUR;
                                throw new Exception($message, $code);
                        }
                } else {
                        $message = "Veuillez indiquer le convertisseur de svg à utiliser pour le service.";
                        $code = RestServeur::HTTP_CODE_ERREUR;
                        throw new Exception($message, $code);
                }
                return $png;
        }

        public function convertirEnPNGAvecImageMagick($svg) {
                $convertisseur = new Imagick();
                $convertisseur->setBackgroundColor(new ImagickPixel('#F8F8F8'));
                $convertisseur->readImageBlob($svg);
                $convertisseur->setImageFormat('png32');
                $convertisseur->resizeImage($this->largeurSVG,$this->hauteurSVG, imagick::FILTER_LANCZOS, 0, true);
                $png = $convertisseur->getImageBlob();
                $convertisseur->clear();
                $convertisseur->destroy();
                return $png;
        }

        public function convertirGraphiqueEnPNGAvecRsvg($svg) {
                $idFichier = $this->getIdFichier();
                $fichierPng = $this->config['cache_stockageChemin'].$idFichier.'.png';
                $fichierSvg = $this->config['cache_stockageChemin'].$idFichier.'.svg';
                file_put_contents($fichierSvg, $svg);
                $commande = "rsvg-convert  $fichierSvg -w ".$this->largeurSVG ." -h ".$this->hauteurSVG ." -o $fichierPng";
                //echo $commande; exit;
                $rsvg = exec($commande);
                $this->indexerGraphiqueFichierPng($fichierPng);
                $png = file_get_contents($fichierPng);
                return $png;
        }

        public function indexerGraphiqueFichierPng($fichierPng) {
                $img = imagecreatefrompng($fichierPng);
                imagetruecolortopalette($img, false, 32);
                imagepng($img, $fichierPng, 9, PNG_ALL_FILTERS);
        }

        public function getIdFichier(){
                $idfichier = str_replace(".","-",$this->ressources[1]);
                $idfichier = str_replace(':','-',$idfichier);
                $idfichier .= "-".$this->ressources[0];
                return $idfichier;
        }
}
?>