Subversion Repositories eFlore/Projets.eflore-projets

Rev

Go to most recent revision | Details | 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
 
276
        return $res['nombre'];
6 jpm 277
	}
109 jpm 278
 
279
	//+------------------------------------------------------------------------------------------------------+
280
	// determine en fct du service appelé (/noms-vernaculaires | /noms-vernaculaires/#id | /noms-vernaculaires/#id/champ |
6 jpm 281
	// /noms-vernaculaires/#id/relations) le format du tableau à retourner.
282
	public function retournerResultatFormate($resultat) {
283
		$this->recupererTableConfig('correspondance_champs');
284
		switch ($this->format_reponse) {
132 aurelien 285
			case 'noms-vernaculaires'				:
286
				$reponse = ($this->retour_format == 'oss') ? $this->formaterEnOss($resultat) : $this->formaterNomsVernaculaires($resultat);			break;
160 delphine 287
			case 'noms-vernaculaires/attributions'	: $reponse = $this->formaterNomsVernaculairesAttributions($resultat);	break;
6 jpm 288
			case 'noms-vernaculaires/id'			: $reponse = $this->formaterNomsVernaculairesId($resultat);			break;
289
			case 'noms-vernaculaires/id/champ'		: $reponse = $this->formaterNomsVernaculairesIdChamp($resultat);	break;
290
			default									:																	break;
291
		}
292
		return $reponse;
293
	}
608 mathilde 294
 
295
	public function ajouterJsonEnTeteNV() {
296
		$table_retour_json['masque'] = $this->recupererMasque();
297
		$table_retour_json['depart'] = $this->limite_requete['depart'];
298
		$table_retour_json['limite'] = $this->limite_requete['limite'];
299
		$table_retour_json['total']  = $this->total_resultat;
6 jpm 300
		$url = $this->formulerUrl($this->total_resultat, '/noms-vernaculaires');
608 mathilde 301
		if (isset($url['precedent']) && $url['precedent'] != '') {
302
			$table_retour_json['href.precedent'] = $url['precedent'];
6 jpm 303
		}
608 mathilde 304
		if (isset($url['suivant']) && $url['suivant']   != '') {
305
			$table_retour_json['href.suivant']   = $url['suivant'];
152 delphine 306
		}
608 mathilde 307
		return $table_retour_json;
308
	}
309
 
310
	public function ajouterJsonResultatNV($resultat) {
6 jpm 311
		foreach ($resultat as $tab) {
312
			foreach ($tab as $key => $valeur) {
313
				if ($valeur != '') {
314
					switch ($key) {
315
						case 'id'				: $num = $valeur;								break;
316
						case 'nom_vernaculaire'	: $this->table_retour['nom'] = $valeur;			break;
317
						default					:												break;
318
					}
319
				}
320
			}
608 mathilde 321
		    if ($this->retour_format == 'max') $this->table_retour['href'] = $this->ajouterHref('noms-vernaculaires', $num);
6 jpm 322
			$resultat_json[$num] = $this->table_retour;
323
			$this->table_retour = array();
324
		}
608 mathilde 325
		return  $resultat_json;
326
	}
109 jpm 327
 
608 mathilde 328
 
329
	public function formaterNomsVernaculaires($resultat) {
330
		$table_retour_json['entete'] = $this->ajouterJsonEnTeteNV();
331
		$resultat = $this->hierarchiserResultat($resultat);
332
		$table_retour_json['resultat'] = $this->ajouterJsonResultatNV($resultat);
6 jpm 333
		return $table_retour_json;
334
	}
132 aurelien 335
 
608 mathilde 336
	public function hierarchiserResultat($resultat) {
337
		//tri recherche floue
338
		if (isset($this->parametres['masque.nv'])) {
966 raphael 339
			return $this->trierRechercheFloue($this->parametres['masque.nv'], $resultat, 'nom_vernaculaire');
608 mathilde 340
		}
341
		if (isset($this->parametres['masque'])) {
966 raphael 342
			return $this->trierRechercheFloue($this->parametres['masque'], $resultat, 'nom_vernaculaire');
608 mathilde 343
		}
344
		return $resultat;
345
	}
346
 
160 delphine 347
	public function recupererMasque() {
348
		$tab_masque = array();
349
		foreach ($this->parametres as $param=>$valeur) {
350
			if (strstr($param, 'masque') != false) {
351
				$tab_masque[] = $param.'='.$valeur;
352
			}
353
		}
966 raphael 354
		return implode('&', $tab_masque);
160 delphine 355
	}
356
 
132 aurelien 357
	public function formaterEnOss($resultat) {
358
		$table_nom = array();
359
		$oss = '';
360
		foreach ($resultat as $tab) {
361
			if (isset($tab['nom_vernaculaire']) ) {
362
				if (!in_array($tab['nom_vernaculaire'], $table_nom)) {
363
					$table_nom[] = $tab['nom_vernaculaire'];
364
					$oss [] = $tab['nom_vernaculaire'];
365
				}
366
			}
367
		}
368
		if (isset($this->masque)) $masque = implode('&', $this->masque);
369
		else $masque = 'Pas de masque';
966 raphael 370
		return array($masque, $oss);
132 aurelien 371
	}
160 delphine 372
 
373
	public function formaterNomsVernaculairesAttributions($resultat) {
374
		//on remplie la table $table_retour_json['entete']
375
		$table_retour_json['entete']['masque'] = $this->recupererMasque();
376
		$table_retour_json['entete']['depart'] = $this->limite_requete['depart'];
377
		$table_retour_json['entete']['limite'] = $this->limite_requete['limite'];
378
		$table_retour_json['entete']['total']  = $this->total_resultat;
379
		$url = $this->formulerUrl($this->total_resultat, '/noms-vernaculaires/attributions');
729 raphael 380
		if (!empty($url['precedent'])) {
160 delphine 381
			$table_retour_json['entete']['href.precedent'] = $url['precedent'];
382
		}
729 raphael 383
		if (!empty($url['suivant'])) {
160 delphine 384
			$table_retour_json['entete']['href.suivant']   = $url['suivant'];
385
		}
888 raphael 386
		foreach ($resultat as &$tab) {
730 raphael 387
			$nnv = $tab['num_nom_vernaculaire'];
388
			$resultat_json[$nnv]['id'] = $tab['id'];
389
			$resultat_json[$nnv]['nom_vernaculaire'] = $tab['nom_vernaculaire'];
888 raphael 390
			$resultat_json[$nnv]['langue.code'] = $resultat_json[$nnv]['code_langue'] = $tab['code_langue'];
730 raphael 391
			$resultat_json[$nnv]['taxon.code'] = 'bdtfx.nt:'.$tab['num_taxon'];
160 delphine 392
			if ($this->retour_format == 'max') {
284 jpm 393
				$this->taxons[] = $tab['num_taxon']; // utilisé pour chercher les noms latins plus bas
729 raphael 394
				if($this->champs_supp) {
730 raphael 395
					//$resultat_json[$nnv] = $this->ajouterChampsOntologieLigneResultat($tab);
396
					// simple initialisation par copie de la référence de l'original
397
					$resultat_json[$nnv] = &$tab;
286 aurelien 398
				}
729 raphael 399
				else {
730 raphael 400
					$resultat_json[$nnv]['num_taxon'] = $tab['num_taxon'];
401
					$resultat_json[$nnv]['nom_retenu.code'] = $tab['num_taxon'];
402
					$resultat_json[$nnv]['taxon'] = $tab['num_taxon'];
403
					$resultat_json[$nnv]['href'] = $this->ajouterHref('noms-vernaculaires', $tab['id']);
729 raphael 404
				}
160 delphine 405
			}
280 aurelien 406
		}
730 raphael 407
 
408
		// dans ce cas (particulier?) nous n'avons pour l'heure initialisé qu'une référence
409
		// vers le tableau de valeurs original
410
		if ($this->retour_format == 'max' && $this->champs_supp) {
411
			// récupérons désormais les ontologies
412
			$this->ajouterChampsOntologieLigneTousResultats($resultat_json);
413
		}
414
 
280 aurelien 415
		if ($this->retour_format == 'max') {
284 jpm 416
			// On est obligé de faire un deuxième boucle pour demander tous les taxons présents en une
417
			// fois et les attribuer aux noms car c'est beaucoup plus rapide
418
			$noms_sci = $this->recupererNomTaxons();
286 aurelien 419
			foreach ($resultat_json as $num_nom => &$tab) {
420
				$tab = $this->ajouterTaxonsAttributionsLigneResultat($tab, $noms_sci);
627 aurelien 421
				if($tab == null) {
422
					unset($resultat_json[$num_nom]);
423
				}
284 jpm 424
			}
160 delphine 425
		}
280 aurelien 426
 
160 delphine 427
		$table_retour_json['resultat'] = $resultat_json;
428
		return $table_retour_json;
429
	}
430
 
286 aurelien 431
	/**
432
	 * Ajoute les champs d'ontologie supplémentaires si necéssaire
832 raphael 433
	 * en faisant appels aux web services associés.
434
	 * Les appels peuvent être fait individuellement (pour un couple <ontologie:valeur>) ou bien
435
	 * regroupés, **si le webservice correspondant le supporte**.
436
	 *
437
	 * Nous disposons à ce jour de 3 (trois) webservices d'ontologies correspondant aux noms vernaculaires (cf $champ_infos)
438
	 * Mais 2 d'entre eux sont identiques, il s'agit de /nvjfl/ontologies/. Or ce webservice supporte le multi-critère.
439
	 * Nous pouvons donc factorisé l'appel pour "conseil_emploi" et "genre", mais pas pour "taxon".
440
	 *
730 raphael 441
	 * @param array in/out $resultats: tous les résultats
442
	 */
443
	public function ajouterChampsOntologieLigneTousResultats(&$resultats) {
832 raphael 444
		$champs_sup = array_intersect($this->champs_supp, array_keys(self::$champ_infos));
730 raphael 445
 
832 raphael 446
		// La regroupement des toutes les valeurs recherchées (pour tous les
447
		// résultats), pour "les" onotologies supportant le multi-critère est effectué ci-dessous.
448
		// Dans les faits ce n'est le cas que pour nvjfl.
449
		$ontologieParamPending = self::NvjflOntologieIndex($resultats, $champs_sup);
450
		$this->NvjflOntologieExpand($ontologieParamPending);
451
		self::NvjflOntologieCombine($resultats);
730 raphael 452
 
832 raphael 453
		// pour les ontologies multi-critères, on vient de le régler ci-dessus
454
		$champs_sup = array_diff($champs_sup, self::$onto_multi_support);
455
 
456
 
457
		// ici, $champs_sup ne peut contenir, au plus, que "taxon".
458
		// code historique:
459
		foreach($champs_sup as $cle) {
460
			$champs_supplementaires = self::$champ_infos[$cle];
730 raphael 461
			// extrait, depuis un élément de $champ_infos:
462
			// $service, $ressource, $projet, $nom, $intitule, $bdd_champ
463
			extract($champs_supplementaires);
464
 
465
			foreach ($resultats as &$tab) {
466
				$valeur_recherche = $tab[$bdd_champ];
467
				if(!trim($valeur_recherche)) continue;
468
 
469
				$url = $this->ajouterHrefAutreProjet($service, $ressource, $valeur_recherche, $projet);
470
				$tab[$intitule] = $this->chercherSignificationCode($url, $nom);
471
			}
472
		}
473
	}
474
 
731 raphael 475
	/* Récupère les valeurs recherchées pour une liste de résultats, (plus ou moins)
476
	   spécifiquement au service d'Ontologies de NVJFL.
477
	   Aggrège les valeurs dans le tableau retourné.
478
	   Une référence vers l'index du tableau (NULL pour l'instant) est laissée dans
479
	   un élément du résultat. */
832 raphael 480
	static function NvjflOntologieIndex(&$resultats, $champs_sup) {
481
		// nous ne supportons le multi-critère que sur les ontologies nvjfl, et nous
482
		// avons précisé celles qui sont concernées dans self::$onto_multi_support
483
		$champs_sup = array_intersect($champs_sup, self::$onto_multi_support);
731 raphael 484
		$ontologieParamPending = Array();
485
		foreach($resultats as &$resultat) {
832 raphael 486
			foreach($champs_sup as $v) {
487
				// de cet extract() nous n'utilisons que $bdd_champ et $ressource
488
				extract(self::$champ_infos[$v]);
489
				if(!isset($resultat[$bdd_champ])) continue;
490
 
491
				$valeur_recherche = $resultat[$bdd_champ];
492
				if(!trim($valeur_recherche)) continue;
493
 
494
				// XXX: $ressource contient déjà ':' comme suffixe
495
				$critere = $ressource . $valeur_recherche;
496
				$ontologieParamPending[$critere] = NULL;
497
				// placeholder pour le résultat
498
				$resultat[SPE_INDEX_NVJFL][$v][$critere] =
499
					&$ontologieParamPending[$critere];
500
			}
731 raphael 501
		}
502
		return $ontologieParamPending;
503
	}
504
 
505
	// TODO: switch to static si il peut en être de même pour ajouterHrefAutreProjet()
506
	/* À partir d'un aggrégat des critère de requêtes d'ontologies, spécifiques à NVJFL,
507
	   créé une URL multi-critère.
508
	   Celle-ci, dans ce cas précis, n'est que la concaténation, par des virgules,
832 raphael 509
	   des couples <ressource:ValeurRecherchée>.
510
	   L'URL est appelée et la valeur correspondante est remplacée dans $criteres_requete.
731 raphael 511
 
512
	   Note: dans le cadre du tryptique index/expand/combine pour lequel cette fonction existe,
832 raphael 513
	   la valeur est référencée par un élément d'une ou plusieurs lignes de $resultat correspondantes.
731 raphael 514
	   Celle(s)-ci sera[ont] donc changée(s) dans la foulée. */
515
	public function NvjflOntologieExpand(&$criteres_requete) {
516
		// équivalent spécifique de ajouterHrefAutreProjet()
517
		$valeurs_requises = implode(',', array_keys($criteres_requete));
832 raphael 518
		// en vérité, nous ne supportons ceci ici que pour nvjfl et non n'importe quel url_service
809 raphael 519
		$url = Config::get('url_service').'/ontologies/'.$valeurs_requises;
731 raphael 520
		$val = $this->consulterHref($url);
831 raphael 521
 
522
		// TODO, le webservice d'ontologies devrait être modifié pour retourner un tableau
523
		// indexé par critère requesté à *CHAQUE* fois, y compris lorsque 1 seul critère est
524
		// demandé.
525
		if(array_key_exists('id', $val) && count($criteres_requete) == 1) {
526
			$k = key($criteres_requete);
527
			$criteres_requete[$k] = $val;
528
			return;
529
		}
530
 
832 raphael 531
		// subtilité, cette affectation modifie par conséquent les valeurs dans
532
		// $resultats[X][SPE_INDEX_NVJFL]
731 raphael 533
		// dont la référence pointe toujours sur $v
534
		foreach($val as $k => $v) $criteres_requete[$k] = $val->$k;
535
	}
536
 
537
	/* Fonction finale du tryptique: réordonne les valeurs obtenues auprès du web-service
832 raphael 538
	   NVJFL en adéquation avec les champs attendus en sortie.
539
	   Dès l'indexation des critères, nous avons associé une (ou plusieurs) référence(s) du
540
	   tableau de résultats vers le tableau de retour des ontologies à l'aide d'un index
541
	   particulier l'index SPE_INDEX_NVJFL qui contient comme élément(s)
542
	   un ou plusieurs ontologies (les indexes de self::$champ_infos) qui elles-mêmes contiennent
543
	   une ou plusieurs valeurs représentant les valeurs recherchées appartement à cette ontologies.
544
	   Celui-ci est supprimé après avoir été correctement copié. */
545
	/**
546
	 * @param array in/out $resultats: tous les résultats
547
	 * @param array in $critere: tableau des ontologies:valeur demandées, de la forme [ numStatut:1, genreNombre:11, ... ]
548
	 */
848 raphael 549
	static function NvjflOntologieCombine(&$resultats) {
731 raphael 550
		foreach($resultats as &$resultat) {
832 raphael 551
			if(!array_key_exists(SPE_INDEX_NVJFL, $resultat)) continue;
552
 
553
			/* Note: la complétude d'un résultat peut dépendre de plusieurs ontologies différentes,
554
			   d'où cette boucle. Cependant une seule valeur sera demandé pour cette ontologie, c'est pourquoi
555
			   $resultat[SPE_INDEX_NVJFL][$onto_name], s'il existe, ne contiendra toujours qu'un seul élément.
556
			   Puisque par définition un résultat contenant des valeurs d'ontologie n'aura jamais qu'un seul et unique
557
			   attribut num_genre (ou num_statut, ou autre) */
558
			foreach(self::$onto_multi_support as $onto_name) {
848 raphael 559
				if(!array_key_exists($onto_name, $resultat[SPE_INDEX_NVJFL])) continue;
560
 
832 raphael 561
				/* $onto_name est un nom d'ontologie (l'une des clefs, parmi conseil_emploi et genre,
562
				   cf la boucle sur $champs_sup dans  NvjflOntologieIndex()
563
				   de cet extract() nous n'utilisons que $intitule et $nom */
564
				extract(self::$champ_infos[$onto_name]);
565
 
566
				// equivalent de l'affectation finale de chercherSignificationCode()
567
				// (utilisé lors de recherches d'ontologies en mono-critère)
568
				// XXX: PHP-5.3 pas de récupération d'attribut sur fonction
569
				$r = current($resultat[SPE_INDEX_NVJFL][$onto_name]);
570
				$resultat[$intitule] = $r->$nom;
571
 
572
				// XXX: certes nous pourrions nous contenter du unset() final
573
				unset($resultat[SPE_INDEX_NVJFL][$onto_name]);
574
			}
575
			unset($resultat[SPE_INDEX_NVJFL]);
731 raphael 576
		}
577
	}
578
 
730 raphael 579
	/**
580
	 * Ajoute les champs d'ontologie supplémentaires si necéssaire
581
	 * en faisant appels aux web services associés
286 aurelien 582
	 * @param array $ligne_resultat
583
	 *
584
	 * @return array la ligne modifiée
585
	 */
284 jpm 586
	public function ajouterChampsOntologieLigneResultat($ligne_resultat) {
832 raphael 587
		foreach(self::$champ_infos as $cle => $champs_supplementaires) {
729 raphael 588
			if(!in_array($cle, $this->champs_supp)) continue;
589
			// extrait, depuis un élément de $champ_infos:
590
			// $service, $ressource, $projet, $nom, $intitule, $bdd_champ
591
			extract($champs_supplementaires);
592
			$valeur_recherche = $ligne_resultat[$bdd_champ];
593
			if(!trim($valeur_recherche)) continue;
594
			$url = $this->ajouterHrefAutreProjet($service, $ressource, $valeur_recherche, $projet);
595
			$ligne_resultat[$intitule] = $this->chercherSignificationCode($url, $nom);
277 aurelien 596
		}
284 jpm 597
		return $ligne_resultat;
277 aurelien 598
	}
599
 
284 jpm 600
	/**
601
	 * Fonction qui ajoute les attributions à une ligne de résultats
602
	 *
603
	 * @param array $ligne_tableau_resultat
604
	 * @param array $nom_sci
605
	 */
606
	public function ajouterTaxonsAttributionsLigneResultat(&$ligne_tableau_resultat, &$noms_sci) {
285 aurelien 607
		if (isset($noms_sci[$ligne_tableau_resultat['num_taxon']])) {
608
			$ligne_tableau_resultat['nom_retenu.code'] = $noms_sci[$ligne_tableau_resultat['num_taxon']]['id'];
609
			$ligne_tableau_resultat['taxon'] = $noms_sci[$ligne_tableau_resultat['num_taxon']]['nom_sci'];
627 aurelien 610
		} else {
611
			$ligne_tableau_resultat = null;
284 jpm 612
		}
613
		return $ligne_tableau_resultat;
614
	}
615
 
616
	private function trierLigneTableau($a, $b) {
617
		$retour = 0;
618
 
619
		if ($a[$this->champ_tri] == $b[$this->champ_tri]) {
620
			$retour = 0;
621
		}
622
 
623
		if($this->champ_tri == 'code_langue') {
624
			if ($a[$this->champ_tri] == 'fra' && $b[$this->champ_tri] != 'fra') {
625
				$retour = ($this->direction_tri == 'asc') ? -1 : 1;
626
			} else if ($a[$this->champ_tri] != 'fra' && $b[$this->champ_tri] == 'fra') {
627
				$retour = ($this->direction_tri == 'asc') ? 1 : -1;
628
			} else {
629
				$retour = $this->comparerChaineSelonDirectionTri($a[$this->champ_tri], $b[$this->champ_tri]);
630
			}
631
		} else {
632
			$retour = $this->comparerChaineSelonDirectionTri($a[$this->champ_tri], $b[$this->champ_tri]);
633
		}
634
		return $retour;
635
	}
636
 
637
	private function comparerChaineSelonDirectionTri($a, $b) {
638
		if($this->direction_tri == 'asc') {
639
			return ($a < $b) ? -1 : 1;
640
		} else {
641
			return ($a > $b) ? -1 : 1;
642
		}
643
	}
644
 
6 jpm 645
	// formatage de la reponse /id ss la forme
646
	// id, nom_vernaculaire, attributions
647
	// langue
648
	// num_nom (correspond à un taxon bdtfx)
649
	public function formaterNomsVernaculairesId($resultat) {
650
		foreach ($resultat as $taxon) { // pour chaque attribution à un taxon bdtfx
651
			// on crée les variables qui serviront de clés et on les enléves du tableau
652
			$num_nom = $taxon['num_nom_vernaculaire']; // unique pour un trinôme id, langue, taxon
653
			unset($taxon['num_nom_vernaculaire']);
654
			$langue = $taxon['code_langue'];
655
			unset($taxon['code_langue']);
109 jpm 656
 
6 jpm 657
			foreach ($this->correspondance_champs as $key => $correspondance) { // ordonne les infos pour affichage
658
				if (isset($taxon[$key]) && $taxon[$key] != "") {
659
					$this->afficherDonnees($correspondance, $taxon[$key], $langue, $num_nom);
660
				}
661
			}
662
			foreach ($taxon as $key => $valeur) { // rajoute les champs non prévus dans l'api
663
				if (!isset($this->correspondance_champs[$key]) && $valeur != "") {
664
					$this->afficherDonnees($key, $valeur, $langue, $num_nom);
665
				}
666
			}
667
			if ($this->retour_format == 'max') $this->chargerBiblio($num_nom, $langue);
668
		}
669
		if ($this->retour_format == 'max') $this->afficherTaxons(); // va chercher les noms de tous les taxons
670
		unset($this->table_retour['href']);
671
		return $this->table_retour;
672
	}
109 jpm 673
 
6 jpm 674
	public function afficherDonnees($champ, $valeur, $langue = '', $num_nom = '') {
675
		if ($champ == 'id' || $champ == 'nom_vernaculaire') {
676
			$this->table_retour[$champ] = $valeur;
677
		} elseif (preg_match('/^(.*)\.code$/', $champ, $match)) {
678
				switch ($match[1]) {
679
					case 'taxon'	: if ($this->retour_format == 'max') {$this->taxons[$num_nom] = $valeur;}
680
						$this->afficherPointCode($match[1], $langue, $num_nom, $valeur);	break;
109 jpm 681
					case 'langue'	: //$this->afficherPointCode($match[1], 'iso-639-3', 'langues', $valeur);
6 jpm 682
						break;
683
					case 'genre'	: $this->afficherPointCode($match[1], $langue, $num_nom, $valeur);	break;
684
					case 'conseil_emploi'	: $this->afficherPointCode($match[1], $langue, $num_nom, $valeur);	break;
685
					default : break;
686
				}
109 jpm 687
 
6 jpm 688
		} elseif ($langue != '') {
689
			$this->table_retour['attributions'][$langue][$num_nom][$champ] = $valeur;
690
		} else {
691
			$this->table_retour[$champ] = $valeur;
692
		}
693
	}
109 jpm 694
 
6 jpm 695
	public function afficherPointCode($nomChamp, $langue, $num_nom, $valeur) {
832 raphael 696
		if (isset(self::$champ_infos[$nomChamp])) {
697
			extract(self::$champ_infos[$nomChamp]);
6 jpm 698
		}
109 jpm 699
 
6 jpm 700
		if ($this->retour_format == 'max') {
701
			$url = $this->ajouterHrefAutreProjet($service, $ressource, $valeur, $projet);
702
			if ($service == 'taxons') {
703
				$code_valeur = '';
164 delphine 704
				$this->table_retour['attributions'][$langue][$num_nom]['nom_retenu.code'] = $code_valeur;
109 jpm 705
			} else {
6 jpm 706
				$code_valeur = $this->chercherSignificationCode($url, $nom);
707
			}
708
			if ($projet != '') $projet .= '.';
709
			$this->table_retour['attributions'][$langue][$num_nom][$nomChamp] = $code_valeur;
710
			$this->table_retour['attributions'][$langue][$num_nom][$nomChamp.'.code'] = $projet.$ressource.$valeur;
711
			$this->table_retour['attributions'][$langue][$num_nom][$nomChamp.'.href'] = $url;
712
		} else {
713
			if ($projet != '') $projet .= '.';
714
			$this->table_retour['attributions'][$langue][$num_nom][$nomChamp.'.code'] = $projet.$ressource.$valeur;
715
		}
716
	}
109 jpm 717
 
6 jpm 718
	public function chercherSignificationCode($url, $nom) {
719
		if (isset($this->signification_code[$url])) {
720
			$valeur = $this->signification_code[$url];
721
		} else {
722
			$res = $this->consulterHref($url);
723
			$valeur = $res->$nom;
724
			$this->signification_code[$url] = $valeur;
725
		}
726
		return $valeur;
727
	}
109 jpm 728
 
6 jpm 729
	public function afficherTaxons() {
160 delphine 730
		$resultat = $this->recupererNomTaxons();
6 jpm 731
		foreach ($this->table_retour['attributions'] as $code_langue=>$langue) {
732
			foreach ($langue as $num_nom=>$taxon) {
733
				$num_tax = ltrim($taxon['taxon.code'], 'bdtfx.nt:');
734
				if (isset($resultat[$num_tax])) {
164 delphine 735
					$this->table_retour['attributions'][$code_langue][$num_nom]['nom_retenu.code'] = $resultat[$num_tax]['id'];
736
					$this->table_retour['attributions'][$code_langue][$num_nom]['taxon'] = $resultat[$num_tax]['nom_sci'];
6 jpm 737
				}
738
			}
739
		}
740
	}
160 delphine 741
 
742
	public function recupererNomTaxons() {
627 aurelien 743
		$taxons = array_unique($this->taxons);
744
		$url = Config::get('url_service_base').'bdtfx/taxons?navigation.limite=500&ns.structure=au&masque.nt='.implode(',', $taxons);
160 delphine 745
		$res = $this->consulterHref($url);
746
		foreach ($res->resultat as $id=>$taxon) {
164 delphine 747
			$resultat[$taxon->num_taxonomique]['id'] = 'bdtfx.nn:'.$id;
627 aurelien 748
			$resultat[$taxon->num_taxonomique]['nom_sci'] = $taxon->nom_sci_complet;
160 delphine 749
		}
750
		return $resultat;
751
	}
6 jpm 752
 
753
	public function formaterNomsVernaculairesIdChamp($resultat) {
109 jpm 754
		$this->table_retour['id'] = $this->ressources[0];
755
		$champs = explode(' ', $this->ressources[1]);
6 jpm 756
		if (in_array('attributions', $champs) != false) {
757
			$this->formaterNomsVernaculairesId($resultat);
758
			unset($this->table_retour['nom_vernaculaire']);
160 delphine 759
		} else {
6 jpm 760
			$champ_attributions = array('num_taxon', 'zone_usage', 'num_statut', 'num_genre', 'notes');
761
			foreach ($resultat as $taxon) {
762
				foreach ($taxon as $key=>$valeur) {
763
					if ($key == 'code_langue' && in_array('langue', $champs) != false) {
764
						$this->table_retour['attributions']['langue'][] = $valeur;
765
					} elseif (in_array($key, $champ_attributions) != false) {
766
						$this->afficherPoint($this->correspondance_champs[$key] , $valeur, $taxon['code_langue'], $taxon['num_nom_vernaculaire']);
767
					} elseif (in_array($key, $champs) != false) {
768
						$this->table_retour[$key] = $valeur;
769
					}
770
				}
771
				if (in_array('biblio', $champs) != false) $this->chargerBiblio($taxon['num_nom_vernaculaire'], $taxon['code_langue']);
772
			}
773
			if (in_array('biblio', $champs) != false && array_search('biblio.num_ref', $this->table_retour) != false) $this->table_retour['biblio'] = null;
774
		}
775
		return $this->table_retour;
776
	}
109 jpm 777
 
6 jpm 778
	public function afficherPoint($champ, $valeur, $langue, $num_nom) {
779
		preg_match('/^(.*)\.code$/', $champ, $match);
780
		$champ = $match[1];
832 raphael 781
		if (isset(self::$champ_infos[$champ])) {
782
			extract(self::$champ_infos[$champ]);
6 jpm 783
			$url = $this->ajouterHrefAutreProjet($service, $ressource, $valeur, $projet);
784
			$projet .= '.';
785
		}
109 jpm 786
 
787
		$champs = explode(' ', $this->ressources[1]);
6 jpm 788
		if (in_array($champ.'.*', $champs) !== false && isset($projet)) {
789
			$this->table_retour['attributions'][$langue][$num_nom][$champ.'.code'] = $projet.$ressource.$valeur;
790
			$this->table_retour['attributions'][$langue][$num_nom][$champ.'.href'] = $url;
109 jpm 791
		}
6 jpm 792
		if (in_array($champ.'.code', $champs) !== false && isset($projet)) {
793
			$this->table_retour['attributions'][$langue][$num_nom][$champ.'.code'] = $projet.$ressource.$valeur;
109 jpm 794
		}
6 jpm 795
		if (in_array($champ.'.href', $champs) !== false && isset($projet)) {
796
			$this->table_retour['attributions'][$langue][$num_nom][$champ.'.href'] = $url;
109 jpm 797
		}
6 jpm 798
		if (in_array($champ, $champs) !== false) {
799
			if (isset($url)) {
800
				$this->table_retour['attributions'][$langue][$num_nom][$champ] = $this->chercherSignificationCode($url, $nom);
801
			} else {
802
				$this->table_retour['attributions'][$langue][$champ] = $valeur;
803
			}
109 jpm 804
		}
6 jpm 805
	}
806
 
807
	public function afficherLangue($nomChamp, $projet, $service, $valeur, $ressource = '', $nom = 'nom') {
808
		if ($this->retour_format == 'max') {
809
				$this->table_retour['attributions'][$nomChamp] = $nom;
810
				$this->table_retour['attributions'][$nomChamp.'.code'] = $projet.$ressource.$valeur;
811
				$this->table_retour['attributions'][$nomChamp.'.href'] = $url;
812
		} else {
813
			$this->table_retour['attributions'][$nomChamp.'.code'] = $projet.$ressource.$valeur;
814
		}
815
	}
109 jpm 816
 
6 jpm 817
	public function chargerBiblio($num_nom, $langue) {
818
		list($table, $version) = explode('_v',$this->table);
819
		$requete = "SELECT b.*, lb.notes FROM nvjfl_lien_biblio_v$version lb, nvjfl_biblio_v$version b ".
820
					"WHERE b.num_ref = lb.num_ref AND lb.num_nom = '$num_nom' ;";
284 jpm 821
		$resultat = $this->getBdd()->recupererTous($requete);
109 jpm 822
 
6 jpm 823
		 if ($resultat == '') { //cas ou la requete comporte des erreurs
824
		 	$r = 'La requête SQL formée comporte une erreur !!';
825
			$this->renvoyerErreur(RestServeur::HTTP_CODE_RESSOURCE_INTROUVABLE, $r);
826
			Debug::printr($requete);
827
		 } elseif ($resultat) {
828
			foreach ($resultat as $res) {
829
			   	foreach ($res as $cle => $valeur) {
830
			   		if ($valeur !== "") {
831
			   			$this->table_retour['attributions'][$langue][$num_nom]['biblio.'.$cle] = $valeur;
832
			   		}
833
			    }
834
			}
835
		}
836
	}
109 jpm 837
 
6 jpm 838
}
839
?>