Subversion Repositories eFlore/Projets.eflore-projets

Rev

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

Rev Author Line No. Line
6 jpm 1
<?php
2
/**
3
* Description :
4
* Classe ZoneGeo.php fournit des informations sur un ensemble de lieux à une échelle donnée.
15 jpm 5
* Le but étant de fournir un ensemble minimal d'information comprenant :
6
* un identifiant (numérique ou alphanumérique sous forme de ChatMot si possible), un nom, une region et
6 jpm 7
* éventuellement une relation hiérarchique avec un autre terme (=classe).
8
* Si l'url finit par /zone-geo on retourne une liste de zones (seulement les 100 premières par défaut).
9
* L'url peut contenir des paramètres optionnels passés après le ? : /zone-geo?param1=val1&param2=val2&...
15 jpm 10
*
11
* Les paramètres de requête disponibles sont : masque, masque.code, masque.nom, masque.region , recherche,
6 jpm 12
* distinct, retour.format, navigation.depart et navigation.limite.
15 jpm 13
*
6 jpm 14
* Encodage en entrée : utf8
15
* Encodage en sortie : utf8
16
* @package framework-v3
15 jpm 17
* @author Delphine Cauquil <delphine@tela-botanica.org>
6 jpm 18
* @author Jennifer Dhé <jennifer.dhe@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 1.0
22
* @copyright 1999-${year} Tela Botanica (accueil@tela-botanica.org)
23
*/
24
 
25
class ZoneGeo extends Commun {
15 jpm 26
 
6 jpm 27
	protected $service = 'zone-geo';
15 jpm 28
 
6 jpm 29
	/**
30
	 * Permet de stocker la requete formulée : /zone-geo | /zone-geo/#id | /zone-geo/#id/champ | /zone-geo/#id/relations
15 jpm 31
	 * Est remplit au cours de l'analyse des ressources (traiterRessources()), par défaut, a la valeur du service.
6 jpm 32
	 * Est utilisée principalement pr déterminer le format du tableau à retourner.	 */
33
	protected $format_reponse = 'zone-geo';
15 jpm 34
 
35
	/** Variables constituant les parametres de la requete SQL (champ, condition, group by, limit) remplie
6 jpm 36
	 * selon ressources et paramètres	 */
37
	protected $requete_champ = ' * ';
38
	protected $requete_condition = '';
15 jpm 39
	protected $limite_requete = array(
6 jpm 40
		'depart' => 0,
41
		'limite' => 100
42
	);
15 jpm 43
 
6 jpm 44
	/** Stockage des ressources et paramétres */
45
	protected $table_ressources = array();
46
	protected $table_param = array();
47
	/**
15 jpm 48
	 * Precise la contenance plus ou moins précise du tableau à retourner :
49
	 *  - min = les données présentes dans la table
6 jpm 50
	 *  - max = les données de la table + les informations complémentaires (pour les identifiants et les codes)
15 jpm 51
	 *  - oss = la liste des nom_sci (uniquement pour noms et taxons)
6 jpm 52
	 */
53
	protected $retour_format = 'max';
15 jpm 54
	/** Valeur du paramètre de requete recherche :
55
	 *  - stricte : le masque est passé tel quel à l'opérateur LIKE.
56
	 *  - etendue : ajout automatique du signe % à la place des espaces et en fin de masque avec utilisation de LIKE.
6 jpm 57
	 *  - floue : recherche tolérante vis-à-vis d'approximations ou d'erreurs (fautes d'orthographe par exemple) */
58
	protected $recherche;
15 jpm 59
 
6 jpm 60
	/** Permet de stocker le tableau de résultat (non encodé en json) */
61
	protected $table_retour = array();
62
	/** Stocke le nombre total de résultats de la requete principale. Est calculée lors de l'assemblage de la requete */
63
	protected $total_resultat;
15 jpm 64
 
65
	// +-----------------------------------------------------------------------------------------------------+
66
	public function traiterParametres() {
67
		if (isset($this->parametres) && !empty($this->parametres)) {
68
			$this->table_param = $this->parametres;
69
 
70
			//	masque : filtre la liste en fonction d'un masque de recherche portant sur le code, le nom ou la region.
71
			//	masque.code : filtre uniquement sur le code. masque.nom : filtre uniquement sur le nom.
72
			//	masque.region : filtre uniquement sur la region.
73
			if (isset($this->parametres['recherche']) && $this->parametres['recherche'] != '') {
74
				$this->recherche = $this->parametres['recherche'];
6 jpm 75
			}
15 jpm 76
 
77
			foreach ($this->parametres as $param => $valeur) {
6 jpm 78
				switch ($param) {
15 jpm 79
					case 'masque' :
80
						$this->ajouterLeFiltreMasque('masque', $valeur);
81
						break;
82
					case 'masque.code' :
83
						$this->ajouterLeFiltreMasque('codet', $valeur);
84
						break;
85
					case 'masque.nom' :
86
						$this->ajouterLeFiltreMasque('nom', $valeur);
87
						break;
88
					case 'masque.statut' :
89
						$this->ajouterLeFiltreMasque('codet_statut', $valeur);
90
						break;
91
					case 'retour.format' :
92
						$this->retour_format = $valeur;
93
						break;
94
					case 'navigation.depart' :
95
						$this->limite_requete['depart'] = $valeur;
96
						break;
97
					case 'navigation.limite' :
98
						$this->limite_requete['limite'] = $valeur;
99
						break;
100
					case 'recherche' :
101
						break;
102
					default						:
103
						$p = 'Erreur dans les paramètres de recherche de votre requête : '.
104
							'</br> Le paramètre " '.$param.' " n\'existe pas.';
105
							$this->renvoyerErreur(RestServeur::HTTP_CODE_MAUVAISE_REQUETE, $p);	break;
6 jpm 106
				}
107
			}
108
		}
109
	}
15 jpm 110
 
6 jpm 111
	public function ajouterLeFiltreMasque($nom_champ, $valeur) {
112
		if ($nom_champ == 'codet') {
113
			$this->requete_condition[] .= $nom_champ.' = '.$this->getBdd()->proteger($valeur);
114
		} else {
115
			if ($this->recherche == 'floue') {
116
				if ($nom_champ == 'masque') {
117
					$this->requete_condition[] = ' ( codet = '.$this->getBdd()->proteger($valeur)
118
						.' OR (SOUNDEX(nom_francais) = SOUNDEX(\''.$valeur.'\')'
119
						.' OR SOUNDEX(REVERSE(nom_francais)) = SOUNDEX(REVERSE(\''.$valeur.'\')) OR '
120
							.'SOUNDEX(nom_anglais) = SOUNDEX(\''.$valeur.'\')'
121
						.' OR SOUNDEX(REVERSE(nom_anglais)) = SOUNDEX(REVERSE(\''.$valeur.'\'))) '
122
						.' OR ( SOUNDEX(codet_statut) = SOUNDEX(\''.$valeur.'\')'
123
						.' OR SOUNDEX(REVERSE(codet_statut)) = SOUNDEX(REVERSE(\''.$valeur.'\')) '
124
						.')) ';
125
				} elseif ($nom_champ == 'nom') {
126
					$this->requete_condition[] = '(SOUNDEX(nom_francais) = SOUNDEX(\''.$valeur.'\')'
15 jpm 127
						.' OR SOUNDEX(REVERSE(nom_francais)) = SOUNDEX(REVERSE(\''.$valeur.'\'))) OR
6 jpm 128
						(SOUNDEX(nom_anglais) = SOUNDEX(\''.$valeur.'\')'
129
						.' OR SOUNDEX(REVERSE(nom_anglais)) = SOUNDEX(REVERSE(\''.$valeur.'\'))) ';
130
				} else {
131
					$this->requete_condition[] = '(SOUNDEX('.$nom_champ.') = SOUNDEX(\''.$valeur.'\')'
132
						.' OR SOUNDEX(REVERSE('.$nom_champ.')) = SOUNDEX(REVERSE(\''.$valeur.'\'))) ';
133
				}
134
			} else {
135
				if ($this->recherche == 'etendue') {
136
					$valeur = str_replace(' ','%', $valeur);
137
					$valeur .= '%';
138
				}
15 jpm 139
 
6 jpm 140
				if ($nom_champ == 'masque') {
141
					$this->requete_condition[] = '(codet = '.$this->getBdd()->proteger($valeur)
142
						.' OR nom_francais LIKE '.$this->getBdd()->proteger($valeur)
143
						.' OR nom_anglais LIKE '.$this->getBdd()->proteger($valeur)
144
						.' OR codet_statut LIKE '.$this->getBdd()->proteger($valeur).')';
145
				} elseif ($nom_champ == 'nom') {
146
					$this->requete_condition[] = '(nom_francais LIKE '.$this->getBdd()->proteger($valeur).' OR '
147
						.'nom_anglais LIKE '.$this->getBdd()->proteger($valeur).') ';
148
				} else {
149
					$this->requete_condition[] = $nom_champ.' LIKE '.$this->getBdd()->proteger($valeur);
150
				}
151
			}
152
		}
153
	}
15 jpm 154
 
155
	// +-----------------------------------------------------------------------------------------------------+
156
	public function traiterRessources() {
157
		if (isset($this->ressources) && !empty($this->ressources)) {
158
			$this->table_ressources = $this->ressources;
6 jpm 159
			if (isset($this->table_ressources[0]) && !empty($this->table_ressources[0])) {
160
				//requete = /zone-geo/#id
161
				$this->traiterRessourceId();
162
				if (isset($this->table_ressources[1]) && !empty($this->table_ressources[1])) {
163
					//requete = /zone-geo/#id/#champ ou /zone-geo/#id/relations
164
					$this->traiterRessourceChampOuRelations();
165
				}
166
			}
167
		}
168
	}
15 jpm 169
 
6 jpm 170
	public function traiterRessourceId() {
171
		//requete : /zone-geo/#id (ex : /zone-geo/7)
172
		if ($this->table_ressources[0]) {
173
			$this->requete_condition[] = ' codet = '.$this->getBdd()->proteger($this->table_ressources[0]);
174
			$this->format_reponse .= '/id';
175
		} else {
176
			$r = 'Erreur dans les ressources de votre requête : </br> La ressource " '.$this->table_ressources[0].
177
				' " n\'existe pas.';
15 jpm 178
			$this->renvoyerErreur(RestServeur::HTTP_CODE_MAUVAISE_REQUETE, $r);
6 jpm 179
		}
180
	}
15 jpm 181
 
182
 
6 jpm 183
	public function traiterRessourceChampOuRelations() {
184
		if ($this->table_ressources[1] == 'relations') {
185
			$r = 'Erreur dans les ressources de votre requête : </br> La ressource " '.$this->table_ressources[1].
186
				' " n\'existe pas.';
187
			$this->renvoyerErreur(RestServeur::HTTP_CODE_MAUVAISE_REQUETE, $r);
188
		} else {
189
			$this->format_reponse .= '/champ';
190
		}
191
	}
15 jpm 192
 
193
// +-------------------------------------------------------------------------------------------------------------------+
6 jpm 194
	public function assemblerLaRequete() {
15 jpm 195
		//assemblage de la requete :
6 jpm 196
		$requete = 	' SELECT '.$this->requete_champ.
197
			' FROM '.$this->table
198
			.$this->formerRequeteCondition()
199
			.$this->formerRequeteLimite();
200
		return $requete;
201
	}
15 jpm 202
 
203
	//ajout d'une limite seulement pour les listes (pas plus de 100 resultats retournés pr les requetes
6 jpm 204
	// suivantes : /zone-geo et /zone-geo/#id/relations)
205
	public function formerRequeteLimite() {
206
		if ($this->format_reponse != 'zone-geo') {
15 jpm 207
			$this->requete_limite = '';
6 jpm 208
		} elseif (($depart = $this->limite_requete['depart']) > ($this->total_resultat = $this->recupererTotalResultat())) {
15 jpm 209
			//cas ou la requete presente un navigation.depart supérieur au nb total de resultats.
210
			$this->limite_requete['depart'] =
6 jpm 211
				(($nb - $this->limite_requete['limite']) < 0) ? 0 : ($nb - $this->limite_requete['limite']);
212
			$this->requete_limite = ' LIMIT '.$this->limite_requete['depart'].', '.$this->limite_requete['limite'];
213
		} else {
214
			$this->requete_limite = ' LIMIT '.$this->limite_requete['depart'].', '.$this->limite_requete['limite'];
215
		}
216
		return $this->requete_limite;
217
	}
15 jpm 218
 
6 jpm 219
	public  function formerRequeteCondition() {
220
		$condition = '';
15 jpm 221
		if ($this->requete_condition != null) {
6 jpm 222
			$condition = ' WHERE '.implode(' AND ', $this->requete_condition);
15 jpm 223
		}
6 jpm 224
		return $condition;
225
	}
15 jpm 226
 
6 jpm 227
	public function recupererTotalResultat() {
228
		//on récupère le nombre total de résultats de la requete (ex : le nombre d'id contenu dans la liste /zone-geo)
229
		$requete = 'SELECT count(*) as nombre FROM '
230
			.$this->table
231
			.$this->formerRequeteCondition();
232
		$res = $this->getBdd()->recuperer($requete);
15 jpm 233
 
6 jpm 234
		if ($res) {
235
			$total = $res['nombre'];
236
		} else {
237
			$t = 'Fonction recupererTotalResultat() : <br/>Données introuvables dans la base';
238
			$this->renvoyerErreur(RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE, $t);
239
		}
240
		return $total;
241
	}
15 jpm 242
 
243
// +-------------------------------------------------------------------------------------------------------------------+
244
	// determine en fct du service appelé (/zone-geo | /zone-geo/#id | /zone-geo/#id/champ |
6 jpm 245
	// /zone-geo/#id/relations) le format du tableau à retourner. Encode en json
246
	public function retournerResultatFormate($resultat) {
247
		$this->recupererTableConfig('correspondance_champs');
248
		switch ($this->format_reponse) {
249
			case 'zone-geo'				: $reponse = $this->formaterZoneGeo($resultat);				break;
250
			case 'zone-geo/id'			: $reponse = $this->formaterZoneGeoId($resultat[0]);		break;
251
			case 'zone-geo/id/champ'	: $reponse = $this->formaterZoneGeoIdChamp($resultat[0]);	break;
252
			default						:															break;
253
		}
254
		return $reponse;
255
	}
15 jpm 256
 
6 jpm 257
	public function formaterZoneGeo($resultat) {
258
		//on remplit la table $table_retour_json['entete']
259
		$this->table_retour['depart'] = $this->limite_requete['depart'];
260
		$this->table_retour['limite'] = $this->limite_requete['limite'];
261
		$this->table_retour['total']  = $this->total_resultat;
262
		$url = $this->formulerUrl($this->total_resultat, '/zone-geo');
15 jpm 263
		if (isset($url['precedent']) && $url['precedent'] != '') {
264
			$this->table_retour['href.precedent'] = $url['precedent'];
265
		}
266
		if (isset($url['suivant']) && $url['suivant'] != '') {
267
			$this->table_retour['href.suivant'] = $url['suivant'];
268
		}
6 jpm 269
		$table_retour_json['entete'] = $this->table_retour;
15 jpm 270
 
6 jpm 271
		//on remplit la table $table_retour_json['resultat']
272
		$this->table_retour = array();
273
		if (isset($this->table_param['masque_nom'])) $resultat = $this->trierRechercheFloue($this->table_param['masque_nom'], $resultat, 'nom_francais');
274
		foreach ($resultat as $tab) {
275
			foreach ($tab as $key => $valeur) {
276
				$valeur = rtrim($valeur);
277
				if ($valeur != '') {
278
					switch ($key) {
279
						case 'codet'		: $num = $valeur; $this->table_retour['code'] = $valeur;				break;
280
						case 'nom_francais' : $this->table_retour['nom'] = $valeur;									break;
281
						case 'nom_anglais'	: if ($tab['nom_francais'] == '') $this->table_retour['nom'] = $valeur;	break;
282
						case 'codet_statut' : $this->table_retour['statut'] = $valeur;								break;
283
						default				:																		break;
284
					}
285
				}
286
			}
287
			if ($this->retour_format == 'max') {
288
				$this->table_retour['href'] = $this->ajouterHref('zone-geo', $num);
289
			}
290
			$resultat_json[$num] = $this->table_retour;
291
			$this->table_retour = array();
292
		}
293
		$table_retour_json['resultat'] = $resultat_json;
294
		return $table_retour_json;
295
	}
15 jpm 296
 
6 jpm 297
	public function formaterZoneGeoId($resultat) {
298
		foreach ($resultat as $key => $valeur) {
299
			if ($valeur != '') {
300
				$this->afficherDonnees($key, $valeur);
15 jpm 301
			}
6 jpm 302
		}
303
		unset($this->table_retour['href']);
304
		return $this->table_retour;
305
	}
15 jpm 306
 
6 jpm 307
	public function formaterZoneGeoIdChamp($resultat) {
308
		//on recupère tous les resultats possibles
309
		$reponse = $this->formaterZoneGeoId($resultat);
310
		$this->table_retour = array();
311
		//on recupère les résultats demandés à partir du tableau de résultat complet
312
		$this->table_retour['id'] = $reponse['code'];
313
 
314
		$champs = explode(' ', $this->table_ressources[1]);
315
		foreach ($champs as $champ) {
316
			if ($champ == 'nom') $champ = 'nom.fr';
317
			if ($this->verifierValiditeChamp($champ)) {
318
				if (strrpos($champ, '.*') !== false) {
319
					$this->afficherPointEtoile($champ, $reponse);
320
				} else {
321
					if (isset($reponse[$champ])) {
322
						$this->table_retour[$champ] = $reponse[$champ];
323
					} else {
324
						$this->table_retour[$champ] = null;
325
					}
326
				}
327
			}
328
		}
329
		return $this->table_retour;
330
	}
15 jpm 331
 
6 jpm 332
	public function verifierValiditeChamp($champ) {
333
		preg_match('/^([^.]+)(\.([^.]+))?$/', $champ, $match);
334
		$champs_possibles = $this->correspondance_champs;
335
		$champs_possibles[] = 'nom.*';
15 jpm 336
 
6 jpm 337
		if (in_array($match[1], $champs_possibles)) {
338
			$validite = true;
339
		} elseif (in_array($match[0], $champs_possibles)) {
340
			$validite = true;
341
		} else {
342
			$champs_possibles = implode('</li><li>', $champs_possibles);
343
			$c = 'Erreur dans votre requête : </br> Le champ "'.$champ_possibles.'" n\'existe pas. '.
344
				'Les champs disponibles sont : <li>'.$champs_possibles.'</li>';
345
			$this->renvoyerErreur(RestServeur::HTTP_CODE_MAUVAISE_REQUETE, $c);
346
		}
347
		return $validite;
348
	}
15 jpm 349
 
6 jpm 350
	public function afficherPointEtoile($champ, $reponse) {
351
		preg_match('/^([^.]+\.)\*$/', $champ, $match);
352
		foreach ($reponse as $chp => $valeur) {
353
			if (strrpos($chp, $match[1]) !== false) {
354
				if ($valeur != '') {
355
					$this->table_retour[$chp] = $valeur;
356
				} else {
357
					$this->table_retour[$chp] = null;
358
				}
359
			}
360
		}
361
	}
15 jpm 362
 
6 jpm 363
	public function afficherDonnees($champ, $valeur) {
364
		if ($this->retour_format == 'max') {
365
			if ($champ == 'codet_statut') {
366
				$this->table_retour[$this->correspondance_champs[$champ]] = $valeur;
15 jpm 367
				$this->table_retour[$this->correspondance_champs[$champ].'.href'] =
6 jpm 368
					$this->ajouterHref('ontologies', 'masque.nom=Codet '.$valeur, '?');
369
			} else {
370
				$this->table_retour[$this->correspondance_champs[$champ]] = $valeur;
371
			}
372
		} else {
373
			$this->table_retour[$this->correspondance_champs[$champ]] = $valeur;
374
		}
375
	}
376
 
377
// +-------------------------------------------------------------------------------------------------------------------+
378
	/** Permet de retourner l'url http://tela-botanica.org/service:eflore:0.1/[projet]/[version_projet]/[service]/[ressource]:[valeur]
15 jpm 379
	 * @param $service : correspond au nom de la ressource à laquelle on souhaite acceder
380
	 * @param $val : correspond au paramètre de la ressource (ex :
6 jpm 381
	 * @param $projet : est remplit dans les cas suivants :
15 jpm 382
	 * 	- si le projet dans lequel se trouve l'information est différent de celui du service appelé
6 jpm 383
	 *  - si on souhaite rappeler le meme projet avec la meme ressource mais un parametre de ressource différent
384
	 */
385
	public function ajouterHref($service, $val, $separation = '/') {
386
		$val = $this->encoderUrl($val);
387
		if ($this->version_projet == '+') {
388
			$url = Config::get('url_service_base').Config::get('nom_projet').'/'.$service.$separation.$val;
389
		} else {
390
			$url = Config::get('url_service_base').Config::get('nom_projet').'/'.$this->version_projet.'/'.$service.$separation.$val;
391
		}
392
		return $url;
393
	}
15 jpm 394
 
6 jpm 395
	public function encoderUrl($url) {
396
		$url = str_replace(' ', '%20', $url);
397
		$url = str_replace('?', urlencode('?'), $url);
398
		return $url;
399
	}
400
}
401
?>