Subversion Repositories eFlore/Projets.eflore-projets

Rev

Rev 831 | Rev 848 | 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 NomsVernaculaires.php fournit une liste de noms vernaculaires et leur liaison à la bdtfx
109 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 langue et
6 jpm 7
* une relation avec un taxon de la bdtfx.
8
* Si l'url finit par /noms-vernaculaires on retourne une liste de noms (seulement les 100 premières par défaut).
9
* L'url peut contenir des paramètres optionnels passés après le ? : /observations?param1=val1&param2=val2&...
109 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.
109 jpm 13
*
6 jpm 14
* Encodage en entrée : utf8
15
* Encodage en sortie : utf8
16
* @package framework-v3
109 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
*/
734 raphael 24
 
25
// Un caractère de concaténation entre le projet et le service.
26
// Ce caractère ne doit pas faire partie d'aucun des noms de service ou projet
27
define('RES_VAL_SEP', '@');
832 raphael 28
define('SPE_INDEX_NVJFL', '_result_ontologies' . RES_VAL_SEP . 'nvjfl');
734 raphael 29
 
6 jpm 30
class NomsVernaculaires extends Commun {
832 raphael 31
 
32
	static $onto_multi_support = array('conseil_emploi', 'genre');
33
	static $champ_infos = array(
729 raphael 34
		'taxon' => array('service' => 'taxons', 'ressource' => 'nt:', 'projet' => 'bdtfx', 'nom' => 'nom_sci',
35
						 // utilisés par ajouterChampsOntologieLigneResultat()
36
						 'intitule' => 'taxon.code', // intitulé du champ tel qu'il sera renvoyé en JSON
37
						 'bdd_champ' => 'num_taxon'), // intitulé du champ tel qu'il est présent dans l'enregistrement MySQL
38
		'conseil_emploi' => array('service' => 'ontologies', 'ressource' => 'numStatut:', 'projet' => 'nvjfl', 'nom' => 'nom',
39
								  'intitule' => 'conseil_emploi', 'bdd_champ' => 'num_statut'),
40
		'genre' => array('service' => 'ontologies', 'ressource' => 'genreNombre:', 'projet' => 'nvjfl', 'nom' => 'nom',
41
						 'intitule' => 'genre', 'bdd_champ' => 'num_genre'));
109 jpm 42
 
6 jpm 43
	protected $service = 'noms-vernaculaires';
109 jpm 44
 
6 jpm 45
	/**
46
	 * Permet de stocker la requete formulée : /noms-vernaculaires | /noms-vernaculaires/#id |
47
	 *  /noms-vernaculaires/#id/champ | /noms-vernaculaires/#id/relations
109 jpm 48
	 * Est remplit au cours de l'analyse des ressources (traiterRessources()), par défaut, a la valeur du service.
6 jpm 49
	 * Est utilisée principalement pr déterminer le format du tableau à retourner.	 */
109 jpm 50
	protected $format_reponse = 'noms-vernaculaires';
51
 
52
	/** Variables constituant les parametres de la requete SQL (champ, condition, limit) remplie
6 jpm 53
	 * selon ressources et paramètres */
54
	protected $requete_champ = array(' * ');
55
	protected $requete_condition = '';
56
	protected $limite_requete = array(
109 jpm 57
		'depart' => 0,
6 jpm 58
		'limite' => 100
59
	);
284 jpm 60
 
61
	protected $champ_tri = 'code_langue';
62
	protected $direction_tri = 'asc';
286 aurelien 63
 
64
	/**
65
	 * Indique les champs supplémentaires à retourner
66
	 *  - conseil_emploi = conseil d'emploi du nom vernaculaire
67
	 *  - genre = genre et nombre du nom
68
	 *  - taxon = nom retenu associé à ce nom
69
	 */
70
	protected $champs_supp = array();
109 jpm 71
 
6 jpm 72
	/**
109 jpm 73
	 * Precise la contenance plus ou moins précise du tableau à retourner :
74
	 *  - min = les données présentes dans la table
6 jpm 75
	 *  - max = les données de la table + les informations complémentaires (pour les identifiants et les codes)
76
	 *  - oss = la liste des nom_sci (uniquement pour noms et taxons) */
77
	protected $retour_format = 'max';
109 jpm 78
	/** Valeur du paramètre de requete recherche :
79
	 *  - stricte : le masque est passé tel quel à l'opérateur LIKE.
80
	 *  - etendue : ajout automatique du signe % à la place des espaces et en fin de masque avec utilisation de LIKE.
6 jpm 81
	 *  - floue : recherche tolérante vis-à-vis d'approximations ou d'erreurs (fautes d'orthographe par exemple) */
82
	protected $recherche;
284 jpm 83
 
6 jpm 84
	/** Permet de stocker le tableau de résultat (non encodé en json) */
85
	protected $table_retour = array();
86
	/** Stocke le nombre total de résultats de la requete principale. Est calculée lors de l'assemblage de la requete */
87
	protected $total_resultat;
536 gduche 88
 
89
	private $config;
90
 
563 aurelien 91
	public function __construct($config) {
536 gduche 92
		$this->config = is_null($config) ? Config::get('NomsVernaculaires') : $config;
93
	}
109 jpm 94
 
95
	//+------------------------------------------------------------------------------------------------------+
6 jpm 96
	// créer une condition en fonction du paramétre
109 jpm 97
	public function traiterParametres() {
98
		if (isset($this->parametres) && !empty($this->parametres)) {
99
 
100
			if (isset($this->parametres['recherche']) && $this->parametres['recherche'] != '') {
101
				$this->recherche = $this->parametres['recherche'];
6 jpm 102
			}
109 jpm 103
			foreach ($this->parametres as $param => $valeur) {
6 jpm 104
				switch ($param) {
109 jpm 105
					case 'masque' :
284 jpm 106
						$this->ajouterFiltreMasque('nom_vernaculaire', $valeur);
109 jpm 107
						break;
108
					case 'masque.nt' :
284 jpm 109
						$this->ajouterFiltreMasque('num_taxon', $valeur);
109 jpm 110
						break;
111
					case 'masque.nv' :
284 jpm 112
						$this->ajouterFiltreMasque('nom_vernaculaire', $valeur);
109 jpm 113
						break;
114
					case 'masque.lg' :
284 jpm 115
						$this->ajouterFiltreMasque('code_langue', $valeur);
109 jpm 116
						break;
117
					case 'masque.cce' :
284 jpm 118
						$this->ajouterFiltreMasque('num_statut', $valeur);
109 jpm 119
						break;
120
					case 'retour.format' :
121
						$this->retour_format = $valeur;
122
						break;
123
					case 'navigation.depart' :
124
						$this->limite_requete['depart'] = $valeur;
125
						break;
126
					case 'navigation.limite' :
127
						$this->limite_requete['limite'] = $valeur;
128
						break;
286 aurelien 129
					case 'retour.champs' :
130
						$this->champs_supp = explode(',',$valeur);
131
					break;
109 jpm 132
					case 'recherche' :
133
						break;
152 delphine 134
					case 'version.projet' :
135
						break;
109 jpm 136
					default :
137
						$p = 'Erreur dans les paramètres de recherche de votre requête : '.
138
							'</br> Le paramètre " '.$param.' " n\'existe pas.';
139
							$this->renvoyerErreur(RestServeur::HTTP_CODE_MAUVAISE_REQUETE, $p);
6 jpm 140
				}
141
			}
142
		}
143
	}
109 jpm 144
 
284 jpm 145
	public function ajouterFiltreMasque($nom_champ, $valeur) {
6 jpm 146
		if ($nom_champ == 'num_taxon') { // si il s'agit d'un chiffre
147
			$this->requete_condition[] = $nom_champ.' = '.$this->getBdd()->proteger($valeur);
148
		} else {
149
			if ($this->recherche == 'floue') {
150
				$this->requete_condition[] = '(SOUNDEX('.$nom_champ.') = SOUNDEX(\''.$valeur.'\')'
151
					.' OR SOUNDEX(REVERSE('.$nom_champ.')) = SOUNDEX(REVERSE(\''.$valeur.'\'))) ';
152
			} else {
153
				if ($this->recherche == 'etendue') {
180 delphine 154
					$valeur = '%'.str_replace(' ','% ', $valeur);
6 jpm 155
					$valeur .= '%';
156
				}
157
				$this->requete_condition[] = $nom_champ.' LIKE '.$this->getBdd()->proteger($valeur);
158
			}
159
		}
160
	}
161
 
109 jpm 162
	//+------------------------------------------------------------------------------------------------------+
6 jpm 163
	// en fonction de la présence des ressources modifie requete_champ et requete_condition
109 jpm 164
	public function traiterRessources() {
165
		if (isset($this->ressources) && !empty($this->ressources)) {
166
			if (isset($this->ressources[0]) && !empty($this->ressources[0])) {
6 jpm 167
				$this->traiterRessourceId(); // ajoute condition id=#valeur
109 jpm 168
				if (isset($this->ressources[1]) && !empty($this->ressources[1])) {
160 delphine 169
					$this->traiterRessourceChamp(); //modifie requete_champ ou requete_condition
6 jpm 170
				}
171
			}
172
		} else { //rajoute distinct pour ne pas avoir plusieurs fois le même nom
173
			$this->requete_champ = array('distinct(id)', 'nom_vernaculaire ');
174
		}
175
	}
109 jpm 176
 
6 jpm 177
	//requete : /noms-vernaculaires/#id (ex : /noms-vernaculaires/7)
178
	public function traiterRessourceId() {
109 jpm 179
		if (is_numeric($this->ressources[0])) {
180
			$this->requete_condition[] = ' id = '.$this->getBdd()->proteger($this->ressources[0]);
6 jpm 181
			$this->format_reponse .= '/id';
160 delphine 182
		} elseif ($this->ressources[0] == 'attributions') {
183
			$this->format_reponse .= '/attributions';
6 jpm 184
		} else {
109 jpm 185
			$r = 'Erreur dans les ressources de votre requête : </br> La ressource " '.$this->ressources[0].
6 jpm 186
				' " n\'existe pas.';
109 jpm 187
			$this->renvoyerErreur(RestServeur::HTTP_CODE_MAUVAISE_REQUETE, $r);
6 jpm 188
		}
189
	}
109 jpm 190
 
191
 
160 delphine 192
	public function traiterRessourceChamp() {
193
		$this->format_reponse .= '/champ';
194
		$this->analyserChamp();
6 jpm 195
	}
109 jpm 196
 
6 jpm 197
	public function analyserChamp() {
198
		$this->requete_champ = array();
199
		$this->recupererTableConfig('champs_possibles');// s'il y a plusieurs champs correspondant au champ demandé ils sont séparé par des |
109 jpm 200
		$champs = explode(' ', $this->ressources[1]);
6 jpm 201
		foreach ($champs as $champ) {
202
			preg_match('/^([^.]+)(\.([^.]+))?$/', $champ, $match);
203
			if (isset($this->champs_possibles[$match[1]])) {
204
				$this->requete_champ[] = str_replace('|', ', ', $this->champs_possibles[$match[1]]);
205
			} elseif (isset($this->champs_possibles[$match[0]])) {
206
				$this->requete_champ[] = str_replace('|', ', ', $this->champs_possibles[$match[0]]);
207
			} else {
208
				$champs_possibles = implode('</li><li>', array_keys($this->champs_possibles));
209
				$c = 'Erreur dans votre requête : </br> Le champ "'.$champ_possibles.'" n\'existe pas. '.
210
					'Les champs disponibles sont : <li>'.$champs_possibles.'</li> et leurs déclinaisons (ex. ".code").';
211
				$this->renvoyerErreur(RestServeur::HTTP_CODE_MAUVAISE_REQUETE, $c);
212
			}
213
		}
214
	}
109 jpm 215
 
216
	//+------------------------------------------------------------------------------------------------------+
6 jpm 217
	public function assemblerLaRequete() {
218
		$requete = ' SELECT '.$this->formerRequeteChamp().
659 delphine 219
					', CASE num_statut WHEN "" THEN 1 ELSE 0 END AS is_null '.
6 jpm 220
					' FROM '.$this->table
659 delphine 221
					.$this->formerRequeteCondition().
222
					' ORDER BY is_null ASC, num_statut ASC '
6 jpm 223
					.$this->formerRequeteLimite();
224
		return $requete;
225
	}
109 jpm 226
 
6 jpm 227
	public  function formerRequeteChamp() {
228
		if (in_array('*', $this->requete_champ)) {
229
			$champ = ' * ';
230
		} else {
231
			$champ = implode(', ', $this->requete_champ);
232
		}
233
		return $champ;
234
	}
109 jpm 235
 
6 jpm 236
	public  function formerRequeteCondition() {
237
		$condition = '';
109 jpm 238
		if ($this->requete_condition != null) {
6 jpm 239
			$condition = ' WHERE '.implode(' AND ', $this->requete_condition);
109 jpm 240
		}
6 jpm 241
		return $condition;
242
	}
109 jpm 243
 
244
	//ajout d'une limite seulement pour les listes (pas plus de 100 resultats retournés pr les requetes
6 jpm 245
	// suivantes : /noms-vernaculaires et /noms-vernaculaires/#id/relations)
246
	public function formerRequeteLimite() {
247
		if (in_array($this->format_reponse , array($this->service.'/id', $this->service.'/id/champs'))) {
109 jpm 248
			$this->requete_limite = '';
6 jpm 249
		} elseif (($depart = $this->limite_requete['depart']) > ($this->total_resultat = $this->recupererTotalResultat())) {
109 jpm 250
			$this->limite_requete['depart'] =
6 jpm 251
				(($this->total_resultat - $this->limite_requete['limite']) < 0) ? 0 : ($this->total_resultat - $this->limite_requete['limite']);
109 jpm 252
			$this->requete_limite = ' LIMIT '.$this->limite_requete['depart'].', '.$this->limite_requete['limite'];
6 jpm 253
		} else {
109 jpm 254
			$this->requete_limite = ' LIMIT '.$this->limite_requete['depart'].', '.$this->limite_requete['limite'];
6 jpm 255
		}
256
		return $this->requete_limite;
257
	}
109 jpm 258
 
6 jpm 259
	//on récupère le nombre total de résultats de la requete (ex : le nombre d'id contenu dans la liste /noms-vernaculaires)
260
	public function recupererTotalResultat() {
160 delphine 261
		$distinct = ($this->format_reponse == 'noms-vernaculaires/attributions') ? 'id' : 'distinct(id)';
262
		$requete = 'SELECT count('.$distinct.') as nombre FROM '
6 jpm 263
			.$this->table
264
			.$this->formerRequeteCondition();
265
		$res = $this->getBdd()->recuperer($requete);
109 jpm 266
 
6 jpm 267
		if ($res) {
268
			$total = $res['nombre'];
269
		} else {
160 delphine 270
			$t = 'Fonction recupererTotalResultat() : <br/>Données introuvables dans la base '.$requete;
6 jpm 271
			$this->renvoyerErreur(RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE, $t);
272
		}
273
		return $total;
274
	}
109 jpm 275
 
276
	//+------------------------------------------------------------------------------------------------------+
277
	// determine en fct du service appelé (/noms-vernaculaires | /noms-vernaculaires/#id | /noms-vernaculaires/#id/champ |
6 jpm 278
	// /noms-vernaculaires/#id/relations) le format du tableau à retourner.
279
	public function retournerResultatFormate($resultat) {
280
		$this->recupererTableConfig('correspondance_champs');
281
		switch ($this->format_reponse) {
132 aurelien 282
			case 'noms-vernaculaires'				:
283
				$reponse = ($this->retour_format == 'oss') ? $this->formaterEnOss($resultat) : $this->formaterNomsVernaculaires($resultat);			break;
160 delphine 284
			case 'noms-vernaculaires/attributions'	: $reponse = $this->formaterNomsVernaculairesAttributions($resultat);	break;
6 jpm 285
			case 'noms-vernaculaires/id'			: $reponse = $this->formaterNomsVernaculairesId($resultat);			break;
286
			case 'noms-vernaculaires/id/champ'		: $reponse = $this->formaterNomsVernaculairesIdChamp($resultat);	break;
287
			default									:																	break;
288
		}
289
		return $reponse;
290
	}
608 mathilde 291
 
292
	public function ajouterJsonEnTeteNV() {
293
		$table_retour_json['masque'] = $this->recupererMasque();
294
		$table_retour_json['depart'] = $this->limite_requete['depart'];
295
		$table_retour_json['limite'] = $this->limite_requete['limite'];
296
		$table_retour_json['total']  = $this->total_resultat;
6 jpm 297
		$url = $this->formulerUrl($this->total_resultat, '/noms-vernaculaires');
608 mathilde 298
		if (isset($url['precedent']) && $url['precedent'] != '') {
299
			$table_retour_json['href.precedent'] = $url['precedent'];
6 jpm 300
		}
608 mathilde 301
		if (isset($url['suivant']) && $url['suivant']   != '') {
302
			$table_retour_json['href.suivant']   = $url['suivant'];
152 delphine 303
		}
608 mathilde 304
		return $table_retour_json;
305
	}
306
 
307
	public function ajouterJsonResultatNV($resultat) {
6 jpm 308
		foreach ($resultat as $tab) {
309
			foreach ($tab as $key => $valeur) {
310
				if ($valeur != '') {
311
					switch ($key) {
312
						case 'id'				: $num = $valeur;								break;
313
						case 'nom_vernaculaire'	: $this->table_retour['nom'] = $valeur;			break;
314
						default					:												break;
315
					}
316
				}
317
			}
608 mathilde 318
		    if ($this->retour_format == 'max') $this->table_retour['href'] = $this->ajouterHref('noms-vernaculaires', $num);
6 jpm 319
			$resultat_json[$num] = $this->table_retour;
320
			$this->table_retour = array();
321
		}
608 mathilde 322
		return  $resultat_json;
323
	}
109 jpm 324
 
608 mathilde 325
 
326
	public function formaterNomsVernaculaires($resultat) {
327
		$table_retour_json['entete'] = $this->ajouterJsonEnTeteNV();
328
		$resultat = $this->hierarchiserResultat($resultat);
329
		$table_retour_json['resultat'] = $this->ajouterJsonResultatNV($resultat);
6 jpm 330
		return $table_retour_json;
331
	}
132 aurelien 332
 
608 mathilde 333
	public function hierarchiserResultat($resultat) {
334
		//tri recherche floue
335
		if (isset($this->parametres['masque.nv'])) {
336
			$resultat = $this->trierRechercheFloue($this->parametres['masque.nv'], $resultat, 'nom_vernaculaire');
337
		}
338
		if (isset($this->parametres['masque'])) {
339
			$resultat = $this->trierRechercheFloue($this->parametres['masque'], $resultat, 'nom_vernaculaire');
340
		}
341
		return $resultat;
342
	}
343
 
160 delphine 344
	public function recupererMasque() {
345
		$tab_masque = array();
346
		foreach ($this->parametres as $param=>$valeur) {
347
			if (strstr($param, 'masque') != false) {
348
				$tab_masque[] = $param.'='.$valeur;
349
			}
350
		}
351
		$masque = implode('&', $tab_masque);
352
		return $masque;
353
	}
354
 
132 aurelien 355
	public function formaterEnOss($resultat) {
356
		$table_nom = array();
357
		$oss = '';
358
		foreach ($resultat as $tab) {
359
			if (isset($tab['nom_vernaculaire']) ) {
360
				if (!in_array($tab['nom_vernaculaire'], $table_nom)) {
361
					$table_nom[] = $tab['nom_vernaculaire'];
362
					$oss [] = $tab['nom_vernaculaire'];
363
				}
364
			}
365
		}
366
		if (isset($this->masque)) $masque = implode('&', $this->masque);
367
		else $masque = 'Pas de masque';
368
		$table_retour_oss = array($masque, $oss);
369
		return $table_retour_oss;
370
	}
160 delphine 371
 
372
	public function formaterNomsVernaculairesAttributions($resultat) {
373
		//on remplie la table $table_retour_json['entete']
374
		$table_retour_json['entete']['masque'] = $this->recupererMasque();
375
		$table_retour_json['entete']['depart'] = $this->limite_requete['depart'];
376
		$table_retour_json['entete']['limite'] = $this->limite_requete['limite'];
377
		$table_retour_json['entete']['total']  = $this->total_resultat;
378
		$url = $this->formulerUrl($this->total_resultat, '/noms-vernaculaires/attributions');
729 raphael 379
		if (!empty($url['precedent'])) {
160 delphine 380
			$table_retour_json['entete']['href.precedent'] = $url['precedent'];
381
		}
729 raphael 382
		if (!empty($url['suivant'])) {
160 delphine 383
			$table_retour_json['entete']['href.suivant']   = $url['suivant'];
384
		}
284 jpm 385
		foreach ($resultat as &$tab) {
730 raphael 386
			$nnv = $tab['num_nom_vernaculaire'];
387
			$resultat_json[$nnv]['id'] = $tab['id'];
388
			$resultat_json[$nnv]['nom_vernaculaire'] = $tab['nom_vernaculaire'];
784 raphael 389
			$resultat_json[$nnv]['langue.code'] = $tab['code_langue'];
730 raphael 390
			$resultat_json[$nnv]['taxon.code'] = 'bdtfx.nt:'.$tab['num_taxon'];
160 delphine 391
			if ($this->retour_format == 'max') {
284 jpm 392
				$this->taxons[] = $tab['num_taxon']; // utilisé pour chercher les noms latins plus bas
729 raphael 393
				if($this->champs_supp) {
730 raphael 394
					//$resultat_json[$nnv] = $this->ajouterChampsOntologieLigneResultat($tab);
395
					// simple initialisation par copie de la référence de l'original
396
					$resultat_json[$nnv] = &$tab;
286 aurelien 397
				}
729 raphael 398
				else {
730 raphael 399
					$resultat_json[$nnv]['num_taxon'] = $tab['num_taxon'];
400
					$resultat_json[$nnv]['nom_retenu.code'] = $tab['num_taxon'];
401
					$resultat_json[$nnv]['taxon'] = $tab['num_taxon'];
402
					$resultat_json[$nnv]['href'] = $this->ajouterHref('noms-vernaculaires', $tab['id']);
729 raphael 403
				}
160 delphine 404
			}
280 aurelien 405
		}
730 raphael 406
 
407
		// dans ce cas (particulier?) nous n'avons pour l'heure initialisé qu'une référence
408
		// vers le tableau de valeurs original
409
		if ($this->retour_format == 'max' && $this->champs_supp) {
410
			// récupérons désormais les ontologies
411
			$this->ajouterChampsOntologieLigneTousResultats($resultat_json);
412
		}
413
 
280 aurelien 414
		if ($this->retour_format == 'max') {
284 jpm 415
			// On est obligé de faire un deuxième boucle pour demander tous les taxons présents en une
416
			// fois et les attribuer aux noms car c'est beaucoup plus rapide
417
			$noms_sci = $this->recupererNomTaxons();
286 aurelien 418
			foreach ($resultat_json as $num_nom => &$tab) {
419
				$tab = $this->ajouterTaxonsAttributionsLigneResultat($tab, $noms_sci);
627 aurelien 420
				if($tab == null) {
421
					unset($resultat_json[$num_nom]);
422
				}
284 jpm 423
			}
160 delphine 424
		}
280 aurelien 425
 
160 delphine 426
		$table_retour_json['resultat'] = $resultat_json;
427
		return $table_retour_json;
428
	}
429
 
286 aurelien 430
	/**
431
	 * Ajoute les champs d'ontologie supplémentaires si necéssaire
832 raphael 432
	 * en faisant appels aux web services associés.
433
	 * Les appels peuvent être fait individuellement (pour un couple <ontologie:valeur>) ou bien
434
	 * regroupés, **si le webservice correspondant le supporte**.
435
	 *
436
	 * Nous disposons à ce jour de 3 (trois) webservices d'ontologies correspondant aux noms vernaculaires (cf $champ_infos)
437
	 * Mais 2 d'entre eux sont identiques, il s'agit de /nvjfl/ontologies/. Or ce webservice supporte le multi-critère.
438
	 * Nous pouvons donc factorisé l'appel pour "conseil_emploi" et "genre", mais pas pour "taxon".
439
	 *
730 raphael 440
	 * @param array in/out $resultats: tous les résultats
441
	 */
442
	public function ajouterChampsOntologieLigneTousResultats(&$resultats) {
832 raphael 443
		$champs_sup = array_intersect($this->champs_supp, array_keys(self::$champ_infos));
730 raphael 444
 
832 raphael 445
		// La regroupement des toutes les valeurs recherchées (pour tous les
446
		// résultats), pour "les" onotologies supportant le multi-critère est effectué ci-dessous.
447
		// Dans les faits ce n'est le cas que pour nvjfl.
448
		$ontologieParamPending = self::NvjflOntologieIndex($resultats, $champs_sup);
449
		$this->NvjflOntologieExpand($ontologieParamPending);
450
		self::NvjflOntologieCombine($resultats);
730 raphael 451
 
832 raphael 452
		// pour les ontologies multi-critères, on vient de le régler ci-dessus
453
		$champs_sup = array_diff($champs_sup, self::$onto_multi_support);
454
 
455
 
456
		// ici, $champs_sup ne peut contenir, au plus, que "taxon".
457
		// code historique:
458
		foreach($champs_sup as $cle) {
459
			$champs_supplementaires = self::$champ_infos[$cle];
730 raphael 460
			// extrait, depuis un élément de $champ_infos:
461
			// $service, $ressource, $projet, $nom, $intitule, $bdd_champ
462
			extract($champs_supplementaires);
463
 
464
			foreach ($resultats as &$tab) {
465
				$valeur_recherche = $tab[$bdd_champ];
466
				if(!trim($valeur_recherche)) continue;
467
 
468
				$url = $this->ajouterHrefAutreProjet($service, $ressource, $valeur_recherche, $projet);
469
				$tab[$intitule] = $this->chercherSignificationCode($url, $nom);
470
			}
471
		}
472
	}
473
 
731 raphael 474
	/* Récupère les valeurs recherchées pour une liste de résultats, (plus ou moins)
475
	   spécifiquement au service d'Ontologies de NVJFL.
476
	   Aggrège les valeurs dans le tableau retourné.
477
	   Une référence vers l'index du tableau (NULL pour l'instant) est laissée dans
478
	   un élément du résultat. */
832 raphael 479
	static function NvjflOntologieIndex(&$resultats, $champs_sup) {
480
		// nous ne supportons le multi-critère que sur les ontologies nvjfl, et nous
481
		// avons précisé celles qui sont concernées dans self::$onto_multi_support
482
		$champs_sup = array_intersect($champs_sup, self::$onto_multi_support);
731 raphael 483
		$ontologieParamPending = Array();
484
		foreach($resultats as &$resultat) {
832 raphael 485
			foreach($champs_sup as $v) {
486
				// de cet extract() nous n'utilisons que $bdd_champ et $ressource
487
				extract(self::$champ_infos[$v]);
488
				if(!isset($resultat[$bdd_champ])) continue;
489
 
490
				$valeur_recherche = $resultat[$bdd_champ];
491
				if(!trim($valeur_recherche)) continue;
492
 
493
				// XXX: $ressource contient déjà ':' comme suffixe
494
				$critere = $ressource . $valeur_recherche;
495
				$ontologieParamPending[$critere] = NULL;
496
				// placeholder pour le résultat
497
				$resultat[SPE_INDEX_NVJFL][$v][$critere] =
498
					&$ontologieParamPending[$critere];
499
			}
731 raphael 500
		}
501
		return $ontologieParamPending;
502
	}
503
 
504
	// TODO: switch to static si il peut en être de même pour ajouterHrefAutreProjet()
505
	/* À partir d'un aggrégat des critère de requêtes d'ontologies, spécifiques à NVJFL,
506
	   créé une URL multi-critère.
507
	   Celle-ci, dans ce cas précis, n'est que la concaténation, par des virgules,
832 raphael 508
	   des couples <ressource:ValeurRecherchée>.
509
	   L'URL est appelée et la valeur correspondante est remplacée dans $criteres_requete.
731 raphael 510
 
511
	   Note: dans le cadre du tryptique index/expand/combine pour lequel cette fonction existe,
832 raphael 512
	   la valeur est référencée par un élément d'une ou plusieurs lignes de $resultat correspondantes.
731 raphael 513
	   Celle(s)-ci sera[ont] donc changée(s) dans la foulée. */
514
	public function NvjflOntologieExpand(&$criteres_requete) {
515
		// équivalent spécifique de ajouterHrefAutreProjet()
516
		$valeurs_requises = implode(',', array_keys($criteres_requete));
832 raphael 517
		// en vérité, nous ne supportons ceci ici que pour nvjfl et non n'importe quel url_service
809 raphael 518
		$url = Config::get('url_service').'/ontologies/'.$valeurs_requises;
731 raphael 519
		$val = $this->consulterHref($url);
831 raphael 520
 
521
		// TODO, le webservice d'ontologies devrait être modifié pour retourner un tableau
522
		// indexé par critère requesté à *CHAQUE* fois, y compris lorsque 1 seul critère est
523
		// demandé.
524
		if(array_key_exists('id', $val) && count($criteres_requete) == 1) {
525
			$k = key($criteres_requete);
526
			$criteres_requete[$k] = $val;
527
			return;
528
		}
529
 
832 raphael 530
		// subtilité, cette affectation modifie par conséquent les valeurs dans
531
		// $resultats[X][SPE_INDEX_NVJFL]
731 raphael 532
		// dont la référence pointe toujours sur $v
533
		foreach($val as $k => $v) $criteres_requete[$k] = $val->$k;
534
	}
535
 
536
	/* Fonction finale du tryptique: réordonne les valeurs obtenues auprès du web-service
832 raphael 537
	   NVJFL en adéquation avec les champs attendus en sortie.
538
	   Dès l'indexation des critères, nous avons associé une (ou plusieurs) référence(s) du
539
	   tableau de résultats vers le tableau de retour des ontologies à l'aide d'un index
540
	   particulier l'index SPE_INDEX_NVJFL qui contient comme élément(s)
541
	   un ou plusieurs ontologies (les indexes de self::$champ_infos) qui elles-mêmes contiennent
542
	   une ou plusieurs valeurs représentant les valeurs recherchées appartement à cette ontologies.
543
	   Celui-ci est supprimé après avoir été correctement copié. */
544
	/**
545
	 * @param array in/out $resultats: tous les résultats
546
	 * @param array in $critere: tableau des ontologies:valeur demandées, de la forme [ numStatut:1, genreNombre:11, ... ]
547
	 */
548
	static function NvjflOntologieCombine(&$resultats, $criteres) {
731 raphael 549
		foreach($resultats as &$resultat) {
832 raphael 550
			if(!array_key_exists(SPE_INDEX_NVJFL, $resultat)) continue;
551
 
552
			/* Note: la complétude d'un résultat peut dépendre de plusieurs ontologies différentes,
553
			   d'où cette boucle. Cependant une seule valeur sera demandé pour cette ontologie, c'est pourquoi
554
			   $resultat[SPE_INDEX_NVJFL][$onto_name], s'il existe, ne contiendra toujours qu'un seul élément.
555
			   Puisque par définition un résultat contenant des valeurs d'ontologie n'aura jamais qu'un seul et unique
556
			   attribut num_genre (ou num_statut, ou autre) */
557
			foreach(self::$onto_multi_support as $onto_name) {
558
				/* $onto_name est un nom d'ontologie (l'une des clefs, parmi conseil_emploi et genre,
559
				   cf la boucle sur $champs_sup dans  NvjflOntologieIndex()
560
				   de cet extract() nous n'utilisons que $intitule et $nom */
561
				extract(self::$champ_infos[$onto_name]);
562
 
563
				// equivalent de l'affectation finale de chercherSignificationCode()
564
				// (utilisé lors de recherches d'ontologies en mono-critère)
565
				// XXX: PHP-5.3 pas de récupération d'attribut sur fonction
566
				$r = current($resultat[SPE_INDEX_NVJFL][$onto_name]);
567
				$resultat[$intitule] = $r->$nom;
568
 
569
				// XXX: certes nous pourrions nous contenter du unset() final
570
				unset($resultat[SPE_INDEX_NVJFL][$onto_name]);
571
			}
572
			unset($resultat[SPE_INDEX_NVJFL]);
731 raphael 573
		}
574
	}
575
 
730 raphael 576
	/**
577
	 * Ajoute les champs d'ontologie supplémentaires si necéssaire
578
	 * en faisant appels aux web services associés
286 aurelien 579
	 * @param array $ligne_resultat
580
	 *
581
	 * @return array la ligne modifiée
582
	 */
284 jpm 583
	public function ajouterChampsOntologieLigneResultat($ligne_resultat) {
832 raphael 584
		foreach(self::$champ_infos as $cle => $champs_supplementaires) {
729 raphael 585
			if(!in_array($cle, $this->champs_supp)) continue;
586
			// extrait, depuis un élément de $champ_infos:
587
			// $service, $ressource, $projet, $nom, $intitule, $bdd_champ
588
			extract($champs_supplementaires);
589
			$valeur_recherche = $ligne_resultat[$bdd_champ];
590
			if(!trim($valeur_recherche)) continue;
591
			$url = $this->ajouterHrefAutreProjet($service, $ressource, $valeur_recherche, $projet);
592
			$ligne_resultat[$intitule] = $this->chercherSignificationCode($url, $nom);
277 aurelien 593
		}
284 jpm 594
		return $ligne_resultat;
277 aurelien 595
	}
596
 
284 jpm 597
	/**
598
	 * Fonction qui ajoute les attributions à une ligne de résultats
599
	 *
600
	 * @param array $ligne_tableau_resultat
601
	 * @param array $nom_sci
602
	 */
603
	public function ajouterTaxonsAttributionsLigneResultat(&$ligne_tableau_resultat, &$noms_sci) {
285 aurelien 604
		if (isset($noms_sci[$ligne_tableau_resultat['num_taxon']])) {
605
			$ligne_tableau_resultat['nom_retenu.code'] = $noms_sci[$ligne_tableau_resultat['num_taxon']]['id'];
606
			$ligne_tableau_resultat['taxon'] = $noms_sci[$ligne_tableau_resultat['num_taxon']]['nom_sci'];
627 aurelien 607
		} else {
608
			$ligne_tableau_resultat = null;
284 jpm 609
		}
610
		return $ligne_tableau_resultat;
611
	}
612
 
613
	private function trierLigneTableau($a, $b) {
614
		$retour = 0;
615
 
616
		if ($a[$this->champ_tri] == $b[$this->champ_tri]) {
617
			$retour = 0;
618
		}
619
 
620
		if($this->champ_tri == 'code_langue') {
621
			if ($a[$this->champ_tri] == 'fra' && $b[$this->champ_tri] != 'fra') {
622
				$retour = ($this->direction_tri == 'asc') ? -1 : 1;
623
			} else if ($a[$this->champ_tri] != 'fra' && $b[$this->champ_tri] == 'fra') {
624
				$retour = ($this->direction_tri == 'asc') ? 1 : -1;
625
			} else {
626
				$retour = $this->comparerChaineSelonDirectionTri($a[$this->champ_tri], $b[$this->champ_tri]);
627
			}
628
		} else {
629
			$retour = $this->comparerChaineSelonDirectionTri($a[$this->champ_tri], $b[$this->champ_tri]);
630
		}
631
		return $retour;
632
	}
633
 
634
	private function comparerChaineSelonDirectionTri($a, $b) {
635
		if($this->direction_tri == 'asc') {
636
			return ($a < $b) ? -1 : 1;
637
		} else {
638
			return ($a > $b) ? -1 : 1;
639
		}
640
	}
641
 
6 jpm 642
	// formatage de la reponse /id ss la forme
643
	// id, nom_vernaculaire, attributions
644
	// langue
645
	// num_nom (correspond à un taxon bdtfx)
646
	public function formaterNomsVernaculairesId($resultat) {
647
		foreach ($resultat as $taxon) { // pour chaque attribution à un taxon bdtfx
648
			// on crée les variables qui serviront de clés et on les enléves du tableau
649
			$num_nom = $taxon['num_nom_vernaculaire']; // unique pour un trinôme id, langue, taxon
650
			unset($taxon['num_nom_vernaculaire']);
651
			$langue = $taxon['code_langue'];
652
			unset($taxon['code_langue']);
109 jpm 653
 
6 jpm 654
			foreach ($this->correspondance_champs as $key => $correspondance) { // ordonne les infos pour affichage
655
				if (isset($taxon[$key]) && $taxon[$key] != "") {
656
					$this->afficherDonnees($correspondance, $taxon[$key], $langue, $num_nom);
657
				}
658
			}
659
			foreach ($taxon as $key => $valeur) { // rajoute les champs non prévus dans l'api
660
				if (!isset($this->correspondance_champs[$key]) && $valeur != "") {
661
					$this->afficherDonnees($key, $valeur, $langue, $num_nom);
662
				}
663
			}
664
			if ($this->retour_format == 'max') $this->chargerBiblio($num_nom, $langue);
665
		}
666
		if ($this->retour_format == 'max') $this->afficherTaxons(); // va chercher les noms de tous les taxons
667
		unset($this->table_retour['href']);
668
		return $this->table_retour;
669
	}
109 jpm 670
 
6 jpm 671
	public function afficherDonnees($champ, $valeur, $langue = '', $num_nom = '') {
672
		if ($champ == 'id' || $champ == 'nom_vernaculaire') {
673
			$this->table_retour[$champ] = $valeur;
674
		} elseif (preg_match('/^(.*)\.code$/', $champ, $match)) {
675
				switch ($match[1]) {
676
					case 'taxon'	: if ($this->retour_format == 'max') {$this->taxons[$num_nom] = $valeur;}
677
						$this->afficherPointCode($match[1], $langue, $num_nom, $valeur);	break;
109 jpm 678
					case 'langue'	: //$this->afficherPointCode($match[1], 'iso-639-3', 'langues', $valeur);
6 jpm 679
						break;
680
					case 'genre'	: $this->afficherPointCode($match[1], $langue, $num_nom, $valeur);	break;
681
					case 'conseil_emploi'	: $this->afficherPointCode($match[1], $langue, $num_nom, $valeur);	break;
682
					default : break;
683
				}
109 jpm 684
 
6 jpm 685
		} elseif ($langue != '') {
686
			$this->table_retour['attributions'][$langue][$num_nom][$champ] = $valeur;
687
		} else {
688
			$this->table_retour[$champ] = $valeur;
689
		}
690
	}
109 jpm 691
 
6 jpm 692
	public function afficherPointCode($nomChamp, $langue, $num_nom, $valeur) {
832 raphael 693
		if (isset(self::$champ_infos[$nomChamp])) {
694
			extract(self::$champ_infos[$nomChamp]);
6 jpm 695
		}
109 jpm 696
 
6 jpm 697
		if ($this->retour_format == 'max') {
698
			$url = $this->ajouterHrefAutreProjet($service, $ressource, $valeur, $projet);
699
			if ($service == 'taxons') {
700
				$code_valeur = '';
164 delphine 701
				$this->table_retour['attributions'][$langue][$num_nom]['nom_retenu.code'] = $code_valeur;
109 jpm 702
			} else {
6 jpm 703
				$code_valeur = $this->chercherSignificationCode($url, $nom);
704
			}
705
			if ($projet != '') $projet .= '.';
706
			$this->table_retour['attributions'][$langue][$num_nom][$nomChamp] = $code_valeur;
707
			$this->table_retour['attributions'][$langue][$num_nom][$nomChamp.'.code'] = $projet.$ressource.$valeur;
708
			$this->table_retour['attributions'][$langue][$num_nom][$nomChamp.'.href'] = $url;
709
		} else {
710
			if ($projet != '') $projet .= '.';
711
			$this->table_retour['attributions'][$langue][$num_nom][$nomChamp.'.code'] = $projet.$ressource.$valeur;
712
		}
713
	}
109 jpm 714
 
6 jpm 715
	public function chercherSignificationCode($url, $nom) {
716
		if (isset($this->signification_code[$url])) {
717
			$valeur = $this->signification_code[$url];
718
		} else {
719
			$res = $this->consulterHref($url);
720
			$valeur = $res->$nom;
721
			$this->signification_code[$url] = $valeur;
722
		}
723
		return $valeur;
724
	}
109 jpm 725
 
6 jpm 726
	public function afficherTaxons() {
160 delphine 727
		$resultat = $this->recupererNomTaxons();
6 jpm 728
		foreach ($this->table_retour['attributions'] as $code_langue=>$langue) {
729
			foreach ($langue as $num_nom=>$taxon) {
730
				$num_tax = ltrim($taxon['taxon.code'], 'bdtfx.nt:');
731
				if (isset($resultat[$num_tax])) {
164 delphine 732
					$this->table_retour['attributions'][$code_langue][$num_nom]['nom_retenu.code'] = $resultat[$num_tax]['id'];
733
					$this->table_retour['attributions'][$code_langue][$num_nom]['taxon'] = $resultat[$num_tax]['nom_sci'];
6 jpm 734
				}
735
			}
736
		}
737
	}
160 delphine 738
 
739
	public function recupererNomTaxons() {
627 aurelien 740
		$taxons = array_unique($this->taxons);
741
		$url = Config::get('url_service_base').'bdtfx/taxons?navigation.limite=500&ns.structure=au&masque.nt='.implode(',', $taxons);
160 delphine 742
		$res = $this->consulterHref($url);
743
		foreach ($res->resultat as $id=>$taxon) {
164 delphine 744
			$resultat[$taxon->num_taxonomique]['id'] = 'bdtfx.nn:'.$id;
627 aurelien 745
			$resultat[$taxon->num_taxonomique]['nom_sci'] = $taxon->nom_sci_complet;
160 delphine 746
		}
747
		return $resultat;
748
	}
6 jpm 749
 
750
	public function formaterNomsVernaculairesIdChamp($resultat) {
109 jpm 751
		$this->table_retour['id'] = $this->ressources[0];
752
		$champs = explode(' ', $this->ressources[1]);
6 jpm 753
		if (in_array('attributions', $champs) != false) {
754
			$this->formaterNomsVernaculairesId($resultat);
755
			unset($this->table_retour['nom_vernaculaire']);
160 delphine 756
		} else {
6 jpm 757
			$champ_attributions = array('num_taxon', 'zone_usage', 'num_statut', 'num_genre', 'notes');
758
			foreach ($resultat as $taxon) {
759
				foreach ($taxon as $key=>$valeur) {
760
					if ($key == 'code_langue' && in_array('langue', $champs) != false) {
761
						$this->table_retour['attributions']['langue'][] = $valeur;
762
					} elseif (in_array($key, $champ_attributions) != false) {
763
						$this->afficherPoint($this->correspondance_champs[$key] , $valeur, $taxon['code_langue'], $taxon['num_nom_vernaculaire']);
764
					} elseif (in_array($key, $champs) != false) {
765
						$this->table_retour[$key] = $valeur;
766
					}
767
				}
768
				if (in_array('biblio', $champs) != false) $this->chargerBiblio($taxon['num_nom_vernaculaire'], $taxon['code_langue']);
769
			}
770
			if (in_array('biblio', $champs) != false && array_search('biblio.num_ref', $this->table_retour) != false) $this->table_retour['biblio'] = null;
771
		}
772
		return $this->table_retour;
773
	}
109 jpm 774
 
6 jpm 775
	public function afficherPoint($champ, $valeur, $langue, $num_nom) {
776
		preg_match('/^(.*)\.code$/', $champ, $match);
777
		$champ = $match[1];
832 raphael 778
		if (isset(self::$champ_infos[$champ])) {
779
			extract(self::$champ_infos[$champ]);
6 jpm 780
			$url = $this->ajouterHrefAutreProjet($service, $ressource, $valeur, $projet);
781
			$projet .= '.';
782
		}
109 jpm 783
 
784
		$champs = explode(' ', $this->ressources[1]);
6 jpm 785
		if (in_array($champ.'.*', $champs) !== false && isset($projet)) {
786
			$this->table_retour['attributions'][$langue][$num_nom][$champ.'.code'] = $projet.$ressource.$valeur;
787
			$this->table_retour['attributions'][$langue][$num_nom][$champ.'.href'] = $url;
109 jpm 788
		}
6 jpm 789
		if (in_array($champ.'.code', $champs) !== false && isset($projet)) {
790
			$this->table_retour['attributions'][$langue][$num_nom][$champ.'.code'] = $projet.$ressource.$valeur;
109 jpm 791
		}
6 jpm 792
		if (in_array($champ.'.href', $champs) !== false && isset($projet)) {
793
			$this->table_retour['attributions'][$langue][$num_nom][$champ.'.href'] = $url;
109 jpm 794
		}
6 jpm 795
		if (in_array($champ, $champs) !== false) {
796
			if (isset($url)) {
797
				$this->table_retour['attributions'][$langue][$num_nom][$champ] = $this->chercherSignificationCode($url, $nom);
798
			} else {
799
				$this->table_retour['attributions'][$langue][$champ] = $valeur;
800
			}
109 jpm 801
		}
6 jpm 802
	}
803
 
804
	public function afficherLangue($nomChamp, $projet, $service, $valeur, $ressource = '', $nom = 'nom') {
805
		if ($this->retour_format == 'max') {
806
				$this->table_retour['attributions'][$nomChamp] = $nom;
807
				$this->table_retour['attributions'][$nomChamp.'.code'] = $projet.$ressource.$valeur;
808
				$this->table_retour['attributions'][$nomChamp.'.href'] = $url;
809
		} else {
810
			$this->table_retour['attributions'][$nomChamp.'.code'] = $projet.$ressource.$valeur;
811
		}
812
	}
109 jpm 813
 
6 jpm 814
	public function chargerBiblio($num_nom, $langue) {
815
		list($table, $version) = explode('_v',$this->table);
816
		$requete = "SELECT b.*, lb.notes FROM nvjfl_lien_biblio_v$version lb, nvjfl_biblio_v$version b ".
817
					"WHERE b.num_ref = lb.num_ref AND lb.num_nom = '$num_nom' ;";
284 jpm 818
		$resultat = $this->getBdd()->recupererTous($requete);
109 jpm 819
 
6 jpm 820
		 if ($resultat == '') { //cas ou la requete comporte des erreurs
821
		 	$r = 'La requête SQL formée comporte une erreur !!';
822
			$this->renvoyerErreur(RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE, $r);
823
			Debug::printr($requete);
824
		 } elseif ($resultat) {
825
			foreach ($resultat as $res) {
826
			   	foreach ($res as $cle => $valeur) {
827
			   		if ($valeur !== "") {
828
			   			$this->table_retour['attributions'][$langue][$num_nom]['biblio.'.$cle] = $valeur;
829
			   		}
830
			    }
831
			}
832
		}
833
	}
109 jpm 834
 
6 jpm 835
}
836
?>