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

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

Ajout d'une fonction de formatage pour le get hierarchyfull afin de passer le rang en minuscules.
Eviter de repasser dans la vérification de l'étape 1 car cela ne sert à rien.
Corriger l'indexation du tableau de la hiérarchie complète d'une taxon et suppression du taxon lui-même qui ne doit pas faire partie de sa propre hiérarchie.

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