* @author Jean-Pascal MILCENT * @author Aurelien PERONNET * @license GPL v3 * @license CECILL v2 * @copyright 1999-2014 Tela Botanica */ class AjouterCommentaire { private $conteneur; private $navigation; private $bdd; private $parametres = array(); private $mapping = array(); private $erreurs = array(); public function __construct(Conteneur $conteneur) { $this->conteneur = $conteneur; $this->navigation = $this->conteneur->getNavigation(); $this->bdd = $this->conteneur->getBdd(); $this->mapping = $this->conteneur->getParametreTableau('commentaires.mapping'); } public function ajouter($parametres) { $this->parametres = $parametres; $this->verifierParametres(); $this->completerParametresUtilisateur(); $this->gererPropositionInitiale(); // Dernière chance de rattachement au référentiel d'un nom // sans nn (cas du copier-coller ou bien de l'appli tierce // qui envoie des infos incomplètes) $this->tenterEnrichissementTaxonomique(); $idCommentaireAjoute = $this->insererCommentaire(); // Mettre en forme le résultat et l'envoyer pour affichage $resultat = new ResultatService(); $resultat->corps = array('id_commentaire' => $idCommentaireAjoute); return $resultat; } private function verifierParametres() { if (!isset($this->parametres['observation'])) { $this->erreurs[] = "Impossible d'ajouter un commentaire sans identifiant d'observation (paramètre 'observation')."; } if (!isset($this->parametres['auteur.id'])) { $this->verifierParamsAuteurAnonyme(); } $this->verifierParamsNonVide(); if (isset($this->parametres['nom_sel_nn']) && !isset($this->parametres['nom_referentiel'])) { $this->erreurs[] = "Si le paramètre «nom_sel_nn» est présent, le paramètre «nom_referentiel» doit l'être aussi."; } if (!empty($this->erreurs)) { $msg = "Erreur de configuration :\n".implode("\n\n", $this->erreurs); throw new Exception($msg, RestServeur::HTTP_CODE_MAUVAISE_REQUETE); } } private function verifierParamsAuteurAnonyme() { $paramsAuteur = array('auteur.nom', 'auteur.prenom', 'auteur.courriel'); $paramsAuteurManquant = array(); foreach ($paramsAuteur as $param) { if (!isset($this->parametres[$param])) { $paramsAuteurManquant[] = $param; } } if (!empty($paramsAuteurManquant)) { $msgAuteurTpl = "Si le parametre 'auteur.id' n'est pas utilisé, il est nécessaire d'indiquer les ". "nom (paramètre 'auteur.nom'), prénom (paramètre 'auteur.prenom') et courriel ". "(paramètre 'auteur.courriel') de l'auteur.\nLes paramètres suivant sont abscents : %s\n"; $this->erreurs[] = sprintf($msgAuteurTpl, implode(', ', $paramsAuteurManquant)); } } private function verifierParamsNonVide() { $paramsNonVide = array('nom_sel', 'nom_referentiel', 'nom_sel_nn'); foreach ($paramsNonVide as $param) { if (isset($this->parametres[$param]) && trim($this->parametres[$param]) == '' ) { $this->erreurs[] = "S'il est présent le paramètre «$param» ne peut pas être vide."; } } } private function completerParametresUtilisateur() { $utilisateur = (isset($this->parametres['auteur.id'])) ? $this->obtenirUtilisateurAvecId() : $this->obtenirUtilisateurSansId(); if ($utilisateur !== false) { foreach ($utilisateur as $param => $valeur) { $this->parametres[$param] = $valeur; } } } private function obtenirUtilisateurAvecId() { $auteurIdP = $this->bdd->proteger($this->parametres['auteur.id']); $requete = "SELECT id_utilisateur AS 'auteur.id', nom AS 'auteur.nom', prenom AS 'auteur.prenom', courriel AS 'auteur.courriel' ". 'FROM del_utilisateur '. "WHERE id_utilisateur = $auteurIdP ". ' -- '.__FILE__.' : '.__LINE__; $utilisateur = $this->bdd->recuperer($requete); return $utilisateur; } private function obtenirUtilisateurSansId() { $nomP = $this->bdd->proteger($this->parametres['auteur.nom']); $prenomP = $this->bdd->proteger($this->parametres['auteur.prenom']); $courrielP = $this->bdd->proteger($this->parametres['auteur.courriel']); $requete = "SELECT id_utilisateur AS 'auteur.id', nom AS 'auteur.nom', prenom AS 'auteur.prenom', ". "courriel AS 'auteur.courriel' ". 'FROM del_utilisateur '. "WHERE courriel = $courrielP AND nom = $nomP AND prenom = $prenomP ". ' -- '.__FILE__.' : '.__LINE__; $utilisateur = $this->bdd->recuperer($requete); return $utilisateur; } private function gererPropositionInitiale() { if ($this->verifierExistencePropositionInitiale() === false) { $this->creerPropositionInitiale(); // TODO : en cas d'échec de la création de la proposition ajouter un log... } } private function verifierExistencePropositionInitiale() { $idObsP = $this->bdd->proteger($this->parametres['observation']); $requete = 'SELECT COUNT(*) >= 1 AS existe '. 'FROM del_commentaire '. "WHERE ce_observation = $idObsP ". ' AND proposition_initiale = 1 '. ' -- '.__FILE__.' : '.__LINE__; $resultat = $this->bdd->recuperer($requete); return $resultat['existe'] == 1; } private function creerPropositionInitiale() { $idObsP = $this->bdd->proteger($this->parametres['observation']); $requete = 'INSERT IGNORE INTO del_commentaire '. '(ce_observation, 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) '. 'SELECT id_observation, ce_utilisateur, prenom, nom, courriel, nom_sel, '. "IF(nom_sel_nn = 0, NULL, nom_sel_nn), IF(nom_ret = '', NULL, nom_ret), IF(nom_ret_nn = 0, NULL, nom_ret_nn), ". "IF(nt = 0, NULL, nt), IF(famille = '', NULL, famille), IF(nom_sel_nn = 0, NULL, nom_referentiel), NOW(), '1' ". 'FROM del_observation AS do '. ' LEFT JOIN del_utilisateur AS du '. ' ON do.ce_utilisateur = du.id_utilisateur '. "WHERE id_observation = $idObsP ". ' -- '.__FILE__.' : '.__LINE__; $resultat = $this->bdd->executer($requete); return $resultat; } private function insererCommentaire() { $champs = $this->creerEnteteChamps(); $values = $this->creerClauseValues(); $requete = "INSERT INTO del_commentaire (date, $champs) VALUES (NOW(), $values) ". ' -- '.__FILE__.' : '.__LINE__; $retour = $this->bdd->executer($requete); if ($retour == null) { $msgTpl = "Erreur inopinée lors de l'insertion du commentaire lié à l'observation «%s»."; $msg = sprintf($msgTpl, $this->parametres['observation']); throw new Exception($msg, RestServeur::HTTP_CODE_ERREUR); } $idCommentaire = $this->bdd->recupererIdDernierAjout(); return $idCommentaire; } private function creerEnteteChamps() { return $this->creerSuiteChampsOuValeurs('champs'); } private function creerClauseValues() { return $this->creerSuiteChampsOuValeurs('valeurs'); } private function creerSuiteChampsOuValeurs($mode) { $suite = array(); foreach ($this->mapping as $nomChampBdd => $nomAttributSortie) { if (isset($this->parametres[$nomAttributSortie]) && $this->parametres[$nomAttributSortie] != null) { if ($mode == 'valeurs') { $suite[] = $this->bdd->proteger($this->parametres[$nomAttributSortie]); } else if ($mode == 'champs') { $suite[] = $nomChampBdd; } else { $msg = "Erreur interne : mauvais paramètre passé à la méthode 'creerSuiteChampsOuValeurs'"; throw new Exception($msg, RestServeur::HTTP_CODE_ERREUR); } } } return implode(', ', $suite); } private function tenterEnrichissementTaxonomique() { if($this->commentaireEstPropositionSansNn()) { // TODO: utiliser le référentiel de l'obs si celui-ci // n'est pas fourni dans le commentaire et prendre le résultat // si celui-ci est unique $referentiel = $this->parametres['nom_referentiel']; $requete = urlencode($this->parametres['nom_sel']); $url = sprintf($this->conteneur->getParametre('nomstaxons.url_autocompletion_tpl'), $referentiel, $requete); $restClient = $this->conteneur->getRestClient(); // Un retour vide est possible (un cas normal où il n'y a pas de résultat) // mais il fait planter le retour du service si on active l'affichage des erreurs // donc on passe sciemment les erreurs sous silence (car cette erreur n'en est pas une) $resultatJson = @$restClient->consulter($url); $resultats = json_decode($resultatJson, true); // On ne fait l'affectation que si l'on est sur (donc si un seul résultat) if (isset($resultats['resultat']) && count($resultats['resultat']) == 1) { $info = array_pop($resultats['resultat']); $this->parametres['nom_sel_nn'] = $info['num_nom']; } } } private function commentaireEstPropositionSansNn() { // Pas besoin de tester si c'est vide, normalement verifierParametres // l'a déjà fait au-dessus return isset($this->parametres['nom_sel']) && isset($this->parametres['nom_referentiel']) && !isset($this->parametres['nom_sel_nn']); } }