source: spip-zone/_plugins_/n-core/trunk/inc/ncore_noisette.php @ 113630

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

Par cohérence avec le fait de pouvoir compléter la description d'un type de noisette et d'une noisette, il faut proposer des services idoines pour traiter les champs textuels par typo() qui pourraient être spécifiques au plugin appelant. On crée donc type_noisette_traiter_typo() et noisette_traiter_typo().
Les API de lecture des types et noisettes sont donc maintenant finalisées.

  • Property svn:eol-style set to native
File size: 30.8 KB
Line 
1<?php
2/**
3 * Ce fichier contient l'API N-Core de gestion des noisettes, c'est-à-dire les instances paramétrées
4 * de types de noisette affectées à un conteneur.
5 *
6 * @package SPIP\NCORE\NOISETTE\API
7 */
8if (!defined('_ECRIRE_INC_VERSION')) {
9        return;
10}
11
12
13/**
14 * Ajoute dans un conteneur, à un rang donné ou en dernier rang, une noisette d'un type donné.
15 * La fonction met à jour les rangs des autres noisettes si nécessaire.
16 *
17 * @api
18 * @uses type_noisette_lire()
19 * @uses ncore_conteneur_verifier()
20 * @uses ncore_conteneur_identifier()
21 * @uses ncore_conteneur_construire()
22 * @uses ncore_conteneur_est_noisette()
23 * @uses ncore_noisette_decrire()
24 * @uses ncore_noisette_completer()
25 * @uses ncore_noisette_lister()
26 * @uses ncore_noisette_ranger()
27 * @uses ncore_noisette_stocker()
28 *
29 * @param string $plugin
30 *        Identifiant qui permet de distinguer le module appelant qui peut-être un plugin comme le noiZetier ou
31 *        un script. Pour un plugin, le plus pertinent est d'utiliser le préfixe.
32 * @param string $type_noisette
33 *        Identifiant du type de noisette à ajouter au squelette.
34 * @param array  $conteneur
35 *        Identifiant du conteneur accueillant la noisette qui prend soit la forme d'un tableau soit celui d'un id.
36 * @param int    $rang
37 *        Rang dans le conteneur où insérer la noisette. Si l'argument n'est pas fourni ou est égal à 0
38 *        on insère la noisette en fin de conteneur.
39 * @param string $stockage
40 *        Identifiant du service de stockage à utiliser si précisé. Dans ce cas, ni celui du plugin
41 *        ni celui de N-Core ne seront utilisés. En général, cet identifiant est le préfixe d'un plugin
42 *        fournissant le service de stockage souhaité.
43 *
44 * @return int|string|bool
45 *        Retourne l'identifiant de la nouvelle instance de noisette créée ou `false` en cas d'erreur.
46 **/
47function noisette_ajouter($plugin, $type_noisette, $conteneur, $rang = 0, $stockage = '') {
48
49        // Initialisation de la valeur de sortie.
50        $noisette_ajoutee = false;
51
52        if ($type_noisette) {
53                // On récupère les paramètres du type de noisette.
54                include_spip('inc/ncore_type_noisette');
55                $champs = type_noisette_lire(
56                        $plugin,
57                        $type_noisette,
58                        'parametres',
59                        false,
60                        $stockage
61                );
62
63                // Et on leur associe des valeurs par défaut.
64                include_spip('inc/saisies');
65                $parametres = saisies_lister_valeurs_defaut($champs);
66
67                // On charge les services de N-Core.
68                // Ce sont ces fonctions qui aiguillent ou pas vers un service spécifique du plugin.
69                include_spip('ncore/ncore');
70
71                // Suivant que le conteneur est passé au format tableau ou id on complète les deux identifiants
72                $id_conteneur = '';
73                if (is_array($conteneur)) {
74                        // -- Vérification des index du conteneur.
75                        $conteneur = ncore_conteneur_verifier($plugin, $conteneur, $stockage);
76                        // -- Calcul de l'id
77                        if ($conteneur) {
78                                $id_conteneur = ncore_conteneur_identifier($plugin, $conteneur, $stockage);
79                        }
80                } elseif (is_string($conteneur)) {
81                        $id_conteneur = $conteneur;
82                        $conteneur = ncore_conteneur_construire($plugin, $id_conteneur, $stockage);
83                }
84
85                // On initialise la description de la noisette à ajouter et en particulier on stocke le tableau et l'id du
86                // conteneur pour simplifier les traitements par la suite.
87                if ($id_conteneur) {
88                        // -- Initialisation par défaut
89                        $description = array(
90                                'plugin'        => $plugin,
91                                'type_noisette' => $type_noisette,
92                                'conteneur'     => serialize($conteneur),
93                                'id_conteneur'  => $id_conteneur,
94                                'rang_noisette' => intval($rang),
95                                'est_conteneur' => type_noisette_lire($plugin, $type_noisette, 'conteneur', false, $stockage),
96                                'parametres'    => serialize($parametres),
97                                'encapsulation' => 'defaut',
98                                'css'           => '',
99                                'profondeur'    => 0
100                        );
101                        // -- Pour les noisettes conteneur pas de capsule englobante.
102                        if ($description['est_conteneur'] == 'oui') {
103                                $description['encapsulation'] = 'non';
104                        }
105
106                        // -- Pour une noisette incluse dans un conteneur noisette on calcule la profondeur.
107                        if (ncore_conteneur_est_noisette($plugin, $conteneur, $stockage)) {
108                                $description_conteneur = ncore_noisette_decrire($plugin, $conteneur['id_noisette'], $stockage);
109                                $description['profondeur'] = $description_conteneur['profondeur'] + 1;
110                        }
111
112                        // Complément à la description par défaut, spécifique au plugin utilisateur, si nécessaire.
113                        $description = ncore_noisette_completer($plugin, $description, $stockage);
114
115                        // On récupère les noisettes déjà affectées au conteneur sous la forme d'un tableau indexé
116                        // par le rang de chaque noisette.
117                        $noisettes = ncore_noisette_lister($plugin, $id_conteneur, '', 'rang_noisette', $stockage);
118
119                        // On calcule le rang max déjà utilisé.
120                        $rang_max = $noisettes ? max(array_keys($noisettes)) : 0;
121
122                        if (!$rang or ($rang and ($rang > $rang_max))) {
123                                // Si, le rang est nul ou si il est strictement supérieur au rang_max, on positionne la noisette
124                                // à ajouter au rang max + 1.
125                                // En effet, si le rang est supérieur au rang max c'est que la nouvelle noisette est ajoutée
126                                // après les noisettes existantes, donc cela revient à insérer la noisette en fin de liste.
127                                // Postionner le rang à max + 1 permet d'éviter d'avoir des trous dans la liste des rangs.
128                                $description['rang_noisette'] = $rang_max + 1;
129                        } else {
130                                // Si le rang est non nul et inférieur ou égal au rang max c'est qu'on insère la noisette dans la liste
131                                // existante : il faut décaler d'un rang les noisettes de rang supérieur ou égal si elle existent pour
132                                // libérer la position de la nouvelle noisette.
133                                if ($rang <= $rang_max) {
134                                        krsort($noisettes);
135                                        foreach ($noisettes as $_rang => $_description) {
136                                                if ($_rang >= $rang) {
137                                                        ncore_noisette_ranger($plugin, $_description, $_rang + 1, $stockage);
138                                                }
139                                        }
140                                }
141                        }
142
143                        // La description de la nouvelle noisette est prête à être stockée à sa position.
144                        $noisette_ajoutee = ncore_noisette_stocker($plugin, $description, $stockage);
145                }
146        }
147
148        return $noisette_ajoutee;
149}
150
151/**
152 * Met à jour les paramètres éditables d'une noisette donnée.
153 * La fonction contrôle la liste des champs modifiables.
154 *
155 * @api
156 * @uses ncore_noisette_decrire()
157 * @uses ncore_noisette_stocker()
158 *
159 * @param string $plugin
160 *        Identifiant qui permet de distinguer le module appelant qui peut-être un plugin comme le noiZetier ou
161 *        un script. Pour un plugin, le plus pertinent est d'utiliser le préfixe.
162 * @param mixed  $noisette
163 *        Identifiant de la noisette qui peut prendre soit la forme d'un entier ou d'une chaine unique, soit la forme
164 *        d'un couple (id conteneur, rang).
165 * @param array  $modifications
166 *        Tableau des couples (champ, valeur) à mettre à jour pour la noisette spécifiée.
167 *        La fonction contrôle la liste des champs éditables en filtrant les champs standard comme `parametres`,
168 *        `balise`, `css` et éventuellement ceux spécifiquement définis par le plugin utilisateur dans
169 *        l'argument $editables_specifiques.
170 * @param array  $editables_specifiques
171 *        Liste de champs éditables spécifiques au plugin utilisateur ou tableau vide sinon. Le tableau possède deux
172 *        index, l'un pour les noisettes conteneur `conteneur`, l'autre pour les noisettes non conteneur `non_conteneur`.
173 * @param string $stockage
174 *        Identifiant du service de stockage à utiliser si précisé. Dans ce cas, ni celui du plugin
175 *        ni celui de N-Core ne seront utilisés. En général, cet identifiant est le préfixe d'un plugin
176 *        fournissant le service de stockage souhaité.
177 *
178 * @return bool
179 */
180function noisette_parametrer($plugin, $noisette, $modifications, $editables_specifiques = array(), $stockage = '') {
181
182        // Initialisation du retour
183        $noisette_parametree = false;
184
185        // On charge les services de N-Core.
186        // Ce sont ces fonctions qui aiguillent ou pas vers un service spécifique du plugin.
187        include_spip('ncore/ncore');
188
189        // L'identifiant d'une noisette peut être fourni de deux façons :
190        // - par une valeur unique, celle créée lors de l'ajout et qui peut-être un entier (id d'une table SPIP) ou
191        //   une chaine unique par exemple générée par uniqid().
192        // - ou par un tableau à deux entrées fournissant le conteneur et le rang dans le conteneur
193        //   (qui est unique pour un conteneur donné).
194        if (!empty($noisette) and (is_string($noisette) or is_numeric($noisette) or is_array($noisette))) {
195                // On récupère la description complète de la noisette avant de modifier les champs éditables spécifiés.
196                $description = ncore_noisette_decrire($plugin, $noisette, $stockage);
197
198                // On contrôle les champs éditables et on met à jour la description de la noisette.
199                // Pour une noisette conteneur les champs encapsulation et css ne sont pas éditables
200                if ($description['est_conteneur'] == 'oui') {
201                        $parametres = array_merge(
202                                array('parametres'),
203                                (isset($editables_specifiques['conteneur']) ? $editables_specifiques['conteneur'] : array())
204                        );
205                } else {
206                        $parametres = array_merge(
207                                array('parametres', 'encapsulation', 'css'),
208                                (isset($editables_specifiques['non_conteneur']) ? $editables_specifiques['non_conteneur'] : array())
209                        );
210                }
211                $modifications = array_intersect_key($modifications, array_flip($parametres));
212                $description = array_merge($description, $modifications);
213
214                // La description est prête à être stockée en remplacement de l'existante.
215                if (ncore_noisette_stocker($plugin, $description, $stockage)) {
216                        $noisette_parametree = true;
217                }
218        }
219
220        return $noisette_parametree;
221}
222
223/**
224 * Supprime une noisette donnée du conteneur auquel elle est associée et, si cette noisette est un conteneur,
225 * le vide de ses noisettes au préalable.
226 * La fonction met à jour les rangs des autres noisettes si nécessaire.
227 *
228 * @api
229 * @uses ncore_noisette_decrire()
230 * @uses ncore_noisette_destocker()
231 * @uses ncore_noisette_lister()
232 * @uses ncore_noisette_ranger()
233 *
234 * @param string $plugin
235 *        Identifiant qui permet de distinguer le module appelant qui peut-être un plugin comme le noiZetier ou
236 *        un script. Pour un plugin, le plus pertinent est d'utiliser le préfixe.
237 * @param mixed  $noisette
238 *        Identifiant de la noisette qui peut prendre soit la forme d'un entier ou d'une chaine unique, soit la forme
239 *        d'un couple (id conteneur, rang).
240 * @param string $stockage
241 *        Identifiant du service de stockage à utiliser si précisé. Dans ce cas, ni celui du plugin
242 *        ni celui de N-Core ne seront utilisés. En général, cet identifiant est le préfixe d'un plugin
243 *        fournissant le service de stockage souhaité.
244 *
245 * @return bool
246 */
247function noisette_supprimer($plugin, $noisette, $stockage = '') {
248
249        // Initialisation du retour
250        $noisette_supprimee = false;
251
252        // On charge les services de N-Core.
253        // Ce sont ces fonctions qui aiguillent ou pas vers un service spécifique du plugin.
254        include_spip('ncore/ncore');
255
256        // L'identifiant d'une noisette peut être fourni de deux façons :
257        // - par une valeur unique, celle créée lors de l'ajout et qui peut-être un entier (id d'une table SPIP) ou
258        //   une chaine unique par exemple générée par uniqid().
259        // - ou par un tableau à deux entrées fournissant le conteneur et le rang dans le conteneur
260        //   (qui est unique pour un conteneur donné).
261        if (!empty($noisette) and (is_string($noisette) or is_numeric($noisette) or is_array($noisette))) {
262                // Avant de supprimer la noisette on sauvegarde sa description.
263                // Cela permet de conserver le rang et l'id du conteneur indépendamment de l'identifiant
264                // utilisé pour spécifier la noisette.
265                $description = ncore_noisette_decrire($plugin, $noisette, $stockage);
266
267                // Si la noisette est de type conteneur, il faut d'abord vider le conteneur qu'elle représente
268                // et ce de façon récursive. La récursivité est gérée par la fonction de service ncore_conteneur_destocker().
269                $conteneur_destocke = true;
270                if ($description['est_conteneur'] == 'oui') {
271                        // Inutile de redéfinir un conteneur car la description de la noisette contient les deux champs
272                        // essentiels, à savoir, type_noisette et id_noisette.
273                        $conteneur_destocke = ncore_conteneur_destocker($plugin, $description, $stockage);
274                }
275
276                // Suppression de la noisette. On passe la description complète ce qui permet à la fonction de
277                // destockage de choisir la méthode d'identification la plus adaptée.
278                if ($conteneur_destocke and ncore_noisette_destocker($plugin, $description, $stockage)) {
279                        // On récupère les noisettes restant affectées au conteneur sous la forme d'un tableau indexé par rang.
280                        $autres_noisettes = ncore_noisette_lister(
281                                $plugin,
282                                $description['id_conteneur'],
283                                '',
284                                'rang_noisette',
285                                $stockage
286                        );
287
288                        // Si il reste des noisettes, on tasse d'un rang les noisettes qui suivaient la noisette supprimée.
289                        if ($autres_noisettes) {
290                                // On lit les noisettes restantes dans l'ordre décroissant pour éviter d'écraser une noisette.
291                                ksort($autres_noisettes);
292                                foreach ($autres_noisettes as $_rang => $_autre_description) {
293                                        if ($_rang > $description['rang_noisette']) {
294                                                ncore_noisette_ranger($plugin, $_autre_description, $_autre_description['rang_noisette'] - 1, $stockage);
295                                        }
296                                }
297                        }
298
299                        $noisette_supprimee = true;
300                }
301        }
302
303        return $noisette_supprimee;
304}
305
306/**
307 * Retourne, pour une noisette donnée, la description complète ou seulement un champ précis.
308 * Les champs textuels peuvent subir un traitement typo si demandé.
309 *
310 * @api
311 * @uses ncore_noisette_decrire()
312 *
313 * @param string  $plugin
314 *        Identifiant qui permet de distinguer le module appelant qui peut-être un plugin comme le noiZetier ou
315 *        un script. Pour un plugin, le plus pertinent est d'utiliser le préfixe.
316 * @param mixed   $noisette
317 *        Identifiant de la noisette qui peut prendre soit la forme d'un entier ou d'une chaine unique, soit la forme
318 *        d'un couple (id conteneur, rang).
319 * @param string  $information
320 *        Information spécifique à retourner ou vide pour retourner toute la description.
321 * @param boolean $traiter_typo
322 *        Indique si les données textuelles doivent être retournées brutes ou si elles doivent être traitées
323 *        en utilisant la fonction typo. Par défaut l'indicateur vaut `false`.
324 *        Les champs sérialisés sont eux toujours désérialisés.
325 *        Pour l'instant il n'y a pas de champ textuel directement associé à une noisette.
326 * @param string  $stockage
327 *        Identifiant du service de stockage à utiliser si précisé. Dans ce cas, ni celui du plugin
328 *        ni celui de N-Core ne seront utilisés. En général, cet identifiant est le préfixe d'un plugin
329 *        fournissant le service de stockage souhaité.
330 *
331 * @return array|string|int
332 *        La description complète ou champ précis demandé pour une noisette donnée. Les champs
333 *        de type tableau sont systématiquement désérialisés et si demandé, les champs textuels peuvent être
334 *        traités avec la fonction typo().
335 */
336function noisette_lire($plugin, $noisette, $information = '', $traiter_typo = false, $stockage = '') {
337
338        // On indexe le tableau des descriptions par le plugin appelant en cas d'appel sur le même hit
339        // par deux plugins différents.
340        // En outre, on gère un tableau par type d'identification, id noisette ou couple (id conteneur, rang).
341        static $description_noisette_par_id = array();
342        static $description_noisette_par_rang = array();
343
344        // Initialisation de la description en sortie.
345        $noisette_lue = array();
346
347        if (!empty($noisette) and (is_string($noisette) or is_numeric($noisette) or is_array($noisette))) {
348                // On charge les services de N-Core.
349                // Ce sont ces fonctions qui aiguillent ou pas vers un service spécifique du plugin.
350                include_spip('ncore/ncore');
351
352                // On vérifie si la noisette est valide et si la description n'a pas déjà été enregistrée dans le tableau adéquat.
353                $description_existe = false;
354                $noisette_invalide = false;
355                if (!is_array($noisette)) {
356                        $description_existe = isset($description_noisette_par_id[$plugin][$traiter_typo][$noisette]) ? true : false;
357                } elseif (isset($noisette['id_conteneur'], $noisette['rang_noisette'])) {
358                        $description_existe = isset($description_noisette_par_rang[$plugin][$traiter_typo][$noisette['id_conteneur']][$noisette['rang_noisette']])
359                                ? true
360                                : false;
361                } else {
362                        $noisette_invalide = true;
363                }
364
365                if (!$noisette_invalide) {
366                        if (!$description_existe) {
367                                // Lecture de toute la configuration de la noisette: les données retournées sont brutes.
368                                $description = ncore_noisette_decrire($plugin, $noisette, $stockage);
369
370                                if ($description) {
371                                        // Traitements des champs textuels : aucun champ textuel à traiter dans la description par défaut.
372                                        if ($traiter_typo) {
373                                                $description = ncore_noisette_traiter_typo($plugin, $description, $stockage);
374                                        }
375
376                                        // Traitements des champs tableaux sérialisés si nécessaire
377                                        $description['parametres'] = unserialize($description['parametres']);
378                                        $description['conteneur'] = unserialize($description['conteneur']);
379                                }
380
381                                // Sauvegarde de la description de la noisette pour une consultation ultérieure dans le même hit
382                                // en suivant le type d'identification.
383                                if (!is_array($noisette)) {
384                                        $description_noisette_par_id[$plugin][$traiter_typo][$noisette] = $description;
385                                } else {
386                                        $description_noisette_par_rang[$plugin][$traiter_typo][$noisette['id_conteneur']][$noisette['rang_noisette']] = $description;
387                                }
388                        }
389
390                        if ($information) {
391                                if ((!is_array($noisette) and isset($description_noisette_par_id[$plugin][$traiter_typo][$noisette][$information]))
392                                        or (is_array($noisette)
393                                                and isset($description_noisette_par_rang[$plugin][$traiter_typo][$noisette['id_conteneur']][$noisette['rang_noisette']][$information]))) {
394                                        $noisette_lue = is_array($noisette)
395                                                ? $description_noisette_par_rang[$plugin][$traiter_typo][$noisette['id_conteneur']][$noisette['rang_noisette']][$information]
396                                                : $description_noisette_par_id[$plugin][$traiter_typo][$noisette][$information];
397                                } else {
398                                        $noisette_lue = '';
399                                }
400                        } else {
401                                $noisette_lue = is_array($noisette)
402                                        ? $description_noisette_par_rang[$plugin][$traiter_typo][$noisette['id_conteneur']][$noisette['rang_noisette']]
403                                        : $description_noisette_par_id[$plugin][$traiter_typo][$noisette];
404                        }
405                }
406        }
407
408        return $noisette_lue;
409}
410
411/**
412 * Déplace une noisette donnée au sein d’un même conteneur ou dans un autre conteneur.
413 * La fonction met à jour les rangs des autres noisettes si nécessaire.
414 *
415 * @api
416 *
417 * @uses ncore_noisette_decrire()
418 * @uses ncore_conteneur_verifier()
419 * @uses ncore_conteneur_identifier()
420 * @uses ncore_noisette_lister()
421 * @uses ncore_conteneur_construire()
422 * @uses ncore_conteneur_est_noisette()
423 * @uses ncore_noisette_changer_conteneur()
424 * @uses ncore_noisette_ranger()
425 *
426 * @param string       $plugin
427 *        Identifiant qui permet de distinguer le module appelant qui peut-être un plugin comme le noiZetier ou
428 *        un script. Pour un plugin, le plus pertinent est d'utiliser le préfixe.
429 * @param mixed        $noisette
430 *        Identifiant de la noisette qui peut prendre soit la forme d'un entier ou d'une chaine unique, soit la forme
431 *        d'un couple (id conteneur, rang).
432 * @param array|string $conteneur_destination
433 *        Identifiant du conteneur destination qui prend soit la forme d'un tableau soit celui d'un id.
434 * @param int          $rang_destination
435 *        Entier représentant le rang où repositionner la noisette dans le squelette contextualisé.
436 * @param string       $stockage
437 *        Identifiant du service de stockage à utiliser si précisé.
438 *
439 * @return bool
440 *         Renvoie `false` si la noisette n'est pas déplacée à cause d'une erreur de traitement ou parce que le
441 *         rang destination est identique au rang origine, sinon `true`.
442 */
443function noisette_deplacer($plugin, $noisette, $conteneur_destination, $rang_destination, $stockage = '') {
444
445        // Initialisation du retour
446        $noisette_deplacee = false;
447
448        // On charge les services de N-Core.
449        // Ce sont ces fonctions qui aiguillent ou pas vers un service spécifique du plugin.
450        include_spip('ncore/ncore');
451
452        // L'identifiant d'une noisette peut être fourni de deux façons :
453        // - par une valeur unique, celle créée lors de l'ajout et qui peut-être un entier (id d'une table SPIP) ou
454        //   une chaine unique par exemple générée par uniqid().
455        // - ou par un tableau à deux entrées fournissant le conteneur et le rang
456        //   (qui est unique pour un conteneur donné).
457        if (!empty($noisette) and (is_string($noisette) or is_numeric($noisette) or is_array($noisette))) {
458                // Avant de déplacer la noisette on sauvegarde sa description, son id conteneur et son rang.
459                $description = ncore_noisette_decrire($plugin, $noisette, $stockage);
460                $id_conteneur_origine = $description['id_conteneur'];
461                $rang_origine = $description['rang_noisette'];
462
463                // On détermine l'id du conteneur destination en fonction du mode d'identification fourni par l'argument.
464                $id_conteneur_destination = '';
465                if (is_array($conteneur_destination)) {
466                        // -- Vérification des index du conteneur.
467                        $conteneur_destination = ncore_conteneur_verifier($plugin, $conteneur_destination, $stockage);
468                        // -- Calcul de l'id
469                        if ($conteneur_destination) {
470                                $id_conteneur_destination = ncore_conteneur_identifier(
471                                        $plugin,
472                                        $conteneur_destination,
473                                        $stockage
474                                );
475                        }
476                } elseif (is_string($conteneur_destination)) {
477                        $id_conteneur_destination = $conteneur_destination;
478                }
479
480                // Si le conteneur destination est différent du conteneur origine, la première opération consiste à
481                // transférer la noisette en fin du conteneur destination, ce qui est toujours possible.
482                // Ensuite on tasse le conteneur d'origine.
483                if ($id_conteneur_destination) {
484                        if ($id_conteneur_destination != $id_conteneur_origine) {
485                                // On recherche le dernier rang utilisé dans le conteneur destination et on se positionne après.
486                                $rangs = ncore_noisette_lister(
487                                        $plugin,
488                                        $id_conteneur_destination,
489                                        'rang_noisette',
490                                        'id_noisette',
491                                        $stockage
492                                );
493                                $rang_conteneur_destination = $rangs ? max($rangs) + 1 : 1;
494
495                                // Pour éviter que chaque plugin ait à gérer la profondeur, N-Core calcule la profondeur de la noisette à son
496                                // nouvel emplacement avant de déplacer celle-ci et la fournit à la fonction de changement de conteneur.
497                                if (!is_array($conteneur_destination)) {
498                                        $conteneur_destination = ncore_conteneur_construire($plugin, $id_conteneur_destination, $stockage);
499                                }
500                                if (ncore_conteneur_est_noisette($plugin, $conteneur_destination, $stockage)) {
501                                        $description_conteneur = ncore_noisette_decrire($plugin, $conteneur_destination['id_noisette'], $stockage);
502                                        $profondeur_destination = $description_conteneur['profondeur'] + 1;
503                                } else {
504                                        $profondeur_destination = 0;
505                                }
506
507                                // On transfère la noisette vers le conteneur destination à la position calculée (max + 1).
508                                $description = ncore_noisette_changer_conteneur(
509                                        $plugin,
510                                        $description,
511                                        $id_conteneur_destination,
512                                        $rang_conteneur_destination,
513                                        $profondeur_destination,
514                                        $stockage
515                                );
516
517                                // Il faut maintenant tasser les noisettes du conteneur d'origine qui a perdu une noisette.
518                                // -- On récupère les noisettes restant affectées au conteneur origine sous la forme d'un tableau
519                                //    indexé par rang.
520                                $autres_noisettes = ncore_noisette_lister(
521                                        $plugin,
522                                        $id_conteneur_origine,
523                                        '',
524                                        'rang_noisette',
525                                        $stockage
526                                );
527
528                                // Si il reste des noisettes, on tasse d'un rang les noisettes qui suivaient la noisette supprimée.
529                                if ($autres_noisettes) {
530                                        // On lit les noisettes restantes dans l'ordre décroissant pour éviter d'écraser une noisette.
531                                        ksort($autres_noisettes);
532                                        foreach ($autres_noisettes as $_rang => $_autre_description) {
533                                                if ($_rang > $rang_origine) {
534                                                        ncore_noisette_ranger($plugin, $_autre_description, $_autre_description['rang_noisette'] - 1, $stockage);
535                                                }
536                                        }
537                                }
538
539                                // Le rang origine devient donc le nouveau rang de la noisette dans le conteneur destination.
540                                $rang_origine = $description['rang_noisette'];
541                        }
542
543                        // A partir de là, le déplacement est un déplacement à l'intérieur d'un conteneur.
544                        // Si les rangs origine et destination sont identiques on ne fait rien !
545                        if ($rang_destination != $rang_origine) {
546                                // On récupère les noisettes affectées au même conteneur sous la forme d'un tableau indexé par le rang.
547                                $noisettes = ncore_noisette_lister(
548                                        $plugin,
549                                        $description['id_conteneur'],
550                                        '',
551                                        'rang_noisette',
552                                        $stockage
553                                );
554
555                                // On vérifie que le rang destination est bien compris entre 1 et le rang max, sinon on le force à l'une
556                                // des bornes.
557                                $rang_destination = max(1, $rang_destination);
558                                $rang_max = $noisettes ? max(array_keys($noisettes)) : 0;
559                                $rang_destination = min($rang_max, $rang_destination);
560
561                                // Suivant la position d'origine et de destination de la noisette déplacée on trie les noisettes
562                                // du conteneur.
563                                if ($rang_destination < $rang_origine) {
564                                        krsort($noisettes);
565                                } else {
566                                        ksort($noisettes);
567                                }
568
569                                // On déplace les noisettes impactées à l'exception de la noisette concernée par le déplacement
570                                // afin de créer une position libre.
571                                foreach ($noisettes as $_rang => $_description) {
572                                        if ($rang_destination < $rang_origine) {
573                                                // On "descend" les noisettes du rang destination au rang origine non compris.
574                                                if (($_rang >= $rang_destination) and ($_rang < $rang_origine)) {
575                                                        ncore_noisette_ranger($plugin, $_description, $_rang + 1, $stockage);
576                                                }
577                                        } else {
578                                                // On "remonte" les noisettes du rang destination au rang origine non compris.
579                                                if (($_rang <= $rang_destination) and ($_rang > $rang_origine)) {
580                                                        ncore_noisette_ranger($plugin, $_description, $_rang - 1, $stockage);
581                                                }
582                                        }
583                                }
584
585                                // On positionne le rang de la noisette à déplacer au rang destination.
586                                // On met le rang à zéro pour indiquer que l'emplacement d'origine n'est plus occupé par la
587                                // noisette et qu'il ne faut pas le supprimer lors du rangement.
588                                $description['rang_noisette'] = 0;
589                                if (ncore_noisette_ranger($plugin, $description, $rang_destination, $stockage)) {
590                                        $noisette_deplacee = true;
591                                }
592                        }
593                }
594        }
595
596        return $noisette_deplacee;
597}
598
599/**
600 * Duplique une noisette donnée dans un conteneur destination et, si cette noisette est un conteneur, duplique aussi
601 * les noisettes contenues de façon récursive.
602 *
603 * @api
604 * @uses ncore_noisette_decrire()
605 * @uses noisette_ajouter()
606 * @uses noisette_parametrer()
607 * @uses ncore_noisette_lister()
608 * @uses noisette_dupliquer()
609 *
610 * @param string       $plugin
611 *        Identifiant qui permet de distinguer le module appelant qui peut-être un plugin comme le noiZetier ou
612 *        un script. Pour un plugin, le plus pertinent est d'utiliser le préfixe.
613 * @param mixed        $noisette
614 *        Identifiant de la noisette qui peut prendre soit la forme d'un entier ou d'une chaine unique, soit la forme
615 *        d'un couple (id conteneur, rang).
616 * @param array|string $conteneur
617 *        Identifiant du conteneur destination qui prend soit la forme d'un tableau soit celui d'un id.
618 * @param int    $rang
619 *        Rang dans le conteneur destination où insérer la noisette dupliquée. Si l'argument n'est pas fourni ou
620 *        est égal à 0 on insère la noisette en fin de conteneur.
621 * @param array        $parametrage
622 *        Tableau indiquant les champs éditables de la noisette source à copier dans la noisette dupliquée.
623 * @param string       $stockage
624 *        Identifiant du service de stockage à utiliser si précisé. Dans ce cas, ni celui du plugin
625 *        ni celui de N-Core ne seront utilisés. En général, cet identifiant est le préfixe d'un plugin
626 *        fournissant le service de stockage souhaité.
627 *
628 * @return bool
629 */
630function noisette_dupliquer($plugin, $noisette, $conteneur, $rang = 0, $parametrage = array(), $stockage = '') {
631
632        // Initialisation du retour
633        $noisette_dupliquee = false;
634
635        // On charge les services de N-Core.
636        // Ce sont ces fonctions qui aiguillent ou pas vers un service spécifique du plugin.
637        include_spip('ncore/ncore');
638
639        // L'identifiant d'une noisette peut être fourni de deux façons :
640        // - par une valeur unique, celle créée lors de l'ajout et qui peut-être un entier (id d'une table SPIP) ou
641        //   une chaine unique par exemple générée par uniqid().
642        // - ou par un tableau à deux entrées fournissant le conteneur et le rang dans le conteneur
643        //   (qui est unique pour un conteneur donné).
644        if (!empty($noisette) and (is_string($noisette) or is_numeric($noisette) or is_array($noisette))) {
645                // Avant de dupliquer la noisette on sauvegarde sa description car il faudra utiliser ses paramètres
646                // d'affichage, d'encapsulation et de style pour la duplication.
647                $description = ncore_noisette_decrire($plugin, $noisette, $stockage);
648
649                // On ajoute la noisette à la fin du conteneur destination : la noisette est créée par défaut.
650                if ($id_noisette = noisette_ajouter($plugin, $description['type_noisette'], $conteneur, $rang, $stockage)) {
651                        // Suivant le paramétrage demandé on copie les champs idoines de la noisette source.
652                        if ($parametrage) {
653                                $modifications = array();
654                                foreach ($parametrage as $_champ) {
655                                        if (($description['est_conteneur'] == 'non')
656                                        or (($description['est_conteneur'] == 'oui') and (($_champ == 'encapsulation') or ($_champ == 'css')))) {
657                                                $modifications[$_champ] = $description[$_champ];
658                                        }
659                                }
660
661                                if ($modifications) {
662                                        noisette_parametrer($plugin, $id_noisette, $modifications, array(), $stockage);
663                                }
664                        }
665
666                        // Si la noisette est de type conteneur, il faut aussi dupliquer les noisettes éventuellement contenues
667                        // et ce de façon récursive.
668                        if ($description['est_conteneur'] == 'oui') {
669                                // On récupère les noisettes incluses dans la noisette origine qui est un conteneur.
670                                $autres_noisettes = ncore_noisette_lister(
671                                        $plugin,
672                                        array('type_noisette' => $description['type_noisette'], 'id_noisette' => $description['id_noisette']),
673                                        '',
674                                        'rang_noisette',
675                                        $stockage
676                                );
677
678                                // Si il reste des noisettes, on tasse d'un rang les noisettes qui suivaient la noisette supprimée.
679                                if ($autres_noisettes) {
680                                        // On calcule l'id conteneur de la noisette conteneur venant d'être dupliquée pour y dupliquer les
681                                        // noisettes incluses.
682                                        $conteneur_noisette_dupliquee = array(
683                                                'type_noisette' => $description['type_noisette'],
684                                                'id_noisette' => $id_noisette
685                                        );
686
687                                        // On lit les noisettes incluses et on appelle la fonction dupliquer récursivement.
688                                        ksort($autres_noisettes);
689                                        foreach ($autres_noisettes as $_rang => $_autre_description) {
690                                                noisette_dupliquer(
691                                                        $plugin,
692                                                        $_autre_description['id_noisette'],
693                                                        $conteneur_noisette_dupliquee,
694                                                        $parametrage,
695                                                        $stockage
696                                                );
697                                        }
698                                }
699                        }
700
701                        $noisette_dupliquee = true;
702                }
703        }
704
705        return $noisette_dupliquee;
706}
Note: See TracBrowser for help on using the repository browser.