319 lines
10 KiB
PHP
319 lines
10 KiB
PHP
|
<?php
|
||
|
|
||
|
/***************************************************************************\
|
||
|
* SPIP, Systeme de publication pour l'internet *
|
||
|
* *
|
||
|
* Copyright (c) 2001-2019 *
|
||
|
* Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James *
|
||
|
* *
|
||
|
* Ce programme est un logiciel libre distribue sous licence GNU/GPL. *
|
||
|
* Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne. *
|
||
|
\***************************************************************************/
|
||
|
|
||
|
/**
|
||
|
* CVT Multi étapes
|
||
|
*
|
||
|
* Module facilitant l'écriture de formulaires CVT
|
||
|
* en plusieurs étapes.
|
||
|
*
|
||
|
* `#FORMULAIRE_TRUC`
|
||
|
*
|
||
|
* Squelette :
|
||
|
* Chaque étape est representée par un squelette indépendant qui doit
|
||
|
* implémenter un formulaire autonome pour les saisies de l'étape n :
|
||
|
*
|
||
|
* - formulaires/truc.html pour l'etape 1
|
||
|
* - formulaires/truc_2.html pour l'etape 2
|
||
|
* - formulaires/truc_n.html pour l'etape n
|
||
|
*
|
||
|
* Si un squelette `formulaires/truc_n.html` manque pour l'étape n
|
||
|
* c'est `formulaires/truc.html` qui sera utilisé
|
||
|
* (charge à lui de gérer le cas de cette étape).
|
||
|
*
|
||
|
* Charger :
|
||
|
* `formulaires_truc_charger_dist()` :
|
||
|
* passer '_etapes' => nombre total d'etapes de saisies (>1 !)
|
||
|
* indiquer toutes les valeurs à saisir sur toutes les pages
|
||
|
* comme si il s'agissait d'un formulaire unique
|
||
|
*
|
||
|
* Vérifier :
|
||
|
* Le numero d'étape courante est disponible dans `$x=_request('_etape')`, si nécessaire
|
||
|
* `_request()` permet d'accéder aux saisies effectuées depuis l'étape 1,
|
||
|
* comme si les étapes 1 a `$x` avaient été saisies en une seule fois
|
||
|
*
|
||
|
* - formulaires_truc_verifier_1_dist() : verifier les saisies de l'etape 1 uniquement
|
||
|
* - formulaires_truc_verifier_2_dist() : verifier les saisies de l'etape 2
|
||
|
* - formulaires_truc_verifier_n_dist() : verifier les saisies de l'etape n
|
||
|
*
|
||
|
* Il est possible d'implémenter toutes les vérifications dans une fonction unique
|
||
|
* qui sera alors appelée avec en premier argument le numero de l'étape à vérifier
|
||
|
* `formulaires_truc_verifier_etape_dist($etape,...)` : vérifier les saisies
|
||
|
* de l'étape `$etape` uniquement.
|
||
|
*
|
||
|
* À chaque étape x, les étapes 1 a x sont appelées en vérification
|
||
|
* pour vérifier l'absence de régression dans la validation (erreur, tentative de réinjection ...)
|
||
|
* en cas d'erreur, la saisie retourne à la première étape en erreur.
|
||
|
* en cas de succès, l'étape est incrémentée, sauf si c'est la dernière.
|
||
|
* Dans ce dernier cas on déclenche `traiter()`.
|
||
|
*
|
||
|
* Traiter :
|
||
|
* `formulaires_truc_traiter_dist()` : ne sera appelé que lorsque **toutes**
|
||
|
* les étapes auront été saisies sans erreur.
|
||
|
*
|
||
|
* La fonction traiter peut donc traiter l'ensemble des saisies comme si il
|
||
|
* s'agissait d'un formulaire unique dans lequel toutes les données auraient
|
||
|
* été saisies en une fois.
|
||
|
*/
|
||
|
|
||
|
if (!defined('_ECRIRE_INC_VERSION')) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Reinjecter dans _request() les valeurs postees
|
||
|
* dans les etapes precedentes
|
||
|
*
|
||
|
* @param string $form
|
||
|
* @return array
|
||
|
*/
|
||
|
function cvtmulti_recuperer_post_precedents($form) {
|
||
|
include_spip('inc/filtres');
|
||
|
if ($form
|
||
|
and $c = _request('cvtm_prev_post')
|
||
|
and $c = decoder_contexte_ajax($c, $form)
|
||
|
) {
|
||
|
#var_dump($c);
|
||
|
|
||
|
# reinjecter dans la bonne variable pour permettre de retrouver
|
||
|
# toutes les saisies dans un seul tableau
|
||
|
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
|
||
|
$store = &$_POST;
|
||
|
} else {
|
||
|
$store = &$_GET;
|
||
|
}
|
||
|
|
||
|
foreach ($c as $k => $v) // on ecrase pas si saisi a nouveau !
|
||
|
{
|
||
|
if (!isset($store[$k])) {
|
||
|
$_REQUEST[$k] = $store[$k] = $v;
|
||
|
} // mais si tableau des deux cotes, on merge avec priorite a la derniere saisie
|
||
|
elseif (is_array($store[$k])
|
||
|
and is_array($v)
|
||
|
and $z = array_keys($v)
|
||
|
and !is_numeric(reset($z))
|
||
|
and $z = array_keys($store[$k])
|
||
|
and !is_numeric(reset($z))
|
||
|
) {
|
||
|
$_REQUEST[$k] = $store[$k] = array_merge($v, $store[$k]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// vider pour eviter un second appel a verifier_n
|
||
|
// en cas de double implementation (unipotence)
|
||
|
set_request('cvtm_prev_post');
|
||
|
|
||
|
return array($c['_etape'], $c['_etapes']);
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sauvegarder les valeurs postees dans une variable encodee
|
||
|
* pour les recuperer a la prochaine etape
|
||
|
*
|
||
|
* @param string $form
|
||
|
* @param bool $je_suis_poste
|
||
|
* @param array $valeurs
|
||
|
* @return array
|
||
|
*/
|
||
|
function cvtmulti_sauver_post($form, $je_suis_poste, &$valeurs) {
|
||
|
if (!isset($valeurs['_cvtm_prev_post'])) {
|
||
|
$post = array('_etape' => $valeurs['_etape'], '_etapes' => $valeurs['_etapes']);
|
||
|
foreach (array_keys($valeurs) as $champ) {
|
||
|
if (substr($champ, 0, 1) !== '_') {
|
||
|
if ($je_suis_poste || (isset($valeurs['_forcer_request']) && $valeurs['_forcer_request'])) {
|
||
|
if (($v = _request($champ)) !== null) {
|
||
|
$post[$champ] = $v;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
include_spip('inc/filtres');
|
||
|
$c = encoder_contexte_ajax($post, $form);
|
||
|
if (!isset($valeurs['_hidden'])) {
|
||
|
$valeurs['_hidden'] = '';
|
||
|
}
|
||
|
$valeurs['_hidden'] .= "<input type='hidden' name='cvtm_prev_post' value='$c' />";
|
||
|
// marquer comme fait, pour eviter double encodage (unipotence)
|
||
|
$valeurs['_cvtm_prev_post'] = true;
|
||
|
}
|
||
|
|
||
|
return $valeurs;
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Reperer une demande de formulaire CVT multi page
|
||
|
* et la reformater
|
||
|
*
|
||
|
* @deprecated : appel direct de cvtmulti_formulaire_charger_etapes par le core
|
||
|
* @param array $flux
|
||
|
* @return array
|
||
|
*/
|
||
|
function cvtmulti_formulaire_charger($flux) {
|
||
|
if (is_array($flux['data'])
|
||
|
and isset($flux['data']['_etapes'])
|
||
|
) {
|
||
|
$flux['data'] = cvtmulti_formulaire_charger_etapes($flux['args'], $flux['data']);
|
||
|
}
|
||
|
|
||
|
return $flux;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Charger une etape du cvt multi
|
||
|
* @param $args
|
||
|
* @param $valeurs
|
||
|
* @return array
|
||
|
*/
|
||
|
function cvtmulti_formulaire_charger_etapes($args, $valeurs) {
|
||
|
if (!isset($valeurs['_etape'])) {
|
||
|
$form = $args['form'];
|
||
|
$je_suis_poste = $args['je_suis_poste'];
|
||
|
$nb_etapes = $valeurs['_etapes'];
|
||
|
$etape = _request('_etape');
|
||
|
$etape = min(max($etape, 1), $nb_etapes);
|
||
|
set_request('_etape', $etape);
|
||
|
$valeurs['_etape'] = $etape;
|
||
|
|
||
|
// sauver les posts de cette etape pour les avoir a la prochaine etape
|
||
|
$valeurs = cvtmulti_sauver_post($form, $je_suis_poste, $valeurs);
|
||
|
}
|
||
|
return $valeurs;
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Verifier les etapes de saisie
|
||
|
*
|
||
|
* @deprecated : appel direct de cvtmulti_formulaire_verifier_etapes par le core
|
||
|
* @param array $flux
|
||
|
* @return array
|
||
|
*/
|
||
|
function cvtmulti_formulaire_verifier($flux) {
|
||
|
$flux['data'] = cvtmulti_formulaire_verifier_etapes($flux['args'], $flux['data']);
|
||
|
return $flux;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Verifier les etapes de saisie
|
||
|
*
|
||
|
* @param array $args
|
||
|
* @param $erreurs
|
||
|
* @return array
|
||
|
*/
|
||
|
function cvtmulti_formulaire_verifier_etapes($args, $erreurs) {
|
||
|
#var_dump('Pipe verifier');
|
||
|
|
||
|
if ($form = $args['form']
|
||
|
and ($e = cvtmulti_recuperer_post_precedents($form)) !== false
|
||
|
) {
|
||
|
// recuperer l'etape saisie et le nombre d'etapes total
|
||
|
list($etape, $etapes) = $e;
|
||
|
$etape_demandee = intval(_request('aller_a_etape')); // possibilite de poster un entier dans aller_a_etape
|
||
|
|
||
|
$args['etape_saisie'] = $etape;
|
||
|
$args['etapes'] = $etapes;
|
||
|
// lancer les verifs pour chaque etape deja saisie de 1 a $etape
|
||
|
$erreurs_etapes = array();
|
||
|
$derniere_etape_ok = 0;
|
||
|
$e = 0;
|
||
|
while ($e < max($etape, $etape_demandee -1) and $e < $etapes) {
|
||
|
$e++;
|
||
|
$erreurs_etapes[$e] = array();
|
||
|
if ($verifier = charger_fonction("verifier_$e", "formulaires/$form/", true)) {
|
||
|
$erreurs_etapes[$e] = call_user_func_array($verifier, $args['args']);
|
||
|
} elseif ($verifier = charger_fonction("verifier_etape", "formulaires/$form/", true)) {
|
||
|
$a = $args['args'];
|
||
|
array_unshift($a, $e);
|
||
|
$erreurs_etapes[$e] = call_user_func_array($verifier, $a);
|
||
|
}
|
||
|
// et on appelle un pipeline dedie aux etapes, plus easy
|
||
|
$args['etape'] = $e;
|
||
|
$args['etape_demandee'] = $etape_demandee;
|
||
|
$erreurs_etapes[$e] = pipeline(
|
||
|
'formulaire_verifier_etape',
|
||
|
array(
|
||
|
'args' => $args,
|
||
|
'data' => $erreurs_etapes[$e]
|
||
|
)
|
||
|
);
|
||
|
|
||
|
if ($derniere_etape_ok == $e - 1 and !count($erreurs_etapes[$e])) {
|
||
|
$derniere_etape_ok = $e;
|
||
|
}
|
||
|
// possibilite de poster dans _retour_etape_x ou aller_a_etape
|
||
|
if (!is_null(_request("_retour_etape_$e"))) {
|
||
|
$etape_demandee = $e;
|
||
|
}
|
||
|
// Il se peut que les verifications ait décidé de faire sauter des étapes
|
||
|
if ($aller_a_etape = intval(_request('aller_a_etape'))) {
|
||
|
$etape_demandee = $aller_a_etape; // possibilite de poster un entier dans aller_a_etape
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
// si la derniere etape OK etait la derniere
|
||
|
// on renvoie le flux inchange et ca declenche traiter
|
||
|
if ($derniere_etape_ok == $etapes
|
||
|
and (!$etape_demandee or $etape_demandee>=$etapes)) {
|
||
|
return $erreurs;
|
||
|
} else {
|
||
|
$etape = $derniere_etape_ok + 1;
|
||
|
if ($etape_demandee > 0 and $etape_demandee < $etape) {
|
||
|
$etape = $etape_demandee;
|
||
|
}
|
||
|
$etape = min($etape, $etapes);
|
||
|
#var_dump("prochaine etape $etape");
|
||
|
// retourner les erreurs de l'etape ciblee
|
||
|
$erreurs = isset($erreurs_etapes[$etape]) ? $erreurs_etapes[$etape] : array();
|
||
|
// Ne pas se tromper dans le texte du message d'erreur : la clé '_etapes' n'est pas une erreur !
|
||
|
if ($erreurs) {
|
||
|
if (!isset($erreurs['message_erreur'])) {
|
||
|
$erreurs['message_erreur'] = singulier_ou_pluriel(count($erreurs), 'avis_1_erreur_saisie', 'avis_nb_erreurs_saisie');
|
||
|
}
|
||
|
} else {
|
||
|
$erreurs['message_erreur'] = "";
|
||
|
}
|
||
|
$erreurs['_etapes'] = "etape suivante $etape";
|
||
|
set_request('_etape', $etape);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return $erreurs;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Selectionner le bon fond en fonction de l'etape
|
||
|
* L'etape 1 est sur le fond sans suffixe
|
||
|
* Les autres etapes x sont sur le fond _x
|
||
|
*
|
||
|
* @param array $flux
|
||
|
* @return array
|
||
|
*/
|
||
|
function cvtmulti_styliser($flux) {
|
||
|
if (strncmp($flux['args']['fond'], 'formulaires/', 12) == 0
|
||
|
and isset($flux['args']['contexte']['_etapes'])
|
||
|
and isset($flux['args']['contexte']['_etape'])
|
||
|
and ($e = $flux['args']['contexte']['_etape']) > 1
|
||
|
and $ext = $flux['args']['ext']
|
||
|
and $f = $flux['data']
|
||
|
and file_exists($f . "_$e.$ext")
|
||
|
) {
|
||
|
$flux['data'] = $f . "_$e";
|
||
|
}
|
||
|
|
||
|
return $flux;
|
||
|
}
|