source: spip-zone/_plugins_/saisies/trunk/inc/saisies_lister.php @ 114719

Last change on this file since 114719 was 114719, checked in by maieul@…, 8 months ago

retour ligne

File size: 16.7 KB
Line 
1<?php
2
3/**
4 * Gestion de listes des saisies.
5 *
6 * @return SPIP\Saisies\Listes
7 **/
8
9// Sécurité
10if (!defined('_ECRIRE_INC_VERSION')) {
11        return;
12}
13
14/**
15 * Prend la description complète du contenu d'un formulaire et retourne
16 * les saisies "à plat" classées par identifiant unique.
17 *
18 * @param array $contenu        Le contenu d'un formulaire
19 * @param bool  $avec_conteneur Indique si on renvoie aussi les saisies ayant des enfants, comme les fieldsets
20 *
21 * @return array Un tableau avec uniquement les saisies
22 */
23function saisies_lister_par_identifiant($contenu, $avec_conteneur = true) {
24        $saisies = array();
25
26        if (is_array($contenu)) {
27                foreach ($contenu as $ligne) {
28                        if (is_array($ligne)) {
29                                $enfants_presents = (isset($ligne['saisies']) and is_array($ligne['saisies']));
30                                if (array_key_exists('saisie', $ligne) and (!$enfants_presents or $avec_conteneur)) {
31                                        $saisies[$ligne['identifiant']] = $ligne;
32                                }
33                                if ($enfants_presents) {
34                                        $saisies = array_merge($saisies, saisies_lister_par_identifiant($ligne['saisies']));
35                                }
36                        }
37                }
38        }
39
40        return $saisies;
41}
42
43/**
44 * Prend la description complète du contenu d'un formulaire et retourne
45 * les saisies "à plat" classées par nom.
46 *
47 * @param array $contenu        Le contenu d'un formulaire
48 * @param bool  $avec_conteneur Indique si on renvoie aussi les saisies ayant des enfants, comme les fieldset
49 *
50 * @return array Un tableau avec uniquement les saisies
51 */
52function saisies_lister_par_nom($contenu, $avec_conteneur = true) {
53        $saisies = array();
54
55        if (is_array($contenu)) {
56                foreach ($contenu as $ligne) {
57                        if (is_array($ligne)) {
58                                if (
59                                        array_key_exists('saisie', $ligne)
60                                        and (!isset($ligne['saisies']) or !is_array($ligne['saisies']) or $avec_conteneur)
61                                        and isset($ligne['options'])
62                                ) {
63                                        $saisies[$ligne['options']['nom']] = $ligne;
64                                }
65                                if (isset($ligne['saisies']) and is_array($ligne['saisies'])) {
66                                        $saisies = array_merge($saisies, saisies_lister_par_nom($ligne['saisies']));
67                                }
68                        }
69                }
70        }
71
72        return $saisies;
73}
74
75/**
76 * Liste les saisies ayant une option X
77 * # saisies_lister_avec_option('sql', $saisies);.
78 *
79 *
80 * @param string $option  Nom de l'option cherchée
81 * @param array  $saisies Liste de saisies
82 * @param string $tri     tri par défaut des résultats (s'ils ne sont pas deja triés) ('nom', 'identifiant')
83 *
84 * @return liste de ces saisies triees par nom ayant une option X définie
85 */
86function saisies_lister_avec_option($option, $saisies, $tri = 'nom') {
87        $saisies_option = array();
88
89        // tri par nom si ce n'est pas le cas
90        $s = array_keys($saisies);
91        if (is_int(array_shift($s))) {
92                $trier = 'saisies_lister_par_'.$tri;
93                $saisies = $trier($saisies);
94        }
95
96        foreach ($saisies as $nom_ou_id => $saisie) {
97                if (isset($saisie['options'][$option]) and $saisie['options'][$option]) {
98                        $saisies_option[$nom_ou_id] = $saisie;
99                }
100        }
101
102        return $saisies_option;
103}
104
105/**
106 * Liste les saisies ayant une definition SQL.
107 *
108 * @param array  $saisies liste de saisies
109 * @param string $tri     tri par défaut des résultats (s'ils ne sont pas deja triés) ('nom', 'identifiant')
110 *
111 * @return liste de ces saisies triees par nom ayant une option sql définie
112 */
113function saisies_lister_avec_sql($saisies, $tri = 'nom') {
114        return saisies_lister_avec_option('sql', $saisies, $tri);
115}
116
117/**
118 * Liste les saisies d'un certain type.
119 *
120 * @example `$saisies_date = saisies_lister_avec_type($saisies, 'date')`
121 *
122 * @param array  $saisies liste de saisies
123 * @param string|array $type    Type de la saisie, ou tableau de types
124 * @param string $tri     tri par défaut des résultats (s'ils ne sont pas deja triés) ('nom')
125 *
126 * @return liste de ces saisies triees par nom
127 */
128function saisies_lister_avec_type($saisies, $type, $tri = 'nom') {
129        if (!is_array($type)) {
130                $type = array($type);
131        }
132        $saisies_type = array();
133
134        // tri par nom si ce n'est pas le cas
135        $s = array_keys($saisies);
136        if (is_int(array_shift($s))) {
137                $trier = 'saisies_lister_par_'.$tri;
138                $saisies = $trier($saisies);
139        }
140
141        foreach ($saisies as $nom_ou_id => $saisie) {
142                if (in_array($saisie['saisie'], $type)) {
143                        $saisies_type[$nom_ou_id] = $saisie;
144                }
145        }
146        return $saisies_type;
147}
148
149/**
150 * Prend la description complète du contenu d'un formulaire et retourne
151 * les saisies "à plat" classées par type de saisie.
152 * $saisie['input']['input_1'] = $saisie.
153 *
154 * @param array $contenu Le contenu d'un formulaire
155 *
156 * @return array Un tableau avec uniquement les saisies
157 */
158function saisies_lister_par_type($contenu) {
159        $saisies = array();
160
161        if (is_array($contenu)) {
162                foreach ($contenu as $ligne) {
163                        if (is_array($ligne)) {
164                                if (array_key_exists('saisie', $ligne) and (!is_array($ligne['saisies']))) {
165                                        $saisies[ $ligne['saisie'] ][ $ligne['options']['nom'] ] = $ligne;
166                                }
167                                if (is_array($ligne['saisies'])) {
168                                        $saisies = array_merge_recursive($saisies, saisies_lister_par_type($ligne['saisies']));
169                                }
170                        }
171                }
172        }
173
174        return $saisies;
175}
176
177/**
178 * Liste les saisies par étapes s'il y en a
179 *
180 * @param array $saisies
181 *              Liste des saisies
182 * @return array|bool
183 *              Retourne un tableau associatif par numéro d'étape avec pour chacune leurs saisies, false si pas d'étapes
184 */
185function saisies_lister_par_etapes($saisies) {
186        $saisies_etapes = false;
187        $etapes = 0;
188
189        if (isset($saisies['options']['etapes_activer']) and $saisies['options']['etapes_activer']) {
190                // Un premier parcourt pour compter les étapes
191                foreach ($saisies as $cle => $saisie) {
192                        if (is_array($saisies) and $saisie['saisie'] == 'fieldset') {
193                                $etapes++;
194                        }
195                }
196
197                // Seulement s'il y a au moins deux étapes
198                if ($etapes > 1) {
199                        $saisies_etapes = array();
200                        $compteur_etape = 0;
201
202                        // On reparcourt pour lister les saisies
203                        foreach ($saisies as $cle => $saisie) {
204                                // Si c'est un groupe, on ajoute son contenu à l'étape
205                                if (isset($saisie['saisie']) and $saisie['saisie'] == 'fieldset') {
206                                        $compteur_etape++;
207                                        // S'il y a eu des champs hors groupe avant, on fusionne
208                                        if (isset($saisies_etapes[$compteur_etape]['saisies'])) {
209                                                $saisies_precedentes = $saisies_etapes[$compteur_etape]['saisies'];
210                                                $saisies_etapes[$compteur_etape] = $saisie;
211                                                $saisies_etapes[$compteur_etape]['saisies'] = array_merge($saisies_precedentes, $saisie['saisies']);
212                                        }
213                                        else {
214                                                $saisies_etapes[$compteur_etape] = $saisie;
215                                        }
216                                }
217                                // Sinon si champ externe à un groupe, on l'ajoute à toutes les étapes
218                                elseif (isset($saisie['saisie'])) {
219                                        for ($e=1;$e<=$etapes;$e++) {
220                                                if (!isset($saisies_etapes[$e]['saisies'])) {
221                                                        $saisies_etapes[$e] = array('saisies'=>array());
222                                                }
223                                                array_push($saisies_etapes[$e]['saisies'], $saisie);
224                                        }
225                                }
226                        }
227                }
228        }
229
230        return $saisies_etapes;
231}
232
233/**
234 * Prend la description complète du contenu d'un formulaire et retourne
235 * une liste des noms des champs du formulaire.
236 *
237 * @param array $contenu        Le contenu d'un formulaire
238 * @param bool  $avec_conteneur Indique si on renvoie aussi les saisies ayant des enfants, comme les fieldset
239 *
240 * @return array Un tableau listant les noms des champs
241 */
242function saisies_lister_champs($contenu, $avec_conteneur = true) {
243        $saisies = saisies_lister_par_nom($contenu, $avec_conteneur);
244
245        return array_keys($saisies);
246}
247
248/**
249 * Prend la description complète du contenu d'un formulaire et retourne
250 * une liste des labels humains des vrais champs du formulaire (par nom)
251 *
252 * @param array $contenu        Le contenu d'un formulaire
253 * @param bool  $avec_conteneur Indique si on renvoie aussi les saisies ayant des enfants, comme les fieldset
254 *
255 * @return array Un tableau listant les labels humains des champs
256 */
257function saisies_lister_labels($contenu, $avec_conteneur = false) {
258        $saisies = saisies_lister_par_nom($contenu, $avec_conteneur);
259
260        $labels = array();
261        foreach ($saisies as $nom => $saisie) {
262                if (isset($saisie['options']['label'])) {
263                        $labels[$nom] = $saisie['options']['label'];
264                }
265        }
266
267        return $labels;
268}
269
270/**
271 * A utiliser dans une fonction charger d'un formulaire CVT,
272 * cette fonction renvoie le tableau de contexte correspondant
273 * de la forme $contexte['nom_champ'] = ''.
274 *
275 * @param array $contenu Le contenu d'un formulaire (un tableau de saisies)
276 *
277 * @return array Un tableau de contexte
278 */
279function saisies_charger_champs($contenu) {
280        if (function_exists('array_fill_keys')) { // php 5.2
281                return array_fill_keys(saisies_lister_champs($contenu, false), null);
282        }
283        $champs = array();
284        foreach (saisies_lister_champs($contenu, false) as $champ) {
285                $champs[$champ] = null;
286        }
287
288        return $champs;
289}
290
291/**
292 * Prend la description complète du contenu d'un formulaire et retourne
293 * une liste des valeurs par défaut des champs du formulaire.
294 *
295 * @param array $contenu Le contenu d'un formulaire
296 *
297 * @return array Un tableau renvoyant la valeur par défaut de chaque champs
298 */
299function saisies_lister_valeurs_defaut($contenu) {
300        $contenu = saisies_lister_par_nom($contenu, false);
301        $defauts = array();
302
303        foreach ($contenu as $nom => $saisie) {
304                // Si le nom du champ est un tableau indexé, il faut parser !
305                if (preg_match('/([\w]+)((\[[\w]+\])+)/', $nom, $separe)) {
306                        $nom = $separe[1];
307                        // Dans ce cas on ne récupère que le nom,
308                        // la valeur par défaut du tableau devra être renseigné autre part
309                        $defauts[$nom] = array();
310                }
311                else {
312                        $defauts[$nom] = isset($saisie['options']['defaut']) ? $saisie['options']['defaut'] : '';
313                }
314        }
315
316        return $defauts;
317}
318
319/**
320 * Compare deux tableaux de saisies pour connaitre les différences.
321 *
322 * @param array  $saisies_anciennes Un tableau décrivant des saisies
323 * @param array  $saisies_nouvelles Un autre tableau décrivant des saisies
324 * @param bool   $avec_conteneur    Indique si on veut prendre en compte dans la comparaison les conteneurs comme les fieldsets
325 * @param string $tri               Comparer selon quel tri ? 'nom' / 'identifiant'
326 *
327 * @return array Retourne le tableau des saisies supprimées, ajoutées et modifiées
328 */
329function saisies_comparer($saisies_anciennes, $saisies_nouvelles, $avec_conteneur = true, $tri = 'nom') {
330        $trier = "saisies_lister_par_$tri";
331        $saisies_anciennes = $trier($saisies_anciennes, $avec_conteneur);
332        $saisies_nouvelles = $trier($saisies_nouvelles, $avec_conteneur);
333
334        // Les saisies supprimées sont celles qui restent dans les anciennes quand on a enlevé toutes les nouvelles
335        $saisies_supprimees = array_diff_key($saisies_anciennes, $saisies_nouvelles);
336        // Les saisies ajoutées, c'est le contraire
337        $saisies_ajoutees = array_diff_key($saisies_nouvelles, $saisies_anciennes);
338        // Il reste alors les saisies qui ont le même nom
339        $saisies_restantes = array_intersect_key($saisies_anciennes, $saisies_nouvelles);
340        // Dans celles-ci, celles qui sont modifiées sont celles dont la valeurs est différentes
341        $saisies_modifiees = array_udiff(array_diff_key($saisies_nouvelles, $saisies_ajoutees), $saisies_restantes, 'saisies_comparer_rappel');
342        #$saisies_modifiees = array_udiff($saisies_nouvelles, $saisies_restantes, 'saisies_comparer_rappel');
343        // Et enfin les saisies qui ont le même nom et la même valeur
344        $saisies_identiques = array_diff_key($saisies_restantes, $saisies_modifiees);
345
346        return array(
347                'supprimees' => $saisies_supprimees,
348                'ajoutees' => $saisies_ajoutees,
349                'modifiees' => $saisies_modifiees,
350                'identiques' => $saisies_identiques,
351        );
352}
353
354/**
355 * Compare deux saisies et indique si elles sont égales ou pas.
356 *
357 * @param array $a Une description de saisie
358 * @param array $b Une autre description de saisie
359 *
360 * @return int Retourne 0 si les saisies sont identiques, 1 sinon.
361 */
362function saisies_comparer_rappel($a, $b) {
363        if ($a === $b) {
364                return 0;
365        } else {
366                return 1;
367        }
368}
369
370/**
371 * Compare deux tableaux de saisies pour connaitre les différences
372 * en s'appuyant sur les identifiants de saisies.
373 *
374 * @see saisies_comparer()
375 *
376 * @param array $saisies_anciennes Un tableau décrivant des saisies
377 * @param array $saisies_nouvelles Un autre tableau décrivant des saisies
378 * @param bool  $avec_conteneur    Indique si on veut prendre en compte dans la comparaison
379 *                                 les conteneurs comme les fieldsets
380 *
381 * @return array Retourne le tableau des saisies supprimées, ajoutées et modifiées
382 */
383function saisies_comparer_par_identifiant($saisies_anciennes, $saisies_nouvelles, $avec_conteneur = true) {
384        return saisies_comparer($saisies_anciennes, $saisies_nouvelles, $avec_conteneur, 'identifiant');
385}
386
387/**
388 * Liste toutes les saisies configurables (ayant une description).
389 *
390 * @return array Un tableau listant des saisies et leurs options
391 */
392function saisies_lister_disponibles($saisies_repertoire = 'saisies') {
393        static $saisies = null;
394
395        if (is_null($saisies)) {
396                $saisies = array();
397                $liste = find_all_in_path("$saisies_repertoire/", '.+[.]yaml$');
398
399                if (count($liste)) {
400                        foreach ($liste as $fichier => $chemin) {
401                                $type_saisie = preg_replace(',[.]yaml$,i', '', $fichier);
402                                $dossier = str_replace($fichier, '', $chemin);
403
404                                // On ne garde que les saisies qui ont bien le HTML avec !
405                                if (
406                                        file_exists("$dossier$type_saisie.html")
407                                        and (
408                                                is_array($saisie = saisies_charger_infos($type_saisie))
409                                        )
410                                ) {
411                                        $saisies[$type_saisie] = $saisie;
412                                }
413                        }
414                }
415        }
416
417        return $saisies;
418}
419
420/**
421 * Liste tous les groupes de saisies configurables (ayant une description).
422 *
423 * @return array Un tableau listant des saisies et leurs options
424 */
425function saisies_groupes_lister_disponibles($saisies_repertoire = 'saisies') {
426        static $saisies = null;
427
428        if (is_null($saisies)) {
429                $saisies = array();
430                $liste = find_all_in_path("$saisies_repertoire/", '.+[.]yaml$');
431
432                if (count($liste)) {
433                        foreach ($liste as $fichier => $chemin) {
434                                $type_saisie = preg_replace(',[.]yaml$,i', '', $fichier);
435                                $dossier = str_replace($fichier, '', $chemin);
436
437                                if (is_array($saisie = saisies_charger_infos($type_saisie, $saisies_repertoire))) {
438                                        $saisies[$type_saisie] = $saisie;
439                                }
440                        }
441                }
442        }
443
444        return $saisies;
445}
446
447/**
448 * Lister les saisies existantes ayant une définition SQL.
449 *
450 * @return array Un tableau listant des saisies et leurs options
451 */
452function saisies_lister_disponibles_sql($saisies_repertoire = 'saisies') {
453        $saisies = array();
454        $saisies_disponibles = saisies_lister_disponibles($saisies_repertoire);
455
456        foreach ($saisies_disponibles as $type => $saisie) {
457                if (isset($saisie['defaut']['options']['sql']) and $saisie['defaut']['options']['sql']) {
458                        $saisies[$type] = $saisie;
459                }
460        }
461
462        return $saisies;
463}
464
465/**
466 * Charger les informations contenues dans le YAML d'une saisie.
467 *
468 * @param string $type_saisie Le type de la saisie
469 *
470 * @return array Un tableau contenant le YAML décodé
471 */
472function saisies_charger_infos($type_saisie, $saisies_repertoire = 'saisies') {
473        if (defined('_DIR_PLUGIN_YAML')) {
474                include_spip('inc/yaml');
475                $fichier = find_in_path("$saisies_repertoire/$type_saisie.yaml");
476                $saisie = yaml_decode_file($fichier);
477
478                if (is_array($saisie)) {
479                        $saisie['titre'] = (isset($saisie['titre']) and $saisie['titre'])
480                                ? _T_ou_typo($saisie['titre']) : $type_saisie;
481                        $saisie['description'] = (isset($saisie['description']) and $saisie['description'])
482                                ? _T_ou_typo($saisie['description']) : '';
483                        $saisie['icone'] = (isset($saisie['icone']) and $saisie['icone'])
484                                ? find_in_path($saisie['icone']) : '';
485                }
486        }
487        else {
488                $saisie = array();
489        }
490
491        return $saisie;
492}
493
494/**
495 * Quelles sont les saisies qui se débrouillent toutes seules, sans le _base commun.
496 *
497 * @return array Retourne un tableau contenant les types de saisies qui ne doivent pas utiliser le _base.html commun
498 */
499function saisies_autonomes() {
500        $saisies_autonomes = pipeline(
501                'saisies_autonomes',
502                array(
503                        'fieldset',
504                        'hidden',
505                        'destinataires',
506                        'explication',
507                )
508        );
509
510        return $saisies_autonomes;
511}
512
513/**
514 * La saisie renvoie t-elle un tableau?
515 * note: on teste saisie par saisie, et non pas type de saisie par type de saisie, car certaine type (Evenements par ex) peut, en fonction des options, être tabulaire ou pas.
516 * @param $saisie
517 * @return return bool true si la saisie est tabulaire, false sinon
518**/
519function saisies_saisie_est_tabulaire($saisie) {
520        if (in_array($saisie['saisie'], array('checkbox', 'selection_multiple'))) {
521                $est_tabulaire = true;
522        } else {
523                $est_tabulaire =  false;
524        }
525        return pipeline('saisie_est_tabulaire',
526                array('args' => $saisie, 'data' => $est_tabulaire)
527        );
528}
529
530/**
531 * Indique si une saisie à sa valeur gelée
532 * - soit par option disabled avec envoi cachée
533 * - soit par option readonly
534 * @param array $description description de la saisie
535 * @return bool true si gélée, false sinon)
536**/
537function saisies_verifier_gel_saisie($description) {
538        $options = $description['options'];
539        //As t-on bloqué d'une manière ou d'une autre la valeur postée?
540        if ((
541                isset($options['readonly'])
542                and $options['readonly']
543        )
544        or (
545                isset($options['disable'])
546                and isset($options['disable_avec_post'])
547                and $options['disable']
548                and $options['disable_avec_post']
549        )
550        ) {
551                return true;
552        } else {
553                return false;
554        }
555}
Note: See TracBrowser for help on using the repository browser.