Carnet Wiki

De Forms&Tables à Formidable, retour d’expérience

Version 1 — Novembre 2010 Yffic

Avant

A l’origine un site spip 2.1 avec Forms&Tables pour gérer un agenda événementiel. Le formulaire d’ajout d’événements est constitué de :
-  un champ texte pour saisie de la date au format jj/mm/aaaa (sans vérification). Champ utilisé pour trier les enregistrements. Obligatoire
-  un champ texte pour saisir une précision pour la date (par exemple « Du 3 au 8 décembre »). Si rempli, ce champ est affiché à la place du champ précédent
-  un champ heure
-  un champ texte pour saisie d’un nom de spectacle
-  un champ texte pour saisie d’une ville
-  un champ texte pour saisie d’un département
-  un champ texte de saisie d’un nom de festival ou d’événement.
-  un champ de saisie d’url (site officiel de l’événement)
-  une zone de commentaire

L’ajout d’événement ne peut se faire que dans le Back Office.

L’agenda est présenté sur le site public dans un tableau avec une ligne par événement. 2 liens permettent d’afficher les événements de l’année en cours ou des années passées triés chronologiquement.

Les 2 squelettes

(appel dans article.htm : <INCLURE{fond=inc-agenda}{ajax}{env}{id_article,senstri}>)

Fichier inc-agenda.html

#SET{tri,date_1}
[(#SET{senstri,#ENV{senstri,0}})]

<p>
[<a href="[(#SELF|parametre_url{senstri, 0})]" title="Année en cours" class='ajax'>Année en cours</a>]
[<a href="[(#SELF|parametre_url{senstri, 1})]" title="Années passées" class='ajax'>Années passées</a>]
</p>

<B_donnees>

<table class="spip donnees" id='donnees-#ENV{id_table}'>
	<BOUCLE_donnees(FORMS_DONNEES){id_form=1}{tri_donnee #GET{tri}}{inverse #GET{senstri}}>
		<BOUCLE_date(FORMS_CHAMPS){id_form}{titre=Date}>#SET{dateevenement,#VALEUR}</BOUCLE_date>
		
		[(#GET{senstri}|=={0}|oui)
			[(#GET{dateevenement}|dansfutur|>={0}|oui)
				[<tr><td class="agenda-annee">
						<span>(#GET{dateevenement}|annee|unique)</span>
				</td></tr>]
				<tr class="[(#_donnees:COMPTEUR_BOUCLE|alterner{row_even,row_odd})]">
					<INCLURE{fond=inc-agenda-ligne}{id_form}{id_donnee}>
				</tr>
			]
		]
		[(#GET{senstri}|=={1}|oui)
			[(#GET{dateevenement}|dansfutur|<{0}|oui)
				[<tr><td class="agenda-annee">
						<span>(#GET{dateevenement}|annee|unique)</span>
				</td></tr>]
				<tr class="[(#_donnees:COMPTEUR_BOUCLE|alterner{row_even,row_odd})]">
					<INCLURE{fond=inc-agenda-ligne}{id_form}{id_donnee}>
				</tr>
			]
		]
	</BOUCLE_donnees>
</table>

</B_donnees>

Fichier inc-agenda-ligne.html

<BOUCLE_date(FORMS_CHAMPS){id_form}{titre=Date}>#SET{dateevenement,#VALEUR}</BOUCLE_date>

<td>
   <BOUCLE_datetxt(FORMS_CHAMPS){id_form}{titre=Datetxt}>
      <span class="#_reponses:EDIT{#CHAMP}" >#VALEUR</span>
      [(#VALEUR|?{'',' '})<span class="#_reponses:EDIT{#CHAMP}" >[(#GET{dateevenement}|affdate_jourcourt)]</span>]
   </BOUCLE_datetxt>
   <BOUCLE_horaire(FORMS_CHAMPS){id_form}{titre=Heure}>[ - <span class="#_reponses:EDIT{#CHAMP}" >(#VALEUR)</span>]</BOUCLE_horaire>
</td>
<td>
   <BOUCLE_spectacle(FORMS_CHAMPS){id_form}{titre=Spectacle}>[<span class="#_reponses:EDIT{#CHAMP}" >(#VALEUR)</span>]</BOUCLE_spectacle>
</td>
<td>
   <BOUCLE_ville(FORMS_CHAMPS){id_form}{titre=Ville}>[<span class="#_reponses:EDIT{#CHAMP}" >(#VALEUR)</span>]</BOUCLE_ville>
   <BOUCLE_dept(FORMS_CHAMPS){id_form}{titre=Département}>[ (<span class="#_reponses:EDIT{#CHAMP}" >(#VALEUR)</span>)]</BOUCLE_dept>
</td>
<td>
   <B_festival>
      #SET{fermer,0}
      <BOUCLE_lien(FORMS_CHAMPS){id_form}{titre=Site}>[#SET{fermer,1}<a href="(#VALEUR)" class="spip_out">]</BOUCLE_lien>
   <BOUCLE_festival(FORMS_CHAMPS){id_form}{titre=Festival}>[<span class="#_reponses:EDIT{#CHAMP}" >(#VALEUR)</span>]</BOUCLE_festival>
      [(#GET{fermer}|=={1}|?{'</a>',''})]
   </B_festival>
</td>
<td>
   <BOUCLE_commentaire(FORMS_CHAMPS){id_form}{titre=Commentaire}>
      [<span class="infobulle" title="(#VALEUR|attribut_html)"><img src="#CHEMIN{images/info.png}" alt="Infos" /></span>]
   </BOUCLE_commentaire>
</td>

Migration

Le Formulaire

  1. Exportation du formulaire depuis Forms&Tables (nécessite d’activer le plugin Snippets) dans un fichier xml
  2. Suppression des warnings au début du fichier xml
  3. Importation du formulaire dans Formidable

Remarque : si à cette étape vous modifiez le formulaire, le nom des champs risque de ne plus correspondre dans la table spip_formulaires_reponses_champs. Donc si par exemple, votre premier champ est un input de type date ’nommé date_1, et que vous modifiez le formulaire pour utiliser le champ « date » de Formidable qui utilise un petit calendrier de saisie de date, ce nouveau champ se nommera date_2. Il faudra donc modifier le nom lors de l’importation décrite ci-après.

Les données

On ne peut pas actuellement les importer directement. Il faut donc passer par phpMyAdmin par exemple pour récupérer les données sous forme de fichier csv des tables spip_forms_donnees (contient les réponses) et spip_forms_donnees_champs (contient les saisies de chaque réponse). Il va falloir insérer ces données dans les tables nommées respectivement spip_formulaires_reponses et spip_formulaires_reponses_champs après un petit traitement « manuel » pour satisfaire les correspondances de champs.

Structure de spip_forms_donnees Structure de spip_formulaires_reponses
id_donnee (bigint) id_formulaires_reponse (bigint)
id_form (bigint) id_formulaire (bigint)
date (datetime) date (datetime)
ip (varchar) ip (varchar)
id_auteur (bigint) id_auteur (bigint)
cookie (varchar) cookie (varchar)
statut (varchar) statut (varchar)
maj (timestamp) maj (timestamp)
id_article_export (bigint)
url (varchar)
confirmation (varchar)
rang (bigint)
bgch (bigint)
bdte (bigint)

niveau (bigint)||

Structure de spip_forms_donnees_champs Structure de spip_formulaires_reponses_champs
id_donnee (bigint) id_formulaires_reponse (bigint)
champ (varchar) nom (varchar)
valeur (text) valeur (text)
maj (timestamp) maj (timestamp)

Une méthode possible pour migrer ces données :
-  sous phpMyAdmin, exporter les données en Table Open Office en gardant les noms de champ en première ligne.
-  Supprimer les colonnes qui n’existent pas dans la table destination et faire concorder l’ordre des colonnes. Faire attention pour les champs de date que celles-ci restent au format MySql (aaaa-mm-jj hh:mm:ss).
-  Enregistrer le fichier résultat en csv (UTF-8, séparateur de champ : point-virgule, séparateur de texte : guillemets doubles).
-  Dans phpMyAdmin, importer le fichier csv (en ignorant la première ligne qui contient le nom des champs) dans la table destination.

Vous pouvez vérifier que tout s’est correctement déroulé en visualisant et analysant les réponses dans Formidable.

Adapter les squelettes.

(appel dans article.htm : <INCLURE{fond=inc-agenda}{env}{id_article,senstri}>)

Fichier inc-agenda.html

[(#SET{senstri,#ENV{senstri,0}})]

<div id="menu-agenda">
   [<a href="[(#SELF|parametre_url{id_reponse,''}|parametre_url{gerer,-1}|parametre_url{senstri, 0})]" title="Année en cours">Année en cours</a>]
   [<a href="[(#SELF|parametre_url{id_reponse,''}|parametre_url{gerer,-1}|parametre_url{senstri, 1})]" title="Années passées">Années passées</a>]
   [(#REM) affichage du menu d'ajout d'événement. Uniquement pour les administrateurs ]
   [(#SESSION{statut}|=={0minirezo}|oui)
      <a href="[(#SELF|parametre_url{id_reponse,''}|parametre_url{gerer,1})]" title="Ajouter une date" class="agenda-ajouter">Ajouter une date</a>
   ]
</div>

[(#ENV{gerer}|=={1}|non) 
   <div id="agenda" class="table">
      <INCLURE{fond=inc-agenda-afficher}{env}{id_article,senstri=#GET{senstri}}>
   </div>
]

[(#REM) affichage du formulaire si demande d'ajout ou de modification ]
[(#ENV{gerer}|=={1}|oui|et{#SESSION{statut}|=={0minirezo}|oui})
   #FORMULAIRE_FORMIDABLE{1,#ARRAY,#ENV{id_reponse}}
]

Fichier inc-agenda-afficher.html

#SET{cpt,0}
<BOUCLE_formulaire(FORMULAIRES){id_formulaire=1}>
   [(#REM) lister les saisies par leur nom de champ]
   #SET{saisies, #SAISIES|unserialize|saisies_lister_par_nom} 

   <BOUCLE_reponse(FORMULAIRES_REPONSES){id_formulaire}{tri_selon_donnee date_2}{inverse #ENV{senstri}}>

      #SET{valeurs,#ARRAY}
      <BOUCLE_champs(FORMULAIRES_REPONSES_CHAMPS){id_formulaires_reponse}>
         #SET{test_array,#VALEUR|unserialize}
         #SET{valeur,#GET{test_array}|is_array|?{#GET{test_array},#VALEUR}}
         #SET_MERGE{valeurs,#ARRAY{#NOM,#GET{valeur}}}
      </BOUCLE_champs>

      #SET{dateevenement,#GET{valeurs}|table_valeur{date_2}}
      
      #SET{cpt, #GET{cpt}|plus{1}}
      [(#ENV{senstri}|=={1}|non|et{#GET{dateevenement}|dansfutur|>={0}|oui})
         [(#INCLURE{fond=inc-agenda-ligne}
                              {id_formulaires_reponse}
                              {cpt=#GET{cpt}}
                              {dateevt=#GET{dateevenement}}
                              {saisies=#GET{saisies}}
                              {valeurs=#GET{valeurs}})]
      ]
      [(#ENV{senstri}|=={1}|oui|et{#GET{dateevenement}|dansfutur|<{0}|oui})
         [(#INCLURE{fond=inc-agenda-ligne}
                              {id_formulaires_reponse}
                              {cpt=#GET{cpt}}
                              {dateevt=#GET{dateevenement}}
                              {saisies=#GET{saisies}}
                              {valeurs=#GET{valeurs}})]
      ]

   </BOUCLE_reponse>

</BOUCLE_formulaire>

Fichier inc-agenda-ligne.html

#SET{saisies, #ENV{saisies}}
#SET{valeurs, #ENV{valeurs}}
#SET{dateevenement, #ENV{dateevt}}
#SET{env_affichage,#ARRAY{valeur_uniquement,oui,sans_reponse,""}}

[<div class="agenda_annee">(#GET{dateevenement}|annee|unique)</div>]

<div class="ligne [(#ENV{cpt}|alterner{row_even,row_odd})]">
   [(#REM) Date et heure de l'evenement ]
   <div class="afficher cellule">
      [(#GET{saisies}|table_valeur{ligne_1}|saisies_generer_vue{#GET{valeurs},#GET{env_affichage}}|textebrut)]
      [(#GET{valeurs}|table_valeur{ligne_1}|?{'',' '}) [(#GET{dateevenement}|affdate_jourcourt)]]
      [ - (#GET{saisies}|table_valeur{ligne_2}|saisies_generer_vue{#GET{valeurs},#GET{env_affichage}}|textebrut)]
   </div>

   [(#REM) Spectacle ]
   <div class="afficher cellule">
      [(#GET{saisies}|table_valeur{ligne_3}|saisies_generer_vue{#GET{valeurs},#GET{env_affichage}}|textebrut)]
   </div>

   [(#REM) Departement Ville ]
   <div class="afficher cellule">
      ([(#GET{saisies}|table_valeur{ligne_4}|saisies_generer_vue{#GET{valeurs},#GET{env_affichage}}|textebrut)]
      [ (#GET{saisies}|table_valeur{ligne_5}|saisies_generer_vue{#GET{valeurs},#GET{env_affichage}}|textebrut)])
   </div>

   [(#REM) Lien vers site officiel de l'evenement ]
   <div class="afficher cellule">
   	#SET{fermer,0}
      [#SET{fermer,1}<a href="(#GET{valeurs}|table_valeur{url_1})" class="spip_out">]
      [(#GET{saisies}|table_valeur{ligne_6}|saisies_generer_vue{#GET{valeurs},#GET{env_affichage}}|textebrut)]
      [(#GET{fermer}|=={1}|oui)</a>]
	</div>
   
   [(#REM) affichage des icones de modification et suppression. Uniquement pour les administrateurs non restreints ]
   [(#SESSION{statut}|=={0minirezo}|oui)
      <div class="afficher cellule">
      <a href="[(#SELF|parametre_url{gerer,1}|parametre_url{id_reponse,#ID_FORMULAIRES_REPONSE})]">
      	<img src="#CHEMIN{images/formulaire-configurer-16.png}" alt="<:Modifier:>" title="<:Modifier:>" />
      </a>
      </div>
      <div class="afficher cellule">
      <a onclick="javascript:return confirm('<:confirmer_supprimer_evt:>');" 
      	href="#URL_ACTION_AUTEUR{instituer_formulaires_reponse, #ID_FORMULAIRES_REPONSE-poubelle, #SELF|parametre_url{var_mode,recalcul}}">
         <img src="#CHEMIN{images/formulaire-annuler-16.png}" alt="<:Supprimer:>" title="<:Supprimer:>" />
      </a>
      </div>
   ]
</div>

Ceci n’est sûrement pas parfait, mais si ca peut aider... Je n’ai pas encore eu le temps de travailler sur « l’ajaxisation », il y a un recalcul à forcer quelque part, mais je n’ai trouvé ni où ni comment faire. "Avec spip, on apprend tous les jours".

A noter que formidable est compatible avec le plugin multilang. Il suffit d’ajouter aux champs désirés la classe multilang