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

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

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

  • Property svn:eol-style set to native
File size: 15.7 KB
Line 
1<?php
2/**
3 * Ce fichier contient l'API N-Core de gestion des types de noisette qui consiste à stocker les descriptions
4 * dans un espace à accès rapide et à permettre leur lecture et leur mise à jour.
5 *
6 * @package SPIP\NCORE\TYPE_NOISETTE\API
7 */
8if (!defined('_ECRIRE_INC_VERSION')) {
9        return;
10}
11
12
13/**
14 * Charge ou recharge les descriptions des types de noisette à partir des fichiers YAML.
15 * La fonction optimise le chargement en effectuant uniquement les traitements nécessaires
16 * en fonction des modifications, ajouts et suppressions des types de noisette identifiés
17 * en comparant les md5 des fichiers YAML.
18 *
19 * @api
20 * @uses ncore_type_noisette_initialiser_dossier()
21 * @uses ncore_type_noisette_lister()
22 * @uses ncore_type_noisette_completer()
23 * @uses ncore_type_noisette_stocker()
24 *
25 * @param string $plugin
26 *        Identifiant qui permet de distinguer le module appelant qui peut-être un plugin comme le noiZetier
27 *        ou un script. Pour un plugin, le plus pertinent est d'utiliser le préfixe.
28 * @param bool   $recharger
29 *        Si `true` force le rechargement de tous les types de noisette, sinon le chargement se base sur le
30 *        md5 des fichiers YAML. Par défaut vaut `false`.
31 * @param string $stockage
32 *        Identifiant du service de stockage à utiliser si précisé.
33 *
34 * @return bool
35 *        `false` si une erreur s'est produite, `true` sinon.
36 */
37function type_noisette_charger($plugin, $recharger = false, $stockage = '') {
38
39        // Retour de la fonction
40        $retour = true;
41
42        // Initialiser le contexte de rechargement
43        // TODO : voir si on ajoute un var_mode=recalcul_types_noisette ?
44
45        // On charge l'API de stockge de N-Core.
46        // Ce sont ces fonctions qui aiguillent ou pas vers une éventuelle fonction spécifique de stockage.
47        include_spip("ncore/ncore");
48
49        // On récupère la configuration du dossier relatif où chercher les types de noisettes à charger.
50        $dossier = ncore_type_noisette_initialiser_dossier($plugin);
51
52        // On recherche les types de noisette directement par leur fichier YAML de configuration car il est
53        // obligatoire. La recherche s'effectue dans le path en utilisant le dossier relatif fourni.
54        if ($fichiers = find_all_in_path($dossier, '.+[.]yaml$')) {
55                // On s'assure que la noisette conteneur fournie par N-Core soit bien dans la liste ce qui peut ne pas être
56                // le cas si le dossier relatif des types de noisette du plugin appelant est différent de celui de N-Core.
57                $dossier_ncore = ncore_type_noisette_initialiser_dossier('ncore');
58                if ($dossier != $dossier_ncore) {
59                        $fichiers['conteneur.yaml'] = find_in_path("${dossier_ncore}conteneur.yaml");
60                }
61
62                // Initialisation des tableaux de types de noisette.
63                $types_noisette_a_ajouter = $types_noisette_a_changer = $types_noisette_a_effacer = array();
64
65                // Récupération de la description complète des types de noisette déjà enregistrés de façon :
66                // - à gérer l'activité des types en fin de chargement
67                // - de comparer les signatures md5 des noisettes déjà enregistrées. Si on force le rechargement il est inutile
68                //   de gérer les signatures et les noisettes modifiées ou obsolètes.
69                $types_noisettes_existantes = ncore_type_noisette_lister($plugin, '', $stockage);
70                $signatures = array();
71                if (!$recharger) {
72                        $signatures = array_column($types_noisettes_existantes, 'signature', 'type_noisette');
73                        // On initialise la liste des types de noisette à supprimer avec l'ensemble des types de noisette déjà stockés.
74                        $types_noisette_a_effacer = $signatures ? array_keys($signatures) : array();
75                }
76
77                foreach ($fichiers as $_squelette => $_chemin) {
78                        $type_noisette = basename($_squelette, '.yaml');
79                        // Si on a forcé le rechargement ou si aucun md5 n'est encore stocké pour le type de noisette
80                        // on positionne la valeur du md5 stocké à chaine vide.
81                        // De cette façon, on force la lecture du fichier YAML du type de noisette.
82                        $md5_stocke = (isset($signatures[$type_noisette]) and !$recharger)
83                                ? $signatures[$type_noisette]
84                                : '';
85
86                        // Initialisation de la description par défaut du type de noisette
87                        // -- on y inclut le plugin appelant et la signature
88                        $description_defaut = array(
89                                'type_noisette' => $type_noisette,
90                                'nom'           => $type_noisette,
91                                'description'   => '',
92                                'icon'          => 'noisette-24.png',
93                                'necessite'     => array(),
94                                'actif'         => 'oui',
95                                'conteneur'     => 'non',
96                                'contexte'      => array(),
97                                'ajax'          => 'defaut',
98                                'inclusion'     => 'defaut',
99                                'parametres'    => array(),
100                                'plugin'        => $plugin,
101                                'signature'     => '',
102                        );
103
104                        // On vérifie que le md5 du fichier YAML est bien différent de celui stocké avant de charger
105                        // le contenu. Sinon, on passe au fichier suivant.
106                        $md5 = md5_file($_chemin);
107                        if ($md5 != $md5_stocke) {
108                                include_spip('inc/yaml');
109                                $description = yaml_decode_file($_chemin, array('include' => true));
110
111                                // TODO : ne faudrait-il pas "valider" le fichier YAML ici ou alors lors du stockage ?
112                                // Traitements des champs pouvant être soit une chaine soit un tableau
113                                if (!empty($description['necessite']) and is_string($description['necessite'])) {
114                                        $description['necessite'] = array($description['necessite']);
115                                }
116                                if (!empty($description['contexte']) and is_string($description['contexte'])) {
117                                        $description['contexte'] = array($description['contexte']);
118                                }
119
120                                // On repère les types de noisette qui nécessitent des plugins explicitement dans leur
121                                // fichier de configuration :
122                                // -- si un plugin nécessité est inactif, on indique le type de noisette comme inactif mais on l'inclut
123                                //    dans la liste retournée.
124                                // Rappel: si un type de noisette est incluse dans un plugin non actif elle ne sera pas détectée
125                                //         lors du find_all_in_path() puisque le plugin n'est pas dans le path SPIP.
126                                //         Ce n'est pas ce cas qui est traité ici.
127                                if (!empty($description['necessite'])) {
128                                        foreach ($description['necessite'] as $_plugin_necessite) {
129                                                if (!defined('_DIR_PLUGIN_' . strtoupper($_plugin_necessite))) {
130                                                        $description['actif'] = 'non';
131                                                        break;
132                                                }
133                                        }
134                                }
135
136                                // En mode rechargement forcé toute noisette est considérée comme nouvelle.
137                                // Sinon, la noisette doit être retirée de la base car un plugin qu'elle nécessite a été désactivée:
138                                // => il suffit pour cela de la laisser dans la liste des noisettes obsolètes.
139                                // Mise à jour du md5
140                                $description['signature'] = $md5;
141                                // Complétude de la description avec les valeurs par défaut
142                                $description = array_merge($description_defaut, $description);
143                                // Traitement spécifique d'un type de noisette conteneur : l'ajax et l'inclusion dynamique
144                                // ne sont pas autorisés et le contexte est défini lors de l'encapsulation.
145                                if ($description['conteneur'] == 'oui') {
146                                        $description['contexte'] = array('aucun');
147                                        $description['ajax'] = 'non';
148                                        $description['inclusion'] = 'statique';
149                                }
150                                // Si le contexte est vide alors on le force à env pour éviter de traiter ce cas (contexte vide)
151                                // lors de la compilation.
152                                if (!$description['contexte']) {
153                                        $description['contexte'] = array('env');
154                                }
155                                // Sérialisation des champs 'necessite', 'contexte' et 'parametres' qui sont des tableaux
156                                $description['necessite'] = serialize($description['necessite']);
157                                $description['contexte'] = serialize($description['contexte']);
158                                $description['parametres'] = serialize($description['parametres']);
159                                // Complément spécifique au plugin utilisateur si nécessaire
160                                $description = ncore_type_noisette_completer($plugin, $description, $stockage);
161
162                                if (!$md5_stocke or $recharger) {
163                                        // Le type de noisette est soit nouveau soit on est en mode rechargement forcé:
164                                        // => il faut le rajouter.
165                                        $types_noisette_a_ajouter[] = $description;
166                                } else {
167                                        // La description stockée a été modifiée et le mode ne force pas le rechargement:
168                                        // => il faut mettre à jour le type de noisette.
169                                        $types_noisette_a_changer[] = $description;
170                                        // => et il faut donc le supprimer de la liste de types de noisette obsolètes
171                                        $types_noisette_a_effacer = array_diff($types_noisette_a_effacer, array($type_noisette));
172                                }
173                        } else {
174                                // Le type de noisette n'a pas changé et n'a donc pas été rechargé:
175                                // => Il faut donc juste indiquer qu'il n'est pas obsolète.
176                                $types_noisette_a_effacer = array_diff($types_noisette_a_effacer, array($type_noisette));
177                        }
178                }
179
180                // On complète la liste des types de noisette à changer avec les types de noisette dont l'indicateur
181                // d'activité est modifié suite à l'activation ou à la désactivation d'un plugin (le fichier YAML lui
182                // n'a pas changé). Il est inutile de le faire si on recharge tout.
183                // -- on cherche ces types en excluant les pages obsolètes et celles à changer qui ont déjà recalculé
184                //    l'indicateur lors de la lecture du fichier YAML.
185                if (!$recharger) {
186                        $types_noisette_exclus = $types_noisette_a_changer
187                                ? array_merge(array_column($types_noisette_a_changer, 'type_noisette'), $types_noisette_a_effacer)
188                                : $types_noisette_a_effacer;
189                        $types_noisette_a_verifier = $types_noisette_exclus
190                                ? array_diff_key($types_noisettes_existantes, array_flip($types_noisette_exclus))
191                                : $types_noisettes_existantes;
192
193                        if ($types_noisette_a_verifier) {
194                                foreach ($types_noisette_a_verifier as $_type => $_description) {
195                                        $actif = 'oui';
196                                        $plugins_necessites = unserialize($_description['necessite']);
197                                        if ($plugins_necessites) {
198                                                foreach ($plugins_necessites as $_plugin_necessite) {
199                                                        if (!defined('_DIR_PLUGIN_' . strtoupper($_plugin_necessite))) {
200                                                                $actif = 'non';
201                                                                break;
202                                                        }
203                                                }
204                                        }
205                                        if ($actif != $_description['actif']) {
206                                                // On stocke la mise à jour dans les types à changer.
207                                                $_description['actif'] = $actif;
208                                                $types_noisette_a_changer[] = $_description;
209                                        }
210
211                                }
212                        }
213                }
214
215                // Mise à jour du stockage des types de noisette si au moins un des 3 tableaux est non vide et que le chargement forcé
216                // n'est pas demandé ou si le chargement forcé a été demandé:
217                // -- Suppression des types de noisettes obsolètes ou de tous les types de noisettes si on est en mode rechargement forcé.
218                //    Pour permettre une optimisation du traitement en mode rechargement forcé on passe toujours le mode.
219                // -- Update des types de noisette modifiés.
220                // -- Insertion des nouveaux types de noisette.
221                if ($recharger
222                or (!$recharger and ($types_noisette_a_ajouter or $types_noisette_a_effacer or $types_noisette_a_changer))) {
223                        $types_noisette = array('a_ajouter' => $types_noisette_a_ajouter);
224                        if (!$recharger) {
225                                $types_noisette['a_effacer'] = $types_noisette_a_effacer;
226                                $types_noisette['a_changer'] = $types_noisette_a_changer;
227                        }
228                        $retour = ncore_type_noisette_stocker($plugin, $types_noisette, $recharger, $stockage);
229                }
230        }
231
232        return $retour;
233}
234
235
236/**
237 * Retourne, pour un type de noisette donné, la description complète ou seulement un champ précis.
238 * Les champs textuels peuvent subir une traitement typo si demandé.
239 *
240 * @api
241 * @uses ncore_type_noisette_decrire()
242 *
243 * @param string  $plugin
244 *        Le service permet de distinguer l'appelant qui peut-être un plugin comme le noiZetier ou
245 *        un script. Pour un plugin, le plus pertinent est d'utiliser le préfixe.
246 * @param string  $type_noisette
247 *        Identifiant du type de noisette.
248 * @param string  $information
249 *        Information spécifique à retourner ou vide pour retourner toute la description.
250 * @param boolean $traiter_typo
251 *        Indique si les données textuelles doivent être retournées brutes ou si elles doivent être traitées
252 *        en utilisant la fonction typo. Par défaut l'indicateur vaut `false`.
253 *        Les champs sérialisés sont eux toujours désérialisés.
254 * @param string  $stockage
255 *        Identifiant du service de stockage à utiliser si précisé.
256 *
257 * @return array|string
258 *        La description complète ou champ précis demandé pour un type de noisette donné. Les champs
259 *        de type tableau sont systématiquement désérialisés et si demandé, les champs textuels peuvent être
260 *        traités avec la fonction typo().
261 */
262function type_noisette_lire($plugin, $type_noisette, $information = '', $traiter_typo = false, $stockage = '') {
263
264        // On indexe le tableau des descriptions par le plugin appelant en cas d'appel sur le même hit
265        // par deux plugins différents.
266        static $description_type_noisette = array();
267
268        // Stocker la description de la noisette si besoin
269        if (!isset($description_type_noisette[$plugin][$traiter_typo][$type_noisette])) {
270                // On charge l'API de N-Core.
271                // Ce sont ces fonctions qui aiguillent ou pas vers une fonction spécifique du service.
272                include_spip("ncore/ncore");
273
274                // Lecture de toute la configuration de la noisette: les données retournées sont brutes.
275                $description = ncore_type_noisette_decrire($plugin, $type_noisette, $stockage);
276
277                if ($description) {
278                        // Traitements des champs textuels
279                        if ($traiter_typo) {
280                                $description = ncore_type_noisette_traiter_typo($plugin, $description, $stockage);
281                        }
282
283                        // Traitements des champs tableaux sérialisés
284                        $description['contexte'] = unserialize($description['contexte']);
285                        $description['necessite'] = unserialize($description['necessite']);
286                        $description['parametres'] = unserialize($description['parametres']);
287                }
288
289                // Sauvegarde de la description de la page pour une consultation ultérieure dans le même hit.
290                $description_type_noisette[$plugin][$traiter_typo][$type_noisette] = $description;
291        }
292
293        if ($information) {
294                if (isset($description_type_noisette[$plugin][$traiter_typo][$type_noisette][$information])) {
295                        $type_noisette_lu = $description_type_noisette[$plugin][$traiter_typo][$type_noisette][$information];
296                } else {
297                        $type_noisette_lu = '';
298                }
299        } else {
300                $type_noisette_lu = $description_type_noisette[$plugin][$traiter_typo][$type_noisette];
301        }
302
303        return $type_noisette_lu;
304}
305
306/**
307 * Renvoie une liste de descriptions de types de noisette éventuellement filtrée sur certains champs
308 * fournis en argument.
309 *
310 * @api
311 * @uses ncore_type_noisette_lister()
312 *
313 * @param string $plugin
314 *        Identifiant qui permet de distinguer le module appelant qui peut-être un plugin comme le noiZetier
315 *        ou un script. Pour un plugin, le plus pertinent est d'utiliser le préfixe.
316 * @param array  $filtres
317 *        Tableau associatif `[champ] = valeur` de critères de filtres sur les descriptions de types de noisette.
318 *        Le seul opérateur possible est l'égalité.
319 * @param string $stockage
320 *        Identifiant du service de stockage à utiliser si précisé.
321 *
322 * @return array
323 *        Tableau des descriptions des types de noisette trouvés indexé par le type de noisette.
324 */
325function type_noisette_repertorier($plugin, $filtres = array(), $stockage = '') {
326
327        // On indexe le tableau des types de noisette par le plugin appelant en cas d'appel sur le même hit
328        // par deux plugins différents.
329        static $types_noisette = array();
330
331        if (!isset($types_noisette[$plugin])) {
332                // On charge l'API de N-Core.
333                // Ce sont ces fonctions qui aiguillent ou pas vers une fonction spécifique du service.
334                include_spip("ncore/ncore");
335
336                // On récupère la description complète de tous les types de noisettes détectés par le plugin appelant
337                $types_noisette[$plugin] = ncore_type_noisette_lister($plugin, '', $stockage);
338        }
339
340        // Application des filtres éventuellement demandés en argument de la fonction
341        $types_noisette_filtres = $types_noisette[$plugin];
342        if ($filtres) {
343                foreach ($types_noisette_filtres as $_type_noisette => $_description) {
344                        foreach ($filtres as $_critere => $_valeur) {
345                                if (isset($_description[$_critere]) and ($_description[$_critere] != $_valeur)) {
346                                        unset($types_noisette_filtres[$_type_noisette]);
347                                        break;
348                                }
349                        }
350                }
351        }
352
353        return $types_noisette_filtres;
354}
Note: See TracBrowser for help on using the repository browser.