Cet article décrit la mise en place d'un formulaire d'inscription combiné avec un workflow de validation. Ce formulaire a pour but de remplacer l'inscription automatique (signup.jsp) présente en standard. Le développement est réalisé sous la forme d'un plugin de manière à ce que la migration de la fonctionnalité soit la plus simple possible d'une version de JCMS à une autre.
1. Création d'un Type de Formulaire
Dans l'éditeur de formulaire, on créé un type DemandeInscription.
1.1 Création des champs
Dans un premier temps, il faut créer tous les champs nécessaires au formulaire. Il faut tenir compte de l'ordre des champs ainsi que des libellés qui doivent être simples et compréhensibles. Les gabarits d'édition de types ne sont pas multi langue, par conséquent, si le site est multilingue, le gabarit d'edition du formulaire devra être retravaillé.
1.2 Propriétés sur les champs
Une fois les champs créés, il faut ajuster les propriétés de chacun. Il faut déterminer si le champ est obligatoire et ajouter une aide contextuelle. Si le champ est trop technique ou obscur il est préférable de faire apparaître cette aide.
1.3 Propriétés sur le type
Enfin il faut déterminer comment le site va se comporter après soumission du formulaire. Qui sera le responsable des soumissions ? Est-ce qu'un espace de travail sera dédié aux demandes d'inscription ? Faut-il notifier le responsable des soumissions ou plutôt associer un workflow aux soumissions ?
1.4 Redémarrage du site
Une fois toutes les étapes réalisées il ne reste plus qu'à sauvegarder le type et redémarrer JCMS pour que les ressources nécessaires à la gestion du formulaire soient générées.
2. Mises en place du formulaire
Cette deuxième étape consiste à donner un accès au formulaire depuis l'espace publique du site. Pour le moment seulement une JSP types/DemandeInscription/editFormDemandeInscription.jsp a été généré. Il faut maintenant créer un lien vers cette JSP.
2.1 Accès direct par l'URL
Pour vérifier que tout fonctionne correctement, dans un premier temps il faut essayer d'accéder, à la JSP générée par l'URL du navigateur. Pour cela deux solutions sont possibles :- Accès direct :
http://host/webapp/types/Type/editFormDemandeInscription.jsp
A noter qu'avec JCMS 4.1.1, l'accès direct renvoit automatiquement sur l'accès par le portail.
- Accès par le portail :
http://host/webapp/display.jsp?id=c_5&jsp=types/Type/editFormDemandeInscription.jsp
Le portail doit bien évidement être composé d'une PortletSelection pour pouvoir afficher la JSP dans le portail. Le portail peut être spécifier par le paramètre portal.
2.2 Accès par une portlet WYSIWYG
Pour permettre un accès plus simple à ce formulaire, il faut créer une portlet WYSIWYG contenant un lien vers le formulaire. Cette portlet ne devra bien évidemment être visible que si le membre n'est pas authentifié.
2.3 Modification de PortletInscription
La portlet PortletInscription redirige son formulaire vers signup.jsp. Cette JSP a pour rôle de créer un compte utilisateur sous réserve que la configuration du site l'autorise. Il faut donc modifier le gabarit d'affichage de cette portlet pour rediriger vers le nouveau formulaire.
1 <%@ include file='/doInitPage.jsp' %>
2 <%@ include file='/portal/doPortletParams.jsp' %>
3 <% PortletSignUp box = (PortletSignUp) portlet; %>
4
5 <%
6 if (!channel.getBooleanProperty("channel.sign-up",false) || !channel.isDataWriteEnabled()){
7 request.setAttribute("ShowPortalElement",Boolean.FALSE);
8 }
9 Portal signupPortal = box.getDisplayPortal() != null ? box.getDisplayPortal() : portal;
10 %>
11
12 <table width="100%" cellspacing="0" cellpadding="5" border="0">
13 <form method="get" action="<%=contextPath%>/types/DemandeInscription/editFormDemandeInscription.jsp">
14 <tr>
15 <td>
16 <jalios:if predicate='<%= Util.notEmpty(box.getIntro(userLang)) %>'>
17 <span class="Intro"><%= box.getIntro(userLang) %></span>
18 </jalios:if><br>
19 <input type="text" name="email" size="18" value="" class="Form">
20 <input type="image" border="0" name="imageField2" src="images/jalios/icons/ok.gif" align="middle">
21 <input name="redirect" type="hidden" value="<%= ServletUtil.getUrl(request) %>" >
22 <input name="portal" type="hidden" value="<%= signupPortal.getId() %>" >
23 </td>
24 </tr>
25 </form>
26 </table>
3. Validation du formulaire
Maintenant que le formulaire est mis en place, il serait assez intéressant d'automatiser le processus de validation. Il faut pouvoir envoyer un mail au valideur et préalablement créer un membre à partir du formulaire… Pour cela nous allons donc nous appuyer sur un workflow de validation.
3.1 Création d'un Workflow de validation
Pour que la demande d'inscription soit prise en compte, il faut définir un workflow de validation. Ce workflow permettra de simplifier et d'automatiser partiellement la création de compte utilisateur.
Ce workflow sera composé des états suivants:
- Demande effectuée
- Demande rejetée
- Demande approuvée
3.2 Association Workflow / Formulaire
L'association d'un Type avec un Workflow se fait dans un espace de travail donné. Il faut déclarer dans la zone d'administration de l'espace de travail choisi, que les Formulaire d'Inscription seront soumis à ce Workflow.
Il faut enfin affecter un groupe ou un membre au rôle de valideur dans cet espace de travail.
Les demandes seront donc créées dans l'état Demande effectuée dans l'espace de travail choisi. Les valideurs auront pour mission d'approuver ou de rejeter la demande.
3.3 Automatisation de la validation
Lorsque la demande est approuvée, il serait intéressant de créer immédiatement un membre dans JCMS. Le valideur n'ayant plus alors qu'a finir la mise à jour et à envoyer le mot de passe par mail au membre.
Pour cela il faut créer un StoreListener qui déclenchera la création du membre lorsque le formulaire passera dans l'état Demande approuvée.
1 package plugin.inscription;
2 import com.jalios.jcms.*;
3 import com.jalios.jstore.*;
4 import com.jalios.util.Util;
5
6 import java.util.*;
7 import generated.*;
8
9 public class DemandeInscriptionListener implements StoreListener{
10
11 // -------------------------------------------------------------------------------------
12 // ||| StoreListener implementation ||||||||||||||||||||||||||||||||||||||||||||||||||||
13 // -------------------------------------------------------------------------------------
14
15 public void handleCreate(Storable storable, boolean firstTime) {
16 if ((storable == null) || (!(storable instanceof DemandeInscription))){
17 return;
18 }
19 createMember((DemandeInscription) storable);
20 }
21
22 public void handleCommitUpdate(Storable storable, Storable oldStorable, boolean firstTime){
23 if ((storable == null) || (!(storable instanceof DemandeInscription))){
24 return;
25 }
26 createMember((DemandeInscription) storable);
27 }
28
29 public void handleDelete(Storable storable, boolean firstTime) { }
30 public void handlePrepareUpdate(Storable storable, Map attributes, boolean firstTime) { }
31
34 // -------------------------------------------------------------------------------------
35 // ||| Specific Code |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
36 // -------------------------------------------------------------------------------------
37
38 protected void createMember(DemandeInscription pub){
39
40 if (pub.getPstatus() != -60){
41 return;
42 }
43 Member newMember = new Member();
44
45 // TODO: Login must be unique
46
47 newMember.setLogin(Util.getString(pub.getIdentifiantSouhaite(), Util.buildID(pub.getName())));
48 newMember.setName(pub.getName());
49 newMember.setFirstName(Util.getString(pub.getPrenom(),""));
50 newMember.setEmail(pub.getEmail());
51 newMember.setSalutation(pub.getCivilite());
52 newMember.setJobTitle(Util.getString(pub.getFonction(),""));
53 newMember.setInfo(pub.getQuestion());
54 newMember.setGroups(new Group[] {Channel.getChannel().getDefaultGroup()});
55 newMember.disable();
56
57 Channel.getChannel().createData(newMember,Channel.getChannel().getDefaultAdmin());
58 }
59 }
Ce listener a été développé dans le package plugin.inscription. Pour le moment il n'y a aucune norme pour les noms de package de plugins. Les plugins doivent être déclarés manuellement dans le fichier classes/custom/JcmsInit.java.
1 public static void initAfterStoreLoad(Channel channel) {
2
3 channel.addStoreListener(
4 new plugin.inscription.DemandeInscriptionListener(), generated.DemandeInscription.class, false);
5 }
6 }
4. Quelques Réflexions
4.1 Robustesse
Cet exemple soulève quelques questions intéressantes à se poser. Que se passe-t-il si un même login est soumis plusieurs fois ? Comment gérer le changement d'état du formulaire ? Quand le formulaire quitte l'état approuvé ou bien est supprimé, faut il désactiver le membre ?
4.2 Evolutivité
Il est très simple de faire évoluer ce type vers des formulaires plus complexes. On peut imaginer des formulaires beaucoup plus précis permettant une création automatique du compte utilisateur.
De la même manière le workflow peut très simplement être modifié pour ajouter des états notifiant périodiquement le valideur qu'il n'a pas fini de valider la demande.
4.3 Ergonomie
Pour améliorer l'ergonomie, après soumission du formulaire, il faut rediriger l'utilisateur vers une publication qui lui explique ce qui va se passer et quand son compte sera activé.













