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 I

7 February 2011
Catégorie : Astuces et Conseils
Posté par : bess
Dernièrement je me suis posé la question de savoir s'il était possible de gagner quelques octets sur l'installation de CmsMadeSimple. Après mettre rendu compte qu'il y avait matière à ceuser j'ai décidé de rédiger ce petit tutorial en plusieurs parties qui abordera des notions assez complètes pour créer un module à partir d'une balise utilisateur.

CmsMadeSimple peut il être plus léger qu'il ne l'est déjà ?

La réponse est oui (et hop je vous spoil la fin du tuto au passage). La faute à la manière dont CmsMadeSimple gère les fichiers de langues au travers des modules de tous poils.

Explications :

Actuellement vous pouvez installer une version dite "full" qui embarquera au passage toutes les traductions possibles de CmsMadeSimple. Vous avez également la possibilité d'installer une version de base (anglais uniquement) et y ajouter un addon français qui va se charger de traduire le contenu de CmsMadeSimple.

La plupart d'entre vous opteront pour cette seconde solution dès que vous souhaitez gagner de la place car embarquer des dizaines de fichiers de traduction, c'est pas rien...

Si la mise à disposition des archives de CmsMadeSimple est bien faite, ce n'est pas forcement le cas des modules qui ne sont disponibles qu'en version full !

Hé oui, installer un pack français, déterminer la langue en front-office et en back-office tout en français, faites tout comme il faudrait et puis installez un simple module : vous embarquez également le russe, l'allemand et tout le reste.

Evaluation des pertes (de place)

Petit exemple avec des modules que tout le monde connait :

  • CgExtensions : 2058 Ko dont 188 Ko de fichiers de langue non FR
  • FEU : 1679 Ko dont 876 Ko de fichiers de langue non FR
  • Gallery : 1514 Ko dont 271 Ko de fichiers de langue non FR

Et ainsi de suite... Plus il est connu et plus nombreuses seront les traductions associées

Alors supprimer les fichiers inutiles ne changera pas la face de votre site ça n'augmentera pas sa vitesse et ne vous libèrera pas 50% de la place prise par CmsMadeSimple. Mais pour un extrémiste du web comme moi, il est difficile de ne pas pester contre tous ces fichiers qui prennent de la place pour rien... d'ou là suite

Le tutorial

Je vais tout d'abord vous présenter la balise utilisateur et vous expliquer son utilisation. Une fois le principe maitrisé je rédigerais un tutorial qui transformera cette balise en module à part entière avec forcement plus d'options.

Tout d'abord j'ai besoin de lister les fichiers de langue de mon installation. Il y en a deux sortes : ceux qui ont un chemin identique d'une installation à une autre , et ceux qui (comme les fichiers de module) sont totalement changeant d'une installation à une autre.

Impossible dès lors de m'amuser à lister à l'avance TOUS les fichiers pouvant exister afin de faire une simple suppression de fichiers de langue si celui existe.

Je démarre donc avec la partie la plus simple en définissant un tableau comportant les patterns des répertoires connus et fixes :

define ("DIR", "D");
define ("FILE", "F");
$patterns = array();
$patterns[] = array(FILE,'/admin/lang/%1$s.nls.php');
$patterns[] = array(FILE,'/admin/lang/ext/%1$s/admin.inc.php');
$patterns[] = array(FILE,'/admin/lang/ext/%1$s/index.html');
$patterns[] = array(DIR,'/admin/lang/ext/%1$s');
$patterns[] = array(FILE,'/lib/lang/cms_selflink/ext/%1$s.php');
$patterns[] = array(FILE,'/lib/lang/tasks/ext/%1$s.php');
$patterns[] = array(FILE,'/lib/filemanager/ImageManager/lang/%2$s.js');

Je connais ces répertoires simplement en parcourant une installation sur mon PC et en trouvant à droite et à gauche ces fichus fichiers.

à celà j'ajoutes les répertoires des modules plus "/lang/ext" qui est la norme de fichiers de langues pour tous les modules. En premier je récupère le répertoire des modules :

global $gCms;
$config =& $gCms->GetConfig();
$path = $config['root_path'].'/modules';

Ensuite j'utilise une petite fonction prise je ne sais plus où qui va lister les répertoires de $path

$dirs = array();
global $gCms;
$config =& $gCms->GetConfig();
$path = $config['root_path'].'/modules';
if (!is_dir($path) || !$handle = @dir($path)) {
trigger_error('\''.$path.'\' doesn\'t exists or is not a valid directory', E_USER_ERROR);
} else {
while ($entry = $handle->read()) {
if ($entry !== "." && $entry !== "..") {
$path_to_entry = $path.'/'.$entry;
if (@is_dir($path_to_entry)) {
$dirs[] = $path_to_entry;
}
}
}
}

J'ai donc dans $dirs tous les répertoires des modules. Il me reste à leur ajouter les sous répertoires des fichiers de langue que je connais : "/lang/ext"

 

$patterns = array();
foreach($dirs as $dir){
$patterns[] = array(FILE,$dir.'/lang/ext/%1$s.php');
}

return $patterns;

 

Je place tout ce code dans une fonction que j'appel "getModulesDirectoriesToPattern()" pour faire plus propre et je peux donc rajouter à la liste des patterns déjà écrits ceux des répertoires des modules.

define ("DIR", "D");
define ("FILE", "F");
$patterns = array();
$patterns = getModulesDirectoriesToPattern();

$patterns[] = array(FILE,'/admin/lang/%1$s.nls.php');
$patterns[] = array(FILE,'/admin/lang/ext/%1$s/admin.inc.php');
$patterns[] = array(FILE,'/admin/lang/ext/%1$s/index.html');
$patterns[] = array(DIR,'/admin/lang/ext/%1$s');
$patterns[] = array(FILE,'/lib/lang/cms_selflink/ext/%1$s.php');
$patterns[] = array(FILE,'/lib/lang/tasks/ext/%1$s.php');

$patterns[] = array(FILE,'/lib/filemanager/ImageManager/lang/%2$s.js');

Maintenant que j'ai tous ces patterns, il me faut boucler dessus ET sur la liste des langues connues. J'ai donc du dresser un listing que chacun pourra enrichir à sa façon

$langs = array();
$langs[] = array("ca_ES");
$langs[] = array("cs_CZ");
$langs[] = array("da_DK");
$langs[] = array("de_DE");
$langs[] = array("es_ES");
$langs[] = array("en_CY");
$langs[] = array("et_EE");
$langs[] = array("fa_FA");
$langs[] = array("fi_FI");
//$langs[] = array("fr_FR","fr");
$langs[] = array("hr_HR");
$langs[] = array("hu_HU");
$langs[] = array("it_IT");
$langs[] = array("iw_IL");
$langs[] = array("ja_JP");
$langs[] = array("lt_LT");
$langs[] = array("nb_NO");
$langs[] = array("nl_NL","nl");
$langs[] = array("pl_PL");
$langs[] = array("pt_PT");
$langs[] = array("ro_RO");
$langs[] = array("ru_RU");
$langs[] = array("sk_SK");
$langs[] = array("sl_SI");
$langs[] = array("so_SO");
$langs[] = array("sr_YU");
$langs[] = array("sv_SE");
$langs[] = array("tr_TR");

Le premier paramètre sera utilisé dans les %1$ des patterns, évidement le second est dédié aux %2$. J'ai du utiliser cette ruse vu que les fichiers n'ont pas tous la même nomenclature pour se distinguer les uns des autres.

fichier.fr_FR.php et fichier.nl_NL.php VS autrefichier.fr.php et autrefichier.nl.php ... Allez comprendre :)

Bref nous voici donc avec la liste des langues et la liste des patterns des chemins (répertoires + fichiers), ne reste plus qu'une bonne double boucle pour en finir

Je définit une variable globale à faux pour l'instant

define ("DELETE", false);

et on boucle !

$size=0;
//Pour chaque patterns
foreach($patterns as $pattern){
//pour chaque langue
foreach($langs as $lang){
//On remplace les %1$ et %2$ par la langue
$path = sprintf($pattern[1], $lang[0], (count($lang)>1?$lang[1]:null));

//Si le pattern désigne un fichier qui existe
if($pattern[0] == FILE && @is_file($path)){
//on récupère son poids
$stat = stat($path);
$size += $stat[7];

echo <<<HTML
$stat[7]\t$path\n
HTML;
//Si à supprimer, on supprime
if(DELETE)
unlink($path);

//Si le pattern est un répertoire qui existe
} else if($pattern[0] == DIR && @is_dir($path)){
echo <<<HTML
\t\t$path\n
HTML;
//Si à supprimer, on supprime
if(DELETE)
rmdir($path);
}
}
}

echo "\n\nTOTAL ".(DELETE?"DELETED ":'').": $size";

Fin de l'histoire... Si la variable DELETE est définie à faux, on fait un simple listing, si elle est définie à vrai, on supprime les fichiers sans poser de question et on fait également un listing.

Rapide simple et efficasse, Notez qu'en commentant une ligne des langues ou en la décommentant vous sauvegardez les fichiers qui s'y rapportent, ainsi dans notre exemple, les fichiers de langue FR sont épargnées

Je vous redonne le code au complet et je vous souhaites bon nettoyage sur vos environnements de test bien évidement (tout le monde sais que tester en production c'est mortel dans tous les sens du terme...)



$temps_debut = microtime(true);


define ("DELETE", true);
//define ("DELETE", false);


$langs = array();
$langs[] = array("ca_ES");
$langs[] = array("cs_CZ");
$langs[] = array("da_DK");
$langs[] = array("de_DE");
$langs[] = array("es_ES");
$langs[] = array("en_CY");
$langs[] = array("et_EE");
$langs[] = array("fa_FA");
$langs[] = array("fi_FI");
//$langs[] = array("fr_FR","fr");
$langs[] = array("hr_HR");
$langs[] = array("hu_HU");
$langs[] = array("it_IT");
$langs[] = array("iw_IL");
$langs[] = array("ja_JP");
$langs[] = array("lt_LT");
$langs[] = array("nb_NO");
$langs[] = array("nl_NL","nl");
$langs[] = array("pl_PL");
$langs[] = array("pt_PT");
$langs[] = array("ro_RO");
$langs[] = array("ru_RU");
$langs[] = array("sk_SK");
$langs[] = array("sl_SI");
$langs[] = array("so_SO");
$langs[] = array("sr_YU");
$langs[] = array("sv_SE");
$langs[] = array("tr_TR");

define ("DIR", "D");
define ("FILE", "F");

function getModulesDirectoriesToPattern()
{
$dirs = array();
global $gCms;
$config =& $gCms->GetConfig();
$path = $config['root_path'].'/modules';
if (!is_dir($path) || !$handle = @dir($path)) {
trigger_error('\''.$path.'\' doesn\'t exists or is not a valid directory', E_USER_ERROR);
} else {
while ($entry = $handle->read()) {
if ($entry !== "." && $entry !== "..") {
$path_to_entry = $path.'/'.$entry;
if (@is_dir($path_to_entry)) {
$dirs[] = $path_to_entry;
}
}
}
}

$patterns = array();
foreach($dirs as $dir)
{
$patterns[] = array(FILE,$dir.'/lang/ext/%1$s.php');
}

return $patterns;
}

$patterns = array();
$patterns = getModulesDirectoriesToPattern();

$patterns[] = array(FILE,'/admin/lang/%1$s.nls.php');
$patterns[] = array(FILE,'/admin/lang/ext/%1$s/admin.inc.php');
$patterns[] = array(FILE,'/admin/lang/ext/%1$s/index.html');
$patterns[] = array(DIR,'/admin/lang/ext/%1$s');
$patterns[] = array(FILE,'/lib/lang/cms_selflink/ext/%1$s.php');
$patterns[] = array(FILE,'/lib/lang/tasks/ext/%1$s.php');

$patterns[] = array(FILE,'/lib/filemanager/ImageManager/lang/%2$s.js');



echo <<<HTML
################################
## CLEANING UDT FOR CMSMS
##
## Version 1.0.0 - 30/01/2011
##
## By Bess : contact at furie dot be
################################

HTML;

if(DELETE)
{
echo <<<HTML
##
## ! DELETING MODE !
##
################################


HTML;
} else
{
echo <<<HTML
##
## TESTING MODE : NO SUPPRESSION
##
################################


HTML;
}



$size=0;
//Pour chaque patterns
foreach($patterns as $pattern)
{
//pour chaque langue
foreach($langs as $lang)
{
//On remplace les %1$ et %2$ par la langue
$path = sprintf($pattern[1], $lang[0], (count($lang)>1?$lang[1]:null));

//Si le pattern désigne un fichier qui existe
if($pattern[0] == FILE && @is_file($path))
{
//on récupère son poids
$stat = stat($path);
$size += $stat[7];


echo <<<HTML
$stat[7]\t$path\n
HTML;
//Si à supprimer, on supprime
if(DELETE)
unlink($path);

//Si le pattern est un répertoire qui existe
} else if($pattern[0] == DIR && @is_dir($path))
{
echo <<<HTML
\t\t$path\n
HTML;
//Si à supprimer, on supprime
if(DELETE)
rmdir($path);
}
}
}

echo "\n\nTOTAL ".(DELETE?"DELETED ":'').": $size";

$temps_fin = microtime(true);
echo "\n\nTemps d'execution : ".round($temps_fin - $temps_debut, 4);

Voilà pour notre balise. Si vous avez des questions ou des idées d'améliorations : c'est en dessous. Personnellement j'ai gagné 2Mo de place sur une installation sommaire + quelques modules, et vous ?

Le prochains billet vous montrera donc comment depuis cette balise coder tout un module qui va faire encore plus : nettoyer même après l'installation d'un module ou sa mise à jour grace à la gestion des évènements sous CmsMadeSimple !

 

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