source: spip-zone/_plugins_/taxonomie/trunk/services/itis/itis_api.php @ 109225

Last change on this file since 109225 was 109225, checked in by eric@…, 23 months ago

Mise au point de la recherche par nom commun.

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