source: spip-zone/_plugins_/taxonomie/trunk/taxonomie_ieconfig.php @ 113677

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

Correction items de langue et rang_taxon au lieu de rang.

  • Property svn:eol-style set to native
File size: 19.2 KB
Line 
1<?php
2
3if (!defined('_ECRIRE_INC_VERSION')) {
4        return;
5}
6
7/**
8 * Pipeline ieconfig pour l'import/export des données de configuration du plugin et de certaines données de production.
9 *
10 * @param array $flux
11 *
12 * @return array
13 */
14function taxonomie_ieconfig($flux) {
15
16        // On détermine l'action demandée qui peut être : afficher le formulaire d'export ou d'import, construire le
17        // tableau d'export ou exécuter l'importation.
18        $action = $flux['args']['action'];
19
20        if ($action == 'form_export') {
21                // Construire le formulaire d'export :
22                // -- on demande le minimum à savoir si l'utilisateur veut inclure dans son export l'ensemble des données
23                //    de Taxonomie.
24                $saisies = array(
25                        array(
26                                'saisie' => 'fieldset',
27                                'options' => array(
28                                        'nom'   => 'taxonomie_fieldset',
29                                        'label' => '<:taxonomie:titre_page_taxonomie:>',
30                                        'icone' => 'taxon-16.png',
31                                ),
32                                'saisies' => array(
33                                        array(
34                                                'saisie' => 'oui_non',
35                                                'options' => array(
36                                                        'nom' => 'taxonomie_export_option',
37                                                        'label' => '<:taxonomie:export_option:>',
38                                                        'explication' => '<:taxonomie:export_explication:>',
39                                                        'defaut' => '',
40                                                ),
41                                        ),
42                                ),
43                        ),
44                );
45                $flux['data'] = array_merge($flux['data'], $saisies);
46
47        } elseif (($action == 'export') and (_request('taxonomie_export_option') == 'on')) {
48                // Générer le tableau d'export
49                $flux['data']['taxonomie'] = taxonomie_ieconfig_exporter();
50
51        } elseif (($action == 'form_import') and isset($flux['args']['config']['taxonomie'])) {
52                // Construire le formulaire d'import :
53                // On affiche la version de Taxonomie et le schéma de base de données avec lesquels le fichier d'import
54                // à été créé.
55                $import = $flux['args']['config']['taxonomie'];
56                $texte_explication = _T(
57                        'taxonomie:import_resume',
58                        array('version' => $import['version'], 'schema' => $import['schema']));
59
60                // La configuration : une case suffit car on applique toujours un remplacement et la configuration est
61                // toujours présente dans un export.
62                $informer_plugin = chercher_filtre('info_plugin');
63                $version = $informer_plugin('taxonomie', 'version', true);
64                $schema = $informer_plugin('taxonomie', 'schema');
65                $plugin = $informer_plugin('taxonomie', 'nom');
66                if ($schema == $import['schema']) {
67                        $explication_config = _T(
68                                'taxonomie:import_configuration_explication',
69                                array('version' => $version, 'schema' => $schema));
70                } else {
71                        $explication_config = _T(
72                                'taxonomie:import_configuration_avertissement',
73                                array('version' => $version, 'schema' => $schema));
74                }
75
76                $saisies = array(
77                        array(
78                                'saisie'  => 'fieldset',
79                                'options' => array(
80                                        'nom'   => 'taxonomie_export',
81                                        'label' => $plugin,
82                                        'icone' => 'taxonomie-24.png',
83                                ),
84                                'saisies' => array(
85                                        array(
86                                                'saisie'  => 'explication',
87                                                'options' => array(
88                                                        'nom'   => 'taxonomie_export_explication',
89                                                        'texte' => $texte_explication,
90                                                ),
91                                        ),
92                                        array(
93                                                'saisie'  => 'case',
94                                                'options' => array(
95                                                        'nom'         => 'taxonomie_import_config',
96                                                        'label'       => '<:taxonomie:import_configuration_label:>',
97                                                        'label_case'  => '<:taxonomie:import_configuration_labelcase:>',
98                                                        'explication' => $explication_config
99                                                ),
100                                        ),
101                                ),
102                        ),
103                );
104                $flux['data'] = array_merge($flux['data'], $saisies);
105        }
106
107        // Import de la configuration
108        if (($action == 'import') and isset($flux['args']['config']['noizetier'])) {
109                // On récupère les demandes d'importation.
110                $importation['configuration'] = _request('taxonomie_import_config');
111                $importation['pages_explicites'] = _request('noizetier_import_pages');
112                $importation['compositions_virtuelles'] = _request('noizetier_import_compositions');
113                $importation['noisettes'] = _request('noizetier_import_noisettes');
114
115                // Si au moins l'une est requise on appelle la fonction d'import.
116                if ($importation['configuration']
117                or $importation['pages_explicites']
118                or $importation['compositions_virtuelles']
119                or $importation['noisettes']) {
120                        if (!noizetier_ieconfig_importer($importation, $flux['args']['config']['noizetier'])) {
121                                $flux['data'] .= _T('noizetier:ieconfig_probleme_import_config').'<br />';
122                        }
123                }
124        }
125
126        return $flux;
127}
128
129
130// --------------------------------------------------------------------
131// ------------------------- API IMPORT/EXPORT ------------------------
132// --------------------------------------------------------------------
133
134/**
135 * Retourne le tableau d'export du plugin Taxonomie contenant toujours sa configuration et les taxons nécessitant d'être
136 * sauvegardés car non créés via les fichiers ITIS.
137 * Les taxons concernés sont :
138 * - les taxons du règne au genre, importés via les fichiers ITIS puis édités manuellement;
139 * - les taxons ascendants d'une espèce (entre le genre et l'espèce non compris), non inclus dans un fichier ITIS
140 *   et insérés lors de la création d'une espèce;
141 * - les taxons de type espèce et descendants créés manuellement.
142 *
143 * @return array
144 *         Tableau d'export pour le pipeline ieconfig_exporter.
145 **/
146function taxonomie_ieconfig_exporter() {
147
148        $export = array();
149
150        // Insérer une en-tête qui permet de connaitre la version du plugin Taxonomie utilisé lors de l'export
151        $informer_plugin = chercher_filtre('info_plugin');
152        $export['version'] = $informer_plugin('taxonomie', 'version', true);
153        $export['schema'] = $informer_plugin('taxonomie', 'schema');
154        $export['contenu'] = array();
155
156        // Exportation de la configuration du plugin rangée dans la meta taxonomie uniquement.
157        // Etant donné que l'on utilise ce pipeline pour les données de production de Taxonomie, on exporte aussi
158        // sa configuration via ce pipeline et non via le pipeline ieconfig_metas.
159        include_spip('inc/config');
160        $export['configuration'] = lire_config('taxonomie');
161        $export['contenu']['configuration'] = $export['configuration'] ? 'on' : '';
162
163        // Les metas de chargement de chaque règne ne sont pas exportées mais on identifie quand même la liste des règnes
164        // insérés dans la base. Les taxons seront ensuite exportés par règne pour permettre un import plus ciblé.
165        include_spip('taxonomie_fonctions');
166        include_spip('inc/taxonomie');
167        $export['regnes'] = array();
168        $regnes = regne_lister();
169        foreach ($regnes as $_regne) {
170                if (regne_existe($_regne, $meta_regne)) {
171                        $export['regnes'][] = $_regne;
172                }
173        }
174        $export['contenu']['regnes'] = $export['regnes'] ? 'on' : '';
175
176        // Exportation de la table spip_taxons des taxons nécessitant d'être sauvegardés.
177        if ($export['contenu']['regnes']) {
178                // Récupération de la description de la table spip_taxons afin de connaitre la liste des colonnes.
179                include_spip('base/objets');
180                $from ='spip_taxons';
181                $description_table = lister_tables_objets_sql($from);
182                $select = array_diff(array_keys($description_table['field']), array('id_taxon', 'maj'));
183
184                // Pour faciliter l'import et aussi mieux le cibler les taxons exportés sont rangés par règne (index au nom
185                // du règne). Ensuite, on sépare aussi les taxons édités (index [taxons][edites]), les taxons créés en tant
186                // qu'ascendant d'une espèce (index [taxons][crees]) et les espèces créées manuellement (index [especes]).
187                foreach ($export['regnes'] as $_regne) {
188                        // Extraction des taxons du règne au genre édités manuellement par les utilisateurs ou créés lors d'un
189                        // ajout d'espèce.
190                        // On sauvegarde les champs éditables uniquement des édités et tous les champs pour les autres.
191                        $export[$_regne]['taxons'] = taxon_preserver($_regne);
192                        $export['contenu']['taxons']['edites'][$_regne] = $export[$_regne]['taxons']['edites'] ? 'on' : '';
193                        $export['contenu']['taxons']['crees'][$_regne] = $export[$_regne]['taxons']['crees'] ? 'on' : '';
194
195                        // Extraction des espèces et descendants.
196                        $export[$_regne]['especes'] = array();
197                        $where = array(
198                                'regne=' . sql_quote($_regne),
199                                'importe=' . sql_quote('non'),
200                                'espece=' . sql_quote('oui')
201                        );
202                        $export[$_regne]['especes'] = sql_allfetsel($select, $from, $where);
203                        $export['contenu']['especes'][$_regne] = $export[$_regne]['especes'] ? 'on' : '';
204                }
205        }
206
207        return $export;
208}
209
210/**
211 * Importe tout ou partie d'un fichier d'export ieconfig contenant les données du noiZetier.
212 *
213 * @param array $importation
214 *        Tableau associatif des demandes d'importation issues du formulaire ieconfig. Les index et les valeurs
215 *        possibles sont :
216 *        - `configuration` : vaut `on` pour importer ou null sinon
217 *        - `pages_explicites` : vaut `on` pour importer ou null sinon
218 *        - `compositions_virtuelles` : vaut `remplacer`, `ajouter` ou `fusionner` pour importer ou null sinon.
219 *        - `noisettes` : vaut `remplacer` ou `ajouter` pour importer ou null sinon.
220 * @param array $contenu_import
221 *        Tableau des données du noiZetier issues du fichier d'import.
222 *
223 * @return bool
224 */
225function taxonomie_ieconfig_importer($importation, $contenu_import) {
226
227        // Initialisation de la sortie
228        $retour = true;
229
230        // On appelle le pipeline pour éventuellement modifier le contenu à importer.
231        $contenu_import = pipeline('noizetier_config_import', $contenu_import);
232
233        // On récupère la liste des blocs par défaut des pages du site pour filtrer des blocs non autorisés
234        // provenant éventuellement de l'import. Cette liste sert pour les pages explicites et les compositions virtuelles.
235        include_spip('inc/noizetier_bloc');
236        $blocs_defaut = noizetier_bloc_lister_defaut();
237
238        // La configuration
239        if ($importation['configuration']) {
240                // On remplace la configuration actuelle par celle du fichier d'import.
241                include_spip('inc/config');
242                ecrire_config('noizetier', $contenu_import['configuration']);
243        }
244
245        // Les pages explicites
246        if ($importation['pages_explicites']) {
247                // On fusionne les blocs exclus de la configuration avec ceux des pages explicites de la base.
248                // -- On récupère toutes les pages de la base avec leur blocs exclus
249                $select = array('page', 'blocs_exclus');
250                $where = array('est_virtuelle=' . sql_quote('non'));
251                $pages_explicites_base = sql_allfetsel($select,'spip_noizetier_pages', $where);
252                // -- on structure les blocs exclus du fichier d'import sous la forme [page] = blocs exclus
253                $blocs_exclus_import = array_column($contenu_import['pages_explicites'], 'blocs_exclus', 'page');
254                // -- on compare les pages de la base et celles de l'import et on met à jour systématiquement
255                //    les pages communes (même identifiant).
256                foreach ($pages_explicites_base as $_page_explicite) {
257                        if (isset($blocs_exclus_import[$_page_explicite['page']])) {
258                                // Remplacement des blocs exclus de la page actuelle par ceux du fichier d'import. On filtre
259                                // les blocs éventuellement non autorisés sur le site.
260                                $modification = array(
261                                        'blocs_exclus' => array_intersect($blocs_exclus_import[$_page_explicite['page']], $blocs_defaut)
262                                );
263                                $where = array('page=' . sql_quote($_page_explicite['page']));
264                                sql_updateq('spip_noizetier_pages', $modification, $where);
265                        }
266                }
267        }
268
269        // Les compositions virtuelles
270        if ($importation['compositions_virtuelles']) {
271                if ($importation['compositions_virtuelles'] == 'remplacer') {
272                        // On vide d'abord la table spip_noizetier_pages de toutes le compositions virtuelles du noiZetier.
273                        $where = array('est_virtuelle=' . sql_quote('oui'));
274                        if (!sql_delete('spip_noizetier_pages', $where)) {
275                                $retour = false;
276                        }
277                }
278
279                if ($retour) {
280                        // On collecte les compositions virtuelles actuellement en base.
281                        $select = array('page');
282                        $where = array('est_virtuelle=' . sql_quote('oui'));
283                        $compositions_base = sql_allfetsel($select, 'spip_noizetier_pages', $where);
284                        if ($compositions_base) {
285                                $compositions_base = array_map('reset', $compositions_base);
286                        }
287
288                        // Suivant le mode d'importation et l'existence ou pas de la composition en base on ajoute ou
289                        // on met à jour la composition virtuelle ou on ne fait rien.
290                        foreach ($contenu_import['compositions_virtuelles'] as $_composition) {
291                                // On filtre les blocs exclus avec la liste des blocs par défaut du site.
292                                $composition = $_composition;
293                                $composition['blocs_exclus'] = array_intersect($composition['blocs_exclus'], $blocs_defaut);
294
295                                // On détermine l'opération à faire ou pas.
296                                if (in_array($composition['page'], $compositions_base)) {
297                                        if ($importation['compositions_virtuelles'] == 'fusionner') {
298                                                $where = 'page=' . sql_quote($composition['page']);
299                                                unset($composition['page']);
300                                                sql_updateq('spip_noizetier_pages', $composition, $where);
301                                        }
302                                } else {
303                                        sql_insertq('spip_noizetier_pages', $composition);
304                                }
305                        }
306                }
307        }
308
309        // Les noisettes
310        if ($importation['noisettes']) {
311                if ($importation['noisettes'] == 'remplacer') {
312                        // On vide d'abord la table spip_noisettes de toutes les noisettes du noiZetier.
313                        $where = array('plugin=' . sql_quote('noizetier'));
314                        if (sql_delete('spip_noisettes', $where) === false) {
315                                $retour = false;
316                        }
317                }
318
319                if ($retour) {
320                        // Liste des pages génériques disponibles dans la base.
321                        $pages_base = sql_allfetsel('page','spip_noizetier_pages');
322                        $pages_base = array_map('reset', $pages_base);
323
324                        // Nombre de noisettes par conteneur. On récupère l'ensemble des conteneurs y compris les noisettes
325                        // conteneur mais seuls les blocs Z du noiZetier sont utiles.
326                        $select = array('id_conteneur', 'count(*) as nb_noisettes');
327                        $where = array('plugin=' . sql_quote('noizetier'));
328                        $group_by = array('id_conteneur');
329                        $nb_noisettes_base = sql_allfetsel($select, 'spip_noisettes', $where, $group_by);
330                        if ($nb_noisettes_base) {
331                                $nb_noisettes_base = array_column($nb_noisettes_base, 'nb_noisettes', 'id_conteneur');
332                        }
333
334                        // On insère les noisettes du fichier d'import appartenant à des pages ou des objets disponibles dans la
335                        // base. Dans le fichier d'export, les noisettes conteneur sont classées avant les autres noisettes et
336                        // suivant une profondeur croissante de façon à être créées quand les noisettes imbriquées le nécessiteront.
337                        // Cette opération se fait en deux passes pour gérer le fait que les noisettes conteneur vont
338                        // changer d'id ce qui change leur identifiant de conteneur :
339                        // - Passe 1 : si la noisette est à insérer on l'ajoute dans le conteneur sans se préoccuper du changement
340                        //             d'id de conteneur pour les noisettes conteneur. On stocke toutes les informations nécessaires
341                        //             à la passe 2 comme le nouvel id des noisettes conteneur.
342                        include_spip('base/objets');
343                        include_spip('inc/ncore_conteneur');
344                        include_spip('inc/ncore_noisette');
345                        $noisettes_conteneur = $noisettes_imbriquees = array();
346                        foreach ($contenu_import['noisettes'] as $_id_noisette_ancien => $_noisette) {
347                                // On vérifie qu'il faut bien importer la noisette
348                                $noisette_a_importer = false;
349                                if ($_noisette['type']) {
350                                        $page_import = $_noisette['composition']
351                                                ? $_noisette['type'] . '-' . $_noisette['composition']
352                                                : $_noisette['type'];
353                                        if (in_array($page_import, $pages_base)) {
354                                                $noisette_a_importer = true;
355                                        }
356                                } else {
357                                        $table_objet = table_objet_sql($_noisette['objet']);
358                                        $id_table_objet = id_table_objet($_noisette['objet']);
359                                        $where = array($id_table_objet. '=' . intval($_noisette['id_objet']));
360                                        if (sql_countsel($table_objet, $where)) {
361                                                $noisette_a_importer = true;
362                                        }
363                                }
364
365                                if ($noisette_a_importer) {
366                                        // La noisette à importer est bien associée à une page ou un objet de la base.
367                                        // Les noisettes ne sont pas triées dans l'ordre d'insertion pour un conteneur donné,
368                                        // il faut donc se baser sur le rang dans le fichier d'import. Pour une noisette appartenant à un
369                                        // conteneur noisette on reprend le rang tel que mais pour une noisette incluse dans un bloc Z il
370                                        // faut recalculer le rang en tenant compte des noisettes déjà incluses dans la base.
371                                        $rang = $_noisette['rang_noisette'];
372                                        $conteneur = unserialize($_noisette['conteneur']);
373                                        $conteneur_est_noisette = conteneur_est_noisette('noizetier', $conteneur);
374                                        if (!$conteneur_est_noisette) {
375                                                $rang_max = !empty($nb_noisettes_base[$_noisette['id_conteneur']])
376                                                        ? $nb_noisettes_base[$_noisette['id_conteneur']]
377                                                        : 0;
378                                                $rang += $rang_max;
379                                        }
380                                        $id_noisette_nouveau = noisette_ajouter(
381                                                'noizetier',
382                                                $_noisette['type_noisette'],
383                                                $conteneur,
384                                                $rang);
385                                        // La noisette a été ajoutée de façon générique (paramètres par défaut). Pour finaliser l'importation
386                                        // il faut aussi mettre à jour les données paramétrables : parametres, encapsulation et css.
387                                        if ($id_noisette_nouveau) {
388                                                $champs_modifiables = array('parametres');
389                                                if ($_noisette['est_conteneur'] != 'oui') {
390                                                        $champs_modifiables = array_merge($champs_modifiables, array('parametres', 'encapsulation', 'css'));
391                                                }
392                                                $modifications = array_intersect_key($_noisette, array_flip($champs_modifiables));
393                                                noisette_parametrer('noizetier', $id_noisette_nouveau, $modifications);
394                                        }
395
396                                        // Pour conclure il faut stocker les informations nécessaires à la passe suivante:
397                                        // - les noisettes imbriquées dans un conteneur noisette et les référence de ce conteneur
398                                        // - la nouvelle valeur de l'id_noisette des noisettes conteneur
399                                        if ($conteneur_est_noisette) {
400                                                // Il faut se rappeler de la noisette car il faudra changer son conteneur (2 champs) lors de la
401                                                // deuxième passe. On stocke
402                                                $noisettes_imbriquees[$id_noisette_nouveau] = array(
403                                                        'type_noisette' => $conteneur['type_noisette'],
404                                                        'id_noisette' => $conteneur['id_noisette']
405                                                );
406                                        }
407                                        if ($_noisette['est_conteneur'] == 'oui') {
408                                                // La noisette est un conteneur. On constitue un tableau permettant de calculer son nouvel
409                                                // identifiant induit par son nouvel id de noisette. Le tableau est indexé par son ancien id.
410                                                $noisettes_conteneur[$_id_noisette_ancien] = $id_noisette_nouveau;
411                                        }
412                                }
413                        }
414
415                        // - Passe 2 : On reprend les noisettes venant d'être insérées dans une noisette conteneur et
416                        //             on rétablit le bon conteneur (id et tableau sérialisé), la profondeur et les informations
417                        //             du bloc Z accueillant les noisettes.
418                        if ($noisettes_imbriquees) {
419                                foreach ($noisettes_imbriquees as $_id_noisette_nouveau => $_conteneur_ancien) {
420                                        // Détermination du conteneur
421                                        $nouveau_conteneur = $_conteneur_ancien;
422                                        $nouveau_conteneur['id_noisette'] = $noisettes_conteneur[$_conteneur_ancien['id_noisette']];
423
424                                        // Détermination de la profondeur et des caractéristiques du bloc Z de plus haut niveau.
425                                        // Le conteneur est une noisette, qui a été insérée précédemment, on la lit.
426                                        $select = array('type', 'composition', 'objet', 'id_objet',     'bloc', 'profondeur');
427                                        $where = array(
428                                                'id_noisette=' . intval($nouveau_conteneur['id_noisette']),
429                                                'plugin=' . sql_quote('noizetier')
430                                        );
431                                        $modifications = sql_fetsel($select, 'spip_noisettes', $where);
432
433                                        // On finalise les modifications
434                                        $modifications['profondeur'] += 1;
435                                        $modifications['conteneur'] = serialize($nouveau_conteneur);
436                                        $modifications['id_conteneur'] = conteneur_identifier('noizetier', $nouveau_conteneur);
437
438                                        // On met à jour le contenu de la noisette en base.
439                                        $where = array('plugin=' . sql_quote('noizetier'), 'id_noisette=' . intval($_id_noisette_nouveau));
440                                        sql_updateq('spip_noisettes', $modifications, $where);
441                                }
442                        }
443                }
444        }
445
446        // On invalide le cache
447        include_spip('inc/invalideur');
448        suivre_invalideur('noizetier-import-config');
449
450        return $retour;
451}
Note: See TracBrowser for help on using the repository browser.