1 | <?php |
---|
2 | /** |
---|
3 | * Ce fichier contient l'ensemble des constantes et fonctions implémentant le service de taxonomie ITIS. |
---|
4 | * |
---|
5 | * @package SPIP\TAXONOMIE\SERVICES\ITIS |
---|
6 | * @todo phpdoc : exemples |
---|
7 | */ |
---|
8 | if (!defined('_ECRIRE_INC_VERSION')) { |
---|
9 | return; |
---|
10 | } |
---|
11 | |
---|
12 | if (!defined('_TAXONOMIE_ITIS_ENDPOINT_BASE_URL')) { |
---|
13 | /** |
---|
14 | * Préfixe des URL du service web de ITIS. |
---|
15 | */ |
---|
16 | define('_TAXONOMIE_ITIS_ENDPOINT_BASE_URL', 'http://www.itis.gov/ITISWebService/'); |
---|
17 | } |
---|
18 | |
---|
19 | if (!defined('_TAXONOMIE_ITIS_TAXON_BASE_URL')) { |
---|
20 | /** |
---|
21 | * URL de base d'une page d'un taxon sur le site d'ITIS. |
---|
22 | * Cette URL est fournie dans les credits. |
---|
23 | */ |
---|
24 | define('_TAXONOMIE_ITIS_TAXON_BASE_URL', 'http://www.itis.gov/servlet/SingleRpt/SingleRpt?search_topic=TSN&search_value='); |
---|
25 | } |
---|
26 | |
---|
27 | if (!defined('_TAXONOMIE_ITIS_SITE_URL')) { |
---|
28 | /** |
---|
29 | * URL de la page d'accueil du site ITIS. |
---|
30 | * Cette URL est fournie dans les credits. |
---|
31 | */ |
---|
32 | define('_TAXONOMIE_ITIS_SITE_URL', 'http://www.itis.gov'); |
---|
33 | } |
---|
34 | |
---|
35 | if (!defined('_TAXONOMIE_ITIS_REGEXP_RANKNAME')) { |
---|
36 | /** |
---|
37 | * Ligne d'un fichier ITIS hiérachie généré. |
---|
38 | * Il est indispensable de respecter les majuscules des noms de groupe pour éviter de matcher |
---|
39 | * les suborder, infrakingdom... |
---|
40 | */ |
---|
41 | define('_TAXONOMIE_ITIS_REGEXP_RANKNAME', '#(%rank_list%):\s*(([A-Z]\s+)?[\w-]+)\s*(.+)\s*\[(\d+)\]\s*$#'); |
---|
42 | } |
---|
43 | |
---|
44 | |
---|
45 | $GLOBALS['itis_language'] = array( |
---|
46 | /** |
---|
47 | * Variable globale de configuration de la correspondance entre langue Wikipedia |
---|
48 | * et code de langue SPIP. La langue du service est l'index, le code SPIP est la valeur. |
---|
49 | */ |
---|
50 | 'french' => 'fr', |
---|
51 | 'english' => 'en', |
---|
52 | 'spanish' => 'es' |
---|
53 | ); |
---|
54 | $GLOBALS['itis_webservice'] = array( |
---|
55 | /** |
---|
56 | * Variable globale de configuration de l'api des actions du service web ITIS |
---|
57 | */ |
---|
58 | 'search' => array( |
---|
59 | 'commonname' => array( |
---|
60 | 'function' => 'searchByCommonName', |
---|
61 | 'argument' => 'srchKey', |
---|
62 | 'list' => 'commonNames', |
---|
63 | 'index' => array('tsn' => 'tsn'), |
---|
64 | 'find' => array('nom_commun' => 'commonName') |
---|
65 | ), |
---|
66 | 'scientificname' => array( |
---|
67 | 'function' => 'searchByScientificName', |
---|
68 | 'argument' => 'srchKey', |
---|
69 | 'list' => 'scientificNames', |
---|
70 | 'index' => array('tsn' => 'tsn'), |
---|
71 | 'find' => array('nom_scientifique' => 'combinedName') |
---|
72 | ) |
---|
73 | ), |
---|
74 | 'vernacular' => array( |
---|
75 | 'vernacularlanguage' => array( |
---|
76 | 'function' => 'getTsnByVernacularLanguage', |
---|
77 | 'argument' => 'language', |
---|
78 | 'list' => 'vernacularTsns', |
---|
79 | 'index' => array('tsn' => 'commonName') |
---|
80 | ) |
---|
81 | ), |
---|
82 | 'getfull' => array( |
---|
83 | 'record' => array( |
---|
84 | 'function' => 'getFullRecordFromTSN', |
---|
85 | 'argument' => 'tsn', |
---|
86 | 'list' => '', |
---|
87 | 'index' => array( |
---|
88 | 'nom_scientifique' => 'scientificName/combinedName', |
---|
89 | 'rang' => 'taxRank/rankName', |
---|
90 | 'regne' => 'kingdom/kingdomName', |
---|
91 | 'tsn_parent' => 'parentTSN/parentTsn', |
---|
92 | 'auteur' => 'taxonAuthor/authorship', |
---|
93 | 'nom_commun' => 'commonNameList/commonNames', |
---|
94 | ) |
---|
95 | ) |
---|
96 | ), |
---|
97 | 'get' => array( |
---|
98 | 'scientificname' => array( |
---|
99 | 'function' => 'getScientificNameFromTSN', |
---|
100 | 'argument' => 'tsn', |
---|
101 | 'list' => '', |
---|
102 | 'index' => array('string', 'combinedName'), |
---|
103 | ), |
---|
104 | 'kingdomname' => array( |
---|
105 | 'function' => 'getKingdomNameFromTSN', |
---|
106 | 'argument' => 'tsn', |
---|
107 | 'list' => '', |
---|
108 | 'index' => array('string', 'kingdomName'), |
---|
109 | ), |
---|
110 | 'parent' => array( |
---|
111 | 'function' => 'getHierarchyUpFromTSN', |
---|
112 | 'argument' => 'tsn', |
---|
113 | 'list' => '', |
---|
114 | 'index' => array('string', 'parentTsn'), |
---|
115 | ), |
---|
116 | 'rankname' => array( |
---|
117 | 'function' => 'getTaxonomicRankNameFromTSN', |
---|
118 | 'argument' => 'tsn', |
---|
119 | 'list' => '', |
---|
120 | 'index' => array('string', 'rankName'), |
---|
121 | ), |
---|
122 | 'author' => array( |
---|
123 | 'function' => 'getTaxonAuthorshipFromTSN', |
---|
124 | 'argument' => 'tsn', |
---|
125 | 'list' => '', |
---|
126 | 'index' => array('string', 'authorship'), |
---|
127 | ), |
---|
128 | 'coremetadata' => array( |
---|
129 | 'function' => 'getCoreMetadataFromTSN', |
---|
130 | 'argument' => 'tsn', |
---|
131 | 'list' => '', |
---|
132 | 'index' => array('array', ''), |
---|
133 | ), |
---|
134 | 'experts' => array( |
---|
135 | 'function' => 'getExpertsFromTSN', |
---|
136 | 'argument' => 'tsn', |
---|
137 | 'list' => 'experts', |
---|
138 | 'index' => array('array', ''), |
---|
139 | ), |
---|
140 | 'commonnames' => array( |
---|
141 | 'function' => 'getCommonNamesFromTSN', |
---|
142 | 'argument' => 'tsn', |
---|
143 | 'list' => 'commonNames', |
---|
144 | 'index' => array('array', array('language' => 'commonName')), |
---|
145 | ), |
---|
146 | 'othersources' => array( |
---|
147 | 'function' => 'getOtherSourcesFromTSN', |
---|
148 | 'argument' => 'tsn', |
---|
149 | 'list' => 'otherSources', |
---|
150 | 'index' => array('array', ''), |
---|
151 | ), |
---|
152 | 'hierarchyfull' => array( |
---|
153 | 'function' => 'getFullHierarchyFromTSN', |
---|
154 | 'argument' => 'tsn', |
---|
155 | 'list' => 'hierarchyList', |
---|
156 | 'index' => array('array', ''), |
---|
157 | ), |
---|
158 | 'hierarchydown' => array( |
---|
159 | 'function' => 'getHierarchyDownFromTSN', |
---|
160 | 'argument' => 'tsn', |
---|
161 | 'list' => 'hierarchyList', |
---|
162 | 'index' => array('array', ''), |
---|
163 | ), |
---|
164 | ), |
---|
165 | ); |
---|
166 | |
---|
167 | |
---|
168 | // ----------------------------------------------------------------------- |
---|
169 | // ------------ API du web service ITIS - Actions principales ------------ |
---|
170 | // ----------------------------------------------------------------------- |
---|
171 | |
---|
172 | /** |
---|
173 | * Recherche un taxon dans la base ITIS par son nom commun ou scientifique |
---|
174 | * et retourne son identifiant unique nommé TSN ou 0 si le taxon n'existe pas. |
---|
175 | * Selon le critère de correspondance de la recherche (stricte ou pas) la fonction |
---|
176 | * retourne un ou plusieurs taxons. |
---|
177 | * |
---|
178 | * @api |
---|
179 | * @uses itis_build_url() |
---|
180 | * @uses service_requeter_json() |
---|
181 | * |
---|
182 | * @param string $action |
---|
183 | * Recherche par nom commun ou par nom scientifique. Prend les valeurs `commonname` ou `scientificname` |
---|
184 | * @param string $search |
---|
185 | * Nom à rechercher précisément. Seul le taxon dont le nom coincidera exactement sera retourné. |
---|
186 | * @param bool $strict |
---|
187 | * `true` indique une correspondance stricte de la chaine recherchée ce qui a pour conséquence de renvoyer |
---|
188 | * une seule valeur de TSN. `false` indique une correspondance partielle et peut donc renvoyer plusieurs TSN. |
---|
189 | * |
---|
190 | * @return array |
---|
191 | * Si la recherche est stricte, la fonction retourne l'identifiant unique TSN dans la base ITIS |
---|
192 | * ou 0 si la recherche échoue. |
---|
193 | * Sinon, la fonction retourne une liste de couples de valeurs (TNS, valeur trouvée). |
---|
194 | */ |
---|
195 | function itis_search_tsn($action, $search, $strict = true) { |
---|
196 | |
---|
197 | $tsn = array(); |
---|
198 | |
---|
199 | // Normaliser la recherche: trim et mise en lettres minuscules |
---|
200 | $search = strtolower(trim($search)); |
---|
201 | |
---|
202 | // Construire l'URL de la fonction de recherche |
---|
203 | $url = itis_build_url('json', 'search', $action, rawurlencode($search)); |
---|
204 | |
---|
205 | // Acquisition des données spécifiées par l'url |
---|
206 | $requeter = charger_fonction('taxonomie_requeter', 'inc'); |
---|
207 | $data = $requeter($url); |
---|
208 | |
---|
209 | // Récupération du TSN du taxon recherché |
---|
210 | $api = $GLOBALS['itis_webservice']['search'][$action]; |
---|
211 | if (!empty($data[$api['list']])) { |
---|
212 | // La recherche peut renvoyer plusieurs taxons. Suivant le critère de correspondance de la recherche |
---|
213 | // on renvoie le "bon" taxon ou tous les taxons trouvés. |
---|
214 | $tsn_destination = reset($api['index']); |
---|
215 | $tsn_key = key($api['index']); |
---|
216 | $search_destination = reset($api['find']); |
---|
217 | $search_key = key($api['find']); |
---|
218 | foreach ($data[$api['list']] as $_data) { |
---|
219 | if ($_data) { |
---|
220 | if (!$strict or ($strict and (strcasecmp($_data[$search_key], $search) == 0))) { |
---|
221 | $tsn[] = array( |
---|
222 | $tsn_destination => intval($_data[$tsn_key]), |
---|
223 | $search_destination => $_data[$search_key] |
---|
224 | ); |
---|
225 | if ($strict) { |
---|
226 | break; |
---|
227 | } |
---|
228 | } |
---|
229 | } |
---|
230 | } |
---|
231 | } |
---|
232 | |
---|
233 | return $tsn; |
---|
234 | } |
---|
235 | |
---|
236 | |
---|
237 | /** |
---|
238 | * Renvoie l'ensemble des informations sur un taxon désigné par son identifiant unique TSN. |
---|
239 | * |
---|
240 | * @api |
---|
241 | * @uses itis_build_url() |
---|
242 | * @uses service_requeter_json() |
---|
243 | * |
---|
244 | * @param int $tsn |
---|
245 | * Identifiant unique du taxon dans la base ITIS, le TSN |
---|
246 | * |
---|
247 | * @return array |
---|
248 | * Si le taxon est trouvé, le tableau renvoyé possède les index associatifs suivants: |
---|
249 | * - `nom_scientique` : le nom scientifique du taxon en minuscules |
---|
250 | * - `rang` : le nom anglais du rang taxonomique du taxon |
---|
251 | * - `regne` : le nom scientifque du règne du taxon en minuscules |
---|
252 | * - `tsn_parent` : le TSN du parent du taxon ou 0 si le taxon est un règne |
---|
253 | * - `auteur` : la citation d’auteurs et la date de publication |
---|
254 | * - `nom_commun` : un tableau indexé par langue (au sens d'ITIS en minuscules, `english`, `french`, |
---|
255 | * `spanish`) fournissant le nom commun dans chacune des langues |
---|
256 | */ |
---|
257 | function itis_get_record($tsn) { |
---|
258 | |
---|
259 | $record = array(); |
---|
260 | |
---|
261 | // Construire l'URL de l'api sollicitée |
---|
262 | $url = itis_build_url('json', 'getfull', 'record', strval($tsn)); |
---|
263 | |
---|
264 | // Acquisition des données spécifiées par l'url |
---|
265 | $requeter = charger_fonction('taxonomie_requeter', 'inc'); |
---|
266 | $data = $requeter($url); |
---|
267 | |
---|
268 | // Récupération des informations choisies parmi l'enregistrement reçu à partir de la configuration |
---|
269 | // de l'action. |
---|
270 | $api = $GLOBALS['itis_webservice']['getfull']['record']; |
---|
271 | include_spip('inc/filtres'); |
---|
272 | $data = $api['list'] ? table_valeur($data, $api['list'], null) : $data; |
---|
273 | if (!empty($data)) { |
---|
274 | foreach ($api['index'] as $_destination => $_keys) { |
---|
275 | $element = $_keys ? table_valeur($data, $_keys, null) : $data; |
---|
276 | $record[$_destination] = is_string($element) ? trim($element) : $element; |
---|
277 | } |
---|
278 | } |
---|
279 | |
---|
280 | // On réorganise le sous-tableau des noms communs |
---|
281 | $noms = array(); |
---|
282 | if (is_array($record['nom_commun']) and $record['nom_commun']) { |
---|
283 | foreach ($record['nom_commun'] as $_nom) { |
---|
284 | $noms[strtolower($_nom['language'])] = trim($_nom['commonName']); |
---|
285 | } |
---|
286 | } |
---|
287 | // Et on modifie l'index des noms communs avec le tableau venant d'être construit. |
---|
288 | $record['nom_commun'] = $noms; |
---|
289 | |
---|
290 | return $record; |
---|
291 | } |
---|
292 | |
---|
293 | |
---|
294 | /** |
---|
295 | * Renvoie les informations demandées sur un taxon désigné par son identifiant unique TSN. |
---|
296 | * |
---|
297 | * @api |
---|
298 | * @uses itis_build_url() |
---|
299 | * @uses service_requeter_json() |
---|
300 | * |
---|
301 | * @param string $action |
---|
302 | * Type d'information demandé. Prend les valeurs |
---|
303 | * - `scientificname` : le nom scientifique du taxon |
---|
304 | * - `kingdomname` : le règne du taxon |
---|
305 | * - `parent` : le taxon parent dont son TSN |
---|
306 | * - `rankname` : le rang taxonomique du taxon |
---|
307 | * - `author` : le ou les auteurs du taxon |
---|
308 | * - `coremetadata` : les métadonnées (à vérifier) |
---|
309 | * - `experts` : les experts du taxon |
---|
310 | * - `commonnames` : le ou les noms communs |
---|
311 | * - `othersources` : les sources d'information sur le taxon |
---|
312 | * - `hierarchyfull` : la hiérarchie complète jusqu'au taxon |
---|
313 | * - `hierarchydown` : la hiérarchie (à vérifier) |
---|
314 | * @param int $tsn |
---|
315 | * Identifiant unique du taxon dans la base ITIS (TSN) |
---|
316 | * |
---|
317 | * @return string|array |
---|
318 | * Chaine ou tableau caractéristique du type d'information demandé. |
---|
319 | */ |
---|
320 | function itis_get_information($action, $tsn) { |
---|
321 | |
---|
322 | // Construire l'URL de l'api sollicitée |
---|
323 | $url = itis_build_url('json', 'get', $action, strval($tsn)); |
---|
324 | |
---|
325 | // Acquisition des données spécifiées par l'url |
---|
326 | $requeter = charger_fonction('taxonomie_requeter', 'inc'); |
---|
327 | $data = $requeter($url); |
---|
328 | |
---|
329 | // On vérifie que le tableau est complet sinon on retourne un tableau vide |
---|
330 | $api = $GLOBALS['itis_webservice']['get'][$action]; |
---|
331 | include_spip('inc/filtres'); |
---|
332 | $data = $api['list'] ? table_valeur($data, $api['list'], null) : $data; |
---|
333 | list($type, $index) = $api['index']; |
---|
334 | |
---|
335 | if ($type == 'string') { |
---|
336 | $information = ''; |
---|
337 | if (!empty($data[$index])) { |
---|
338 | $information = $data[$index]; |
---|
339 | } |
---|
340 | } else { |
---|
341 | $information = array(); |
---|
342 | if ($data) { |
---|
343 | $first_value = reset($data); |
---|
344 | if ($first_value) { |
---|
345 | if (!$index) { |
---|
346 | $information = $data; |
---|
347 | $format = "format_$action"; |
---|
348 | if (function_exists($format)) { |
---|
349 | $information = $format($information); |
---|
350 | } |
---|
351 | } else { |
---|
352 | $destination = reset($index); |
---|
353 | $key = key($index); |
---|
354 | foreach ($data as $_data) { |
---|
355 | $information[strtolower($_data[$destination])][] = $_data[$key]; |
---|
356 | } |
---|
357 | } |
---|
358 | } |
---|
359 | } |
---|
360 | } |
---|
361 | |
---|
362 | return $information; |
---|
363 | } |
---|
364 | |
---|
365 | |
---|
366 | /** |
---|
367 | * Renvoie la liste des noms communs définis pour certains taxons dans une langue donnée mais |
---|
368 | * tout règne confondu. |
---|
369 | * Peu de taxons sont traduits dans la base ITIS, seules le français, l'anglais et |
---|
370 | * l'espagnol sont réellement utilisables. |
---|
371 | * Pour l'anglais, le nombre de taxons est très important car les 4 règnes non supportés par |
---|
372 | * le plugin Taxonomie sont fortement traduits. |
---|
373 | * |
---|
374 | * @api |
---|
375 | * @uses itis_build_url() |
---|
376 | * @uses service_requeter_json() |
---|
377 | * |
---|
378 | * @param $language |
---|
379 | * Langue au sens d'ITIS écrite en minuscules. Vaut `french`, `english`, `spanish`... |
---|
380 | * |
---|
381 | * @return array |
---|
382 | * Tableau des noms communs associés à leur TSN. Le format du tableau est le suivant: |
---|
383 | * - l'index représente le TSN du taxon, |
---|
384 | * - la valeur fournit le tableau des noms communs, chaque nom étant préfixé du code de langue |
---|
385 | * de SPIP (ex: `[fr]bactéries`) |
---|
386 | */ |
---|
387 | function itis_list_vernaculars($language) { |
---|
388 | |
---|
389 | $vernaculars = array(); |
---|
390 | |
---|
391 | // Construire l'URL de l'api sollicitée |
---|
392 | $url = itis_build_url('json', 'vernacular', 'vernacularlanguage', $language); |
---|
393 | |
---|
394 | // Acquisition des données spécifiées par l'url |
---|
395 | include_spip('inc/distant'); |
---|
396 | $requeter = charger_fonction('taxonomie_requeter', 'inc'); |
---|
397 | $data = $requeter($url, _INC_DISTANT_MAX_SIZE * 7); |
---|
398 | |
---|
399 | $api = $GLOBALS['itis_webservice']['vernacular']['vernacularlanguage']; |
---|
400 | if (!empty($data[$api['list']])) { |
---|
401 | $tag_language = '[' . $GLOBALS['itis_language'][$language] . ']'; |
---|
402 | $destination = reset($api['index']); |
---|
403 | $key = key($api['index']); |
---|
404 | foreach ($data[$api['list']] as $_data) { |
---|
405 | if (!empty($_data[$destination]) |
---|
406 | and !empty($_data[$key]) |
---|
407 | ) { |
---|
408 | $vernaculars[$_data[$destination]][] = $tag_language . $_data[$key]; |
---|
409 | } |
---|
410 | } |
---|
411 | } |
---|
412 | |
---|
413 | return $vernaculars; |
---|
414 | } |
---|
415 | |
---|
416 | |
---|
417 | // ----------------------------------------------------------------------------------------------- |
---|
418 | // ------------ API du web service ITIS - Fonctions de lecture des fichiers de taxons ------------ |
---|
419 | // ----------------------------------------------------------------------------------------------- |
---|
420 | |
---|
421 | /** |
---|
422 | * Lit le fichier hiérarchique ITIS des taxons d'un règne et renvoie la liste des taxons retenus. |
---|
423 | * |
---|
424 | * @api |
---|
425 | * |
---|
426 | * @param string $kingdom |
---|
427 | * Nom scientifique du règne en lettres minuscules : `animalia`, `plantae`, `fungi`. |
---|
428 | * @param array $ranks |
---|
429 | * Liste des rangs à charger à partir du fichier des taxons. Cette liste contient soit les rangs |
---|
430 | * principaux du règne, soit les rangs principaux et secondaires, soit tous les rangs y compris |
---|
431 | * les rangs intercalaires. |
---|
432 | * Le tableau est de la forme [nom anglais du rang en minuscules] = id ITIS du rang |
---|
433 | * @param int $sha_file |
---|
434 | * Sha calculé à partir du fichier de taxons correspondant au règne choisi. Le sha est retourné |
---|
435 | * par la fonction afin d'être stocké par le plugin. |
---|
436 | * |
---|
437 | * @return array |
---|
438 | * Chaque élément du tableau est un taxon. Un taxon est un tableau associatif dont chaque |
---|
439 | * index correspond à un champ de la table `spip_taxons`. Le tableau est ainsi prêt pour une |
---|
440 | * insertion en base de données. |
---|
441 | */ |
---|
442 | function itis_read_hierarchy($kingdom, $ranks, &$sha_file) { |
---|
443 | |
---|
444 | $hierarchy = array(); |
---|
445 | $sha_file = false; |
---|
446 | |
---|
447 | if ($ranks) { |
---|
448 | // Classer la liste des rangs de manière à aller du règne au genre. |
---|
449 | asort($ranks); |
---|
450 | |
---|
451 | // Construire la regexp qui permet de limiter la hiérarchie comme demandée |
---|
452 | include_spip('inc/taxonomer'); |
---|
453 | $rank_list = implode('|', array_map('ucfirst', array_keys($ranks))); |
---|
454 | $regexp = str_replace('%rank_list%', $rank_list, _TAXONOMIE_ITIS_REGEXP_RANKNAME); |
---|
455 | |
---|
456 | $file = find_in_path('services/itis/' . ucfirst($kingdom) . '_Genus.txt'); |
---|
457 | if (file_exists($file) and ($sha_file = sha1_file($file))) { |
---|
458 | $lines = file($file); |
---|
459 | if ($lines) { |
---|
460 | $parents = array(); |
---|
461 | $rank_position = 0; |
---|
462 | foreach ($ranks as $_rank_name => $_rank_id) { |
---|
463 | $parents[$_rank_id] = 0; |
---|
464 | $rank_position++; |
---|
465 | $ranks[$_rank_name] = $rank_position; |
---|
466 | } |
---|
467 | $max_rank_position = $rank_position; |
---|
468 | // Scan du fichier ligne par ligne |
---|
469 | include_spip('inc/charsets'); |
---|
470 | foreach ($lines as $_line) { |
---|
471 | $taxon = array( |
---|
472 | 'regne' => $kingdom, |
---|
473 | 'nom_commun' => '', |
---|
474 | 'descriptif' => '', |
---|
475 | 'indicateur' => '', |
---|
476 | 'edite' => 'non' |
---|
477 | ); |
---|
478 | if (preg_match($regexp, $_line, $match)) { |
---|
479 | // Initialisation du taxon |
---|
480 | $taxon['rang'] = strtolower($match[1]); |
---|
481 | $taxon['nom_scientifique'] = strtolower($match[2]); |
---|
482 | $taxon['auteur'] = trim(importer_charset(trim($match[4]), 'iso-8859-1'), '[]'); |
---|
483 | $tsn = intval($match[5]); |
---|
484 | $taxon['tsn'] = $tsn; |
---|
485 | |
---|
486 | // Vérifier si il existe un indicateur spécial dans le nom scientifique comme |
---|
487 | // un X pour indiquer un taxon hybride. |
---|
488 | if (strtolower(trim($match[3])) == 'x') { |
---|
489 | $taxon['indicateur'] = 'hybride'; |
---|
490 | } |
---|
491 | |
---|
492 | // Recherche du parent |
---|
493 | $taxon_rank_position = $ranks[$taxon['rang']]; |
---|
494 | if ($taxon_rank_position == $ranks[_TAXONOMIE_RANG_REGNE]) { |
---|
495 | // On traite à part le cas du règne qui ne se rencontre qu'une fois en début de fichier |
---|
496 | $taxon['tsn_parent'] = 0; |
---|
497 | } else { |
---|
498 | // On recherche le premier parent donc la position n'est pas 0. |
---|
499 | for ($i = $taxon_rank_position - 1; $i >= 1; $i--) { |
---|
500 | if ($parents[$i]) { |
---|
501 | $taxon['tsn_parent'] = $parents[$i]; |
---|
502 | break; |
---|
503 | } |
---|
504 | } |
---|
505 | } |
---|
506 | |
---|
507 | // Insertion du taxon dans la hiérarchie |
---|
508 | $hierarchy[$tsn] = $taxon; |
---|
509 | |
---|
510 | // Stockage du TSN du rang venant d'être inséré |
---|
511 | $parents[$taxon_rank_position] = $tsn; |
---|
512 | // On vide les position de rangs d'après |
---|
513 | for ($i = $taxon_rank_position + 1; $i <= $max_rank_position; $i++) { |
---|
514 | $parents[$i] = 0; |
---|
515 | } |
---|
516 | } else { |
---|
517 | // On trace la ligne qui n'est pas détectée comme une ligne de taxon. |
---|
518 | spip_log("Ligne non phrasée: ${_line}", 'taxonomie'); |
---|
519 | } |
---|
520 | } |
---|
521 | } |
---|
522 | } |
---|
523 | } |
---|
524 | |
---|
525 | return $hierarchy; |
---|
526 | } |
---|
527 | |
---|
528 | |
---|
529 | /** |
---|
530 | * Lit le fichier des noms communs - tout règne confondu - d'une langue donnée et renvoie un tableau |
---|
531 | * de tous ces noms indexés par leur TSN. |
---|
532 | * La base de données ITIS contient souvent plusieurs traductions d'une même langue pour un taxon donné. Cette |
---|
533 | * fonction met à jour séquentiellement les traductions sans s'en préoccuper. De fait, c'est la dernière traduction |
---|
534 | * rencontrée qui sera fournie dans le tableau de sortie. |
---|
535 | * |
---|
536 | * @api |
---|
537 | * |
---|
538 | * @param string $language |
---|
539 | * Langue au sens d'ITIS écrite en minuscules. Vaut `french`, `english`, `spanish` etc. |
---|
540 | * @param int $sha_file |
---|
541 | * Sha calculé à partir du fichier des noms communs choisi. Le sha est retourné |
---|
542 | * par la fonction afin d'être stocké par le plugin. |
---|
543 | * |
---|
544 | * @return array |
---|
545 | * Tableau des noms communs d'une langue donnée indexé par TSN. Le nom commun est préfixé |
---|
546 | * par le tag de langue SPIP pour être utilisé simplement dans une balise `<multi>`. |
---|
547 | */ |
---|
548 | function itis_read_vernaculars($language, &$sha_file) { |
---|
549 | |
---|
550 | $vernaculars = array(); |
---|
551 | $sha_file = false; |
---|
552 | |
---|
553 | // Ouvrir le fichier de nom communs correspondant au code de langue spécifié |
---|
554 | $file = find_in_path("services/itis/vernaculars_${language}.csv"); |
---|
555 | if (file_exists($file) and ($sha_file = sha1_file($file))) { |
---|
556 | // Lecture du fichier csv comme un fichier texte sachant que : |
---|
557 | // - le délimiteur de colonne est une virgule |
---|
558 | // - le caractère d'encadrement d'un texte est le double-quotes |
---|
559 | $lines = file($file); |
---|
560 | if ($lines) { |
---|
561 | // Créer le tableau de sortie à partir du tableau issu du csv (TSN, nom commun) |
---|
562 | $tag_language = '[' . $GLOBALS['itis_language'][$language] . ']'; |
---|
563 | foreach ($lines as $_line) { |
---|
564 | list($tsn, $name) = explode(',', trim($_line)); |
---|
565 | $vernaculars[intval($tsn)] = $tag_language . trim($name, '"'); |
---|
566 | } |
---|
567 | } |
---|
568 | } |
---|
569 | |
---|
570 | return $vernaculars; |
---|
571 | } |
---|
572 | |
---|
573 | |
---|
574 | /** |
---|
575 | * Lit le fichier des rangs d'un règne donné et construit la hiérarchie de ces mêmes rangs. |
---|
576 | * |
---|
577 | * @api |
---|
578 | * |
---|
579 | * @param string $kingdom |
---|
580 | * Nom scientifique du règne en lettres minuscules : `animalia`, `plantae`, `fungi`. |
---|
581 | * @param int $sha_file |
---|
582 | * Sha calculé à partir du fichier de taxons correspondant au règne choisi. Le sha est retourné |
---|
583 | * par la fonction afin d'être stocké par le plugin. |
---|
584 | * |
---|
585 | * @return array |
---|
586 | * Tableau des rangs identifiés par leur nom scientifique en anglais et organisé comme une hiérarchie |
---|
587 | * du règne au rang de plus bas niveau. |
---|
588 | */ |
---|
589 | function itis_read_ranks($kingdom, &$sha_file) { |
---|
590 | |
---|
591 | $ranks = array(); |
---|
592 | $sha_file = false; |
---|
593 | |
---|
594 | // Ouvrir le fichier des rangs du règne spécifié. |
---|
595 | $file = find_in_path("services/itis/${kingdom}_ranks.json"); |
---|
596 | if (file_exists($file) and ($sha_file = sha1_file($file))) { |
---|
597 | // Lecture du fichier json et décodage en tableau. |
---|
598 | include_spip('inc/flock'); |
---|
599 | lire_fichier($file, $content); |
---|
600 | if ($content) { |
---|
601 | $itis_ranks = json_decode($content, true); |
---|
602 | if ($itis_ranks) { |
---|
603 | // Le fichier est toujours classé du règne au rang fils le plus bas dans l'arborescence. |
---|
604 | // On peut donc être assuré que le parent d'un rang donné a toujours été préalablement |
---|
605 | // traité sauf le premier, le règne. |
---|
606 | include_spip('inc/taxonomer'); |
---|
607 | $rank_ids = array(); |
---|
608 | foreach ($itis_ranks as $_rank) { |
---|
609 | $rank_name = strtolower($_rank['rank_name']); |
---|
610 | // -- Sauvegarde de l'id qui servira lors de la lecture du fichier hiérarchique des taxons. |
---|
611 | $ranks[$rank_name]['id'] = $_rank['rank_id']; |
---|
612 | // -- Détermination des parents |
---|
613 | if (isset($rank_ids[$_rank['dir_parent_rank_id']]) and isset($rank_ids[$_rank['req_parent_rank_id']])) { |
---|
614 | // Cas des rangs enfant du règne. |
---|
615 | $ranks[$rank_name]['parent'] = $rank_ids[$_rank['dir_parent_rank_id']]; |
---|
616 | $ranks[$rank_name]['parent_principal'] = $rank_ids[$_rank['req_parent_rank_id']]; |
---|
617 | } else { |
---|
618 | // Cas du règne qui n'a pas de parent. |
---|
619 | $ranks[$rank_name]['parent'] = ''; |
---|
620 | $ranks[$rank_name]['parent_principal'] = ''; |
---|
621 | } |
---|
622 | // -- Détermination du type de rang |
---|
623 | if ((strpos(_TAXONOMIE_RANGS_PRINCIPAUX, $rank_name) !== false) |
---|
624 | or ($rank_name == _TAXONOMIE_RANG_DIVISION)) { |
---|
625 | $ranks[$rank_name]['type'] = _TAXONOMIE_RANG_TYPE_PRINCIPAL; |
---|
626 | } elseif (strpos(_TAXONOMIE_RANGS_SECONDAIRES, $rank_name) !== false) { |
---|
627 | $ranks[$rank_name]['type'] = _TAXONOMIE_RANG_TYPE_SECONDAIRE; |
---|
628 | } else{ |
---|
629 | $ranks[$rank_name]['type'] = _TAXONOMIE_RANG_TYPE_INTERCALAIRE; |
---|
630 | } |
---|
631 | |
---|
632 | // -- Sauvegarde de l'id ITIS du rang traité pour les descendants. |
---|
633 | $rank_ids[$_rank['rank_id']] = $rank_name; |
---|
634 | } |
---|
635 | } |
---|
636 | } |
---|
637 | } |
---|
638 | |
---|
639 | return $ranks; |
---|
640 | } |
---|
641 | |
---|
642 | |
---|
643 | // --------------------------------------------------------------------- |
---|
644 | // ------------ API du web service ITIS - Fonctions annexes ------------ |
---|
645 | // --------------------------------------------------------------------- |
---|
646 | |
---|
647 | /** |
---|
648 | * Renvoie la langue telle que le service ITIS la désigne à partir du code de langue |
---|
649 | * de SPIP. |
---|
650 | * |
---|
651 | * @api |
---|
652 | * |
---|
653 | * @param string $spip_language |
---|
654 | * Code de langue de SPIP. Prend les valeurs `fr`, `en`, `es`, etc. |
---|
655 | * La variable globale `$GLOBALS['itis_language']` définit le transcodage langue ITIS vers code SPIP. |
---|
656 | * |
---|
657 | * @return string |
---|
658 | * Langue au sens d'ITIS en minuscules - `french`, `english`, `spanish` - ou chaine vide sinon. |
---|
659 | */ |
---|
660 | function itis_find_language($spip_language) { |
---|
661 | |
---|
662 | if (!$language = array_search($spip_language, $GLOBALS['itis_language'])) { |
---|
663 | $language = ''; |
---|
664 | } |
---|
665 | |
---|
666 | return $language; |
---|
667 | } |
---|
668 | |
---|
669 | |
---|
670 | /** |
---|
671 | * Construit la phrase de crédits précisant que les données fournies proviennent de la base de données |
---|
672 | * d'ITIS. |
---|
673 | * |
---|
674 | * @api |
---|
675 | * |
---|
676 | * @param int $id_taxon |
---|
677 | * Id du taxon nécessaire pour construire l'url de la page ITIS fournissant une information complète sur |
---|
678 | * le taxon. |
---|
679 | * @param array $informations |
---|
680 | * Tableau des informations complémentaires sur la source. Pour ITIS ce tableau est vide. |
---|
681 | * |
---|
682 | * @return string |
---|
683 | * Phrase de crédit. |
---|
684 | */ |
---|
685 | function itis_credit($id_taxon, $informations = array()) { |
---|
686 | |
---|
687 | // On recherche le TSN du taxon afin de construire l'url vers sa page sur ITIS |
---|
688 | $taxon = sql_fetsel('tsn, nom_scientifique', 'spip_taxons', 'id_taxon=' . sql_quote($id_taxon)); |
---|
689 | |
---|
690 | // On crée l'url du taxon sur le site ITIS |
---|
691 | $url_taxon = _TAXONOMIE_ITIS_TAXON_BASE_URL . $taxon['tsn']; |
---|
692 | $link_taxon = '<a class="nom_scientifique" href="' . $url_taxon . '" rel="noreferrer">' . ucfirst($taxon['nom_scientifique']) . '</a>'; |
---|
693 | $link_site = '<a href="' . _TAXONOMIE_ITIS_SITE_URL . '" rel="noreferrer">' . _TAXONOMIE_ITIS_SITE_URL . '</a>'; |
---|
694 | |
---|
695 | // On établit la citation |
---|
696 | $credit = _T('taxonomie:credit_itis', array_merge(array('url_site' => $link_site, 'url_taxon' => $link_taxon), $informations)); |
---|
697 | |
---|
698 | return $credit; |
---|
699 | } |
---|
700 | |
---|
701 | |
---|
702 | /** |
---|
703 | * Calcule le sha de chaque fichier ITIS fournissant des données, à savoir, ceux des règnes et ceux des noms |
---|
704 | * communs par langue. |
---|
705 | * |
---|
706 | * @api |
---|
707 | * |
---|
708 | * @return array |
---|
709 | * Tableau à deux index principaux: |
---|
710 | * - `taxons` : tableau associatif indexé par règne |
---|
711 | * - `traductions` : tableau associatif par code de langue SPIP |
---|
712 | */ |
---|
713 | function itis_review_sha() { |
---|
714 | |
---|
715 | $shas = array(); |
---|
716 | |
---|
717 | include_spip('inc/taxonomer'); |
---|
718 | $kingdoms = explode(':', _TAXONOMIE_REGNES); |
---|
719 | |
---|
720 | foreach ($kingdoms as $_kingdom) { |
---|
721 | $file = find_in_path('services/itis/' . ucfirst($_kingdom) . '_Genus.txt'); |
---|
722 | if (file_exists($file) and ($sha_file = sha1_file($file))) { |
---|
723 | $shas['taxons'][$_kingdom] = $sha_file; |
---|
724 | } |
---|
725 | } |
---|
726 | |
---|
727 | foreach (array_keys($GLOBALS['itis_language']) as $_language) { |
---|
728 | $file = find_in_path("services/itis/vernaculars_${_language}.csv"); |
---|
729 | if (file_exists($file) and ($sha_file = sha1_file($file))) { |
---|
730 | $shas['traductions'][$GLOBALS['itis_language'][$_language]] = $sha_file; |
---|
731 | } |
---|
732 | } |
---|
733 | |
---|
734 | return $shas; |
---|
735 | } |
---|
736 | |
---|
737 | |
---|
738 | // ---------------------------------------------------------------- |
---|
739 | // ------------ Fonctions internes utilisées par l'API ------------ |
---|
740 | // ---------------------------------------------------------------- |
---|
741 | |
---|
742 | /** |
---|
743 | * Construit l'URL de la requête ITIS correspondant à la demande utilisateur. |
---|
744 | * |
---|
745 | * @internal |
---|
746 | * |
---|
747 | * @param string $format |
---|
748 | * Format du résultat de la requête. Prend les valeurs `json` ou `xml`. Le `json` est recommandé. |
---|
749 | * @param string $group |
---|
750 | * Groupe d'actions du même type. Prend les valeurs: |
---|
751 | * - `search` : groupe des actions de recherche du TSN à partir du nom commun ou scientifique |
---|
752 | * - `vernacular` : groupe de l'action fournissant les noms communs d'une langue donnée |
---|
753 | * - `getfull` : groupe de l'action fournissant l'ensemble des informations d'un taxon |
---|
754 | * - `get` : groupe des actions fournissant une information précise sur un taxon |
---|
755 | * @param string $action |
---|
756 | * Nom de l'action du service ITIS. Les valeurs dépendent du groupe. Par exemple, pour le groupe |
---|
757 | * `search` les actions sont `commonname` et `scientificname`. |
---|
758 | * @param string $key |
---|
759 | * Clé de recherche qui dépend de l'action demandée. Ce peut être le nom scientifique, le TSN, etc. |
---|
760 | * Cette clé doit être encodée si besoin par l'appelant. |
---|
761 | * |
---|
762 | * @return string |
---|
763 | * L'URL de la requête au service |
---|
764 | */ |
---|
765 | function itis_build_url($format, $group, $action, $key) { |
---|
766 | |
---|
767 | // Construire l'URL de l'api sollicitée |
---|
768 | $url = _TAXONOMIE_ITIS_ENDPOINT_BASE_URL |
---|
769 | . ($format == 'json' ? 'jsonservice/' : 'services/ITISService/') |
---|
770 | . $GLOBALS['itis_webservice'][$group][$action]['function'] . '?' |
---|
771 | . $GLOBALS['itis_webservice'][$group][$action]['argument'] . '=' . $key; |
---|
772 | |
---|
773 | return $url; |
---|
774 | } |
---|