source: spip-zone/_plugins_/taxonomie/trunk/inc/taxonomie.php @ 109417

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

Amélioration de la performance du merge des traductions en sortant directement si les deux balises sont identiques.
Ajout du squelette taxon_edit de façon à présenter le nom scientifique correctement.

  • Property svn:eol-style set to native
File size: 12.9 KB
Line 
1<?php
2/**
3 * Ce fichier contient l'ensemble des constantes et des utilitaires nécessaires au fonctionnement du plugin.
4 *
5 */
6if (!defined('_ECRIRE_INC_VERSION')) {
7        return;
8}
9
10
11$GLOBALS['_taxonomie']['regnes'] = array('animalia', 'plantae', 'fungi');
12
13if (!defined('_TAXONOMIE_RANG_TYPE_PRINCIPAL')) {
14        /**
15         * Type de rang selon la nomenclature taxonomique.
16         */
17        define('_TAXONOMIE_RANG_TYPE_PRINCIPAL', 'principal');
18}
19if (!defined('_TAXONOMIE_RANG_TYPE_SECONDAIRE')) {
20        /**
21         * Type de rang selon la nomenclature taxonomique.
22         */
23        define('_TAXONOMIE_RANG_TYPE_SECONDAIRE', 'secondaire');
24}
25if (!defined('_TAXONOMIE_RANG_TYPE_INTERCALAIRE')) {
26        /**
27         * Type de rang selon la nomenclature taxonomique.
28         */
29        define('_TAXONOMIE_RANG_TYPE_INTERCALAIRE', 'intercalaire');
30}
31
32// TODO : vérifier les rangs stirp, morph, aberration, unspecified.
33// TODO : vérifier pourquoi le rang serie n'est pas dans la liste de ITIS
34$GLOBALS['_taxonomie']['rangs'] = array(
35        'kingdom'       => array('type' => _TAXONOMIE_RANG_TYPE_PRINCIPAL, 'est_espece' => false, 'synonyme' => ''),
36        'subkingdom'    => array('type' => _TAXONOMIE_RANG_TYPE_INTERCALAIRE, 'est_espece' => false, 'synonyme' => ''),
37        'infrakingdom'  => array('type' => _TAXONOMIE_RANG_TYPE_INTERCALAIRE, 'est_espece' => false, 'synonyme' => ''),
38        'superphylum'   => array('type' => _TAXONOMIE_RANG_TYPE_INTERCALAIRE, 'est_espece' => false, 'synonyme' => 'superdivision'),
39        'phylum'        => array('type' => _TAXONOMIE_RANG_TYPE_PRINCIPAL, 'est_espece' => false, 'synonyme' => 'division'),
40        'subphylum'     => array('type' => _TAXONOMIE_RANG_TYPE_INTERCALAIRE, 'est_espece' => false, 'synonyme' => 'subdivision'),
41        'infraphylum'   => array('type' => _TAXONOMIE_RANG_TYPE_INTERCALAIRE, 'est_espece' => false, 'synonyme' => 'infradivision'),
42        'superdivision' => array('type' => _TAXONOMIE_RANG_TYPE_INTERCALAIRE, 'est_espece' => false, 'synonyme' => 'superphylum'),
43        'division'      => array('type' => _TAXONOMIE_RANG_TYPE_PRINCIPAL, 'est_espece' => false, 'synonyme' => 'phylum'),
44        'subdivision'   => array('type' => _TAXONOMIE_RANG_TYPE_INTERCALAIRE, 'est_espece' => false, 'synonyme' => 'subphylum'),
45        'infradivision' => array('type' => _TAXONOMIE_RANG_TYPE_INTERCALAIRE, 'est_espece' => false, 'synonyme' => 'infraphylum'),
46        'superclass'    => array('type' => _TAXONOMIE_RANG_TYPE_INTERCALAIRE, 'est_espece' => false, 'synonyme' => ''),
47        'class'         => array('type' => _TAXONOMIE_RANG_TYPE_PRINCIPAL, 'est_espece' => false, 'synonyme' => ''),
48        'subclass'      => array('type' => _TAXONOMIE_RANG_TYPE_INTERCALAIRE, 'est_espece' => false, 'synonyme' => ''),
49        'infraclass'    => array('type' => _TAXONOMIE_RANG_TYPE_INTERCALAIRE, 'est_espece' => false, 'synonyme' => ''),
50        'superorder'    => array('type' => _TAXONOMIE_RANG_TYPE_INTERCALAIRE, 'est_espece' => false, 'synonyme' => ''),
51        'order'         => array('type' => _TAXONOMIE_RANG_TYPE_PRINCIPAL, 'est_espece' => false, 'synonyme' => ''),
52        'suborder'      => array('type' => _TAXONOMIE_RANG_TYPE_INTERCALAIRE, 'est_espece' => false, 'synonyme' => ''),
53        'infraorder'    => array('type' => _TAXONOMIE_RANG_TYPE_INTERCALAIRE, 'est_espece' => false, 'synonyme' => ''),
54        'section'       => array('type' => _TAXONOMIE_RANG_TYPE_SECONDAIRE, 'est_espece' => false, 'synonyme' => ''),
55        'subsection'    => array('type' => _TAXONOMIE_RANG_TYPE_INTERCALAIRE, 'est_espece' => false, 'synonyme' => ''),
56        'superfamily'   => array('type' => _TAXONOMIE_RANG_TYPE_INTERCALAIRE, 'est_espece' => false, 'synonyme' => ''),
57        'family'        => array('type' => _TAXONOMIE_RANG_TYPE_PRINCIPAL, 'est_espece' => false, 'synonyme' => ''),
58        'subfamily'     => array('type' => _TAXONOMIE_RANG_TYPE_INTERCALAIRE, 'est_espece' => false, 'synonyme' => ''),
59        'tribe'         => array('type' => _TAXONOMIE_RANG_TYPE_SECONDAIRE, 'est_espece' => false, 'synonyme' => ''),
60        'subtribe'      => array('type' => _TAXONOMIE_RANG_TYPE_INTERCALAIRE, 'est_espece' => false, 'synonyme' => ''),
61        'genus'         => array('type' => _TAXONOMIE_RANG_TYPE_PRINCIPAL, 'est_espece' => false, 'synonyme' => ''),
62        'subgenus'      => array('type' => _TAXONOMIE_RANG_TYPE_INTERCALAIRE, 'est_espece' => false, 'synonyme' => ''),
63        'species'       => array('type' => _TAXONOMIE_RANG_TYPE_PRINCIPAL, 'est_espece' => true, 'synonyme' => ''),
64        'subspecies'    => array('type' => _TAXONOMIE_RANG_TYPE_INTERCALAIRE, 'est_espece' => true, 'synonyme' => ''),
65        'variety'       => array('type' => _TAXONOMIE_RANG_TYPE_SECONDAIRE, 'est_espece' => true, 'synonyme' => ''),
66        'subvariety'    => array('type' => _TAXONOMIE_RANG_TYPE_INTERCALAIRE, 'est_espece' => true, 'synonyme' => ''),
67        'form'          => array('type' => _TAXONOMIE_RANG_TYPE_SECONDAIRE, 'est_espece' => true, 'synonyme' => ''),
68        'subform'       => array('type' => _TAXONOMIE_RANG_TYPE_INTERCALAIRE, 'est_espece' => true, 'synonyme' => ''),
69        'race'          => array('type' => _TAXONOMIE_RANG_TYPE_INTERCALAIRE, 'est_espece' => true, 'synonyme' => 'variety'),
70        'stirp'         => array('type' => _TAXONOMIE_RANG_TYPE_INTERCALAIRE, 'est_espece' => true, 'synonyme' => ''),
71        'morph'         => array('type' => _TAXONOMIE_RANG_TYPE_INTERCALAIRE, 'est_espece' => true, 'synonyme' => ''),
72        'aberration'    => array('type' => _TAXONOMIE_RANG_TYPE_INTERCALAIRE, 'est_espece' => true, 'synonyme' => ''),
73        'unspecified'   => array('type' => _TAXONOMIE_RANG_TYPE_INTERCALAIRE, 'est_espece' => true, 'synonyme' => '')
74);
75
76if (!defined('_TAXONOMIE_RANG_REGNE')) {
77        /**
78         * Nom anglais du rang principal `règne`.
79         */
80        define('_TAXONOMIE_RANG_REGNE', 'kingdom');
81}
82if (!defined('_TAXONOMIE_RANG_GENRE')) {
83        /**
84         * Nom anglais du rang principal `genre`.
85         */
86        define('_TAXONOMIE_RANG_GENRE', 'genus');
87}
88if (!defined('_TAXONOMIE_RANG_ESPECE')) {
89        /**
90         * Nom anglais du rang principal `espèce`.
91         */
92        define('_TAXONOMIE_RANG_ESPECE', 'species');
93}
94
95if (!defined('_TAXONOMIE_LANGUES_POSSIBLES')) {
96        /**
97         * Liste des langues utilisables pour les noms communs et les textes des taxons.
98         */
99        define('_TAXONOMIE_LANGUES_POSSIBLES', 'fr:en:es:pt:de:it');
100}
101
102
103/**
104 * Renvoie la liste des règnes supportés par le plugin.
105 *
106 * @package SPIP\TAXONOMIE\REGNE
107 *
108 * @api
109 *
110 * @return array
111 *        Liste des noms scientifiques en minuscules des règnes supportés.
112 */
113function regne_lister() {
114
115        return $GLOBALS['_taxonomie']['regnes'];
116}
117
118
119/**
120 * Renvoie le type de rang principal, secondaire ou intercalaire.
121 *
122 * @package SPIP\TAXONOMIE\RANG
123 *
124 * @api
125 *
126 * @param string $rang
127 *        Nom anglais du rang en minuscules.
128 *
129 * @return string
130 *        `principal`, `secondaire` ou `intercalaire` si le rang est valide, chaine vide sinon.
131 */
132function rang_informer_type($rang) {
133
134        // Initialisation à chaine vide pour le cas où le rang n'est pas dans la liste des rangs admis.
135        $type = '';
136
137        if (!empty($GLOBALS['_taxonomie']['rangs'][$rang])) {
138                $type = $GLOBALS['_taxonomie']['rangs'][$rang]['type'];
139        }
140
141        return $type;
142}
143
144
145/**
146 * Détermine si un rang est celui d'une espèce ou d'un taxon de rang inférieur.
147 *
148 * @package SPIP\TAXONOMIE\RANG
149 *
150 * @api
151 *
152 * @param string $rang
153 *        Nom anglais du rang en minuscules.
154 *
155 * @return bool
156 *        `true` si le rang est celui d'une espèce ou d'un taxon de rang inférieur, `false` sinon.
157 */
158function rang_est_espece($rang) {
159
160        // Initialisation à false pour le cas où le rang n'est pas dans la liste des rangs admis.
161        $est_espece = false;
162
163        if (!empty($GLOBALS['_taxonomie']['rangs'][$rang])) {
164                $est_espece = $GLOBALS['_taxonomie']['rangs'][$rang]['est_espece'];
165        }
166
167        return $est_espece;
168}
169
170
171/**
172 * Extrait, de la table `spip_taxons`, la liste des taxons d'un règne donné - importés via un fichier ITIS -
173 * ayant fait l'objet d'une modification manuelle et la liste des taxons créés lors de l'ajout d'une espèce et donc
174 * non importés avec le fichier ITIS.
175 *
176 * @package SPIP\TAXONOMIE\TAXON
177 *
178 * @api
179 *
180 * @param string $regne
181 *        Nom scientifique du règne en lettres minuscules : `animalia`, `plantae`, `fungi`.
182 *
183 * @return array
184 *        Liste des taxons modifiées manuellement et créés suite à l'ajout d'une espèce.
185 *        Chaque élément de la liste est un tableau composé, pour les taxons modifiés manuellement des index
186 *        `tsn`, `nom_commun`, `descriptif` et pour les taxons créés via une espèce de tous les champs du objet
187 *        taxon, à l'exception de l'id (`id_taxon`) et de la date de mise à jour (`maj`).
188 */
189function taxon_preserver($regne) {
190
191        // Récupération de la description de la table spip_taxons afin de connaitre la liste des colonnes.
192        include_spip('base/objets');
193        $description_table = lister_tables_objets_sql('spip_taxons');
194
195        // Récupération de la liste des taxons importés via le fichier ITIS du règne concerné et édités manuellement.
196        // Ces champs éditables (nom_commun, descriptif) seront réinjectés après le chargement du règne via un update.
197        $from = array('spip_taxons');
198        $select = array_merge($description_table['champs_editables'], array('tsn'));
199        $where = array('regne=' . sql_quote($regne), 'edite=' . sql_quote('oui'), 'importe=' . sql_quote('oui'));
200        $taxons['edites'] = sql_allfetsel($select, $from, $where);
201
202        // Récupération de la liste des taxons non importés via le fichier ITIS du règne concerné mais créés lors de l'ajout
203        // d'une espèce.
204        // Ces taxons seront réinjectés après le chargement du règne via un create.
205        // -- on récupère tous les champs du taxons sauf ceux qui seront mis à jour automatique lors de l'insertion de
206        //    l'objet en BD (id_taxon, maj).
207        $select = array_diff(array_keys($description_table['field']), array('id_taxon', 'maj'));
208        $where = array('regne=' . sql_quote($regne), 'importe=' . sql_quote('non'));
209        $taxons['crees'] = sql_allfetsel($select, $from, $where);
210
211        return $taxons;
212}
213
214
215/**
216 * Fusionne les traductions d'une balise `<multi>` avec celles d'une autre balise `<multi>`.
217 * L'une des balise est considérée comme prioritaire ce qui permet de régler le cas où la même
218 * langue est présente dans les deux balises.
219 * Si on ne trouve pas de balise `<multi>` dans l'un ou l'autre des paramètres, on considère que
220 * le texte est tout même formaté de la façon suivante : texte0[langue1]texte1[langue2]texte2...
221 *
222 * @package SPIP\TAXONOMIE\TAXON
223 *
224 * @api
225 *
226 * @param string $multi_prioritaire
227 *        Balise multi considérée comme prioritaire en cas de conflit sur une langue.
228 * @param string $multi_non_prioritaire
229 *        Balise multi considérée comme non prioritaire en cas de conflit sur une langue.
230 *
231 * @return string
232 *        La chaine construite est toujours une balise `<multi>` complète ou une chaine vide sinon.
233 */
234function taxon_merger_traductions($multi_prioritaire, $multi_non_prioritaire) {
235
236        $multi_merge = '';
237
238        // On extrait le contenu de la balise <multi> si elle existe.
239        $multi_prioritaire = trim($multi_prioritaire);
240        $multi_non_prioritaire = trim($multi_non_prioritaire);
241
242        // Si les deux balises sont identiques on sort directement avec le multi prioritaire ce qui améliore les
243        // performances.
244        if ($multi_prioritaire == $multi_non_prioritaire) {
245                $multi_merge = $multi_prioritaire;
246        } else {
247                include_spip('inc/filtres');
248                if (preg_match(_EXTRAIRE_MULTI, $multi_prioritaire, $match)) {
249                        $multi_prioritaire = trim($match[1]);
250                }
251                if (preg_match(_EXTRAIRE_MULTI, $multi_non_prioritaire, $match)) {
252                        $multi_non_prioritaire = trim($match[1]);
253                }
254
255                if ($multi_prioritaire) {
256                        if ($multi_non_prioritaire) {
257                                // On extrait les traductions sous forme de tableau langue=>traduction.
258                                $traductions_prioritaires = extraire_trads($multi_prioritaire);
259                                $traductions_non_prioritaires = extraire_trads($multi_non_prioritaire);
260
261                                // On complète les traductions prioritaires avec les traductions non prioritaires dont la langue n'est pas
262                                // présente dans les traductions prioritaires.
263                                foreach ($traductions_non_prioritaires as $_lang => $_traduction) {
264                                        if (!array_key_exists($_lang, $traductions_prioritaires)) {
265                                                $traductions_prioritaires[$_lang] = $_traduction;
266                                        }
267                                }
268
269                                // On construit le contenu de la balise <multi> mergé à partir des traductions prioritaires mises à jour.
270                                // Les traductions vides sont ignorées.
271                                ksort($traductions_prioritaires);
272                                foreach ($traductions_prioritaires as $_lang => $_traduction) {
273                                        if ($_traduction) {
274                                                $multi_merge .= ($_lang ? '[' . $_lang . ']' : '') . trim($_traduction);
275                                        }
276                                }
277                        } else {
278                                $multi_merge = $multi_prioritaire;
279                        }
280                } else {
281                        $multi_merge = $multi_non_prioritaire;
282                }
283
284                // Si le contenu est non vide on l'insère dans une balise <multi>
285                if ($multi_merge) {
286                        $multi_merge = '<multi>' . $multi_merge . '</multi>';
287                }
288        }
289
290        return $multi_merge;
291}
292
293
294/**
295 * Traduit un champ de la table `spip_taxons` dans la langue du site.
296 *
297 * @package SPIP\TAXONOMIE\TAXON
298 *
299 * @api
300 *
301 * @param string $champ
302 *        Nom du champ dans la base de données.
303 *
304 * @return string
305 *        Traduction du champ dans la langue du site.
306 */
307function taxon_traduire_champ($champ) {
308
309        $traduction = '';
310        if ($champ) {
311                $traduction = _T("taxon:champ_${champ}_label");
312        }
313
314        return $traduction;
315}
Note: See TracBrowser for help on using the repository browser.