source: spip-zone/_plugins_/taxonomie/trunk/taxonomie_fonctions.php @ 96990

Last change on this file since 96990 was 96990, checked in by eric@…, 3 years ago

La mise en jour des fichiers ITIS en UTF-8 n'est pas probante!

  • Property svn:eol-style set to native
File size: 10.5 KB
Line 
1<?php
2/**
3 * Ce fichier contient l'ensemble des fonctions implémentant l'API du plugin Taxonomie.
4 *
5 * @package SPIP\TAXONOMIE\API
6 */
7
8if (!defined("_ECRIRE_INC_VERSION")) return;
9
10/**
11 * Charge tous les taxons d'un règne donné, du règne lui-même aux taxons de genre au maximum.
12 * La fonction permet aussi de choisir un rang taxonomique feuille différent du genre.
13 * Les nom communs anglais, français ou espagnols peuvent aussi être chargés en complément mais
14 * ne couvrent pas l'ensemble des taxons.
15 *
16 * @api
17 * @filtre
18 * @uses taxonomie_regne_existe()
19 * @uses taxon_preserver_editions()
20 * @uses taxonomie_vider_regne()
21 * @uses itis_read_hierarchy()
22 * @uses itis_spipcode2language()
23 * @uses itis_read_vernaculars()
24 *
25 * @param string        $regne
26 *              Nom scientifique du règne en lettres minuscules : `animalia`, `plantae`, `fungi`.
27 * @param string        $rang
28 *              Rang taxonomique minimal jusqu'où charger le règne. Ce rang est fourni en anglais, en minuscules et
29 *              correspond à : `phylum`, `class`, `order`, `family`, `genus`.
30 * @param array         $codes_langue
31 *              Tableau des codes (au sens SPIP) des langues à charger pour les noms communs des taxons.
32 *
33 * @return bool
34 *              `true` si le chargement a réussi, `false` sinon
35 */
36function taxonomie_charger_regne($regne, $rang, $codes_langue=array()) {
37        $retour = false;
38        $taxons_edites = array();
39
40        // Vérifie si le règne existe bien dans la table spip_taxons
41        $regne_existe = taxonomie_regne_existe($regne, $meta_regne);
42        if ($regne_existe) {
43                // Sauvegarde des taxons ayant été modifiés manuellement suite à leur création automatique.
44                include_spip('inc/taxonomer');
45                $taxons_edites = taxon_preserver_editions($regne);
46
47                // Vider le règne avant de le recharger
48                taxonomie_vider_regne($regne);
49        }
50
51        // Lecture de la hiérarchie des taxons à partir du fichier texte extrait de la base ITIS
52        $meta_regne = array();
53        include_spip('services/itis/itis_api');
54        $taxons = itis_read_hierarchy($regne, $rang, $meta_regne['sha']);
55
56        // Ajout des noms communs extraits de la base ITIS dans la langue demandée
57        if ($taxons) {
58                $meta_regne['compteur'] = count($taxons);
59                $traductions = array();
60                foreach ($codes_langue as $_code_langue) {
61                        $langue = itis_spipcode2language($_code_langue);
62                        if ($langue) {
63                                $noms = itis_read_vernaculars($langue, $sha_langue);
64                                if ($noms) {
65                                        $meta_regne['traductions']['itis'][$_code_langue]['sha'] = $sha_langue;
66                                        $nb_traductions = 0;
67                                        foreach ($noms as $_tsn => $_nom) {
68                                                if (array_key_exists($_tsn, $taxons)) {
69                                                        // On ajoute les traductions qui sont de la forme [xx]texte
70                                                        // On sauvegarde le tsn concerné afin de clore les traductions
71                                                        // avec les balises multi et d'optimiser ainsi les traitements
72                                                        // sachant qu'il y a très peu de traductions comparées aux taxons
73                                                        $taxons[$_tsn]['nom_commun'] .= $_nom;
74                                                        $nb_traductions += 1;
75                                                        $traductions[$_tsn] = $_tsn;
76                                                }
77                                        }
78                                        $meta_regne['traductions']['itis'][$_code_langue]['compteur'] = $nb_traductions;
79                                }
80                        }
81                }
82
83                // Clore les traductions avec les balises multi
84                if ($traductions) {
85                        foreach ($traductions as $_tsn) {
86                                $taxons[$_tsn]['nom_commun'] =  '<multi>' . $taxons[$_tsn]['nom_commun'] . '</multi>';
87                        }
88                }
89
90                // Réinjection des taxons modifiés manuellement
91                // -- descriptif: remplacement
92                // -- nom commun: merge en considérant que la mise à jour manuelle est prioritaire
93                // -- edite: oui, on conserve bien sur l'indicateur d'édition
94                if ($taxons_edites) {
95                        foreach ($taxons_edites as $_taxon_edite) {
96                                if (($tsn = $_taxon_edite['tsn'])
97                                AND (array_key_exists($tsn, $taxons))) {
98                                        $taxons[$tsn]['descriptif'] = $_taxon_edite['descriptif'];
99                                        $taxons[$tsn]['nom_commun'] = taxon_merger_traductions(
100                                                                                                        $_taxon_edite['nom_commun'],
101                                                                                                        $taxons[$tsn]['nom_commun']);
102                                        $taxons[$tsn]['edite'] = 'oui';
103                                }
104                        }
105                }
106
107                // Insertion dans la base de données
108                $retour = sql_insertq_multi('spip_taxons', array_values($taxons));
109                if ($retour) {
110                        // Insérer les sha dans une meta propre au règne.
111                        // Ca permettra de tester l'utilité ou pas d'un rechargement du règne
112                        $meta_regne['rang'] = $rang;
113                        $meta_regne['maj'] = date('Y-m-d H:i:s');
114                        ecrire_meta("taxonomie_$regne", serialize($meta_regne));
115                }
116        }
117
118        return $retour;
119}
120
121
122/**
123 * Supprime tous les taxons d'un règne donné de la base de données.
124 * La meta concernant les informations de chargement du règne est aussi effacée.
125 * Les modifications manuelles effectuées sur les taxons du règne sont perdues, elles
126 * doivent donc être préservées au préalable.
127 *
128 * @api
129 * @filtre
130 *
131 * @param string        $regne
132 *              Nom scientifique du règne en lettres minuscules : `animalia`, `plantae`, `fungi`.
133 *
134 * @return bool
135 *              `true` si le vidage a réussi, `false` sinon
136 */
137function taxonomie_vider_regne($regne) {
138        $retour = sql_delete('spip_taxons', 'regne=' . sql_quote($regne));
139        if ($retour !== false) {
140                // Supprimer la meta propre au règne.
141                effacer_meta("taxonomie_$regne");
142                $retour = true;
143        }
144
145        return $retour;
146}
147
148
149/**
150 * Retourne l'existence ou pas d'un règne en base de données.
151 * La fonction scrute la table `spip_taxons` et non la meta propre au règne.
152 *
153 * @api
154 * @filtre
155 *
156 * @param string        $regne
157 *              Nom scientifique du règne en lettres minuscules : `animalia`, `plantae`, `fungi`.
158 * @param array         $meta_regne
159 *              Meta propre au règne, créée lors du chargement de celui-ci et retournée si le règne
160 *              existe.
161 *
162 * @return bool
163 *              `true` si le règne existe, `false` sinon.
164 */
165function taxonomie_regne_existe($regne, &$meta_regne) {
166        $meta_regne = array();
167        $existe = false;
168
169        $retour = sql_countsel('spip_taxons', 'regne=' . sql_quote($regne));
170        if ($retour) {
171                // Récupérer la meta propre au règne afin de la retourner.
172                include_spip('inc/config');
173                $meta_regne = lire_config("taxonomie_$regne");
174                $existe = true;
175        }
176
177        return $existe;
178}
179
180
181/**
182 * Liste dans un tableau les rangs taxonomiques supportés par le plugin, suivant certains critères.
183 * Les règnes et les rangs sont exprimés en anglais et écrits en lettres minuscules.
184 * La fonction permet d'exclure certains rangs de la liste.
185 *
186 * @api
187 * @filtre
188 *
189 * @param string        $regne
190 *              Nom scientifique du règne pour lequel la liste des rangs est demandée.
191 *              Cet argument permet de remplacer le rang `phylum` par `division` qui est son synonyme
192 *              pour les règnes fongique et végétal.
193 * @param array         $liste_base
194 *              Liste de base contenant les rangs par défaut à renvoyer. Il existe deux listes de base, à savoir :
195 *              - du règne au genre (`_TAXONOMIE_RANGS_PARENTS_ESPECE`)
196 *              - de l'espèce à la sous-forme (`_TAXONOMIE_RANGS_ESPECE_ET_FILS`)
197 * @param array         $exclusions
198 *              Liste des rangs à exclure de la liste fournie dans l'argument `$liste_base`
199 *
200 * @return array
201 *              Liste des rangs demandée.
202 */
203function taxonomie_lister_rangs($regne=_TAXONOMIE_REGNE_ANIMAL, $liste_base, $exclusions=array()) {
204        include_spip('inc/taxonomer');
205
206        $rangs = explode(':', $liste_base);
207        $rangs = array_diff($rangs, $exclusions);
208
209        if (($regne == _TAXONOMIE_REGNE_FONGIQUE)
210        OR  ($regne == _TAXONOMIE_REGNE_VEGETAL)) {
211                if ($index_cherche = array_search(_TAXONOMIE_RANG_PHYLUM, $rangs))
212                        $rangs[$index_cherche] = _TAXONOMIE_RANG_DIVISION;
213        }
214
215        return $rangs;
216}
217
218
219/**
220 * Fournit l'ascendance taxonomique d'un taxon donné par consultation en base de données.
221 *
222 * @api
223 * @filtre
224 *
225 * @param int           $id_taxon
226 *              Id du taxon pour lequel il faut fournir l'ascendance.
227 * @param int           $tsn_parent
228 *              TSN du parent correspondant au taxon id_taxon. Ce paramètre permet d'optimiser le traitement
229 *              mais n'est pas obligatoire. Si il n'est pas connu lors de l'appel il faut passer `null`.
230 * @param string        $ordre
231 *              Classement de la liste des taxons : `descendant`(défaut) ou `ascendant`.
232 *
233 * @return array
234 *              Liste des taxons ascendants. Chaque taxon est un tableau associatif contenant les informations
235 *              suivantes : `id_taxon`, `tsn_parent`, `nom_scientifique`, `nom_commun`, `rang`.
236 */
237function taxonomie_informer_ascendance($id_taxon, $tsn_parent=null, $ordre='descendant') {
238        $ascendance = array();
239
240        // Si on ne passe pas le tsn du parent correspondant au taxon pour lequel on cherche l'ascendance
241        // alors on le cherche en base de données.
242        // Le fait de passer ce tsn parent est uniquement une optimisation.
243        if (is_null($tsn_parent)) {
244                $tsn_parent = sql_getfetsel('tsn_parent', 'spip_taxons', 'id_taxon=' . intval($id_taxon));
245        }
246
247        while ($tsn_parent > 0) {
248                $select = array('id_taxon', 'tsn_parent', 'nom_scientifique', 'nom_commun', 'rang');
249                $where = array('tsn=' . intval($tsn_parent));
250                $taxon = sql_fetsel($select, 'spip_taxons', $where);
251                if ($taxon) {
252                        $ascendance[] = $taxon;
253                        $tsn_parent = $taxon['tsn_parent'];
254                }
255        }
256
257        if ($ascendance
258        AND ($ordre == 'descendant'))
259                $ascendance = array_reverse($ascendance);
260
261        return $ascendance;
262}
263
264
265/**
266 * Fournit les phrases de crédits des sources d'information ayant permis de compléter le taxon.
267 * La référence ITIS n'est pas répétée dans le champ `sources` de chaque taxon car elle est
268 * à la base de chaque règne. Elle est donc insérée par la fonction.
269 *
270 * @api
271 * @filtre
272 * @uses ${service}_credit fonction de formatage des crédits propre à chaque service
273 *
274 * @param int           $id_taxon
275 *              Id du taxon pour lequel il faut fournir les crédits
276 * @param string        $sources_specifiques
277 *              Tableau sérialisé des sources possibles autres qu'ITIS (CINFO, WIKIPEDIA...) telles qu'enregistrées
278 *              en base de données dans le champ `sources`.
279 *              Ce paramètre permet d'optimiser le traitement mais n'est pas obligatoire.
280 *
281 * @return array
282 *              Tableau des phrases de crédits indexées par source.
283 */
284function taxonomie_informer_credits($id_taxon, $sources_specifiques=null) {
285        $sources = array();
286
287        // Si on ne passe pas les sources du taxon concerné alors on le cherche en base de données.
288        // Le fait de passer ce champ sources est uniquement une optimisation.
289        if (is_null($sources_specifiques)) {
290                $sources_specifiques = sql_getfetsel('sources', 'spip_taxons', 'id_taxon=' . intval($id_taxon));
291        }
292
293        // On merge ITIS et les autres sources
294        $liste_sources = array('itis' => array());
295        if ($sources_specifiques) {
296                $liste_sources = array_merge($liste_sources, unserialize($sources_specifiques));
297        }
298
299        // Puis on construit la liste des sources pour l'affichage
300        foreach ($liste_sources as $_service => $_infos_source) {
301                include_spip("services/${_service}/${_service}_api");
302                if (function_exists($citer = "${_service}_credit")) {
303                        $sources[$_service] = $citer($id_taxon, $_infos_source);
304                }
305        }
306
307        return $sources;
308}
309
310?>
Note: See TracBrowser for help on using the repository browser.