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

Last change on this file since 110211 was 110211, checked in by eric@…, 2 years ago

Le tag indiquant que le type de noisette est un conteneur s'appelle conteneur pas est_conteneur.

  • Property svn:eol-style set to native
File size: 19.7 KB
Line 
1<?php
2/**
3 * Ce fichier contient l'API N-Core de gestion des noisettes, c'est-à-dire les instances paramétrées
4 * de types de noisette affectées à un conteneur.
5 *
6 * @package SPIP\NCORE\NOISETTE\API
7 */
8if (!defined('_ECRIRE_INC_VERSION')) {
9        return;
10}
11
12
13/**
14 * Ajoute dans un conteneur, à un rang donné ou en dernier rang, une noisette d'un type donné.
15 * La fonction met à jour les rangs des autres noisettes si nécessaire.
16 *
17 * @api
18 * @uses type_noisette_lire()
19 * @uses ncore_noisette_completer()
20 * @uses ncore_noisette_lister()
21 * @uses ncore_noisette_stocker()
22 * @uses ncore_noisette_ranger()
23 *
24 * @param string $plugin
25 *        Identifiant qui permet de distinguer le module appelant qui peut-être un plugin comme le noiZetier ou
26 *        un script. Pour un plugin, le plus pertinent est d'utiliser le préfixe.
27 * @param string $type_noisette
28 *        Identifiant du type de noisette à ajouter au squelette.
29 * @param array  $conteneur
30 *        Tableau associatif descriptif du conteneur accueillant la noisette. Un conteneur peut-être un squelette seul
31 *        ou associé à un contexte d'utilisation et dans ce cas il possède un index `squelette` ou un objet quelconque
32 *        sans lien avec un squelette. Dans tous les cas, les index, à l'exception de `squelette`, sont spécifiques
33 *        à l'utilisation qui en est faite par le plugin.
34 * @param int    $rang
35 *        Rang dans le squelette contextualisé où insérer la noisette. Si l'argument n'est pas fourni ou est égal à 0
36 *        on insère la noisette en fin de bloc.
37 * @param string $stockage
38 *        Identifiant du service de stockage à utiliser si précisé. Dans ce cas, ni celui du plugin
39 *        ni celui de N-Core ne seront utilisés. En général, cet identifiant est le préfixe d'un plugin
40 *        fournissant le service de stockage souhaité.
41 *
42 * @return int|string|bool
43 *        Retourne l'identifiant de la nouvelle instance de noisette créée ou `false` en cas d'erreur.
44 **/
45function noisette_ajouter($plugin, $type_noisette, $conteneur, $rang = 0, $stockage = '') {
46
47        // Initialisation de la valeur de sortie.
48        $noisette_ajoutee = false;
49
50        if ($type_noisette) {
51                // On récupère les paramètres du type de noisette.
52                include_spip('inc/ncore_type_noisette');
53                $champs = type_noisette_lire(
54                        $plugin,
55                        $type_noisette,
56                        'parametres',
57                        false,
58                        $stockage
59                );
60
61                // Et on leur associe des valeurs par défaut.
62                include_spip('inc/saisies');
63                $parametres = saisies_lister_valeurs_defaut($champs);
64
65                // On charge les services de N-Core.
66                // Ce sont ces fonctions qui aiguillent ou pas vers un service spécifique du plugin.
67                include_spip('ncore/ncore');
68
69                // On initialise la description de la noisette à ajouter et en particulier on stocke l'id du conteneur
70                // pour simplifier les traitements par la suite.
71                $description = array(
72                        'plugin'        => $plugin,
73                        'type_noisette' => $type_noisette,
74                        'conteneur'     => serialize($conteneur),
75                        'id_conteneur'  => ncore_conteneur_identifier($plugin, $conteneur, $stockage),
76                        'rang_noisette' => intval($rang),
77                        'est_conteneur' => type_noisette_lire($plugin, $type_noisette, 'conteneur', false, $stockage),
78                        'parametres'    => serialize($parametres),
79                        'balise'        => 'defaut',
80                        'css'           => ''
81                );
82
83                // Mise à jour de la description pour les noisettes conteneur:
84                // -- pas de div englobante.
85                if ($description['est_conteneur'] == 'oui') {
86                        $description['balise'] = 'non';
87                }
88
89                // Complément à la description par défaut, spécifique au plugin utilisateur, si nécessaire.
90                $description = ncore_noisette_completer($plugin, $description, $stockage);
91
92                // On récupère les noisettes déjà affectées au conteneur sous la forme d'un tableau indexé
93                // par le rang de chaque noisette.
94                $noisettes = ncore_noisette_lister($plugin, $conteneur, '', 'rang_noisette', $stockage);
95
96                // On calcule le rang max déjà utilisé.
97                $rang_max = $noisettes ? max(array_keys($noisettes)) : 0;
98
99                if (!$rang or ($rang and ($rang > $rang_max))) {
100                        // Si, le rang est nul ou si il est strictement supérieur au rang_max, on positionne la noisette
101                        // à ajouter au rang max + 1.
102                        // En effet, si le rang est supérieur au rang max c'est que la nouvelle noisette est ajoutée
103                        // après les noisettes existantes, donc cela revient à insérer la noisette en fin de liste.
104                        // Postionner le rang à max + 1 permet d'éviter d'avoir des trous dans la liste des rangs.
105                        $description['rang_noisette'] = $rang_max + 1;
106                } else {
107                        // Si le rang est non nul et inférieur ou égal au rang max c'est qu'on insère la noisette dans la liste
108                        // existante : il faut décaler d'un rang les noisettes de rang supérieur ou égal si elle existent pour
109                        // libérer la position de la nouvelle noisette.
110                        if ($rang <= $rang_max) {
111                                krsort($noisettes);
112                                foreach ($noisettes as $_rang => $_description) {
113                                        if ($_rang >= $rang) {
114                                                ncore_noisette_ranger($plugin, $_description, $_rang + 1, $stockage);
115                                        }
116                                }
117                        }
118                }
119
120                // La description de la nouvelle noisette est prête à être stockée à sa position.
121                $noisette_ajoutee = ncore_noisette_stocker($plugin, $description, $stockage);
122        }
123
124        return $noisette_ajoutee;
125}
126
127/**
128 * Supprime une noisette donnée du conteneur auquel elle est associée et, si cette noisette est un conteneur,
129 * le vide de ses noisettes au préalable.
130 * La fonction met à jour les rangs des autres noisettes si nécessaire.
131 *
132 * @api
133 * @uses ncore_noisette_decrire()
134 * @uses ncore_noisette_destocker()
135 * @uses ncore_noisette_lister()
136 * @uses ncore_noisette_ranger()
137 *
138 * @param string $plugin
139 *        Identifiant qui permet de distinguer le module appelant qui peut-être un plugin comme le noiZetier ou
140 *        un script. Pour un plugin, le plus pertinent est d'utiliser le préfixe.
141 * @param mixed  $noisette
142 *        Identifiant de la noisette qui peut prendre soit la forme d'un entier ou d'une chaine unique, soit la forme
143 *        d'un couple (id conteneur, rang).
144 * @param string $stockage
145 *        Identifiant du service de stockage à utiliser si précisé. Dans ce cas, ni celui du plugin
146 *        ni celui de N-Core ne seront utilisés. En général, cet identifiant est le préfixe d'un plugin
147 *        fournissant le service de stockage souhaité.
148 *
149 * @return bool
150 */
151function noisette_supprimer($plugin, $noisette, $stockage = '') {
152
153        // Initialisation du retour
154        $retour = false;
155
156        // On charge les services de N-Core.
157        // Ce sont ces fonctions qui aiguillent ou pas vers un service spécifique du plugin.
158        include_spip('ncore/ncore');
159
160        // L'identifiant d'une noisette peut être fourni de deux façons :
161        // - par une valeur unique, celle créée lors de l'ajout et qui peut-être un entier (id d'une table SPIP) ou
162        //   une chaine unique par exemple générée par uniqid().
163        // - ou par un tableau à deux entrées fournissant le conteneur et le rang dans le conteneur
164        //   (qui est unique pour un conteneur donné).
165        if (!empty($noisette) and (is_string($noisette) or is_numeric($noisette) or is_array($noisette))) {
166                // Avant de supprimer la noisette on sauvegarde sa description.
167                // Cela permet de conserver le rang et l'id du conteneur indépendamment de l'identifiant
168                // utilisé pour spécifier la noisette.
169                $description = ncore_noisette_decrire($plugin, $noisette, $stockage);
170
171                // Si la noisette est de type conteneur, il faut vider le conteneur des éventuelles noisettes
172                // incluses avant de supprimer la noisette elle-même.
173                if ($description['est_conteneur'] == 'oui') {
174                        // Inutile de redéfinir un conteneur car la description de la noisette contient les deux champs
175                        // essentiels, à savoir, type_noisette et id_noisette.
176                        ncore_conteneur_destocker($plugin, $description, $stockage);
177                }
178
179                // Suppression de la noisette. On passe la description complète ce qui permet à la fonction de
180                // destockage de choisir la méthode d'identification la plus adaptée.
181                $retour = ncore_noisette_destocker($plugin, $description, $stockage);
182
183                // On récupère les noisettes restant affectées au conteneur sous la forme d'un tableau indexé par rang.
184                $autres_noisettes = ncore_noisette_lister(
185                        $plugin,
186                        $description['id_conteneur'],
187                        '',
188                        'rang_noisette',
189                        $stockage
190                );
191
192                // Si il reste des noisettes, on tasse d'un rang les noisettes qui suivaient la noisette supprimée.
193                if ($autres_noisettes) {
194                        // On lit les noisettes restantes dans l'ordre décroissant pour éviter d'écraser une noisette.
195                        ksort($autres_noisettes);
196                        foreach ($autres_noisettes as $_rang => $_autre_description) {
197                                if ($_rang > $description['rang_noisette']) {
198                                        ncore_noisette_ranger($plugin, $_autre_description, $_autre_description['rang_noisette'] - 1, $stockage);
199                                }
200                        }
201                }
202        }
203
204        return $retour;
205}
206
207/**
208 * Retourne, pour une noisette donnée, la description complète ou seulement un champ précis.
209 * Les champs textuels peuvent subir un traitement typo si demandé.
210 *
211 * @api
212 * @uses ncore_noisette_decrire()
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 mixed   $noisette
218 *        Identifiant de la noisette qui peut prendre soit la forme d'un entier ou d'une chaine unique, soit la forme
219 *        d'un couple (id conteneur, rang).
220 * @param string  $information
221 *        Information spécifique à retourner ou vide pour retourner toute la description.
222 * @param boolean $traiter_typo
223 *        Indique si les données textuelles doivent être retournées brutes ou si elles doivent être traitées
224 *        en utilisant la fonction _T_ou_typo. Par défaut l'indicateur vaut `false`.
225 *        Les champs sérialisés sont eux toujours désérialisés.
226 *        Pour l'instant il n'y a pas de champ textuel directement associé à une noisette.
227 * @param string  $stockage
228 *        Identifiant du service de stockage à utiliser si précisé. Dans ce cas, ni celui du plugin
229 *        ni celui de N-Core ne seront utilisés. En général, cet identifiant est le préfixe d'un plugin
230 *        fournissant le service de stockage souhaité.
231 *
232 * @return bool
233 */
234function noisette_lire($plugin, $noisette, $information = '', $traiter_typo = false, $stockage = '') {
235
236        // On indexe le tableau des descriptions par le plugin appelant en cas d'appel sur le même hit
237        // par deux plugins différents.
238        // En outre, on gère un tableau par type d'identification, id noisette ou couple (id conteneur, rang).
239        static $description_noisette_par_id = array();
240        static $description_noisette_par_rang = array();
241
242        // Initialisation de la description en sortie.
243        $retour = array();
244
245        if (!empty($noisette) and (is_string($noisette) or is_numeric($noisette) or is_array($noisette))) {
246                // On charge les services de N-Core.
247                // Ce sont ces fonctions qui aiguillent ou pas vers un service spécifique du plugin.
248                include_spip('ncore/ncore');
249
250                // On vérifie si la noisette est valide et si la description n'a pas déjà été enregistrée dans le tableau adéquat.
251                $description_existe = false;
252                $noisette_invalide = false;
253                if (!is_array($noisette)) {
254                        $description_existe = isset($description_noisette_par_id[$plugin][$noisette]) ? true : false;
255                } elseif (isset($noisette['id_conteneur'], $noisette['rang_noisette'])) {
256                        $description_existe = isset($description_noisette_par_rang[$plugin][$noisette['id_conteneur']][$noisette['rang_noisette']])
257                                ? true
258                                : false;
259                } else {
260                        $noisette_invalide = true;
261                }
262
263                if (!$noisette_invalide) {
264                        if (!$description_existe) {
265                                // Lecture de toute la configuration de la noisette: les données retournées sont brutes.
266                                $description = ncore_noisette_decrire($plugin, $noisette, $stockage);
267
268                                // Traitements des champs tableaux sérialisés si nécessaire
269                                if ($description) {
270                                        if (isset($description['parametres']) and is_string($description['parametres'])) {
271                                                $description['parametres'] = unserialize($description['parametres']);
272                                        }
273                                        if (isset($description['conteneur']) and is_string($description['conteneur'])) {
274                                                $description['conteneur'] = unserialize($description['conteneur']);
275                                        }
276                                }
277
278                                // Sauvegarde de la description de la noisette pour une consultation ultérieure dans le même hit
279                                // en suivant le type d'identification.
280                                if (!is_array($noisette)) {
281                                        $description_noisette_par_id[$plugin][$noisette] = $description;
282                                } else {
283                                        $description_noisette_par_rang[$plugin][$noisette['id_conteneur']][$noisette['rang_noisette']] = $description;
284                                }
285                        }
286
287                        if ($information) {
288                                if ((!is_array($noisette) and isset($description_noisette_par_id[$plugin][$noisette][$information]))
289                                        or (is_array($noisette)
290                                                and isset($description_noisette_par_rang[$plugin][$noisette['id_conteneur']][$noisette['rang_noisette']][$information]))) {
291                                        $retour = is_array($noisette)
292                                                ? $description_noisette_par_rang[$plugin][$noisette['id_conteneur']][$noisette['rang_noisette']][$information]
293                                                : $description_noisette_par_id[$plugin][$noisette][$information];
294                                } else {
295                                        $retour = '';
296                                }
297                        } else {
298                                $retour = is_array($noisette)
299                                        ? $description_noisette_par_rang[$plugin][$noisette['id_conteneur']][$noisette['rang_noisette']]
300                                        : $description_noisette_par_id[$plugin][$noisette];
301                        }
302                }
303        }
304
305        return $retour;
306}
307
308/**
309 * Déplace une noisette donnée au sein d’un conteneur.
310 * La fonction met à jour les rangs des autres noisettes si nécessaire.
311 *
312 * @api
313 * @uses ncore_noisette_decrire()
314 * @uses ncore_noisette_lister()
315 * @uses ncore_noisette_ranger()
316 *
317 * @param string $plugin
318 *        Identifiant qui permet de distinguer le module appelant qui peut-être un plugin comme le noiZetier ou
319 *        un script. Pour un plugin, le plus pertinent est d'utiliser le préfixe.
320 * @param mixed  $noisette
321 *        Identifiant de la noisette qui peut prendre soit la forme d'un entier ou d'une chaine unique, soit la forme
322 *        d'un couple (id conteneur, rang).
323 * @param int    $rang_destination
324 *        Entier représentant le rang où repositionner la noisette dans le squelette contextualisé.
325 * @param string $stockage
326 *        Identifiant du service de stockage à utiliser si précisé. Dans ce cas, ni celui du plugin
327 *        ni celui de N-Core ne seront utilisés. En général, cet identifiant est le préfixe d'un plugin
328 *        fournissant le service de stockage souhaité.
329 *
330 * @return bool
331 */
332function noisette_deplacer($plugin, $noisette, $rang_destination, $stockage = '') {
333
334        // Initialisation du retour
335        $retour = false;
336
337        // On charge les services de N-Core.
338        // Ce sont ces fonctions qui aiguillent ou pas vers un service spécifique du plugin.
339        include_spip('ncore/ncore');
340
341        // L'identifiant d'une noisette peut être fourni de deux façons :
342        // - par une valeur unique, celle créée lors de l'ajout et qui peut-être un entier (id d'une table SPIP) ou
343        //   une chaine unique par exemple générée par uniqid().
344        // - ou par un tableau à deux entrées fournissant le conteneur et le rang
345        //   (qui est unique pour un conteneur donné).
346        if (!empty($noisette) and (is_string($noisette) or is_numeric($noisette) or is_array($noisette))) {
347                // Avant de deplacer la noisette on sauvegarde sa description et son rang origine.
348                $description = ncore_noisette_decrire($plugin, $noisette, $stockage);
349                $rang_origine = $description['rang_noisette'];
350
351                // Si les rangs origine et destination sont identiques on ne fait rien !
352                if ($rang_destination != $rang_origine) {
353                        // On récupère les noisettes affectées au même conteneur sous la forme d'un tableau indexé par le rang.
354                        $noisettes = ncore_noisette_lister(
355                                $plugin,
356                                $description['id_conteneur'],
357                                '',
358                                'rang_noisette',
359                                $stockage
360                        );
361
362                        // On vérifie que le rang destination est bien compris entre 1 et le rang max, sinon on le force à l'une
363                        // des bornes.
364                        $rang_destination = max(1, $rang_destination);
365                        $rang_max = $noisettes ? max(array_keys($noisettes)) : 0;
366                        $rang_destination = min($rang_max, $rang_destination);
367
368                        // Suivant la position d'origine et de destination de la noisette déplacée on trie les noisettes
369                        // du conteneur.
370                        if ($rang_destination < $rang_origine) {
371                                krsort($noisettes);
372                        } else {
373                                ksort($noisettes);
374                        }
375
376                        // On déplace les noisettes impactées à l'exception de la noisette concernée par le déplacement
377                        // afin de créer une position libre.
378                        foreach ($noisettes as $_rang => $_description) {
379                                if ($rang_destination < $rang_origine) {
380                                        // On "descend" les noisettes du rang destination au rang origine non compris.
381                                        if (($_rang >= $rang_destination) and ($_rang < $rang_origine)) {
382                                                ncore_noisette_ranger($plugin, $_description, $_rang + 1, $stockage);
383                                        }
384                                } else {
385                                        // On "remonte" les noisettes du rang destination au rang origine non compris.
386                                        if (($_rang <= $rang_destination) and ($_rang > $rang_origine)) {
387                                                ncore_noisette_ranger($plugin, $_description, $_rang - 1, $stockage);
388                                        }
389                                }
390                        }
391
392                        // On positionne le rang de la noisette à déplacer au rang destination.
393                        // On met le rang à zéro pour indiquer que l'emplacement d'origine n'est plus occupé par la
394                        // noisette et qu'il ne faut pas le supprimer lors du rangement.
395                        $description['rang_noisette'] = 0;
396                        ncore_noisette_ranger($plugin, $description, $rang_destination, $stockage);
397                }
398        }
399
400        return $retour;
401}
402
403/**
404 * Renvoie une liste de descriptions de noisettes appartenant à un conteneur donné ou pas et éventuellement filtrée
405 * sur certains champs.
406 * Le tableau retourné est indexé soit par identifiant de noisette soit par identifiant du conteneur et rang.
407 *
408 * @api
409 * @uses ncore_noisette_lister()
410 *
411 * @param string $plugin
412 *        Identifiant qui permet de distinguer le module appelant qui peut-être un plugin comme le noiZetier
413 *        ou un script. Pour un plugin, le plus pertinent est d'utiliser le préfixe.
414 * @param array|string $conteneur
415 *        Tableau descriptif du conteneur ou identifiant du conteneur ou vide si on souhaite adresser tous les
416 *        conteneurs.
417 * @param string $cle
418 *        Champ de la description d'une noisette servant d'index du tableau. En général on utilisera soit `id_noisette`
419 *        soit `rang`.
420 * @param array  $filtres
421 *        Tableau associatif `[champ] = valeur` de critères de filtres sur les descriptions de types de noisette.
422 *        Le seul opérateur possible est l'égalité.
423 * @param string $stockage
424 *        Identifiant du service de stockage à utiliser si précisé. Dans ce cas, ni celui du plugin
425 *        ni celui de N-Core ne seront utilisés. En général, cet identifiant est le préfixe d'un plugin
426 *        fournissant le service de stockage souhaité.
427 *
428 * @return array
429 *        Tableau des descriptions des types de noisette trouvés indexé par le type de noisette.
430 */
431function noisette_repertorier($plugin, $conteneur, $cle = 'rang_noisette', $filtres = array(), $stockage = '') {
432
433        // On indexe le tableau des noisettes par le plugin appelant en cas d'appel sur le même hit
434        // par deux plugins différents.
435        static $noisettes = array();
436
437        if (!isset($noisettes[$plugin])) {
438                // On charge l'API de N-Core.
439                // Ce sont ces fonctions qui aiguillent ou pas vers une fonction spécifique du service.
440                include_spip("ncore/ncore");
441
442                // On récupère la description complète de tous les types de noisettes détectés par le plugin appelant
443                $noisettes[$plugin] = ncore_noisette_lister($plugin, $conteneur, '', $cle, $stockage);
444        }
445
446        // Application des filtres éventuellement demandés en argument de la fonction
447        $noisettes_filtrees = $noisettes[$plugin];
448        if ($filtres) {
449                foreach ($noisettes_filtrees as $_noisette => $_description) {
450                        foreach ($filtres as $_critere => $_valeur) {
451                                if (isset($_description[$_critere]) and ($_description[$_critere] != $_valeur)) {
452                                        unset($noisettes_filtrees[$_noisette]);
453                                        break;
454                                }
455                        }
456                }
457        }
458
459        return $noisettes_filtrees;
460}
Note: See TracBrowser for help on using the repository browser.