Hi again everybody,
I've been pretty busy lately, so I haven't had much time to work on xoops-related things.
However, I had started to walk a path, and wanted to continue following it to the end ofthe road. With this update to my previous description (erlier in this thread), I think we are slowly reaching a point where Xoops2 will be able to have easy cloneable modules.
Previously I've introdused
$ModuleDirName (shortly known as $ModuleName) and
$VarPrefix and shown how to use those to make dynamically changeable language-constants, and to easier access files and URL's I've introdused
$ModuleUrlPath and
$ModuleRootPath.
Mvandam showed how to use the above to access the module's database tables.
I belive searching, notification and comments can be done the same way, but I've not looked into that yet. (Please let me know!)
Then phatjew mentioned the problem with blocks, function and class-names, which has to be different for each clone of the module, which made it even harder to make a fully cloneable module. I'm still not sure why function and class-names needs to be unique within the module except when they are dealing with blocks, but I'm sure you will be able to explain why to me, and to provide me with an example so I can see it fail with my own eyes.
Well, back to why I'm writing this.
I saw there were a problem with the functions related to blocks, and after many hours of thinking and a few hours of coding (actualy mostly looking the php manual) I've found this solusion:
From xoops_version.php, a block will have to be called like this:
// At the top of the file:
$pathparts = explode("/", realpath(__FILE__)); // Get path to this file.
$ModuleDirName = $pathparts[array_search('modules', $pathparts)+1]; // Extract module name from path.
$VarPrefix = '_MI_'.strtoupper($ModuleDirName); // Prepare a prefix for the language constants.
// ***********
// More code goes here, detailed further down this text.
// ***********
//
// For each block:
$modversion['blocks'][1]['file'] = $ModuleDirName.'_block.php';
$modversion['blocks'][1]['name'] = constant($VarPrefix.'_BLOCK');
$modversion['blocks'][1]['description'] = 'Shows a block';
$modversion['blocks'][1]['show_func'] = 'b_'.$ModuleDirName.'_block1'; // Same as in the block
$modversion['blocks'][1]['edit_func'] = 'b_'.$ModuleDirName.'_block1_edit'; // Same as in the block
$modversion['blocks'][1]['options'] = 'sofar|so|good';
$modversion['blocks'][1]['template'] = $ModuleDirName.'_test_block.html';
The way to actualy create dynamical function names are unfortuately rather ugly, but this is the only way I've found to make it work:
This goes into a file in your blocks dir, in this case: '/blocks/'.$ModuleDirName.'_test_block.html':
// At the top of the file:
$pathparts = explode("/", realpath(__FILE__));
$ModuleDirName = $pathparts[array_search('modules', $pathparts)+1];
include_once XOOPS_ROOT_PATH . '/modules/'.$ModuleDirName.'/include/groupaccess.php';
// Code for show_func:
$bname1 = 'b_'.$ModuleDirName.'_block1'; // The name of the function. - Same as in the xoops_version.php
$bfunc1 = sprintf('
function %s($options) {
// Here goes your blocks code.
}
', $bname1
);
eval($bfunc1);
// Code for edit_func:
$bname2 = 'b_'.$ModuleDirName.'_block1_edit'; // The name of the function. - Same as in the xoops_version.php
$bfunc2 = sprintf('
function %s($options) {
// Here goes your blocks edit code.
}
', $bname2
);
eval($bfunc2);
I'm fairly sure the above would work with classes, too, but I still haven't been looking into actualy creating classes, so those of you who has classes in your modules, please try it out, and post the results. Thanks.
Well.. Sofar, so good. This actualy works, but it does not actualy make the module cloneable, as there also are some problems with names of templates and block files, as they are expected to be unique to each module, so I had to make a fix for that, too.
My solusion, is to simply rename the files that needs to be renamed. So every time the xoops_version.php file is used, a check will be made to see if the directry name has changed since last time it was checked. To remember the name, I've created a file called the name of the directory the module is resident in, and ending with the extension
.cfg (I know, not a good name, but it had to have a name).
Thus every time xoops_version.php is inwoked, it will check if the file with the current $ModuleDirName exixts. If not, it will delete all the .cfg files in the current dir name, then rename all files in a list of dirs after a special pattern, and finaly create a .cfg file with the current $ModuleDirName.
The script expects the files to be renamed to use underscores to separate the name parts, and that the first part of the name is the name of the moduledir. eg.
mymodule_sub_display_vars.php or
mymodule_display.html. The first part will be automatically changed to the name of the current moduledir.
Notice the line below, starting with $updatedirs. This line contains relative paths to dirs which should have it's files scanned and renamed - if they contain an underscore.
There might be a more clever solusion, but this is working
The following code should be inserted at the point indicated in the first code-block above.
$ModuleRootPath = XOOPS_ROOT_PATH.'/modules/'.$ModuleDirName;
if (! file_exists($ModuleRootPath.'/'.$ModuleDirName.'.cfg')) { // Only execute if module has been moved.
$dir = opendir($ModuleRootPath); // Delete old .cfg file - if any exists.
while (false !== ($name = readdir($dir))) {
if (is_file($ModuleRootPath."/".$name)) { // Looking for files...
if (eregi('.cfg$', $name)) { // ending with .cfg
unlink($ModuleRootPath."/".$name); // ..to be deleted!
}
}
}
closedir($dir);
$updatedirs = array("blocks", "templates", "templates/admin", "templates/blocks");
reset ($updatedirs);
foreach ($updatedirs as $subdir) {
$currentdir = $ModuleRootPath.'/'.$subdir;
$dir = opendir($currentdir);
while (false !== ($name = readdir($dir))) {
if (is_file($currentdir."/".$name)) { // Looking for files...
$nameparts = explode("_", $name);
if (count($nameparts)>1) { // Filename must contain an underscore
$nameparts[0] = $ModuleDirName;
$newname = implode("_", $nameparts);
rename ($currentdir.'/'.$name, $currentdir.'/'.$newname);
}
}
}
closedir($dir);
}
$fd =fopen($ModuleRootPath.'/'.$ModuleDirName.'.cfg', "w"); // Make new .cfg file.
fwrite($fd, $ModuleDirName);
fclose($fd);
}
The template descriptor in the xoops_version.php file, then becomes something like this:
$modversion['templates'][1]['file'] = $ModuleDirName.'_main.html';
$modversion['templates'][1]['description'] = 'The main module form';
$modversion['templates'][6]['file'] = 'admin/'.$ModuleDirName.'_admin_testmenu.html';
$modversion['templates'][6]['description'] = 'Test of smarty in admin..';
Easy, isn't it?
Now I'm just looking forward to hear your suggestions on how to improve the above.
Best regards,
Daigoro