SquelettesDeFormulaires

All contributions published for previous SPIP versions

Résumé

Cette page s’adresse aux codeurs de Spip en tout genre, les administrateurs de sites pouvant profiter de cette rationalisation sans se soucier de ce qui se passe en coulisse.

A partir de la version CVS 12/12/2004, une balise FORMULAIRE_* est compilée comme une balise INCLURE, à ceci près que le squelette à inclure n’est connu qu’au dernier moment. Il devient alors possible de personnaliser l’aspect graphique des formulaires en ajoutant un squelette formulaire_X.html qui sera choisi prioritairement à formulaire_X-dist.htmlcomme d’habitude: plus besoin de programmation en PHP, plus besoin de précaution particulière à chaque installation.

Exemples

  • création d’une copie du formulaire forum FormulaireLivreOr (avant les modifications pour la 1.9)
  • FormulaireDesMotsEtDesSites (spip 1.9)

Comment ça marche ?

La nouvelle version comporte une nouvelle implémentation des balises de formulaires, dont les fonctions associées peuvent retourner, plutôt qu’une chaîne HTML, un tableau de 3 éléments savoir:

-  le nom d’un squelette
-  le délai associé à la page HTML produite par ce squelette
-  le contexte inclus (donc un sous-tableau de couples variable/valeur).

Depuis la 1.9.0
Il y a un couple de fichiers pour définir une balise de formulaire à placer dans des sous repertoires de votre répertoire squelettes (ou à integrer dans un plugin)

-  un fichier balise/X.php3 contenant la fonction PHP à invoquer dans un squelette incluant une telle balise;
-  un fichier formulaires/formulaire_X-dist.html, squelette du texte HTML correspondant à cette balise.

Avant la 1.9.0 L’énorme fichier inc-formulaires est remplacé par des couples de fichiers pour chaque balise FORMULAIRE_X:

-  un fichier inc-X.php3contenant la fonction PHP à invoquer dans un squelette incluant une telle balise;
-  un fichier formulaire_X-dist.html, squelette du texte HTML correspondant à cette balise.


balise/X.php3

Là dedans on met les fonctions php de traitement des données

On peut rencontrer les éléments suivants :

function balise_FORMULAIRE_FORUM ($p)

Cette fonction défini la balise, et en particulier les variables à récuperer dans le contexte et à passer à la fonction _stat en appelant la fonction "calculer_balise_dynamique". On pourra ainsi récuperer l’id_article d’une boucle englobante ou la langue contenue dans l’url. C’est un peu comme les paramètres que l’on passe à une balise INCLURE spip.

Exemple

function balise_FORMULAIRE_FORUM ($p) {

	$p = calculer_balise_dynamique($p,'FORMULAIRE_FORUM', array('id_rubrique', 'id_forum', 'id_article', 'id_breve', 'id_syndic', 'ajouter_mot', 'ajouter_groupe', 'afficher_texte'));
	// Ajouter l'invalideur forums sur les pages contenant ce formulaire
	$p->code = code_invalideur_forums($p, $p->code);
	return $p;
}

calculer_balise_dynamique($p,'FORMULAIRE_FORUM', array('id_rubrique', 'id_forum', 'id_article', 'id_breve', 'id_syndic', 'ajouter_mot', 'ajouter_groupe', 'afficher_texte')) déclare le nom de la balise (et des fonctions à chercher plus tard) et un tableau des variables à récupérer dans le contexte.

code_invalideur_forums n’est pas obligatoire, ici il permet d’invalider le cache de SPIP quand on poste un nouveau commentaire, pour que la page soit recalculé avant que le delais du cache soit écoulé.

function balise_FORMULAIRE_XXX_stat($args, $filtres)

Cette fonction reçois deux tableaux:

  1. le premier contient les variables collectée avec le tableau cité plus haut ainsi que les paramètres passés directement à la balise.
  2. le second reçoit les filtres appliqués à la balise, au cas où on veuille faire un prétraitement dessus (pour récuperer des variables par exemple).

Elle doit retourner soit:

  • une chaîne qui représente un message d’erreur
  • un tableau qui sera passé à la balise _dyn (contenant des arguments pour la balise, en générale, le paramètre $args)

function balise_FORMULAIRE_SITE_dyn($id_machin)

Ah, c’est ici qu’on met le traitement des données (insertion en base etc).

Elle reçoit les valeures retournées par la fonction _stat et doit retourner soit:

  • un message d’erreur
  • un tableau représentant un squelette SPIP:
    1. le nom du fond (e.g. "formulaires/formulaire_forum")
    2. le délais
    3. un tableau des paramètres à passer à ce squelette (ensuite accessible par #ENV)

On peut acceder ici aux variables postées par le formulaire en utilisation la fonction _request('name'); et faire des traitements en fonction de celles ci pour faire l’insertion en base, envoyer un mail etc...


formulaires/formulaire_X.html

Ici c’est les balises HTML et le code SPIP usuel d’un squelette SPIP.

On mets les valeurs des champs des formulaires avec des #ENV{truc} ou truc est défini dans le tableau passant le contexte d’inclusion dans le fichier php.

********

A partir du 24/12, les formulaires LOGIN_PRIVE et LOGIN_PUBLIC sont aussi définis par un squelette formulaire_login-dist.html. Le même fichier sert pour les deux balises. Le nouveau squelette permet de visualiser le logo de l’auteur lors la phase de saisie du mot de passe.

Ces deux balises acceptent à présent un paramètre indiquant le login dont on veut la saisie du mot passe. Cette
possibilité permet par exemple de construire une page d’accueil de l’espace privé sous forme de la suite des logos des auteurs, chaque logo étant associé à la saisie du mot de passe spécifique. Cet effet (avec une mise en page évidemment très améliorable) pourra être obtenu en remplaçant dans le squelette de la page d’accueil (l’historique login-dist.html, à ne pas confondre avec le nouveau) la balise #LOGIN_PRIVE par:

<BOUCLE1(AUTEURS){tout}>[(#LOGIN_PRIVE{#LOGIN})]</BOUCLE1>

Exemple

à compléter

Remarques et précautions d’usage

  1. Il n’y a pas de miracle: la prise en compte des données à chaque requête induit parfois un contexte inclus pléthorique (cf inc-forum) que le créateur du squelette doit inévitablement étudier. En d’autres termes, la programmation n’apparaît plus, mais le nombre de variables qu’elle manipulait existe toujours. Pour l’essentiel, il s’agit des champs de la table SQL à remplir.
  2. Les variables du contexte inclus peuvent évidemement contenir du HTML: ça donne de la souplesse mais ça ne va pas dans le sens de l’explicitation de tout code HTML dans des squelettes. C’est en fait une inclusion dans l’inclusion qui est la solution propre, mais ça pose des pbs d’accès parfois (en particulier afficher_barre qui serait un squelette de l’espace privé, entité impossible pour le moment).
  3. La fonction associée à une telle balise peut continuer à retourner une chaîne, comme dans l’ancienne version. L’usage prévu concerne les cas où l’insertion dans le squelette englogant se réduit à une simple chaîne (genre "message bien envoyé" ou "accès interdit" etc), car il serait trop lourd de démultiplier des squelettes minuscules. De nouveau on peut utiliser cette brêche pour retourner du HTML non explicité dans un squelette mais ça ne va pas dans le sens etc.
  4. Pour eviter le bouclage du debuger (ModeDebug), désormais le nom des variables rajoutées par Spip dans les URL commence systématiquement par var_. En particulier, forcer le recalcul se fait maintenant par var_mode=recalcul.
  5. Les balises de squelettes sont calculées à l’envoi de la page et non à la compilation. En conséquence, la syntaxe [texte_avant_conditionnel (#BALISE) texte_après_conditionnel] ne fonctionne pas puisque le texte "_conditionnel" sera toujours présent.

Questions / Réponses

Est-ce que cette solution permet aussi de concevoir un squelette pour #MENU_LANG (public) différent de celui de admin (je dis ça car je n’ai pas trouvé d’autres solution que de modifier inc-lang.php3, mais il doit y avoir plus simple. Peut-on redefinir #MENU_LANG (public) dans mes fonctions.php3 ou mes_options.php3 par exemple ?

Oui, toutes les balises qui déclenchent une deuxième passe de PHP devraient suivre l’API des balises de formulaires, et donc se reposer sur un squelette modifiable. On peut faire ce travail pour MENU_LANG, toutefois en l’état le résultat sera un peu frustrant: conceptuellement on aimerait faire une boucle sur les langues disponibles, mais celles-ci sont répertoriées non par une table SQL mais par la présence de fichiers ecrire/lang/spip_*.php3. —> (de même qu’il existe /ecrire/admin_index.php3 il pourrait aussi exister /ecrire/admin_lang.php3 qui mettrait à jour une petite table SQL et qui permetrait, aussi, d’ajouter des traductions... en éditant les fichiers de langues.)

Il y a donc une réflexion plus profonde à faire ici, mais redéfinir la fonction balise_MENU_LANG dans mes_fonctions ou mes_options est en tout cas la piste à suivre.

Pourquoi des squelettes de formulaire ?

C’est ainsi plus facile à personaliser. Précédement les balises de formulaires se compilaient par l’appel de fonctions PHP produisant dynamiquement du HTML. Changer ce texte HTML impliquait donc de programmer en PHP, et non de concevoir uniquement des squelettes dans le HTML étendu que nous connaissons. En outre, à chaque nouvelle installation de Spip, il fallait veiller à ne pas écraser sa version personnelle du fichier inc-formulaires, et eventuellement le réadapter si la version standard avait changé. Ce comportement dérogatoire a pour origine la difficile prise en compte, A CHAQUE REQUETE, de l’identité du réquereur et/ou des données envoyées en méthode Post, ce qui interdit la mise en cache et exige une deuxième passe de PHP après l’exécution du squelette.

Est ce que la recherche du fond se fait de le même facon que la recherche des fond des squelettes normaux ? C’est à dire:
-  est ce que si on fait un fichier formulaire_forum-XX.html il sera utilisé pour la rubrique XX
-  est ce que si je fait un fichier formulaire_forum.en.html il sera utilisé dans les pages en anglais ?

Réponse : Non. On peut seulement surcharger le -dist. Rappellons toutefois que la fonction chercher_squelette est redéfinissable (dans mes_fonctions ou mes_options).

Petit tutoriel : #MENU_LANG (en hibernation)

Un exemple concret a partir de avec . A suivre ( TutorielBaliseMultiLang )...
— >


Déesse A. <esj <at> vertsdesevres.net>
Subject: Re: squelettes de formulaires (et barre de raccourcis)
Newsgroups: gmane.comp.web.spip.devel
Date: FormulaireDesMotsEtDesSites-01-09 21:32:57 GMT (41 weeks, 2 days, 13 hours and 46 minutes ago)

Le 9 janv. 05, à 21:36, Michel JORDA a écrit :

> Bonjour à tous,
> je suis parti dans un développement un peu délicat, toujours est-il que
> je me sers des brèves de façon peu standard. J’ai donc besoin d’écrire
> mon formulaire d’écriture de brèves.
> Evidemment, ca serait dommage de ne pas utiliser la nouvelle interface
> géniale a base de
> inc-formulaire_XXXX.php
> formulaire_XXXX.html
>
> Malheureusement, soit je ne creuse pas dans le bon sens, soit la
> "double
> passe" du php me perd totalement… bref impossible d’arriver à qq chose
> d’utilisable…

Je donne qq infos sous toutes réserves car il n’est pas impossible que
cette interface change, c’est encore expérimental.

Le point est difficile parce qu’on veut à la fois récupérer les valeurs
calculées à la mise en cache de la page contenant la balise, et celles
qui ne seront connues qu’à chaque requête à cette page, l’union des
deux devant etre disponible à chaque requête. Donc pour une balise #B
il faut déclarer:

B_collecte: tableau des noms des valeurs décrites ci-dessus (en gros
c’est tous les attributs Name contenu dans le formulaire, plus
éventuellement qq champs issus des boucles incluant la balise);

B_stat: fonction recevant ces valeurs en argument, ainsi que les
filtres de la balise, lors de la mise en cache. A ce moment, il peut
apparaitre qu’il n’y a déjà plus rien à faire (par exemple pour le
formulaire d’inscriptions, il n’y a rien à produire si elles ne sont
pas autorisées). Dans ce cas, cette fonction doit rendre une chaine qui
sera insérée dans le squelette à la mise en cache, celui-ci contenant
alors une page HTML statique. Si elle rend un tableau, on insère dans
le squelette une interpolation PHP qui sera donc exécutée à chaque
requête. L’exécution consistera à appliquer B_dyn sur le tableau alors
retourné.

B_dyn: fonction recevant les valeurs jugées utiles par B_stat. Comme
elle est appelée à chaque requête, elle a accès aux valeurs des cookies
(contrairement à B_stat) et peut donc controler les droits éventuels.
Si elle retourne une chaîne, celle-ci est insérée dans le squelette
(sur le plan du développement graphique, je conseille de ne recourir à
ca que pour un message brut, sans balise Html).
Sinon, elle doit retourner un tableau de 3 éléments, équivalents au
fond / délai / contexte_inclus des scripts habituels.

Enfin, il suffit de déclarer ces 3 choses dans un fichier nommé
inc-B.php3 pour
que le compilateur reconnaisse #B comme une balise de ce type.

Ca parait compliqué, mais ça a l’avantage de couvrir toutes les
situations de balises incomplétement calculables à la mise en cache.
Cette interface est d’ailleurs à présent le seul cas d’interpolation de
PHP insérée par le compilateur. Il y a évidemment une interface plus
conviviale à développer à terme, mais le mécanisme sous-jacent ne me
semble pas simplifiable.

Emmanuel

Fichier commenté : formulaire ecrire auteur

Petite explication dans le code par Stéphane Laurent...

&lt;?php

if (!defined(&quot;_ECRIRE_INC_VERSION&quot;)) return;    #securite


// On prend l'email dans le contexte de maniere a ne pas avoir a le
// verifier dans la base ni a le devoiler au visiteur
global $balise_FORMULAIRE_ECRIRE_AUTEUR_collecte;

//ici, tu vas collecter des données dans l'environnement d'execution
//cad que tu recupere le contenu des balises de la boucle englobante
//ici, le contexte d'execution peut etre une boucle auteur, article ...
//voire meme hors boucle avec un id_auteur en parametre
$balise_FORMULAIRE_ECRIRE_AUTEUR_collecte = array('id_auteur', 
'id_article', 'email');
//si tu veux recuperer d'autre données, il faut les passer en parametre 
au formulaire
//FORMULAIRE_ECRIRE_AUTEUR{arg0,arg1}
//tu les recuperera alors dans arg[0], arg[1]
//les données collectées viennent se placer après les données passées en 
argument
//si tu passes 2 parametres, la premiere donnée collectée sera arg[2]
//
function balise_FORMULAIRE_ECRIRE_AUTEUR_stat($args, $filtres) {

     // Pas d'id_auteur ni d'id_article ? Erreur de squelette
     if (!$args[0] AND !$args[1])
         return erreur_squelette(
             _T('zbug_champ_hors_motif',
                 array ('champ' =&gt; '#FORMULAIRE_ECRIRE_AUTEUR',
                     'motif' =&gt; 'AUTEURS/ARTICLES')), '');

     // Si on est dans un contexte article, sortir tous les mails des 
auteurs
     // de l'article
     if (!$args[0] AND $args[1]) {
         unset ($args[2]);
         $s = spip_query(&quot;SELECT auteurs.email AS email
         FROM spip_auteurs as auteurs, spip_auteurs_articles as lien
         WHERE lien.id_article=&quot;.intval($args[1])
         . &quot; AND auteurs.id_auteur = lien.id_auteur&quot;);
         while ($row = spip_fetch_array($s))
             if ($row['email'] AND email_valide($row['email']))
                 $args[2].= ','.$row['email'];
         $args[2] = substr($args[2], 1);
     }

     // On ne peut pas ecrire a un auteur dont le mail n'est pas valide
     if (!$args[2] OR !email_valide($args[2]))
         return '';

     // OK
     return $args;
}

function balise_FORMULAIRE_ECRIRE_AUTEUR_dyn($id_auteur, $id_article, 
$mail) {
     include_ecrire('inc_texte.php3');
     $puce = $GLOBALS['puce'.$GLOBALS['spip_lang_rtl']];

     // id du formulaire (pour en avoir plusieurs sur une meme page)
     $id = ($id_auteur ? '_'.$id_auteur : '_ar'.$id_article);
     #spip_log(&quot;id formulaire = $id, &quot;._request(&quot;valide&quot;.$id));
     $sujet = _request('sujet_message_auteur'.$id);
     $texte = _request('texte_message_auteur'.$id);
     $adres = _request('email_message_auteur'.$id);
     $nom = _request('nom_message_auteur'.$id);

     $mailko = $texte && !email_valide($adres);

     $validable = $texte && $sujet && (!$mailko);

     // doit-on envoyer le mail ?
     if ($validable
     AND $id == _request('num_formulaire_ecrire_auteur')
     AND _request('confirmer'.$id)) {
         $texte .= &quot;\n\n-- &quot;._T('envoi_via_le_site').&quot; 
&quot;.supprimer_tags(extraire_multi(lire_meta('nom_site'))).&quot; 
(&quot;.lire_meta('adresse_site').&quot;/) --\n&quot;;
         include_ecrire(&quot;inc_mail.php3&quot;);

//si tu veux le nom dans le corps du mail, il faut l'ajouter ...
        $texte=&quot;Nom : &quot;.$nom.&quot;\nTexte : &quot;.$texte;

         envoyer_mail($mail, $sujet, $texte, $adres,
                 &quot;X-Originating-IP: &quot;.$GLOBALS['REMOTE_ADDR']);
         return _T('form_prop_message_envoye');
     }

     return
         array('formulaire_ecrire_auteur', 0,
             array(
             'id' =&gt; $id,
             'mailko' =&gt; $mailko ? $puce : '',
             'mail' =&gt; $adres,
             'sujetko' =&gt; ($texte && !$sujet) ? $puce : '',
             'sujet' =&gt; $sujet,
             'nom' =&gt; $nom,
             'texte' =&gt; $texte,
             'valide' =&gt; ($validable ? $id : ''),
             'bouton' =&gt; (_T('form_prop_envoyer')),
             'boutonconfirmation' =&gt; ($validable ?
                 _T('form_prop_confirmer_envoi') :
                 '')
             )
         );
}
?&gt;

updated on 4 May 2007

Discussion

Une discussion

  • Bonjour,
    je souhaite supprimer l’étape qui consiste à confirmer l’envoi du mail dans le formulaire_auteur, j’aimerais que lorsque l’on clique sur envoyer le message, il parte de suite... y’a-t-il une solution ?

    Reply to this message

Comment on this article

Who are you?
  • [Log in]

To show your avatar with your message, register it first on gravatar.com (free et painless) and don’t forget to indicate your Email addresse here.

Enter your comment here

This form accepts SPIP shortcuts {{bold}} {italic} -*list [text->url] <quote> <code> and HTML code <q> <del> <ins>. To create paragraphs, just leave empty lines.

Add a document

Follow the comments: RSS 2.0 | Atom