Dans cette page, je vais présenter les éléments constitutifs d'un module Dynacase et mettre en oeuvre ces éléments pour construire un module d'exemple qu'on nommera freedom-foo.
Pour bien suivre cette présentation, il est souhaitable d'avoir bien en tête les notions d'Applications et d'Actions de Dynacase et du fonctionnement général de ceux-ci.
[A détailler]
Vous avez surement déjà manipulé des Applications et des Actions dans Dynacase…
[A détailler]
Dans les exemples ci-dessous, nous allons détailler la construction d'un module freedom-foo qui fournira une Application Dynacase nommé FOO, avec un ensemble d'actions associés.
Le fichier info.xml permet de décrire le module Dynacase en fournissant en particulier la version du module, une description, des dépendances avec d'autres modules Dynacase, un ensemble de paramètres, un descriptif des évolutions (changelog), et un ensemble d'action de pre-install, post-install, etc.
<?xml version="1.0"?> <module name="freedom-foo" version="1.2.3" release="1" [basecomponent="no"]> <description lang="en">Freedom foo</description> [<description lang="fr">Freedom toto</description>] <requires> [<installer version="1.0.0" comp="ge" />] <module name="freedom-bar" /> <module name="freedom-baz" version="1.0.0" comp="ge" /> [...] </requires> <parameters> <param name="foo_dir" label="Directory of FOO" type="text" default="/var/foo" needed="yes" /> <param name="foo_color" label="Color of FOO" type="enum" values="red|green|blue" default="green" needed="no" /> </parameters> <changelog> <version number="1.1.1" date="2009-01-01"> <change title='First change' url='http://dev.dynacase.org/issues/111'> Comment for first change. </change> <change title='Second change'> Comment for second change. </change> <change title='Third change'> </change> </version> <version number="1.1.0" date="2008-12-15"/> </changelog> <pre-install> <check type="syscommand" command="zip" /> <check type="phpfunction" function="pg_connect"> <help>You might need to install a php-pg package.</help> </check> <check type="file" file="/var/foo" predicate="is_dir" /> </pre-install> <post-install> <process command="programs/app_post FOO I" /> <process command="programs/record_application FOO" /> <process command="programs/app_post FOO U" /> <process command="programs/update_catalog" /> </post-install> <post-upgrade> <process command="programs/pre_migration FOO" /> <process command="programs/app_post FOO U" /> <process command="programs/record_application FOO" /> <process command="programs/post_migration FOO" /> <process command="programs/update_catalog" /> </post-upgrade> <post-param> </post-param> </module>
La racine du document info.xml est un tag <module> avec les attributs suivants :
name : le nom du moduleversion : la version du module (sous la forme N.N.N)release : le numéro de release de la versionbasecomponent : yes ou no, permet de spécifier si le module est un module de base, obligatoire a toute installation de Dynacase (optionnel, par défaut la valeur est no)author : l'auteur du module (ex. John Doe john.doe@example.net)(optionnel)licence : licence du module (optionnel)<?xml version="1.0"?> <module name="freedom-foo" version="1.2.3" release="rc1" author="John Doe <john.doe@example.net>" licence="GPLV2"> [...] </module>
Le module peut fournir une description textuelle pour expliciter le rôle du module. On pourra fournir des descriptions localisés en utilisant l'attribut lang.
Exemple :
<description lang="fr">Ce module permet à Dynacase de se connecter à FOO</description> <description lang="en">This module allows Dynacase to connect to FOO</description>
Les dépendances permettent d'exprimer qu'un module requiert d'autres modules Dynacase avec eventuellement une contrainte sur la version de ceux-ci.
Le tag <requires> est composés d'éléments <module> qui ont les attributs suivants :
name : le nom du module Dynacase requisversion : la version que le module requis doit avoircomp : gt ou ge, opérateur de comparaison de version
Le module peut aussi exprimer une contrainte sur la version de l'installeur lui même à l'aide de l'élément <installer>. Dans ce cas, les attributs sont :
version : la version de l'installeur que requiert le modulecomp : gt ou ge, opérateur de comparaison de version Exemple :
<requires> <installer version="1.0" comp="ge" /> <module name="freedom-bar" version="2.0" comp="ge" /> <module name="freedom-baz" version="1.9" comp="gt" /> <requires>
Dans cet exemple, le module requiert un installeur avec une version >= 1.0, le module freedom-bar en version >= 2.0 et le module freedom-baz en version > 1.9.
Le changelog permet d'indiquer les évolutions produites en rapport avec les versions du module. Ces informations sont contenues dans une balise <changelog> contenant des <version>.
Les éléments <version> ont les attributs suivants :
number : le numero de versiondate : la date de publication de la version
Les éléments <version> contiennent des éléments <change> qui décrivent chaque changement effectué. Les éléments <change> ont les attributs suivants :
title : l'intitulé du changementurl : une url en rapport avec le changement (dans l'interface dynacase-control, les chaines de forme issues/111/ sont reconnues et donnent comme texte du lien affiché 'issues 111' ; sinon un texte par défaut est utilisé)
La valeur de l'élément <change> constitue une description.
Exemple :
<changelog> <version number="1.1.1" date="2009-01-01"> <change title='First change' url='http://dev.dynacase.org/issues/111'> Comment for first change. </change> <change title='Second change'> Comment for second change. </change> <change title='Third change'> </change> </version> <version number="1.1.0" date="2008-12-15"/> </changelog>
Un module peut demander lors de son installation (ou upgrade) l'entrée de certains paramètres.
Les paramètres nécessaires au module sont renseignés avec un élément <parameters> contenant des éléments <param>.
Les élements <param> ont les attributs suivants :
name : le nom du paramètrelabel : le label textuel pour présenter le paramètretype : text ou enum, permet de spécifier le type de donnée attendudefault : la valeur par défaut présenté à l'utilisateur lors de la saisie des paramètres.needed : yes ou no, permet de spécifier si la saisie du paramètre est obligatoire ou optionnelle.values : lorsque type=“enum”, l'attribut values permet de spécifier une list de choix finis à partir de laquelle l'utilisateur selectionnera une valeur Exemple :
<parameters> <param name="foo_dir" label="Directory of FOO" type="text" default="/var/foo" needed="yes" /> <param name="foo_color" label="Color of FOO" type="enum" values="red|green|blue" default="green" needed="no" /> </parameters>
Lors de l'installation, upgrade ou suppression d'un module, un ensemble d'actions peuvent être effectués avant (pre) et après (post) l'opération suivant l'ordre suivant :
Chaque phase (pre-install, post-install, etc.) spécifie un ensemble de check ou process qui sont exécutés et qui retournent un status d'échec ou de réussite.
Une phase est validé lorsque tous ses sous-éléments check ou process ont retournés un statut de réussite.
Si une phase n'est pas validé, alors l'installation, ou l'upgrade, alors il est présenté à l'utilisateur les messages d'erreurs rencontrés, et celui-ci peut rejouer la phase après avoir eventuellement corrigé le problème, ou bien il peut choisir d'ignorer les messages d'erreurs et poursuivre l'install/ugprade.
Les éléments de pre-install s'exécutent avant l'installation des fichiers du module sur le système de fichier.
Les actions possible peuvent être des éléments <check>.
Chaque élément <check> peut fournir un élément <help> qui sera présenté à l'utilisateur lorsque l'action échoue.
Exemple :
<pre-install> <check type="phpfunction" function="pspell_new"> <help>Il faut peut-être installer php5-pspell avec apspell et aspell-fr</help> </check> <check type="syscommand" command="convert" /> </pre-install>
Les actions de pre-install serviront généralement à vérifier la présence de certains éléments et bloquer l'installation si ces éléments ne sont pas présents/corrects.
Les éléments de post-install s'exécutent après l'installation des fichiers du module sur le système de fichier.
Les actions possible peuvent être des éléments <process>.
Chaque élément <process> peut fournir un élément <label> qui sera présenté à l'utilisateur lorsque l'action sera exécuté.
Exemple :
<post-install> <process command="programs/record_application FOO"> <label lang="en">Record FOO application in database</label> </process> <process command="programs/update_catalog"> <label lang="en">Generate localization catalog</label> </process> </post-install>
Les actions de post-install serviront généralement à configurer le module qui viens d'être isntallé. Une erreur dans la phase de post-install laissera les fichiers installés en place, mais le paquet sera marqué en erreur de post-install dans l'interface.
Les éléments de pre-upgrade s'exécutent avant l'installation des nouveaux fichiers du module sur le système de fichier.
Les actions possible peuvent être des éléments <check>.
Chaque élément <check> peut fournir un élément <help> qui sera présenté à l'utilisateur lorsque l'action échoue.
Exemple :
<pre-upgrade> <check type="phpfunction" function="pspell_new"> <help>Il faut peut-être installer php5-pspell avec apspell et aspell-fr</help> </check> <check type="syscommand" command="convert" /> </pre-upgrade>
Les actions de pre-upgrade serviront généralement à vérifier la présence de certains éléments et bloquer l'upgrade si ces éléments ne sont pas présents/corrects.
Les éléments de post-upgrade s'exécutent après l'installation des nouveaux fichiers du module sur le système de fichier.
Les actions possible peuvent être des éléments <process>.
Chaque élément <process> peut fournir un élément <label> qui sera présenté à l'utilisateur lorsque l'action sera exécuté.
Exemple :
<post-upgrade> <process command="programs/pre_migration FOO"> <label lang="en">Pre-migration scripts</label> </process> <process command="programs/record_application FOO"> <label lang="en">Update application record in database</label> </process> <process command="programs/post_migration FOO"> <label lang="en">Post-migration scripts</label> </process> <process command="programs/update_catalog"> <label lang="en">Re-generate localization catalog</label> </process> </post-install>
Les actions de post-upgrade serviront généralement à configurer le module qui viens d'être isntallé, lancer les scripts de migration, etc. Une erreur dans la phase de post-upgrade laissera les fichiers installés en place, mais le paquet sera marqué en erreur de post-upgrade dans l'interface.
Les éléments check permettent d'executer des actions pour vérifier la présence de certains éléments.
Le check de type phpfunction permet de vérifier la présence d'une fonction PHP.
Le nom de la fonction testé est spécifié avec l'attribut function.
Exemple :
<check type="phpfunction" function="pg_connect" />
Le check de type syscommand permet de vérifier la présence d'une commande disponible sur le système.
Le nom de la command testé est spécifié avec l'attribut command
Exemple :
<check type="syscommand" command="convert" />
Le check de type phpclass permet de vérifier la présence d'une classe objet PHP.
Le nom de la classe PHP est fournis avec les attributs suivants :
include : le nom du fichier pour inclure la définition de la classeclass : le nom de la classeExemple :
<check type="phpclass" include="Net/SMTP.php" class="Net_SMTP" />
LE check de type apachemodule permet de vérifier qu'un module Apache particulier est activé et chargé par celui-ci.
Le nom du module est spécifié par l'attribut module.
Exemple :
<check type="apachemodule" module="mod_expires" />
Les éléments process servent à exécuter les actions permettant d'effectuer les opérations nécessaires au fonctionnement du module suite à son installation.
Prototype :
programs/app_post <APPNAME> I|UUtilisable dans les phases :
post-installpost-upgradeConditions d'utilisation :
post-install, le programme doit être exécuté avec le programme record_applicationpost-upgrade, le programme doit être exécuté après pre_migration et avant le programme record_application
Le programme app_post permet de lancer un script _post pour initialiser une application Dynacase.
Les arguments sont :
I | U : Le nom de la phase d'initialisation a exécuter (I pour install, U pour upgrade)Exemple :
<post-install> <process command="programs/post_app WEBDESK I" /> [...] </post-install> <post-upgrade> [...] <process command="programs/post_app WEBDESK U" /> [...] </post-upgrade>
Prototype :
programs/record_application <APPNAME>Utilisable dans les phases :
post-installpost-upgradeConditions d'utilisation :
app_post
Le programme record_application est utilisé pour enregistrer, ou mettre à jour, la définition de l'application en base de données.
La ligne de commande est spécifié par l'attribut command.
record_application prend en argument le nom de l'application à enregistrer.
Exemple :
<process command="programs/record_application FOO" />
Prototype :
programs/update_catalogUtilisable dans les phases :
post-installpost-upgradeConditions d'utilisation :
Le programme update_catalog est utilisé pour ré-générer le catalogue des messages de localisation.
Exemple :
<process command="programs/update_catalog" />
Prototype :
programs/pre_migrationUtilisable dans les phases :
post-upgradeConditions d'utilisation :
app_post
Le programme pre_migration est utilisé pour exécuter les scripts de pre-migration d'un module lors de sa mise-à-jour.
Exemple :
<process command="programs/pre_migration" />
Prototype :
programs/post_migrationUtilisable dans les phases :
post-upgradeConditions d'utilisation :
record_application, et avant le update_catalog
Le programme post_migration est utilisé pour exécuter les scripts de post-migration d'un module lors de sa mise-à-jour.
Exemple :
<process command="programs/post_migration" />
Prototype :
./wsh.phpUtilisable dans les phases :
post-installpost-upgradeConditions d'utilisation :
Le programme ./wsh.php est utilisé pour exécuter des méthodes sur des classes documentaires et exécuter des API Dynacase.
Exemple :
<process command="./wsh.php --api=freedom_refresh --method=postModify --famid=FOO" />
Vous avez la possibilité d'écrire vos propres programmes de post-install, post-upgrade, etc. afin d'effectuer des opérations spécifiques à votre module.
Ces programmes seront généralement développés soit en shell Bash soit en PHP. Ils seront disponible après la phase de décompression de votre paquet, dans le répertoire que vous aurez spécifié à l'empaquetage.
Le programme est exécuté dans le répertoire racine de l'installeur DYNACASE-CONTROL, et les variables d'environnement suivantes sont accessible depuis le script :
$CWD) dans lequel sera exécuté votre programmes)Exemple :
#!/bin/bash set -e # -- Récupérer la valeur du paramètre `foo_dir' spécifié par l'utilisateur PARAM_FOO_DIR=`"$WIFF_ROOT"/wiff --getValue=foo_dir` # -- Créer le répertoire s'il n'existe pas if [ ! -d "$PARAM_FOO_DIR" ]; mkdir "$PARAM_FOO_DIR" fi # -- Ajouter le nom de ce répertoire dans le fichier # -- `foo_dir.list' dans le sous-répertoire de mon module `FOO' echo "$PARAM_FOO_DIR" >> "$WIFF_CONTEXT_ROOT"/FOO/foo_dir.list
Note : Le programme PHP a aussi accès aux variables d'environnement, comme le script Bash, mais le chemin d'include doit être construit en fonction de vos besoins.
Exemple :
#!/usr/bin/env php <?php $WIFF_ROOT=getenv('WIFF_ROOT'); if( $WIFF_ROOT === false ) { print "WIFF_ROOT environment variable is not set!"; exit( 1 ); } $WIFF_CONTEXT_ROOT=getenv('WIFF_CONTEXT_ROOT'); if( $WIFF_CONTEXT_ROOT === false ) { print "WIFF_CONTEXT_ROOT environment variable is not set!"; exit( 1 ); } # -- Si je dois accéder aux fichier d'include de Dynacase # -- j'ajoute les répertoire d'include de Dynacase # -- dans mon include_path PHP set_include_path( get_include_path().PATH_SEPARATOR."$WIFF_ROOT/include".PATH_SEPARATOR$WIFF_CONTEXT_ROOT ); set_include_path(join(PATH_SEPARATOR, array( get_include_path(), "$WIFF_ROOT/include", "$WIFF_CONTEXT_ROOT" ))); # -- A présent, je peux inclure les librairies de l'installeur require("lib/Lib.Cli.php"); # -- ... et les librairies Dynacase require("WHAT/Lib.Common.php"); $param_foo_dir = wiff_getParamValue('foo_dir'); if( ! is_dir($param_foo_dir) ) { $ret = mkdir($param_foo_dir); if( $ret === false ) { print sprintf("Error: could not create directory '%s'!", $param_foo_dir); exit( 1 ); } } ?> [A compléter]
Pour fabriquer votre fichier webinst il faut disposer d'un fichier configure.in d'un fichier Makefile.in comme ceux-ci.
Le configure.in
# Autoconf script for libphp
#
#
AC_REVISION($Id: configure.in $)
dnl
dnl Process this file with autoconf to produce a configure script.
dnl
AC_PREREQ(2.13)
AC_INIT(./Makefile.in)
AC_SUBST(VERSION)
VERSION=`cat VERSION`
AC_SUBST(RELEASE)
RELEASE=`cat RELEASE`
AC_SUBST(PACKAGE)
PACKAGE=freedom-myapplication
AC_SUBST(APPNAME)
APPNAME=MYAPP
ac_default_prefix=/usr/share/what
AC_SUBST(PUBRULE)
PUBRULE=
AC_ARG_WITH(pubrule, [ --with-pubrule=dir Path to PubRule], PUBRULE=$withval)
if test "x$PUBRULE" != "x"; then
PUBRULEDIR=$PUBRULE
else
if test "x$PUBRULEDIR" == "x"; then
AC_CHECK_FILE($HOME/anakeen/devtools/PubRule, PUBRULEDIR=$HOME/anakeen/devtools/)
if test "x$PUBRULEDIR" = "x"; then
PUBRULEDIR=`pwd`
fi
fi
fi
AC_CHECK_FILE($PUBRULEDIR/PubRule, PUBRULE=$PUBRULEDIR)
if test "x$PUBRULE" = "x"; then
AC_MSG_ERROR([Could not find PubRule])
fi
AC_MSG_NOTICE([PubRule located at $PUBRULE])
AC_OUTPUT(Makefile info.xml )
Le Makefile :
# ============================================
# $Id: Makefile.in $
# ============================================
PACKAGE = @PACKAGE@
VERSION = @VERSION@
RELEASE = @RELEASE@
utildir=@PUBRULE@
pubdir = @prefix@
appname = offline
srcdir = @srcdir@
SUBDIR= Action
TOP_MODULES =
TAR = gtar
GZIP_ENV = --best
export targetdir PACKAGE
pages_not_xml = info.xml
include $(utildir)/PubRule
DISTFILES += $(SUBDIR) \
RELEASE VERSION
le makefile inclut le fichier Pubrule. Il contient un ensemble de règles pour publier le code et fabriquer les paquets.
Vous devez inclure ce fichier dans le répertoire de vos sources. Ensuite vous tapez :
autoconf ./configure make webinst
cela va générer le fichier webinst correspondant à votre module.