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

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

Phpdoc et formatage PSR SPIP

  • Property svn:eol-style set to native
File size: 12.6 KB
Line 
1<?php
2/**
3 * Ce fichier contient l'ensemble des constantes et des utilitaires nécessaires au fonctionnement du plugin.
4 *
5 * @package SPIP\TAXONOMIE
6 */
7if (!defined('_ECRIRE_INC_VERSION')) {
8        return;
9}
10
11if (!defined('_TAXONOMIE_REGNE_ANIMAL')) {
12        /**
13         * Nom latin du règne animal (animaux).
14         */
15        define('_TAXONOMIE_REGNE_ANIMAL', 'animalia');
16}
17if (!defined('_TAXONOMIE_REGNE_VEGETAL')) {
18        /**
19         * Nom latin du règne végétal (plantes).
20         */
21        define('_TAXONOMIE_REGNE_VEGETAL', 'plantae');
22}
23if (!defined('_TAXONOMIE_REGNE_FONGIQUE')) {
24        /**
25         * Nom latin du règne fongique (champignons).
26         */
27        define('_TAXONOMIE_REGNE_FONGIQUE', 'fungi');
28}
29
30if (!defined('_TAXONOMIE_REGNES')) {
31        /**
32         * Liste des règnes supportés par le plugin (concanétation des noms séparés par le signe deux-points).
33         */
34        define('_TAXONOMIE_REGNES',
35                implode(':', array(
36                        _TAXONOMIE_REGNE_ANIMAL,
37                        _TAXONOMIE_REGNE_VEGETAL,
38                        _TAXONOMIE_REGNE_FONGIQUE
39                )));
40}
41
42if (!defined('_TAXONOMIE_RANG_REGNE')) {
43        /**
44         * Nom anglais du rang `règne`.
45         */
46        define('_TAXONOMIE_RANG_REGNE', 'kingdom');
47}
48// Suivant le règne l'embranchement se nomme phylum (animalia) ou division (fungi, plantae).
49// Néanmoins, le terme phylum est souvent accepté pour l'ensemble des règnes
50if (!defined('_TAXONOMIE_RANG_PHYLUM')) {
51        /**
52         * Nom anglais du rang `phylum` ou `embranchement`.
53         * Ce nom est utilisé pour le règne `animalia`
54         */
55        define('_TAXONOMIE_RANG_PHYLUM', 'phylum');
56}
57if (!defined('_TAXONOMIE_RANG_DIVISION')) {
58        /**
59         * Nom anglais du rang `division`.
60         * Ce nom est utilisé pour le règne `fungi` ou `plantae` et correspond au `phylum` pour le règne animal.
61         */
62        define('_TAXONOMIE_RANG_DIVISION', 'division');
63}
64if (!defined('_TAXONOMIE_RANG_CLASSE')) {
65        /**
66         * Nom anglais du rang `classe`.
67         */
68        define('_TAXONOMIE_RANG_CLASSE', 'class');
69}
70if (!defined('_TAXONOMIE_RANG_ORDRE')) {
71        /**
72         * Nom anglais du rang `ordre`.
73         */
74        define('_TAXONOMIE_RANG_ORDRE', 'order');
75}
76if (!defined('_TAXONOMIE_RANG_FAMILLE')) {
77        /**
78         * Nom anglais du rang `famille`.
79         */
80        define('_TAXONOMIE_RANG_FAMILLE', 'family');
81}
82if (!defined('_TAXONOMIE_RANG_GENRE')) {
83        /**
84         * Nom anglais du rang `genre`.
85         */
86        define('_TAXONOMIE_RANG_GENRE', 'genus');
87}
88if (!defined('_TAXONOMIE_RANG_ESPECE')) {
89        /**
90         * Nom anglais du rang `espèce`.
91         */
92        define('_TAXONOMIE_RANG_ESPECE', 'species');
93}
94if (!defined('_TAXONOMIE_RANG_SOUS_ESPECE')) {
95        /**
96         * Nom anglais du rang intercalaire `sous-espèce`.
97         */
98        define('_TAXONOMIE_RANG_SOUS_ESPECE', 'subspecies');
99}
100if (!defined('_TAXONOMIE_RANG_VARIETE')) {
101        /**
102         * Nom anglais du rang `variété`.
103         */
104        define('_TAXONOMIE_RANG_VARIETE', 'variety');
105}
106if (!defined('_TAXONOMIE_RANG_SOUS_VARIETE')) {
107        /**
108         * Nom anglais du rang intercalaire `sous-variété`.
109         */
110        define('_TAXONOMIE_RANG_SOUS_VARIETE', 'subvariety');
111}
112if (!defined('_TAXONOMIE_RANG_RACE')) {
113        /**
114         * Nom anglais du rang `race`.
115         */
116        define('_TAXONOMIE_RANG_RACE', 'race');
117}
118if (!defined('_TAXONOMIE_RANG_FORME')) {
119        /**
120         * Nom anglais du rang `forme`.
121         */
122        define('_TAXONOMIE_RANG_FORME', 'forma');
123}
124if (!defined('_TAXONOMIE_RANG_SOUS_FORME')) {
125        /**
126         * Nom anglais du rang intercalaire `sous-règne`.
127         */
128        define('_TAXONOMIE_RANG_SOUS_FORME', 'subforma');
129}
130
131if (!defined('_TAXONOMIE_RANGS_PARENTS_ESPECE')) {
132        /**
133         * Liste des rangs utilisés du règne au genre compris (concanétation des noms séparés par le signe deux-points).
134         * On utilise par défaut au niveau 2 le terme phylum du règne animal (division pour les autres règnes)
135         */
136        define('_TAXONOMIE_RANGS_PARENTS_ESPECE',
137                implode(':', array(
138                        _TAXONOMIE_RANG_REGNE,
139                        _TAXONOMIE_RANG_PHYLUM,
140                        _TAXONOMIE_RANG_CLASSE,
141                        _TAXONOMIE_RANG_ORDRE,
142                        _TAXONOMIE_RANG_FAMILLE,
143                        _TAXONOMIE_RANG_GENRE
144                        )
145                )
146        );
147}
148if (!defined('_TAXONOMIE_RANGS_ESPECE_ET_FILS')) {
149        /**
150         * Liste des rangs utilisés de l'espèce à la sous-forme (concanétation des noms séparés par le signe deux-points).
151         */
152        define('_TAXONOMIE_RANGS_ESPECE_ET_FILS',
153                implode(':', array(
154                        _TAXONOMIE_RANG_ESPECE,
155                        _TAXONOMIE_RANG_SOUS_ESPECE,
156                        _TAXONOMIE_RANG_VARIETE,
157                        _TAXONOMIE_RANG_SOUS_VARIETE,
158                        _TAXONOMIE_RANG_RACE,
159                        _TAXONOMIE_RANG_FORME,
160                        _TAXONOMIE_RANG_SOUS_FORME
161                        )
162                )
163        );
164}
165if (!defined('_TAXONOMIE_RANGS')) {
166        /**
167         * Liste complète des rangs utilisés par le plugin (concanétation des noms séparés par le signe deux-points).
168         */
169        define('_TAXONOMIE_RANGS',
170                _TAXONOMIE_RANGS_PARENTS_ESPECE . ':' . _TAXONOMIE_RANGS_ESPECE_ET_FILS);
171}
172
173if (!defined('_TAXONOMIE_CACHE_NOMDIR')) {
174        /**
175         * Nom du dossier contenant les fichiers caches des éléments de taxonomie
176         *
177         * @package SPIP\TAXONOMIE\CACHE
178         */
179        define('_TAXONOMIE_CACHE_NOMDIR', 'cache-taxonomie/');
180}
181if (!defined('_TAXONOMIE_CACHE_DIR')) {
182        /**
183         * Chemin du dossier contenant les fichiers caches des boussoles
184         *
185         * @package SPIP\TAXONOMIE\CACHE
186         */
187        define('_TAXONOMIE_CACHE_DIR', _DIR_VAR . _TAXONOMIE_CACHE_NOMDIR);
188}
189
190
191/**
192 * Renvoie, à partir de l'url du service, le tableau des données demandées.
193 * Le service utilise dans ce cas une chaine JSON qui est décodée pour fournir
194 * le tableau de sortie. Le flux retourné par le service est systématiquement
195 * transcodé dans le charset du site avant d'être décodé.
196 *
197 * @package SPIP\TAXONOMIE\SERVICES
198 * @uses recuperer_url()
199 *
200 * @param string   $url
201 *        URL complète de la requête au service web concerné.
202 * @param int|null $taille_max
203 *        Taille maximale du flux récupéré suite à la requête.
204 *        `null` désigne la taille par défaut.
205 *
206 * @return array
207 */
208function service_requeter_json($url, $taille_max = null) {
209        // Acquisition des données spécifiées par l'url
210        include_spip('inc/distant');
211        $options = array(
212                'transcoder' => true,
213                'taille_max' => $taille_max);
214        $flux = recuperer_url($url, $options);
215
216        // Tranformation de la chaine json reçue en tableau associatif
217        $data = json_decode($flux['page'], true);
218
219        return $data;
220}
221
222
223/**
224 * Extrait de la table `spip_taxons` la liste des taxons d'un règne donné ayant fait l'objet
225 * d'une modification manuelle.
226 *
227 * @package SPIP\TAXONOMIE\OBJET
228 *
229 * @param string $regne
230 *        Nom scientifique du règne en lettres minuscules : `animalia`, `plantae`, `fungi`.
231 *
232 * @return array
233 *        Liste des taxons modifiées manuellement. Chaque élément de la liste est un tableau
234 *        composé des index `tsn`, `nom_commun`, `descriptif`.
235 */
236function taxon_preserver_editions($regne) {
237        $select = array('tsn', 'nom_commun', 'descriptif');
238        $where = array('regne=' . sql_quote($regne), 'edite=' . sql_quote('oui'));
239        $taxons = sql_allfetsel($select, 'spip_taxons', $where);
240
241        return $taxons;
242}
243
244
245/**
246 * Fusionne les traductions d'une balise `<multi>` avec celles d'une autre balise `<multi>`.
247 * L'une des balise est considérée comme prioritaire ce qui permet de régler le cas où la même
248 * langue est présente dans les deux balises.
249 * Si on ne trouve pas de balise `<multi>` dans l'un ou l'autre des paramètres, on considère que
250 * le texte est tout même formaté de la façon suivante : texte0[langue1]texte1[langue2]texte2...
251 *
252 * @package SPIP\TAXONOMIE\OBJET
253 *
254 * @param string $multi_prioritaire
255 *        Balise multi considérée comme prioritaire en cas de conflit sur une langue.
256 * @param string $multi_non_prioritaire
257 *        Balise multi considérée comme non prioritaire en cas de conflit sur une langue.
258 *
259 * @return string
260 *        La chaine construite est toujours une balise `<multi>` complète ou une chaine vide sinon.
261 */
262function taxon_merger_traductions($multi_prioritaire, $multi_non_prioritaire) {
263        $multi_merge = '';
264
265        // On extrait le contenu de la balise <multi> si elle existe.
266        include_spip('inc/filtres');
267        $multi_prioritaire = trim($multi_prioritaire);
268        $multi_non_prioritaire = trim($multi_non_prioritaire);
269        if (preg_match(_EXTRAIRE_MULTI, $multi_prioritaire, $match)) {
270                $multi_prioritaire = trim($match[1]);
271        }
272        if (preg_match(_EXTRAIRE_MULTI, $multi_non_prioritaire, $match)) {
273                $multi_non_prioritaire = trim($match[1]);
274        }
275
276        if ($multi_prioritaire) {
277                if ($multi_non_prioritaire) {
278                        // On extrait les traductions sous forme de tableau langue=>traduction.
279                        $traductions_prioritaires = extraire_trads($multi_prioritaire);
280                        $traductions_non_prioritaires = extraire_trads($multi_non_prioritaire);
281
282                        // On complète les traductions prioritaires avec les traductions non prioritaires dont la langue n'est pas
283                        // présente dans les traductions prioritaires.
284                        foreach ($traductions_non_prioritaires as $_lang => $_traduction) {
285                                if (!array_key_exists($_lang, $traductions_prioritaires)) {
286                                        $traductions_prioritaires[$_lang] = $_traduction;
287                                }
288                        }
289
290                        // On construit le contenu de la balise <multi> mergé à partir des traductions prioritaires mises à jour.
291                        // Les traductions vides sont ignorées.
292                        ksort($traductions_prioritaires);
293                        foreach ($traductions_prioritaires as $_lang => $_traduction) {
294                                if ($_traduction) {
295                                        $multi_merge .= ($_lang ? '[' . $_lang . ']' : '') . trim($_traduction);
296                                }
297                        }
298                } else {
299                        $multi_merge = $multi_prioritaire;
300                }
301        } else {
302                $multi_merge = $multi_non_prioritaire;
303        }
304
305        // Si le contenu est non vide on l'insère dans une balise <multi>
306        if ($multi_merge) {
307                $multi_merge = '<multi>' . $multi_merge . '</multi>';
308        }
309
310        return $multi_merge;
311}
312
313
314/**
315 * Traduit un champ de la table `spip_taxons` dans la langue du site.
316 *
317 * @package SPIP\TAXONOMIE\OBJET
318 *
319 * @param $champ
320 *        Nom du champ dans la base de données.
321 *
322 * @return string
323 *        Traduction du champ dans la langue du site.
324 */
325function taxon_traduire_champ($champ) {
326        $traduction = '';
327        if ($champ) {
328                $traduction = _T("taxon:champ_${champ}_label");
329        }
330
331        return $traduction;
332}
333
334
335/**
336 * Ecrit le contenu issu d'un service taxonomique dans un fichier texte afin d'optimiser le nombre
337 * de requêtes adressées au service.
338 *
339 * @package SPIP\TAXONOMIE\CACHE
340 *
341 * @param string $cache
342 *        Contenu du fichier cache. Si le service appelant manipule un tableau il doit le sérialiser avant
343 *        d'appeler cette fonction.
344 * @param string $service
345 * @param int    $tsn
346 * @param string $spip_langue
347 * @param string $action
348 *
349 * @return boolean
350 *        Toujours à vrai.
351 */
352function cache_taxonomie_ecrire($cache, $service, $tsn, $spip_langue = '', $action = '') {
353        // Création du dossier cache si besoin
354        sous_repertoire(_DIR_VAR, trim(_TAXONOMIE_CACHE_NOMDIR, '/'));
355
356        // Ecriture du fichier cache
357        $fichier_cache = cache_taxonomie_nommer($service, $tsn, $spip_langue, $action);
358        ecrire_fichier($fichier_cache, $cache);
359
360        return true;
361}
362
363
364/**
365 * Construit le nom du fichier cache en fonction du service, du taxon concernés et
366 * d'autres critères optionnels.
367 *
368 * @package SPIP\TAXONOMIE\CACHE
369 *
370 * @param string $service
371 * @param int    $tsn
372 * @param string $spip_langue
373 * @param string $action
374 *
375 * @return string
376 */
377function cache_taxonomie_nommer($service, $tsn, $spip_langue = '', $action = '') {
378        // Construction du chemin complet d'un fichier cache
379        $fichier_cache = _TAXONOMIE_CACHE_DIR
380                                         . $service
381                                         . ($action ? '_' . $action : '')
382                                         . '_' . $tsn
383                                         . ($spip_langue ? '_' . $spip_langue : '')
384                                         . '.txt';
385
386        return $fichier_cache;
387}
388
389/**
390 * Vérifie l'existence du fichier cache pour un taxon et un service donnés.
391 * Si le fichier existe la fonction retourne son chemin complet.
392 *
393 * @package SPIP\TAXONOMIE\CACHE
394 *
395 * @param string $service
396 * @param int    $tsn
397 * @param string $spip_langue
398 * @param string $action
399 *
400 * @return string
401 *        Chemin du fichier cache si il existe ou chaine vide sinon.
402 */
403function cache_taxonomie_existe($service, $tsn, $spip_langue = '', $action = '') {
404        // Contruire le nom du fichier cache
405        $fichier_cache = cache_taxonomie_nommer($service, $tsn, $spip_langue, $action);
406
407        // Vérification de l'existence du fichier:
408        // - chaine vide si le fichier n'existe pas
409        // - chemin complet du fichier si il existe
410        if (!file_exists($fichier_cache)) {
411                $fichier_cache = '';
412        }
413
414        return $fichier_cache;
415}
416
417
418/**
419 * Supprime tout ou partie des fichiers cache taxonomiques.
420 *
421 * @package SPIP\TAXONOMIE\CACHE
422 *
423 * @param array|string $caches
424 *        Liste des fichiers à supprimer ou vide si tous les fichiers cache doivent être supprimés.
425 *        Il est possible de passer un seul fichier comme une chaine.
426 *
427 * @return boolean
428 *        Toujours à `true`.
429 */
430function cache_taxonomie_supprimer($caches = array()) {
431        include_spip('inc/flock');
432
433        if ($caches) {
434                $fichiers_cache = is_string($caches) ? array($caches) : $caches;
435        } else {
436                $fichiers_cache = glob(_TAXONOMIE_CACHE_DIR . '*.*');
437        }
438
439        if ($fichiers_cache) {
440                foreach ($fichiers_cache as $_fichier) {
441                        supprimer_fichier($_fichier);
442                }
443        }
444
445        return true;
446}
Note: See TracBrowser for help on using the repository browser.