Subversion Repositories eFlore/Projets.eflore-projets

Rev

Rev 832 | Rev 888 | 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
	 */
848 raphael 548
	static function NvjflOntologieCombine(&$resultats) {
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) {
848 raphael 558
				if(!array_key_exists($onto_name, $resultat[SPE_INDEX_NVJFL])) continue;
559
 
832 raphael 560
				/* $onto_name est un nom d'ontologie (l'une des clefs, parmi conseil_emploi et genre,
561
				   cf la boucle sur $champs_sup dans  NvjflOntologieIndex()
562
				   de cet extract() nous n'utilisons que $intitule et $nom */
563
				extract(self::$champ_infos[$onto_name]);
564
 
565
				// equivalent de l'affectation finale de chercherSignificationCode()
566
				// (utilisé lors de recherches d'ontologies en mono-critère)
567
				// XXX: PHP-5.3 pas de récupération d'attribut sur fonction
568
				$r = current($resultat[SPE_INDEX_NVJFL][$onto_name]);
569
				$resultat[$intitule] = $r->$nom;
570
 
571
				// XXX: certes nous pourrions nous contenter du unset() final
572
				unset($resultat[SPE_INDEX_NVJFL][$onto_name]);
573
			}
574
			unset($resultat[SPE_INDEX_NVJFL]);
731 raphael 575
		}
576
	}
577
 
730 raphael 578
	/**
579
	 * Ajoute les champs d'ontologie supplémentaires si necéssaire
580
	 * en faisant appels aux web services associés
286 aurelien 581
	 * @param array $ligne_resultat
582
	 *
583
	 * @return array la ligne modifiée
584
	 */
284 jpm 585
	public function ajouterChampsOntologieLigneResultat($ligne_resultat) {
832 raphael 586
		foreach(self::$champ_infos as $cle => $champs_supplementaires) {
729 raphael 587
			if(!in_array($cle, $this->champs_supp)) continue;
588
			// extrait, depuis un élément de $champ_infos:
589
			// $service, $ressource, $projet, $nom, $intitule, $bdd_champ
590
			extract($champs_supplementaires);
591
			$valeur_recherche = $ligne_resultat[$bdd_champ];
592
			if(!trim($valeur_recherche)) continue;
593
			$url = $this->ajouterHrefAutreProjet($service, $ressource, $valeur_recherche, $projet);
594
			$ligne_resultat[$intitule] = $this->chercherSignificationCode($url, $nom);
277 aurelien 595
		}
284 jpm 596
		return $ligne_resultat;
277 aurelien 597
	}
598
 
284 jpm 599
	/**
600
	 * Fonction qui ajoute les attributions à une ligne de résultats
601
	 *
602
	 * @param array $ligne_tableau_resultat
603
	 * @param array $nom_sci
604
	 */
605
	public function ajouterTaxonsAttributionsLigneResultat(&$ligne_tableau_resultat, &$noms_sci) {
285 aurelien 606
		if (isset($noms_sci[$ligne_tableau_resultat['num_taxon']])) {
607
			$ligne_tableau_resultat['nom_retenu.code'] = $noms_sci[$ligne_tableau_resultat['num_taxon']]['id'];
608
			$ligne_tableau_resultat['taxon'] = $noms_sci[$ligne_tableau_resultat['num_taxon']]['nom_sci'];
627 aurelien 609
		} else {
610
			$ligne_tableau_resultat = null;
284 jpm 611
		}
612
		return $ligne_tableau_resultat;
613
	}
614
 
615
	private function trierLigneTableau($a, $b) {
616
		$retour = 0;
617
 
618
		if ($a[$this->champ_tri] == $b[$this->champ_tri]) {
619
			$retour = 0;
620
		}
621
 
622
		if($this->champ_tri == 'code_langue') {
623
			if ($a[$this->champ_tri] == 'fra' && $b[$this->champ_tri] != 'fra') {
624
				$retour = ($this->direction_tri == 'asc') ? -1 : 1;
625
			} else if ($a[$this->champ_tri] != 'fra' && $b[$this->champ_tri] == 'fra') {
626
				$retour = ($this->direction_tri == 'asc') ? 1 : -1;
627
			} else {
628
				$retour = $this->comparerChaineSelonDirectionTri($a[$this->champ_tri], $b[$this->champ_tri]);
629
			}
630
		} else {
631
			$retour = $this->comparerChaineSelonDirectionTri($a[$this->champ_tri], $b[$this->champ_tri]);
632
		}
633
		return $retour;
634
	}
635
 
636
	private function comparerChaineSelonDirectionTri($a, $b) {
637
		if($this->direction_tri == 'asc') {
638
			return ($a < $b) ? -1 : 1;
639
		} else {
640
			return ($a > $b) ? -1 : 1;
641
		}
642
	}
643
 
6 jpm 644
	// formatage de la reponse /id ss la forme
645
	// id, nom_vernaculaire, attributions
646
	// langue
647
	// num_nom (correspond à un taxon bdtfx)
648
	public function formaterNomsVernaculairesId($resultat) {
649
		foreach ($resultat as $taxon) { // pour chaque attribution à un taxon bdtfx
650
			// on crée les variables qui serviront de clés et on les enléves du tableau
651
			$num_nom = $taxon['num_nom_vernaculaire']; // unique pour un trinôme id, langue, taxon
652
			unset($taxon['num_nom_vernaculaire']);
653
			$langue = $taxon['code_langue'];
654
			unset($taxon['code_langue']);
109 jpm 655
 
6 jpm 656
			foreach ($this->correspondance_champs as $key => $correspondance) { // ordonne les infos pour affichage
657
				if (isset($taxon[$key]) && $taxon[$key] != "") {
658
					$this->afficherDonnees($correspondance, $taxon[$key], $langue, $num_nom);
659
				}
660
			}
661
			foreach ($taxon as $key => $valeur) { // rajoute les champs non prévus dans l'api
662
				if (!isset($this->correspondance_champs[$key]) && $valeur != "") {
663
					$this->afficherDonnees($key, $valeur, $langue, $num_nom);
664
				}
665
			}
666
			if ($this->retour_format == 'max') $this->chargerBiblio($num_nom, $langue);
667
		}
668
		if ($this->retour_format == 'max') $this->afficherTaxons(); // va chercher les noms de tous les taxons
669
		unset($this->table_retour['href']);
670
		return $this->table_retour;
671
	}
109 jpm 672
 
6 jpm 673
	public function afficherDonnees($champ, $valeur, $langue = '', $num_nom = '') {
674
		if ($champ == 'id' || $champ == 'nom_vernaculaire') {
675
			$this->table_retour[$champ] = $valeur;
676
		} elseif (preg_match('/^(.*)\.code$/', $champ, $match)) {
677
				switch ($match[1]) {
678
					case 'taxon'	: if ($this->retour_format == 'max') {$this->taxons[$num_nom] = $valeur;}
679
						$this->afficherPointCode($match[1], $langue, $num_nom, $valeur);	break;
109 jpm 680
					case 'langue'	: //$this->afficherPointCode($match[1], 'iso-639-3', 'langues', $valeur);
6 jpm 681
						break;
682
					case 'genre'	: $this->afficherPointCode($match[1], $langue, $num_nom, $valeur);	break;
683
					case 'conseil_emploi'	: $this->afficherPointCode($match[1], $langue, $num_nom, $valeur);	break;
684
					default : break;
685
				}
109 jpm 686
 
6 jpm 687
		} elseif ($langue != '') {
688
			$this->table_retour['attributions'][$langue][$num_nom][$champ] = $valeur;
689
		} else {
690
			$this->table_retour[$champ] = $valeur;
691
		}
692
	}
109 jpm 693
 
6 jpm 694
	public function afficherPointCode($nomChamp, $langue, $num_nom, $valeur) {
832 raphael 695
		if (isset(self::$champ_infos[$nomChamp])) {
696
			extract(self::$champ_infos[$nomChamp]);
6 jpm 697
		}
109 jpm 698
 
6 jpm 699
		if ($this->retour_format == 'max') {
700
			$url = $this->ajouterHrefAutreProjet($service, $ressource, $valeur, $projet);
701
			if ($service == 'taxons') {
702
				$code_valeur = '';
164 delphine 703
				$this->table_retour['attributions'][$langue][$num_nom]['nom_retenu.code'] = $code_valeur;
109 jpm 704
			} else {
6 jpm 705
				$code_valeur = $this->chercherSignificationCode($url, $nom);
706
			}
707
			if ($projet != '') $projet .= '.';
708
			$this->table_retour['attributions'][$langue][$num_nom][$nomChamp] = $code_valeur;
709
			$this->table_retour['attributions'][$langue][$num_nom][$nomChamp.'.code'] = $projet.$ressource.$valeur;
710
			$this->table_retour['attributions'][$langue][$num_nom][$nomChamp.'.href'] = $url;
711
		} else {
712
			if ($projet != '') $projet .= '.';
713
			$this->table_retour['attributions'][$langue][$num_nom][$nomChamp.'.code'] = $projet.$ressource.$valeur;
714
		}
715
	}
109 jpm 716
 
6 jpm 717
	public function chercherSignificationCode($url, $nom) {
718
		if (isset($this->signification_code[$url])) {
719
			$valeur = $this->signification_code[$url];
720
		} else {
721
			$res = $this->consulterHref($url);
722
			$valeur = $res->$nom;
723
			$this->signification_code[$url] = $valeur;
724
		}
725
		return $valeur;
726
	}
109 jpm 727
 
6 jpm 728
	public function afficherTaxons() {
160 delphine 729
		$resultat = $this->recupererNomTaxons();
6 jpm 730
		foreach ($this->table_retour['attributions'] as $code_langue=>$langue) {
731
			foreach ($langue as $num_nom=>$taxon) {
732
				$num_tax = ltrim($taxon['taxon.code'], 'bdtfx.nt:');
733
				if (isset($resultat[$num_tax])) {
164 delphine 734
					$this->table_retour['attributions'][$code_langue][$num_nom]['nom_retenu.code'] = $resultat[$num_tax]['id'];
735
					$this->table_retour['attributions'][$code_langue][$num_nom]['taxon'] = $resultat[$num_tax]['nom_sci'];
6 jpm 736
				}
737
			}
738
		}
739
	}
160 delphine 740
 
741
	public function recupererNomTaxons() {
627 aurelien 742
		$taxons = array_unique($this->taxons);
743
		$url = Config::get('url_service_base').'bdtfx/taxons?navigation.limite=500&ns.structure=au&masque.nt='.implode(',', $taxons);
160 delphine 744
		$res = $this->consulterHref($url);
745
		foreach ($res->resultat as $id=>$taxon) {
164 delphine 746
			$resultat[$taxon->num_taxonomique]['id'] = 'bdtfx.nn:'.$id;
627 aurelien 747
			$resultat[$taxon->num_taxonomique]['nom_sci'] = $taxon->nom_sci_complet;
160 delphine 748
		}
749
		return $resultat;
750
	}
6 jpm 751
 
752
	public function formaterNomsVernaculairesIdChamp($resultat) {
109 jpm 753
		$this->table_retour['id'] = $this->ressources[0];
754
		$champs = explode(' ', $this->ressources[1]);
6 jpm 755
		if (in_array('attributions', $champs) != false) {
756
			$this->formaterNomsVernaculairesId($resultat);
757
			unset($this->table_retour['nom_vernaculaire']);
160 delphine 758
		} else {
6 jpm 759
			$champ_attributions = array('num_taxon', 'zone_usage', 'num_statut', 'num_genre', 'notes');
760
			foreach ($resultat as $taxon) {
761
				foreach ($taxon as $key=>$valeur) {
762
					if ($key == 'code_langue' && in_array('langue', $champs) != false) {
763
						$this->table_retour['attributions']['langue'][] = $valeur;
764
					} elseif (in_array($key, $champ_attributions) != false) {
765
						$this->afficherPoint($this->correspondance_champs[$key] , $valeur, $taxon['code_langue'], $taxon['num_nom_vernaculaire']);
766
					} elseif (in_array($key, $champs) != false) {
767
						$this->table_retour[$key] = $valeur;
768
					}
769
				}
770
				if (in_array('biblio', $champs) != false) $this->chargerBiblio($taxon['num_nom_vernaculaire'], $taxon['code_langue']);
771
			}
772
			if (in_array('biblio', $champs) != false && array_search('biblio.num_ref', $this->table_retour) != false) $this->table_retour['biblio'] = null;
773
		}
774
		return $this->table_retour;
775
	}
109 jpm 776
 
6 jpm 777
	public function afficherPoint($champ, $valeur, $langue, $num_nom) {
778
		preg_match('/^(.*)\.code$/', $champ, $match);
779
		$champ = $match[1];
832 raphael 780
		if (isset(self::$champ_infos[$champ])) {
781
			extract(self::$champ_infos[$champ]);
6 jpm 782
			$url = $this->ajouterHrefAutreProjet($service, $ressource, $valeur, $projet);
783
			$projet .= '.';
784
		}
109 jpm 785
 
786
		$champs = explode(' ', $this->ressources[1]);
6 jpm 787
		if (in_array($champ.'.*', $champs) !== false && isset($projet)) {
788
			$this->table_retour['attributions'][$langue][$num_nom][$champ.'.code'] = $projet.$ressource.$valeur;
789
			$this->table_retour['attributions'][$langue][$num_nom][$champ.'.href'] = $url;
109 jpm 790
		}
6 jpm 791
		if (in_array($champ.'.code', $champs) !== false && isset($projet)) {
792
			$this->table_retour['attributions'][$langue][$num_nom][$champ.'.code'] = $projet.$ressource.$valeur;
109 jpm 793
		}
6 jpm 794
		if (in_array($champ.'.href', $champs) !== false && isset($projet)) {
795
			$this->table_retour['attributions'][$langue][$num_nom][$champ.'.href'] = $url;
109 jpm 796
		}
6 jpm 797
		if (in_array($champ, $champs) !== false) {
798
			if (isset($url)) {
799
				$this->table_retour['attributions'][$langue][$num_nom][$champ] = $this->chercherSignificationCode($url, $nom);
800
			} else {
801
				$this->table_retour['attributions'][$langue][$champ] = $valeur;
802
			}
109 jpm 803
		}
6 jpm 804
	}
805
 
806
	public function afficherLangue($nomChamp, $projet, $service, $valeur, $ressource = '', $nom = 'nom') {
807
		if ($this->retour_format == 'max') {
808
				$this->table_retour['attributions'][$nomChamp] = $nom;
809
				$this->table_retour['attributions'][$nomChamp.'.code'] = $projet.$ressource.$valeur;
810
				$this->table_retour['attributions'][$nomChamp.'.href'] = $url;
811
		} else {
812
			$this->table_retour['attributions'][$nomChamp.'.code'] = $projet.$ressource.$valeur;
813
		}
814
	}
109 jpm 815
 
6 jpm 816
	public function chargerBiblio($num_nom, $langue) {
817
		list($table, $version) = explode('_v',$this->table);
818
		$requete = "SELECT b.*, lb.notes FROM nvjfl_lien_biblio_v$version lb, nvjfl_biblio_v$version b ".
819
					"WHERE b.num_ref = lb.num_ref AND lb.num_nom = '$num_nom' ;";
284 jpm 820
		$resultat = $this->getBdd()->recupererTous($requete);
109 jpm 821
 
6 jpm 822
		 if ($resultat == '') { //cas ou la requete comporte des erreurs
823
		 	$r = 'La requête SQL formée comporte une erreur !!';
824
			$this->renvoyerErreur(RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE, $r);
825
			Debug::printr($requete);
826
		 } elseif ($resultat) {
827
			foreach ($resultat as $res) {
828
			   	foreach ($res as $cle => $valeur) {
829
			   		if ($valeur !== "") {
830
			   			$this->table_retour['attributions'][$langue][$num_nom]['biblio.'.$cle] = $valeur;
831
			   		}
832
			    }
833
			}
834
		}
835
	}
109 jpm 836
 
6 jpm 837
}
838
?>