Subversion Repositories eFlore/Applications.del

Rev

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

Rev Author Line No. Line
1142 aurelien 1
<?php
2
/**
1813 jpm 3
 * Web service récupèrant toutes les données de la table del_obs_images
4
 * pour retourner une liste d'images associées à la détermination la plus probable.
1142 aurelien 5
 *
1813 jpm 6
 * Possibilité de ne renvoyer que les images les mieux notées pour un protocole donné.
7
 *
8
 * @category   DEL
9
 * @package    Services
10
 * @subpackage Determinations
11
 * @version    0.1
12
 * @author     Mathias CHOUET <mathias@tela-botanica.org>
13
 * @author     Jean-Pascal MILCENT <jpm@tela-botanica.org>
14
 * @author     Aurelien PERONNET <aurelien@tela-botanica.org>
15
 * @license    GPL v3 <http://www.gnu.org/licenses/gpl.txt>
16
 * @license    CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt>
17
 * @copyright  1999-2014 Tela Botanica <accueil@tela-botanica.org>
1142 aurelien 18
 */
19
 
20
class ListeImagesDeterminationsProbables {
1700 jpm 21
 
1168 aurelien 22
	private $indexImagesIds = array();
1142 aurelien 23
	private $conteneur;
24
	private $navigation;
25
	private $bdd;
1813 jpm 26
 
27
	private $erreurs = array();
1142 aurelien 28
	private $parametres = array();
1813 jpm 29
	private $protocoles = array();
1700 jpm 30
 
1813 jpm 31
	private $resultats = array();
32
	private $propositions = array();
33
	private $votes = array();
34
 
1142 aurelien 35
	public function __construct(Conteneur $conteneur = null) {
36
		$this->conteneur = $conteneur == null ? new Conteneur() : $conteneur;
37
		$this->navigation = $conteneur->getNavigation();
1793 jpm 38
		$this->bdd = $this->conteneur->getBdd();
1813 jpm 39
		$this->chargerProtocoles();
1142 aurelien 40
	}
1700 jpm 41
 
1813 jpm 42
	private function chargerProtocoles() {
43
		$requete = 'SELECT id_protocole FROM del_image_protocole -- '.__FILE__.' : '.__LINE__;
44
		$resultats = $this->bdd->recupererTous($requete);
45
		if ($resultats) {
46
			foreach ($resultats as $infos) {
47
				$this->protocoles[] = $infos['id_protocole'];
48
			}
49
			sort($this->protocoles);
1468 raphael 50
		}
1813 jpm 51
	}
1700 jpm 52
 
1813 jpm 53
	public function consulter($parametres) {
54
		$this->parametres = $parametres;
1143 aurelien 55
		$this->verifierParametres();
1700 jpm 56
 
1142 aurelien 57
		// Lancement du service
1813 jpm 58
		$infos = $this->chargerInfos();
59
		$this->modifierEnteteTotal();
60
		if ($infos) {
61
			$this->traiterResultats($infos);
62
			$this->completerResutlats();
1144 aurelien 63
		}
1700 jpm 64
 
1142 aurelien 65
		// Mettre en forme le résultat et l'envoyer pour affichage
66
		$resultat = new ResultatService();
1813 jpm 67
		$resultat->corps = array('entete' => $this->navigation->getEntete(), 'resultats' => $this->resultats);
1142 aurelien 68
		return $resultat;
69
	}
1700 jpm 70
 
71
	private function verifierParametres() {
1813 jpm 72
		$this->verifierParamProtocole();
73
		$this->verifierParamVote();
1144 aurelien 74
 
1813 jpm 75
		if (!empty($this->erreurs)) {
76
			$msg = "Erreur de configuration :\n".implode("\n\n", $this->erreurs);
77
			throw new Exception($msg, RestServeur::HTTP_CODE_MAUVAISE_REQUETE);
1142 aurelien 78
		}
1813 jpm 79
	}
1700 jpm 80
 
1813 jpm 81
	private function verifierParamProtocole() {
82
		if (isset($this->parametres['masque.protocole'])) {
83
			$protocoleExistant = in_array($this->parametres['masque.protocole'], $this->protocoles);
84
 
85
			if (!is_numeric($this->parametres['masque.protocole']) || $protocoleExistant === false) {
86
				$protocolesListe = implode(', ', $this->protocoles);
87
				$msg = "La valeur pour le protocole doit être un entier compris dans les numéros de protocole ".
88
					"existants : $protocolesListe";
89
				$this->erreurs[] = $msg;
90
			}
1142 aurelien 91
		}
1813 jpm 92
	}
1700 jpm 93
 
1813 jpm 94
	private function verifierParamVote() {
95
		if (isset($this->parametres['masque.valeur_min_vote'])) {
96
			$minVote = $this->parametres['masque.valeur_min_vote'];
97
			if (!is_numeric($minVote) || ($minVote < 0 && $minVote > 5)) {
98
				$this->erreurs[] = "La valeur minimum de valeur des votes doit être un entier compris entre 0 et 5.";
99
			}
1142 aurelien 100
		}
101
	}
1700 jpm 102
 
1813 jpm 103
	private function chargerInfos() {
104
		$whereClause = $this->getClauseWhere();
105
		$depart = $this->navigation->getDepart();
106
		$limite = $this->navigation->getLimite();
1464 raphael 107
 
1813 jpm 108
		$requete = 'SELECT SQL_CALC_FOUND_ROWS di.id_observation AS id_observation, nom_referentiel, nom_ret, '.
109
			'nom_ret_nn, nt, famille, ce_zone_geo, zone_geo, lieudit, station, milieu, date_observation, '.
110
			'di.mots_cles_texte AS mots_cles_texte, di.commentaire AS commentaire, '.
111
			'di.i_mots_cles_texte AS mots_cles_texte_image, date_transmission, di.id_image AS id_image, '.
112
			'di.ce_utilisateur AS ce_utilisateur, prenom, nom, courriel, di.nom_utilisateur, di.prenom_utilisateur, '.
113
			'di.courriel_utilisateur, nom_original, ce_protocole, moyenne, nb_votes, nb_tags '.
114
			'FROM v_del_image AS di '.
115
			'	LEFT JOIN del_utilisateur AS du '.
116
			'		ON du.id_utilisateur = IF(LENGTH(di.ce_utilisateur) > 5, 0, di.ce_utilisateur) '.
117
			'	LEFT JOIN del_image_stat AS ds ON (di.id_image = ds.ce_image) '.
118
			"$whereClause ".
119
			'GROUP BY id_image '.
120
			'ORDER BY moyenne '.
121
			"LIMIT $depart, $limite ".
122
			' -- '.__FILE__.' : '.__LINE__;
123
		// TODO : optimisation voir http://www.tela-botanica.org/wikini/DevInformatiques/wakka.php?wiki=AppliDelOptmisationVues
124
		return $this->bdd->recupererTous($requete);
125
	}
126
 
127
	private function getClauseWhere() {
1700 jpm 128
		$where = array();
1813 jpm 129
		if (isset($this->parametres['masque.protocole'])) {
130
			$protocoleIdP = $this->bdd->proteger($this->parametres['masque.protocole']);
131
			$where[] = "ds.ce_protocole = $protocoleIdP ";
132
		}
133
		if (isset($this->parametres['masque.valeur_vote_min'])) {
134
			$voteP = $this->bdd->proteger($this->parametres['masque.valeur_vote_min']);
135
			$where[] = "moyenne >= $voteP";
136
		}
137
		return (count($where) > 0) ? 'WHERE '.implode(' AND ', $where).' ' : '';
138
	}
1464 raphael 139
 
1813 jpm 140
	private function modifierEnteteTotal() {
141
		$requete = 'SELECT FOUND_ROWS() AS nbre -- '.__FILE__.' : '.__LINE__;
142
		$compte = $this->bdd->recuperer($requete);
143
		$total = ($compte !== false) ? (int) $compte['nbre'] : 0;
144
		$this->navigation->setTotal($total);
1464 raphael 145
	}
1700 jpm 146
 
1142 aurelien 147
	/**
148
	* Retourner un tableau d'images formaté en fonction des liaisons trouvées
1813 jpm 149
	* @param $infos les infos sur les images et observations
1142 aurelien 150
	* */
1813 jpm 151
	private function traiterResultats($infos) {
152
		foreach ($infos as $info) {
153
			$idImage = $info['id_image'];
154
			$index = $this->formaterIndexResultat($info);
1700 jpm 155
 
1813 jpm 156
			$this->obsIds[] = $info['id_observation'];
1168 aurelien 157
			$this->indexImagesIds[$idImage] = $index;
1813 jpm 158
			$this->resultats[$index] = array(
1700 jpm 159
				'id_image' => $idImage,
1813 jpm 160
				'id_observation' => $info['id_observation'],
161
				'auteur.intitule' => $this->formaterIntituleAuteur($info),
162
				'binaire.href' => $this->formaterBinaireHref($info),
163
				'determination.famille' => $info['famille'],
164
				'determination.referentiel' => $info['nom_referentiel'],
165
				'determination.ns' => $info['nom_ret'],
166
				'determination.nn' => $info['nom_ret_nn'],
167
				'determination.nt' => $info['nt'],
168
				'date_observation' => $info['date_observation'],
169
				'localite' => $this->formaterLieu($info),
170
				'mots_cles_image_cel' => $this->formaterMotsClesCel($info),
171
				'mots_cles_image_del' => ''
1142 aurelien 172
			);
173
		}
174
	}
1700 jpm 175
 
1813 jpm 176
	private function formaterIndexResultat($infos) {
177
		return $infos['id_image'].'-'.$infos['id_observation'];
178
	}
179
 
180
	private function formaterIntituleAuteur($infos) {
181
		if ($infos['ce_utilisateur'] == 0) {
182
			$infos['prenom'] = $infos['prenom_utilisateur'];
183
			$infos['nom'] = $infos['nom_utilisateur'];
184
		}
185
		$intitule = $infos['prenom'].' '.$infos['nom'];
186
		return $intitule;
187
	}
188
 
189
	private function formaterBinaireHref($infos) {
190
		return sprintf($this->conteneur->getParametre('determinations.url_image_tpl'), $infos['id_image']);
191
	}
192
 
193
	private function formaterLieu($infos) {
194
		$lieuFormate = '';
195
		if ($infos['ce_zone_geo']) {
196
			$lieu = $infos['zone_geo'];
197
			$id_zone_geo = $infos['ce_zone_geo'];
198
			if (strpos($infos['ce_zone_geo'], 'INSEE-C:') === 0) {
199
				$id_zone_geo = str_replace('INSEE-C:', '', $infos['ce_zone_geo']);
200
				$id_zone_geo = strlen($id_zone_geo) >= 5 ? substr($id_zone_geo, 0, 2) : $id_zone_geo;
201
			}
202
			$lieuFormate =  "$lieu ($id_zone_geo)";
203
		}
204
		return $lieuFormate;
205
	}
206
 
1142 aurelien 207
	/**
1813 jpm 208
	 * Formater les mots clés du cel en n'affichant que ceux faisant partie d'une liste définie dans le
209
	 * fichier de configuration.
210
	 *
211
	 * @param $infos le tableau contenant les infos sur une image.
212
	 * @return string la chaine filtrée
1700 jpm 213
	 */
1813 jpm 214
	private function formaterMotsClesCel($infos) {
215
		$motsClesAffiches = $this->conteneur->getParametreTableau('determinations.mots_cles_cel_affiches');
216
		$motsClesCel = explode(',', $infos['mots_cles_texte_image']);
217
		$motsCles = array_intersect($motsClesAffiches, $motsClesCel);
218
		return implode(',', $motsCles);
219
	}
1468 raphael 220
 
1813 jpm 221
	private function completerResutlats() {
222
		$this->chargerVotes();
223
		$this->chargerPropositions();
1468 raphael 224
 
1813 jpm 225
		$this->completerMotsCles();
1468 raphael 226
 
1813 jpm 227
		foreach ($this->resultats as $index => $infos) {
228
			if ($this->doitRemplacerObservationParProposition($index)) {
229
				$id_obs = $infos['id_observation'];
230
				$this->resultats[$index]['determination.famille'] = $this->propositions[$id_obs]['famille'];
231
				$this->resultats[$index]['determination.ns'] = $this->propositions[$id_obs]['nom_sel'];
232
				$this->resultats[$index]['determination.nn'] = $this->propositions[$id_obs]['nom_sel_nn'];
233
				$this->resultats[$index]['determination.nt'] = $this->propositions[$id_obs]['nt'];
234
			}
235
			$this->completerUrlFicheEflore($index);
236
		}
237
	}
1700 jpm 238
 
1813 jpm 239
	private function chargerVotes() {
240
		$idsObs = implode(',', $this->obsIds);
241
		$requete = 'SELECT ce_proposition, valeur, ce_utilisateur '.
242
			'FROM del_commentaire_vote '.
243
			'WHERE ce_proposition IN '.
244
			'( SELECT id_commentaire '.
245
			'	FROM del_commentaire '.
246
			"	WHERE ce_observation IN ($idsObs) AND nom_sel IS NOT NULL ) ".
247
			'ORDER BY ce_proposition '.
248
			' -- '.__FILE__.' : '.__LINE__;
249
		$resultats = $this->bdd->recupererTous($requete);
250
		if ($resultats !== false) {
251
			foreach ($resultats as $vote) {
252
				if (!isset($this->votes[$vote['ce_proposition']])) {
253
					$this->votes[$vote['ce_proposition']] = 0;
254
				}
255
				$valeur = ($vote['valeur'] == 1) ? 1 : -1;
256
				$this->votes[$vote['ce_proposition']] += is_numeric($vote['ce_utilisateur']) ? 3 * $valeur : $valeur;
1142 aurelien 257
			}
1700 jpm 258
		}
1813 jpm 259
	}
1700 jpm 260
 
1813 jpm 261
	private function chargerPropositions() {
262
		$idsObs = implode(',', $this->obsIds);
263
		$requete = 'SELECT * '.
264
			'FROM del_commentaire '.
265
			"WHERE ce_observation IN ($idsObs) ".
266
			'AND nom_sel IS NOT NULL '.
267
			' -- '.__FILE__.' : '.__LINE__;
268
		$resultats = $this->bdd->recupererTous($requete);
269
 
270
		foreach($resultats as $proposition) {
1700 jpm 271
			$id_proposition = $proposition['id_commentaire'];
272
			$id_obs = $proposition['ce_observation'];
1813 jpm 273
			$proposition['valeur'] = (isset($this->votes[$id_proposition])) ? $this->votes[$id_proposition] : -1;
1700 jpm 274
 
1813 jpm 275
			if (!isset($this->propositions[$id_obs])) {
276
				$this->propositions[$id_obs] = $proposition;
1700 jpm 277
			} else {
1813 jpm 278
				$score_actuel = $proposition['valeur'];
279
				$score_precedent = $this->propositions[$id_obs]['valeur'];
280
				if ($score_actuel >= $score_precedent) {
281
					$this->propositions[$id_obs] = $proposition;
282
				}
1142 aurelien 283
			}
1700 jpm 284
		}
1813 jpm 285
	}
1168 aurelien 286
 
1813 jpm 287
	private function completerMotsCles() {
288
		$idsImages = implode(',', array_keys($this->indexImagesIds));
289
		$requete = 'SELECT tag, ce_image '.
290
			'FROM del_image_tag '.
291
			"WHERE ce_image IN ($idsImages) ".
292
			'AND actif = 1 '.
293
			' -- '.__FILE__.' : '.__LINE__;
294
		$resultats = $this->bdd->recupererTous($requete);
1700 jpm 295
 
1813 jpm 296
		foreach ($resultats as $info) {
297
			$index = $this->indexImagesIds[$info['ce_image']];
298
			$tag = ($this->resultats[$index]['mots_cles_image_del'] != '') ? ','.$info['tag'] : $info['tag'];
299
			$this->resultats[$index]['mots_cles_image_del'] .= $tag ;
1700 jpm 300
		}
1142 aurelien 301
	}
1700 jpm 302
 
1813 jpm 303
	private function doitRemplacerObservationParProposition($index) {
304
		$idObs = $this->resultats[$index]['id_observation'];
305
		return ((isset($this->propositions[$idObs])
306
			&& $this->propositions[$idObs] != null
307
			&& $this->propositions[$idObs]['nom_sel_nn'] != 0)
308
			&& ($this->propositions[$idObs]['valeur'] > 0 || 	$this->resultats[$index]['determination.nn'] == 0)
1142 aurelien 309
		);
310
	}
1700 jpm 311
 
1813 jpm 312
	private function completerUrlFicheEflore($index) {
313
		if (isset($this->resultats[$index]['determination.nn'])) {
314
			$urlTpl = $this->conteneur->getParametre('determinations.url_fiche_eflore_tpl');
315
			$nn = $this->resultats[$index]['determination.nn'];
1142 aurelien 316
 
1813 jpm 317
			$this->resultats[$index]['url_fiche_eflore'] = sprintf($urlTpl, $nn);
1700 jpm 318
		}
1144 aurelien 319
	}
1813 jpm 320
}