Subversion Repositories eFlore/Applications.cel

Rev

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

<?php
// declare(encoding='UTF-8');
/**
 * Service fournissant des informations concernant le CEL au format RSS1, RSS2 ou ATOM.
 * Encodage en entrée : utf8
 * Encodage en sortie : utf8
 * Format du service :
 * /CelSyndicationObservation/liste-des-flux
 * /CelSyndicationObservation/opml
 * /CelSyndicationObservation/par-defaut/(rss1|rss2|atom)?start=0&limit=150
 * /CelSyndicationObservation/pour-admin/(rss1|rss2|atom)?start=0&limit=150
 * /CelSyndicationObservation/par-mots-cles/(rss1|rss2|atom)/mot-cle?start=0&limit=150
 * /CelSyndicationObservation/par-commune/(rss1|rss2|atom)/nom-commune?start=0&limit=150
 *
 * Les paramêtres :
 *  - "start" indique le numéro du premier item à afficher
 *  - "limit" nombre d'items à afficher
 *
 * @internal   Mininum PHP version : 5.2
 * @category   CEL
 * @package    Services
 * @subpackage Syndication
 * @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 CelSyndicationObservation extends Cel {

        private $parametres_origines = null;
        private $format = null;
        private $service = null;
        private $squelette = null;
        private $squelette_dossier = null;
        private $auteurs = array();
        private $flux = array();
        private $criteres = array(
                'utilisateur' => 'courriel_utilisateur',
                'commune' => 'zone_geo',
                'dept' => 'ce_zone_geo',
                'taxon' => 'nom_ret',
                'num_taxon' => 'nt',
                'commentaire' => 'commentaire',
                'date' => 'date_observation',
                'motcle' => 'tags',
                'projet' => 'mots-cles');
        private $catalogue_cles_labels_champs_etendus = array();

        /**
         * Méthode appelée avec une requête de type GET.
         */
        public function getElement($params = array()) {
                // Initialisation des variables
                $this->parametres_origines = $params;
                $info = array();
                $contenu = '';

                if (! $this->etreFluxAdmin() || $this->authentifierAdmin()) {
                        // Pré traitement des paramêtres
                        $pour_bdd = false;
                        $p = $this->traiterParametres(array('service', 'format'), $params, $pour_bdd);
                        extract($p);
                        $this->parametres = $params;
                        $this->squelette_dossier = dirname(__FILE__).DIRECTORY_SEPARATOR.'squelettes'.DIRECTORY_SEPARATOR;

                        // Récupération de la liste des flux
                        $this->chargerListeDesFlux();

                        // Chargement du bon type de service demandé
                        if (isset($service)) {
                                $this->service = $this->traiterNomService($service);
                                $methode = $this->getNomMethodeService();
                                if (method_exists($this, $methode)) {
                                        if (isset($format) && preg_match('/^(?:rss1|rss2|atom)$/i', $format)) {
                                                // Mise en minuscule de l'indication du format
                                                $this->format = strtolower($format);
                                                // Définition du fichier squelette demandé
                                                $this->squelette = $this->squelette_dossier.$this->format.'.tpl.xml';
                                        } else if (isset($this->flux[$this->service])) {
                                                $this->format = '';
                                                $this->messages[] = "Le service CEL Syndication nécessite d'indiquer en second paramètre le format : rss1, rss2 ou atom.";
                                        }

                                        if (!isset($this->flux[$this->service]) || isset($this->format)) {
                                                // Suppression des paramêtres inutile pour le reste des méthodes
                                                array_shift($this->parametres);
                                                array_shift($this->parametres);

                                                // Récupération du contenu à renvoyer
                                                $contenu = $this->$methode();
                                        }
                                } else {
                                        $this->messages[] = "Le type d'information demandé '$this->service' n'est pas disponible.";
                                }
                        } else {
                                $this->messages[] = "Le service CEL Syndication Observation nécessite d'indiquer en premier paramètre le type d'information demandé.";
                        }
                }

                // Envoie sur la sortie standard
                $encodage = 'utf-8';
                $mime = $this->getTypeMime();
                $formatage_json = $this->getFormatageJson();
                $this->envoyer($contenu, $mime, $encodage, $formatage_json);
        }

        private function getUrlBase() {
                $url_base = sprintf($this->config['settings']['baseURLAbsolu'], get_class($this).'/');
                return $url_base;
        }

        private function getUrlServiceBase() {
                $url_service = $this->getUrlBase().implode('/', $this->parametres_origines);
                return $url_service;
        }

        private function traiterNomService($nom) {
                $nom = strtolower($nom);
                return $nom;
        }

        private function getNomMethodeService() {
                $methode = '';
                $service_formate = str_replace(' ', '', ucwords(implode(' ', explode('-', $this->service))));
                $methode = 'getService'.$service_formate;
                return $methode;
        }

        private function getTypeMime() {
                $mime = '';
                $test = isset($this->format) ? $this->format : $this->service;
                switch ($test) {
                        case 'atom' :
                                $mime = 'application/atom+xml';
                                break;
                        case 'rss1' :
                        case 'rss2' :
                                $mime = 'application/rss+xml';
                                break;
                        case 'opml' :
                                $mime = 'text/x-opml';
                                break;
                        default:
                                $mime = 'text/html';
                }
                return $mime;
        }

        private function getFormatageJson() {
                $json = false;
                switch ($this->service) {
                        case 'liste-des-flux' :
                                $json = true;
                                break;
                        default:
                                $json = false;
                }
                return $json;
        }

        private function getFlux($nom) {
                return isset($this->flux[$nom]) ? $this->flux[$nom] : array();
        }

        private function setFlux($nom, $titre, $description) {
                $url_base = $this->getUrlBase();
                $formats = array('atom', 'rss2', 'rss1');
                $flux = array();
                foreach ($formats as $format) {
                        $url = $url_base.$nom.'/'.$format;
                        $flux[$format] = $url;
                }
                $this->flux[$nom] = array('titre' => $titre, 'description' => $description, 'urls' => $flux);
        }

        private function chargerListeDesFlux() {
                $this->setFlux('par-defaut', 'Flux de syndication des observations publiques du CEL',
                        'Ce flux fournit des informations sur les observations du CEL.');
                $this->setFlux('par-mots-cles', 'Flux de syndication obsolète',
                        "Ce flux est désormais accessible via le flux multicriteres/atom/M?tag='mot-cle'.");
                $this->setFlux('par-commune','Flux de syndication obsolète',
                        "Ce flux  est désormais accessible via le flux multicriteres/atom/M?commune='commune'.");
                $this->setFlux('multicriteres','Flux de syndication des nouvelles observations publiques du CEL '.
                        'filtrées par un ou plusieurs critères',
                        "Ce flux fournit des informations sur les nouvelles observations du CEL filtrées par ".
                        "auteur (mail), commune (nom), departement (code postal), taxon (nom scientifique), commentaire, projet ".
                        "et/ou date.");
        }

        private function getServiceListeDesFlux() {
                return $this->flux;
        }

        private function getServiceOpml() {
                $donnees = array();
                $id = 1;
                foreach ($this->flux as $flux_nom => $flux){
                        $info = array();
                        $info['type'] = 'atom';
                        $info['titre'] = $flux['titre'];
                        $info['texte'] = "CEL - Obs - $flux_nom";
                        $info['description'] = $flux['description'];
                        $info['url_xml'] = $this->getUrlBase().$flux_nom.'/atom';
                        $info['url_html'] = $this->config['settings']['aideCelUrl'].'FluxSyndication';
                        $donnees['liste_flux'][] = $info;
                }

                $this->squelette = $this->squelette_dossier.'opml.tpl.xml';
                $contenu = Cel::traiterSquelettePhp($this->squelette, $donnees);
                return $contenu;
        }

        private function getServiceParDefaut() {
                // Construction de la requête
                $requete =      (isset($this->distinct) ? 'SELECT DISTINCT' : 'SELECT').' * '.
                        'FROM cel_obs '.
                        (($this->etreFluxAdmin()) ? '' : 'WHERE transmission = 1 ').
                        'ORDER BY '.(isset($this->orderby) && (!is_null($this->orderby)) ? $this->orderby  : 'date_modification DESC').' '.
                        "LIMIT $this->start,$this->limit ";

                $elements = Cel::db()->requeter($requete);

                // Création du contenu
                $contenu = $this->executerService($elements);
                return $contenu;
        }

        private function getServiceParMotsCles() {
                $infos=array();
                $infos[0]['nom_sel_nn'] = '';
                $infos[0]['date_modification'] = '2011-06-28';
                $donnees = $this->construireDonneesCommunesAuFlux($infos);
                $donnees['items'][0]['guid'] = 0;
                $donnees['items'][0]['description'] =  'Ce flux est devenu obsolète. Veuillez utiliser le flux '.
                        '<b>http://www.tela-botanica.org/eflore/cel2/jrest/CelSyndicationObservation/multicriteres/atom?projet=';
                if (isset($this->parametres[0])) {
                        $donnees['items'][0]['description'] .= $this->parametres[0].'</b>';
                } else {
                        $donnees['items'][0]['description'] .= '</b>';
                }
                $donnees['items'][0]['titre'] = '';
                $contenu = Cel::traiterSquelettePhp($this->squelette, $donnees);
                return $contenu;
        }

        private function getServiceParCommune() {
                $infos=array();
                $infos[0]['nom_sel_nn'] = '';
                $infos[0]['date_modification'] = '2011-06-28';
                $donnees = $this->construireDonneesCommunesAuFlux($infos);
                $donnees['items'][0]['guid'] = 0;
                $donnees['items'][0]['description'] = 'Ce flux est devenu obsolète. Veuillez utiliser le flux '.
                        '<b>http://www.tela-botanica.org/eflore/cel2/jrest/CelSyndicationObservation/multicriteres/atom?commune=';
                if (isset($this->parametres[0])) {
                        $donnees['items'][0]['description'] .= $this->parametres[0].'</b>';
                } else {
                        $donnees['items'][0]['description'] .= '</b>';
                }
                $donnees['items'][0]['titre'] = '';
                $contenu = Cel::traiterSquelettePhp($this->squelette, $donnees);
                return $contenu;
        }

        private function getServiceMultiCriteres() {
                $contenu = '';
                if (isset($_GET['debut'])) $this->start = $_GET['debut'];
                if (isset($_GET['limite'])) $this->limit = $_GET['limite'];

                $this->limit = ($this->limit < 1000) ? $this->limit : 1000;// Pour éviter les abus !

                // Construction de la requête
                $requete = (isset($this->distinct) ? 'SELECT DISTINCT' : 'SELECT').' * '.
                                'FROM cel_obs '.
                                'WHERE 1 AND '.(($this->etreFluxAdmin()) ? '' : ' transmission = 1 AND ');

                if ($this->estUneRechercheGenerale()) {
                        $chaine_requete = $_GET['recherche'];
                        $requete .= $this->creerSousRequeteRechercheGenerale($chaine_requete);
                } else {
                        $criteres = $this->traiterCriteresMultiples($_GET) ;
                        if (!empty($criteres)) {
                                $requete .= $this->creerSousRequeteRechercheParCriteres($criteres);
                        }
                }
                $requete = rtrim($requete, 'AND ');
                $requete .= ' ORDER BY '.(isset($this->orderby) && (!is_null($this->orderby)) ? $this->orderby  :
                        'date_modification DESC, zone_geo ASC').' '.
                                "LIMIT $this->start,$this->limit ";

                $elements = Cel::db()->requeter($requete);

                // Création du contenu
                if ($elements != false && count($elements) > 0) {
                        $contenu = $this->executerService($elements);
                } else {
                        $this->messages[] = "Aucune observation disponible.";
                }

        return $contenu;
        }

        private function creerSousRequeteRechercheParCriteres($criteres) {
                $requete = '';
                foreach ($criteres as $pair) {
                        $nom_valeur = explode("=",$pair);
                        if (sizeof($nom_valeur) != 0) {
                                switch ($nom_valeur[0]) {
                                        case "ci_limite" : $this->limit = Cel::db()->quote($nom_valeur[1]); break;
                                        case "commentaire" : $mots_comment_liste = explode(" " , $nom_valeur[1]);
                                                foreach($mots_comment_liste as $mot_comment) {
                                                        $mot_comment = trim($mot_comment) ;
                                                        $requete .= $nom_valeur[0].' LIKE '.Cel::db()->quote('%'.$mot_comment.'%').' AND ';
                                                }
                                                break;
                                        case "date_observation" :
                                                $nom_valeur[1] = str_replace('/', '-', $nom_valeur[1]);
                                                if (preg_match('/(^[0-9]{2})-([0-9]{2})-([0-9]{4}$)/', $nom_valeur[1], $matches)) {
                                                        $nom_valeur[1] = $matches[3].'-'.$matches[2].'-'.$matches[1];
                                                }
                                                $requete .= $nom_valeur[0].'='.Cel::db()->quote($nom_valeur[1]).' AND '; break;
                                        case "ce_zone_geo" :
                                                $requete .= ' ('.$nom_valeur[0].' LIKE "INSEE-C:'.$nom_valeur[1].'%") AND '; break;
                                        case "nom_ret" :
                                                if ($nom_valeur[1] == "indetermine") $nom_valeur[1] = 'null';
                                                $requete .= ' ('.$nom_valeur[0].' LIKE "%'.$nom_valeur[1].'%" OR nom_sel LIKE "%'.
                                                        $nom_valeur[1].'%") AND '; break;
                                        case "mots-cles" : $requete .= $this->creerSousRequeteMotsCles($nom_valeur[1]).' AND '; break;
                                        case "tags" : $requete .= $this->creerSousRequeteTags($nom_valeur[1]).' AND '; break;
                                        default : $requete .= $nom_valeur[0].' = "'.$nom_valeur[1].'" AND '; break;
                                }
                        }
                }
                $requete = rtrim($requete,' AND ');
                return $requete;
        }

        private function creerSousRequeteMotsCles($mot_cle) {
                $requete = '';
                if (preg_match('/.*OU.*/', $mot_cle)) {
                        $mots_cles_tab = explode('OU',$mot_cle);
                        foreach($mots_cles_tab as $mot_cle_item) {
                                $requete .= '(mots_cles_texte LIKE '.Cel::db()->proteger('%'.$mot_cle_item.'%').') OR ';
                        }
                        $requete = '('.rtrim($requete,'OR ').') ';
                } else if (preg_match('/.*ET.*/', $mot_cle)) {
                        $mots_cles_tab = explode('ET',$mot_cle);
                        foreach($mots_cles_tab as $mot_cle_item) {
                                $requete .= '(mots_cles_texte LIKE '.Cel::db()->proteger('%'.$mot_cle_item.'%').') AND ';
                        }
                        $requete = '('.rtrim($requete, 'AND ').') ';
                } else {
                        $requete = "(mots_cles_texte LIKE ".Cel::db()->proteger('%'.$mot_cle.'%').') ';
                }
                return $requete;
        }

        private function creerSousRequeteTags($tag) {
                $requete = '(id_observation IN (SELECT ce_observation FROM cel_images ci WHERE ';
                $where = '';
                if (preg_match('/.*OU.*/', $tag)) {
                        $mots_cles_tab = explode('OU',$tag);
                        foreach($mots_cles_tab as $mot_cle_item) {
                                $where .= '(ci.mots_cles_texte LIKE '.Cel::db()->proteger('%'.$mot_cle_item.'%').') OR ';
                        }
                        $where .= '('.rtrim($where,'OR ').') ';
                } else if (preg_match('/.*ET.*/', $tag)) {
                        $mots_cles_tab = explode('ET',$tag);
                        foreach($mots_cles_tab as $mot_cle_item) {
                                $where .= '(ci.mots_cles_texte LIKE '.Cel::db()->proteger('%'.$mot_cle_item.'%').') AND ';
                        }
                        $where .= '('.rtrim($where, 'AND ').') ';
                } else {
                        $where .= "(ci.mots_cles_texte LIKE ".Cel::db()->proteger('%'.$tag.'%').') ';
                }
                $requete .= $where.' ))';
                return $requete;
        }

        private function traiterCriteresMultiples($tableau_criteres) {
                $tableau_criteres_pour_bdd = array();

                foreach($tableau_criteres as $nom_critere => $valeur_critere) {
                        if (isset($this->criteres[$nom_critere])) {
                                $tableau_criteres_pour_bdd[] = $this->criteres[$nom_critere].'='.$valeur_critere;
                        }
                }
                return $tableau_criteres_pour_bdd;
        }

        private function creerSousRequeteRechercheGenerale($chaine_requete) {
                $requete = '';
                if (trim($chaine_requete) != '') {
                        $chaine_requete = strtolower($chaine_requete);
                        $chaine_requete = str_replace(' ', '_', $chaine_requete);
                        $requete = ' ('.
                                'nom_ret LIKE "'.$chaine_requete.'%"'.
                                ' OR '.
                                'nom_sel LIKE "'.$chaine_requete.'%"'.
                                ' OR '.
                                'zone_geo LIKE "'.$chaine_requete.'%" '.
                                ' OR '.
                                'ce_zone_geo LIKE "'.$chaine_requete.'%" '.
                                ' OR '.
                                'ce_zone_geo LIKE "INSEE-C:'.$chaine_requete.'%" '.
                                ' OR '.
                                'courriel_utilisateur LIKE "'.$chaine_requete.'%" '.
                                ' OR '.
                                'mots_cles_texte LIKE "'.$chaine_requete.'%" '.
                                ') ';
                }
                return $requete;
        }

        private function estUneRechercheGenerale() {
                return isset($_GET['recherche']);
        }

        private function executerService($elements) {
                $contenu = '';
                if (is_array($elements)) {
                        // Prétraitement des données
                        $donnees = $this->construireDonneesCommunesAuFlux($elements);
                        $ids_observations = array();
                        foreach ($elements as $element) {
                                $identifiants[$element['courriel_utilisateur']] = $element['courriel_utilisateur'];
                                $ids_observations[] = $element['id_observation'];
                        }
                        $gestion_champs_etendus = new GestionChampsEtendus($this->config, 'obs');
                        $champs_etendus = $gestion_champs_etendus->consulterParLots($ids_observations);
                        if(!empty($champs_etendus)) {
                                $this->catalogue_cles_labels_champs_etendus = $gestion_champs_etendus->consulterCatalogueChampsEtendusPredefinis(true);
                                // afin de simplifier les erreurs de majuscules et minuscules
                                $this->catalogue_cles_labels_champs_etendus = array_change_key_case($this->catalogue_cles_labels_champs_etendus);
                        }
                        $this->auteurs = $this->creerAuteurs($identifiants);
                        foreach ($elements as $element) {
                                $element['obs_etendue'] = isset($champs_etendus[$element['id_observation']]) ? $champs_etendus[$element['id_observation']] : array();
                                $donnees['items'][] = $this->construireDonneesCommunesAuxItems($element);
                        }

                        // Création du contenu à partir d'un template PHP
                        if (isset($this->squelette)) {
                                $contenu = Cel::traiterSquelettePhp($this->squelette, $donnees);
                        }
                }
                return $contenu;
        }

        private function construireDonneesCommunesAuFlux($observations) {
                $donnees = $this->getFlux($this->service);
                $donnees['guid'] = $this->getUrlServiceBase();
                $donnees['titre'] = 'Flux des observations du CEL';
                $donnees['lien_service'] = $this->creerUrlService();
                $donnees['lien_cel'] = $this->config['settings']['baseURLAbsolu'];
                $donnees['editeur'] = $this->config['settings']['editeur'];
                $derniere_info_en_date = reset($observations);
                $date_modification_timestamp = strtotime($derniere_info_en_date['date_modification']);
                $donnees['date_maj_RSS'] = date(DATE_RSS, $date_modification_timestamp);
                $donnees['date_maj_ATOM'] = date(DATE_ATOM, $date_modification_timestamp);
                $donnees['date_maj_W3C'] = date(DATE_W3C, $date_modification_timestamp);
                $donnees['annee_courante'] = date('Y');
                $donnees['generateur'] = 'CEL - Jrest - CelSyndicationObservation';
                $donnees['generateur_version'] = (preg_match('/([0-9]+)/', '$Revision$', $match)) ?  $match[1] : '0';
                return $donnees;
        }

        private function construireDonneesCommunesAuxItems($observation) {
                $item = array();
                $date_modification_timestamp = $this->convertirDateHeureMysqlEnTimestamp($observation['date_modification']);
                $item['date_maj_simple'] = strftime('%A %d %B %Y à %H:%M', $date_modification_timestamp);
                $item['date_maj_RSS'] = date(DATE_RSS, $date_modification_timestamp);
                $item['date_maj_ATOM'] = date(DATE_ATOM, $date_modification_timestamp);
                $item['date_maj_W3C'] = date(DATE_W3C, $date_modification_timestamp);
                $item['date_creation_simple'] = strftime('%A %d %B %Y à %H:%M', strtotime($observation['date_creation']));
                $item['titre'] = $this->creerTitre($observation);
                $item['guid'] = $this->creerGuidItem($observation);
                $item['lien'] = $this->creerLienItem($observation);
                $item['categorie'] = $this->creerCategorie($item);
                $item['description'] = $this->creerDescription(Cel::protegerCaracteresHtmlDansChamps($observation), $item);
                $item['description_encodee'] = htmlspecialchars($this->creerDescription($observation, $item));
                $item['modifier_par'] = $this->nettoyerTexte($observation['id_observation']);
                return $item;
        }

        private function creerTitre($obs) {
                $date = ($obs['date_observation'] != '0000-00-00 00:00:00') ? 'le '.date("d/m/Y", strtotime($obs['date_observation'])) : '' ;
                $nom_plante = $obs['nom_sel'].' [nn'.$obs['nom_sel_nn'].']';
                $lieu = Cel::formaterZoneGeoEtCodePourAffichage($obs);
                $utilisateur = $this->getIntituleAuteur($obs['courriel_utilisateur']);
                $titre = "$nom_plante à $lieu par $utilisateur $date";
                $titre = $this->nettoyerTexte($titre);
                return $titre;
        }

        private function creerGuidItem($element) {
                $guid = sprintf($this->config['settings']['guidObsTpl'], $element['id_observation']);
                return $guid;
        }

        private function creerLienItem($element) {
                $lien = null;
                if ($element['nom_sel_nn'] != 0) {
                        $lien = $this->getUrlEflore($element['nom_referentiel'], $element['nom_sel_nn'], 'cel');
                }
                return $lien;
        }

        private function creerDescription($obs, $item) {
                $id_obs = $obs['id_observation'];
                $famille = $obs['famille'];
                $nom_saisi = $obs['nom_sel'];
                $nom_retenu = $obs['nom_ret'];
                $auteur = $this->getIntituleAuteur($obs['courriel_utilisateur']);
                $auteur_mail = $obs['courriel_utilisateur'];
                $mots_cles_obs = $obs['mots_cles_texte'];
                $lien_correction = sprintf($this->config['settings']['phpEditUrlTpl'], $obs['id_observation']);
                
                $lieu =  Cel::formaterZoneGeoEtCodePourAffichage($obs).' > '.$obs['lieudit'].' > '.$obs['station'];
                $milieu = $obs['milieu'];
                $coordonnees = ($this->etreNull($obs['latitude']) && $this->etreNull($obs['longitude'])) ? '' : $obs['latitude'].'/'.$obs['longitude'];
                $commentaire = $obs['commentaire'];
                $date_observation = ($obs['date_observation'] != '0000-00-00 00:00:00') ? $this->formaterDate($obs['date_observation'], '%A %d %B %Y') : '';
                $date_transmission = $this->formaterDate($obs['date_transmission']);
                $date_modification = $this->formaterDate($obs['date_modification']);
                $date_creation = $this->formaterDate($obs['date_creation']);
                $transmission = $obs['transmission'] == 1 ? "oui ($date_transmission)" : 'non';

                $description = '<h2>'."Observation #$id_obs de $nom_saisi".'</h2>'.
                        '<ul>'.
                        '<li>'.'Famille : '.$famille.'</li>'.
                        '<li>'.'Nom saisi : '.$nom_saisi.'</li>'.
                        '<li>'.'Nom retenu : '.$nom_retenu.'</li>'.
                        '<li>'.'Observée le : '.$date_observation.'</li>'.
                        '<li>'.'Lieu : '.$lieu.'</li>'.
                        '<li>'.'Milieu : '.$milieu.'</li>'.
                        (($this->etreFluxAdmin()) ? '<li>Coordonnées (Lat/Long) : '.$coordonnees.'</li>' : '').
                        '<li>'.'Commentaire : '.$this->nePasInterpreterXml($commentaire).'</li>'.
                        '<li>'.'Mots-clés : '.$this->nePasInterpreterXml($mots_cles_obs).'</li>'.
                        (($this->etreFluxAdmin()) ? '<li>Transmis (= public) : '.$transmission.'</li>' : '').
                        '<li>Modifiée le : '.$date_modification.'</li>'.
                        '<li>Créée le : '.$date_creation.'</li>'.
                        '<li>'.'Par : '.
                                (($this->etreFluxAdmin()) ? '<a href="mailto:'.$auteur_mail.'">'.$auteur.'</a>' : $auteur).
                        '</li>'.
                        $this->creerDescriptionChampsEtendus($obs, $item).
                        (($this->etreFluxAdmin()) ? '<li><a href="'.$lien_correction.'">Corriger cette observation</a></li>' : '').
                        '</ul>';
                $description = $this->nettoyerTexte($description);
                return $description;
        }

        private function creerDescriptionChampsEtendus($obs, $item) {
                $champs_etendus = '';
                foreach($obs['obs_etendue'] as $cle => &$champ) {
                        if($this->doitAfficherChampEtendu($champ->cle, $this->catalogue_cles_labels_champs_etendus)) {
                                if(isset($this->catalogue_cles_labels_champs_etendus[$champ->cle])) {
                                        $label = $this->catalogue_cles_labels_champs_etendus[$champ->cle]['label'];
                                } else {
                                        $label = preg_replace("/(?<=\\w)(?=[A-Z])/"," $1", $champ->cle);
                                        $label = trim($label);
                                        $label = $label;
                                }
                                $champs_etendus .= '<li>'.$this->nePasInterpreterXml($label.' : '.$champ->valeur).' </li>';
                        }
                }

                if($champs_etendus != '') {
                        $champs_etendus = '<li> Champs supplémentaires : <ul>'.$champs_etendus.'</ul></li>';
                }

                return $champs_etendus;
        }

        private function doitAfficherChampEtendu($cle, $catalogue) {
                // Suppression des nombres à la fin de la chaines dans le cas des clés
                // "multiples" et mise en minuscule
                $cle_simplifiee = preg_replace("/\d+$/","",$cle);
                $cle_simplifiee = strtolower(rtrim($cle_simplifiee, ":"));

                // Un champ est affichable s'il n'est pas au catalogue ou bien
                // s'il n'est pas marqué privé dans celui-ci
                $affichable = !isset($catalogue[$cle_simplifiee]) ||
                                                $catalogue[$cle_simplifiee]['options']['prive'] != 1;

                return $affichable;
        }

        private function creerCategorie($element) {
                $categorie = '';
                $categorie = 'Observation';
                $categorie = $this->nettoyerTexte($categorie);
                return $categorie;
        }

        private function etreFluxAdmin() {
                return (isset($_GET['admin']) && $_GET['admin'] == '1') ? true : false;
        }

        private function creerUrlService() {
                $url_service = $this->getUrlServiceBase();
                if (count($_GET) > 0) {
                        $parametres_get = array();
                        foreach ($_GET as $cle => $valeur) {
                                $parametres_get[] = $cle.'='.$valeur;
                        }
                        $url_service .= '?'.implode('&amp;', $parametres_get);
                }
                return $url_service;
        }

        private function getIntituleAuteur($courriel) {
                $courriel = strtolower($courriel);
                if(isset($this->auteurs[$courriel])) {
                        $intitule = $this->auteurs[$courriel];
                } else {
                        $intitule = $courriel;
                }
                return $intitule;
        }
}