Subversion Repositories eFlore/Applications.del

Rev

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

Rev Author Line No. Line
858 gduche 1
<?php
2
// declare(encoding='UTF-8');
3
/**
1793 jpm 4
 * Permet d'ajouter un commentaire.
858 gduche 5
 *
1795 jpm 6
 * @category   DEL
7
 * @package    Services
1793 jpm 8
 * @subpackage Commentaires
1795 jpm 9
 * @version    0.1
10
 * @author     Mathias CHOUET <mathias@tela-botanica.org>
11
 * @author     Jean-Pascal MILCENT <jpm@tela-botanica.org>
12
 * @author     Aurelien PERONNET <aurelien@tela-botanica.org>
13
 * @license    GPL v3 <http://www.gnu.org/licenses/gpl.txt>
14
 * @license    CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt>
15
 * @copyright  1999-2014 Tela Botanica <accueil@tela-botanica.org>
858 gduche 16
 */
17
 
18
class AjouterCommentaire {
1299 jpm 19
 
858 gduche 20
	private $conteneur;
21
	private $navigation;
22
	private $bdd;
23
	private $parametres = array();
1299 jpm 24
 
1795 jpm 25
	private $mapping = array();
1805 jpm 26
	private $erreurs = array();
858 gduche 27
 
1793 jpm 28
	public function __construct(Conteneur $conteneur) {
29
		$this->conteneur = $conteneur;
1795 jpm 30
		$this->navigation =  $this->conteneur->getNavigation();
1793 jpm 31
		$this->bdd = $this->conteneur->getBdd();
1795 jpm 32
 
33
		$this->mapping = $this->conteneur->getParametreTableau('commentaires.mapping');
858 gduche 34
	}
1299 jpm 35
 
1795 jpm 36
	public function ajouter($parametres) {
37
		$this->parametres = $parametres;
38
		$this->verifierParametres();
1299 jpm 39
 
1795 jpm 40
		$this->completerParametresUtilisateur();
41
		$this->gererPropositionInitiale();
1949 aurelien 42
		// Dernière chance de rattachement au référentiel d'un nom
43
		// sans nn (cas du copier-coller ou bien de l'appli tierce
44
		// qui envoie des infos incomplètes)
45
		$this->tenterEnrichissementTaxonomique();
1795 jpm 46
		$idCommentaireAjoute = $this->insererCommentaire();
1299 jpm 47
 
883 aurelien 48
		// Mettre en forme le résultat et l'envoyer pour affichage
858 gduche 49
		$resultat = new ResultatService();
1795 jpm 50
		$resultat->corps = array('id_commentaire' => $idCommentaireAjoute);
1299 jpm 51
 
858 gduche 52
		return $resultat;
53
	}
1299 jpm 54
 
2157 mathias 55
	/**
56
	 * Vérifie notamment que l'auteur du vote est désigné soit par un ID, soit
57
	 * par un triplet (nom, prénom, adresse courriel)
58
	 */
1795 jpm 59
	private function verifierParametres() {
858 gduche 60
		if (!isset($this->parametres['observation'])) {
1805 jpm 61
			$this->erreurs[] = "Impossible d'ajouter un commentaire sans identifiant d'observation (paramètre 'observation').";
1299 jpm 62
		}
63
 
874 gduche 64
		if (!isset($this->parametres['auteur.id'])) {
1805 jpm 65
			$this->verifierParamsAuteurAnonyme();
1299 jpm 66
		}
67
 
1805 jpm 68
		$this->verifierParamsNonVide();
69
 
70
		if (isset($this->parametres['nom_sel_nn']) && !isset($this->parametres['nom_referentiel'])) {
71
			$this->erreurs[] = "Si le paramètre «nom_sel_nn» est présent, le paramètre «nom_referentiel» doit l'être aussi.";
883 aurelien 72
		}
1299 jpm 73
 
1805 jpm 74
		if (!empty($this->erreurs)) {
75
			$msg = "Erreur de configuration :\n".implode("\n\n", $this->erreurs);
1795 jpm 76
			throw new Exception($msg, RestServeur::HTTP_CODE_MAUVAISE_REQUETE);
858 gduche 77
		}
78
	}
1299 jpm 79
 
1805 jpm 80
	private function verifierParamsAuteurAnonyme() {
81
		$paramsAuteur = array('auteur.nom', 'auteur.prenom', 'auteur.courriel');
82
		$paramsAuteurManquant = array();
83
		foreach ($paramsAuteur as $param) {
84
			if (!isset($this->parametres[$param])) {
85
				$paramsAuteurManquant[] = $param;
86
			}
87
		}
88
 
89
		if (!empty($paramsAuteurManquant)) {
90
			$msgAuteurTpl = "Si le parametre 'auteur.id' n'est pas utilisé, il est nécessaire d'indiquer les ".
91
			"nom (paramètre 'auteur.nom'), prénom (paramètre 'auteur.prenom') et courriel ".
92
			"(paramètre 'auteur.courriel') de l'auteur.\nLes paramètres suivant sont abscents : %s\n";
93
			$this->erreurs[] = sprintf($msgAuteurTpl, implode(', ', $paramsAuteurManquant));
94
		}
95
	}
96
 
97
	private function verifierParamsNonVide() {
98
		$paramsNonVide = array('nom_sel', 'nom_referentiel', 'nom_sel_nn');
99
		foreach ($paramsNonVide as $param) {
100
			if (isset($this->parametres[$param]) && trim($this->parametres[$param]) == '' ) {
101
				$this->erreurs[] = "S'il est présent le paramètre «$param» ne peut pas être vide.";
102
			}
103
		}
104
	}
105
 
2157 mathias 106
	/**
107
	 * Si l'auteur du vote est désigné par un ID, va chercher ses nom, prénom, courriel;
108
	 * s'il est désigné par un triplet (nom, prénom, adresse courriel), va chercher son ID
109
	 */
1795 jpm 110
	private function completerParametresUtilisateur() {
111
		$utilisateur =  (isset($this->parametres['auteur.id'])) ? $this->obtenirUtilisateurAvecId() : $this->obtenirUtilisateurSansId();
2157 mathias 112
		if ($utilisateur != false) {
1795 jpm 113
			foreach ($utilisateur as $param => $valeur) {
114
				$this->parametres[$param] = $valeur;
1299 jpm 115
			}
858 gduche 116
		}
1795 jpm 117
	}
1299 jpm 118
 
2157 mathias 119
	/**
120
	 * On suppose que si l'utilisateur envoie sa proposition avec un ID, c'est
121
	 * qu'il est connu d'IP, donc qu'on trouvera ses coordonnées dans
122
	 * del_utilisateur_infos
123
	 *
124
	 * @TODO valider cette hypothèse
125
	 */
1795 jpm 126
	private function obtenirUtilisateurAvecId() {
127
		$auteurIdP = $this->bdd->proteger($this->parametres['auteur.id']);
128
		$requete = "SELECT id_utilisateur AS 'auteur.id', nom AS 'auteur.nom', prenom AS 'auteur.prenom', courriel AS 'auteur.courriel' ".
2157 mathias 129
			'FROM del_utilisateur_infos '.
1795 jpm 130
			"WHERE id_utilisateur = $auteurIdP ".
131
			' -- '.__FILE__.' : '.__LINE__;
132
		$utilisateur = $this->bdd->recuperer($requete);
858 gduche 133
		return $utilisateur;
134
	}
1299 jpm 135
 
2157 mathias 136
	/**
137
	 * Pour un utilisateur désigné par un triplet (nom, prenom, adresse courriel), demande
138
	 * son ID à l'annuaire - vue la base de données (2017-03-24), aucun tuple ne contient
139
	 * une adresse courriel sans contenir d'ID, mais beaucoup ne contiennent ni l'un ni
140
	 * l'autre (code stupide, tentative de correction ajd)
141
	 */
1795 jpm 142
	private function obtenirUtilisateurSansId() {
143
		$nomP = $this->bdd->proteger($this->parametres['auteur.nom']);
144
		$prenomP = $this->bdd->proteger($this->parametres['auteur.prenom']);
145
		$courrielP = $this->bdd->proteger($this->parametres['auteur.courriel']);
1299 jpm 146
 
2157 mathias 147
		// Si l'utilisateur s'est déjà connecté à DeL au moins une fois, on récupère ses
148
		// nom et prénom connus dans la base; on lui interdit d'usurper sa propre identité
1299 jpm 149
		$requete = "SELECT id_utilisateur AS 'auteur.id', nom AS 'auteur.nom', prenom AS 'auteur.prenom', ".
1795 jpm 150
			"courriel AS 'auteur.courriel' ".
2157 mathias 151
			'FROM del_utilisateur_infos '.
152
			"WHERE courriel = $courrielP ".
1795 jpm 153
			' -- '.__FILE__.' : '.__LINE__;
154
		$utilisateur = $this->bdd->recuperer($requete);
2157 mathias 155
 
156
		// si l'utilisateur n'a pas été trouvé, on devrait aller le chercher dans
157
		// l'annuaire, au cas où il soit inscrit à TB mais ne se soit pas connecté
158
		// @TODO faire un appel au service annuaire/identite-par-courriel
159
 
1795 jpm 160
		return $utilisateur;
858 gduche 161
	}
1299 jpm 162
 
1795 jpm 163
	private function gererPropositionInitiale() {
1803 jpm 164
		if ($this->verifierExistencePropositionInitiale() === false) {
1795 jpm 165
			$this->creerPropositionInitiale();
166
			// TODO : en cas d'échec de la création de la proposition ajouter un log...
858 gduche 167
		}
168
	}
1299 jpm 169
 
1795 jpm 170
	private function verifierExistencePropositionInitiale() {
171
		$idObsP =  $this->bdd->proteger($this->parametres['observation']);
1299 jpm 172
		$requete = 'SELECT COUNT(*) >= 1 AS existe '.
173
			'FROM del_commentaire '.
1795 jpm 174
			"WHERE ce_observation = $idObsP ".
175
			'	AND proposition_initiale = 1 '.
176
			' -- '.__FILE__.' : '.__LINE__;
1251 aurelien 177
		$resultat = $this->bdd->recuperer($requete);
178
		return $resultat['existe'] == 1;
179
	}
1299 jpm 180
 
1795 jpm 181
	private function creerPropositionInitiale() {
182
		$idObsP =  $this->bdd->proteger($this->parametres['observation']);
2157 mathias 183
 
1795 jpm 184
		$requete = 'INSERT IGNORE INTO del_commentaire '.
1299 jpm 185
			'(ce_observation, ce_utilisateur, utilisateur_prenom, utilisateur_nom, utilisateur_courriel, '.
1301 jpm 186
			'nom_sel, nom_sel_nn, nom_ret, nom_ret_nn, nt, famille, nom_referentiel, date, proposition_initiale) '.
2157 mathias 187
			'SELECT id_observation, ce_utilisateur, prenom_utilisateur, nom_utilisateur, courriel_utilisateur, nom_sel, '.
1802 jpm 188
			"IF(nom_sel_nn = 0, NULL, nom_sel_nn), IF(nom_ret = '', NULL, nom_ret), IF(nom_ret_nn = 0, NULL, nom_ret_nn), ".
189
			"IF(nt = 0, NULL, nt), IF(famille = '', NULL, famille), IF(nom_sel_nn = 0, NULL, nom_referentiel), NOW(), '1' ".
1299 jpm 190
			'FROM del_observation AS do '.
1795 jpm 191
			"WHERE id_observation = $idObsP ".
192
			' -- '.__FILE__.' : '.__LINE__;
2157 mathias 193
 
1795 jpm 194
		$resultat = $this->bdd->executer($requete);
2157 mathias 195
 
1251 aurelien 196
		return $resultat;
197
	}
1299 jpm 198
 
1795 jpm 199
	private function insererCommentaire() {
200
		$champs = $this->creerEnteteChamps();
201
		$values = $this->creerClauseValues();
202
		$requete = "INSERT INTO del_commentaire (date, $champs) VALUES (NOW(), $values) ".
203
			' -- '.__FILE__.' : '.__LINE__;
1299 jpm 204
 
1795 jpm 205
		$retour = $this->bdd->executer($requete);
206
		if ($retour == null) {
207
			$msgTpl = "Erreur inopinée lors de l'insertion du commentaire lié à l'observation «%s».";
208
			$msg = sprintf($msgTpl, $this->parametres['observation']);
209
			throw new Exception($msg, RestServeur::HTTP_CODE_ERREUR);
858 gduche 210
		}
1299 jpm 211
 
1795 jpm 212
		$idCommentaire = $this->bdd->recupererIdDernierAjout();
213
		return $idCommentaire;
858 gduche 214
	}
1299 jpm 215
 
1795 jpm 216
	private function creerEnteteChamps() {
217
		return $this->creerSuiteChampsOuValeurs('champs');
218
	}
219
 
220
	private function creerClauseValues() {
221
		return $this->creerSuiteChampsOuValeurs('valeurs');
222
	}
223
 
224
	private function creerSuiteChampsOuValeurs($mode) {
225
		$suite = array();
226
		foreach ($this->mapping as $nomChampBdd => $nomAttributSortie) {
227
			if (isset($this->parametres[$nomAttributSortie]) && $this->parametres[$nomAttributSortie] != null) {
228
				if ($mode == 'valeurs') {
229
					$suite[] = $this->bdd->proteger($this->parametres[$nomAttributSortie]);
230
				} else if ($mode == 'champs') {
231
					$suite[] = $nomChampBdd;
232
				} else {
233
					$msg = "Erreur interne : mauvais paramètre passé à la méthode 'creerSuiteChampsOuValeurs'";
234
					throw new Exception($msg, RestServeur::HTTP_CODE_ERREUR);
235
				}
858 gduche 236
			}
237
		}
1795 jpm 238
		return implode(', ', $suite);
858 gduche 239
	}
1949 aurelien 240
 
241
	private function tenterEnrichissementTaxonomique() {
242
		if($this->commentaireEstPropositionSansNn()) {
1977 aurelien 243
			// TODO: utiliser le référentiel de l'obs si celui-ci
244
			// n'est pas fourni dans le commentaire et prendre le résultat
245
			// si celui-ci est unique
1949 aurelien 246
			$referentiel = $this->parametres['nom_referentiel'];
247
			$requete = urlencode($this->parametres['nom_sel']);
248
 
249
			$url = sprintf($this->conteneur->getParametre('nomstaxons.url_autocompletion_tpl'), $referentiel, $requete);
250
			$restClient = $this->conteneur->getRestClient();
251
			// Un retour vide est possible (un cas normal où il n'y a pas de résultat)
252
			// mais il fait planter le retour du service si on active l'affichage des erreurs
2210 arthur 253
			// donc on passe sciemment les erreurs sous silence (car cette erreur n'en est pas une)
254
			$resultatJson = @$restClient->consulter($url);
1949 aurelien 255
			$resultats = json_decode($resultatJson, true);
256
 
257
			// On ne fait l'affectation que si l'on est sur (donc si un seul résultat)
258
			if (isset($resultats['resultat']) && count($resultats['resultat']) == 1) {
259
				$info = array_pop($resultats['resultat']);
2210 arthur 260
				$this->parametres['nom_sel_nn'] = $info['num_nom'];
1949 aurelien 261
			}
262
		}
263
	}
264
 
265
	private function commentaireEstPropositionSansNn() {
266
		// Pas besoin de tester si c'est vide, normalement verifierParametres
267
		// l'a déjà fait au-dessus
268
		return isset($this->parametres['nom_sel'])
269
				&& isset($this->parametres['nom_referentiel'])
270
						&& !isset($this->parametres['nom_sel_nn']);
271
	}
1793 jpm 272
}