Subversion Repositories eFlore/Applications.moissonnage

Rev

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

Rev Author Line No. Line
26 alex 1
<?php
2
 
3
/**
4
 *
5
 * Classe en charge de recuperer les donnees d'observation ou liees a leur localisation
6
 * Le jeu de donnees a interroger est celui utilise par l'application Carnet En Ligne
7
 * (http://www.tela-botanica.org/page:cel)
8
 *
9
 * On passera en parametre lors de la creation d'une instance un objet contenant la liste des criteres
10
 * qui vont restreindre le nombre de resultats a renvoyer
11
 *
12
 * Les deux operations suivantes peuvent etre utilisees dans les services :
13
 *   - recupererStations : va rechercher dans la base de donnees tous les points d'observations
14
 *     correspondant aux criteres de recherche demandes. La precision des lieux d'observation est
15
 *     soit un point precis, soit ramenee au niveau de la commune dans laquelle l'observation a ete faite
16
 *     En fonction du niveau de zoom et du nombre de resultats trouves, la presentation se fera
17
 *     soit par les points localisant les stations pour des niveaux de zoom eleves ou pour un nombre
18
 *     de stations inferieur a un seuil, ou par des mailles de 64*64 pixels dans le cas contraire
19
 *
20
 *   - recupererObservations : va rechercher dans la base de donnees les donnees sur des observations
21
 *     a partir des coordonnees longitude et latitude d'une station (+ des parametres additionnels)
22
 *
23
 * Les donnees seront renvoyees au format JSON
24
 *
25
 * @package framework-0.3
26
 * @author Alexandre GALIBERT <alexandre.galibert@tela-botanica.org>
27
 * @license GPL v3 <http://www.gnu.org/licenses/gpl.txt>
28
 * @license CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt>
29
 * @version $Id$
30
 * @copyright 2013 Tela Botanica (accueil@tela-botanica.org)
31
 *
32
 */
33
 
34
 
35
class FloradataFormateur {
36
 
37
	private $criteresRecherche;
38
	private $bdd;
39
 
40
 
41
	public function __construct($criteresRecherche) {
42
		$this->criteresRecherche = $criteresRecherche;
43
	}
44
 
45
	public function recupererStations() {
46
		$requeteSql = $this->construireRequeteStations();
47
		$stations = $this->getBdd()->recupererTous($requeteSql);
48
		$zoomMaxMaillage = Config::get('zoom_maximal_maillage');
49
		$seuilMaillage   = Config::get('seuil_maillage');
50
		$zoom = $this->criteresRecherche->zoom;
51
		$bbox = $this->criteresRecherche->bbox;
52
		// TODO: gérer une notion d'échelle plutot que de zoom (pour les clients SIG)
53
		if (count($stations) > $seuilMaillage && intval($zoom)<= $zoomMaxMaillage) {
54
			$maillage = new Maillage($bbox, $zoom);
55
			$maillage->genererMaillesVides();
56
			$maillage->ajouterPoints($stations);
57
			$stations = $maillage->formaterSortie();
58
		}
59
		$formateurJSON = new FormateurJson('floradata');
60
		$donneesFormatees = $formateurJSON->formaterStations($stations);
61
		return $donneesFormatees;
62
	}
63
 
64
	public function recupererObservations() {
65
		$requeteSql = $this->construireRequeteObservations();
66
		$observations = $this->getBdd()->recupererTous($requeteSql);
67
		$nomSite = $this->obtenirNomStation();
68
		$formateurJSON = new FormateurJson('floradata');
69
		$donneesFormatees = $formateurJSON->formaterObservations($observations, $nomSite);
70
		return $donneesFormatees;
71
	}
72
 
73
 
74
 
75
	// ------------------------------------------------------------------------ //
76
	// Fonctions de construction des criteres de recherches pour la requete SQL //
77
	// ------------------------------------------------------------------------ //
78
 
79
	private function getBdd() {
80
		if (!isset($this->bdd)) {
81
			$this->bdd = new Bdd();
82
		}
83
		$this->bdd->requeter("USE ".Config::get('bdd_nom'));
84
		return $this->bdd;
85
	}
86
 
87
	private function construireRequeteStations() {
31 alex 88
		$bbox = $this->criteresRecherche->bbox;
26 alex 89
		$selectTypeSite =
90
			"IF(".
91
				"(longitude IS NULL OR latitude IS NULL) ".
92
				"OR (longitude=0 AND latitude=0) ".
31 alex 93
				"OR (mots_cles_texte LIKE '%sensible%') ".
94
				"OR NOT (".
95
					"longitude BETWEEN ".$bbox['ouest']." AND ".$bbox['est']." ".
96
					"AND latitude BETWEEN ".$bbox['sud']." AND ".$bbox['nord'].
97
				")".
26 alex 98
				", 'COMMUNE', 'STATION'".
99
			")";
100
		$requete =
31 alex 101
			"SELECT COUNT(id_observation) AS observations, ce_zone_geo, zone_geo, station, ".
102
			"longitude, latitude, nom AS nom_commune,wgs84_longitude AS lng_commune, ".
103
			"wgs84_latitude AS lat_commune, ".$selectTypeSite." AS type_site ".
104
			"FROM cel_obs  LEFT JOIN cel_zones_geo cz ON ce_zone_geo=id_zone_geo ".
105
			"WHERE transmission=1 ".
26 alex 106
			$this->construireWhereDepartement().' '.
107
			$this->construireWhereAuteur().' '.
31 alex 108
			$this->construireWhereDate().' '.
26 alex 109
			$this->construireWhereReferentiel().' '.
110
			$this->construireWhereTaxon().' '.
111
			$this->construireWhereCoordonneesBbox().' '.
112
			"GROUP BY longitude, latitude, wgs84_longitude, wgs84_latitude";
113
		return $requete;
114
	}
115
 
116
	private function construireRequeteObservations() {
117
		$requete =
118
			"SELECT id_observation AS id_obs, nom_ret_nn AS nn, nom_ret AS nomSci, ".
31 alex 119
			"Date(date_observation) AS date, milieu AS lieu, nom_referentiel, ".
26 alex 120
			"Concat(prenom_utilisateur, ' ', nom_utilisateur) AS observateur, ce_utilisateur AS observateurId ".
121
			"FROM cel_obs WHERE transmission=1 ".
122
			$this->construireWhereAuteur().' '.
123
			$this->construireWhereReferentiel().' '.
31 alex 124
			$this->construireWhereDate().' '.
26 alex 125
			$this->construireWhereTaxon().' '.
126
			$this->construireWhereCoordonneesPoint().' '.
127
			"ORDER BY nom_ret, date, observateur";
128
		return $requete;
129
	}
130
 
31 alex 131
	protected function construireWhereTaxon() {
26 alex 132
		$sql = '';
133
		if (isset($this->criteresRecherche->taxon)) {
31 alex 134
			$taxons = $this->criteresRecherche->taxon;
135
			$criteres = array();
136
			foreach ($taxons as $taxon) {
137
				$nomRang = $this->getNomRang($taxon);
138
				if ($nomRang == 'genre') {
139
					$criteres[] = "famille=".$this->getBdd()->proteger($taxon['nom']);
140
				} else {
141
					$criteres[] = "nom_ret LIKE ".$this->getBdd()->proteger($taxon['nom']."%");
142
					if ($nomRang == 'espece') {
143
						$criteres = array_merge($criteres, $this->concatenerTaxonsSousEspeces($taxon));
144
					}
145
				}
26 alex 146
			}
31 alex 147
			$sql = "AND (".implode(' OR ',array_unique($criteres)).")";
26 alex 148
		}
149
		return $sql;
150
	}
151
 
31 alex 152
	protected function getNomRang($taxon) {
153
		$nomsRangs = array('famille', 'genre', 'espece', 'sous_espece');
154
		for ($index = 0; $index < count($nomsRangs)
155
		&& Config::get("rang.".$nomsRangs[$index]) != $taxon['rang']; $index ++);
156
		$position = $index == count($nomsRangs) ? count($nomsRangs)-1 : $index;
157
		return $nomsRangs[$position];
158
	}
159
 
160
	protected function concatenerTaxonsSousEspeces($taxon) {
161
		$referentiel = new Referentiel($this->criteresRecherche->referentiel, $taxon);
162
		$sousTaxons = $referentiel->recupererTaxonsSousEspeces();
163
		$criteres = array();
164
		foreach ($sousTaxons as $sousTaxon) {
165
			$criteres[] = "nom_ret LIKE ".$this->getBdd()->proteger($sousTaxon['nom']."%");
166
		}
167
		return $criteres;
168
	}
169
 
170
	protected function concatenerTaxonsFamilles($taxon) {
171
		$referentiel = new Referentiel($this->criteresRecherche->referentiel, $taxon);
172
		$sousTaxons = $referentiel->recupererTaxonsFamilles();
173
		$criteres = array();
174
		foreach ($sousTaxons as $sousTaxon) {
175
			$criteres[] = "nom_ret LIKE ".$this->getBdd()->proteger($sousTaxon['nom']."%");
176
		}
177
		return $criteres;
178
	}
179
 
26 alex 180
	private function construireWhereReferentiel() {
181
		$sql = '';
182
		if (isset($this->criteresRecherche->referentiel) && !isset($this->criteresRecherche->taxon)) {
183
			$referentiel = current(explode('_', $this->criteresRecherche->referentiel));
184
			$sql = "AND nom_referentiel LIKE ".$this->getBdd()->proteger($referentiel."%");
185
		}
186
		return $sql;
187
	}
188
 
189
	private function construireWhereDepartement() {
190
		$sql = '';
191
		if (isset($this->criteresRecherche->departement)) {
192
			$valeurs_a_proteger = $this->criteresRecherche->departement;
193
			foreach ($valeurs_a_proteger as $valeur) {
194
				$valeurs_protegees[] = "ce_zone_geo LIKE " . $this->getBdd()->proteger('INSEE-C:' . $valeur . '%');
195
			}
196
			$valeurs = implode(' OR ', $valeurs_protegees);
197
			$sql = "AND ($valeurs)";
198
		}
199
		return $sql;
200
	}
201
 
202
	private function construireWhereAuteur() {
203
		$sql = '';
204
		if (isset($this->criteresRecherche->auteur)) {
205
			$utilisateur = $this->getBdd()->proteger($this->criteresRecherche->auteur);
206
			$sql = "AND courriel_utilisateur = $utilisateur";
207
		}
208
		return $sql;
209
	}
210
 
31 alex 211
	private function construireWhereDate() {
212
		$sql = '';
213
		if (isset($this->criteresRecherche->nbJours)) {
214
			$nbJours = $this->criteresRecherche->nbJours;
215
			$sql = "AND (Datediff(Curdate(), date_creation)<={$nbJours})";
216
		} else {
217
			$sql = $this->construireWhereDateDebutEtFin();
218
		}
219
		return $sql;
220
	}
221
 
222
	private function construireWhereDateDebutEtFin() {
223
		$sql = '';
224
		$dateDebut = isset($this->criteresRecherche->dateDebut) ? $this->criteresRecherche->dateDebut : null;
225
		$dateFin   = isset($this->criteresRecherche->dateFin) ? $this->criteresRecherche->dateFin : null;
226
		if (!is_null($dateDebut) || !is_null($dateFin)) {
227
			$dateFin = !is_null($dateFin) ? $dateFin : date('Y-m-d');
228
			$condition = '';
229
			if ($dateDebut == $dateFin) {
230
				$condition = "Date(date_observation)=".$this->getBdd()->proteger($dateDebut);
231
			} elseif (is_null($dateFin)) {
232
				$condition = "Date(date_observation)>=".$this->getBdd()->proteger($dateDebut);
233
			} elseif (is_null($dateDebut)) {
234
				$condition = "Date(date_observation)<=".$this->getBdd()->proteger($dateFin);
235
			} else {
236
				$condition = "Date(date_observation) BETWEEN ".$this->getBdd()->proteger($dateDebut)." ".
237
						"AND ".$this->getBdd()->proteger($dateFin);
238
			}
239
			$sql = "AND ($condition)";
240
		}
241
		return $sql;
242
	}
243
 
26 alex 244
	private function construireWhereCoordonneesBbox() {
245
		$bbox = $this->criteresRecherche->bbox;
246
		$sql =
247
			"AND (".
248
				"(".
31 alex 249
					"latitude BETWEEN ".$bbox['sud']." AND ".$bbox['nord']." ".
250
					"AND longitude BETWEEN ".$bbox['ouest']." AND ".$bbox['est'].
26 alex 251
				") OR (".
31 alex 252
					"((longitude IS NULL OR latitude IS NULL) OR (longitude=0 AND latitude=0) ".
253
					"OR (longitude>180 AND latitude>90)) AND ".
26 alex 254
					"wgs84_longitude BETWEEN ".$bbox['ouest']." AND ". $bbox['est']." ".
255
					"AND wgs84_latitude BETWEEN ".$bbox['sud']." AND ".$bbox['nord'].
256
				")".
257
			")";
258
		return $sql;
259
	}
260
 
261
	private function construireWhereCoordonneesPoint() {
31 alex 262
		$longitude = $this->criteresRecherche->longitude;
263
		$latitude  = $this->criteresRecherche->latitude;
264
		$condition = "(longitude=".$longitude." AND latitude=".$latitude." ".
265
			"AND (mots_cles_texte IS NULL OR mots_cles_texte NOT LIKE '%sensible%'))";
266
		if ($this->criteresRecherche->typeSite == 'commune') {
267
			$commune = $this->obtenirCoordonneesCommune();
268
			$condition .=
269
				" OR (".
270
					"((longitude IS NULL OR latitude IS NULL) OR (longitude=0 AND latitude=0) ".
271
					"OR (longitude>180 AND latitude>90)) ".
272
					"AND ce_zone_geo=".$this->getBdd()->proteger($commune['id_zone_geo']).
273
				")";
26 alex 274
		}
275
		return "AND ($condition)";
276
	}
277
 
278
	private function obtenirCoordonneesCommune() {
279
		$requete = "SELECT id_zone_geo, nom FROM cel_zones_geo WHERE wgs84_longitude=".
280
		$this->criteresRecherche->longitude." AND wgs84_latitude=".$this->criteresRecherche->latitude;
281
		$commune = $this->getBdd()->recuperer($requete);
282
		if ($commune === false) {
283
			$commune = null;
284
		}
285
		return $commune;
286
	}
287
 
288
	private function obtenirNomStation() {
289
		// verifier si les coordonnees du point de requetage correspondent a une commune
290
		$station = $this->obtenirCoordonneesCommune();
291
		if (is_null($station)) {
292
			$requete = 'SELECT DISTINCT lieudit AS nom FROM cel_obs WHERE longitude='.
293
				$this->criteresRecherche->longitude.' AND latitude='.$this->criteresRecherche->latitude;
294
			$station = $this->getBdd()->recuperer($requete);
295
		}
296
		$nomStation = '';
297
		if ($station !== false) {
298
			$nomStation = trim($station['nom']);
299
		}
300
		return $nomStation;
301
	}
302
 
303
}
304
 
305
?>