Subversion Repositories eFlore/Applications.cel

Rev

Rev 3914 | Blame | Compare with Previous | Last modification | View Log | RSS feed

<?php
// declare(encoding='UTF-8');
/**
 * Service fournissant permettant de visualiser ou télécharger des images du CEL
 * Spécifiquement pour le format O (original) tout en supprimant les EXIF
 * de façon à protéger les espèces protégées floutées
 *
 * @internal   Mininum PHP version : 5.2
 * @category   CEL
 * @package    Services
 * @subpackage Images
 * @version    0.1
 * @author     Mathias CHOUET <mathias@tela-botanica.org>
 * @author     Jean-Pascal MILCENT <jpm@tela-botanica.org>
 * @author     Aurelien 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>
 * @copyright  1999-2014 Tela Botanica <accueil@tela-botanica.org>
 */
class CelImageFormatO {

        private $config;
        // @TODO tirer ça de la config
        private $formats = array('O');
        const METHODE_TELECHARGEMENT = 'telecharger';
        const METHODE_AFFICHAGE = 'afficher';

        // Pas besoin d'étendre Cel ici, surtout que le constructeur
        // de la classe Cel instancie toujours une connexion à la bdd
        // dont on a pas besoin ici. Ceci évite de planter le service
        // quand la bdd est surchargée.
        public function __construct($config) {
                $this->config = $config;
        }

        public function getRessource() {
                header('Content-Type: application/json');
                echo json_encode($this->obtenirDescriptionService());
        }

        /**
        * Méthode appelée avec une requête de type GET.
        */
        public function getElement($params) {
                // suppression des 0 non significatifs à gauche
                $id = ltrim($params[0], '0');
                $format = isset($_GET['format']) ? $_GET['format'] : 'M';
                $methode_livraison = isset($_GET['methode']) ? $_GET['methode'] : self::METHODE_AFFICHAGE;

                if($this->verifierParametres($id, $format, $methode_livraison)) {
                        $gestion_formats_images = new ImageRecreation($this->config);
                        $image_binaire = $gestion_formats_images->creerOuRenvoyerImage($params[0], $format);

                        if($image_binaire) {
                                $this->envoyerImage($id, $image_binaire, $format, $methode_livraison);
                        } else {
                                header("HTTP/1.0 404 Not Found");
                                echo 'Aucune image ne correspond à cet identifiant';
                        }
                }
        }

        private function verifierParametres($id, $format, $methode_livraison) {
                $ok = true;
                $message = '';
                if(!is_numeric($id)) {
                        $message .= "L'identifiant de format doit être un entier. ";
                        $ok = false;
                }

                if(!in_array($format, $this->formats)) {
                        $message .= "Le format d'image est inconnu, les formats acceptés sont ".implode(',', $this->formats).". ";
                        $ok = false;
                }

                $types_methode_livraison = array(self::METHODE_AFFICHAGE, self::METHODE_TELECHARGEMENT);
                if (!in_array($methode_livraison, $types_methode_livraison)) {
                        $message .= "Le format de methode de livraison ".$methode_livraison." n'est pas acceptée par le service. ".
                                        " Seuls les methodes suivantes sont gérés : ".implode(',', $types_methode_livraison);
                        $ok = false;
                }

                if(!empty($message)) {
                        header("HTTP/1.0 400 Bad Request");
                        echo $message;
                }
                return $ok;
        }

        private function envoyerImage($id, $image_binaire, $format, $methode) {
                $gestion_formats_images = new ImageRecreation($this->config);
                $dossier = $gestion_formats_images->obtenirDossierPourFormat($id, $format);
                $nom_fichier = $gestion_formats_images->convertirIdBddVersNomFichier($id, $format);

                $last_modified_time = filemtime($dossier.'/'.$nom_fichier);
                
                // On génère l'ETAG faible
                $etag = 'W/"' . md5($last_modified_time) . '"';
                
                // On définit les bons headers
                header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $last_modified_time) . " GMT");
                header('Cache-Control: public, max-age=604800'); // On peut ici changer la durée de validité du cache
                header("Etag: $etag");
                
                // On vérifie les headers envoyés dans la requête
                if (
                (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) === $last_modified_time) ||
                (isset($_SERVER['HTTP_IF_NONE_MATCH']) && $etag === trim($_SERVER['HTTP_IF_NONE_MATCH']))
                ) {
                        // On renvoit une 304 si on n'a rien modifié depuis
                        header('HTTP/1.1 304 Not Modified');
                        exit();
                }

                if ($methode == self::METHODE_AFFICHAGE) {
                        header('Content-Type: image/jpeg');
                } else {
                        $this->envoyerHeadersTelechargement($id, $image_binaire, $format);
                }

                echo $image_binaire;
                exit();
        }

        private function envoyerHeadersTelechargement($id, $image_binaire, $format) {
                if (function_exists('mb_strlen')) {
                        $taille = mb_strlen($image_binaire, '8bit');
                } else {
                        $taille = strlen($image_binaire);
                }

                // creation du format original
                $id_avec_zeros = sprintf('%09s', $id) ;
                $id_avec_zeros_underscores = wordwrap($id_avec_zeros, 3 , '_', true) ;
                $nom_fichier = $id_avec_zeros_underscores.'_'.$format.'.jpg';

                header('Content-Description: File Transfer');
                header('Content-Type: application/octet-stream');
                header('Content-Disposition: attachment; filename="'.$nom_fichier.'"');
                header('Content-Transfer-Encoding: binary');
                header('Connection: Keep-Alive');
                header('Expires: 0');
                header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
                header('Pragma: public');
                header('Content-Length: '.$taille);
        }

        private function obtenirDescriptionService() {
                $retour = array('description' => 'Ce service peut être appelé afin de visualiser ou bien télécharger les images du cel',
                        'formats' => $this->formats,
                        'utilisation' => 'http://'.$_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI']."/{id} où {id} est l'identifiant numérique de l'image désirée",
                        'parametres' => array(
                                'methode' => "Valeurs : afficher, telecharger. Permet de préciser si l'image doit être affichée ou téléchargée",
                                'format' => "Valeurs : voir la liste ci dessous. Permet de demander un format précis de l'image parmi ceux disponibles ")
                );

                // ^^ c'est marrant non ?
                $format_formates = array();
                foreach ($this->formats as $format) {
                        if ($format == "O") {
                                $format_formates["O"] = array("hauteur" => "dépend de l'image originale",
                                                "largeur" => "dépend de l'image originale",
                                                "notes" => "Image dans son ratio et sa résolution originale (elle peut éventuellement avoir été compressée en qualité)"
                                );
                        } else {
                                $description = array();
                                if (strpos($format, 'R') !== false) {
                                        $description[] = "Format carré, rogné pour ne garder que le centre de l'image.";
                                }
                                if (strpos($format, 'C') !== false) {
                                        $description[] = "Format carré, si le format contient R, il est rogné, sinon des bandes blanches sont ajoutées pour conserver le ratio.";
                                }

                                if (empty($description)) {
                                        $description[] = "Format standard, le ratio original de l'image est conservé";
                                }

                                $resolution = $this->config['cel']['format_'.$format];
                                $resolution = explode("_", $resolution);
                                $format_formates[$format] = array("hauteur" => $resolution[0],
                                                "largeur" => $resolution[1],
                                                "notes" => implode(' ', $description)
                                );
                        }
                }

                $retour['resolutions'] = $format_formates;
                return $retour;
        }
}