diff --git a/formulaires/editer_formulaire_champs.html b/formulaires/editer_formulaire_champs.html index 341af9dc106ad035db9951448704e7ebb5d31cf6..125a863c5c7555b2bb58299d5c2474ae89953f98 100644 --- a/formulaires/editer_formulaire_champs.html +++ b/formulaires/editer_formulaire_champs.html @@ -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> ] diff --git a/formulaires/editer_formulaire_champs.php b/formulaires/editer_formulaire_champs.php index 39e8c6a3eecd014a3beb62fe81633b02284adfb9..ab7a637a78417b507ff3a693230d0abd68e76ebb 100644 --- a/formulaires/editer_formulaire_champs.php +++ b/formulaires/editer_formulaire_champs.php @@ -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; diff --git a/formulaires/formidable.html b/formulaires/formidable.html index 990572bc403ddfea1d0460119d4970fd1f6453d2..9f0826e3a2e3e5c793474c8f68c3482db4d9a33d 100644 --- a/formulaires/formidable.html +++ b/formulaires/formidable.html @@ -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) diff --git a/formulaires/formidable.php b/formulaires/formidable.php index 6e8f1b04e62e020b54a24c3464fe767e0d3d6009..ae120fc9e8d325cbd9d77f7829f9f35ff8fad2f4 100644 --- a/formulaires/formidable.php +++ b/formulaires/formidable.php @@ -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; } diff --git a/formulaires/inc-formidable-boutons.html b/formulaires/inc-formidable-boutons.html index 5381699d71412d0f3cc54aaf28b273c950aad5f0..c637d82fb67bddbab45f0f515bcf5d4510e7f2cc 100644 --- a/formulaires/inc-formidable-boutons.html +++ b/formulaires/inc-formidable-boutons.html @@ -1,4 +1,11 @@ <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> diff --git a/lang/formidable_fr.php b/lang/formidable_fr.php index 0a888b0fac3ea0563091044e2edd1bbb3090cd68..797eb2c9ed6769ea1a14f804eabdd574599d7fa7 100644 --- a/lang/formidable_fr.php +++ b/lang/formidable_fr.php @@ -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', diff --git a/paquet.xml b/paquet.xml index c9cd3defbbbb50d67982eb49750475f404046a42..24cf7cdbb949949f4235a7e9c02e207d5f335c7b 100644 --- a/paquet.xml +++ b/paquet.xml @@ -1,7 +1,7 @@ <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" /> diff --git a/prive/squelettes/contenu/formulaire.html b/prive/squelettes/contenu/formulaire.html index b61b10b58be98f396d3ba7e83a7f17ef0c968854..bd7664859fdf1b22649d404069f5de1837da2163 100644 --- a/prive/squelettes/contenu/formulaire.html +++ b/prive/squelettes/contenu/formulaire.html @@ -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>'}} diff --git a/traiter/enregistrement.php b/traiter/enregistrement.php index 72cb053836b02d7450cf8938e9c894d09fe57e84..b4c9b559d4649fa11c2f80261ec5a9e900eecd58 100644 --- a/traiter/enregistrement.php +++ b/traiter/enregistrement.php @@ -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