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

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

Pétouille de pétouille de phpdoc

  • Property svn:eol-style set to native
File size: 41.8 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 du dossier relatif où trouver les types de noisettes.
299 * Cette information est utilisée a minima au chargement des types de noisettes disponibles.
300 *
301 * Le service N-Core considère que par défaut le dossier relatif des types de noisette est 'noisettes/'.
302 *
303 * @package SPIP\NCORE\TYPE_NOISETTE\SERVICE
304 *
305 * @uses ncore_chercher_service()
306 *
307 * @param string $plugin
308 *        Identifiant qui permet de distinguer le module appelant qui peut-être un plugin comme le noiZetier ou
309 *        un script. Pour un plugin, le plus pertinent est d'utiliser le préfixe.
310 *
311 * @return string
312 *              Chemin relatif du dossier où chercher les types de noisette.
313 */
314function ncore_type_noisette_initialiser_dossier($plugin) {
315
316        // On cherche le service de stockage à utiliser selon la logique suivante :
317        // - si le service de stockage est non vide on l'utilise en considérant que la fonction existe forcément;
318        // - sinon, on utilise la fonction du plugin appelant si elle existe;
319        // - et sinon, on utilise la fonction de N-Core.
320        include_spip('inc/ncore_utils');
321        if ($configurer = ncore_chercher_service($plugin, 'type_noisette_initialiser_dossier', '')) {
322                // On passe le plugin appelant à la fonction car cela permet ainsi de mutualiser les services de stockage.
323                // On autorise la fonction du plugin à retourner autre chose que true ou false si tant est que l'on puisse
324                // en déduire un booléen (par exemple, 'on' et '' comme le retourne une case à cocher du plugin Saisies).
325                $dossier = $configurer($plugin);
326        } else {
327                // Le service ne propose pas de fonction propre, on utilise celle de N-Core.
328                $dossier = 'noisettes/';
329        }
330
331        return $dossier;
332}
333
334
335// -----------------------------------------------------------------------
336// ----------------------------- NOISETTES -------------------------------
337// -----------------------------------------------------------------------
338
339/**
340 * Stocke la description d'une nouvelle noisette et calcule son identifiant unique, ou met à jour les paramètres
341 * d'affichage d'une noisette existante.
342 *
343 * @package SPIP\NCORE\NOISETTE\SERVICE
344 *
345 * @uses ncore_chercher_service()
346 *
347 * @param string $plugin
348 *        Identifiant qui permet de distinguer le module appelant qui peut-être un plugin comme le noiZetier ou
349 *        un script. Pour un plugin, le plus pertinent est d'utiliser le préfixe.
350 * @param array  $description
351 *        Description de la noisette. Soit la description ne contient pas l'id de la noisette et c'est un ajout,
352 *        soit la description contient l'id et c'est une mise à jour.
353 * @param string $stockage
354 *        Identifiant du service de stockage à utiliser si précisé.
355 *
356 * @return int|string
357 *        Id de la noisette de type entier ou chaine.
358 *        Le stockage N-Core renvoie lui une chaine construite à partir du plugin et de la fonction uniqid()
359 *        ou chaine vide en cas d'erreur.
360 */
361function ncore_noisette_stocker($plugin, $description, $stockage = '') {
362
363        // On cherche le service de stockage à utiliser selon la logique suivante :
364        // - si le service de stockage est non vide on l'utilise en considérant que la fonction existe forcément;
365        // - sinon, on utilise la fonction du plugin appelant si elle existe;
366        // - et sinon, on utilise la fonction de N-Core.
367        include_spip('inc/ncore_utils');
368        if ($stocker = ncore_chercher_service($plugin, 'noisette_stocker', $stockage)) {
369                // On passe le plugin appelant à la fonction car cela permet ainsi de mutualiser les services de stockage.
370                $id_noisette = $stocker($plugin, $description);
371        } else {
372                // Le plugin ne propose pas de fonction propre ou le stockage N-Core est explicitement demandé.
373                // -- N-Core stocke les noisettes dans une meta propre au plugin appelant contenant un tableau au format
374                //    [conteneur][rang] = description
375                //    N-Core calcule un identifiant unique pour la noisette qui sera stocké à l'index 'id_noisette' de sa
376                //    description et qui vaudra uniqid() avec comme préfixe le plugin appelant.
377
378                // Initialisation de l'id de la noisette qui sera fourni en sortie. La valeur chaine vide indique une erreur.
379                $id_noisette = '';
380
381                // On lit la meta de stockage des noisettes pour le plugin appelant.
382                include_spip('inc/config');
383                $noisettes = lire_config("${plugin}_noisettes", array());
384
385                // Détermination de l'identifiant du conteneur qui est inclus dans la description et jamais vide.
386                if (!empty($description['id_conteneur'])) {
387                        $id_conteneur = $description['id_conteneur'];
388
389                        if (empty($description['id_noisette'])) {
390                                // Ajout de la noisette :
391                                // -- la description est complète à l'exception de l'id unique qui est créé à la volée
392                                // -- et on range la noisette avec les noisettes affectées au même conteneur en fonction de son rang.
393                                $description['id_noisette'] = uniqid("${plugin}_");
394                                $noisettes[$id_conteneur][$description['rang_noisette']] = $description;
395                        } else {
396                                // Modification de la noisette :
397                                // -- les identifiants de la noisette sont toujours fournies, à savoir, l'id, le conteneur et le rang.
398                                // -- on utilise le conteneur et le rang pour se positionner sur la noisette concernée.
399                                // -- Les modifications ne concernent que les paramètres d'affichage, cette fonction n'est jamais utilisée
400                                //    pour le changement de rang.
401                                if (isset($noisettes[$id_conteneur][$description['rang_noisette']])) {
402                                        $noisettes[$id_conteneur][$description['rang_noisette']] = array_merge(
403                                                $noisettes[$id_conteneur][$description['rang_noisette']],
404                                                $description
405                                        );
406                                }
407                        }
408
409                        // On met à jour la meta
410                        ecrire_config("${plugin}_noisettes", $noisettes);
411
412                        // On renvoie l'id de la noisette ajoutée ou modifiée.
413                        $id_noisette = $description['id_noisette'];
414                }
415        }
416
417        return $id_noisette;
418}
419
420
421/**
422 * Complète la description d'une noisette avec des champs spécifiques au plugin utilisateur si besoin.
423 *
424 * Le plugin N-Core ne complète pas les descriptions de noisette.
425 *
426 * @package SPIP\NCORE\NOISETTE\SERVICE
427 *
428 * @uses ncore_chercher_service()
429 *
430 * @param string $plugin
431 *        Identifiant qui permet de distinguer le module appelant qui peut-être un plugin comme le noiZetier ou
432 *        un script. Pour un plugin, le plus pertinent est d'utiliser le préfixe.
433 * @param array  $description
434 *        Description standard de la noisette. Suivant le plugin utilisateur elle nécessite d'être compléter
435 *        avant son stockage.
436 * @param string $stockage
437 *        Identifiant du service de stockage à utiliser si précisé.
438 *
439 * @return array
440 *        Description de la noisette éventuellement complétée par le plugin utilisateur.
441 */
442function ncore_noisette_completer($plugin, $description, $stockage = '') {
443
444        $description_complete = $description;
445
446        // On cherche le service de stockage à utiliser selon la logique suivante :
447        // - si le service de stockage est non vide on l'utilise en considérant que la fonction existe forcément;
448        // - sinon, on utilise la fonction du plugin appelant si elle existe;
449        // - et sinon, on utilise la fonction de N-Core.
450        include_spip('inc/ncore_utils');
451        if ($completer = ncore_chercher_service($plugin, 'noisette_completer', $stockage)) {
452                // On passe le plugin appelant à la fonction car cela permet ainsi de mutualiser les services de stockage.
453                $description_complete = $completer($plugin, $description);
454        }
455
456        return $description_complete;
457}
458
459
460/**
461 * Positionne une noisette à un rang différent de celui qu'elle occupe dans le conteneur.
462 *
463 * @package SPIP\NCORE\NOISETTE\SERVICE
464 *
465 * @uses ncore_chercher_service()
466 *
467 * @param string $plugin
468 *        Identifiant qui permet de distinguer le module appelant qui peut-être un plugin comme le noiZetier ou
469 *        un script. Pour un plugin, le plus pertinent est d'utiliser le préfixe.
470 * @param array  $description
471 *        Description complète de la noisette.
472 * @param int    $rang_destination
473 *        Position à laquelle ranger la noisette au sein du conteneur.
474 * @param string $stockage
475 *        Identifiant du service de stockage à utiliser si précisé.
476 *
477 * @return bool
478 *        `true` si le traitement s'est bien déroulé, `false` sinon.
479 */
480function ncore_noisette_ranger($plugin, $description, $rang_destination, $stockage = '') {
481
482        // On cherche le service de stockage à utiliser selon la logique suivante :
483        // - si le service de stockage est non vide on l'utilise en considérant que la fonction existe forcément;
484        // - sinon, on utilise la fonction du plugin appelant si elle existe;
485        // - et sinon, on utilise la fonction de N-Core.
486        include_spip('inc/ncore_utils');
487        if ($ranger = ncore_chercher_service($plugin, 'noisette_ranger', $stockage)) {
488                // On passe le plugin appelant à la fonction car cela permet ainsi de mutualiser les services de stockage.
489                $retour = $ranger($plugin, $description, $rang_destination);
490        } else {
491                // Le plugin ne propose pas de fonction propre ou le stockage N-Core est explicitement demandé.
492                // -- N-Core stocke les noisettes dans une meta propre au plugin appelant contenant un tableau au format
493                //    [conteneur][rang] = description
494
495                // Initialisation de la sortie.
496                $retour = false;
497
498                // On lit la meta de stockage des noisettes pour le plugin appelant.
499                include_spip('inc/config');
500                $noisettes = lire_config("${plugin}_noisettes", array());
501
502                if (!empty($description['id_conteneur'])) {
503                        $id_conteneur = $description['id_conteneur'];
504
505                        // On ajoute la noisette au rang choisi même si on doit écraser un index existant:
506                        // -- Il est donc nécessaire de gérer la collision en amont de cette fonction.
507                        // -- Par contre, l'ancien rang de la noisette est supprimé sauf si celui-ci est à zéro.
508                        $rang_source = $description['rang_noisette'];
509                        $description['rang_noisette'] = $rang_destination;
510                        $noisettes[$id_conteneur][$rang_destination] = $description;
511                        if ($rang_source != 0) {
512                                unset($noisettes[$id_conteneur][$rang_source]);
513                        }
514
515                        // On met à jour la meta
516                        ecrire_config("${plugin}_noisettes", $noisettes);
517                        $retour = true;
518                }
519        }
520
521        return $retour;
522}
523
524/**
525 * Retire, de l'espace de stockage, une noisette donnée de son conteneur.
526 *
527 * @package SPIP\NCORE\NOISETTE\SERVICE
528 *
529 * @uses ncore_chercher_service()
530 *
531 * @param string       $plugin
532 *        Identifiant qui permet de distinguer le module appelant qui peut-être un plugin comme le noiZetier ou
533 *        un script. Pour un plugin, le plus pertinent est d'utiliser le préfixe.
534 * @param array|string $description
535 *        Description complète de la noisette.
536 * @param string       $stockage
537 *        Identifiant du service de stockage à utiliser si précisé.
538 *
539 * @return bool
540 *        `true` si le traitement s'est bien déroulé, `false` sinon.
541 */
542function ncore_noisette_destocker($plugin, $description, $stockage = '') {
543
544        // On cherche le service de stockage à utiliser selon la logique suivante :
545        // - si le service de stockage est non vide on l'utilise en considérant que la fonction existe forcément;
546        // - sinon, on utilise la fonction du plugin appelant si elle existe;
547        // - et sinon, on utilise la fonction de N-Core.
548        include_spip('inc/ncore_utils');
549        if ($destocker = ncore_chercher_service($plugin, 'noisette_destocker', $stockage)) {
550                // On passe le plugin appelant à la fonction car cela permet ainsi de mutualiser les services de stockage.
551                $retour = $destocker($plugin, $description);
552        } else {
553                // Le plugin ne propose pas de fonction propre ou le stockage N-Core est explicitement demandé.
554                // -- N-Core stocke les noisettes dans une meta propre au plugin appelant contenant un tableau au format
555                //    [conteneur][rang] = description
556                // -- $description est soit le tableau descriptif de la noisette, soit le conteneur, et dans ce cas, il faut
557                //    supprimer toutes les noisettes du conteneur.
558
559                // Initialisation de la sortie.
560                $retour = false;
561
562                include_spip('inc/config');
563                $meta_noisettes = lire_config("${plugin}_noisettes", array());
564
565                if (isset($meta_noisettes[$description['id_conteneur']][$description['rang_noisette']])) {
566                        // On supprime une noisette donnée.
567                        unset($meta_noisettes[$description['id_conteneur']][$description['rang_noisette']]);
568                        // Si c'est la dernière noisette du conteneur il faut aussi supprimer l'index correspondant au conteneur.
569                        if (!$meta_noisettes[$description['id_conteneur']]) {
570                                unset($meta_noisettes[$description['id_conteneur']]);
571                        }
572                        ecrire_config("${plugin}_noisettes", $meta_noisettes);
573                        $retour = true;
574                }
575        }
576
577        return $retour;
578}
579
580
581/**
582 * Renvoie un champ ou toute la description des noisettes d'un conteneur ou de tous les conteneurs.
583 * Le tableau retourné est indexé soit par identifiant de noisette soit par identifiant du conteneur et rang
584 * de noisette.
585 *
586 * @package SPIP\NCORE\NOISETTE\SERVICE
587 *
588 * @uses ncore_chercher_service()
589 * @uses ncore_conteneur_identifier()
590 *
591 * @param string $plugin
592 *        Identifiant qui permet de distinguer le module appelant qui peut-être un plugin comme le noiZetier ou
593 *        un script. Pour un plugin, le plus pertinent est d'utiliser le préfixe.
594 * @param array|string $conteneur
595 *        Tableau descriptif du conteneur ou identifiant du conteneur ou vide si on souhaite adresser tous les
596 *        conteneurs.
597 * @param string $information
598 *        Identifiant d'un champ de la description d'une noisette.
599 *        Si l'argument est vide, la fonction renvoie les descriptions complètes et si l'argument est
600 *        un champ invalide la fonction renvoie un tableau vide.
601 * @param string $cle
602 *        Champ de la description d'une noisette servant d'index du tableau. En général on utilisera soit `id_noisette`
603 *        soit `rang_noisette`.
604 * @param string $stockage
605 *        Identifiant du service de stockage à utiliser si précisé.
606 *
607 * @return array
608 *        Tableau de la liste des informations demandées indexé par identifiant de noisette ou par rang.
609 */
610function ncore_noisette_lister($plugin, $conteneur = array(), $information = '', $cle = 'rang_noisette', $stockage = '') {
611
612        // On cherche le service de stockage à utiliser selon la logique suivante :
613        // - si le service de stockage est non vide on l'utilise en considérant que la fonction existe forcément;
614        // - sinon, on utilise la fonction du plugin appelant si elle existe;
615        // - et sinon, on utilise la fonction de N-Core.
616        include_spip('inc/ncore_utils');
617        if ($lister = ncore_chercher_service($plugin, 'noisette_lister', $stockage)) {
618                // On passe le plugin appelant à la fonction car cela permet ainsi de mutualiser les services de stockage.
619                $noisettes = $lister($plugin, $conteneur, $information, $cle);
620        } else {
621                // Le plugin ne propose pas de fonction propre ou le stockage N-Core est explicitement demandé.
622                // -- N-Core stocke les noisettes dans une meta propre au plugin appelant contenant un tableau au format
623                //    [conteneur][rang] = description
624
625                // Initialisation du tableau de sortie.
626                $noisettes = array();
627
628                include_spip('inc/config');
629                $meta_noisettes = lire_config("${plugin}_noisettes", array());
630
631                if ($conteneur) {
632                        // On détermine l'id du conteneur en fonction du mode d'identification du conteneur lors de l'appel.
633                        if (is_array($conteneur)) {
634                                $id_conteneur = ncore_conteneur_identifier($plugin, $conteneur, $stockage);
635                        } else {
636                                $id_conteneur = $conteneur;
637                        }
638                        if (!empty($meta_noisettes[$id_conteneur])) {
639                                $noisettes = $meta_noisettes[$id_conteneur];
640                                $noisettes = $information
641                                        ? array_column($noisettes, $information, $cle)
642                                        : array_column($noisettes, null, $cle);
643                        }
644                } elseif ($meta_noisettes) {
645                        if ($cle == 'rang_noisette') {
646                                $noisettes = $meta_noisettes;
647                        } else {
648                                foreach ($meta_noisettes as $_squelette => $_descriptions) {
649                                        $noisettes_squelette = $information
650                                                ? array_column($_descriptions, $information, $cle)
651                                                : array_column($_descriptions, null, $cle);
652                                        $noisettes = array_merge($noisettes, $noisettes_squelette);
653                                }
654                        }
655                }
656        }
657
658        return $noisettes;
659}
660
661
662/**
663 * Renvoie la description brute d'une noisette sans traitement typo des champs textuels ni désérialisation
664 * des champs de type tableau sérialisé.
665 *
666 * @package SPIP\NCORE\NOISETTE\SERVICE
667 *
668 * @uses ncore_chercher_service()
669 *
670 * @param string $plugin
671 *        Identifiant qui permet de distinguer le module appelant qui peut-être un plugin comme le noiZetier ou
672 *        un script. Pour un plugin, le plus pertinent est d'utiliser le préfixe.
673 * @param mixed  $noisette
674 *        Identifiant de la noisette qui peut prendre soit la forme d'un entier ou d'une chaine unique, soit la forme
675 *        d'un couple (conteneur, rang de noisette).
676 * @param string $stockage
677 *        Identifiant du service de stockage à utiliser si précisé.
678 *
679 * @return array
680 *        Tableau de la description du type de noisette. Les champs textuels et les champs de type tableau sérialisé
681 *        sont retournés en l'état.
682 */
683function ncore_noisette_decrire($plugin, $noisette, $stockage = '') {
684
685        // On cherche le service de stockage à utiliser selon la logique suivante :
686        // - si le service de stockage est non vide on l'utilise en considérant que la fonction existe forcément;
687        // - sinon, on utilise la fonction du plugin appelant si elle existe;
688        // - et sinon, on utilise la fonction de N-Core.
689        include_spip('inc/ncore_utils');
690        if ($decrire = ncore_chercher_service($plugin, 'noisette_decrire', $stockage)) {
691                // On passe le plugin appelant à la fonction car cela permet ainsi de mutualiser les services de stockage.
692                $description = $decrire($plugin, $noisette);
693        } else {
694                // Le plugin ne propose pas de fonction propre ou le stockage N-Core est explicitement demandé.
695                // -- N-Core stocke les noisettes dans une meta propre au plugin appelant contenant un tableau au format
696                //    [conteneur][rang] = description
697
698                // Initialisation de la description à retourner.
699                $description = array();
700
701                include_spip('inc/config');
702                $meta_noisettes = lire_config("${plugin}_noisettes", array());
703
704                // On recherche la description dans la meta.
705                if ($meta_noisettes) {
706                        if (!is_array($noisette)) {
707                                // L'identifiant est l'id unique de la noisette. Il faut donc parcourir le tableau pour trouver la
708                                // noisette désirée
709                                // => ce n'est pas la méthode optimale pour le stockage N-Core.
710                                $noisette_trouvee = false;
711                                foreach ($meta_noisettes as $_noisettes_squelette) {
712                                        foreach ($_noisettes_squelette as $_noisette) {
713                                                if ($_noisette['id_noisette'] == $noisette) {
714                                                        $description = $_noisette;
715                                                        $noisette_trouvee = true;
716                                                        break;
717                                                }
718                                        }
719                                        if ($noisette_trouvee) {
720                                                break;
721                                        }
722                                }
723                        } else {
724                                if (isset($noisette['id_conteneur'], $noisette['rang_noisette'])) {
725                                        // Détermination de l'identifiant du conteneur.
726                                        $id_conteneur = $noisette['id_conteneur'];
727                                        if (!empty($meta_noisettes[$id_conteneur][$noisette['rang_noisette']])) {
728                                        // L'identifiant est un tableau associatif fournissant le conteneur et le rang.
729                                        // Comme la meta de N-Core est structurée ainsi c'est la méthode la plus adaptée pour adresser
730                                        // le stockage de N-Core.
731                                        $description = $meta_noisettes[$id_conteneur][$noisette['rang_noisette']];
732                                        }
733                                }
734                        }
735                }
736        }
737
738        return $description;
739}
740
741/**
742 * Renvoie la configuration par défaut de l'encapsulation d'une noisette.
743 * Cette information est utilisée si le champ `encapsulation` de la noisette vaut `defaut`.
744 *
745 * Le service N-Core positionne cette valeur à `true`.
746 *
747 * @package SPIP\NCORE\NOISETTE\SERVICE
748 *
749 * @uses ncore_chercher_service()
750 *
751 * @param string $plugin
752 *        Identifiant qui permet de distinguer le module appelant qui peut-être un plugin comme le noiZetier ou
753 *        un script. Pour un plugin, le plus pertinent est d'utiliser le préfixe.
754 *
755 * @return bool
756 *              `true` si par défaut une noisette est encapsulée, `false` sinon.
757 */
758function ncore_noisette_initialiser_encapsulation($plugin) {
759
760        // On cherche le service de stockage à utiliser selon la logique suivante :
761        // - si le service de stockage est non vide on l'utilise en considérant que la fonction existe forcément;
762        // - sinon, on utilise la fonction du plugin appelant si elle existe;
763        // - et sinon, on utilise la fonction de N-Core.
764        include_spip('inc/ncore_utils');
765        if ($configurer = ncore_chercher_service($plugin, 'noisette_initialiser_encapsulation', '')) {
766                // On passe le plugin appelant à la fonction car cela permet ainsi de mutualiser les services de stockage.
767                // On autorise la fonction du plugin à retourner autre chose que true ou false si tant est que l'on puisse
768                // en déduire un booléen (par exemple, 'on' et '' comme le retourne une case à cocher du plugin Saisies).
769                $defaut_capsule = $configurer($plugin) ? true : false;
770        } else {
771                // Le service ne propose pas de fonction propre, on utilise celle de N-Core.
772                $defaut_capsule = true;
773        }
774
775        return $defaut_capsule;
776}
777
778
779// -----------------------------------------------------------------------
780// ----------------------------- CONTENEURS ------------------------------
781// -----------------------------------------------------------------------
782
783/**
784 * Vérifie la conformité des index du tableau représentant le conteneur et supprime les index inutiles, si besoin.
785 * N-Core vérifie que pour les noisettes conteneur les seuls index sont le type et l'id de la noisette.
786 * Pour les autres conteneurs, c'est au plugin utilisateur de vérifier le conteneur.
787 *
788 * @package SPIP\NCORE\CONTENEUR\SERVICE
789 *
790 * @uses ncore_chercher_service()
791 *
792 * @param string $plugin
793 *        Identifiant qui permet de distinguer le module appelant qui peut-être un plugin comme le noiZetier ou
794 *        un script. Pour un plugin, le plus pertinent est d'utiliser le préfixe.
795 * @param array  $conteneur
796 *        Tableau associatif descriptif du conteneur dont les index doivent être vérifiés.
797 * @param string $stockage
798 *        Identifiant du service de stockage à utiliser si précisé.
799 *
800 * @return array
801 *        Tableau du conteneur dont tous les index sont conformes ou tableau vide si non conforme.
802 */
803function ncore_conteneur_verifier($plugin, $conteneur, $stockage = '') {
804
805        static $index_conteneur_noisette = array('type_noisette', 'id_noisette');
806
807        // N-Core ne vérifie pas les conteneurs spécifiques aux plugins utilisateur
808        // sauf pour les noisettes conteneur qui ne sont déterminées que par leur type et leur id.
809        // Il est donc indispensable que le plugin utilisateur propose toujours une fonction de vérification
810        // pour les conteneurs hors noisette conteneur.
811        $conteneur_verifie = array();
812        if ($conteneur) {
813                if (isset($conteneur['type_noisette'], $conteneur['id_noisette'])
814                and $conteneur['type_noisette']
815                and intval($conteneur['id_noisette'])) {
816                        // Le conteneur est une noisette, N-Core effectue le filtre des index.
817                        $conteneur = array_intersect_key($conteneur, array_flip($index_conteneur_noisette));
818                        if (count($conteneur) == 2) {
819                                $conteneur_verifie = $conteneur;
820                        }
821                } else {
822                        // Le conteneur est spécifique au plugin utilisateur, c'est donc au plugin faire la vérification des index.
823                        include_spip('inc/ncore_utils');
824                        if ($verifier = ncore_chercher_service($plugin, 'conteneur_verifier', $stockage)) {
825                                $conteneur_verifie = $verifier($plugin, $conteneur);
826                        }
827                }
828        }
829
830        return $conteneur_verifie;
831}
832
833/**
834 * Construit un identifiant unique pour le conteneur sous forme de chaine.
835 * N-Core ne fournit d'identifiant que pour les noisettes conteneur.
836 * Pour les autres conteneurs, c'est au plugin utilisateur de calculer l'identifiant.
837 *
838 * @package SPIP\NCORE\CONTENEUR\SERVICE
839 *
840 * @uses ncore_chercher_service()
841 *
842 * @param string $plugin
843 *        Identifiant qui permet de distinguer le module appelant qui peut-être un plugin comme le noiZetier ou
844 *        un script. Pour un plugin, le plus pertinent est d'utiliser le préfixe.
845 * @param array  $conteneur
846 *        Tableau associatif descriptif du conteneur. Les index sont spécifiques à l'utilisation qui en est faite
847 *        par le plugin utilisateur. Néanmoins, pour une noisette conteneur, le tableau est limité aux index
848 *        type de noisette et id de noisette.
849 * @param string $stockage
850 *        Identifiant du service de stockage à utiliser si précisé.
851 *
852 * @return string
853 *        Identifiant du conteneur ou chaine vide en cas d'erreur.
854 */
855function ncore_conteneur_identifier($plugin, $conteneur, $stockage = '') {
856
857        // Il faut calculer l'identifiant du conteneur pour accéder à la bonne liste de noisettes.
858        // N-Core ne propose pas de fonction par défaut pour les conteneurs spécifiques aux plugins utilisateur
859        // sauf pour les noisettes conteneur car elles ne sont déterminées que par leur type et leur id.
860        // Il est donc indispensable que le plugin utilisateur propose toujours une fonction de calcul de l'identifiant
861        // pour les conteneurs hors noisette conteneur.
862        $id_conteneur = '';
863        if ($conteneur) {
864                if (isset($conteneur['type_noisette'], $conteneur['id_noisette'])
865                and $conteneur['type_noisette']
866                and intval($conteneur['id_noisette'])) {
867                        // Le conteneur est une noisette, N-Core effectue le calcul de l'id.
868                        $id_conteneur = $conteneur['type_noisette'] . '|noisette|' . $conteneur['id_noisette'];
869                } else {
870                        // Le conteneur est spécifique au plugin utilisateur, c'est donc au plugin de le calculer.
871                        include_spip('inc/ncore_utils');
872                        if ($identifier = ncore_chercher_service($plugin, 'conteneur_identifier', $stockage)) {
873                                $id_conteneur = $identifier($plugin, $conteneur);
874                        }
875                }
876        }
877
878        return $id_conteneur;
879}
880
881/**
882 * Retire, de l'espace de stockage, toutes les noisettes d'un conteneur et ce de façon récursive si
883 * il existe une imbrication de conteneurs.
884 *
885 * @package SPIP\NCORE\CONTENEUR\SERVICE
886 *
887 * @uses ncore_chercher_service()
888 * @uses ncore_noisette_lister()
889 * @uses ncore_conteneur_identifier()
890 *
891 * @param string       $plugin
892 *        Identifiant qui permet de distinguer le module appelant qui peut-être un plugin comme le noiZetier ou
893 *        un script. Pour un plugin, le plus pertinent est d'utiliser le préfixe.
894 * @param array|string $conteneur
895 *        Tableau descriptif du conteneur ou identifiant du conteneur.
896 * @param string       $stockage
897 *        Identifiant du service de stockage à utiliser si précisé.
898 *
899 * @return bool
900 *        `true` si le traitement s'est bien déroulé, `false` sinon.
901 */
902function ncore_conteneur_destocker($plugin, $conteneur, $stockage = '') {
903
904        // Initialisation de la sortie.
905        $retour = false;
906
907        // On liste les noisettes du conteneur concerné et on repère les noisettes conteneur.
908        // Chaque conteneur imbriqué est vidé et ce de façon récursive.
909        foreach (ncore_noisette_lister($plugin, $conteneur, '', 'rang_noisette', $stockage) as $_noisette) {
910                if ($_noisette['est_conteneur'] == 'oui') {
911                        // On vide récursivement les noisettes de type conteneur.
912                        ncore_conteneur_destocker($plugin, $_noisette, $stockage);
913                }
914        }
915
916        // On cherche le service de stockage à utiliser selon la logique suivante :
917        // - si le service de stockage est non vide on l'utilise en considérant que la fonction existe forcément;
918        // - sinon, on utilise la fonction du plugin appelant si elle existe;
919        // - et sinon, on utilise la fonction de N-Core.
920        include_spip('inc/ncore_utils');
921        if ($destocker = ncore_chercher_service($plugin, 'conteneur_destocker', $stockage)) {
922                // On passe le plugin appelant à la fonction car cela permet ainsi de mutualiser les services de stockage.
923                $retour = $destocker($plugin, $conteneur);
924        } else {
925                // Le plugin ne propose pas de fonction propre ou le stockage N-Core est explicitement demandé.
926                // -- N-Core stocke les noisettes dans une meta propre au plugin appelant contenant un tableau au format
927                //    [conteneur][rang] = description
928                include_spip('inc/config');
929                $meta_noisettes = lire_config("${plugin}_noisettes", array());
930
931                // On détermine l'id du conteneur en fonction du mode d'identification du conteneur lors de l'appel.
932                if (is_array($conteneur)) {
933                        $id_conteneur = ncore_conteneur_identifier($plugin, $conteneur, $stockage);
934                } else {
935                        $id_conteneur = $conteneur;
936                }
937
938                if (isset($meta_noisettes[$id_conteneur])) {
939                        // On supprime toutes les noisettes du conteneur.
940                        unset($meta_noisettes[$id_conteneur]);
941                        ecrire_config("${plugin}_noisettes", $meta_noisettes);
942                        $retour = true;
943                }
944        }
945
946        return $retour;
947}
Note: See TracBrowser for help on using the repository browser.