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

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

Ajouter quelques vérifications.

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