source: spip-zone/_plugins_/n-core/trunk/ncore/ncore.php @ 113529

Last change on this file since 113529 was 113529, checked in by root, 4 months ago

Mise à jour des tags @uses du phpdoc

  • Property svn:eol-style set to native
File size: 50.0 KB
Line 
1<?php
2/**
3 * Ce fichier contient les fonctions du service de stockage N-Core pour les types de noisettes et les noisettes.
4 *
5 * Chaque fonction, soit aiguille, si elle existe, vers une fonction "homonyme" propre au plugin appelant
6 * ou à un autre service de stockage, soit déroule sa propre implémentation.
7 * Ainsi, les plugins externes peuvent, si elle leur convient, utiliser l'implémentation proposée par N-Core
8 * en codant un minimum de fonctions, à savoir, `conteneur_identifier` et `conteneur_verifier`.
9 */
10if (!defined('_ECRIRE_INC_VERSION')) {
11        return;
12}
13
14
15// -----------------------------------------------------------------------
16// ------------------------- TYPES DE NOISETTE ---------------------------
17// -----------------------------------------------------------------------
18
19/**
20 * Stocke les descriptions des types de noisette en distinguant les types de noisette obsolètes, les types de
21 * noisettes modifiés et les types de noisettes nouveaux.
22 * Chaque description de type de noisette est un tableau associatif dont tous les index possibles - y compris
23 * la signature - sont initialisés quelque soit le contenu du fichier YAML.
24 *
25 * Le service N-Core stocke les descriptions dans un cache et les signatures dans un autre.
26 *
27 * @package SPIP\NCORE\TYPE_NOISETTE\SERVICE
28 *
29 * @uses ncore_chercher_service()
30 * @uses cache_lire()
31 * @uses cache_ecrire()
32 *
33 * @param string $plugin
34 *        Identifiant qui permet de distinguer le module appelant qui peut-être un plugin comme le noiZetier ou
35 *        un script. Pour un plugin, le plus pertinent est d'utiliser le préfixe.
36 * @param array  $types_noisette
37 *        Tableau associatif à 3 entrées fournissant les descriptions des types de noisettes nouveaux, obsolètes
38 *        et modifiés:
39 *        `a_effacer` : liste des identifiants de type de noisette devenus obsolètes.
40 *        `a_changer` : liste des descriptions des types de noisette dont le fichier YAML a été modifié.
41 *        `a_ajouter` : liste des descriptions des nouveaux types de noisette.
42 *        Si $recharger est à `true`, seul l'index `nouvelles` est fourni dans le tableau $types_noisette.
43 * @param bool   $recharger
44 *        Indique si le chargement en cours est forcé ou pas. Cela permet à la fonction N-Core ou au service
45 *        concerné d'optimiser le traitement sachant que seules les types de noisette nouveaux sont fournis.
46 * @param string $stockage
47 *        Identifiant du service de stockage à utiliser si précisé.
48 *
49 * @return bool
50 *        `true` si le traitement s'est bien déroulé, `false` sinon.
51 */
52function ncore_type_noisette_stocker($plugin, $types_noisette, $recharger, $stockage = '') {
53
54        // On cherche le service de stockage à utiliser selon la logique suivante :
55        // - si le service de stockage est non vide on l'utilise en considérant que la fonction existe forcément;
56        // - sinon, on utilise la fonction du plugin appelant si elle existe;
57        // - et sinon, on utilise la fonction de N-Core.
58        include_spip('inc/ncore_utils');
59        if ($stocker = ncore_chercher_service($plugin, 'type_noisette_stocker', $stockage)) {
60                // On passe le plugin appelant à la fonction car cela permet ainsi de mutualiser les services de stockage.
61                $retour = $stocker($plugin, $types_noisette, $recharger);
62        } else {
63                // Le plugin ne propose pas de fonction propre ou le stockage N-Core est explicitement demandé.
64                // Les descriptions de types de noisette et les signatures sont stockés dans deux caches distincts.
65                // -- Les descriptions : on conserve la signature pour chaque description, le tableau est réindexé avec l'identifiant
66                //    de la noisette.
67                // -- Les signatures : on isole la liste des signatures et on indexe le tableau avec l'identifiant de la noisette.
68
69                // Initialisation de la sortie.
70                $retour = true;
71
72                include_spip('inc/ncore_cache');
73                if ($recharger) {
74                        // Si le rechargement est forcé, tous les types de noisette sont nouveaux, on peut donc écraser les caches
75                        // existants sans s'en préoccuper.
76                        $descriptions = array_column($types_noisette['a_ajouter'], null, 'type_noisette');
77                        cache_ecrire($plugin, _NCORE_NOMCACHE_TYPE_NOISETTE_DESCRIPTION, $descriptions);
78
79                        $signatures = array_column($types_noisette['a_ajouter'], 'signature', 'type_noisette');
80                        cache_ecrire($plugin, _NCORE_NOMCACHE_TYPE_NOISETTE_SIGNATURE, $signatures);
81                } else {
82                        // On lit les cache existants et on applique les modifications.
83                        $descriptions = cache_lire($plugin, _NCORE_NOMCACHE_TYPE_NOISETTE_DESCRIPTION);
84                        $signatures = cache_lire($plugin, _NCORE_NOMCACHE_TYPE_NOISETTE_SIGNATURE);
85
86                        // On supprime les noisettes obsolètes
87                        if (!empty($types_noisette['a_effacer'])) {
88                                $descriptions_obsoletes = array_column($types_noisette['a_effacer'], null, 'type_noisette');
89                                $descriptions = array_diff($descriptions, $descriptions_obsoletes);
90
91                                $signatures_obsoletes = array_column($types_noisette['a_effacer'], 'signature', 'type_noisette');
92                                $signatures = array_diff($signatures, $signatures_obsoletes);
93                        }
94
95                        // On remplace les noisettes modifiées et on ajoute les noisettes nouvelles. Cette opération peut-être
96                        // réalisée en une action avec la fonction array_merge.
97                        if (!empty($types_noisette['a_changer']) or !empty($types_noisette['a_ajouter'])) {
98                                $descriptions_modifiees = array_column($types_noisette['a_changer'], null, 'type_noisette');
99                                $descriptions_nouvelles = array_column($types_noisette['a_ajouter'], null, 'type_noisette');
100                                $descriptions = array_merge($descriptions, $descriptions_modifiees, $descriptions_nouvelles);
101
102                                $signatures_modifiees = array_column($types_noisette['a_changer'], 'signature', 'type_noisette');
103                                $signatures_nouvelles = array_column($types_noisette['a_ajouter'], 'signature', 'type_noisette');
104                                $signatures = array_merge($signatures, $signatures_modifiees, $signatures_nouvelles);
105                        }
106
107                        // On recrée les caches.
108                        cache_ecrire($plugin, _NCORE_NOMCACHE_TYPE_NOISETTE_DESCRIPTION, $descriptions);
109                        cache_ecrire($plugin, _NCORE_NOMCACHE_TYPE_NOISETTE_SIGNATURE, $signatures);
110                }
111        }
112
113        return $retour;
114}
115
116/**
117 * Complète la description d'un type de noisette issue de la lecture de son fichier YAML.
118 *
119 * Le plugin N-Core ne complète pas les types de noisette.
120 *
121 * @package SPIP\NCORE\TYPE_NOISETTE\SERVICE
122 *
123 * @uses ncore_chercher_service()
124 *
125 * @param string $plugin
126 *        Identifiant qui permet de distinguer le module appelant qui peut-être un plugin comme le noiZetier ou
127 *        un script. Pour un plugin, le plus pertinent est d'utiliser le préfixe.
128 * @param array  $description
129 *        Description du type de noisette issue de la lecture du fichier YAML. Suivant le plugin utilisateur elle
130 *        nécessite d'être compléter avant son stockage.
131 * @param string $stockage
132 *        Identifiant du service de stockage à utiliser si précisé.
133 *
134 * @return array
135 *        Description du type de noisette éventuellement complétée par le plugin utilisateur.
136 */
137function ncore_type_noisette_completer($plugin, $description, $stockage = '') {
138
139        $description_complete = $description;
140
141        // On cherche le service de stockage à utiliser selon la logique suivante :
142        // - si le service de stockage est non vide on l'utilise en considérant que la fonction existe forcément;
143        // - sinon, on utilise la fonction du plugin appelant si elle existe;
144        // - et sinon, on utilise la fonction de N-Core.
145        include_spip('inc/ncore_utils');
146        if ($completer = ncore_chercher_service($plugin, 'type_noisette_completer', $stockage)) {
147                // On passe le plugin appelant à la fonction car cela permet ainsi de mutualiser les services de stockage.
148                $description_complete = $completer($plugin, $description);
149        }
150
151        return $description_complete;
152}
153
154/**
155 * Renvoie la description brute d'un type de noisette sans traitement typo ni désérialisation des champs de type
156 * tableau sérialisé.
157 *
158 * Le service N-Core lit la description du type de noisette concerné dans le cache des descriptions.
159 *
160 * @package SPIP\NCORE\TYPE_NOISETTE\SERVICE
161 *
162 * @uses ncore_chercher_service()
163 * @uses cache_lire()
164 *
165 * @param string $plugin
166 *        Identifiant qui permet de distinguer le module appelant qui peut-être un plugin comme le noiZetier ou
167 *        un script. Pour un plugin, le plus pertinent est d'utiliser le préfixe.
168 * @param string $type_noisette
169 *        Identifiant du type de noisette.
170 * @param string $stockage
171 *        Identifiant du service de stockage à utiliser si précisé.
172 *
173 * @return array
174 *        Tableau de la description du type de noisette. Les champs textuels et les champs de type tableau sérialisé
175 *        sont retournés en l'état.
176 */
177function ncore_type_noisette_decrire($plugin, $type_noisette, $stockage = '') {
178
179        // On cherche le service de stockage à utiliser selon la logique suivante :
180        // - si le service de stockage est non vide on l'utilise en considérant que la fonction existe forcément;
181        // - sinon, on utilise la fonction du plugin appelant si elle existe;
182        // - et sinon, on utilise la fonction de N-Core.
183        include_spip('inc/ncore_utils');
184        if ($decrire = ncore_chercher_service($plugin, 'type_noisette_decrire', $stockage)) {
185                // On passe le plugin appelant à la fonction car cela permet ainsi de mutualiser les services de stockage.
186                $description = $decrire($plugin, $type_noisette);
187        } else {
188                // Le plugin ne propose pas de fonction propre ou le stockage N-Core est explicitement demandé.
189                // -- Lecture de toute la description du type de noisette à partir du cache.
190                // -- Les données sont renvoyées brutes sans traitement sur les textes ni sur les tableaux sérialisés.
191
192                // Initialisation de la description à renvoyer.
193                $description = array();
194
195                include_spip('inc/ncore_cache');
196                $descriptions = cache_lire($plugin, _NCORE_NOMCACHE_TYPE_NOISETTE_DESCRIPTION);
197                if (isset($descriptions[$type_noisette])) {
198                        $description = $descriptions[$type_noisette];
199                }
200        }
201
202        return $description;
203}
204
205/**
206 * Renvoie, pour l'ensemble des types de noisette, l'information brute demandée
207 * ou toute la description si aucune information n'est explicitement demandée.
208 *
209 * @package SPIP\NCORE\TYPE_NOISETTE\SERVICE
210 *
211 * @uses ncore_chercher_service()
212 * @uses cache_lire()
213 *
214 * @param string $plugin
215 *        Identifiant qui permet de distinguer le module appelant qui peut-être un plugin comme le noiZetier ou
216 *        un script. Pour un plugin, le plus pertinent est d'utiliser le préfixe.
217 * @param string $information
218 *        Identifiant d'un champ de la description d'un type de noisette ou `signature`.
219 *        Si l'argument est vide, la fonction renvoie les descriptions complètes et si l'argument est
220 *        un champ invalide la fonction renvoie un tableau vide.
221 * @param string $stockage
222 *        Identifiant du service de stockage à utiliser si précisé.
223 *
224 * @return array
225 *        Tableau de la forme `[noisette] = information ou description complète`.
226 */
227function ncore_type_noisette_lister($plugin, $information = '', $stockage = '') {
228
229        // On cherche le service de stockage à utiliser selon la logique suivante :
230        // - si le service de stockage est non vide on l'utilise en considérant que la fonction existe forcément;
231        // - sinon, on utilise la fonction du plugin appelant si elle existe;
232        // - et sinon, on utilise la fonction de N-Core.
233        include_spip('inc/ncore_utils');
234        if ($lister = ncore_chercher_service($plugin, 'type_noisette_lister', $stockage)) {
235                // On passe le plugin appelant à la fonction car cela permet ainsi de mutualiser les services de stockage.
236                $types_noisettes = $lister($plugin, $information);
237        } else {
238                // Le plugin ne propose pas de fonction propre ou le stockage N-Core est explicitement demandé.
239                // -- Initialisation du tableau de sortie
240                $types_noisettes = array();
241
242                include_spip('inc/ncore_cache');
243                if ($information == 'signature') {
244                        // Les signatures md5 sont sockées dans un fichier cache séparé de celui des descriptions de noisettes.
245                        $types_noisettes = cache_lire($plugin, _NCORE_NOMCACHE_TYPE_NOISETTE_SIGNATURE);
246                } elseif ($descriptions = cache_lire($plugin, _NCORE_NOMCACHE_TYPE_NOISETTE_DESCRIPTION)) {
247                        if ($information) {
248                                // Si $information n'est pas une colonne valide array_column retournera un tableau vide.
249                                $types_noisettes = array_column($descriptions, $information, 'type_noisette');
250                        } else {
251                                $types_noisettes = $descriptions;
252                        }
253                }
254        }
255
256        return $types_noisettes;
257}
258
259/**
260 * Renvoie la configuration par défaut de l'ajax à appliquer pour la compilation des noisettes.
261 * Cette information est utilisée si la description YAML d'un type noisette ne contient pas de tag ajax
262 * ou contient un tag ajax à `defaut`.
263 *
264 * Le service N-Core considère que toute noisette est par défaut insérée en ajax.
265 *
266 * @package SPIP\NCORE\TYPE_NOISETTE\SERVICE
267 *
268 * @uses ncore_chercher_service()
269 *
270 * @param string $plugin
271 *        Identifiant qui permet de distinguer le module appelant qui peut-être un plugin comme le noiZetier ou
272 *        un script. Pour un plugin, le plus pertinent est d'utiliser le préfixe.
273 *
274 * @return bool
275 *              `true` si par défaut une noisette est insérée en ajax, `false` sinon.
276 */
277function ncore_type_noisette_initialiser_ajax($plugin) {
278
279        // On cherche le service de stockage à utiliser selon la logique suivante :
280        // - si le service de stockage est non vide on l'utilise en considérant que la fonction existe forcément;
281        // - sinon, on utilise la fonction du plugin appelant si elle existe;
282        // - et sinon, on utilise la fonction de N-Core.
283        include_spip('inc/ncore_utils');
284        if ($configurer = ncore_chercher_service($plugin, 'type_noisette_initialiser_ajax', '')) {
285                // On passe le plugin appelant à la fonction car cela permet ainsi de mutualiser les services de stockage.
286                // On autorise la fonction du plugin à retourner autre chose que true ou false si tant est que l'on puisse
287                // en déduire un booléen (par exemple, 'on' et '' comme le retourne une case à cocher du plugin Saisies).
288                $defaut_ajax = $configurer($plugin) ? true : false;
289        } else {
290                // Le service ne propose pas de fonction propre, on utilise celle de N-Core.
291                $defaut_ajax = true;
292        }
293
294        return $defaut_ajax;
295}
296
297/**
298 * Renvoie la configuration par défaut de l'inclusion dynamique à appliquer pour la compilation des noisettes.
299 * Cette information est utilisée si la description YAML d'un type noisette ne contient pas de tag inclusion
300 * ou contient un tag inclusion à `defaut`.
301 *
302 * Le service N-Core considère que toute noisette est par défaut insérée en statique.
303 *
304 * @package SPIP\NCORE\TYPE_NOISETTE\SERVICE
305 *
306 * @uses ncore_chercher_service()
307 *
308 * @param string $plugin
309 *        Identifiant qui permet de distinguer le module appelant qui peut-être un plugin comme le noiZetier ou
310 *        un script. Pour un plugin, le plus pertinent est d'utiliser le préfixe.
311 *
312 * @return bool
313 *              `true` si par défaut une noisette est insérée en dynamique, `false` sinon.
314 */
315function ncore_type_noisette_initialiser_inclusion($plugin) {
316
317        // On cherche le service de stockage à utiliser selon la logique suivante :
318        // - si le service de stockage est non vide on l'utilise en considérant que la fonction existe forcément;
319        // - sinon, on utilise la fonction du plugin appelant si elle existe;
320        // - et sinon, on utilise la fonction de N-Core.
321        include_spip('inc/ncore_utils');
322        if ($configurer = ncore_chercher_service($plugin, 'type_noisette_initialiser_inclusion', '')) {
323                // On passe le plugin appelant à la fonction car cela permet ainsi de mutualiser les services de stockage.
324                // On autorise la fonction du plugin à retourner autre chose que true ou false si tant est que l'on puisse
325                // en déduire un booléen (par exemple, 'on' et '' comme le retourne une case à cocher du plugin Saisies).
326                $defaut_inclusion = $configurer($plugin) ? true : false;
327        } else {
328                // Le service ne propose pas de fonction propre, on utilise celle de N-Core.
329                $defaut_inclusion = false;
330        }
331
332        return $defaut_inclusion;
333}
334
335/**
336 * Renvoie la configuration par défaut du dossier relatif où trouver les types de noisettes.
337 * Cette information est utilisée a minima au chargement des types de noisettes disponibles.
338 *
339 * Le service N-Core considère que par défaut le dossier relatif des types de noisette est 'noisettes/'.
340 *
341 * @package SPIP\NCORE\TYPE_NOISETTE\SERVICE
342 *
343 * @uses ncore_chercher_service()
344 *
345 * @param string $plugin
346 *        Identifiant qui permet de distinguer le module appelant qui peut-être un plugin comme le noiZetier ou
347 *        un script. Pour un plugin, le plus pertinent est d'utiliser le préfixe.
348 *
349 * @return string
350 *              Chemin relatif du dossier où chercher les types de noisette.
351 */
352function ncore_type_noisette_initialiser_dossier($plugin) {
353
354        // On cherche le service de stockage à utiliser selon la logique suivante :
355        // - si le service de stockage est non vide on l'utilise en considérant que la fonction existe forcément;
356        // - sinon, on utilise la fonction du plugin appelant si elle existe;
357        // - et sinon, on utilise la fonction de N-Core.
358        include_spip('inc/ncore_utils');
359        if ($configurer = ncore_chercher_service($plugin, 'type_noisette_initialiser_dossier', '')) {
360                // On passe le plugin appelant à la fonction car cela permet ainsi de mutualiser les services de stockage.
361                // On autorise la fonction du plugin à retourner autre chose que true ou false si tant est que l'on puisse
362                // en déduire un booléen (par exemple, 'on' et '' comme le retourne une case à cocher du plugin Saisies).
363                $dossier = $configurer($plugin);
364        } else {
365                // Le service ne propose pas de fonction propre, on utilise celle de N-Core.
366                $dossier = 'noisettes/';
367        }
368
369        return $dossier;
370}
371
372
373// -----------------------------------------------------------------------
374// ----------------------------- NOISETTES -------------------------------
375// -----------------------------------------------------------------------
376
377/**
378 * Stocke la description d'une nouvelle noisette et calcule son identifiant unique, ou met à jour les paramètres
379 * d'affichage d'une noisette existante.
380 *
381 * @package SPIP\NCORE\NOISETTE\SERVICE
382 *
383 * @uses ncore_chercher_service()
384 *
385 * @param string $plugin
386 *        Identifiant qui permet de distinguer le module appelant qui peut-être un plugin comme le noiZetier ou
387 *        un script. Pour un plugin, le plus pertinent est d'utiliser le préfixe.
388 * @param array  $description
389 *        Description de la noisette. Soit la description ne contient pas l'id de la noisette et c'est un ajout,
390 *        soit la description contient l'id et c'est une mise à jour.
391 * @param string $stockage
392 *        Identifiant du service de stockage à utiliser si précisé.
393 *
394 * @return int|string
395 *        Id de la noisette de type entier ou chaine.
396 *        Le stockage N-Core renvoie lui une chaine construite à partir du plugin et de la fonction uniqid()
397 *        ou chaine vide en cas d'erreur.
398 */
399function ncore_noisette_stocker($plugin, $description, $stockage = '') {
400
401        // On cherche le service de stockage à utiliser selon la logique suivante :
402        // - si le service de stockage est non vide on l'utilise en considérant que la fonction existe forcément;
403        // - sinon, on utilise la fonction du plugin appelant si elle existe;
404        // - et sinon, on utilise la fonction de N-Core.
405        include_spip('inc/ncore_utils');
406        if ($stocker = ncore_chercher_service($plugin, 'noisette_stocker', $stockage)) {
407                // On passe le plugin appelant à la fonction car cela permet ainsi de mutualiser les services de stockage.
408                $id_noisette = $stocker($plugin, $description);
409        } else {
410                // Le plugin ne propose pas de fonction propre ou le stockage N-Core est explicitement demandé.
411                // -- N-Core stocke les noisettes dans une meta propre au plugin appelant contenant un tableau au format
412                //    [id_conteneur][rang] = description
413                //    N-Core calcule un identifiant unique pour la noisette qui sera stocké à l'index 'id_noisette' de sa
414                //    description et qui vaudra uniqid() avec comme préfixe le plugin appelant.
415
416                // Initialisation de l'id de la noisette qui sera fourni en sortie. La valeur chaine vide indique une erreur.
417                $id_noisette = '';
418
419                // On lit la meta de stockage des noisettes pour le plugin appelant.
420                include_spip('inc/config');
421                $noisettes = lire_config("${plugin}_noisettes", array());
422
423                // Détermination de l'identifiant du conteneur qui est inclus dans la description et jamais vide.
424                if (!empty($description['id_conteneur'])) {
425                        $id_conteneur = $description['id_conteneur'];
426
427                        if (empty($description['id_noisette'])) {
428                                // Ajout de la noisette :
429                                // -- la description est complète à l'exception de l'id unique qui est créé à la volée
430                                // -- et on range la noisette avec les noisettes affectées au même conteneur en fonction de son rang.
431                                $description['id_noisette'] = uniqid("${plugin}_");
432                                $noisettes[$id_conteneur][$description['rang_noisette']] = $description;
433                        } else {
434                                // Modification de la noisette :
435                                // -- les identifiants de la noisette sont toujours fournies, à savoir, l'id, le conteneur et le rang.
436                                // -- on utilise le conteneur et le rang pour se positionner sur la noisette concernée.
437                                // -- Les modifications ne concernent que les paramètres d'affichage, cette fonction n'est jamais utilisée
438                                //    pour le changement de rang.
439                                if (isset($noisettes[$id_conteneur][$description['rang_noisette']])) {
440                                        $noisettes[$id_conteneur][$description['rang_noisette']] = array_merge(
441                                                $noisettes[$id_conteneur][$description['rang_noisette']],
442                                                $description
443                                        );
444                                }
445                        }
446
447                        // On met à jour la meta
448                        ecrire_config("${plugin}_noisettes", $noisettes);
449
450                        // On renvoie l'id de la noisette ajoutée ou modifiée.
451                        $id_noisette = $description['id_noisette'];
452                }
453        }
454
455        return $id_noisette;
456}
457
458/**
459 * Transfère une noisette d'un conteneur vers un autre à un rang donné et met à jour la profondeur.
460 * Le rang destination n'est pas vérifié lors du rangement dans le conteneur destination. Il convient
461 * à l'appelant de vérifier que le rang est libre.
462 *
463 * @package SPIP\NCORE\NOISETTE\SERVICE
464 *
465 * @uses ncore_chercher_service()
466 * @uses ncore_noisette_destocker()
467 * @uses ncore_conteneur_construire()
468 *
469 * @param string $plugin
470 *        Identifiant qui permet de distinguer le module appelant qui peut-être un plugin comme le noiZetier ou
471 *        un script. Pour un plugin, le plus pertinent est d'utiliser le préfixe.
472 * @param array  $description
473 *        Description de la noisette à changer de conteneur.
474 * @param string $id_conteneur
475 *        Identifiant unique sous forme de chaine du conteneur destination.
476 * @param int    $rang
477 *        Rang où positionner la noisette dans le conteneur destination. Il faut toujours vérifier au préalable
478 *        que ce rang est libre.
479 * @param int    $profondeur
480 *        Profondeur de la noisette à sa nouvelle position.
481 * @param string $stockage
482 *        Identifiant du service de stockage à utiliser si précisé.
483 *
484 * @return array
485 */
486function ncore_noisette_changer_conteneur($plugin, $description, $id_conteneur, $rang, $profondeur, $stockage = '') {
487
488        // On cherche le service de stockage à utiliser selon la logique suivante :
489        // - si le service de stockage est non vide on l'utilise en considérant que la fonction existe forcément;
490        // - sinon, on utilise la fonction du plugin appelant si elle existe;
491        // - et sinon, on utilise la fonction de N-Core.
492        include_spip('inc/ncore_utils');
493        if ($changer = ncore_chercher_service($plugin, 'noisette_changer_conteneur', $stockage)) {
494                // On passe le plugin appelant à la fonction car cela permet ainsi de mutualiser les services de stockage.
495                $description = $changer($plugin, $description, $id_conteneur, $rang, $profondeur);
496        } else {
497                // Le plugin ne propose pas de fonction propre ou le stockage N-Core est explicitement demandé.
498                // -- N-Core stocke les noisettes dans une meta propre au plugin appelant contenant un tableau au format
499                //    [id_conteneur][rang] = description
500
501                // On supprime la noisette de son emplacement actuel en utilisant la description.
502                ncore_noisette_destocker('ncore', $description, $stockage);
503
504                // On lit la meta de stockage des noisettes pour le plugin appelant.
505                include_spip('inc/config');
506                $noisettes = lire_config("${plugin}_noisettes", array());
507
508                // On rajoute la description à son emplacement destination en prenant soin de modifier les index id_conteneur,
509                // conteneur, rang_noisette et profondeur qui doivent représenter le conteneur destination.
510                $description['id_conteneur'] = $id_conteneur;
511                $description['conteneur'] = ncore_conteneur_construire($plugin, $id_conteneur, $stockage);
512                $description['rang_noisette'] = $rang;
513                $description['profondeur'] = $profondeur;
514                $noisettes[$id_conteneur][$rang] = $description;
515
516                // On met à jour la meta
517                ecrire_config("${plugin}_noisettes", $noisettes);
518        }
519
520        return $description;
521}
522
523/**
524 * Complète la description d'une noisette avec des champs spécifiques au plugin utilisateur si besoin.
525 *
526 * Le plugin N-Core ne complète pas les descriptions de noisette.
527 *
528 * @package SPIP\NCORE\NOISETTE\SERVICE
529 *
530 * @uses ncore_chercher_service()
531 *
532 * @param string $plugin
533 *        Identifiant qui permet de distinguer le module appelant qui peut-être un plugin comme le noiZetier ou
534 *        un script. Pour un plugin, le plus pertinent est d'utiliser le préfixe.
535 * @param array  $description
536 *        Description standard de la noisette. Suivant le plugin utilisateur elle nécessite d'être compléter
537 *        avant son stockage.
538 * @param string $stockage
539 *        Identifiant du service de stockage à utiliser si précisé.
540 *
541 * @return array
542 *        Description de la noisette éventuellement complétée par le plugin utilisateur.
543 */
544function ncore_noisette_completer($plugin, $description, $stockage = '') {
545
546        $description_complete = $description;
547
548        // On cherche le service de stockage à utiliser selon la logique suivante :
549        // - si le service de stockage est non vide on l'utilise en considérant que la fonction existe forcément;
550        // - sinon, on utilise la fonction du plugin appelant si elle existe;
551        // - et sinon, on utilise la fonction de N-Core.
552        include_spip('inc/ncore_utils');
553        if ($completer = ncore_chercher_service($plugin, 'noisette_completer', $stockage)) {
554                // On passe le plugin appelant à la fonction car cela permet ainsi de mutualiser les services de stockage.
555                $description_complete = $completer($plugin, $description);
556        }
557
558        return $description_complete;
559}
560
561
562/**
563 * Positionne une noisette à un rang différent de celui qu'elle occupe dans le conteneur.
564 *
565 * @package SPIP\NCORE\NOISETTE\SERVICE
566 *
567 * @uses ncore_chercher_service()
568 *
569 * @param string $plugin
570 *        Identifiant qui permet de distinguer le module appelant qui peut-être un plugin comme le noiZetier ou
571 *        un script. Pour un plugin, le plus pertinent est d'utiliser le préfixe.
572 * @param array  $description
573 *        Description complète de la noisette.
574 * @param int    $rang_destination
575 *        Position à laquelle ranger la noisette au sein du conteneur.
576 * @param string $stockage
577 *        Identifiant du service de stockage à utiliser si précisé.
578 *
579 * @return bool
580 *        `true` si le traitement s'est bien déroulé, `false` sinon.
581 */
582function ncore_noisette_ranger($plugin, $description, $rang_destination, $stockage = '') {
583
584        // On cherche le service de stockage à utiliser selon la logique suivante :
585        // - si le service de stockage est non vide on l'utilise en considérant que la fonction existe forcément;
586        // - sinon, on utilise la fonction du plugin appelant si elle existe;
587        // - et sinon, on utilise la fonction de N-Core.
588        include_spip('inc/ncore_utils');
589        if ($ranger = ncore_chercher_service($plugin, 'noisette_ranger', $stockage)) {
590                // On passe le plugin appelant à la fonction car cela permet ainsi de mutualiser les services de stockage.
591                $retour = $ranger($plugin, $description, $rang_destination);
592        } else {
593                // Le plugin ne propose pas de fonction propre ou le stockage N-Core est explicitement demandé.
594                // -- N-Core stocke les noisettes dans une meta propre au plugin appelant contenant un tableau au format
595                //    [id_conteneur][rang] = description
596
597                // Initialisation de la sortie.
598                $retour = false;
599
600                // On lit la meta de stockage des noisettes pour le plugin appelant.
601                include_spip('inc/config');
602                $noisettes = lire_config("${plugin}_noisettes", array());
603
604                if (!empty($description['id_conteneur'])) {
605                        $id_conteneur = $description['id_conteneur'];
606
607                        // On ajoute la noisette au rang choisi même si on doit écraser un index existant:
608                        // -- Il est donc nécessaire de gérer la collision en amont de cette fonction.
609                        // -- Par contre, l'ancien rang de la noisette est supprimé sauf si celui-ci est à zéro.
610                        $rang_source = $description['rang_noisette'];
611                        $description['rang_noisette'] = $rang_destination;
612                        $noisettes[$id_conteneur][$rang_destination] = $description;
613                        if ($rang_source != 0) {
614                                unset($noisettes[$id_conteneur][$rang_source]);
615                        }
616
617                        // On met à jour la meta
618                        ecrire_config("${plugin}_noisettes", $noisettes);
619                        $retour = true;
620                }
621        }
622
623        return $retour;
624}
625
626/**
627 * Retire, de l'espace de stockage, une noisette donnée de son conteneur.
628 *
629 * @package SPIP\NCORE\NOISETTE\SERVICE
630 *
631 * @uses ncore_chercher_service()
632 *
633 * @param string       $plugin
634 *        Identifiant qui permet de distinguer le module appelant qui peut-être un plugin comme le noiZetier ou
635 *        un script. Pour un plugin, le plus pertinent est d'utiliser le préfixe.
636 * @param array|string $description
637 *        Description complète de la noisette.
638 * @param string       $stockage
639 *        Identifiant du service de stockage à utiliser si précisé.
640 *
641 * @return bool
642 *        `true` si le traitement s'est bien déroulé, `false` sinon.
643 */
644function ncore_noisette_destocker($plugin, $description, $stockage = '') {
645
646        // On cherche le service de stockage à utiliser selon la logique suivante :
647        // - si le service de stockage est non vide on l'utilise en considérant que la fonction existe forcément;
648        // - sinon, on utilise la fonction du plugin appelant si elle existe;
649        // - et sinon, on utilise la fonction de N-Core.
650        include_spip('inc/ncore_utils');
651        if ($destocker = ncore_chercher_service($plugin, 'noisette_destocker', $stockage)) {
652                // On passe le plugin appelant à la fonction car cela permet ainsi de mutualiser les services de stockage.
653                $retour = $destocker($plugin, $description);
654        } else {
655                // Le plugin ne propose pas de fonction propre ou le stockage N-Core est explicitement demandé.
656                // -- N-Core stocke les noisettes dans une meta propre au plugin appelant contenant un tableau au format
657                //    [id_conteneur][rang] = description
658                // -- $description est soit le tableau descriptif de la noisette, soit le conteneur, et dans ce cas, il faut
659                //    supprimer toutes les noisettes du conteneur.
660
661                // Initialisation de la sortie.
662                $retour = false;
663
664                include_spip('inc/config');
665                $meta_noisettes = lire_config("${plugin}_noisettes", array());
666
667                if (isset($meta_noisettes[$description['id_conteneur']][$description['rang_noisette']])) {
668                        // On supprime une noisette donnée.
669                        unset($meta_noisettes[$description['id_conteneur']][$description['rang_noisette']]);
670                        // Si c'est la dernière noisette du conteneur il faut aussi supprimer l'index correspondant au conteneur.
671                        if (!$meta_noisettes[$description['id_conteneur']]) {
672                                unset($meta_noisettes[$description['id_conteneur']]);
673                        }
674                        ecrire_config("${plugin}_noisettes", $meta_noisettes);
675                        $retour = true;
676                }
677        }
678
679        return $retour;
680}
681
682
683/**
684 * Renvoie un champ ou toute la description des noisettes d'un conteneur ou de tous les conteneurs.
685 * Le tableau retourné est indexé soit par identifiant de noisette soit par identifiant du conteneur et rang
686 * de noisette.
687 *
688 * @package SPIP\NCORE\NOISETTE\SERVICE
689 *
690 * @uses ncore_chercher_service()
691 * @uses ncore_conteneur_identifier()
692 *
693 * @param string $plugin
694 *        Identifiant qui permet de distinguer le module appelant qui peut-être un plugin comme le noiZetier ou
695 *        un script. Pour un plugin, le plus pertinent est d'utiliser le préfixe.
696 * @param array|string $conteneur
697 *        Tableau descriptif du conteneur ou identifiant du conteneur ou vide si on souhaite adresser tous les
698 *        conteneurs.
699 * @param string $information
700 *        Identifiant d'un champ de la description d'une noisette.
701 *        Si l'argument est vide, la fonction renvoie les descriptions complètes et si l'argument est
702 *        un champ invalide la fonction renvoie un tableau vide.
703 * @param string $cle
704 *        Champ de la description d'une noisette servant d'index du tableau. En général on utilisera soit `id_noisette`
705 *        soit `rang_noisette`.
706 * @param string $stockage
707 *        Identifiant du service de stockage à utiliser si précisé.
708 *
709 * @return array
710 *        Tableau de la liste des informations demandées indexé par identifiant de noisette ou par rang.
711 */
712function ncore_noisette_lister($plugin, $conteneur = array(), $information = '', $cle = 'rang_noisette', $stockage = '') {
713
714        // On cherche le service de stockage à utiliser selon la logique suivante :
715        // - si le service de stockage est non vide on l'utilise en considérant que la fonction existe forcément;
716        // - sinon, on utilise la fonction du plugin appelant si elle existe;
717        // - et sinon, on utilise la fonction de N-Core.
718        include_spip('inc/ncore_utils');
719        if ($lister = ncore_chercher_service($plugin, 'noisette_lister', $stockage)) {
720                // On passe le plugin appelant à la fonction car cela permet ainsi de mutualiser les services de stockage.
721                $noisettes = $lister($plugin, $conteneur, $information, $cle);
722        } else {
723                // Le plugin ne propose pas de fonction propre ou le stockage N-Core est explicitement demandé.
724                // -- N-Core stocke les noisettes dans une meta propre au plugin appelant contenant un tableau au format
725                //    [id_conteneur][rang] = description
726
727                // Initialisation du tableau de sortie.
728                $noisettes = array();
729
730                include_spip('inc/config');
731                $meta_noisettes = lire_config("${plugin}_noisettes", array());
732
733                if ($conteneur) {
734                        // On détermine l'id du conteneur en fonction du mode d'identification du conteneur lors de l'appel.
735                        if (is_array($conteneur)) {
736                                $id_conteneur = ncore_conteneur_identifier($plugin, $conteneur, $stockage);
737                        } else {
738                                $id_conteneur = $conteneur;
739                        }
740                        if (!empty($meta_noisettes[$id_conteneur])) {
741                                $noisettes = $meta_noisettes[$id_conteneur];
742                                $noisettes = $information
743                                        ? array_column($noisettes, $information, $cle)
744                                        : array_column($noisettes, null, $cle);
745                        }
746                } elseif ($meta_noisettes) {
747                        if ($cle == 'rang_noisette') {
748                                $noisettes = $meta_noisettes;
749                        } else {
750                                foreach ($meta_noisettes as $_squelette => $_descriptions) {
751                                        $noisettes_squelette = $information
752                                                ? array_column($_descriptions, $information, $cle)
753                                                : array_column($_descriptions, null, $cle);
754                                        $noisettes = array_merge($noisettes, $noisettes_squelette);
755                                }
756                        }
757                }
758        }
759
760        return $noisettes;
761}
762
763
764/**
765 * Renvoie la description brute d'une noisette sans traitement typo des champs textuels ni désérialisation
766 * des champs de type tableau sérialisé.
767 *
768 * @package SPIP\NCORE\NOISETTE\SERVICE
769 *
770 * @uses ncore_chercher_service()
771 *
772 * @param string $plugin
773 *        Identifiant qui permet de distinguer le module appelant qui peut-être un plugin comme le noiZetier ou
774 *        un script. Pour un plugin, le plus pertinent est d'utiliser le préfixe.
775 * @param mixed  $noisette
776 *        Identifiant de la noisette qui peut prendre soit la forme d'un entier ou d'une chaine unique, soit la forme
777 *        d'un couple (conteneur, rang de noisette).
778 * @param string $stockage
779 *        Identifiant du service de stockage à utiliser si précisé.
780 *
781 * @return array
782 *        Tableau de la description du type de noisette. Les champs textuels et les champs de type tableau sérialisé
783 *        sont retournés en l'état.
784 */
785function ncore_noisette_decrire($plugin, $noisette, $stockage = '') {
786
787        // On cherche le service de stockage à utiliser selon la logique suivante :
788        // - si le service de stockage est non vide on l'utilise en considérant que la fonction existe forcément;
789        // - sinon, on utilise la fonction du plugin appelant si elle existe;
790        // - et sinon, on utilise la fonction de N-Core.
791        include_spip('inc/ncore_utils');
792        if ($decrire = ncore_chercher_service($plugin, 'noisette_decrire', $stockage)) {
793                // On passe le plugin appelant à la fonction car cela permet ainsi de mutualiser les services de stockage.
794                $description = $decrire($plugin, $noisette);
795        } else {
796                // Le plugin ne propose pas de fonction propre ou le stockage N-Core est explicitement demandé.
797                // -- N-Core stocke les noisettes dans une meta propre au plugin appelant contenant un tableau au format
798                //    [id_conteneur][rang] = description
799
800                // Initialisation de la description à retourner.
801                $description = array();
802
803                include_spip('inc/config');
804                $meta_noisettes = lire_config("${plugin}_noisettes", array());
805
806                // On recherche la description dans la meta.
807                if ($meta_noisettes) {
808                        if (!is_array($noisette)) {
809                                // L'identifiant est l'id unique de la noisette. Il faut donc parcourir le tableau pour trouver la
810                                // noisette désirée
811                                // => ce n'est pas la méthode optimale pour le stockage N-Core.
812                                $noisette_trouvee = false;
813                                foreach ($meta_noisettes as $_noisettes_squelette) {
814                                        foreach ($_noisettes_squelette as $_noisette) {
815                                                if ($_noisette['id_noisette'] == $noisette) {
816                                                        $description = $_noisette;
817                                                        $noisette_trouvee = true;
818                                                        break;
819                                                }
820                                        }
821                                        if ($noisette_trouvee) {
822                                                break;
823                                        }
824                                }
825                        } else {
826                                if (isset($noisette['id_conteneur'], $noisette['rang_noisette'])) {
827                                        // Détermination de l'identifiant du conteneur.
828                                        $id_conteneur = $noisette['id_conteneur'];
829                                        if (!empty($meta_noisettes[$id_conteneur][$noisette['rang_noisette']])) {
830                                        // L'identifiant est un tableau associatif fournissant le conteneur et le rang.
831                                        // Comme la meta de N-Core est structurée ainsi c'est la méthode la plus adaptée pour adresser
832                                        // le stockage de N-Core.
833                                        $description = $meta_noisettes[$id_conteneur][$noisette['rang_noisette']];
834                                        }
835                                }
836                        }
837                }
838        }
839
840        return $description;
841}
842
843/**
844 * Renvoie la configuration par défaut de l'encapsulation d'une noisette.
845 * Cette information est utilisée si le champ `encapsulation` de la noisette vaut `defaut`.
846 *
847 * Le service N-Core positionne cette valeur à `true`.
848 *
849 * @package SPIP\NCORE\NOISETTE\SERVICE
850 *
851 * @uses ncore_chercher_service()
852 *
853 * @param string $plugin
854 *        Identifiant qui permet de distinguer le module appelant qui peut-être un plugin comme le noiZetier ou
855 *        un script. Pour un plugin, le plus pertinent est d'utiliser le préfixe.
856 *
857 * @return bool
858 *              `true` si par défaut une noisette est encapsulée, `false` sinon.
859 */
860function ncore_noisette_initialiser_encapsulation($plugin) {
861
862        // On cherche le service de stockage à utiliser selon la logique suivante :
863        // - si le service de stockage est non vide on l'utilise en considérant que la fonction existe forcément;
864        // - sinon, on utilise la fonction du plugin appelant si elle existe;
865        // - et sinon, on utilise la fonction de N-Core.
866        include_spip('inc/ncore_utils');
867        if ($configurer = ncore_chercher_service($plugin, 'noisette_initialiser_encapsulation', '')) {
868                // On passe le plugin appelant à la fonction car cela permet ainsi de mutualiser les services de stockage.
869                // On autorise la fonction du plugin à retourner autre chose que true ou false si tant est que l'on puisse
870                // en déduire un booléen (par exemple, 'on' et '' comme le retourne une case à cocher du plugin Saisies).
871                $defaut_capsule = $configurer($plugin) ? true : false;
872        } else {
873                // Le service ne propose pas de fonction propre, on utilise celle de N-Core.
874                $defaut_capsule = true;
875        }
876
877        return $defaut_capsule;
878}
879
880
881// -----------------------------------------------------------------------
882// ----------------------------- CONTENEURS ------------------------------
883// -----------------------------------------------------------------------
884
885/**
886 * Vérifie la conformité des index du tableau représentant le conteneur et supprime les index inutiles, si besoin.
887 * N-Core vérifie que pour les noisettes conteneur les seuls index sont le type et l'id de la noisette.
888 * Pour les autres conteneurs, c'est au plugin utilisateur de vérifier le conteneur.
889 *
890 * @package SPIP\NCORE\CONTENEUR\SERVICE
891 *
892 * @uses ncore_chercher_service()
893 *
894 * @param string $plugin
895 *        Identifiant qui permet de distinguer le module appelant qui peut-être un plugin comme le noiZetier ou
896 *        un script. Pour un plugin, le plus pertinent est d'utiliser le préfixe.
897 * @param array  $conteneur
898 *        Tableau associatif descriptif du conteneur dont les index doivent être vérifiés.
899 * @param string $stockage
900 *        Identifiant du service de stockage à utiliser si précisé.
901 *
902 * @return array
903 *        Tableau du conteneur dont tous les index sont conformes ou tableau vide si non conforme.
904 */
905function ncore_conteneur_verifier($plugin, $conteneur, $stockage = '') {
906
907        static $index_conteneur_noisette = array('type_noisette', 'id_noisette');
908
909        // N-Core ne vérifie pas les conteneurs spécifiques aux plugins utilisateur
910        // sauf pour les noisettes conteneur qui ne sont déterminées que par leur type et leur id.
911        // Il est donc indispensable que le plugin utilisateur propose toujours une fonction de vérification
912        // pour les conteneurs hors noisette conteneur.
913        $conteneur_verifie = array();
914        if ($conteneur) {
915                if (isset($conteneur['type_noisette'], $conteneur['id_noisette'])
916                and $conteneur['type_noisette']
917                and intval($conteneur['id_noisette'])) {
918                        // Le conteneur est une noisette, N-Core effectue le filtre des index.
919                        $conteneur = array_intersect_key($conteneur, array_flip($index_conteneur_noisette));
920                        if (count($conteneur) == 2) {
921                                $conteneur_verifie = $conteneur;
922                        }
923                } else {
924                        // Le conteneur est spécifique au plugin utilisateur, c'est donc au plugin faire la vérification des index.
925                        include_spip('inc/ncore_utils');
926                        if ($verifier = ncore_chercher_service($plugin, 'conteneur_verifier', $stockage)) {
927                                $conteneur_verifie = $verifier($plugin, $conteneur);
928                        }
929                }
930        }
931
932        return $conteneur_verifie;
933}
934
935/**
936 * Construit un identifiant unique pour le conteneur sous forme de chaine.
937 * N-Core ne fournit d'identifiant que pour les noisettes conteneur.
938 * Pour les autres conteneurs, c'est au plugin utilisateur de calculer l'identifiant.
939 *
940 * @package SPIP\NCORE\CONTENEUR\SERVICE
941 *
942 * @uses ncore_chercher_service()
943 *
944 * @param string $plugin
945 *        Identifiant qui permet de distinguer le module appelant qui peut-être un plugin comme le noiZetier ou
946 *        un script. Pour un plugin, le plus pertinent est d'utiliser le préfixe.
947 * @param array  $conteneur
948 *        Tableau associatif descriptif du conteneur. Les index sont spécifiques à l'utilisation qui en est faite
949 *        par le plugin utilisateur. Néanmoins, pour une noisette conteneur, le tableau est limité aux index
950 *        type de noisette et id de noisette.
951 * @param string $stockage
952 *        Identifiant du service de stockage à utiliser si précisé.
953 *
954 * @return string
955 *        Identifiant du conteneur ou chaine vide en cas d'erreur.
956 */
957function ncore_conteneur_identifier($plugin, $conteneur, $stockage = '') {
958
959        // Il faut calculer l'identifiant du conteneur pour accéder à la bonne liste de noisettes.
960        // N-Core ne propose pas de fonction par défaut pour les conteneurs spécifiques aux plugins utilisateur
961        // sauf pour les noisettes conteneur car elles ne sont déterminées que par leur type et leur id.
962        // Il est donc indispensable que le plugin utilisateur propose toujours une fonction de calcul de l'identifiant
963        // pour les conteneurs hors noisette conteneur.
964        $id_conteneur = '';
965        if ($conteneur) {
966                if (isset($conteneur['type_noisette'], $conteneur['id_noisette'])
967                and $conteneur['type_noisette']
968                and intval($conteneur['id_noisette'])) {
969                        // Le conteneur est une noisette, N-Core effectue le calcul de l'id.
970                        $id_conteneur = $conteneur['type_noisette'] . '|noisette|' . $conteneur['id_noisette'];
971                } else {
972                        // Le conteneur est spécifique au plugin utilisateur, c'est donc au plugin de le calculer.
973                        include_spip('inc/ncore_utils');
974                        if ($identifier = ncore_chercher_service($plugin, 'conteneur_identifier', $stockage)) {
975                                $id_conteneur = $identifier($plugin, $conteneur);
976                        }
977                }
978        }
979
980        return $id_conteneur;
981}
982
983/**
984 * Reconstruit le conteneur sous forme de tableau à partir de son identifiant unique (fonction inverse
985 * de `ncore_conteneur_identifier`).
986 * N-Core ne fournit le conteneur que pour les noisettes conteneur.
987 * Pour les autres conteneurs, c'est au plugin utilisateur de calculer le tableau.
988 *
989 * @package SPIP\NCORE\CONTENEUR\SERVICE
990 *
991 * @uses ncore_chercher_service()
992 *
993 * @param string $plugin
994 *        Identifiant qui permet de distinguer le module appelant qui peut-être un plugin comme le noiZetier ou
995 *        un script. Pour un plugin, le plus pertinent est d'utiliser le préfixe.
996 * @param string $id_conteneur
997 *        Identifiant unique du conteneur. Si l'id correspond à une noisette conteneur le traitement sera fait
998 *        par N-Core, sinon par le plugin utilisateur
999 * @param string $stockage
1000 *        Identifiant du service de stockage à utiliser si précisé.
1001 *
1002 * @return array
1003 *        Tableau représentatif du conteneur ou tableau vide en cas d'erreur.
1004 */
1005function ncore_conteneur_construire($plugin, $id_conteneur, $stockage = '') {
1006
1007        // Il faut recomposer le tableau du conteneur à partir de son id.
1008        // N-Core ne propose pas de fonction par défaut pour les conteneurs spécifiques aux plugins utilisateur
1009        // sauf pour les noisettes conteneur.
1010        // Il est donc indispensable que le plugin utilisateur propose toujours une fonction de calcul du tableau
1011        // pour les conteneurs hors noisette conteneur.
1012        $conteneur = array();
1013        if ($id_conteneur) {
1014                $elements = explode('|', $id_conteneur);
1015                if ((count($elements) == 3) and ($elements[1] == 'noisette')) {
1016                        // C'est une noisette conteneur : les index sont le type et l'id de noisette.
1017                        $conteneur['type_noisette'] = $elements[0];
1018                        $conteneur['id_noisette'] = intval($elements[2]);
1019                } else {
1020                        // Le conteneur est spécifique au plugin utilisateur, c'est donc au plugin de le calculer.
1021                        include_spip('inc/ncore_utils');
1022                        if ($construire = ncore_chercher_service($plugin, 'conteneur_construire', $stockage)) {
1023                                $conteneur = $construire($plugin, $id_conteneur);
1024                        }
1025                }
1026        }
1027
1028        return $conteneur;
1029}
1030
1031/**
1032 * Détermine si un conteneur est une noisette ou pas. Le conteneur a été vérifié au préalable.
1033 * Ce service est le seul a ne pas être surchargeable par un plugin utilisateur car les noisettes conteneur
1034 * sont gérées entièrement par N-Core.
1035 *
1036 * @package SPIP\NCORE\CONTENEUR\SERVICE
1037 *
1038 * @param string $plugin
1039 *        Identifiant qui permet de distinguer le module appelant qui peut-être un plugin comme le noiZetier ou
1040 *        un script. Pour un plugin, le plus pertinent est d'utiliser le préfixe.
1041 * @param array $conteneur
1042 *        Identifiant du conteneur sous forme de tableau canonique.
1043 * @param string $stockage
1044 *        Identifiant du service de stockage à utiliser si précisé.
1045 *
1046 * @return bool
1047 *        `true` si le conteneur est une noisette `false` sinon.
1048 */
1049function ncore_conteneur_est_noisette($plugin, $conteneur, $stockage = '') {
1050
1051        // Initialiser la sortie
1052        $est_noisette = false;
1053
1054        // On détermine à partir du tableau si le conteneur est une noisette.
1055        if (isset($conteneur['type_noisette'], $conteneur['id_noisette'])
1056        and $conteneur['type_noisette']
1057        and intval($conteneur['id_noisette'])) {
1058                $est_noisette = true;
1059        }
1060
1061        return $est_noisette;
1062}
1063
1064/**
1065 * Retire, de l'espace de stockage, toutes les noisettes d'un conteneur et ce de façon récursive si
1066 * il existe une imbrication de conteneurs.
1067 *
1068 * @package SPIP\NCORE\CONTENEUR\SERVICE
1069 *
1070 * @uses ncore_noisette_lister()
1071 * @uses ncore_conteneur_destocker()
1072 * @uses ncore_chercher_service()
1073 * @uses ncore_conteneur_identifier()
1074 *
1075 * @param string       $plugin
1076 *        Identifiant qui permet de distinguer le module appelant qui peut-être un plugin comme le noiZetier ou
1077 *        un script. Pour un plugin, le plus pertinent est d'utiliser le préfixe.
1078 * @param array|string $conteneur
1079 *        Tableau descriptif du conteneur ou identifiant du conteneur.
1080 * @param string       $stockage
1081 *        Identifiant du service de stockage à utiliser si précisé.
1082 *
1083 * @return bool
1084 *        `true` si le traitement s'est bien déroulé, `false` sinon.
1085 */
1086function ncore_conteneur_destocker($plugin, $conteneur, $stockage = '') {
1087
1088        // Initialisation de la sortie.
1089        $retour = false;
1090
1091        // On liste les noisettes du conteneur concerné et on repère les noisettes conteneur.
1092        // Chaque conteneur imbriqué est vidé et ce de façon récursive.
1093        foreach (ncore_noisette_lister($plugin, $conteneur, '', 'rang_noisette', $stockage) as $_noisette) {
1094                if ($_noisette['est_conteneur'] == 'oui') {
1095                        // On vide récursivement les noisettes de type conteneur.
1096                        ncore_conteneur_destocker($plugin, $_noisette, $stockage);
1097                }
1098        }
1099
1100        // On cherche le service de stockage à utiliser selon la logique suivante :
1101        // - si le service de stockage est non vide on l'utilise en considérant que la fonction existe forcément;
1102        // - sinon, on utilise la fonction du plugin appelant si elle existe;
1103        // - et sinon, on utilise la fonction de N-Core.
1104        include_spip('inc/ncore_utils');
1105        if ($destocker = ncore_chercher_service($plugin, 'conteneur_destocker', $stockage)) {
1106                // On passe le plugin appelant à la fonction car cela permet ainsi de mutualiser les services de stockage.
1107                $retour = $destocker($plugin, $conteneur);
1108        } else {
1109                // Le plugin ne propose pas de fonction propre ou le stockage N-Core est explicitement demandé.
1110                // -- N-Core stocke les noisettes dans une meta propre au plugin appelant contenant un tableau au format
1111                //    [conteneur][rang] = description
1112                include_spip('inc/config');
1113                $meta_noisettes = lire_config("${plugin}_noisettes", array());
1114
1115                // On détermine l'id du conteneur en fonction du mode d'identification du conteneur lors de l'appel.
1116                if (is_array($conteneur)) {
1117                        $id_conteneur = ncore_conteneur_identifier($plugin, $conteneur, $stockage);
1118                } else {
1119                        $id_conteneur = $conteneur;
1120                }
1121
1122                if (isset($meta_noisettes[$id_conteneur])) {
1123                        // On supprime toutes les noisettes du conteneur.
1124                        unset($meta_noisettes[$id_conteneur]);
1125                        ecrire_config("${plugin}_noisettes", $meta_noisettes);
1126                        $retour = true;
1127                }
1128        }
1129
1130        return $retour;
1131}
Note: See TracBrowser for help on using the repository browser.