3 /***************************************************************************\
4 * SPIP, Systeme de publication pour l'internet *
6 * Copyright (c) 2001-2019 *
7 * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James *
9 * Ce programme est un logiciel libre distribue sous licence GNU/GPL. *
10 * Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne. *
11 \***************************************************************************/
16 * Module facilitant l'écriture de formulaires CVT
17 * en plusieurs étapes.
22 * Chaque étape est representée par un squelette indépendant qui doit
23 * implémenter un formulaire autonome pour les saisies de l'étape n :
25 * - formulaires/truc.html pour l'etape 1
26 * - formulaires/truc_2.html pour l'etape 2
27 * - formulaires/truc_n.html pour l'etape n
29 * Si un squelette `formulaires/truc_n.html` manque pour l'étape n
30 * c'est `formulaires/truc.html` qui sera utilisé
31 * (charge à lui de gérer le cas de cette étape).
34 * `formulaires_truc_charger_dist()` :
35 * passer '_etapes' => nombre total d'etapes de saisies (>1 !)
36 * indiquer toutes les valeurs à saisir sur toutes les pages
37 * comme si il s'agissait d'un formulaire unique
40 * Le numero d'étape courante est disponible dans `$x=_request('_etape')`, si nécessaire
41 * `_request()` permet d'accéder aux saisies effectuées depuis l'étape 1,
42 * comme si les étapes 1 a `$x` avaient été saisies en une seule fois
44 * - formulaires_truc_verifier_1_dist() : verifier les saisies de l'etape 1 uniquement
45 * - formulaires_truc_verifier_2_dist() : verifier les saisies de l'etape 2
46 * - formulaires_truc_verifier_n_dist() : verifier les saisies de l'etape n
48 * Il est possible d'implémenter toutes les vérifications dans une fonction unique
49 * qui sera alors appelée avec en premier argument le numero de l'étape à vérifier
50 * `formulaires_truc_verifier_etape_dist($etape,...)` : vérifier les saisies
51 * de l'étape `$etape` uniquement.
53 * À chaque étape x, les étapes 1 a x sont appelées en vérification
54 * pour vérifier l'absence de régression dans la validation (erreur, tentative de réinjection ...)
55 * en cas d'erreur, la saisie retourne à la première étape en erreur.
56 * en cas de succès, l'étape est incrémentée, sauf si c'est la dernière.
57 * Dans ce dernier cas on déclenche `traiter()`.
60 * `formulaires_truc_traiter_dist()` : ne sera appelé que lorsque **toutes**
61 * les étapes auront été saisies sans erreur.
63 * La fonction traiter peut donc traiter l'ensemble des saisies comme si il
64 * s'agissait d'un formulaire unique dans lequel toutes les données auraient
65 * été saisies en une fois.
68 if (!defined('_ECRIRE_INC_VERSION')) {
73 * Reinjecter dans _request() les valeurs postees
74 * dans les etapes precedentes
79 function cvtmulti_recuperer_post_precedents($form) {
80 include_spip('inc/filtres');
82 and $c = _request('cvtm_prev_post')
83 and $c = decoder_contexte_ajax($c, $form)
87 # reinjecter dans la bonne variable pour permettre de retrouver
88 # toutes les saisies dans un seul tableau
89 if ($_SERVER['REQUEST_METHOD'] == 'POST') {
95 foreach ($c as $k => $v) // on ecrase pas si saisi a nouveau !
97 if (!isset($store[$k])) {
98 $_REQUEST[$k] = $store[$k] = $v;
99 } // mais si tableau des deux cotes, on merge avec priorite a la derniere saisie
100 elseif (is_array($store[$k])
102 and $z = array_keys($v)
103 and !is_numeric(reset($z))
104 and $z = array_keys($store[$k])
105 and !is_numeric(reset($z))
107 $_REQUEST[$k] = $store[$k] = array_merge($v, $store[$k]);
111 // vider pour eviter un second appel a verifier_n
112 // en cas de double implementation (unipotence)
113 set_request('cvtm_prev_post');
115 return array($c['_etape'], $c['_etapes']);
122 * Sauvegarder les valeurs postees dans une variable encodee
123 * pour les recuperer a la prochaine etape
125 * @param string $form
126 * @param bool $je_suis_poste
127 * @param array $valeurs
130 function cvtmulti_sauver_post($form, $je_suis_poste, &$valeurs) {
131 if (!isset($valeurs['_cvtm_prev_post'])) {
132 $post = array('_etape' => $valeurs['_etape'], '_etapes' => $valeurs['_etapes']);
133 foreach (array_keys($valeurs) as $champ) {
134 if (substr($champ, 0, 1) !== '_') {
135 if ($je_suis_poste ||
(isset($valeurs['_forcer_request']) && $valeurs['_forcer_request'])) {
136 if (($v = _request($champ)) !== null) {
142 include_spip('inc/filtres');
143 $c = encoder_contexte_ajax($post, $form);
144 if (!isset($valeurs['_hidden'])) {
145 $valeurs['_hidden'] = '';
147 $valeurs['_hidden'] .= "<input type='hidden' name='cvtm_prev_post' value='$c' />";
148 // marquer comme fait, pour eviter double encodage (unipotence)
149 $valeurs['_cvtm_prev_post'] = true;
157 * Reperer une demande de formulaire CVT multi page
160 * @deprecated : appel direct de cvtmulti_formulaire_charger_etapes par le core
164 function cvtmulti_formulaire_charger($flux) {
165 if (is_array($flux['data'])
166 and isset($flux['data']['_etapes'])
168 $flux['data'] = cvtmulti_formulaire_charger_etapes($flux['args'], $flux['data']);
175 * Charger une etape du cvt multi
180 function cvtmulti_formulaire_charger_etapes($args, $valeurs) {
181 if (!isset($valeurs['_etape'])) {
182 $form = $args['form'];
183 $je_suis_poste = $args['je_suis_poste'];
184 $nb_etapes = $valeurs['_etapes'];
185 $etape = _request('_etape');
186 $etape = min(max($etape, 1), $nb_etapes);
187 set_request('_etape', $etape);
188 $valeurs['_etape'] = $etape;
190 // sauver les posts de cette etape pour les avoir a la prochaine etape
191 $valeurs = cvtmulti_sauver_post($form, $je_suis_poste, $valeurs);
198 * Verifier les etapes de saisie
200 * @deprecated : appel direct de cvtmulti_formulaire_verifier_etapes par le core
204 function cvtmulti_formulaire_verifier($flux) {
205 $flux['data'] = cvtmulti_formulaire_verifier_etapes($flux['args'], $flux['data']);
210 * Verifier les etapes de saisie
216 function cvtmulti_formulaire_verifier_etapes($args, $erreurs) {
217 #var_dump('Pipe verifier');
219 if ($form = $args['form']
220 and ($e = cvtmulti_recuperer_post_precedents($form)) !== false
222 // recuperer l'etape saisie et le nombre d'etapes total
223 list($etape, $etapes) = $e;
224 $etape_demandee = _request('aller_a_etape'); // possibilite de poster en entier dans aller_a_etape
226 // lancer les verifs pour chaque etape deja saisie de 1 a $etape
227 $erreurs_etapes = array();
228 $derniere_etape_ok = 0;
230 while ($e < $etape and $e < $etapes) {
232 $erreurs_etapes[$e] = array();
233 if ($verifier = charger_fonction("verifier_$e", "formulaires/$form/", true)) {
234 $erreurs_etapes[$e] = call_user_func_array($verifier, $args['args']);
235 } elseif ($verifier = charger_fonction("verifier_etape", "formulaires/$form/", true)) {
237 array_unshift($a, $e);
238 $erreurs_etapes[$e] = call_user_func_array($verifier, $a);
240 // et on appelle un pipeline dedie aux etapes, plus easy
242 $erreurs_etapes[$e] = pipeline(
243 'formulaire_verifier_etape',
246 'data' => $erreurs_etapes[$e]
250 if ($derniere_etape_ok == $e - 1 and !count($erreurs_etapes[$e])) {
251 $derniere_etape_ok = $e;
253 // possibilite de poster dans _retour_etape_x
254 if (!is_null(_request("_retour_etape_$e"))) {
255 $etape_demandee = $e;
259 // si la derniere etape OK etait la derniere
260 // on renvoie le flux inchange et ca declenche traiter
261 if ($derniere_etape_ok == $etapes and !$etape_demandee) {
264 $etape = $derniere_etape_ok +
1;
265 if ($etape_demandee > 0 and $etape_demandee < $etape) {
266 $etape = $etape_demandee;
268 $etape = min($etape, $etapes);
269 #var_dump("prochaine etape $etape");
270 // retourner les erreurs de l'etape ciblee
271 $erreurs = isset($erreurs_etapes[$etape]) ?
$erreurs_etapes[$etape] : array();
272 // Ne pas se tromper dans le texte du message d'erreur : la clé '_etapes' n'est pas une erreur !
274 $erreurs['message_erreur'] = singulier_ou_pluriel(count($erreurs), 'avis_1_erreur_saisie', 'avis_nb_erreurs_saisie');
276 $erreurs['message_erreur'] = "";
278 $erreurs['_etapes'] = "etape suivante $etape";
279 set_request('_etape', $etape);
287 * Selectionner le bon fond en fonction de l'etape
288 * L'etape 1 est sur le fond sans suffixe
289 * Les autres etapes x sont sur le fond _x
294 function cvtmulti_styliser($flux) {
295 if (strncmp($flux['args']['fond'], 'formulaires/', 12) == 0
296 and isset($flux['args']['contexte']['_etapes'])
297 and isset($flux['args']['contexte']['_etape'])
298 and ($e = $flux['args']['contexte']['_etape']) > 1
299 and $ext = $flux['args']['ext']
300 and $f = $flux['data']
301 and file_exists($f . "_$e.$ext")
303 $flux['data'] = $f . "_$e";