Subversion Repositories eFlore/Applications.moissonnage

Rev

Rev 31 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 31 Rev 34
Line 1... Line 1...
1
<?php
1
<?php
Line -... Line 2...
-
 
2
 
-
 
3
/**
-
 
4
 * 
-
 
5
 * Classe principale du web service qui peut traiter des requetes provenant d'un navigateur web
-
 
6
 * (stations dans bbox ou observations sur un point), ou d'un client SIG via appel au protocole/service WFS
-
 
7
 * (demande d'observations par stations selon des filtres optionnels). Le web service analyse et verifie
-
 
8
 * les parametres de l'URL de la requete qu'il recoit. S'ils sont tous valides, il va appeler une autre classe
-
 
9
 * pour recuperer les informations demandees dans les differentes sources de donnees.
-
 
10
 * Les donnees recuperees sont ensuite combinees si plusieurs sources sont demandees et mises en forme
-
 
11
 * au format de sortie. Les formats de sortie utilises sont le GeoJSON (extension de JSON pour les donnees
-
 
12
 * geographiques) en destination des navigateurs web et le GML adapte au service WFS pour les clients SIG.
-
 
13
 * Dans le cas ou des erreurs sont levees, le web service renvoie un message d'erreur expliquant le probleme
-
 
14
 * recnontre dans son fonctionnement.
-
 
15
 * 
-
 
16
 * 
-
 
17
 * @package framework-0.4
-
 
18
 * @author Alexandre GALIBERT <alexandre.galibert@tela-botanica.org>
-
 
19
 * @license GPL v3 <http://www.gnu.org/licenses/gpl.txt>
-
 
20
 * @license CECILL v2 <http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt>
-
 
21
 * @version $Id$
-
 
22
 * @copyright 2013 Tela Botanica (accueil@tela-botanica.org)
-
 
23
 *
-
 
24
 */
2
 
25
 
Line 3... Line 26...
3
class Commun {
26
class Commun {
-
 
27
	
4
	
28
	
5
	
29
	private $parametres = array();
-
 
30
	private $ressources = array();
-
 
31
	private $nomSource = '';
-
 
32
	private $nomService = '';
-
 
33
	
Line 6... Line -...
6
	private $parametres;
-
 
7
	private $nomSource;
34
	private $verificateur = null;
Line 8... Line 35...
8
	private $nomService;
35
	private $parametresRecherche = null;
9
	
36
	private $retour = array();
10
	private $verificateur;
37
	
-
 
38
	const MIME_WFS = 'text/xml';
-
 
39
	
-
 
40
	
-
 
41
	public function consulter($ressources, $parametres) {
-
 
42
		$this->recupererRessourcesEtParametres($ressources, $parametres);
-
 
43
		$retour = null;
-
 
44
		if (in_array("wfs", $ressources)) {
-
 
45
			$retour = $this->traiterRequeteWfs();
-
 
46
		} else {
-
 
47
			$retour = $this->traiterRequeteNavigateur();
-
 
48
		}
-
 
49
		return $retour;
-
 
50
	}
-
 
51
	
-
 
52
	
11
	private $parametresRecherche;
53
	
-
 
54
	/*********************************************/
-
 
55
	// Verification parametres URL non-WFS
-
 
56
	
-
 
57
	private function traiterRequeteWfs() {
-
 
58
		$retour = null;
-
 
59
		try {
-
 
60
			$this->parametresRecherche = new StdClass();
-
 
61
			$this->traiterParametreOperation();
-
 
62
			if ($this->parametresRecherche->operation != 'GetCapabilities') {
-
 
63
				$this->traiterParametreSource();
-
 
64
			}
-
 
65
			if ($this->parametresRecherche->operation == 'GetFeature') {
-
 
66
				$retour = $this->getFeature();
-
 
67
			} else {
-
 
68
				$formateurWfs = new FormateurWfs();
-
 
69
				$nomMethode = 'formater'.$this->parametresRecherche->operation;
-
 
70
				$parametre = isset($this->parametresRecherche->sources)
-
 
71
					? $this->parametresRecherche->sources : null;
-
 
72
				$retour = new ResultatService();
-
 
73
				$retour->mime = self::MIME_WFS;
-
 
74
				$retour->corps = $formateurWfs->$nomMethode($parametre);
-
 
75
			}
-
 
76
		} catch (Exception $erreur) {
-
 
77
			$formateurWfs = new FormateurWfs();
-
 
78
			$retour = new ResultatService();
-
 
79
			$retour->mime = self::MIME_WFS;
-
 
80
			$retour->corps = $formateurWfs->formaterException($erreur);
-
 
81
		}
-
 
82
		return $retour;
-
 
83
	}
-
 
84
	
-
 
85
	private function getFeature() {
-
 
86
		if (array_key_exists('bbox', $this->parametres)) {
-
 
87
			$this->traiterParametreBbox();
-
 
88
		} elseif (array_key_exists('filter', $this->parametres)) {
-
 
89
			$this->traiterParametreFilter();
-
 
90
		}
-
 
91
		$this->recupererStationsWfs();
-
 
92
		$formateurWfs = new FormateurWfs();
-
 
93
		$retour = new ResultatService();
-
 
94
		$retour->mime = self::MIME_WFS;
-
 
95
		$retour->corps = $formateurWfs->formaterGetFeature($this->retour, $this->parametresRecherche->sources);
-
 
96
		return $retour;
-
 
97
	}
-
 
98
	
-
 
99
	private function traiterParametreOperation() {
-
 
100
		if ($this->verifierExistenceParametre('request')) {
-
 
101
			if (!$this->estOperationWfsAutorisee()) {
-
 
102
				$message = "L'opération '".$this->parametres['request']."' n'est pas autorisée.\n".
-
 
103
					"Les opérations suivantes sont permises par le service : ".Config::get('operations_wfs');
-
 
104
				throw new Exception($message, RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE);
-
 
105
			} else {
-
 
106
				$this->parametresRecherche->operation = $this->parametres['request'];
-
 
107
			}
-
 
108
		}
-
 
109
	}
-
 
110
		
-
 
111
	private function verifierExistenceParametre($nomParametre) {
-
 
112
		$estParametreExistant = false;
-
 
113
		if (!array_key_exists($nomParametre, $this->parametres)) {
-
 
114
			$message = "Le paramètre nom de l'opération '{$nomParametre}' ".
-
 
115
				"n'a pas été trouvé dans la liste des paramètres.";
-
 
116
			throw new Exception($message, RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE);
-
 
117
		} else {
-
 
118
			$estParametreExistant = true;
-
 
119
		}
-
 
120
		return $estParametreExistant;
-
 
121
	}
-
 
122
	
-
 
123
	private function estOperationWfsAutorisee() {
-
 
124
		$operationsWfsService = explode(',' , Config::get('operations_wfs'));
-
 
125
		return (in_array($this->parametres['request'], $operationsWfsService));
-
 
126
	}
-
 
127
	
12
	
128
	private function traiterParametreSource() {
-
 
129
		// le parametre source (typename) est optionnel par defaut
-
 
130
		if (array_key_exists('typename', $this->parametres)) {
-
 
131
			$sources = explode(',', $this->parametres['typename']);
-
 
132
			$estSourceValide = true;
-
 
133
			foreach ($sources as $source) {
-
 
134
				if (!$this->verifierExistenceSourcesDonnees($source)) {
-
 
135
					$message = "Source de donnees '{$source}' indisponible. Les sources disponibles sont : ".
-
 
136
						Config::get('sources_dispo');
-
 
137
					$estSourceValide = false;
-
 
138
					throw new Exception($message, RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE);
-
 
139
				}
-
 
140
			}
-
 
141
			if ($estSourceValide) {
-
 
142
				$this->parametresRecherche->sources = $sources;
-
 
143
			}
-
 
144
		}
-
 
145
	}
-
 
146
	
-
 
147
	private function traiterParametreBbox() {
-
 
148
		$bboxVerifiee = $this->verifierCoordonneesBbox($this->parametres['bbox']);
-
 
149
		if (is_array($bboxVerifiee) && count($bboxVerifiee) == 4) {
-
 
150
			$this->parametresRecherche->bbox = array($bboxVerifiee);
-
 
151
		}
-
 
152
	}
-
 
153
	
-
 
154
	private function verifierCoordonneesBbox($bbox) {
-
 
155
		$bboxVerifiee = null;
-
 
156
		// verifier que la chaine de caracteres $bbox est une serie de chaque nombre decimaux
-
 
157
		// separes entre eux par une virgule
-
 
158
		if (preg_match('/^(-?\d{1,3}(.\d+)?,){3}(-?\d{1,3}(.\d+)?)$/', $bbox) == 0) {
-
 
159
			$message = "Format de saisie des coordonnees de la bounding box non valide.  Le service ".
-
 
160
					"n'accepte seulement qu'une serie de 4 nombre décimaux séparés par des virgules.";
-
 
161
			throw new Exception($message, RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE);
-
 
162
		} else {
-
 
163
			$coordonnees = explode(',', $bbox);
-
 
164
			$nomsIndexBbox = array("ouest", "sud", "est", "nord");
-
 
165
			$bbox = array();
-
 
166
			for ($i = 0; $i < count($coordonnees); $i ++) {
-
 
167
				$bbox[$nomsIndexBbox[$i]] = $coordonnees[$i];
-
 
168
			}
-
 
169
			// verifier que les coordonnees de chaque bord de la bbox sont valides
-
 
170
			if ($this->estUneBboxValide($bbox)) {
-
 
171
				$bboxVerifiee = $bbox;
-
 
172
			} else {
-
 
173
				$message = "Certaines coordonnées de la bounding box sont situés en dehors des limites ".
-
 
174
						"de notre monde";
-
 
175
				throw new Exception($message, RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE);
-
 
176
			}
-
 
177
		}
-
 
178
		return $bboxVerifiee;
-
 
179
	}
-
 
180
	
-
 
181
	private function estUneBboxValide($bbox) {
-
 
182
		$monde = array(
-
 
183
			'ouest' => floatval(Config::get('carte.limite_ouest')),
-
 
184
			'est'   => floatval(Config::get('carte.limite_est')),
-
 
185
			'sud'   => floatval(Config::get('carte.limite_sud')),
-
 
186
			'nord'  => floatval(Config::get('carte.limite_nord'))
-
 
187
		);
-
 
188
		return (floatval($bbox['ouest']) >= $monde['ouest']  && floatval($bbox['ouest']) <= $monde['est']
-
 
189
			&& floatval($bbox['est'])   >= $monde['ouest']  && floatval($bbox['est'])   <= $monde['est']
-
 
190
			&& floatval($bbox['nord'])  >= $monde['sud']    && floatval($bbox['nord'])  <= $monde['nord']
-
 
191
			&& floatval($bbox['sud'])   >= $monde['sud']    && floatval($bbox['sud'])   <= $monde['nord']);
-
 
192
	}
-
 
193
	
-
 
194
	private function traiterParametreFilter() {
-
 
195
		// la valeur du parametre filter est une chaine de texte qui compose en realite un document XML
-
 
196
		// plus d'infos a l'URL suivante : http://mapserver.org/fr/ogc/filter_encoding.html 
-
 
197
		$filtreTexte = $this->recupererTexteParametreFilter();
-
 
198
		$documentXML = new DomDocument();
-
 
199
		$documentXML->loadXML($filtreTexte);
-
 
200
		$filtres = $documentXML->documentElement->childNodes;
-
 
201
		for ($index = 0; $index < $filtres->length; $index ++) {
-
 
202
			$this->verifierFiltre($filtres->item($index));
-
 
203
		}
-
 
204
	}
-
 
205
	
-
 
206
	private function recupererTexteParametreFilter() {
-
 
207
		$parametresUrl = explode("&", $_SERVER['QUERY_STRING']);
-
 
208
		$filtreTexte = '';
-
 
209
		foreach ($parametresUrl as $parametre) {
-
 
210
			list($cle, $valeur) = explode("=", $parametre);
-
 
211
			if ($cle == 'filter') {
-
 
212
				$filtreTexte = rawurldecode($valeur);
-
 
213
			}
-
 
214
		}
-
 
215
		return $filtreTexte;
-
 
216
	}
-
 
217
	
-
 
218
	private function verifierFiltre($filtre) {
-
 
219
		$operateursAcceptes = explode(',', Config::get('operateurs_wfs'));
-
 
220
		$nomOperateur = $filtre->tagName;
-
 
221
		if (!in_array($nomOperateur, $operateursAcceptes)) {
-
 
222
			$message = "Le filtre '$nomOperateur' n'est pas pris en compte par le serrvice. ".
-
 
223
			"Les opérateurs acceptés sont :".implode(', ', $operateursAcceptes);
-
 
224
			throw new Exception($message, RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE);
-
 
225
		} else {
-
 
226
			if ($nomOperateur == 'BBOX') {
-
 
227
				$bboxUrl = $filtre->lastChild->nodeValue;
-
 
228
				$bboxVerifiee = $this->verifierCoordonneesBbox($bboxUrl);
-
 
229
				$this->parametresRecherche->bbox = array($bboxVerifiee);
-
 
230
			} else {
-
 
231
				$this->traiterOperateurScalaire($filtre);
-
 
232
			}
-
 
233
		}
-
 
234
	}
-
 
235
	
-
 
236
	private function traiterOperateurScalaire($filtre) {
-
 
237
		$nomOperateur = $filtre->tagName;
-
 
238
		$champ  = $filtre->childNodes->item(0)->nodeValue;
-
 
239
		if ($champ != Config::get('champ_filtrage_wfs')) {
-
 
240
			$message = "Le filtre ne peut pas être appliqué sur le champ '$champ'. ".
-
 
241
					"Il est seulement accepté sur le champ '".Config::get('champ_filtrage_wfs')."'";
-
 
242
			throw new Exception($message, RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE);
-
 
243
		} else {
-
 
244
			$valeur = $filtre->childNodes->item(1)->nodeValue;
-
 
245
			$operateur =  $nomOperateur == 'PropertyIsEqualTo' ? "=" : "LIKE";
-
 
246
			$this->parametresRecherche->filtre = array("champ" => $champ, "operateur" => $operateur,
-
 
247
					"valeur" => $valeur);
-
 
248
		}
-
 
249
	}
-
 
250
	
-
 
251
	private function recupererStationsWfs() {
-
 
252
		$this->nomMethode = $this->ressources[0];
-
 
253
		foreach ($this->parametresRecherche->sources as $source) {
-
 
254
			$source = trim($source);
-
 
255
			$resultat = $this->traiterSource($source);
-
 
256
			$this->ajouterResultat($resultat, $source);
-
 
257
		}
-
 
258
	}
-
 
259
	
-
 
260
	
-
 
261
		
-
 
262
	/*********************************************/
13
	
263
	// Verification parametres URL non-WFS
14
	public function consulter($ressources, $parametres) {
264
	
15
		$this->recupererRessourcesEtParametres($ressources, $parametres);
265
	private function traiterRequeteNavigateur() {
16
		$retour = null;
266
		$retour = null;
17
		try {
267
		try {
18
			if (!$this->verifierExistenceSourcesDonnees()) {
268
			if (!$this->estParametreSourceExistant()) {
19
				$message = "Source de donnees indisponible";
-
 
20
				throw new Exception($message, RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE);
269
				$message = "Le paramètre source de données n'a pas été indiqué.";
21
			} else {
270
				throw new Exception($message, RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE);
22
				$this->verifierParametres();
271
			} else {
23
				if ($this->ressources[0] == 'mailles') {
272
				$this->verifierParametres();
24
					$retour = $this->recupererMaillage();
273
				$listeSources = explode(',', $this->parametres['source']);
-
 
274
				foreach ($listeSources as $source) {
-
 
275
					$source = trim($source);
-
 
276
					$resultat = $this->traiterSource($source);
-
 
277
					$this->ajouterResultat($resultat, $source);
25
				} else {
278
				}
26
					$this->chargerNomSource();
279
			}
27
					$this->chargerNomService();
280
			$formateur = new FormateurJson();
28
					$retour = $this->executerServicePourSource();
281
			$nomMethode = 'formater'.ucfirst($this->ressources[0]);
29
				}
282
			$retour = new ResultatService();
Line 30... Line 283...
30
			}
283
			$retour->corps = $formateur->$nomMethode($this->retour);
31
		} catch (Exception $erreur) {
284
		} catch (Exception $erreur) {
32
			$retour = $erreur; 
285
			$retour = $erreur;
-
 
286
		}
-
 
287
		return $retour;
-
 
288
	}
-
 
289
	
-
 
290
	private function recupererRessourcesEtParametres($ressources, $parametres) {
-
 
291
		$this->ressources = $ressources;
-
 
292
		$this->parametres = array();
-
 
293
		foreach ($parametres as $nomParametre => $valeur) {
-
 
294
			$this->parametres[strtolower($nomParametre)] = $valeur;
-
 
295
		}
-
 
296
	}
33
		}
297
	
Line 34... Line 298...
34
		return $retour;
298
	private function estParametreSourceExistant() {
35
	}
299
		$parametreExiste = false;
36
	
300
		if (isset($this->parametres['source'])) {
37
	private function recupererRessourcesEtParametres($ressources, $parametres) {
-
 
38
		$this->ressources = $ressources;
301
			$parametreExiste = true;
39
		$this->parametres = $parametres;
-
 
40
	}
-
 
41
	
-
 
42
	private function verifierExistenceSourcesDonnees() {
-
 
43
		$sourcesDisponibles = explode(',', Config::get('sources_dispo'));
302
		}
44
		$estDisponible = false;
303
		return $parametreExiste;
45
		if (isset($this->parametres['source'])) {
304
	}
46
			if (in_array($this->parametres['source'], $sourcesDisponibles)) {
305
	
Line 61... Line 320...
61
		} else {
320
		} else {
62
			$this->recupererParametresRecherche();
321
			$this->recupererParametresRecherche();
63
		}
322
		}
64
	}
323
	}
Line -... Line 324...
-
 
324
	
-
 
325
	private function traiterSource($source) {
-
 
326
		$retour = array();
-
 
327
		if (!$this->verifierExistenceSourcesDonnees($source)) {
-
 
328
			$message = "Source de donnees indisponible";
-
 
329
			throw new Exception($message, RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE);
-
 
330
		} else {
-
 
331
			$this->chargerNomService($source);
-
 
332
			$retour = $this->executerServicePourSource($source);
-
 
333
		}
-
 
334
		return $retour;
-
 
335
	}
65
	
336
	
66
	private function recupererParametresRecherche() {
337
	private function recupererParametresRecherche() {
67
		$this->parametresRecherche = $this->verificateur->renvoyerResultatVerification();
338
		$this->parametresRecherche = $this->verificateur->renvoyerResultatVerification();
Line 68... Line 339...
68
	}
339
	}
69
	
340
	
70
	private function chargerNomSource() {
341
	private function chargerNomSource($source) {
71
		if (isset($this->parametres['source'])) {
342
		if (isset($this->parametres['source'])) {
72
			$this->nomSource = $this->parametres['source'];
343
			$this->nomSource = $this->parametres['source'];
73
		} else {
344
		} else {
74
			$this->nomSource = Config::get('source_defaut');
345
			$this->nomSource = Config::get('source_defaut');
Line 75... Line 346...
75
		}
346
		}
76
	}
347
	}
77
	
348
	
78
	private function chargerNomService() {
349
	private function chargerNomService($source) {
79
		$this->nomService = ucfirst($this->parametres['source']) . 'Formateur';
350
		$this->nomService = ($source == 'floradata' ? 'Floradata' : 'Moissonnage').'Formateur';
80
		Projets::chargerConfigurationSource($this->parametres['source']);
-
 
81
	}
-
 
82
	
-
 
83
	private function recupererMaillage() {
-
 
84
		$maillage = new Maillage($this->parametresRecherche->bbox, $this->parametresRecherche->zoom);
-
 
85
		$maillage->genererMaillesVides();
-
 
86
		$formateurJSON = new FormateurJson();
-
 
87
		return $formateurJSON->formaterMaillesVides($maillage->formaterSortie(true));
351
		Projets::chargerConfigurationSource($source);
88
	}
352
	}
89
	
353
		
90
	private function executerServicePourSource() {
354
	private function executerServicePourSource($source) {
91
		$objetTraitement = new $this->nomService($this->parametresRecherche);
355
		$objetTraitement = new $this->nomService($this->parametresRecherche, $source);
Line 92... Line 356...
92
		$methode = $this->genererNomMethodeAExecuter();
356
		$methode = $this->genererNomMethodeAExecuter();
93
		return $objetTraitement->$methode();
357
		return $objetTraitement->$methode();
94
	}
358
	}
Line -... Line 359...
-
 
359
	
-
 
360
	private function genererNomMethodeAExecuter() {
-
 
361
		return 'recuperer' . ucfirst($this->ressources[0]);
-
 
362
	}
-
 
363
	
-
 
364
	
-
 
365
	private function ajouterResultat(& $resultat, $source) {
-
 
366
		if (count($this->retour) > 0) {
-
 
367
			if ($this->ressources[0] == 'stations' && count($resultat) > 0
-
 
368
				&& $this->doitTransformerTypeDonnees($resultat)) {
-
 
369
				$this->combinerResultats($resultat, $source);
-
 
370
			} else {
-
 
371
				$this->retour = array_merge($this->retour, $resultat);
-
 
372
			}
-
 
373
		} else {
-
 
374
			$this->retour = array_merge($this->retour, $resultat);
-
 
375
		}
-
 
376
	}
-
 
377
	
-
 
378
	private function doitTransformerTypeDonnees(& $resultat) {
-
 
379
		return ($this->parametresRecherche->zoom <= Config::get('zoom_maximal_maillage') && 
-
 
380
			(($resultat[0]['type_site'] == 'MAILLE' || $this->retour[0]['type_site'] == 'MAILLE')
-
 
381
			|| ($resultat[0]['type_site'] != 'MAILLE' && $this->retour[0]['type_site'] != 'MAILLE'
-
 
382
				&& count($resultat) + count($this->retour) > Config::get('seuil_maillage')))
-
 
383
		);
-
 
384
	}
-
 
385
	
-
 
386
	private function combinerResultats(& $resultat, $source) {
-
 
387
		$maillage = new Maillage($this->parametresRecherche->bbox, $this->parametresRecherche->zoom, $source);
-
 
388
		$maillage->genererMaillesVides();
-
 
389
		if ($resultat[0]['type_site'] == 'MAILLE') {
-
 
390
			$maillage->ajouterMailles($resultat);
-
 
391
		} else {
-
 
392
			$maillage->ajouterStations($resultat);
-
 
393
		}
-
 
394
		if ($this->retour[0]['type_site'] == 'MAILLE') {
-
 
395
			$maillage->ajouterMailles($this->retour);
-
 
396
		} else {
95
	
397
			$maillage->ajouterStations($this->retour);
Line 96... Line 398...
96
	private function genererNomMethodeAExecuter() {
398
		}
97
		return 'recuperer' . ucfirst($this->ressources[0]);
399
		$this->retour = $maillage->formaterSortie();