Subversion Repositories eFlore/Projets.eflore-projets

Rev

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

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