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

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

On crée un nouveau service permettant à un plugin de positionner le défaut d'inclusion à une valeur différente de celle de N-Core (voire de la configurer).
Le champ inclusion devient donc ternaire : defaut (par défaut), statique ou dynamique

  • Property svn:eol-style set to native
File size: 15.9 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 $donnees_typo = array('nom', 'description');
267        static $description_noisette = array();
268
269        // Stocker la description de la noisette si besoin
270        if (!isset($description_noisette[$plugin][$type_noisette])) {
271                // On charge l'API de N-Core.
272                // Ce sont ces fonctions qui aiguillent ou pas vers une fonction spécifique du service.
273                include_spip("ncore/ncore");
274
275                // Lecture de toute la configuration de la noisette: les données retournées sont brutes.
276                $description = ncore_type_noisette_decrire($plugin, $type_noisette, $stockage);
277
278                // Sauvegarde de la description de la page pour une consultation ultérieure dans le même hit.
279                if ($description) {
280                        // Traitements des champs tableaux sérialisés
281                        $description['contexte'] = unserialize($description['contexte']);
282                        $description['necessite'] = unserialize($description['necessite']);
283                        $description['parametres'] = unserialize($description['parametres']);
284                }
285
286                // Stockage de la description
287                $description_noisette[$plugin][$type_noisette] = $description;
288        }
289
290        if ($information) {
291                if (isset($description_noisette[$plugin][$type_noisette][$information])) {
292                        if (in_array($information, $donnees_typo) and $traiter_typo) {
293                                // Traitements de la donnée textuelle
294                                $retour = typo($description_noisette[$plugin][$type_noisette][$information]);
295                        } else {
296                                $retour = $description_noisette[$plugin][$type_noisette][$information];
297                        }
298                } else {
299                        $retour = '';
300                }
301        } else {
302                $retour = $description_noisette[$plugin][$type_noisette];
303                // Traitements des données textuels
304                if ($traiter_typo) {
305                        foreach ($donnees_typo as $_champ) {
306                                if (isset($retour[$_champ])) {
307                                        $retour[$_champ] = typo($retour[$_champ]);
308                                }
309                        }
310                }
311        }
312
313        return $retour;
314}
315
316/**
317 * Renvoie une liste de descriptions de types de noisette éventuellement filtrée sur certains champs
318 * fournis en argument.
319 *
320 * @api
321 * @uses ncore_type_noisette_lister()
322 *
323 * @param string $plugin
324 *        Identifiant qui permet de distinguer le module appelant qui peut-être un plugin comme le noiZetier
325 *        ou un script. Pour un plugin, le plus pertinent est d'utiliser le préfixe.
326 * @param array  $filtres
327 *        Tableau associatif `[champ] = valeur` de critères de filtres sur les descriptions de types de noisette.
328 *        Le seul opérateur possible est l'égalité.
329 * @param string $stockage
330 *        Identifiant du service de stockage à utiliser si précisé.
331 *
332 * @return array
333 *        Tableau des descriptions des types de noisette trouvés indexé par le type de noisette.
334 */
335function type_noisette_repertorier($plugin, $filtres = array(), $stockage = '') {
336
337        // On indexe le tableau des types de noisette par le plugin appelant en cas d'appel sur le même hit
338        // par deux plugins différents.
339        static $types_noisette = array();
340
341        if (!isset($types_noisette[$plugin])) {
342                // On charge l'API de N-Core.
343                // Ce sont ces fonctions qui aiguillent ou pas vers une fonction spécifique du service.
344                include_spip("ncore/ncore");
345
346                // On récupère la description complète de tous les types de noisettes détectés par le plugin appelant
347                $types_noisette[$plugin] = ncore_type_noisette_lister($plugin, '', $stockage);
348        }
349
350        // Application des filtres éventuellement demandés en argument de la fonction
351        $types_noisette_filtres = $types_noisette[$plugin];
352        if ($filtres) {
353                foreach ($types_noisette_filtres as $_type_noisette => $_description) {
354                        foreach ($filtres as $_critere => $_valeur) {
355                                if (isset($_description[$_critere]) and ($_description[$_critere] != $_valeur)) {
356                                        unset($types_noisette_filtres[$_type_noisette]);
357                                        break;
358                                }
359                        }
360                }
361        }
362
363        return $types_noisette_filtres;
364}
Note: See TracBrowser for help on using the repository browser.