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

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

Transfert de certaines fonctions d'API dans inc/taxonomie car elles ne servent jamais de filtres.

  • 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('inc/taxonomie');
166        $export['regnes'] = array();
167        $regnes = regne_lister();
168        foreach ($regnes as $_regne) {
169                if (regne_existe($_regne, $meta_regne)) {
170                        $export['regnes'][] = $_regne;
171                }
172        }
173        $export['contenu']['regnes'] = $export['regnes'] ? 'on' : '';
174
175        // Exportation de la table spip_taxons des taxons nécessitant d'être sauvegardés.
176        if ($export['contenu']['regnes']) {
177                // Récupération de la description de la table spip_taxons afin de connaitre la liste des colonnes.
178                include_spip('base/objets');
179                $from ='spip_taxons';
180                $description_table = lister_tables_objets_sql($from);
181                $select = array_diff(array_keys($description_table['field']), array('id_taxon', 'maj'));
182
183                // Pour faciliter l'import et aussi mieux le cibler les taxons exportés sont rangés par règne (index au nom
184                // du règne). Ensuite, on sépare aussi les taxons édités (index [taxons][edites]), les taxons créés en tant
185                // qu'ascendant d'une espèce (index [taxons][crees]) et les espèces créées manuellement (index [especes]).
186                foreach ($export['regnes'] as $_regne) {
187                        // Extraction des taxons du règne au genre édités manuellement par les utilisateurs ou créés lors d'un
188                        // ajout d'espèce.
189                        // On sauvegarde les champs éditables uniquement des édités et tous les champs pour les autres.
190                        $export[$_regne]['taxons'] = taxon_preserver($_regne);
191                        $export['contenu']['taxons']['edites'][$_regne] = $export[$_regne]['taxons']['edites'] ? 'on' : '';
192                        $export['contenu']['taxons']['crees'][$_regne] = $export[$_regne]['taxons']['crees'] ? 'on' : '';
193
194                        // Extraction des espèces et descendants.
195                        $export[$_regne]['especes'] = array();
196                        $where = array(
197                                'regne=' . sql_quote($_regne),
198                                'importe=' . sql_quote('non'),
199                                'espece=' . sql_quote('oui')
200                        );
201                        $export[$_regne]['especes'] = sql_allfetsel($select, $from, $where);
202                        $export['contenu']['especes'][$_regne] = $export[$_regne]['especes'] ? 'on' : '';
203                }
204        }
205
206        return $export;
207}
208
209/**
210 * Importe tout ou partie d'un fichier d'export ieconfig contenant les données du noiZetier.
211 *
212 * @param array $importation
213 *        Tableau associatif des demandes d'importation issues du formulaire ieconfig. Les index et les valeurs
214 *        possibles sont :
215 *        - `configuration` : vaut `on` pour importer ou null sinon
216 *        - `pages_explicites` : vaut `on` pour importer ou null sinon
217 *        - `compositions_virtuelles` : vaut `remplacer`, `ajouter` ou `fusionner` pour importer ou null sinon.
218 *        - `noisettes` : vaut `remplacer` ou `ajouter` pour importer ou null sinon.
219 * @param array $contenu_import
220 *        Tableau des données du noiZetier issues du fichier d'import.
221 *
222 * @return bool
223 */
224function taxonomie_ieconfig_importer($importation, $contenu_import) {
225
226        // Initialisation de la sortie
227        $retour = true;
228
229        // On appelle le pipeline pour éventuellement modifier le contenu à importer.
230        $contenu_import = pipeline('noizetier_config_import', $contenu_import);
231
232        // On récupère la liste des blocs par défaut des pages du site pour filtrer des blocs non autorisés
233        // provenant éventuellement de l'import. Cette liste sert pour les pages explicites et les compositions virtuelles.
234        include_spip('inc/noizetier_bloc');
235        $blocs_defaut = noizetier_bloc_lister_defaut();
236
237        // La configuration
238        if ($importation['configuration']) {
239                // On remplace la configuration actuelle par celle du fichier d'import.
240                include_spip('inc/config');
241                ecrire_config('noizetier', $contenu_import['configuration']);
242        }
243
244        // Les pages explicites
245        if ($importation['pages_explicites']) {
246                // On fusionne les blocs exclus de la configuration avec ceux des pages explicites de la base.
247                // -- On récupère toutes les pages de la base avec leur blocs exclus
248                $select = array('page', 'blocs_exclus');
249                $where = array('est_virtuelle=' . sql_quote('non'));
250                $pages_explicites_base = sql_allfetsel($select,'spip_noizetier_pages', $where);
251                // -- on structure les blocs exclus du fichier d'import sous la forme [page] = blocs exclus
252                $blocs_exclus_import = array_column($contenu_import['pages_explicites'], 'blocs_exclus', 'page');
253                // -- on compare les pages de la base et celles de l'import et on met à jour systématiquement
254                //    les pages communes (même identifiant).
255                foreach ($pages_explicites_base as $_page_explicite) {
256                        if (isset($blocs_exclus_import[$_page_explicite['page']])) {
257                                // Remplacement des blocs exclus de la page actuelle par ceux du fichier d'import. On filtre
258                                // les blocs éventuellement non autorisés sur le site.
259                                $modification = array(
260                                        'blocs_exclus' => array_intersect($blocs_exclus_import[$_page_explicite['page']], $blocs_defaut)
261                                );
262                                $where = array('page=' . sql_quote($_page_explicite['page']));
263                                sql_updateq('spip_noizetier_pages', $modification, $where);
264                        }
265                }
266        }
267
268        // Les compositions virtuelles
269        if ($importation['compositions_virtuelles']) {
270                if ($importation['compositions_virtuelles'] == 'remplacer') {
271                        // On vide d'abord la table spip_noizetier_pages de toutes le compositions virtuelles du noiZetier.
272                        $where = array('est_virtuelle=' . sql_quote('oui'));
273                        if (!sql_delete('spip_noizetier_pages', $where)) {
274                                $retour = false;
275                        }
276                }
277
278                if ($retour) {
279                        // On collecte les compositions virtuelles actuellement en base.
280                        $select = array('page');
281                        $where = array('est_virtuelle=' . sql_quote('oui'));
282                        $compositions_base = sql_allfetsel($select, 'spip_noizetier_pages', $where);
283                        if ($compositions_base) {
284                                $compositions_base = array_map('reset', $compositions_base);
285                        }
286
287                        // Suivant le mode d'importation et l'existence ou pas de la composition en base on ajoute ou
288                        // on met à jour la composition virtuelle ou on ne fait rien.
289                        foreach ($contenu_import['compositions_virtuelles'] as $_composition) {
290                                // On filtre les blocs exclus avec la liste des blocs par défaut du site.
291                                $composition = $_composition;
292                                $composition['blocs_exclus'] = array_intersect($composition['blocs_exclus'], $blocs_defaut);
293
294                                // On détermine l'opération à faire ou pas.
295                                if (in_array($composition['page'], $compositions_base)) {
296                                        if ($importation['compositions_virtuelles'] == 'fusionner') {
297                                                $where = 'page=' . sql_quote($composition['page']);
298                                                unset($composition['page']);
299                                                sql_updateq('spip_noizetier_pages', $composition, $where);
300                                        }
301                                } else {
302                                        sql_insertq('spip_noizetier_pages', $composition);
303                                }
304                        }
305                }
306        }
307
308        // Les noisettes
309        if ($importation['noisettes']) {
310                if ($importation['noisettes'] == 'remplacer') {
311                        // On vide d'abord la table spip_noisettes de toutes les noisettes du noiZetier.
312                        $where = array('plugin=' . sql_quote('noizetier'));
313                        if (sql_delete('spip_noisettes', $where) === false) {
314                                $retour = false;
315                        }
316                }
317
318                if ($retour) {
319                        // Liste des pages génériques disponibles dans la base.
320                        $pages_base = sql_allfetsel('page','spip_noizetier_pages');
321                        $pages_base = array_map('reset', $pages_base);
322
323                        // Nombre de noisettes par conteneur. On récupère l'ensemble des conteneurs y compris les noisettes
324                        // conteneur mais seuls les blocs Z du noiZetier sont utiles.
325                        $select = array('id_conteneur', 'count(*) as nb_noisettes');
326                        $where = array('plugin=' . sql_quote('noizetier'));
327                        $group_by = array('id_conteneur');
328                        $nb_noisettes_base = sql_allfetsel($select, 'spip_noisettes', $where, $group_by);
329                        if ($nb_noisettes_base) {
330                                $nb_noisettes_base = array_column($nb_noisettes_base, 'nb_noisettes', 'id_conteneur');
331                        }
332
333                        // On insère les noisettes du fichier d'import appartenant à des pages ou des objets disponibles dans la
334                        // base. Dans le fichier d'export, les noisettes conteneur sont classées avant les autres noisettes et
335                        // suivant une profondeur croissante de façon à être créées quand les noisettes imbriquées le nécessiteront.
336                        // Cette opération se fait en deux passes pour gérer le fait que les noisettes conteneur vont
337                        // changer d'id ce qui change leur identifiant de conteneur :
338                        // - Passe 1 : si la noisette est à insérer on l'ajoute dans le conteneur sans se préoccuper du changement
339                        //             d'id de conteneur pour les noisettes conteneur. On stocke toutes les informations nécessaires
340                        //             à la passe 2 comme le nouvel id des noisettes conteneur.
341                        include_spip('base/objets');
342                        include_spip('inc/ncore_conteneur');
343                        include_spip('inc/ncore_noisette');
344                        $noisettes_conteneur = $noisettes_imbriquees = array();
345                        foreach ($contenu_import['noisettes'] as $_id_noisette_ancien => $_noisette) {
346                                // On vérifie qu'il faut bien importer la noisette
347                                $noisette_a_importer = false;
348                                if ($_noisette['type']) {
349                                        $page_import = $_noisette['composition']
350                                                ? $_noisette['type'] . '-' . $_noisette['composition']
351                                                : $_noisette['type'];
352                                        if (in_array($page_import, $pages_base)) {
353                                                $noisette_a_importer = true;
354                                        }
355                                } else {
356                                        $table_objet = table_objet_sql($_noisette['objet']);
357                                        $id_table_objet = id_table_objet($_noisette['objet']);
358                                        $where = array($id_table_objet. '=' . intval($_noisette['id_objet']));
359                                        if (sql_countsel($table_objet, $where)) {
360                                                $noisette_a_importer = true;
361                                        }
362                                }
363
364                                if ($noisette_a_importer) {
365                                        // La noisette à importer est bien associée à une page ou un objet de la base.
366                                        // Les noisettes ne sont pas triées dans l'ordre d'insertion pour un conteneur donné,
367                                        // il faut donc se baser sur le rang dans le fichier d'import. Pour une noisette appartenant à un
368                                        // conteneur noisette on reprend le rang tel que mais pour une noisette incluse dans un bloc Z il
369                                        // faut recalculer le rang en tenant compte des noisettes déjà incluses dans la base.
370                                        $rang = $_noisette['rang_noisette'];
371                                        $conteneur = unserialize($_noisette['conteneur']);
372                                        $conteneur_est_noisette = conteneur_est_noisette('noizetier', $conteneur);
373                                        if (!$conteneur_est_noisette) {
374                                                $rang_max = !empty($nb_noisettes_base[$_noisette['id_conteneur']])
375                                                        ? $nb_noisettes_base[$_noisette['id_conteneur']]
376                                                        : 0;
377                                                $rang += $rang_max;
378                                        }
379                                        $id_noisette_nouveau = noisette_ajouter(
380                                                'noizetier',
381                                                $_noisette['type_noisette'],
382                                                $conteneur,
383                                                $rang);
384                                        // La noisette a été ajoutée de façon générique (paramètres par défaut). Pour finaliser l'importation
385                                        // il faut aussi mettre à jour les données paramétrables : parametres, encapsulation et css.
386                                        if ($id_noisette_nouveau) {
387                                                $champs_modifiables = array('parametres');
388                                                if ($_noisette['est_conteneur'] != 'oui') {
389                                                        $champs_modifiables = array_merge($champs_modifiables, array('parametres', 'encapsulation', 'css'));
390                                                }
391                                                $modifications = array_intersect_key($_noisette, array_flip($champs_modifiables));
392                                                noisette_parametrer('noizetier', $id_noisette_nouveau, $modifications);
393                                        }
394
395                                        // Pour conclure il faut stocker les informations nécessaires à la passe suivante:
396                                        // - les noisettes imbriquées dans un conteneur noisette et les référence de ce conteneur
397                                        // - la nouvelle valeur de l'id_noisette des noisettes conteneur
398                                        if ($conteneur_est_noisette) {
399                                                // Il faut se rappeler de la noisette car il faudra changer son conteneur (2 champs) lors de la
400                                                // deuxième passe. On stocke
401                                                $noisettes_imbriquees[$id_noisette_nouveau] = array(
402                                                        'type_noisette' => $conteneur['type_noisette'],
403                                                        'id_noisette' => $conteneur['id_noisette']
404                                                );
405                                        }
406                                        if ($_noisette['est_conteneur'] == 'oui') {
407                                                // La noisette est un conteneur. On constitue un tableau permettant de calculer son nouvel
408                                                // identifiant induit par son nouvel id de noisette. Le tableau est indexé par son ancien id.
409                                                $noisettes_conteneur[$_id_noisette_ancien] = $id_noisette_nouveau;
410                                        }
411                                }
412                        }
413
414                        // - Passe 2 : On reprend les noisettes venant d'être insérées dans une noisette conteneur et
415                        //             on rétablit le bon conteneur (id et tableau sérialisé), la profondeur et les informations
416                        //             du bloc Z accueillant les noisettes.
417                        if ($noisettes_imbriquees) {
418                                foreach ($noisettes_imbriquees as $_id_noisette_nouveau => $_conteneur_ancien) {
419                                        // Détermination du conteneur
420                                        $nouveau_conteneur = $_conteneur_ancien;
421                                        $nouveau_conteneur['id_noisette'] = $noisettes_conteneur[$_conteneur_ancien['id_noisette']];
422
423                                        // Détermination de la profondeur et des caractéristiques du bloc Z de plus haut niveau.
424                                        // Le conteneur est une noisette, qui a été insérée précédemment, on la lit.
425                                        $select = array('type', 'composition', 'objet', 'id_objet',     'bloc', 'profondeur');
426                                        $where = array(
427                                                'id_noisette=' . intval($nouveau_conteneur['id_noisette']),
428                                                'plugin=' . sql_quote('noizetier')
429                                        );
430                                        $modifications = sql_fetsel($select, 'spip_noisettes', $where);
431
432                                        // On finalise les modifications
433                                        $modifications['profondeur'] += 1;
434                                        $modifications['conteneur'] = serialize($nouveau_conteneur);
435                                        $modifications['id_conteneur'] = conteneur_identifier('noizetier', $nouveau_conteneur);
436
437                                        // On met à jour le contenu de la noisette en base.
438                                        $where = array('plugin=' . sql_quote('noizetier'), 'id_noisette=' . intval($_id_noisette_nouveau));
439                                        sql_updateq('spip_noisettes', $modifications, $where);
440                                }
441                        }
442                }
443        }
444
445        // On invalide le cache
446        include_spip('inc/invalideur');
447        suivre_invalideur('noizetier-import-config');
448
449        return $retour;
450}
Note: See TracBrowser for help on using the repository browser.