From 816db0e8565c4f2c6899110cae7655adace8a136 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 16 Jul 2017 13:25:10 +0200 Subject: [PATCH 1/9] Add protection against duplicate moduel with similar names --- htdocs/langs/en_US/modulebuilder.lang | 3 ++- htdocs/modulebuilder/index.php | 22 ++++++++++++++++++++-- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/htdocs/langs/en_US/modulebuilder.lang b/htdocs/langs/en_US/modulebuilder.lang index 91035a6ab97..2c3744b1b93 100644 --- a/htdocs/langs/en_US/modulebuilder.lang +++ b/htdocs/langs/en_US/modulebuilder.lang @@ -51,4 +51,5 @@ WidgetFile=Widget file ReadmeFile=Readme file ChangeLog=ChangeLog file SqlFile=Sql file -SqlFileKey=Sql file for keys \ No newline at end of file +SqlFileKey=Sql file for keys +AnObjectAlreadyExistWithThisNameAndDiffCase=An object already exists with this name and a different case \ No newline at end of file diff --git a/htdocs/modulebuilder/index.php b/htdocs/modulebuilder/index.php index 528f22fe67a..eb3591fefa9 100644 --- a/htdocs/modulebuilder/index.php +++ b/htdocs/modulebuilder/index.php @@ -160,11 +160,29 @@ if ($dirins && $action == 'initobject' && $module && $objectname) setEventMessages($langs->trans("SpaceOrSpecialCharAreNotAllowed"), null, 'errors'); } + $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template'; + $destdir = $dirins.'/'.strtolower($module); + + // Scan dir class to find if an object with same name already exists. if (! $error) { - $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template'; - $destdir = $dirins.'/'.strtolower($module); + $dirlist=dol_dir_list($destdir.'/class','files',0,'\.txt$'); + $alreadyfound=false; + foreach($dirlist as $key => $val) + { + $filefound=preg_replace('/\.txt$/','',$val['name']); + if (strtolower($objectname) == strtolower($filefound) && $objectname != $filefound) + { + $alreadyfound=true; + $error++; + setEventMessages($langs->trans("AnObjectAlreadyExistWithThisNameAndDiffCase"), null, 'errors'); + break; + } + } + } + if (! $error) + { // Delete some files $filetogenerate = array( 'myobject_card.php'=>strtolower($objectname).'_card.php', From 4d9ae5bb44bd967024c70b2dfa875ddeb7fc8fc9 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Sun, 16 Jul 2017 14:57:30 +0200 Subject: [PATCH 2/9] Work on modulebuilder --- htdocs/core/lib/admin.lib.php | 3 +- htdocs/langs/en_US/modulebuilder.lang | 4 +- htdocs/modulebuilder/index.php | 65 ++++- .../core/modules/modMyModule.class.php | 112 +++++---- .../modulebuilder/template/mymoduleindex.php | 237 ++++++++++++++++++ 5 files changed, 369 insertions(+), 52 deletions(-) create mode 100644 htdocs/modulebuilder/template/mymoduleindex.php diff --git a/htdocs/core/lib/admin.lib.php b/htdocs/core/lib/admin.lib.php index e90f006ac7e..04393fa4d29 100644 --- a/htdocs/core/lib/admin.lib.php +++ b/htdocs/core/lib/admin.lib.php @@ -931,7 +931,8 @@ function unActivateModule($value, $requiredby=1) { //print $dir.$modFile; // TODO Replace this after DolibarrModules is moved as abstract class with a try catch to show module we try to disable has not been found or could not be loaded - $genericMod = new DolibarrModules($db); + include_once DOL_DOCUMENT_ROOT.'/core/modules/DolibarrModules.class.php'; + $genericMod = new DolibarrModules($db); $genericMod->name=preg_replace('/^mod/i','',$modName); $genericMod->rights_class=strtolower(preg_replace('/^mod/i','',$modName)); $genericMod->const_name='MAIN_MODULE_'.strtoupper(preg_replace('/^mod/i','',$modName)); diff --git a/htdocs/langs/en_US/modulebuilder.lang b/htdocs/langs/en_US/modulebuilder.lang index 2c3744b1b93..bbaf00dcaf4 100644 --- a/htdocs/langs/en_US/modulebuilder.lang +++ b/htdocs/langs/en_US/modulebuilder.lang @@ -12,7 +12,7 @@ ModuleInitialized=Module initialized FilesForObjectInitialized=Files for new object '%s' initialized FilesForObjectUpdated=Files for object '%s' updated (.sql files and .class.php file) ModuleBuilderDescdescription=Enter here all general information that describe your module -ModuleBuilderDescspecifications=You can enter here a long text to describe the specifications of your module that is not already structured into other tabs. So you have on hand the rules to develop. Also this text content will be included into the generated documentation (see last tab). +ModuleBuilderDescspecifications=You can enter here a long text to describe the specifications of your module that is not already structured into other tabs. So you have within easy reach all the rules to develop. Also this text content will be included into the generated documentation (see last tab). ModuleBuilderDescobjects=Define here the objects you want to manage with your module. A sql file, a page to list them, to create/edit/view a card and an API 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 your module. @@ -25,7 +25,7 @@ EnterNameOfObjectToDeleteDesc=You can delete an object. WARNING: All files relat DangerZone=Danger zone BuildPackage=Build package/documentation BuildDocumentation=Build documentation -ModuleIsNotActive=This module was not activated yet (go into %s to make it live) +ModuleIsNotActive=This module was not activated yet. Ggo into %s to make it live or click here: ModuleIsLive=This module has been activated. Any change on it may break a current active feature. DescriptionLong=Long description EditorName=Name of editor diff --git a/htdocs/modulebuilder/index.php b/htdocs/modulebuilder/index.php index eb3591fefa9..67581d921c5 100644 --- a/htdocs/modulebuilder/index.php +++ b/htdocs/modulebuilder/index.php @@ -24,6 +24,7 @@ if (! defined('NOSCANPOSTFORINJECTION')) define('NOSCANPOSTFORINJECTION','1'); require '../main.inc.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/modulebuilder.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php'; @@ -389,8 +390,6 @@ if ($dirins && $action == 'confirm_deleteproperty' && $propertykey) } } - - if ($dirins && $action == 'generatepackage') { $modulelowercase=strtolower($module); @@ -449,7 +448,6 @@ if ($dirins && $action == 'generatepackage') } } - // Save file if ($action == 'savefile' && empty($cancel)) { @@ -479,6 +477,47 @@ if ($action == 'savefile' && empty($cancel)) } } +// Enable module +if ($action == 'set' && $user->admin) +{ + $param='module='.$module; + $value = GETPOST('value','alpha'); + $resarray = activateModule($value); + if (! empty($resarray['errors'])) setEventMessages('', $resarray['errors'], 'errors'); + else + { + //var_dump($resarray);exit; + if ($resarray['nbperms'] > 0) + { + $tmpsql="SELECT COUNT(rowid) as nb FROM ".MAIN_DB_PREFIX."user WHERE admin <> 1"; + $resqltmp=$db->query($tmpsql); + if ($resqltmp) + { + $obj=$db->fetch_object($resqltmp); + //var_dump($obj->nb);exit; + if ($obj && $obj->nb > 1) + { + $msg = $langs->trans('ModuleEnabledAdminMustCheckRights'); + setEventMessages($msg, null, 'warnings'); + } + } + else dol_print_error($db); + } + } + header("Location: ".$_SERVER["PHP_SELF"]."?".$param); + exit; +} + +// Disable module +if ($action == 'reset' && $user->admin) +{ + $param='module='.$module; + $value = GETPOST('value','alpha'); + $result=unActivateModule($value); + if ($result) setEventMessages($result, null, 'errors'); + header("Location: ".$_SERVER["PHP_SELF"]."?".$param); + exit; +} /* @@ -674,8 +713,24 @@ elseif (! empty($module)) $h=0; $modulelowercase=strtolower($module); + $const_name = 'MAIN_MODULE_'.strtoupper($module); + $param='&tab='.$tab.'&module='.$module; $urltomodulesetup=''.$langs->trans('Home').'-'.$langs->trans("Setup").'-'.$langs->trans("Modules").''; + $linktoenabledisable=''; + if (! empty($conf->global->$const_name)) // If module is already activated + { + $linktoenabledisable.=''; + $linktoenabledisable.=img_picto($langs->trans("Activated"),'switch_on'); + $linktoenabledisable.=''; + } + else + { + $linktoenabledisable.=''; + $linktoenabledisable.=img_picto($langs->trans("Disabled"),'switch_off'); + $linktoenabledisable.="\n"; + } + $modulestatusinfo=img_info('').' '.$langs->trans("ModuleIsNotActive", $urltomodulesetup); if (! empty($conf->$module->enabled)) { @@ -727,7 +782,9 @@ elseif (! empty($module)) $head2[$h][2] = 'buildpackage'; $h++; - print $modulestatusinfo.'

'; + print $modulestatusinfo; + print ' '.$linktoenabledisable; + print '

'; dol_fiche_head($head2, $tab, '', -1, ''); diff --git a/htdocs/modulebuilder/template/core/modules/modMyModule.class.php b/htdocs/modulebuilder/template/core/modules/modMyModule.class.php index d91b4c6a495..8c7da67b7ab 100644 --- a/htdocs/modulebuilder/template/core/modules/modMyModule.class.php +++ b/htdocs/modulebuilder/template/core/modules/modMyModule.class.php @@ -87,7 +87,7 @@ class modMyModule extends DolibarrModules $this->module_parts = array( 'triggers' => 1, // Set this to 1 if module has its own trigger directory (core/triggers) 'login' => 0, // Set this to 1 if module has its own login method directory (core/login) - 'substitutions' => 0, // Set this to 1 if module has its own substitution function file (core/substitutions) + 'substitutions' => 1, // Set this to 1 if module has its own substitution function file (core/substitutions) 'menus' => 0, // Set this to 1 if module has its own menus handler directory (core/menus) 'theme' => 0, // Set this to 1 if module has its own theme directory (theme) 'tpl' => 0, // Set this to 1 if module overwrite template dir (core/tpl) @@ -110,8 +110,8 @@ class modMyModule extends DolibarrModules $this->depends = array(); // List of module class names as string that must be enabled if this module is enabled $this->requiredby = array(); // List of module ids to disable if this one is disabled $this->conflictwith = array(); // List of module class names as string this module is in conflict with - $this->phpmin = array(5,0); // Minimum version of PHP required by module - $this->need_dolibarr_version = array(3,0); // Minimum version of Dolibarr required by module + $this->phpmin = array(5,3); // Minimum version of PHP required by module + $this->need_dolibarr_version = array(4,0); // Minimum version of Dolibarr required by module $this->langfiles = array("mymodule@mymodule"); $this->warnings_activation = array(); // Warning to show when we activate module. array('always'='text') or array('FR'='textfr','ES'='textes'...) $this->warnings_activation_ext = array(); // Warning to show when we activate an external module. array('always'='text') or array('FR'='textfr','ES'='textes'...) @@ -121,7 +121,9 @@ class modMyModule extends DolibarrModules // Example: $this->const=array(0=>array('MYMODULE_MYNEWCONST1','chaine','myvalue','This is a constant to add',1), // 1=>array('MYMODULE_MYNEWCONST2','chaine','myvalue','This is another constant to add',0, 'current', 1) // ); - $this->const = array(); + $this->const = array( + 1=>array('MYMODULE_MYCONSTANT', 'chaine', 'avalue', 'This is a constant to add', 1, 'allentities', 1) + ); // Array to add new pages in new tabs // Example: $this->tabs = array('objecttype:+tabname1:Title1:mylangfile@mymodule:$user->rights->mymodule->read:/mymodule/mynewtab1.php?id=__ID__', // To add a new tab identified by code tabname1 @@ -183,7 +185,9 @@ class modMyModule extends DolibarrModules // Cronjobs - $this->cronjobs = array(); // List of cron jobs entries to add + $this->cronjobs = array( + 0=>array('label'=>'MyJob label', 'jobtype'=>'method', 'class'=>'/mymodule/class/mymodulemyjob.class.php', 'objectname'=>'MyModuleMyJob', 'method'=>'myMethod', 'parameters'=>'', 'comment'=>'Comment', 'frequency'=>2, 'unitfrequency'=>3600, 'test'=>true) + ); // List of cron jobs entries to add // Example: $this->cronjobs=array(0=>array('label'=>'My label', 'jobtype'=>'method', 'class'=>'/dir/class/file.class.php', 'objectname'=>'MyClass', 'method'=>'myMethod', 'parameters'=>'', 'comment'=>'Comment', 'frequency'=>2, 'unitfrequency'=>3600, 'test'=>true), // 1=>array('label'=>'My label', 'jobtype'=>'command', 'command'=>'', 'parameters'=>'', 'comment'=>'Comment', 'frequency'=>1, 'unitfrequency'=>3600*24, 'test'=>true) // ); @@ -219,57 +223,75 @@ class modMyModule extends DolibarrModules $r=0; // Add here entries to declare new menus - // + // Example to declare a new Top Menu entry and its Left menu entry: - // $this->menu[$r]=array( 'fk_menu'=>'', // '' if this is a top menu. For left menu, use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode - // 'type'=>'top', // This is a Top menu entry - // 'titre'=>'MyModule top menu', - // 'mainmenu'=>'mymodule', - // 'leftmenu'=>'mymodule', - // 'url'=>'/mymodule/pagetop.php', - // 'langs'=>'mylangfile@mymodule', // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. - // 'position'=>100, - // 'enabled'=>'$conf->mymodule->enabled', // Define condition to show or hide menu entry. Use '$conf->mymodule->enabled' if entry must be visible if module is enabled. - // 'perms'=>'1', // Use 'perms'=>'$user->rights->mymodule->level1->level2' if you want your menu with a permission rules - // 'target'=>'', - // 'user'=>2); // 0=Menu for internal users, 1=external users, 2=both + /* BEGIN MODULEBUILDER TOPMENU */ + $this->menu[$r]=array( 'fk_menu'=>'', // '' if this is a top menu. For left menu, use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode + 'type'=>'top', // This is a Top menu entry + 'titre'=>'MyModule', + 'mainmenu'=>'mymodule', + 'leftmenu'=>'', + 'url'=>'/mymodule/mymoduleindex.php', + 'langs'=>'mymodule@mymodule', // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. + 'position'=>1000, + 'enabled'=>'$conf->mymodule->enabled', // Define condition to show or hide menu entry. Use '$conf->mymodule->enabled' if entry must be visible if module is enabled. + 'perms'=>'1', // Use 'perms'=>'$user->rights->mymodule->level1->level2' if you want your menu with a permission rules + 'target'=>'', + 'user'=>2); // 0=Menu for internal users, 1=external users, 2=both // $r++; - // + /* END MODULEBUILDER TOPMENU */ + // Example to declare a Left Menu entry into an existing Top menu entry: - // $this->menu[$r]=array( 'fk_menu'=>'fk_mainmenu=xxx', // '' if this is a top menu. For left menu, use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode - // 'type'=>'left', // This is a Left menu entry - // 'titre'=>'MyModule left menu', - // 'mainmenu'=>'xxx', - // 'leftmenu'=>'mymodule', - // 'url'=>'/mymodule/pagelevel2.php', - // 'langs'=>'mylangfile@mymodule', // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. - // 'position'=>100, - // 'enabled'=>'$conf->mymodule->enabled', // Define condition to show or hide menu entry. Use '$conf->mymodule->enabled' if entry must be visible if module is enabled. Use '$leftmenu==\'system\'' to show if leftmenu system is selected. - // 'perms'=>'1', // Use 'perms'=>'$user->rights->mymodule->level1->level2' if you want your menu with a permission rules - // 'target'=>'', - // 'user'=>2); // 0=Menu for internal users, 1=external users, 2=both - // $r++; + /* BEGIN MODULEBUILDER LEFTMENU MYOBJECT + $this->menu[$r]=array( 'fk_menu'=>'fk_mainmenu=mymodule', // '' if this is a top menu. For left menu, use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode + 'type'=>'left', // This is a Left menu entry + 'titre'=>'List MyObject', + 'mainmenu'=>'mymodule', + 'leftmenu'=>'mymodule', + 'url'=>'/mymodule/myobject_list.php', + 'langs'=>'mymodule@mymodule', // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. + 'position'=>1100, + 'enabled'=>'$conf->mymodule->enabled', // Define condition to show or hide menu entry. Use '$conf->mymodule->enabled' if entry must be visible if module is enabled. Use '$leftmenu==\'system\'' to show if leftmenu system is selected. + 'perms'=>'1', // Use 'perms'=>'$user->rights->mymodule->level1->level2' if you want your menu with a permission rules + 'target'=>'', + 'user'=>2); // 0=Menu for internal users, 1=external users, 2=both + $r++; + $this->menu[$r]=array( 'fk_menu'=>'fk_mainmenu=mymodule&fk_leftmenu=mymodule', // '' if this is a top menu. For left menu, use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode + 'type'=>'left', // This is a Left menu entry + 'titre'=>'New MyObject', + 'mainmenu'=>'mymodule', + 'leftmenu'=>'mymodule', + 'url'=>'/mymodule/myobject_page.php?action=create', + 'langs'=>'mymodule@mymodule', // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory. + 'position'=>1101, + 'enabled'=>'$conf->mymodule->enabled', // Define condition to show or hide menu entry. Use '$conf->mymodule->enabled' if entry must be visible if module is enabled. Use '$leftmenu==\'system\'' to show if leftmenu system is selected. + 'perms'=>'1', // Use 'perms'=>'$user->rights->mymodule->level1->level2' if you want your menu with a permission rules + 'target'=>'', + 'user'=>2); // 0=Menu for internal users, 1=external users, 2=both + $r++; + END MODULEBUILDER LEFTMENU MYOBJECT */ // Exports $r=1; // Example: - // $this->export_code[$r]=$this->rights_class.'_'.$r; - // $this->export_label[$r]='MyModule'; // Translation key (used only if key ExportDataset_xxx_z not found) - // $this->export_enabled[$r]='1'; // Condition to show export in list (ie: '$user->id==3'). Set to 1 to always show when module is enabled. - // $this->export_icon[$r]='generic:MyModule'; // Put here code of icon then string for translation key of module name - // $this->export_permission[$r]=array(array("mymodule","level1","level2")); - // $this->export_fields_array[$r]=array('s.rowid'=>"IdCompany",'s.nom'=>'CompanyName','s.address'=>'Address','s.zip'=>'Zip','s.town'=>'Town','s.fk_pays'=>'Country','s.phone'=>'Phone','s.siren'=>'ProfId1','s.siret'=>'ProfId2','s.ape'=>'ProfId3','s.idprof4'=>'ProfId4','s.code_compta'=>'CustomerAccountancyCode','s.code_compta_fournisseur'=>'SupplierAccountancyCode','f.rowid'=>"InvoiceId",'f.facnumber'=>"InvoiceRef",'f.datec'=>"InvoiceDateCreation",'f.datef'=>"DateInvoice",'f.total'=>"TotalHT",'f.total_ttc'=>"TotalTTC",'f.tva'=>"TotalVAT",'f.paye'=>"InvoicePaid",'f.fk_statut'=>'InvoiceStatus','f.note'=>"InvoiceNote",'fd.rowid'=>'LineId','fd.description'=>"LineDescription",'fd.price'=>"LineUnitPrice",'fd.tva_tx'=>"LineVATRate",'fd.qty'=>"LineQty",'fd.total_ht'=>"LineTotalHT",'fd.total_tva'=>"LineTotalTVA",'fd.total_ttc'=>"LineTotalTTC",'fd.date_start'=>"DateStart",'fd.date_end'=>"DateEnd",'fd.fk_product'=>'ProductId','p.ref'=>'ProductRef'); - // $this->export_TypeFields_array[$r]=array('t.date'=>'Date', 't.qte'=>'Numeric', 't.poids'=>'Numeric', 't.fad'=>'Numeric', 't.paq'=>'Numeric', 't.stockage'=>'Numeric', 't.fadparliv'=>'Numeric', 't.livau100'=>'Numeric', 't.forfait'=>'Numeric', 's.nom'=>'Text','s.address'=>'Text','s.zip'=>'Text','s.town'=>'Text','c.code'=>'Text','s.phone'=>'Text','s.siren'=>'Text','s.siret'=>'Text','s.ape'=>'Text','s.idprof4'=>'Text','s.code_compta'=>'Text','s.code_compta_fournisseur'=>'Text','s.tva_intra'=>'Text','f.facnumber'=>"Text",'f.datec'=>"Date",'f.datef'=>"Date",'f.date_lim_reglement'=>"Date",'f.total'=>"Numeric",'f.total_ttc'=>"Numeric",'f.tva'=>"Numeric",'f.paye'=>"Boolean",'f.fk_statut'=>'Status','f.note_private'=>"Text",'f.note_public'=>"Text",'fd.description'=>"Text",'fd.subprice'=>"Numeric",'fd.tva_tx'=>"Numeric",'fd.qty'=>"Numeric",'fd.total_ht'=>"Numeric",'fd.total_tva'=>"Numeric",'fd.total_ttc'=>"Numeric",'fd.date_start'=>"Date",'fd.date_end'=>"Date",'fd.special_code'=>'Numeric','fd.product_type'=>"Numeric",'fd.fk_product'=>'List:product:label','p.ref'=>'Text','p.label'=>'Text','p.accountancy_code_sell'=>'Text'); - // $this->export_entities_array[$r]=array('s.rowid'=>"company",'s.nom'=>'company','s.address'=>'company','s.zip'=>'company','s.town'=>'company','s.fk_pays'=>'company','s.phone'=>'company','s.siren'=>'company','s.siret'=>'company','s.ape'=>'company','s.idprof4'=>'company','s.code_compta'=>'company','s.code_compta_fournisseur'=>'company','f.rowid'=>"invoice",'f.facnumber'=>"invoice",'f.datec'=>"invoice",'f.datef'=>"invoice",'f.total'=>"invoice",'f.total_ttc'=>"invoice",'f.tva'=>"invoice",'f.paye'=>"invoice",'f.fk_statut'=>'invoice','f.note'=>"invoice",'fd.rowid'=>'invoice_line','fd.description'=>"invoice_line",'fd.price'=>"invoice_line",'fd.total_ht'=>"invoice_line",'fd.total_tva'=>"invoice_line",'fd.total_ttc'=>"invoice_line",'fd.tva_tx'=>"invoice_line",'fd.qty'=>"invoice_line",'fd.date_start'=>"invoice_line",'fd.date_end'=>"invoice_line",'fd.fk_product'=>'product','p.ref'=>'product'); - // $this->export_dependencies_array[$r]=array('invoice_line'=>'fd.rowid','product'=>'fd.rowid'); // To add unique key if we ask a field of a child to avoid the DISTINCT to discard them + /* BEGIN MODULEBUILDER EXPORT MYOBJECT + $this->export_code[$r]=$this->rights_class.'_'.$r; + $this->export_label[$r]='MyModule'; // Translation key (used only if key ExportDataset_xxx_z not found) + $this->export_enabled[$r]='1'; // Condition to show export in list (ie: '$user->id==3'). Set to 1 to always show when module is enabled. + $this->export_icon[$r]='generic:MyModule'; // Put here code of icon then string for translation key of module name + //$this->export_permission[$r]=array(array("mymodule","level1","level2")); + $this->export_fields_array[$r]=array('t.rowid'=>"Id",'t.ref'=>'Ref','t.label'=>'Label','t.datec'=>"DateCreation",'t.tms'=>"DateUpdate"); + $this->export_TypeFields_array[$r]=array('t.rowid'=>'Numeric', 't.ref'=>'Text', 't.label'=>'Label', 't.datec'=>"Date", 't.tms'=>"Date"); + // $this->export_entities_array[$r]=array('t.rowid'=>"company",'s.nom'=>'company','s.address'=>'company','s.zip'=>'company','s.town'=>'company','s.fk_pays'=>'company','s.phone'=>'company','s.siren'=>'company','s.siret'=>'company','s.ape'=>'company','s.idprof4'=>'company','s.code_compta'=>'company','s.code_compta_fournisseur'=>'company','f.rowid'=>"invoice",'f.facnumber'=>"invoice",'f.datec'=>"invoice",'f.datef'=>"invoice",'f.total'=>"invoice",'f.total_ttc'=>"invoice",'f.tva'=>"invoice",'f.paye'=>"invoice",'f.fk_statut'=>'invoice','f.note'=>"invoice",'fd.rowid'=>'invoice_line','fd.description'=>"invoice_line",'fd.price'=>"invoice_line",'fd.total_ht'=>"invoice_line",'fd.total_tva'=>"invoice_line",'fd.total_ttc'=>"invoice_line",'fd.tva_tx'=>"invoice_line",'fd.qty'=>"invoice_line",'fd.date_start'=>"invoice_line",'fd.date_end'=>"invoice_line",'fd.fk_product'=>'product','p.ref'=>'product'); + // $this->export_dependencies_array[$r]=array('invoice_line'=>'fd.rowid','product'=>'fd.rowid'); // To add unique key if we ask a field of a child to avoid the DISTINCT to discard them // $this->export_sql_start[$r]='SELECT DISTINCT '; - // $this->export_sql_end[$r] =' FROM ('.MAIN_DB_PREFIX.'facture as f, '.MAIN_DB_PREFIX.'facturedet as fd, '.MAIN_DB_PREFIX.'societe as s)'; - // $this->export_sql_end[$r] .=' LEFT JOIN '.MAIN_DB_PREFIX.'product as p on (fd.fk_product = p.rowid)'; - // $this->export_sql_end[$r] .=' WHERE f.fk_soc = s.rowid AND f.rowid = fd.fk_facture'; - // $this->export_sql_order[$r] .=' ORDER BY s.nom'; + // $this->export_sql_end[$r] =' FROM '.MAIN_DB_PREFIX.'myobject as t'; + // $this->export_sql_order[$r] .=' ORDER BY t.ref'; // $r++; + END MODULEBUILDER EXPORT MYOBJECT */ + } /** diff --git a/htdocs/modulebuilder/template/mymoduleindex.php b/htdocs/modulebuilder/template/mymoduleindex.php new file mode 100644 index 00000000000..f1c92659f9b --- /dev/null +++ b/htdocs/modulebuilder/template/mymoduleindex.php @@ -0,0 +1,237 @@ + + * Copyright (C) 2004-2015 Laurent Destailleur + * Copyright (C) 2005-2012 Regis Houssin + * Copyright (C) 2015 Jean-François Ferry + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file htdocs/mymodule/template/mymoduleindex.php + * \ingroup mymodule + * \brief Home page of mymodule top menu + */ + +// Load Dolibarr environment +$res=0; +// Try main.inc.php into web root known defined into CONTEXT_DOCUMENT_ROOT (not always defined) +if (! $res && ! empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) $res=@include($_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php"); +// Try main.inc.php into web root detected using web root caluclated from SCRIPT_FILENAME +$tmp=empty($_SERVER['SCRIPT_FILENAME'])?'':$_SERVER['SCRIPT_FILENAME'];$tmp2=realpath(__FILE__); $i=strlen($tmp)-1; $j=strlen($tmp2)-1; +while($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i]==$tmp2[$j]) { $i--; $j--; } +if (! $res && $i > 0 && file_exists(substr($tmp, 0, ($i+1))."/main.inc.php")) $res=@include(substr($tmp, 0, ($i+1))."/main.inc.php"); +if (! $res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i+1)))."/main.inc.php")) $res=@include(dirname(substr($tmp, 0, ($i+1)))."/main.inc.php"); +// Try main.inc.php using relative path +if (! $res && file_exists("../main.inc.php")) $res=@include("../main.inc.php"); +if (! $res && file_exists("../../main.inc.php")) $res=@include("../../main.inc.php"); +if (! $res && file_exists("../../../main.inc.php")) $res=@include("../../../main.inc.php"); +if (! $res) die("Include of main fails"); + +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php'; + +if (! $user->rights->mymodule->read) accessforbidden(); + +$langs->load("mymodule@mymodule"); + +$action=GETPOST('action', 'alpha'); + +// Securite acces client +$socid=GETPOST('socid','int'); +if (isset($user->societe_id) && $user->societe_id > 0) +{ + $action = ''; + $socid = $user->societe_id; +} + +$max=5; +$now=dol_now(); + + +/* + * Actions + */ + +// None + + +/* + * View + */ + +$form = new Form($db); +$formfile = new FormFile($db); + +llxHeader("",$langs->trans("MyModuleArea")); + +print load_fiche_titre($langs->trans("MyModuleArea"),'','mymodule.png@mymodule'); + +print '
'; + + +/* BEGIN MODULEBUILDER DRAFT MYOBJECT +// Draft MyObject +if (! empty($conf->mymodule->enabled) && $user->rights->mymodule->read) +{ + $langs->load("orders"); + + $sql = "SELECT c.rowid, c.ref, c.ref_client, c.total_ht, c.tva as total_tva, c.total_ttc, s.rowid as socid, s.nom as name, s.client, s.canvas"; + $sql.= ", s.code_client"; + $sql.= " FROM ".MAIN_DB_PREFIX."commande as c"; + $sql.= ", ".MAIN_DB_PREFIX."societe as s"; + if (! $user->rights->societe->client->voir && ! $socid) $sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; + $sql.= " WHERE c.fk_soc = s.rowid"; + $sql.= " AND c.fk_statut = 0"; + $sql.= " AND c.entity IN (".getEntity('commande').")"; + if (! $user->rights->societe->client->voir && ! $socid) $sql.= " AND s.rowid = sc.fk_soc AND sc.fk_user = " .$user->id; + if ($socid) $sql.= " AND c.fk_soc = ".$socid; + + $resql = $db->query($sql); + if ($resql) + { + $total = 0; + $num = $db->num_rows($resql); + + print ''; + print ''; + print ''; + + $var = true; + if ($num > 0) + { + $i = 0; + while ($i < $num) + { + + $obj = $db->fetch_object($resql); + print ''; + print ''; + print ''; + $i++; + $total += $obj->total_ttc; + } + if ($total>0) + { + + print '"; + } + } + else + { + + print ''; + } + print "
'.$langs->trans("DraftOrders").($num?' '.$num.'':'').'
'; + $orderstatic->id=$obj->rowid; + $orderstatic->ref=$obj->ref; + $orderstatic->ref_client=$obj->ref_client; + $orderstatic->total_ht = $obj->total_ht; + $orderstatic->total_tva = $obj->total_tva; + $orderstatic->total_ttc = $obj->total_ttc; + print $orderstatic->getNomUrl(1); + print ''; + $companystatic->id=$obj->socid; + $companystatic->name=$obj->name; + $companystatic->client=$obj->client; + $companystatic->code_client = $obj->code_client; + $companystatic->code_fournisseur = $obj->code_fournisseur; + $companystatic->canvas=$obj->canvas; + print $companystatic->getNomUrl(1,'customer',16); + print ''.price($obj->total_ttc).'
'.$langs->trans("Total").''.price($total)."
'.$langs->trans("NoOrder").'

"; + + $db->free($resql); + } + else + { + dol_print_error($db); + } +} +END MODULEBUILDER DRAFT MYOBJECT */ + + +print '
'; + + +$NBMAX=3; +$max=3; + +/* BEGIN MODULEBUILDER LASTMODIFIED MYOBJECT +// Last modified myobject +if (! empty($conf->mymodule->enabled) && $user->rights->mymodule->read) +{ + $sql = "SELECT s.rowid, s.nom as name, s.client, s.datec, s.tms, s.canvas"; + $sql.= ", s.code_client"; + $sql.= " FROM ".MAIN_DB_PREFIX."societe as s"; + if (! $user->rights->societe->client->voir && ! $socid) $sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; + $sql.= " WHERE s.client IN (1, 2, 3)"; + $sql.= " AND s.entity IN (".getEntity($companystatic->element, 1).")"; + if (! $user->rights->societe->client->voir && ! $socid) $sql.= " AND s.rowid = sc.fk_soc AND sc.fk_user = " .$user->id; + if ($socid) $sql.= " AND s.rowid = $socid"; + $sql .= " ORDER BY s.tms DESC"; + $sql .= $db->plimit($max, 0); + + $resql = $db->query($sql); + if ($resql) + { + $num = $db->num_rows($resql); + $i = 0; + + print ''; + print ''; + print ''; + print ''; + print ''; + if ($num) + { + while ($i < $num) + { + $objp = $db->fetch_object($resql); + $companystatic->id=$objp->rowid; + $companystatic->name=$objp->name; + $companystatic->client=$objp->client; + $companystatic->code_client = $objp->code_client; + $companystatic->code_fournisseur = $objp->code_fournisseur; + $companystatic->canvas=$objp->canvas; + print ''; + print ''; + print '"; + print '"; + print ''; + $i++; + + + } + + $db->free($resql); + } + else + { + print ''; + } + print "
'; + if (empty($conf->global->SOCIETE_DISABLE_PROSPECTS) && empty($conf->global->SOCIETE_DISABLE_CUSTOMERS)) print $langs->trans("BoxTitleLastCustomersOrProspects",$max); + else if (! empty($conf->global->SOCIETE_DISABLE_CUSTOMERS)) print $langs->trans("BoxTitleLastModifiedProspects",$max); + else print $langs->trans("BoxTitleLastModifiedCustomers",$max); + print ''.$langs->trans("DateModificationShort").'
'.$companystatic->getNomUrl(1,'customer',48).''; + print $companystatic->getLibCustProspStatut(); + print "'.dol_print_date($db->jdate($objp->tms),'day')."
'.$langs->trans("None").'

"; + } +} +*/ + +print '
'; + +llxFooter(); + +$db->close(); From caaeac35b6b6f17ec0d32b132d420652578f7d2e Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 17 Jul 2017 00:02:04 +0200 Subject: [PATCH 3/9] Work on modulebuilder --- htdocs/modulebuilder/index.php | 3 ++ scripts/modulebuilder/builddoc.php | 67 ++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100755 scripts/modulebuilder/builddoc.php diff --git a/htdocs/modulebuilder/index.php b/htdocs/modulebuilder/index.php index 67581d921c5..2399ce41246 100644 --- a/htdocs/modulebuilder/index.php +++ b/htdocs/modulebuilder/index.php @@ -931,6 +931,9 @@ elseif (! empty($module)) print ' '.$langs->trans("SpecificationFile").' : '.$pathtofile.''; print ' '.img_picto($langs->trans("Edit"), 'edit').''; print '
'; + + // Use MD or asciidoc + //print 'http://asciidoctor.org/docs/user-manual/#compared-to-markdown'; } else { diff --git a/scripts/modulebuilder/builddoc.php b/scripts/modulebuilder/builddoc.php new file mode 100755 index 00000000000..2ac8d97ac32 --- /dev/null +++ b/scripts/modulebuilder/builddoc.php @@ -0,0 +1,67 @@ +#!/usr/bin/env php + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +/** + * \file scripts/modulebuilder/builddoc.php + * \ingroup modulebuilder + * \brief Script to build a documentation from input files (.asciidoc or .md files). Use asciidoctor tool. + * + * If file is a MD file, convert image links into asciidoc format. + * ![Screenshot patient card](img/dolimed_screenshot_patientcard.png?raw=true "Patient card") + * image:img/dolimed_screenshot_patientcard.png[Screenshot patient card] + */ + + +$sapi_type = php_sapi_name(); +$script_file = basename(__FILE__); +$path=dirname(__FILE__).'/'; + +// Test if batch mode +if (substr($sapi_type, 0, 3) == 'cgi') { + echo "Error: You are using PHP for CGI. To execute ".$script_file." from command line, you must use PHP for CLI mode.\n"; + exit(-1); +} + +if (! isset($argv[1]) || ! $argv[1]) { + print "Usage: ".$script_file." inputfile1\n"; + exit(-1); +} +$inputfile1=$argv[1]; + +require_once ($path."../../htdocs/master.inc.php"); + + +// Global variables +$version=DOL_VERSION; +$error=0; + + + +/* + * Main + */ + +@set_time_limit(0); +print "***** ".$script_file." (".$version.") pid=".dol_getmypid()." *****\n"; +print $inputfile1."
"; + + + + From 330f3af74d18cb30a58fda07b37d712810536e78 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 17 Jul 2017 10:26:36 +0200 Subject: [PATCH 4/9] Fix pb in recursive dol_dir_list return. --- htdocs/core/lib/files.lib.php | 7 ++++-- htdocs/langs/en_US/modulebuilder.lang | 5 +++-- htdocs/modulebuilder/index.php | 22 ++++++++++++------- .../Specifications.asciidoc} | 0 4 files changed, 22 insertions(+), 12 deletions(-) rename htdocs/modulebuilder/template/{SPECIFICATIONS.md => doc/Specifications.asciidoc} (100%) diff --git a/htdocs/core/lib/files.lib.php b/htdocs/core/lib/files.lib.php index 074b38bfc2d..a785b55a5ec 100644 --- a/htdocs/core/lib/files.lib.php +++ b/htdocs/core/lib/files.lib.php @@ -51,10 +51,11 @@ function dol_basename($pathfile) * @param string $sortorder Sort order (SORT_ASC, SORT_DESC) * @param int $mode 0=Return array minimum keys loaded (faster), 1=Force all keys like date and size to be loaded (slower), 2=Force load of date only, 3=Force load of size only * @param int $nohook Disable all hooks + * @param string $relativename For recursive purpose only. Must be "" at first call. * @return array Array of array('name'=>'xxx','fullname'=>'/abc/xxx','date'=>'yyy','size'=>99,'type'=>'dir|file',...) * @see dol_dir_list_indatabase */ -function dol_dir_list($path, $types="all", $recursive=0, $filter="", $excludefilter="", $sortcriteria="name", $sortorder=SORT_ASC, $mode=0, $nohook=0) +function dol_dir_list($path, $types="all", $recursive=0, $filter="", $excludefilter="", $sortcriteria="name", $sortorder=SORT_ASC, $mode=0, $nohook=0, $relativename="") { global $db, $hookmanager; global $object; @@ -144,6 +145,7 @@ function dol_dir_list($path, $types="all", $recursive=0, $filter="", $excludefil "name" => $file, "path" => $path, "level1name" => $level1name, + "relativename" => ($relativename?$relativename.'/':'').$file, "fullname" => $path.'/'.$file, "date" => $filedate, "size" => $filesize, @@ -155,7 +157,7 @@ function dol_dir_list($path, $types="all", $recursive=0, $filter="", $excludefil // if we're in a directory and we want recursive behavior, call this function again if ($recursive) { - $file_list = array_merge($file_list,dol_dir_list($path."/".$file, $types, $recursive, $filter, $excludefilter, $sortcriteria, $sortorder, $mode, $nohook)); + $file_list = array_merge($file_list, dol_dir_list($path."/".$file, $types, $recursive, $filter, $excludefilter, $sortcriteria, $sortorder, $mode, $nohook, ($relativename?$relativename.'/':'').$file)); } } else if (! $isdir && (($types == "files") || ($types == "all"))) @@ -172,6 +174,7 @@ function dol_dir_list($path, $types="all", $recursive=0, $filter="", $excludefil "name" => $file, "path" => $path, "level1name" => $level1name, + "relativename" => ($relativename?$relativename.'/':'').$file, "fullname" => $path.'/'.$file, "date" => $filedate, "size" => $filesize, diff --git a/htdocs/langs/en_US/modulebuilder.lang b/htdocs/langs/en_US/modulebuilder.lang index bbaf00dcaf4..9a7fbb7b3bc 100644 --- a/htdocs/langs/en_US/modulebuilder.lang +++ b/htdocs/langs/en_US/modulebuilder.lang @@ -12,7 +12,7 @@ ModuleInitialized=Module initialized FilesForObjectInitialized=Files for new object '%s' initialized FilesForObjectUpdated=Files for object '%s' updated (.sql files and .class.php file) ModuleBuilderDescdescription=Enter here all general information that describe your module -ModuleBuilderDescspecifications=You can enter here a long text to describe the specifications of your module that is not already structured into other tabs. So you have within easy reach all the rules to develop. Also this text content will be included into the generated documentation (see last tab). +ModuleBuilderDescspecifications=You can enter here a long text to describe the specifications of your module that is not already structured into other tabs. So you have within easy reach all the rules to develop. Also this text content will be included into the generated documentation (see last tab). You can use Markdown format, but it is recommanded to use Asciidoc format (Comparison between .md and .asciidoc: http://asciidoctor.org/docs/user-manual/#compared-to-markdown) ModuleBuilderDescobjects=Define here the objects you want to manage with your module. A sql file, a page to list them, to create/edit/view a card and an API 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 your module. @@ -52,4 +52,5 @@ ReadmeFile=Readme file ChangeLog=ChangeLog file SqlFile=Sql file SqlFileKey=Sql file for keys -AnObjectAlreadyExistWithThisNameAndDiffCase=An object already exists with this name and a different case \ No newline at end of file +AnObjectAlreadyExistWithThisNameAndDiffCase=An object already exists with this name and a different case +UseAsciiDocFormat=You can use Markdown format, but it is recommanded to use Asciidoc format (Comparison between .md and .asciidoc: http://asciidoctor.org/docs/user-manual/#compared-to-markdown) \ No newline at end of file diff --git a/htdocs/modulebuilder/index.php b/htdocs/modulebuilder/index.php index 2399ce41246..359c46f17ae 100644 --- a/htdocs/modulebuilder/index.php +++ b/htdocs/modulebuilder/index.php @@ -924,20 +924,26 @@ elseif (! empty($module)) if ($tab == 'specifications') { - $pathtofile = $modulelowercase.'/SPECIFICATIONS.md'; - if ($action != 'editfile' || empty($file)) { - print ' '.$langs->trans("SpecificationFile").' : '.$pathtofile.''; - print ' '.img_picto($langs->trans("Edit"), 'edit').''; - print '
'; + $specs=dol_dir_list(dol_buildpath($modulelowercase.'/doc', 0), 'files', 1, '(\.md|\.asciidoc)$'); - // Use MD or asciidoc - //print 'http://asciidoctor.org/docs/user-manual/#compared-to-markdown'; + foreach ($specs as $spec) + { + $pathtofile = $modulelowercase.'/doc/'.$spec['relativename']; + + print ' '.$langs->trans("SpecificationFile").' : '.$pathtofile.''; + print ' '.img_picto($langs->trans("Edit"), 'edit').''; + print '
'; + } } else { - $fullpathoffile=dol_buildpath($file, 0); + // Use MD or asciidoc + + //print $langs->trans("UseAsciiDocFormat").'
'; + + $fullpathoffile=dol_buildpath($file, 0); $content = file_get_contents($fullpathoffile); diff --git a/htdocs/modulebuilder/template/SPECIFICATIONS.md b/htdocs/modulebuilder/template/doc/Specifications.asciidoc similarity index 100% rename from htdocs/modulebuilder/template/SPECIFICATIONS.md rename to htdocs/modulebuilder/template/doc/Specifications.asciidoc From d832bfc056182e41c303a601ab02133bf00332e3 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 17 Jul 2017 11:05:38 +0200 Subject: [PATCH 5/9] Some fix into dol_compress_dir function. --- htdocs/core/lib/files.lib.php | 19 +++++-- htdocs/langs/en_US/other.lang | 1 + htdocs/modulebuilder/index.php | 96 +++++++++++++++++++++++++++++++--- 3 files changed, 105 insertions(+), 11 deletions(-) diff --git a/htdocs/core/lib/files.lib.php b/htdocs/core/lib/files.lib.php index a785b55a5ec..77502f1737c 100644 --- a/htdocs/core/lib/files.lib.php +++ b/htdocs/core/lib/files.lib.php @@ -47,7 +47,7 @@ function dol_basename($pathfile) * @param string $filter Regex filter to restrict list. This regex value must be escaped for '/' by doing preg_quote($var,'/'), since this char is used for preg_match function, * but must not contains the start and end '/'. Filter is checked into basename only. * @param array $excludefilter Array of Regex for exclude filter (example: array('(\.meta|_preview.*\.png)$','^\.')). Exclude is checked into fullpath. - * @param string $sortcriteria Sort criteria ("","fullname","name","date","size") + * @param string $sortcriteria Sort criteria ("","fullname","relativename","name","date","size") * @param string $sortorder Sort order (SORT_ASC, SORT_DESC) * @param int $mode 0=Return array minimum keys loaded (faster), 1=Force all keys like date and size to be loaded (slower), 2=Force load of date only, 3=Force load of size only * @param int $nohook Disable all hooks @@ -1692,7 +1692,7 @@ function dol_uncompress($inputfile,$outputdir) * Compress a directory and subdirectories into a package file. * * @param string $inputdir Source dir name - * @param string $outputfile Target file name + * @param string $outputfile Target file name (output directory must exists and be writable) * @param string $mode 'zip' * @return int <0 if KO, >0 if OK */ @@ -1701,6 +1701,15 @@ function dol_compress_dir($inputdir, $outputfile, $mode="zip") $foundhandler=0; dol_syslog("Try to zip dir ".$inputdir." into ".$outputdir." mode=".$mode); + + if (! dol_is_dir(dirname($outputfile)) || ! is_writable(dirname($outputfile))) + { + global $langs, $errormsg; + $langs->load("errors"); + $errormsg=$langs->trans("ErrorFailedToWriteInDir",$outputfile); + return -3; + } + try { if ($mode == 'gz') { $foundhandler=0; } @@ -1724,7 +1733,7 @@ function dol_compress_dir($inputdir, $outputfile, $mode="zip") // Initialize archive object $zip = new ZipArchive(); - $zip->open($outputfile, ZipArchive::CREATE | ZipArchive::OVERWRITE); + $result = $zip->open($outputfile, ZipArchive::CREATE | ZipArchive::OVERWRITE); // Create recursive directory iterator /** @var SplFileInfo[] $files */ @@ -1759,6 +1768,10 @@ function dol_compress_dir($inputdir, $outputfile, $mode="zip") dol_syslog("Try to zip with format ".$mode." with no handler for this format",LOG_ERR); return -2; } + else + { + return 0; + } } catch (Exception $e) { diff --git a/htdocs/langs/en_US/other.lang b/htdocs/langs/en_US/other.lang index e15d490c0f2..e519f7af405 100644 --- a/htdocs/langs/en_US/other.lang +++ b/htdocs/langs/en_US/other.lang @@ -17,6 +17,7 @@ TextPreviousMonthOfInvoice=Previous month (text) of invoice date NextMonthOfInvoice=Following month (number 1-12) of invoice date TextNextMonthOfInvoice=Following month (text) of invoice date ZipFileGeneratedInto=Zip file generated into %s. +DocFileGeneratedInto=Doc file generated into %s. YearOfInvoice=Year of invoice date PreviousYearOfInvoice=Previous year of invoice date diff --git a/htdocs/modulebuilder/index.php b/htdocs/modulebuilder/index.php index 359c46f17ae..4afaf136e19 100644 --- a/htdocs/modulebuilder/index.php +++ b/htdocs/modulebuilder/index.php @@ -426,9 +426,19 @@ if ($dirins && $action == 'generatepackage') if (count($arrayversion)) { $FILENAMEZIP="module_".$modulelowercase.'-'.$arrayversion[0].'.'.$arrayversion[1].($arrayversion[2]?".".$arrayversion[2]:"").".zip"; - $outputfile = $conf->admin->dir_temp.'/'.$FILENAMEZIP; - $result = dol_compress_dir($dir, $outputfile, 'zip'); + $dirofmodule = dol_buildpath($modulelowercase, 0).'/bin'; + $outputfile = $dirofmodule.'/'.$FILENAMEZIP; + if ($dirofmodule) + { + if (! dol_is_dir($dirofmodule)) dol_mkdir($dirofmodule); + $result = dol_compress_dir($dir, $outputfile, 'zip'); + } + else + { + $result = -1; + } + if ($result > 0) { setEventMessages($langs->trans("ZipFileGeneratedInto", $outputfile), null); @@ -448,6 +458,76 @@ if ($dirins && $action == 'generatepackage') } } +if ($dirins && $action == 'generatedoc') +{ + $modulelowercase=strtolower($module); + + // Dir for module + $dir = $dirins.'/'.$modulelowercase; + // Zip file to build + $FILENAMEDOC=''; + + // 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++; + dol_print_error($e->getMessage()); + } + } + else + { + $error++; + $langs->load("errors"); + dol_print_error($langs->trans("ErrorFailedToLoadModuleDescriptorForXXX", $module)); + exit; + } + + $arrayversion=explode('.',$moduleobj->version,3); + if (count($arrayversion)) + { + $FILENAMEDOC=$modulelowercase.'.html'; + + $dirofmodule = dol_buildpath($modulelowercase, 0).'/doc'; + $outputfile = $dirofmodule.'/'.$FILENAMEDOC; + if ($dirofmodule) + { + if (! dol_is_dir($dirofmodule)) dol_mkdir($dirofmodule); + //... + + $result = 0; + } + else + { + $result = 0; + } + + if ($result > 0) + { + setEventMessages($langs->trans("DocFileGeneratedInto", $outputfile), null); + } + else + { + $error++; + $langs->load("errors"); + setEventMessages($langs->trans("ErrorFailToGenerateFile", $outputfile), null, 'errors'); + } + } + else + { + $error++; + $langs->load("errors"); + setEventMessages($langs->trans("ErrorCheckVersionIsDefined"), null, 'errors'); + } +} + // Save file if ($action == 'savefile' && empty($cancel)) { @@ -1408,10 +1488,10 @@ elseif (! empty($module)) if (count($arrayversion)) { $FILENAMEZIP="module_".$modulelowercase.'-'.$arrayversion[0].'.'.$arrayversion[1].($arrayversion[2]?".".$arrayversion[2]:"").".zip"; - $outputfile = $conf->admin->dir_temp.'/'.$FILENAMEZIP; + $outputfile = dol_buildpath($modulelowercase, 0).'/bin/'.$FILENAMEZIP; - $FILENAMEDOC="module_".$modulelowercase.'-'.$arrayversion[0].'.'.$arrayversion[1].($arrayversion[2]?".".$arrayversion[2]:"").".md"; - $outputfiledoc = $conf->admin->dir_temp.'/'.$FILENAMEDOC; + $FILENAMEDOC=$modulelowercase.'.html'; + $outputfiledoc = dol_buildpath($modulelowercase, 0).'/doc/'.$FILENAMEDOC; } print '
'; @@ -1430,7 +1510,7 @@ elseif (! empty($module)) print ''; print ''; print ''; - print ''; + print ''; print ''; print '


'; @@ -1445,11 +1525,11 @@ elseif (! empty($module)) print '
'; - print '
'; + print ''; print ''; print ''; print ''; - print ''; + print ''; print '
'; } From 4fa04247a9a9f9f028106ecb125ac7014ce1cb33 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 17 Jul 2017 11:09:32 +0200 Subject: [PATCH 6/9] Finished dev --- htdocs/core/modules/modModuleBuilder.class.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/core/modules/modModuleBuilder.class.php b/htdocs/core/modules/modModuleBuilder.class.php index dce442720a3..dabfda48518 100644 --- a/htdocs/core/modules/modModuleBuilder.class.php +++ b/htdocs/core/modules/modModuleBuilder.class.php @@ -47,7 +47,7 @@ class modModuleBuilder extends DolibarrModules // Module label (no space allowed), used if translation string 'ModuleXXXName' not found (where XXX is value of numeric property 'numero' of module) $this->name = preg_replace('/^mod/i','',get_class($this)); $this->description = "A tool to help developers to build their own module."; - $this->version = 'development'; // 'development', 'experimental' or 'dolibarr' or version + $this->version = 'experimental'; // 'development', 'experimental' or 'dolibarr' or version // Key used in llx_const table to save module status enabled/disabled (where MYMODULE is value of property name of module in uppercase) $this->const_name = 'MAIN_MODULE_'.strtoupper($this->name); // Where to store the module in setup page (0=common,1=interface,2=others,3=very specific) @@ -85,7 +85,7 @@ class modModuleBuilder extends DolibarrModules // Main menu entries //------------------ $this->menu = array(); - + $this->menu[$r]=array('fk_menu'=>'fk_mainmenu=home,fk_leftmenu=admintools', 'type'=>'left', 'titre'=>'ModuleBuilder', @@ -98,6 +98,6 @@ class modModuleBuilder extends DolibarrModules 'enabled'=>'$conf->modulebuilder->enabled && preg_match(\'/^admintools/\',$leftmenu) && ($user->admin || $conf->global->MODULEBUILDER_FOREVERYONE)', 'target'=>'_modulebuilder', 'user'=>0); - + } } From 0cf38f719788a2b2acb9796f34df0985933433a2 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 17 Jul 2017 16:23:24 +0200 Subject: [PATCH 7/9] Fix log file name not set during install --- htdocs/install/inc.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/htdocs/install/inc.php b/htdocs/install/inc.php index b9efc4eb8a4..47ff430ea18 100644 --- a/htdocs/install/inc.php +++ b/htdocs/install/inc.php @@ -220,6 +220,7 @@ if (! defined('SYSLOG_FILE')) // To avoid warning on systems with constant alrea else if (@is_writable('../../../../') && @file_exists('../../../../startdoliwamp.bat')) define('SYSLOG_FILE','../../../../dolibarr_install.log'); // For DoliWamp else if (@is_writable('../../')) define('SYSLOG_FILE','../../dolibarr_install.log'); // For others //print 'SYSLOG_FILE='.SYSLOG_FILE;exit; + if (defined('SYSLOG_FILE')) $conf->global->SYSLOG_FILE=constant('SYSLOG_FILE'); } if (! defined('SYSLOG_FILE_NO_ERROR')) define('SYSLOG_FILE_NO_ERROR',1); // We init log handler for install @@ -325,6 +326,7 @@ function conf($dolibarr_main_document_root) else if (@is_writable('../../../../') && @file_exists('../../../../startdoliwamp.bat')) define('SYSLOG_FILE','../../../../dolibarr_install.log'); // For DoliWamp else if (@is_writable('../../')) define('SYSLOG_FILE','../../dolibarr_install.log'); // For others //print 'SYSLOG_FILE='.SYSLOG_FILE;exit; + if (defined('SYSLOG_FILE')) $conf->global->SYSLOG_FILE=constant('SYSLOG_FILE'); } if (! defined('SYSLOG_FILE_NO_ERROR')) define('SYSLOG_FILE_NO_ERROR',1); // We init log handler for install From b075f7a459de16ae9330c1f48dc3f41315030ad4 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 17 Jul 2017 16:32:10 +0200 Subject: [PATCH 8/9] Incomplete translation --- htdocs/langs/en_US/install.lang | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/langs/en_US/install.lang b/htdocs/langs/en_US/install.lang index 2b10dea91ec..4bd1bba3e9a 100644 --- a/htdocs/langs/en_US/install.lang +++ b/htdocs/langs/en_US/install.lang @@ -53,10 +53,10 @@ AdminLogin=Login for Dolibarr database owner. PasswordAgain=Retype password a second time AdminPassword=Password for Dolibarr database owner. CreateDatabase=Create database -CreateUser=Create owner +CreateUser=Create owner or grant him permission on database DatabaseSuperUserAccess=Database server - Superuser access CheckToCreateDatabase=Check box if database does not exist and must be created.
In this case, you must fill the login/password for superuser account at the bottom of this page. -CheckToCreateUser=Check box if database owner does not exist and must be created.
In this case, you must choose its login and password and also fill the login/password for the superuser account at the bottom of this page. If this box is unchecked, owner database and its passwords must exists. +CheckToCreateUser=Check box if database owner does not exist and must be created, or if it exists but database does not exists and permissions must be granted.
In this case, you must choose its login and password and also fill the login/password for the superuser account at the bottom of this page. If this box is unchecked, owner database and its passwords must exists. DatabaseRootLoginDescription=Login of the user allowed to create new databases or new users, mandatory if your database or its owner does not already exists. KeepEmptyIfNoPassword=Leave empty if user has no password (avoid this) SaveConfigurationFile=Save values From 1ef70b387d2682869732686c7bfa265611951666 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Mon, 17 Jul 2017 16:45:24 +0200 Subject: [PATCH 9/9] Fix bad limit --- htdocs/admin/websites.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/admin/websites.php b/htdocs/admin/websites.php index 66776220d32..61fa7bc17f3 100644 --- a/htdocs/admin/websites.php +++ b/htdocs/admin/websites.php @@ -362,7 +362,7 @@ if ($id) $sql.=" ORDER BY "; } $sql.=$tabsqlsort[$id]; - $sql.=$db->plimit($listlimit+1,$offset); + $sql.=$db->plimit($limit+1, $offset); //print $sql; $fieldlist=explode(',',$tabfield[$id]);