* @author Jean-Pascal MILCENT * @author Aurelien PERONNET * @license GPL v3 * @license CECILL v2 * @copyright 1999-2014 Tela Botanica */ class ObservationDetails { private $conteneur; private $bdd; private $sql; private $idObs; private $protocole; private $observation; private $mappings = array(); public function __construct(Conteneur $conteneur) { $this->conteneur = $conteneur; $this->bdd = $this->conteneur->getBdd(); $this->sql = $this->conteneur->getSql(); $this->mappings['observations'] = $this->conteneur->getParametreTableau('observations.mapping'); $this->mappings['images'] = $this->conteneur->getParametreTableau('images.mapping'); $this->mappings['votes'] = $this->conteneur->getParametreTableau('votes.mapping'); $this->mappings['commentaires'] = $this->conteneur->getParametreTableau('commentaires.mapping'); // les deux alias suivants sont particuliers afin d'éviter un conflit d'alias lors des jointures avec del_commentaire_vote $this->mappings['commentaires']['ce_utilisateur'] = '__auteur_com'; $this->mappings['commentaires']['date'] = '__date_com'; } public function consulter($ressources, $parametres) { $this->idObs = $ressources[0]; $this->protocole = isset($parametres['protocole']) && is_numeric($parametres['protocole']) ? intval($parametres['protocole']) : null; $infos = $this->getInfosObservationEtImages(); if (! $infos) { $message = "Aucune observation ne possède d'identifiant '{$this->idObs}'."; throw new Exception($message, RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE); } $this->formaterObservation($infos); // 3) charge les données de votes et protocoles associés aux images if ($this->observation['images']) { $idsImages = array_keys($this->observation['images']); $votes = $this->sql->getVotesDesImages($idsImages, $this->protocole); $this->sql->ajouterInfosVotesProtocoles($votes, $this->observation['images']); } // 4) charge les commentaires et les votes associés -> modifie/créé $observation['commentaires'] $commentaires = $this->getCommentaires(); $this->ajouterCommentaires($commentaires); // désindexe le tableau (tel qu'apparement attendu par les applis), c'est une exception // TODO : corriger l'appli cliente pour utiliser les index puis supprimer cette ligne $this->observation['images'] = array_values($this->observation['images']); // autre élément de post-processing: le ce_utilisateur de l'observation non-numeric... $this->nettoyerAuteur(); // Mettre en forme le résultat et l'envoyer pour affichage $resultat = new ResultatService(); $resultat->corps = $this->observation; return $resultat; } private function getInfosObservationEtImages() { $obsChamps = $this->sql->getAliasDesChamps($this->mappings['observations'], null, 'do'); $imgChamps = $this->sql->getAliasDesChamps($this->mappings['images'], null, 'di'); // rétrocompatibilité champs de l'annuaire après suppression de del_utilisateur $annuaireChamps = implode(', ', array( "do.prenom_utilisateur AS `auteur.prenom`", "do.nom_utilisateur AS `auteur.nom`", "do.courriel_utilisateur AS `auteur.courriel`")); $requete = "SELECT $obsChamps, $imgChamps, $annuaireChamps ". "FROM del_observation AS do ". " LEFT JOIN del_image AS di ON (do.id_observation = di.ce_observation) ". "WHERE do.id_observation = {$this->idObs} ". '-- '.__FILE__.':'.__LINE__; //Debug::printr($requete); return $this->bdd->recupererTous($requete); } private function formaterObservation($infos) { $infos = array_filter($infos); foreach ($infos as $info) { $image = array_intersect_key($info, array_flip(array('id_image', 'date', 'hauteur' , 'largeur', 'nom_original'))); $urlImgTpl = $this->conteneur->getParametre('cel_img_url_tpl'); $imageFormat = 'XL'; $image['binaire.href'] = sprintf($urlImgTpl, $image['id_image'], $imageFormat); unset($info['id_image'], $info['date'], $info['hauteur'], $info['largeur'], $info['nom_original']); // ATTENTION : la requête retourne de nombreuses lignes avec les mêmes données (test de l'existence nécessaire) if (!isset($this->observation)) { $this->observation = $info; $this->observation['images'] = array(); } if (!isset($this->observation['images'][$image['id_image']])) { $this->observation['images'][$image['id_image']] = $image; } } } private function getCommentaires() { $selectVotes = array('id_vote', 'ce_proposition', 'ce_utilisateur', 'valeur', 'date'); $selectCommentaires = array('id_commentaire', 'ce_observation', 'ce_proposition', 'ce_commentaire_parent', 'texte', 'ce_utilisateur', 'utilisateur_prenom', 'utilisateur_nom', 'utilisateur_courriel', 'nom_sel', 'nom_sel_nn', 'nom_ret', 'nom_ret_nn', 'nt', 'famille', 'nom_referentiel', 'date', 'proposition_initiale','proposition_retenue'); $voteChamps = $this->sql->getAliasDesChamps($this->mappings['votes'], $selectVotes, 'cv'); $commentaireChamps = $this->sql->getAliasDesChamps($this->mappings['commentaires'], $selectCommentaires, 'dc'); // LEFT JOIN optionnel, mais explicatif : récupèration des infos de vote que pour les commentaires comportant un nom_sel "valide" $requete = "SELECT $commentaireChamps, $voteChamps ". "FROM del_commentaire AS dc ". " LEFT JOIN del_commentaire_vote AS cv ". " ON (cv.ce_proposition = dc.id_commentaire AND dc.nom_sel != '' AND dc.nom_sel IS NOT NULL) ". "WHERE ce_observation = {$this->idObs} ". '-- '.__FILE__.':'.__LINE__; $commentaires = $this->bdd->recupererTous($requete); return $commentaires; } private function ajouterCommentaires($commentaires) { if (!$commentaires) return; $ret = array(); foreach ($commentaires as $comment) { $commentId = $comment['id_commentaire']; $voteId = $comment['vote.id']; if (!array_key_exists($commentId, $ret)) { $comment_extract = array_intersect_key($comment, array_flip($this->mappings['commentaires'])); // cas particulier: conflit d'aliases avec del_commentaire_vote $comment_extract['auteur.id'] = $comment_extract['__auteur_com']; $comment_extract['date'] = $comment_extract['__date_com']; unset($comment_extract['__auteur_com'], $comment_extract['__date_com']); // toujours un éléments "votes", quand bien même il n'y en aurait pas $comment_extract['votes'] = array(); $ret[$commentId] = $comment_extract; } if (!$comment['nom_sel'] || ! $voteId) continue; $vote = array_intersect_key($comment, array_flip($this->mappings['votes'])); $ret[$commentId]['votes'][$voteId] = $vote; } $this->observation['commentaires'] = $ret; } private function nettoyerAuteur() { if (!isset($this->observation['auteur.id']) || !is_numeric($this->observation['auteur.id'])) { $this->observation['auteur.id'] = '0'; } if (!isset($this->observation['auteur.nom'])) { $this->observation['auteur.nom'] = '[inconnu]'; } } /** * Modifie une observation directement dans le CEL en faisant un appel à un web service du CEL. * Utilisé uniquement par les admins. * Permet de dépublier une observation. * * @param array $ressources tableau des informations contenues dans l'url après le nom du service * @param array $parametres contenu du post * @return mixed Chaine "OK" (en majuscule) en cas de succès, booléen "false" en cas d'échec */ public function modifier($ressources, $parametres) { $gestionUtilisateurs = $this->conteneur->getUtilisateur(); $gestionUtilisateurs->etreUtilisateurAvecDroitAdmin(); $retour = false; if (isset($parametres['transmission'])) { $idObs = $ressources[0]; $clientRest = $this->conteneur->getRestClient(); $urlTpl = $this->conteneur->getParametre('urlServiceCelObs'); $url = $urlTpl.$idObs; $retourCel = $clientRest->modifier($url, $parametres); $retour = preg_match('/^OK$/i', $retourCel) ? 'OK' : false; if ($retour === false) { $message = "Erreur du web service CEL : ".$retourCel; $code = RestServeur::HTTP_CODE_MAUVAISE_REQUETE; throw new Exception($message, $code); } } else { $message = "Ce web service doit contenir un paramètre 'transmission'."; $code = RestServeur::HTTP_CODE_MAUVAISE_REQUETE; throw new Exception($message, $code); } return $retour; } }