source: spip-zone/_plugins_/taxonomie/trunk/formulaires/creer_espece.php @ 114137

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

La hiérarchie complète d'un taxon comprend aussi les descendants.
Il faut donc les supprimer pour arriver au premier ascendant réel de l'espèce.

  • Property svn:eol-style set to native
File size: 18.3 KB
Line 
1<?php
2/**
3 * Gestion du formulaire de création d'une espèce.
4 *
5 * @package    SPIP\TAXONOMIE\ESPECE
6 */
7if (!defined('_ECRIRE_INC_VERSION')) {
8        return;
9};
10
11if (!defined('_TAXONOMIE_RECHERCHE_MAX_ESPECES')) {
12        /**
13         * Nombre de réponses maximal toléré pour continuer en étape 2.
14         */
15        define('_TAXONOMIE_RECHERCHE_MAX_ESPECES', 35);
16}
17
18/**
19 * Chargement des données :
20 *
21 * @uses regne_lister()
22 * @uses regne_existe()
23 *
24 * @return array
25 *              Tableau des données à charger par le formulaire dans l'étape 1.
26 *      - `type_recherche`         : (saisie) type de la recherche par nom scientifique (`scientificname`)
27 *                                   ou nom commun (`commonname`).
28 *              - `correspondance`         : (saisie) indique si on doit rechercher le texte exact ou pas.
29 *              - `recherche`              : (saisie) texte de la recherche.
30 *              - `regne`                  : (saisie) règne d'appartenance de l'espèce pour limiter le scope de recherche.
31 *              - `_types_recherche`       : (affichage) recherche par nom scientifique ou par nom commun.
32 *              - `_type_recherche_defaut` : (affichage) le type de recherche par défaut est toujours `nom_scientifique`.
33 *              - `_regnes`                : (affichage) liste des règnes déjà chargés dans la base de taxonomie.
34 *              - `_regne_defaut`          : (affichage) le règne par défaut qui est toujours le premier de la liste.
35 *              - `_etapes`                : (affichage) nombre d'étapes du formulaire, à savoir, 3.
36 */
37function formulaires_creer_espece_charger() {
38
39        // Initialisation du chargement.
40        $valeurs = array();
41
42        // Paramètres de saisie de l'étape 1
43        // Type et nature de la recherche, texte de la recherche (qui peut-être non vide si on affiche une erreur
44        // dans la vérification 1) et règne.
45        $valeurs['type_recherche'] = _request('type_recherche');
46        $valeurs['recherche'] = _request('recherche');
47        $valeurs['correspondance'] = _request('correspondance');
48        $valeurs['regne'] = _request('regne');
49
50        // Types de recherche et défaut.
51        $types = array(
52                'scientificname' => 'nom_scientifique',
53                'commonname'     => 'nom_commun'
54        );
55        foreach ($types as $_type_en => $_type_fr) {
56                $valeurs['_types_recherche'][$_type_en] = _T("taxon:champ_${_type_fr}_label");
57        }
58        $valeurs['_type_recherche_defaut'] = 'scientificname';
59
60        // Types de correspondance et défaut.
61        $correspondances = array('exact', 'contenu', 'debut', 'fin');
62        foreach ($correspondances as $_correspondance) {
63                $valeurs['_correspondances'][$_correspondance] = _T("taxonomie:label_recherche_correspondance_${_correspondance}");
64        }
65        $valeurs['_correspondance_defaut'] = 'exact';
66
67        // Acquérir la liste des règnes déjà chargés. Si un règne n'est pas chargé il n'apparait pas dans la liste
68        // car il ne sera alors pas possible de créer correctement l'espèce avec sa hiérarchie de taxons.
69        include_spip('inc/taxonomie');
70        $regnes = regne_lister();
71        foreach ($regnes as $_regne) {
72                if (regne_existe($_regne, $meta_regne)) {
73                        $valeurs['_regnes'][$_regne] = ucfirst(_T("taxonomie:regne_${_regne}"));
74                }
75        }
76        // On force toujours un règne, le premier de la liste.
77        reset($valeurs['_regnes']);
78        $valeurs['_regne_defaut'] = key($valeurs['_regnes']);
79
80        // Initialisation des paramètres du formulaire utilisés en étape 2 et 3 et mis à jour dans les vérifications
81        // de l'étape 1 et 2.
82        // -- Etape 2 (vérification 1)
83        $valeurs['_taxons'] = _request('_taxons');
84        $valeurs['_taxon_defaut'] = _request('_taxon_defaut');
85        // -- Etape 3 (vérification 2)
86        $valeurs['tsn'] = _request('tsn');
87        $valeurs['_espece'] = _request('_espece');
88        $valeurs['_parents'] = _request('_parents');
89
90        // Préciser le nombre d'étapes du formulaire
91        $valeurs['_etapes'] = 3;
92
93        return $valeurs;
94}
95
96/**
97 * Vérification de l'étape 1 du formulaire :
98 *
99 * @uses itis_search_tsn()
100 * @uses itis_get_record()
101 *
102 * @return array
103 *        Message d'erreur si aucun taxon disponible ou si il existe une erreur dans les saisies.
104 *        Sinon, chargement des champs utiles à l'étape 2 :
105 *            - `_taxons`       : (affichage) liste des taxons correspondant à la recherche (tsn, nom scientifique et rang).
106 *            - `_taxon_defaut` : (affichage) tsn du taxon choisi par défaut.
107  */
108function formulaires_creer_espece_verifier_1() {
109
110        // Initialisation des erreurs de vérification.
111        $erreurs = array();
112
113        // Il est inutile de vérifier à nouveau les valeurs de l'étape 1 si on est dans une étape ultérieure
114        // car on ne modifie rien. On gagne du temps en passant outre.
115        if (_request('_etape') == 1) {
116                // Si on a déjà choisi une langue, on peut accéder à Wikipedia avec le nom scientifique et retourner
117                // les pages trouvées (étape 2).
118                if ($recherche = ltrim(_request('recherche'))) {
119                        // On récupère le type de recherche et la correspondance.
120                        $type_recherche = _request('type_recherche');
121                        $correspondance = _request('correspondance');
122                        $recherche_exacte = ($correspondance == 'exact');
123                        $recherche_commence_par = ($correspondance == 'debut');
124
125                        // Si la recherche est de type nom commun on ne peut rien vérifier sur le texte.
126                        // Si la recherche est de type nom scientifique, on vérifie que le texte de recherche :
127                        // - contient au moins deux mots
128                        // - que le deuxième mot n'est pas un 'x' (désigne uniquement un taxon de rang supérieur hybride)
129                        // - et que le deuxième mot n'est pas entre parenthèses (sous-genre).
130                        $recherche_conforme = true;
131                        if ($type_recherche == 'scientificname') {
132                                $nombre_mots = preg_match_all('#\w+#', $recherche, $mots);
133                                if (($nombre_mots < 2) and ($recherche_exacte)) {
134                                        $recherche_conforme = false;
135                                } elseif ($nombre_mots == 2) {
136                                        if ((strtolower($mots[0][1]) == 'x')
137                                        or ((substr($mots[0][1], 0, 1) == '(') and (substr($mots[0][1], -1) == ')'))) {
138                                                $recherche_conforme = false;
139                                        }
140                                }
141                        }
142
143                        if ($recherche_conforme) {
144                                // On recherche le ou les taxons correspondant au texte saisi.
145                                // -- récupération du règne
146                                $regne =  _request('regne');
147                                // -- suppression des espaces en trop dans la chaîne de recherche pour permettre la comparaison
148                                //    avec le combinedName ou le commonName d'ITIS.
149                                $recherche = preg_replace('#\s{2,}#', ' ', $recherche);
150
151                                // Appel de l'API de recherche d'ITIS en fonction du type et de la correspondance de recherche
152                                $action = $type_recherche;
153                                if (($type_recherche == 'commonname') and ($correspondance == 'debut')) {
154                                        $action = 'commonnamebegin';
155                                } elseif (($type_recherche == 'commonname') and ($correspondance == 'fin')) {
156                                        $action = 'commonnameend';
157                                }
158                                include_spip('services/itis/itis_api');
159                                $taxons = itis_search_tsn($action, $recherche, $recherche_exacte);
160                                if ($taxons) {
161                                        if ($recherche_exacte) {
162                                                // Si la correspondance est exacte, les informations de chaque taxon sont suffisantes pour limiter
163                                                // d'emblée le nombre de taxon au seul qui correspond.
164                                                // Néanmoins si un seul taxon est renvoyé rien est à faire car on a déjà le bon taxon.
165                                                if (count($taxons) > 1) {
166                                                        $taxon_exact = array();
167                                                        foreach ($taxons as $_taxon) {
168                                                                if ((($type_recherche == 'scientificname') and (strcasecmp($_taxon['nom_scientifique'], $recherche) === 0))
169                                                                or (($type_recherche == 'commonname') and (strcasecmp($_taxon['nom_commun'], $recherche) === 0))) {
170                                                                        $taxon_exact = $_taxon;
171                                                                        break;
172                                                                }
173                                                        }
174                                                        $taxons = $taxon_exact ? array($taxon_exact) : array();
175                                                }
176                                        } elseif ($recherche_commence_par and ($type_recherche == 'scientificname')) {
177                                                // Si la correspondance est 'commence par' et que l'on recherche par nom scientifique, les informations
178                                                // de chaque taxon sont suffisantes pour limiter d'emblée le nombre de taxons à ceux qui commencent
179                                                // par la recherche.
180                                                foreach ($taxons as $_cle => $_taxon) {
181                                                        if (substr_compare($_taxon['nom_scientifique'], $recherche, 0, strlen($recherche), true) !== 0) {
182                                                                unset($taxons[$_cle]);
183                                                        }
184                                                }
185                                        }
186
187                                        // Etant donné qu'on a filtré le tableau issu de l'appel au service ITIS on vérifie à nouveau que
188                                        // ce tableau n'est pas vide.
189                                        if ($taxons) {
190                                                // Si le nombre de taxons récupérés est trop important on renvoie une erreur.
191                                                if (count($taxons) <= _TAXONOMIE_RECHERCHE_MAX_ESPECES) {
192                                                        // Construire le tableau des taxons trouvés en supprimant:
193                                                        // - les taxons qui n'appartiennent pas au règne concerné
194                                                        // - ou qui n'ont pas un rang compatible (uniquement pour la recherche par nom commun)
195                                                        // - ou qui ne sont pas des appellations valides
196                                                        // - ou qui sont déjà créés.
197                                                        $valeurs['_taxons'] = array();
198                                                        $valeurs['_taxon_defaut'] = 0;
199                                                        include_spip('inc/taxonomie');
200                                                        foreach ($taxons as $_taxon) {
201                                                                if (!sql_countsel('spip_taxons', array('tsn=' . intval($_taxon['tsn'])))) {
202                                                                        $taxon = itis_get_record($_taxon['tsn']);
203                                                                        if (($taxon['usage_valide'])
204                                                                        and (strcasecmp($taxon['regne'], $regne) === 0)
205                                                                        and (rang_est_espece($taxon['rang_taxon']))) {
206                                                                                if ($type_recherche == 'scientificname') {
207                                                                                        $valeurs['_taxons'][$taxon['tsn']] = '<span class="nom_scientifique_inline">'
208                                                                                                . $_taxon['nom_scientifique']
209                                                                                                . '</span>'
210                                                                                                . ' - '
211                                                                                                . _T('taxonomie:rang_' . $taxon['rang_taxon']);
212                                                                                        if (strcasecmp($recherche, $_taxon['nom_scientifique']) === 0) {
213                                                                                                $valeurs['_taxon_defaut'] = $taxon['tsn'];
214                                                                                        }
215                                                                                } else {
216                                                                                        // Vérifier que ce rang est compatible avec une espèce ou un rang inférieur.
217                                                                                        $valeurs['_taxons'][$taxon['tsn']] = $_taxon['nom_commun']
218                                                                                                . " [{$_taxon['langage']}]"
219                                                                                                . ' - '
220                                                                                                . _T('taxonomie:rang_' . $taxon['rang_taxon']);
221                                                                                        if (strcasecmp($recherche, $_taxon['nom_commun']) === 0) {
222                                                                                                $valeurs['_taxon_defaut'] = $taxon['tsn'];
223                                                                                        }
224                                                                                }
225                                                                        }
226                                                                }
227                                                        }
228
229                                                        if ($valeurs['_taxons']) {
230                                                                // Si aucun taxon par défaut, on prend le premier taxon de la liste.
231                                                                if (!$valeurs['_taxon_defaut']) {
232                                                                        reset($valeurs['_taxons']);
233                                                                        $valeurs['_taxon_defaut'] = key($valeurs['_taxons']);
234                                                                }
235                                                                // On fournit ces informations au formulaire pour l'étape 2.
236                                                                foreach ($valeurs as $_champ => $_valeur) {
237                                                                        set_request($_champ, $_valeur);
238                                                                }
239                                                        } else {
240                                                                $erreurs['message_erreur'] = _T('taxonomie:erreur_recherche_aucun_taxon');
241                                                        }
242                                                } else {
243                                                        $erreurs['message_erreur'] = _T('taxonomie:erreur_recherche_max_reponses', array('nb' => count($taxons)));
244                                                }
245                                        } else {
246                                                $erreurs['message_erreur'] = _T('taxonomie:erreur_recherche_aucun_taxon');
247                                        }
248                                } else {
249                                        $erreurs['message_erreur'] = _T('taxonomie:erreur_recherche_aucun_taxon');
250                                }
251                        } else {
252                                $erreurs['recherche'] = _T('taxonomie:erreur_recherche_nom_scientifique');
253                        }
254                } else {
255                        $erreurs['recherche'] = _T('info_obligatoire');
256                }
257        }
258
259        return $erreurs;
260}
261
262
263/**
264 * Vérification de l'étape 2 du formulaire : on présente les informations principales du taxon choisi avant
265 * que l'utilisateur ne valide définitivement son choix. En particulier, on affiche la hiérarchie du taxon
266 * jusqu'au premier taxon de genre et on identifie les taxons qui seront aussi créés dans cette hiérarchie.
267 *
268 * @uses itis_get_record()
269 * @uses itis_get_information()
270 * @uses rang_est_espece()
271 *
272 * @return array
273 *        Message d'erreur si le service ITIS ne renvoie pas les informations demandées (a priori jamais).
274 *        Sinon, chargement des champs utiles à l'étape 3 :
275 *              - `_espece`  : (affichage) toutes les informations ITIS sur l'espèce.
276 *              - `_parents` : (affichage) toutes les informations ITIS sur l'ascendance de l'espèce jusqu'au genre.
277 */
278function formulaires_creer_espece_verifier_2() {
279
280        // Initialisation des erreurs de vérification.
281        $erreurs = array();
282
283        // Il est cette fois indispensable de vérifier à nouveau les valeurs de l'étape 2 si on est dans une l'étape 3
284        // car on a besoin de l'espèce et de ses ascendants jusqu'au genre compris.
285        if ($tsn = intval(_request('tsn'))) {
286                // On récupère les informations de base du taxon afin de les présenter à l'utilisateur pour validation
287                // finale. Ces informations existent forcément car elles ont été demandées à l'étape précédentes et son
288                // donc accessibles directement dans un cache.
289                include_spip('services/itis/itis_api');
290                $espece = itis_get_record($tsn);
291
292                // On passe au formulaire la description de l'espèce après avoir construit la liste des noms communs utiles.
293                $nom_commun = '';
294                if ($espece['nom_commun']) {
295                        include_spip('inc/config');
296                        $langues_utilisees = lire_config('taxonomie/langues_utilisees');
297                        foreach ($espece['nom_commun'] as $_langue => $_nom) {
298                                if (in_array($_langue, $langues_utilisees)) {
299                                        $nom_commun .= ($nom_commun ? '<br />': '') . '[' . $_langue .'] ' . $_nom;
300                                }
301                        }
302                }
303                $espece['nom_commun_affiche'] = $nom_commun;
304                set_request('_espece', $espece);
305
306                // On récupère la hiérarchie complète du taxon à partir de la base ITIS.
307                $ascendants = itis_get_information('hierarchyfull', $espece['tsn']);
308                // Comme la hiérarchie intègre aussi le taxon concerné et les descendants on les supprime. Il y a donc a
309                // minima toujours une suppression celle du taxon concerné.
310                $index = count($ascendants);
311                do {
312                        $index = $index - 1;
313                        $est_espece = $ascendants[$index]['tsn'] == $tsn;
314                        unset($ascendants[$index]);
315                } while (!$est_espece);
316
317                // On classe la liste des ascendants du plus proche au plus éloigné.
318                include_spip('inc/taxonomie');
319                $parents = array();
320                krsort($ascendants);
321                foreach ($ascendants as $_ascendant) {
322                        // Le premier ascendant est toujours affiché.
323                        $parent = $_ascendant;
324                        // On détermine si l'ascendant est un taxon d'espèce ou inférieur,
325                        // ou si c'est un taxon de rang supérieur à l'espèce.
326                        $parent['est_espece'] = rang_est_espece($_ascendant['rang_taxon']);
327                        // On indique si le parent existe déjà ou pas en base
328                        $parent['deja_cree'] = false;
329                        if (sql_countsel('spip_taxons', array('tsn=' . intval($_ascendant['tsn'])))) {
330                                $parent['deja_cree'] = true;
331                        }
332                        // On insère l'ascendant dans la liste des parents.
333                        $parents[] = $parent;
334                        // On sort si on est arrivé au taxon de genre.
335                        if ($_ascendant['rang_taxon'] == _TAXONOMIE_RANG_GENRE) {
336                                break;
337                        }
338                }
339                $parents = array_reverse($parents);
340                set_request('_parents', $parents);
341        } else {
342                $erreurs['message_erreur'] = _T('taxonomie:erreur_formulaire_creer_espece');
343        }
344
345        return $erreurs;
346}
347
348
349/**
350 * Exécution du formulaire : si une page est choisie et existe le descriptif est inséré dans le taxon concerné
351 * et le formulaire renvoie sur la page d'édition du taxon.
352 *
353 * @uses itis_get_record()
354 *
355 * @return array
356 *              Tableau retourné par le formulaire contenant toujours un message de bonne exécution ou
357 *              d'erreur. L'indicateur editable est toujours à vrai.
358 */
359function formulaires_creer_espece_traiter() {
360
361        // Initialisation du retour de la fonction
362        $retour = array();
363
364        if ($tsn = intval(_request('tsn'))) {
365                // Récupération de la liste des champs de la table spip_taxons.
366                include_spip('base/objets');
367                $description_table = lister_tables_objets_sql('spip_taxons');
368                $champs['spip_taxons'] = $description_table['field'];
369
370                // On range la liste des taxons de plus haut rang (genre) à celui de plus petit rang et on ajoute le
371                // taxon espèce en fin de liste. La variable _parents est toujours un tableau d'au moins une unité et
372                // l'espèce existe toujours.
373                $taxons = _request('_parents');
374                $taxons[] = _request('_espece');
375
376                // On boucle d'abord sur les parents si nécessaire et ensuite sur l'espèce.
377                // De cette façon, on évite d'avoir une base incohérente où un taxon de rang inférieur existerait
378                // sans son parent direct.
379                // L'espèce concernée est identifiée car son enregistrement ne contient pas les index deja_cree et est_espece.
380                $erreurs = array();
381                foreach ($taxons as $_index => $_taxon) {
382                        if (empty($_taxon['deja_cree'])) {
383                                // Le genre est le premier parent de la liste ainsi triée et est forcément déjà créé.
384                                // Les parents non créés sont donc soit des taxons comme les sous-genres etc, soit un taxon de rang
385                                // espèce ou inférieur.
386                                // -- On récupère le bloc des informations ITIS du taxon à créer et sa table de destination.
387                                $table = 'spip_taxons';
388                                if (isset($_taxon['deja_cree'])) {
389                                        // C'est un ascendant de l'espèce
390                                        $taxon = itis_get_record($_taxon['tsn']);
391                                } else {
392                                        // C'est l'espèce
393                                        $taxon = $_taxon;
394                                }
395                                // -- On ne retient que les index correspondant à des champs de la table concernée.
396                                $taxon = array_intersect_key($taxon, $champs[$table]);
397
398                                // On formate le nom commun en multi.
399                                $nom_multi = '';
400                                foreach ($taxon['nom_commun'] as $_langue => $_nom) {
401                                        $nom_multi .= '[' . $_langue . ']' . trim($_nom);
402                                }
403                                if ($nom_multi) {
404                                        $nom_multi = '<multi>' . $nom_multi . '</multi>';
405                                }
406                                $taxon['nom_commun'] = $nom_multi;
407
408                                // Finalisation de l'enregistrement du taxon suivant son rang (ie. sa table).
409                                // -- tous les taxons créés on des indicateurs d'édition et d'importation à 'non'
410                                $taxon['edite'] = 'non';
411                                $taxon['importe'] = 'non';
412                                if (isset($_taxon['est_espece']) and !$_taxon['est_espece']) {
413                                        // Pour les taxons de rang supérieur à une espèce, on positionne le statut à 'publie'
414                                        // comme pour tous les autres taxons de ce type (ceux importés via le fichier de règne).
415                                        $taxon['espece'] = 'non';
416                                        $taxon['statut'] = 'publie';
417                                } else {
418                                        // Pour les taxons espèce et de rang inférieur, on positionne le statut à prop
419                                        // (pas de publication par défaut).
420                                        $taxon['espece'] = 'oui';
421                                        $taxon['statut'] = 'prop';
422                                }
423
424                                // Insertion du taxon dans la table idoine.
425                                $id_taxon = sql_insertq($table, $taxon);
426                                if ($id_taxon) {
427                                        if (!isset($_taxon['deja_cree'])) {
428                                                $id_espece = $id_taxon;
429                                        }
430                                } else {
431                                        // En cas d'erreur on sort de la boucle pour éviter de créer des taxons sans parent.
432                                        $erreurs = $taxon;
433                                        break;
434                                }
435                        }
436                }
437
438                if ($erreurs) {
439                        $retour['message_erreur'] = _T('taxonomie:erreur_creation_taxon', array('taxon' => $erreurs['nom_scientifique']));
440                } else {
441                        // Redirection vers la page d'édition du taxon
442                        $retour['redirect'] = parametre_url(generer_url_ecrire('taxon_edit'), 'id_taxon', $id_espece);
443                }
444        } else {
445                $retour['message_erreur'] = _T('taxonomie:erreur_formulaire_creer_espece');
446        }
447
448        return $retour;
449}
Note: See TracBrowser for help on using the repository browser.