Skip to content
Extraits de code Groupes Projets
Valider c12776ca rédigé par rastapopoulos@spip.org's avatar rastapopoulos@spip.org
Parcourir les fichiers

Nouvelle fonctionnalité : on utilise toutes les modifs faites en amont sur...

Nouvelle fonctionnalité : on utilise toutes les modifs faites en amont sur Saisies. On peut donc maintenant configurer certaines options globales dans l'interface du constructeur. Pour cela on déclare au constructeur quelles options on accepte (c'est propre au contexte de Formidable).

Dans le lot, il y a donc la personnalisation du bouton final, et… le multi-étapes !

Pour cela, il a fallu faire un refactoring de la fonction verifier() de Formidable où tout était en dur… On l'a donc vidé de son contenu, afin que Formidable utilise enfin l'API CVT de Saisies avec la fonction saisies().

Au passsage, il y avait une vérification propre à un traitement (enregistrement) sur l'unicité : on en profite pour mettre en place un fonctionnement générique et extensible. Tout type de traitement peut désormais déclarer une fonction de vérification qui lui est propre avec traiter/montraitement_verifier(). Et si ça existe, ça sera utilisé.

Il reste un problème avec ce dernier point : pour le cas habituel ça continue de marcher pareil MAIS quand on active les étapes… Pour le moment j'ai fait le choix lorsqu'il y a étapes, de lancer ces vérifications propres aux traitements à la toute fin, quand on sait qu'on est à la dernière étape. Mais du coup ça ne va pas, car les erreurs ajoutées peuvent être sur des champs qui sont à d'autres étapes. Et CVT ne le sait pas, il reste sur la dernière étape. Donc ça montre "Vous avez X erreurs" en haut, mais on ne voit pas forcément le ou les champs précis en erreur s'ils sont ailleurs. Je ne sais pas encore comment résoudre ça…
parent 94201147
Aucune branche associée trouvée
Aucune étiquette associée trouvée
Aucune requête de fusion associée trouvée
......@@ -6,7 +6,7 @@
[(#ENV*{message_erreur}|non)
<div class="ajax">
#FORMULAIRE_CONSTRUIRE_FORMULAIRE{#ENV{saisie_id}, #ENV{_saisies}}
#FORMULAIRE_CONSTRUIRE_FORMULAIRE{#ENV{saisie_id}, #ENV{_saisies}, #ARRAY{options_globales,#ENV{_options_globales}}}
</div>
]
......
......@@ -21,6 +21,39 @@ function formulaires_editer_formulaire_champs_charger($id_formulaire) {
$contexte['_saisies'] = $saisies;
$contexte['id'] = $id_formulaire;
$contexte['saisie_id'] = "formidable_$id_formulaire";
// Les options globales que l'on permet de configurer pour le contexte de Formidables
$contexte['_options_globales'] = array(
array(
'saisie' => 'input',
'options' => array(
'nom' => 'texte_submit',
'label' => _T('formidable:editer_globales_texte_submit_label'),
),
),
array(
'saisie' => 'case',
'options' => array(
'nom' => 'etapes_activer',
'label_case' => _T('formidable:editer_globales_etapes_activer_label_case'),
'explication' => _T('formidable:editer_globales_etapes_activer_explication'),
),
),
array(
'saisie' => 'input',
'options' => array(
'nom' => 'etapes_suivant',
'label' => _T('formidable:editer_globales_etapes_suivant_label'),
),
),
array(
'saisie' => 'input',
'options' => array(
'nom' => 'etapes_precedent',
'label' => _T('formidable:editer_globales_etapes_precedent_label'),
),
),
);
}
return $contexte;
......
......@@ -9,26 +9,38 @@
[(#ENV{editable}|oui)
[(#ENV{_saisies}|et{#ENV{_saisies}|count}|oui)
<form method='post' action='[(#ENV{action}|ancre_url{[formulaire_#ENV{form}-(#ENV{id,nouveau})]})]' enctype='multipart/form-data'><div>
[(#REM) declarer les hidden qui declencheront le service du formulaire
parametre : url d'action ]
#ACTION_FORMULAIRE{#ENV{action}}
<[(#VAL{ul}|saisie_balise_structure_formulaire)] class="editer-groupe">
#GENERER_SAISIES{#ENV{_saisies}}
<[(#VAL{li}|saisie_balise_structure_formulaire)] style="display:none;">
<label for="mechantrobot-#ENV{id}"><:antispam_champ_vide:></label>
<input type="text" id="mechantrobot-#ENV{id}" name="mechantrobot" value="#ENV{mechantrobot}" />
</[(#VAL{li}|saisie_balise_structure_formulaire)]>
</[(#VAL{ul}|saisie_balise_structure_formulaire)]>
<form method='post' action='[(#ENV{action}|ancre_url{[formulaire_#ENV{form}-(#ENV{id,nouveau})]})]' enctype='multipart/form-data'><div>
[(#REM) declarer les hidden qui declencheront le service du formulaire
parametre : url d'action ]
#ACTION_FORMULAIRE{#ENV{action}}
[(#ENV{_etape}|oui)
#SET{etapes, #ENV{_saisies}|saisies_lister_par_etapes}
<INCLURE{fond=formulaires/inc-saisies-cvt-etapes, etapes=#GET{etapes}, env} />
]
<[(#VAL{ul}|saisie_balise_structure_formulaire)] class="editer-groupe">
#SET{saisies, #ENV{_saisies}}
[(#ENV{_etape}|oui)
#SET{saisies, #GET{etapes}|table_valeur{#ENV{_etape}/saisies}}
]
#GENERER_SAISIES{#GET{saisies}}
<[(#VAL{li}|saisie_balise_structure_formulaire)] style="display:none;">
<label for="mechantrobot-#ENV{id}"><:antispam_champ_vide:></label>
<input type="text" id="mechantrobot-#ENV{id}" name="mechantrobot" value="#ENV{mechantrobot}" />
</[(#VAL{li}|saisie_balise_structure_formulaire)]>
</[(#VAL{ul}|saisie_balise_structure_formulaire)]>
[(#REM) ajouter les saisies supplementaires : extra et autre, a cet endroit ]
<!--extra-->
[(#REM) ajouter les saisies supplementaires : extra et autre, a cet endroit ]
<!--extra-->
<INCLURE{fond=formulaires/inc-formidable-boutons,id_formulaire=#ENV{id}} />
</div></form>
]
<INCLURE{fond=formulaires/inc-formidable-boutons, id_formulaire=#ENV{id}, env} />
</div></form>
]
[(#ENV{_saisies}|et{#ENV{_saisies}|count}|non)
<p class="notice"><:formidable:formulaires_aucun_champ:></p>
<p class="notice"><:formidable:formulaires_aucun_champ:></p>
]
]
[(#ENV{editable}|non)
......
......@@ -45,6 +45,46 @@ function formidable_id_formulaire($id) {
return $id_formulaires[$id] = $id_formulaire;
}
/**
* Déclaration des saisies du formulaire à l'API Saisies.
*
* @param int|string $id
* Identifiant numerique ou textuel du formulaire formidable
* @param array $valeurs
* Valeurs par défauts passées au contexte du formulaire
* Exemple : array('hidden_1' => 3) pour que champ identifie "@hidden_1@" soit prerempli
* @param int|bool $id_formulaires_reponse
* Identifiant d'une réponse pour forcer la reedition de cette reponse spécifique
*
* @return array
* Tableau des saisies
**/
function formulaires_formidable_saisies_dist($id, $valeurs = array(), $id_formulaires_reponse = false) {
$saisies = array();
if (
$id_formulaire = formidable_id_formulaire($id)
and $formulaire = sql_fetsel('*', 'spip_formulaires', 'id_formulaire = ' . intval($id_formulaire))
) {
$saisies = unserialize($formulaire['saisies']);
// Si on est en train de réafficher les valeurs postées,
// ne pas afficher les saisies hidden
if (
$formulaire['apres'] == 'valeurs'
and _request('formidable_afficher_apres') == 'valeurs'
and _request('formidable_traiter_ok') == true
) {
$champs_hidden = saisies_lister_avec_type($saisies, 'hidden');
foreach ($champs_hidden as $champ => $desc) {
$saisies = saisies_supprimer($saisies, $champ);
}
}
}
return $saisies;
}
/**
* Chargement du formulaire CVT de Formidable.
*
......@@ -61,7 +101,7 @@ function formidable_id_formulaire($id) {
* @return array
* Contexte envoyé au squelette HTML du formulaire.
**/
function formulaires_formidable_charger($id, $valeurs = array(), $id_formulaires_reponse = false) {
function formulaires_formidable_charger_dist($id, $valeurs = array(), $id_formulaires_reponse = false) {
$contexte = array();
// On peut donner soit un id soit un identifiant
......@@ -79,25 +119,9 @@ function formulaires_formidable_charger($id, $valeurs = array(), $id_formulaires
// Est-ce que la personne a le droit de répondre ?
if (autoriser('repondre', 'formulaire', $formulaire['id_formulaire'], null, array('formulaire' => $formulaire))) {
$saisies = unserialize($formulaire['saisies']);
$traitements = unserialize($formulaire['traitements']);
// Si on est en train de réafficher les valeurs postées,
// ne pas afficher les saisies hidden
if ($formulaire['apres'] == 'valeurs'
and _request('formidable_afficher_apres') == 'valeurs'
and _request('erreurs') == false
) {
$champs_hidden = saisies_lister_avec_type($saisies, 'hidden');
foreach ($champs_hidden as $champ => $desc) {
$saisies = saisies_supprimer($saisies, $champ);
}
}
// On déclare les champs avec les valeurs par défaut
$contexte = array_merge(saisies_lister_valeurs_defaut($saisies), $contexte);
$contexte['mechantrobot'] = '';
// On ajoute le formulaire complet
$contexte['_saisies'] = $saisies;
$contexte['id'] = $formulaire['id_formulaire'];
$contexte['_hidden'] = '<input type="hidden" name="id_formulaire" value="' . $contexte['id'] . '"/>';
......@@ -185,81 +209,97 @@ function formulaires_formidable_charger($id, $valeurs = array(), $id_formulaires
* @return array
* Tableau des erreurs
**/
function formulaires_formidable_verifier($id, $valeurs = array(), $id_formulaires_reponse = false) {
function formulaires_formidable_verifier_dist($id, $valeurs = array(), $id_formulaires_reponse = false) {
$erreurs = array();
// On peut donner soit un id soit un identifiant
if (!$id_formulaire = formidable_id_formulaire($id)) {
$erreurs['message_erreur'] = _T('formidable:erreur_base');
} else {
// Sale bête !
if (_request('mechantrobot')!='') {
$erreurs['hahahaha'] = 'hahahaha';
return $erreurs;
}
$formulaire = sql_fetsel('*', 'spip_formulaires', 'id_formulaire = ' . intval($id_formulaire));
$saisies = unserialize($formulaire['saisies']);
$erreurs_par_fichier = array();
$erreurs = saisies_verifier($saisies, true, $erreurs_par_fichier);
include_spip('inc/saisies');
$saisies = saisies_chercher_formulaire('formidable', array($id, $valeurs, $id_formulaires_reponse));
// Si on n'est pas dans un formulaire à étape, on lance les vérifications des traitements
if ($saisies and !saisies_lister_par_etapes($saisies)) {
$erreurs = formulaires_formidable_verifier_traitements($id, $valeurs, $id_formulaires_reponse);
}
// Sale bête ! Ça on le fait tout le temps
if (_request('mechantrobot')!='') {
$erreurs['hahahaha'] = 'hahahaha';
}
return $erreurs;
}
// On supprime de $_FILES les fichiers envoyés qui ne passent pas le test de vérification
/**
* Vérification du formulaire CVT de Formidable mais s'il y a des étapes
*
* @param int|string $id
* Identifiant numerique ou textuel du formulaire formidable
* @param array $valeurs
* Valeurs par défauts passées au contexte du formulaire
* Exemple : array('hidden_1' => 3) pour que champ identifie "@hidden_1@" soit prerempli
* @param int|bool $id_formulaires_reponse
* Identifiant d'une réponse pour forcer la reedition de cette reponse spécifique
*
* @return array
* Tableau des erreurs
**/
function formulaires_formidable_verifier_etape_dist($etape, $id, $valeurs = array(), $id_formulaires_reponse = false) {
$erreurs = array();
include_spip('inc/saisies');
$saisies = saisies_chercher_formulaire('formidable', array($id, $valeurs, $id_formulaires_reponse));
// Seulement si on est à la DERNIÈRE étape, on lance les vérifications propres aux traitements
if ($saisies and $etapes = saisies_lister_par_etapes($saisies) and $etape==count($etapes)) {
$erreurs = formulaires_formidable_verifier_traitements($id, $valeurs, $id_formulaires_reponse);
}
return $erreurs;
}
$plugins_actifs = liste_plugin_actifs();
if (isset($plugins_actifs['CVTUPLOAD'])) {
include_spip('inc/cvtupload');
foreach ($erreurs as $champ => $erreur) {
if (isset($erreurs_par_fichier[$champ])) {
cvtupload_nettoyer_files_selon_erreurs($champ, $erreurs_par_fichier[$champ]);
}
}
}
// Si on a pas déjà une erreur sur le champ unicite, on lance une verification
/**
* Lancer des vérifications propres aux traitements
*
* @param int|string $id
* Identifiant numerique ou textuel du formulaire formidable
* @param array $valeurs
* Valeurs par défauts passées au contexte du formulaire
* Exemple : array('hidden_1' => 3) pour que champ identifie "@hidden_1@" soit prerempli
* @param int|bool $id_formulaires_reponse
* Identifiant d'une réponse pour forcer la reedition de cette reponse spécifique
*
* @return array
* Tableau des erreurs
*/
function formulaires_formidable_verifier_traitements($id, $valeurs = array(), $id_formulaires_reponse = false) {
$erreurs = array();
if (
$id_formulaire = formidable_id_formulaire($id)
and $formulaire = sql_fetsel('*', 'spip_formulaires', 'id_formulaire = ' . intval($id_formulaire))
) {
$traitements = unserialize($formulaire['traitements']);
$unicite = $traitements['enregistrement']['unicite'];
$message_erreur_unicite = $traitements['enregistrement']['message_erreur_unicite'];
if ($unicite != '') {
if (!$erreurs[$unicite]) {
$options_enregistrement = isset($traitements['enregistrement']) ? $traitements['enregistrement'] : null;
if (!$id_formulaires_reponse) { // si pas de réponse explictement passée au formulaire, on cherche la réponse qui serait édité
$id_formulaires_reponse = formidable_trouver_reponse_a_editer($formulaire['id_formulaire'], $id_formulaires_reponse, $options_enregistrement);
}
if ($id_formulaires_reponse != false) {
$unicite_exclure_reponse_courante = ' AND R.id_formulaires_reponse != '.$id_formulaires_reponse;
} else {
$unicite_exclure_reponse_courante = '';
}
$reponses = sql_allfetsel(
'R.id_formulaire AS id',
'spip_formulaires_reponses AS R
LEFT JOIN spip_formulaires AS F
ON R.id_formulaire=F.id_formulaire
LEFT JOIN spip_formulaires_reponses_champs AS C
ON R.id_formulaires_reponse=C.id_formulaires_reponse',
'R.id_formulaire = ' . $id_formulaire .
$unicite_exclure_reponse_courante .
' AND C.nom='.sql_quote($unicite).'
AND C.valeur='.sql_quote(_request($unicite)).'
AND R.statut = "publie"'
// Pour chaque traitement choisi, on cherche s'il propose une fonction de vérification propre à ses besoins
foreach ($traitements as $type_traitement => $options) {
if ($verifier_traitement = charger_fonction('verifier', "traiter/$type_traitement", true)) {
$erreurs_traitements = $verifier_traitement(
array(
'formulaire' => $formulaire,
'options' => $options,
'id_formulaire' => $formulaire['id_formulaire'],
'valeurs' => $valeurs,
'id_formulaires_reponse' => $id_formulaires_reponse,
),
$erreurs
);
if (is_array($reponses) && count($reponses) > 0) {
$erreurs[$unicite] = $message_erreur_unicite ?
_T($message_erreur_unicite) : _T('formidable:erreur_unicite');
}
$erreurs = array_merge($erreurs, $erreurs_traitements);
}
}
if ($erreurs and !isset($erreurs['message_erreur'])) {
$erreurs['message_erreur'] = _T('formidable:erreur_generique');
}
if ($erreurs) { // Pour savoir au chargement si le formulaire a deja été envoyé avec erreur'
set_request('erreurs', true);
}
}
return $erreurs;
}
/**
* Traitement du formulaire CVT de Formidable.
*
......@@ -283,7 +323,7 @@ function formulaires_formidable_verifier($id, $valeurs = array(), $id_formulaire
* @return array
* Tableau des erreurs
**/
function formulaires_formidable_traiter($id, $valeurs = array(), $id_formulaires_reponse = false) {
function formulaires_formidable_traiter_dist($id, $valeurs = array(), $id_formulaires_reponse = false) {
$retours = array();
// POST Mortem de securite : on log le $_POST pour ne pas le perdre si quelque chose se passe mal
......@@ -483,7 +523,12 @@ function formulaires_formidable_traiter($id, $valeurs = array(), $id_formulaires
$envoyer_mail = charger_fonction('envoyer_mail', 'inc');
$envoyer_mail($GLOBALS['meta']['email_webmaster'], $erreur_sujet, $erreur_texte);
}
// Pas besoin de ça dans le vrai retour final
unset($retours['traitements']);
// Drapeau pour dire que tous les traitements sont terminés, afin qu'on le sache dans le charger()
set_request('formidable_traiter_ok', true);
return $retours;
}
......
<p class='boutons'>
<span class='image_loading'></span>
<input type='submit' class='submit' value='<:bouton_valider:>' />
[(#SET{label_valider, #ENV{_saisies/options/texte_submit, #ENV{saisies_texte_submit, <:bouton_enregistrer:>}}})]
[(#ENV{_etape}|et{#ENV{_etape}|!={#ENV{_etapes}}})
[(#SET{label_valider, #ENV{_saisies/options/etapes_suivant, <:bouton_suivant:>}})]
]
[(#ENV{_etape}|>{1}|oui)
<input type="submit" class="submit" name="_retour_etape_[(#ENV{_etape}|moins{1})]" value="[(#ENV{_saisies/options/etapes_precedent, <:bouton_precedent:>})]" />
]
<input type="submit" class="submit" value="#GET{label_valider}" />
</p>
......@@ -57,6 +57,11 @@ $GLOBALS[$GLOBALS['idx_lang']] = array(
'editer_css' => 'Classes CSS',
'editer_descriptif' => 'Descriptif',
'editer_descriptif_explication' => 'Une explication du formulaire destinée à l’espace privé.',
'editer_globales_etapes_activer_explication' => 'Lorsque cette option est active, chaque groupe de champs de premier niveau est transformé en étape du formulaire.',
'editer_globales_etapes_activer_label_case' => 'Activer la gestion multi-étapes',
'editer_globales_etapes_precedent_label' => 'Texte du bouton de validation vers l’étape suivante (par défaut "Suivant")',
'editer_globales_etapes_suivant_label' => 'Texte du bouton de validation vers l’étape suivante (par défaut "Suivant")',
'editer_globales_texte_submit_label' => 'Texte du bouton de validation',
'editer_identifiant' => 'Identifiant',
'editer_identifiant_explication' => 'Donnez un identifiant textuel unique qui vous permettra d’appeler plus facilement le formulaire. L’identifiant ne peut contenir que des chiffres, lettres latines non accentuées et le caractère "_".',
'editer_menu_auteurs' => 'Configurer les auteurs',
......
<paquet
prefix="formidable"
categorie="communication"
version="3.35.0"
version="3.36.0"
etat="stable"
compatibilite="[3.0.0;3.2.*]"
logo="images/formidable-64.png"
......@@ -38,14 +38,14 @@
<pipeline nom="corbeille_table_infos" inclure="formidable_pipelines.php" />
<necessite nom="spip_bonux" compatibilite="[3.3.8;[" />
<necessite nom="saisies" compatibilite="[3.13.0;[" />
<necessite nom="saisies" compatibilite="[3.18.1;[" />
<necessite nom="verifier" compatibilite="[1.6.2;[" />
<necessite nom="yaml" compatibilite="[1.5.2;[" />
<necessite nom="facteur" compatibilite="[3.6.2;[" />
<necessite nom="nospam" compatibilite="[1.6.1;[" />
<utilise nom="collectionjson" compatibilite="[1.5.0;[" />
<utilise nom="cvtupload" compatibilite="[1.11.0;[" />
<utilise nom="cvtupload" compatibilite="[1.16.0;[" />
<utilise nom="corbeille" compatibilite="[3.1.0;[" />
<menu nom="formulaires" titre="formidable:bouton_formulaires" parent="menu_edition" icone="images/formulaire-16.png" />
......
......@@ -29,8 +29,10 @@
<p><:formidable:aucun_traitement:></p>
<//B_traitements>
#BOITE_FERMER
#FORMULAIRE_FORMIDABLE{#ID_FORMULAIRE}
<div class="ajax">
#FORMULAIRE_FORMIDABLE{#ID_FORMULAIRE}
</div>
#PIPELINE{afficher_complement_objet,#ARRAY{args,#ARRAY{type,formulaire,id,#ID_FORMULAIRE},data,'<div class="nettoyeur"></div>'}}
......
......@@ -190,6 +190,44 @@ function traiter_enregistrement_update_dist($id_formulaire, $traitement, $saisie
}
}
function traiter_enregistrement_verifier_dist($args, $erreurs) {
$id_formulaire = $args['id_formulaire'];
$options = $args['options'];
$id_formulaires_reponse = $args['id_formulaires_reponse'];
if (($unicite = $options['unicite']) != '' and !$erreurs[$unicite]) {
if (!$id_formulaires_reponse) { // si pas de réponse explictement passée au formulaire, on cherche la réponse qui serait édité
$id_formulaires_reponse = formidable_trouver_reponse_a_editer($id_formulaire, $id_formulaires_reponse, $options);
}
if ($id_formulaires_reponse != false) {
$unicite_exclure_reponse_courante = ' AND R.id_formulaires_reponse != '.$id_formulaires_reponse;
} else {
$unicite_exclure_reponse_courante = '';
}
$reponses = sql_allfetsel(
'R.id_formulaire AS id',
'spip_formulaires_reponses AS R
LEFT JOIN spip_formulaires AS F
ON R.id_formulaire=F.id_formulaire
LEFT JOIN spip_formulaires_reponses_champs AS C
ON R.id_formulaires_reponse=C.id_formulaires_reponse',
'R.id_formulaire = ' . $id_formulaire .
$unicite_exclure_reponse_courante .
' AND C.nom='.sql_quote($unicite).'
AND C.valeur='.sql_quote(_request($unicite)).'
AND R.statut = "publie"'
);
if (is_array($reponses) && count($reponses) > 0) {
$erreurs[$unicite] = $options['message_erreur_unicite'] ?
_T($options['message_erreur_unicite']) : _T('formidable:erreur_unicite');
}
}
return $erreurs;
}
/**
* Pour une saisie 'fichiers' particulière,
* déplace chaque fichier envoyé dans le dossier
......
0% Chargement en cours ou .
You are about to add 0 people to the discussion. Proceed with caution.
Veuillez vous inscrire ou vous pour commenter