Subversion Repositories eFlore/Applications.del

Rev

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

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