source: spip-zone/_plugins_/saisies/inc/saisies.php @ 75184

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

saisies_tableau2chaine() peut désormais gérer le cas des sous-tableau, en marquant début de sous-tableau par *

File size: 13.0 KB
Line 
1<?php
2
3/**
4 * Gestion de l'affichage des saisies
5 *
6 * @return SPIP\Saisies\Saisies
7**/
8
9// Sécurité
10if (!defined('_ECRIRE_INC_VERSION')) return;
11
12/*
13 * Une librairie pour manipuler ou obtenir des infos sur un tableau de saisies
14 *
15 * saisies_lister_par_nom()
16 * saisies_lister_champs()
17 * saisies_lister_valeurs_defaut()
18 * saisies_charger_champs()
19 * saisies_chercher()
20 * saisies_supprimer()
21 * saisies_inserer()
22 * saisies_deplacer()
23 * saisies_modifier()
24 * saisies_verifier()
25 * saisies_comparer()
26 * saisies_generer_html()
27 * saisies_generer_vue()
28 * saisies_generer_nom()
29 * saisies_inserer_html()
30 * saisies_lister_disponibles()
31 * saisies_autonomes()
32 */
33
34// Différentes méthodes pour trouver les saisies
35include_spip('inc/saisies_lister');
36
37// Différentes méthodes pour manipuler une liste de saisies
38include_spip('inc/saisies_manipuler');
39
40// Les outils pour afficher les saisies et leur vue
41include_spip('inc/saisies_afficher');
42
43/*
44 * Cherche la description des saisies d'un formulaire CVT dont on donne le nom
45 *
46 * @param string $form Nom du formulaire dont on cherche les saisies
47 * @return array Retourne les saisies du formulaire sinon false
48 */
49function saisies_chercher_formulaire($form, $args){
50        if ($fonction_saisies = charger_fonction('saisies', 'formulaires/'.$form, true)
51                and $saisies = call_user_func_array($fonction_saisies, $args)
52                and is_array($saisies)
53                // On passe les saisies dans un pipeline normé comme pour CVT
54                and $saisies = pipeline(
55                        'formulaire_saisies',
56                        array(
57                                'args' => array('form' => $form, 'args' => $args),
58                                'data' => $saisies
59                        )
60                )
61                // Si c'est toujours un tableau après le pipeline
62                and is_array($saisies)
63        ){
64                return $saisies;
65        }
66        else{
67                return false;
68        }
69}
70
71/*
72 * Cherche une saisie par son id, son nom ou son chemin et renvoie soit la saisie, soit son chemin
73 *
74 * @param array $saisies Un tableau décrivant les saisies
75 * @param unknown_type $id_ou_nom_ou_chemin L'identifiant ou le nom de la saisie à chercher ou le chemin sous forme d'une liste de clés
76 * @param bool $retourner_chemin Indique si on retourne non pas la saisie mais son chemin
77 * @return array Retourne soit la saisie, soit son chemin, soit null
78 */
79function saisies_chercher($saisies, $id_ou_nom_ou_chemin, $retourner_chemin=false){
80
81        if (is_array($saisies) and $id_ou_nom_ou_chemin){
82                if (is_string($id_ou_nom_ou_chemin)){
83                        $nom = $id_ou_nom_ou_chemin;
84                        // identifiant ? premier caractere @
85                        $id = ($nom[0] == '@');
86
87                        foreach($saisies as $cle => $saisie){
88                                $chemin = array($cle);
89                                // notre saisie est la bonne ?
90                                if ($nom == ($id ? $saisie['identifiant'] : $saisie['options']['nom'])) {
91                                        return $retourner_chemin ? $chemin : $saisie;
92                                // sinon a telle des enfants ? et si c'est le cas, cherchons dedans
93                                } elseif (isset($saisie['saisies']) and is_array($saisie['saisies']) and $saisie['saisies']
94                                        and ($retour = saisies_chercher($saisie['saisies'], $nom, $retourner_chemin))) {
95                                                return $retourner_chemin ? array_merge($chemin, array('saisies'), $retour) : $retour;
96                                }
97
98                        }
99                }
100                elseif (is_array($id_ou_nom_ou_chemin)){
101                        $chemin = $id_ou_nom_ou_chemin;
102                        $saisie = $saisies;
103                        // On vérifie l'existence quand même
104                        foreach ($chemin as $cle){
105                                if (isset($saisie[$cle])) $saisie = $saisie[$cle];
106                                else return null;
107                        }
108                        // Si c'est une vraie saisie
109                        if ($saisie['saisie'] and $saisie['options']['nom'])
110                                return $retourner_chemin ? $chemin : $saisie;
111                }
112        }
113       
114        return null;
115}
116
117/**
118 * Génère un nom unique pour un champ d'un formulaire donné
119 *
120 * @param array $formulaire
121 *     Le formulaire à analyser
122 * @param string $type_saisie
123 *     Le type de champ dont on veut un identifiant
124 * @return string
125 *     Un nom unique par rapport aux autres champs du formulaire
126 */
127function saisies_generer_nom($formulaire, $type_saisie){
128        $champs = saisies_lister_champs($formulaire);
129       
130        // Tant que type_numero existe, on incrémente le compteur
131        $compteur = 1;
132        while (array_search($type_saisie.'_'.$compteur, $champs) !== false)
133                $compteur++;
134       
135        // On a alors un compteur unique pour ce formulaire
136        return $type_saisie.'_'.$compteur;
137}
138
139/*
140 * Crée un identifiant Unique
141 * pour toutes les saisies donnees qui n'en ont pas
142 *
143 * @param Array $saisies Tableau de saisies
144 * @param Bool $regenerer_id Régénère un nouvel identifiant pour toutes les saisies ?
145 * @return Array Tableau de saisies complété des identifiants
146 */
147function saisies_identifier($saisies, $regenerer = false) {
148        if (!is_array($saisies)) {
149                return array();
150        }
151        foreach ($saisies as $k => $saisie) {
152                $saisies[$k] = saisie_identifier($saisie, $regenerer);
153        }
154        return $saisies;
155}
156
157/**
158 * Crée un identifiant Unique
159 * pour la saisie donnee si elle n'en a pas
160 * (et pour ses sous saisies éventuels)
161 *
162 * @param Array $saisie Tableau d'une saisie
163 * @param Bool $regenerer_id Régénère un nouvel identifiant pour la saisie ?
164 * @return Array Tableau de la saisie complété de l'identifiant
165**/
166function saisie_identifier($saisie, $regenerer = false) {
167        if (!isset($saisie['identifiant']) OR !$saisie['identifiant']) {
168                $saisie['identifiant'] = uniqid('@');
169        } elseif ($regenerer) {
170                $saisie['identifiant'] = uniqid('@');
171        }
172        if (isset($saisie['saisies']) AND is_array($saisie['saisies'])) {
173                $saisie['saisies'] = saisies_identifier($saisie['saisies'], $regenerer);
174        }
175        return $saisie;
176}
177
178/*
179 * Vérifier tout un formulaire tel que décrit avec les Saisies
180 *
181 * @param array $formulaire Le contenu d'un formulaire décrit dans un tableau de Saisies
182 * @param bool $saisies_masquees_nulles Si TRUE, les saisies masquées selon afficher_si ne seront pas verifiées, leur valeur étant forcée a NULL. Cette valeur NULL est transmise à traiter (via set_request).
183 * @return array Retourne un tableau d'erreurs
184 */
185function saisies_verifier($formulaire, $saisies_masquees_nulles=true){
186        include_spip('inc/verifier');
187        $erreurs = array();
188        $verif_fonction = charger_fonction('verifier','inc',true);
189
190        if ($saisies_masquees_nulles)
191                $formulaire = saisies_verifier_afficher_si($formulaire);
192       
193        $saisies = saisies_lister_par_nom($formulaire);
194        foreach ($saisies as $saisie){
195                $obligatoire = isset($saisie['options']['obligatoire']) ? $saisie['options']['obligatoire'] : '';
196                $champ = $saisie['options']['nom'];
197                $file = ($saisie['saisie'] == 'input' and isset($saisie['options']['type']) and $saisie['options']['type'] == 'file');
198                $verifier = isset($saisie['verifier']) ? $saisie['verifier'] : false;
199
200                // Si le nom du champ est un tableau indexé, il faut parser !
201                if (preg_match('/([\w]+)((\[[\w]+\])+)/', $champ, $separe)){
202                        $valeur = _request($separe[1]);
203                        preg_match_all('/\[([\w]+)\]/', $separe[2], $index);
204                        // On va chercher au fond du tableau
205                        foreach($index[1] as $cle){
206                                $valeur = isset($valeur[$cle]) ? $valeur[$cle] : null;
207                        }
208                }
209                // Sinon la valeur est juste celle du nom
210                else
211                        $valeur = _request($champ);
212               
213                // On regarde d'abord si le champ est obligatoire
214                if ($obligatoire
215                        and $obligatoire != 'non'
216                        and (
217                                ($file and !$_FILES[$champ]['name'])
218                                or (!$file and (
219                                        is_null($valeur)
220                                        or (is_string($valeur) and trim($valeur) == '')
221                                        or (is_array($valeur) and count($valeur) == 0)
222                                ))
223                        )
224                ) {
225                        $erreurs[$champ] =
226                                (isset($saisie['options']['erreur_obligatoire']) and $saisie['options']['erreur_obligatoire'])
227                                ? $saisie['options']['erreur_obligatoire']
228                                : _T('info_obligatoire');
229                }
230
231                // On continue seulement si ya pas d'erreur d'obligation et qu'il y a une demande de verif
232                if ((!isset($erreurs[$champ]) or !$erreurs[$champ]) and is_array($verifier) and $verif_fonction){
233                        $normaliser = null;
234                        // Si le champ n'est pas valide par rapport au test demandé, on ajoute l'erreur
235                        $options = isset($verifier['options']) ? $verifier['options'] : array();
236                        if ($erreur_eventuelle = $verif_fonction($valeur, $verifier['type'], $options, $normaliser)) {
237                                $erreurs[$champ] = $erreur_eventuelle;
238                        // S'il n'y a pas d'erreur et que la variable de normalisation a été remplie, on l'injecte dans le POST
239                        } elseif (!is_null($normaliser)) {
240                                set_request($champ, $normaliser);
241                        }
242                }
243        }
244       
245        return $erreurs;
246}
247
248/*
249 * Transforme une chaine en tableau avec comme principe :
250 * - une ligne devient une case
251 * - si la ligne est de la forme truc|bidule alors truc est la clé et bidule la valeur
252 * - si la ligne commence par * alors on commence un sous-tableau
253 * @param string $chaine Une chaine à transformer
254 * @return array Retourne un tableau PHP
255 */
256function saisies_chaine2tableau($chaine, $separateur="\n"){
257        if ($chaine and is_string($chaine)){
258                $tableau = array();
259                $soustab = False;
260                // On découpe d'abord en lignes
261                $lignes = explode($separateur, $chaine);
262                foreach ($lignes as $i=>$ligne){
263                        $ligne = trim(trim($ligne), '|');
264                        // Si ce n'est pas une ligne sans rien
265                        if ($ligne !== ''){
266                                // si ca commence par * c'est qu'on va faire un sous tableau
267                                if (strpos($ligne,"*")===0){
268                                                $soustab=True;
269                                                $soustab_cle    = _T_ou_typo(substr($ligne,1), 'multi');
270                                                if (!isset($tableau[$soustab_cle])){
271                                                        $tableau[$soustab_cle] = array();
272                                                }
273                                        }
274                                else{//sinon c'est une entrée normale
275                                // Si on trouve un découpage dans la ligne on fait cle|valeur
276                                        if (strpos($ligne, '|') !== false){
277                                                list($cle,$valeur) = explode('|', $ligne, 2);
278                                                // permettre les traductions de valeurs au passage
279                                                if ($soustab == True){
280                                                        $tableau[$soustab_cle][$cle] = _T_ou_typo($valeur, 'multi');
281                                                        }
282                                                else{
283                                                        $tableau[$cle] = _T_ou_typo($valeur, 'multi');
284                                                        }
285                                        }
286                                // Sinon on génère la clé
287                                        else{
288                                                if ($soustab == True){
289                                                        $tableau[$soustab_cle][$i] = _T_ou_typo($ligne,'multi');
290                                                        }
291                                                else{
292                                                        $tableau[$i] = _T_ou_typo($ligne,'multi');
293                                                        }
294                                        }
295                                }
296                        }
297                }
298                return $tableau;
299        }
300        // Si c'est déjà un tableau on lui applique _T_ou_typo (qui fonctionne de manière récursive avant de le renvoyer
301        elseif (is_array($chaine)){
302                return _T_ou_typo($chaine, 'multi');
303        }
304        else{
305                return array();
306        }
307}
308
309/*
310 * Transforme un tableau en chaine de caractères avec comme principe :
311 * - une case de vient une ligne de la chaine
312 * - chaque ligne est générée avec la forme cle|valeur
313 * - si une entrée du tableau est elle même un tableau, on met une ligne de la forme *clef
314 */
315function saisies_tableau2chaine($tableau){
316        if ($tableau and is_array($tableau)){
317                $chaine = '';
318       
319                foreach($tableau as $cle=>$valeur){
320                        if (is_array($valeur)){
321                                $ligne=trim("*$cle");
322                                $chaine .= "$ligne\n";
323                                $chaine .= saisies_tableau2chaine($valeur)."\n";
324                                }
325                        else{   
326                                $ligne = trim("$cle|$valeur");
327                                $chaine .= "$ligne\n";
328                        }
329                }
330                $chaine = trim($chaine);
331       
332                return $chaine;
333        }
334        // Si c'est déjà une chaine on la renvoie telle quelle
335        elseif (is_string($tableau)){
336                return $tableau;
337        }
338        else{
339                return '';
340        }
341}
342
343
344
345
346/**
347 * Passe une valeur en tableau d'élements si ce n'en est pas une
348 *
349 * entrée :
350 * cle|valeur
351 * cle|valeur
352 *
353 * Sinon :
354 * valeur,valeur
355 *
356 * @param mixed $valeur
357 * @return array Tableau de valeurs
358**/
359function saisies_valeur2tableau($valeur, $sinon_separateur="") {
360        if (is_array($valeur)) {
361                return $valeur;
362        }
363       
364        if (!strlen($valeur)) {
365                return array();
366        }
367       
368        $t = saisies_chaine2tableau($valeur);
369        if (count($t) > 1) {
370                return $t;
371        }
372
373        // qu'une seule valeur, c'est qu'elle a peut etre un separateur a virgule
374        // et a donc une cle est 0 dans ce cas la d'ailleurs
375        if (isset($t[0])) {
376                $t = saisies_chaine2tableau($t[0], ',');
377        }
378       
379        return $t;
380}
381
382
383
384
385/*
386 * Génère une page d'aide listant toutes les saisies et leurs options
387 */
388function saisies_generer_aide(){
389        // On a déjà la liste par saisie
390        $saisies = saisies_lister_disponibles();
391       
392        // On construit une liste par options
393        $options = array();
394        foreach ($saisies as $type_saisie=>$saisie){
395                $options_saisie = saisies_lister_par_nom($saisie['options'], false);
396                foreach ($options_saisie as $nom=>$option){
397                        // Si l'option n'existe pas encore
398                        if (!isset($options[$nom])){
399                                $options[$nom] = _T_ou_typo($option['options']);
400                        }
401                        // On ajoute toujours par qui c'est utilisé
402                        $options[$nom]['utilisee_par'][] = $type_saisie;
403                }
404                ksort($options_saisie);
405                $saisies[$type_saisie]['options'] = $options_saisie;
406        }
407        ksort($options);
408       
409        return recuperer_fond(
410                'inclure/saisies_aide',
411                array(
412                        'saisies' => $saisies,
413                        'options' => $options
414                )
415        );
416}
417
418/*
419 * Le tableau de saisies a-t-il une option afficher_si ?
420 *
421 * @param array $saisies Un tableau de saisies
422 * @return boolean
423 */
424
425function saisies_afficher_si($saisies) {
426        $saisies = saisies_lister_par_nom($saisies,true);
427        // Dès qu'il y a au moins une option afficher_si, on l'active
428        foreach ($saisies as $saisie) {
429                if (isset($saisie['options']['afficher_si']))
430                        return true;
431        }
432        return false;
433}
434
435?>
Note: See TracBrowser for help on using the repository browser.