Puissant pour les pros
Simple pour les utilisateurs

CMS Made Simple, un CMS open source, permet la gestion rapide et facile des contenus d'un site web. Ce CMS est adapté aussi bien pour les petites sociétés que pour les grandes entreprises.

archives

Construire un module - part III

16 May 2011
Catégorie : Astuces et Conseils
Posté par : bess
Nouvelle étape dans la création de votre module, nous allons nous attarder sur les fonctionnalités des fichiers d'installation , de désinstallation et de mise à jour de votre module.

Au départ

Nous avons vu dans un précédent billet qu'un module pouvait se résumer à quelques fichiers :

  • ./CmsModuleCleaner.module.php
  • ./method.install.php
  • ./method.uninstall.php
  • ./lang/en_US.php

Nous allons aujourd'hui nous pencher sur les fichiers d'installation et de désinstallation avant d'embrayer sur un fichier optionnel : celui de la mise à jour.

Pour rappel : nous travaillons toujours sur la création d'un module issu de la balise présentée dans le premier tuto : comment nettoyer CmsMadeSimple des fichiers de langues inutiles.

Récapitulatif non exhaustif des possibilités pour l'installation

CmsMadeSimple permet de très nombreuses opérations pour ces modules. Je vais vous faire la liste des principales fonctions que vous serez amenés un jour à utiliser.

Sécuriser l'accès aux fichiers

Par défaut : ajoutez toujours cette ligne dans le haut de vos fichiers, c'est le meilleur moyen d'éviter des accès indésirables.

if (!isset($gCms)) exit;

Elle signifie : si l'accès ne provient pas du noyau de CmsMadeSimple, je refuse l'accès.

Personnaliser l'expérience utilisateur

La plupart des modules auront besoin de sauvegarder les paramètres de fonctionnement. Je ne parles pas ici d'enregistrer les logs de fonctionnement, mais bien de savoir si l'utilisateur souhaite que mon module de nettoyage des fichiers de langues fonctionne une fois par jour, par heure ,par mois ou jamais.

Cette fonction peut être récupérée dans le module ainsi :

$this()->GetPreference('nom_de_mon_paramètre');

voir la documentation complète de la fonction

et elle peut être mise à jour tout simplement :

$this()->SetPreference('nom_de_mon_paramètre', ##Nouvelle Valeur## );

voir la documentation complète de la fonction

Pensez donc lors de l'installation d'un module à pré-saisir les valeurs des préférences de fonctionnement. Pour notre module de nettoyage, je vais dire par exemple que je dois nettoyer tous les mois, et je vais en profiter pour initialiser la liste des langues connues, la liste des langues que l'utilisateur voudra supprimer. Enfin je vais ajouter un paramètre spécifiant par défaut que je ne supprime rien, le module ferra donc qu'un simple listing après son installation.

le fichier d'installation doit donc contenir :

$delay = 60 * 60 * 24 * 30; // +/-  1 mois
$suppression = false;

$pipe = '|';
$sep = ';';

$langs = "";
$langs.= "ca_ES" . $pipe;
$langs.= "cs_CZ" . $pipe;
$langs.= "da_DK" . $pipe;
$langs.= "de_DE" . $pipe;
$langs.= "es_ES" . $pipe;
$langs.= "en_CY" . $pipe;
$langs.= "et_EE" . $pipe;
$langs.= "fa_FA" . $pipe;
$langs.= "fi_FI" . $pipe;
$langs.= "fr_FR" . $sep . "fr" . $pipe;
$langs.= "hr_HR" . $pipe;
$langs.= "hu_HU" . $pipe;
$langs.= "it_IT" . $pipe;
$langs.= "iw_IL" . $pipe;
$langs.= "ja_JP" . $pipe;
$langs.= "lt_LT" . $pipe;
$langs.= "nb_NO" . $pipe;
$langs.= "nl_NL" . $sep . "nl" . $pipe;
$langs.= "pl_PL" . $pipe;
$langs.= "pt_PT" . $pipe;
$langs.= "ro_RO" . $pipe;
$langs.= "ru_RU" . $pipe;
$langs.= "sk_SK" . $pipe;
$langs.= "sl_SI" . $pipe;
$langs.= "so_SO" . $pipe;
$langs.= "sr_YU" . $pipe;
$langs.= "sv_SE" . $pipe;
$langs.= "tr_TR" . $pipe;

$langs_a_supprimer = "";


// creation des préférences
$this->SetPreference("delay", $delay);
$this->SetPreference("suppression", $suppression);
$this->SetPreference("liste_langue", $langs);
$this->SetPreference("liste_langue_a_supprimer", $langs_a_supprimer);

Persistance des données

Sans doute une des parties les plus complexe : la gestion des accès en base de donnée. C'est un coup à prendre.

Voici quelques points :

Avec CmsMadeSimple on ne gère pas l'incrémentation automatique comme sous mysql, il faut comprendre que CmsMadeSimple repose sur une surcouche qui est capable normalement d'aller sur d'autre plateforme que Mysql, or certaines de ces plateformes ne gère pas l'incrémentation automatique (Oracle par exemple). Nous utiliserons donc un système qui est compatible partout : les séquences simulées par une table.

Exemple le plus parlant : j'ai une liste de client à insérer en base. L'identifiant du client sera un numéro incrémenté.

Je dois donc créer une table : client contenant 2 colonnes : un numéro et un libellé (nom + prénom)

Je créé également une seconde table client_seq qui contiendra une seule colonne : un numéro.

Lorsque j'insère un nouvel enregistrement, je vais vérifier d'abords dans client_seq quelle est la valeur (zéro au départ), j'ajoute 1 à cette valeur, et je met à jour la ligne dans client_seq. J'ajoute ensuite la ligne : 1-Dupont Maurice.

J'insère un nouvel enregistrement. je vais vérifier d'abords dans client_seq quelle est la valeur (Un cette fois ci), j'ajoute 1 à cette valeur, et je met à jour la ligne dans client_seq. J'ajoute ensuite la ligne : 2-Lefrançais François.

et ainsi de suite.

Maintenant prenons notre cas : je souhaites conserver le log de traitement de mon module, c'est un simple texte doublé d'une date, ce qui nous arrangent bien puisque c'est assez proche de notre exemple du dessus.

Prenez l'habitude de nommer les tables de la même manière dans vos modules :

module_nomDuModule_XXX et module_nomDuModule_XXX_seq

Notez qu'on ne préfixe pas par cms_ ce qui est pourtant la norme par défaut. L'explication viendra en dessous

Nous aurons donc

module_cmsModuleCleaner_log et module_cmsModuleCleaner_log_seq

avec 3 colonnes pour la première table : log_id (Entier) | log_texte (Chaine de 255 caractères) | log_date (date)

Le code de tout cela commence par l'initialisation de l'accès BDD :

$db =& $gCms->GetDb();
$taboptarray = array( 'mysql' => 'TYPE=MyISAM' );
$dict = NewDataDictionary( $db );

On continue par la déclaration de la première table, avant de la créer physiquement

// table schema description
$flds = "
log_id I KEY,
log_texte C(255),
log_date " . CMS_ADODB_DT . "
";

$sqlarray = $dict->CreateTableSQL( cms_db_prefix()."module_cmsModuleCleaner_log",
$flds,
$taboptarray);
$dict->ExecuteSQLArray($sqlarray);

Enfin on créé la séquence associée.

// create a sequence
$db->CreateSequence(cms_db_prefix()."module_cmsModuleCleaner_log_seq");

En bonus on peut ajouter un index sur la colonne de la date afin d'accélérer le traitement côté présentation

$query = 'ALTER TABLE '.cms_db_prefix().'module_cmsModuleCleaner_log ADD INDEX (log_date)';
if ($db->Execute($query) === false)
{
die('erreur grave durant l\'installation');
}

Notez dans la "table schema description" de l'utilisation des symboles I,C .. ils spécifient évidement le format de la colonne

  • I : entier
  • C(x) : chaine de x caractères max
  • X : chaine de longueur indéfinie (attention, ca peut ralentir le site si mal utilisé)
  • CMS_ADODB_DT : une date

+ d'information sur le site du framework

Voilà nous avons finit pour la partie génération bdd, nous verrons évidement le complément durant les prochaines parties de création du module.

Permission d'accès

Et si nous souhaitions ne laisser l'accès qu'aux personnes autorisées ? on va effectivement éviter de laisser le premier gus supprimer tous les fichiers de langue sans distinction non ? Allez hop c'est partis avec la fonction suivante :

// create a permission
$this->CreatePermission('cmsModuleCleaner_acces_standard','cmsModuleCleaner : accéder au module');

voir la documentation complète de la fonction

Enrichir le fichier de log de CmsMadeSimple

CmsMadeSimple possède son propre fichier de log qui permet de suivre les installations / désinstallations de toute sorte. Pensez à le renseigner.

$this->Audit( 0, $this->Lang('friendlyname'), $this->Lang('installed'));

Et le reste

Voici pour les 4 grands points que vous retrouverez dans vos fichiers d'installation. Notez qu'il existe également 2 autres sujet que je n'aborderais pas de suite :

La gestion des évènements : très complexe car très abstrait nous le verrons ultérieurement.

La gestion des gabarits : pas mal complexe également, et je ne vois pas comment en parler au travers de mon module de nettoyage, on verra cela sans doute plus tard ;)

Récapitulatif non exhaustif des possibilités pour la désinstallation

J'avais déjà évoqué le sujet dans le précédent billet : il faut penser à TOUT RETIRER : table, préférence, permissions, évènements et gabarits.

Il n'est pas nécessaire de supprimer les fichiers même de votre module, c'est CmsMadeSimple qui s'en occupera.

La désinstallation se fait plus rapidement que l'installation.

On sécurise l'accès à la page

if (!isset($gCms)) exit;

Retirer toutes les préférences :

$this->RemovePreference();

Retirer toutes les tables et séquences :

$db =& $gCms->GetDb();
// remove the database modules_cmsModuleCleaner_log
$dict = NewDataDictionary( $db );
$sqlarray = $dict->DropTableSQL( cms_db_prefix()."module_cmsModuleCleaner_log" );
$dict->ExecuteSQLArray($sqlarray);
$db->DropSequence( cms_db_prefix()."module_cmsModuleCleaner_log_seq" );

Retirer les permissions

$this->RemovePermission('cmsModuleCleaner_acces_standard');

Pensez à renseigner le log de CmsMadeSimple.

$this->Audit( 0, $this->Lang('friendlyname'), $this->Lang('uninstalled'));

Évidement il faut enrichir notre fichier de langue de trois nouvelles lignes :

$lang['installed'] = 'CmsModuleCleaner installed with succes';
$lang['uninstalled'] = 'CmsModuleCleaner uninstalled with succes';
$lang['upgraded'] = 'CmsModuleCleaner upgraded with succes';

La mise à jour de notre installation.

Nous avons vu dans le précédent billet que notre version 1.0.0 était ... pauvre en contenu. Mais elle est déjà installée ! ce qui signifie que si j'ajoute par dessus la prochaine version, CmsMadeSimple ne passera pas par les fichiers d'installation, ne crééra pas de table et rien ne se ferra.

La première solution est de désinstaller le module 1.0.0 et d'installer la version disponible en bas de ce billet... mais bon... c'est un peu de la triche...

La seconde solution est d'ajouter un fichier nommé : ./method.upgrade.php

C'est ce fichier qui sera parcouru à chaque fois que CmsMadeSimple tentera de mettre à jour votre module. Si le fichier n'existe pas, CmsMadeSimple partira du principe qu'il n'y a rien à faire et traitera correctement la mise à jour. Si le fichier est présent dans le fichier xml de la nouvelle version, CmsMadeSimple exécutera en priorité.

Les fonctions à l'intérieur sont exactement les même que celles que nous avons vu pour l'installation et la désinstallation. Cela signifie qu'entre deux versions vous pourrez créer de nouvelles tables, de modifier leur structures, d'ajouter et supprimer des préférences, de faire de savant calcul et d'enregistrer le tout.... Bref rien de neuf pour ceux qui ont lu le début de l'article :)

Encore une fois un seul rappel : sécurisez le fichier :

if (!isset($gCms)) exit;

Il y a toujours un point sensible dans le maintien d'un module : la rétro-compatibilité. Imaginez que vous êtes à la version 10.5.687 (super!) ... cette version apporte juste une permission supplémentaire, vous allez donc dans le fichier ./method.upgrade.php ajouter la création de cette permission. Ainsi ceux qui étaient dans la version précédente auront droit à la mise à jour.

Mais Qu'en est il des personnes étant encore en version 1.0.0 ? ne faut il pas conserver les mise à jour cumulées pour qu'elles puissent passer de 1.0.0 à 10.5.687 ?

A l'inverse, si on conserve tout, tout, tout... que se passe il pour ceux qui ont déjà fait les modifications des dizaines de version précédente ?

Voici pour info le code que j'utilise, je ne prétends pas qu'il soit parfait mais il fonctionne :)

$db =& $gCms->GetDb();
$cleaner =& $gCms->modules["CmsModuleCleaner"]['object'];

if(!isset($cleaner))
return;

$current_version = $oldversion;
switch($current_version)
{
// On est en version 1.0.0
case "1.0.0":version_1_0_0($cleaner);
case "1.1.0":version_1_1_0($cleaner);
}

function version_1_0_0($cleaner)
{
//Va servir pour migrer de 1.0.0 à 1.1.0.
$delay = 60 * 60 * 24 * 30; // +/- 1 mois
$suppression = false;

[ .... Code issu du fichier d'installation ... ]

// create a permission
$cleaner->CreatePermission('cmsModuleCleaner_acces_standard','cmsModuleCleaner : accéder au module');

//Ne pas oublier d'appeler les migrations suivantes : version_1_1_0
version_1_1_0();
}

function version_1_1_0($cleaner)
{
//Servira pour la prochaine mise à jour 1.1.0 -> autre
}

Ainsi, peut importe sa version actuelle, on prendra le train en marche et on se mettra à jour sur uniquement les points qui nous concerne.

Note : oubliez pas de mettre à jour le numero de version dans le fichier ./CmsModuleCleaner.module.php et d'ajouter la log pour CmsMadeSimple en fin de fichier

$this->Audit( 0, 
$this->Lang('friendlyname'),
$this->Lang('upgraded', $this->GetVersion()));

Tester son installation

Une fois l'installation effectuée (ou sa mise à jour, tout dépends de quel état vous démarrez), il faut tester l'installation de son module.

Pour celà, voici quelques astuces :

Après installation/mise à jour on vérifie que tout existe bien

Tester les créations de tables depuis phpmyadmin :

Tester les créations de préférences depuis phpmyadmin :

Tester les permissions depuis phpmyadmin

Et évidement après désinstallation on vérifie que rien ne reste.

Bilan 3

Nous voilà à la fin de cette troisième partie sur l'install/upgrade et la désinstallation de votre module ! Vous pouvez retrouver notre module en version 1.1.0 et tester chez vous l'installation de se module qui s'installe vraiment bien ... mais fait rien d'autre ^^

CmsModuleCleaner-1.1.0.xml (Clic droit > enregistrer sous)

Prochaine étape : nous allons réaliser noter première page dans le panneau d'administration qui permettra de mettre à jour les paramètres de fonctionnement de notre module via les préférences.

 

Stay tuned !

Et pour tous ceux qui ne le savent pas encore ? CMS Made Simple c'est également Facebook, Twitter et même un flux RSS pour rester constamment au courant des nouveautés, des annonces et des préviews de la communauté ! Alors aucune excuse pour dire que vous n'étiez pas au courant :)

  Flux Rss Twitter Facebook