diff --git a/dev/translation/sanity_check_en_langfiles.php b/dev/translation/sanity_check_en_langfiles.php
index bb3430eb22c..9136c192739 100755
--- a/dev/translation/sanity_check_en_langfiles.php
+++ b/dev/translation/sanity_check_en_langfiles.php
@@ -310,6 +310,8 @@ if ((! empty($_REQUEST['unused']) && $_REQUEST['unused'] == 'true') || (isset($a
if (preg_match('/^.*Bytes$/', $value)) $qualifiedforclean=0;
if (preg_match('/^NoteSomeFeaturesAreDisabled/', $value)) $qualifiedforclean=0;
if (preg_match('/^(DoTest|Under|Limits|Cards|CurrentValue|DateLimit|DateAndHour|NbOfLines|NbOfObjects|NbOfReferes|TotalTTCShort|VATs)/', $value)) $qualifiedforclean=0;
+ // modulebuilder
+ if (preg_match('/^ModuleBuilderDesc/', $value)) $qualifiedforclean=0;
// orders
if (preg_match('/^OrderSource/', $value)) $qualifiedforclean=0;
if (preg_match('/^TypeContact_/', $value)) $qualifiedforclean=0;
diff --git a/htdocs/admin/triggers.php b/htdocs/admin/triggers.php
index 0aae9c6915e..0dddfb3c4af 100644
--- a/htdocs/admin/triggers.php
+++ b/htdocs/admin/triggers.php
@@ -47,7 +47,6 @@ print load_fiche_titre($langs->trans("TriggersAvailable"),'','title_setup');
print $langs->trans("TriggersDesc")."
";
print "
\n";
-$template_dir = DOL_DOCUMENT_ROOT.'/core/tpl/';
$interfaces = new Interfaces($db);
$triggers = $interfaces->getTriggersList();
diff --git a/htdocs/core/class/interfaces.class.php b/htdocs/core/class/interfaces.class.php
index 87ae81db856..cd4a56f4174 100644
--- a/htdocs/core/class/interfaces.class.php
+++ b/htdocs/core/class/interfaces.class.php
@@ -226,9 +226,10 @@ class Interfaces
* Return list of triggers. Function used by admin page htdoc/admin/triggers.
* List is sorted by trigger filename so by priority to run.
*
- * @return array Array list of triggers
+ * @param array $forcedirtriggers null=All default directories. This parameter is used by modulebuilder module only.
+ * @return array Array list of triggers
*/
- function getTriggersList()
+ function getTriggersList($forcedirtriggers=null)
{
global $conf, $langs;
@@ -241,11 +242,15 @@ class Interfaces
$i = 0;
$dirtriggers=array_merge(array('/core/triggers/'),$conf->modules_parts['triggers']);
+ if (is_array($forcedirtriggers))
+ {
+ $dirtriggers=$forcedirtriggers;
+ }
+
foreach($dirtriggers as $reldir)
{
$dir=dol_buildpath($reldir,0);
$newdir=dol_osencode($dir);
- //print "xx".$dir;exit;
// Check if directory exists (we do not use dol_is_dir to avoid loading files.lib.php at each call)
if (! is_dir($newdir)) continue;
diff --git a/htdocs/core/lib/files.lib.php b/htdocs/core/lib/files.lib.php
index 2d5b8d2f6db..ad800708522 100644
--- a/htdocs/core/lib/files.lib.php
+++ b/htdocs/core/lib/files.lib.php
@@ -448,14 +448,15 @@ function dol_filemtime($pathoffile)
* @param array $arrayreplacement Array with strings to replace
* @param string $destfile Destination file (can't be a directory). If empty, will be same than source file.
* @param int $newmask Mask for new file (0 by default means $conf->global->MAIN_UMASK). Example: '0666'
+ * @param int $indexdatabase Index new file into database.
* @return int <0 if error, 0 if nothing done (dest file already exists), >0 if OK
* @see dolCopyr
*/
-function dolReplaceInFile($srcfile, $arrayreplacement, $destfile='', $newmask=0)
+function dolReplaceInFile($srcfile, $arrayreplacement, $destfile='', $newmask=0, $indexdatabase=0)
{
global $conf;
- dol_syslog("files.lib.php::dolReplaceInFile srcfile=".$srcfile." destfile=".$destfile." newmask=".$newmask);
+ dol_syslog("files.lib.php::dolReplaceInFile srcfile=".$srcfile." destfile=".$destfile." newmask=".$newmask." indexdatabase=".$indexdatabase);
if (empty($srcfile)) return -1;
if (empty($destfile)) $destfile=$srcfile;
@@ -484,12 +485,15 @@ function dolReplaceInFile($srcfile, $arrayreplacement, $destfile='', $newmask=0)
dol_delete_file($tmpdestfile);
// Create $newpathoftmpdestfile from $newpathofsrcfile
+ $content=file_get_contents($newpathofsrcfile, 'r');
+ $content = make_substitutions($content, $arrayreplacement, null);
-
+ file_put_contents($newpathoftmpdestfile, $content);
+ @chmod($newpathoftmpdestfile, octdec($newmask));
// Rename
- $result=dol_move($newpathoftmpdestfile, $newpathofdestfile, $newmask, (($destfile == $srcfile)?1:0));
+ $result=dol_move($newpathoftmpdestfile, $newpathofdestfile, $newmask, (($destfile == $srcfile)?1:0), 0, $indexdatabase);
if (! $result)
{
dol_syslog("files.lib.php::dolReplaceInFile failed to move tmp file to final dest", LOG_WARNING);
@@ -569,10 +573,11 @@ function dol_copy($srcfile, $destfile, $newmask=0, $overwriteifexists=1)
* @param string $destfile Destination file (a directory)
* @param int $newmask Mask for new file (0 by default means $conf->global->MAIN_UMASK). Example: '0666'
* @param int $overwriteifexists Overwrite file if exists (1 by default)
- * @return int <0 if error, 0 if nothing done (dest dir already exists and overwriteifexists=0), >0 if OK
+ * @param array $arrayreplacement Array to use to replace filenames with another one during the copy (works only on file names, not on directory names).
+ * @return int <0 if error, 0 if nothing done (all files already exists and overwriteifexists=0), >0 if OK
* @see dol_copy
*/
-function dolCopyDir($srcfile, $destfile, $newmask, $overwriteifexists)
+function dolCopyDir($srcfile, $destfile, $newmask, $overwriteifexists, $arrayreplacement=null)
{
global $conf;
@@ -583,7 +588,7 @@ function dolCopyDir($srcfile, $destfile, $newmask, $overwriteifexists)
if (empty($srcfile) || empty($destfile)) return -1;
$destexists=dol_is_dir($destfile);
- if (! $overwriteifexists && $destexists) return 0;
+ //if (! $overwriteifexists && $destexists) return 0; // The overwriteifexists is for files only, so propaated to dol_copy only.
if (! $destexists)
{
@@ -592,37 +597,37 @@ function dolCopyDir($srcfile, $destfile, $newmask, $overwriteifexists)
$dirmaskdec=octdec($newmask);
if (empty($newmask) && ! empty($conf->global->MAIN_UMASK)) $dirmaskdec=octdec($conf->global->MAIN_UMASK);
$dirmaskdec |= octdec('0200'); // Set w bit required to be able to create content for recursive subdirs files
- dol_mkdir($destfile."/".$file, '', decoct($dirmaskdec));
+ dol_mkdir($destfile, '', decoct($dirmaskdec));
}
- $srcfile=dol_osencode($srcfile);
- $destfile=dol_osencode($destfile);
+ $ossrcfile=dol_osencode($srcfile);
+ $osdestfile=dol_osencode($destfile);
- // recursive function to copy
- // all subdirectories and contents:
- if (is_dir($srcfile))
+ // Recursive function to copy all subdirectories and contents:
+ if (is_dir($ossrcfile))
{
- $dir_handle=opendir($srcfile);
+ $dir_handle=opendir($ossrcfile);
while ($file=readdir($dir_handle))
{
if ($file!="." && $file!="..")
{
- if (is_dir($srcfile."/".$file))
+ if (is_dir($ossrcfile."/".$file))
{
- if (!is_dir($destfile."/".$file))
- {
- // We must set mask just before creating dir, becaause it can be set differently by dol_copy
- umask(0);
- $dirmaskdec=octdec($newmask);
- if (empty($newmask) && ! empty($conf->global->MAIN_UMASK)) $dirmaskdec=octdec($conf->global->MAIN_UMASK);
- $dirmaskdec |= octdec('0200'); // Set w bit required to be able to create content for recursive subdirs files
- dol_mkdir($destfile."/".$file, '', decoct($dirmaskdec));
- }
- $tmpresult=dolCopyDir($srcfile."/".$file, $destfile."/".$file, $newmask, $overwriteifexists);
+ //var_dump("xxx dolCopyDir $srcfile/$file, $destfile/$file, $newmask, $overwriteifexists");
+ $tmpresult=dolCopyDir($srcfile."/".$file, $destfile."/".$file, $newmask, $overwriteifexists, $arrayreplacement);
}
else
{
- $tmpresult=dol_copy($srcfile."/".$file, $destfile."/".$file, $newmask, $overwriteifexists);
+ $newfile = $file;
+ // Replace destination filename with a new one
+ if (is_array($arrayreplacement))
+ {
+ foreach($arrayreplacement as $key => $val)
+ {
+ $newfile = str_replace($key, $val, $newfile);
+ }
+ }
+ $tmpresult=dol_copy($srcfile."/".$file, $destfile."/".$newfile, $newmask, $overwriteifexists);
}
// Set result
if ($result > 0 && $tmpresult >= 0)
@@ -641,7 +646,8 @@ function dolCopyDir($srcfile, $destfile, $newmask, $overwriteifexists)
}
else
{
- $result=dol_copy($srcfile, $destfile, $newmask, $overwriteifexists);
+ // Source directory does not exists
+ $result = -2;
}
return $result;
@@ -660,10 +666,11 @@ function dolCopyDir($srcfile, $destfile, $newmask, $overwriteifexists)
* @param integer $newmask Mask in octal string for new file (0 by default means $conf->global->MAIN_UMASK)
* @param int $overwriteifexists Overwrite file if exists (1 by default)
* @param int $testvirus Do an antivirus test. Move is canceled if a virus is found.
+ * @param int $indexdatabase Index new file into database.
* @return boolean True if OK, false if KO
* @see dol_move_uploaded_file
*/
-function dol_move($srcfile, $destfile, $newmask=0, $overwriteifexists=1, $testvirus=0)
+function dol_move($srcfile, $destfile, $newmask=0, $overwriteifexists=1, $testvirus=0, $indexdatabase=1)
{
global $user, $db, $conf;
$result=false;
@@ -709,7 +716,7 @@ function dol_move($srcfile, $destfile, $newmask=0, $overwriteifexists=1, $testvi
}
// Move ok
- if ($result)
+ if ($result && $indexdatabase)
{
// Rename entry into ecm database
$rel_filetorenamebefore = preg_replace('/^'.preg_quote(DOL_DATA_ROOT,'/').'/', '', $srcfile);
diff --git a/htdocs/langs/en_US/modulebuilder.lang b/htdocs/langs/en_US/modulebuilder.lang
index de0c2fc216a..7336a020fa6 100644
--- a/htdocs/langs/en_US/modulebuilder.lang
+++ b/htdocs/langs/en_US/modulebuilder.lang
@@ -6,4 +6,12 @@ ModuleBuilderDesc3=Generated/editable modules found: %s (they a
NewModule=New module
ModuleKey=Key for new module
ModuleInitialized=Module initialized
-
+ModuleBuilderDescdescription=Enter here all general information that describe your module
+ModuleBuilderDescobjects=Define here the new objects you want to manage with our module. A page to list them and a page to create/edit/view a card will be generated.
+ModuleBuilderDescmenus=This tab is dedicated to define menu entries provided by your module.
+ModuleBuilderDescpermissions=This tab is dedicated to define the new permissions you want to provide with our module.
+ModuleBuilderDesctriggers=This is the view of triggers provided by your module. To include code executed when a triggered business event is launched, just edit this file with your IDE.
+ModuleBuilderDescbuildpackage=You can generate here a "ready to distribute" package file (a normalized .zip file) of your module. Just click on button to get your module package file.
+BuildPackage=Build package
+ModuleIsNotActive=This module was not activated yet (go into Home-Setup-Module to make it live)
+ModuleIsLive=This module has been activated. Any change on it may break a current active feature.
\ No newline at end of file
diff --git a/htdocs/modulebuilder/index.php b/htdocs/modulebuilder/index.php
index a033bd1be23..e11ff31a303 100644
--- a/htdocs/modulebuilder/index.php
+++ b/htdocs/modulebuilder/index.php
@@ -29,9 +29,10 @@ $langs->load("admin");
$langs->load("modulebuilder");
$langs->load("other");
-$action=GETPOST('action','alpha');
+$action=GETPOST('action','aZ09');
$confirm=GETPOST('confirm','alpha');
-$module=GETPOST('module');
+$module=GETPOST('module','alpha');
+$tab=GETPOST('tab','aZ09');
if (empty($module)) $module='initmodule';
if (empty($tab)) $tab='description';
@@ -56,30 +57,36 @@ $FILEFLAG='modulebuilder.txt';
if ($dircustom && $action == 'initmodule' && $modulename)
{
$srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template';
- $destdir = $dircustom.'/'.$modulename;
+ $destdir = $dircustom.'/'.strtolower($modulename);
$arrayreplacement=array(
'mymodule'=>strtolower($modulename),
'MyModule'=>$modulename
);
- $result = dolCopyDir($srcdir, $destdir, 0, 0);
+ $result = dolCopyDir($srcdir, $destdir, 0, 0, $arrayreplacement);
//dol_mkdir($destfile);
if ($result <= 0)
{
- $error++;
- $langs->load("errors");
- setEventMessages($langs->trans("ErrorFailToCopyDir", $srcdir, $destdir), null, 'errors');
+ if ($result < 0)
+ {
+ $error++;
+ $langs->load("errors");
+ setEventMessages($langs->trans("ErrorFailToCopyDir", $srcdir, $destdir), null, 'errors');
+ }
+ else // $result == 0
+ {
+ setEventMessages($langs->trans("AllFilesDidAlreadyExist", $srcdir, $destdir), null, 'warnings');
+ }
}
// Edit PHP files
if (! $error)
{
- $listofphpfilestoedit = dol_dir_list($destdir, 'files', 1, '\.php$', '', 'fullname', SORT_ASC, 0, 1);
+ $listofphpfilestoedit = dol_dir_list($destdir, 'files', 1, '\.(php|MD|js)$', '', 'fullname', SORT_ASC, 0, 1);
foreach($listofphpfilestoedit as $phpfileval)
{
- var_dump($phpfileval['fullname']);
-
+ //var_dump($phpfileval['fullname']);
$arrayreplacement=array(
'mymodule'=>strtolower($modulename),
'MyModule'=>$modulename,
@@ -106,6 +113,12 @@ if ($dircustom && $action == 'initmodule' && $modulename)
}
}
+if ($dircustom && $action == 'generatepackage')
+{
+ $dir = $dircustom.'/'.$modulename;
+
+
+}
/*
@@ -138,7 +151,16 @@ if (!empty($conf->modulebuilder->enabled) && $mainmenu == 'modulebuilder') // En
$fullname = $dircustomcursor['fullname'];
if (dol_is_file($fullname.'/'.$FILEFLAG))
{
- $listofmodules[$dircustomcursor['name']]=$fullname;
+ // Get real name of module (MyModule instead of mymodule)
+ $descriptorfiles = dol_dir_list($fullname.'/core/modules/', 'files', 0, 'mod.*\.class\.php');
+ $modulenamewithcase='';
+ foreach($descriptorfiles as $descriptorcursor)
+ {
+ $modulenamewithcase=preg_replace('/^mod/', '', $descriptorcursor['name']);
+ $modulenamewithcase=preg_replace('/\.class\.php$/', '', $modulenamewithcase);
+ }
+ if ($modulenamewithcase) $listofmodules[$dircustomcursor['name']]=$modulenamewithcase;
+ //var_dump($listofmodules);
}
}
}
@@ -154,11 +176,44 @@ if (!empty($conf->modulebuilder->enabled) && $mainmenu == 'modulebuilder') // En
print $langs->trans("ModuleBuilderDesc").'
';
print $langs->trans("ModuleBuilderDesc2", 'conf/conf.php', $dircustom).'
';
print $langs->trans("ModuleBuilderDesc3", count($listofmodules), $FILEFLAG).'
';
-print '
';
-
-
+//print '
';
+
+
+// Load module descriptor
+$error=0;
+$moduleobj = null;
+
+if (! empty($module) && $module != 'initmodule')
+{
+ $modulelowercase=strtolower($module);
+
+ // Load module
+ dol_include_once($modulelowercase.'/core/modules/mod'.$module.'.class.php');
+ $class='mod'.$module;
+
+ if (class_exists($class))
+ {
+ try {
+ $moduleobj = new $class($db);
+ }
+ catch(Exception $e)
+ {
+ $error++;
+ print $e->getMessage();
+ }
+ }
+ else
+ {
+ $error++;
+ $langs->load("errors");
+ print img_warning('').' '.$langs->trans("ErrorFailedToLoadModuleDescriptorForXXX", $module);
+ }
+}
+
print '
';
+
+// Tabs for all modules
$head = array();
$h=0;
@@ -167,11 +222,11 @@ $head[$h][1] = $langs->trans("NewModule");
$head[$h][2] = 'initmodule';
$h++;
-foreach($listofmodules as $tmpmodule => $fullname)
+foreach($listofmodules as $tmpmodule => $tmpmodulewithcase)
{
- $head[$h][0] = $_SERVER["PHP_SELF"].'?module='.$tmpmodule;
- $head[$h][1] = $tmpmodule;
- $head[$h][2] = $tmpmodule;
+ $head[$h][0] = $_SERVER["PHP_SELF"].'?module='.$tmpmodulewithcase;
+ $head[$h][1] = $tmpmodulewithcase;
+ $head[$h][2] = $tmpmodulewithcase;
$h++;
}
@@ -195,73 +250,197 @@ if ($module == 'initmodule')
}
elseif (! empty($module))
{
- $error=0;
-
- // Load module
- dol_include_once($module.'/core/modules/mod'.ucfirst($module).'.class.php');
- $class='mod'.ucfirst($module);
- if (class_exists($class))
- {
- try {
- $moduleobj = new $class($db);
- }
- catch(Exception $e)
- {
- $error++;
- print $e->getMessage();
- }
- }
- else
- {
- $error++;
- $langs->load("errors");
- print img_warning('').' '.$langs->trans("ErrorFailedToLoadModuleDescriptorForXXX", $module);
- }
-
- // Button to delete module
-
-
// Tabs for module
if (! $error)
{
$head2 = array();
$h=0;
-
- foreach($listofmodules as $tmpmodule => $fullname)
+
+ $modulestatusinfo=img_info('').' '.$langs->trans("ModuleIsNotActive");
+ if (! empty($conf->$module->enabled))
{
- $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=description';
+ $modulestatusinfo=img_warning().' '.$langs->trans("ModuleIsLive");
+ }
+
+ foreach($listofmodules as $tmpmodule => $tmpmodulewithcase)
+ {
+ $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=description&module='.$tmpmodulewithcase;
$head2[$h][1] = $langs->trans("Description");
$head2[$h][2] = 'description';
$h++;
- $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=objects';
+ $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=objects&module='.$tmpmodulewithcase;
$head2[$h][1] = $langs->trans("Objects");
$head2[$h][2] = 'objects';
$h++;
- $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab='.$tmpmodule;
+ $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=menus&module='.$tmpmodulewithcase;
$head2[$h][1] = $langs->trans("Menus");
$head2[$h][2] = 'menus';
$h++;
- $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab='.$tmpmodule;
+ $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=permissions&module='.$tmpmodulewithcase;
$head2[$h][1] = $langs->trans("Permissions");
$head2[$h][2] = 'permissions';
$h++;
- $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab='.$tmpmodule;
+ $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=triggers&module='.$tmpmodulewithcase;
$head2[$h][1] = $langs->trans("Triggers");
$head2[$h][2] = 'triggers';
$h++;
+
+ $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=buildpackage&module='.$tmpmodulewithcase;
+ $head2[$h][1] = $langs->trans("BuildPackage");
+ $head2[$h][2] = 'buildpackage';
+ $h++;
+ }
+
+ print $modulestatusinfo.'
';
+
+ dol_fiche_head($head2, $tab, '', -1, '');
+
+ print $langs->trans("ModuleBuilderDesc".$tab).'
';
+
+ if ($tab == 'description')
+ {
+ print '
| '; + print $langs->trans("Parameter"); + print ' | '; + print $langs->trans("Value"); + print ' |
| '; + print $langs->trans("Numero"); + print ' | '; + print $moduleobj->numero; + print ' |
| '; + print $langs->trans("Name"); + print ' | '; + print $moduleobj->getName(); + print ' |
| '; + print $langs->trans("Version"); + print ' | '; + print $moduleobj->getVersion(); + print ' |
| ';
+ print $langs->trans("Family");
+ print " 'crm','financial','hr','projects','products','ecm','technic','interface','other'"; + print ' | '; + print $moduleobj->family; + print ' |
| '; + print $langs->trans("EditorName"); + print ' | '; + print $moduleobj->editor_name; + print ' |
| '; + print $langs->trans("EditorUrl"); + print ' | '; + print $moduleobj->editor_url; + print ' |
| '; + print $langs->trans("Description"); + print ' | '; + print $moduleobj->getDesc(); + print ' |
| '; + print $langs->trans("LongDescription"); + print ' | '; + print $moduleobj->getDescLong(); + print ' |
| '.$langs->trans("File").' | +'.$langs->trans("Active").' | ++ | |
| '.$trigger['picto'].' | '; + print ''.$trigger['file'].' | '; + print ''.$trigger['status'].' | '; + print '';
+ $text=$trigger['info'];
+ $text.=" \n".$langs->trans("File").": \n".$trigger['relpath']; + //$text.="\n".$langs->trans("ExternalModule",$trigger['isocreorexternal']); + print $form->textwithpicto('', $text); + print ' | ';
+ print '