diff --git a/htdocs/api/class/api.class.php b/htdocs/api/class/api.class.php index df7054ca162..de5a1e75d0a 100644 --- a/htdocs/api/class/api.class.php +++ b/htdocs/api/class/api.class.php @@ -216,7 +216,7 @@ class DolibarrApi * * @param string $resource element to check * @param int $resource_id Object ID if we want to check a particular record (optional) is linked to a owned thirdparty (optional). - * @param type $dbtablename 'TableName&SharedElement' with Tablename is table where object is stored. SharedElement is an optional key to define where to check entity. Not used if objectid is null (optional) + * @param string $dbtablename 'TableName&SharedElement' with Tablename is table where object is stored. SharedElement is an optional key to define where to check entity. Not used if objectid is null (optional) * @param string $feature2 Feature to check, second level of permission (optional). Can be or check with 'level1|level2'. * @param string $dbt_keyfield Field name for socid foreign key if not fk_soc. Not used if objectid is null (optional) * @param string $dbt_select Field name for select if not rowid. Not used if objectid is null (optional) diff --git a/htdocs/langs/en_US/main.lang b/htdocs/langs/en_US/main.lang index 3aec931714b..463cf828b29 100644 --- a/htdocs/langs/en_US/main.lang +++ b/htdocs/langs/en_US/main.lang @@ -855,7 +855,7 @@ Download=Download DownloadDocument=Download document ActualizeCurrency=Update currency rate Fiscalyear=Fiscal year -ModuleBuilder=Module Builder +ModuleBuilder=Module and Application Builder SetMultiCurrencyCode=Set currency BulkActions=Bulk actions ClickToShowHelp=Click to show tooltip help diff --git a/htdocs/langs/en_US/modulebuilder.lang b/htdocs/langs/en_US/modulebuilder.lang index 8e2d57a03fc..5cb927dc8b7 100644 --- a/htdocs/langs/en_US/modulebuilder.lang +++ b/htdocs/langs/en_US/modulebuilder.lang @@ -1,5 +1,5 @@ # Dolibarr language file - Source file is en_US - loan -ModuleBuilderDesc=This tool must be used only by experienced users or developers. It provides utilities to build or edit your own module.
Documentation for alternative manual development is here. +ModuleBuilderDesc=This tool must be used only by experienced users or developers. It provides utilities to build or edit your own module. Documentation for alternative manual development is here. EnterNameOfModuleDesc=Enter name of the module/application to create with no spaces. Use uppercase to separate words (For example: MyModule, EcommerceForShop, SyncWithMySystem...) EnterNameOfObjectDesc=Enter name of the object to create with no spaces. Use uppercase to separate words (For example: MyObject, Student, Teacher...). The CRUD class file, but also API file, pages to list/add/edit/delete object and SQL files will be generated. ModuleBuilderDesc2=Path where modules are generated/edited (first directory for external modules defined into %s): %s @@ -21,13 +21,14 @@ ModuleBuilderDesctriggers=This is the view of triggers provided by your module. ModuleBuilderDeschooks=This tab is dedicated to hooks. ModuleBuilderDescwidgets=This tab is dedicated to manage/build widgets. ModuleBuilderDescbuildpackage=You can generate here a "ready to distribute" package file (a normalized .zip file) of your module and a "ready to distribute" documentation file. Just click on button to build the package or documentation file. -EnterNameOfModuleToDeleteDesc=You can delete your module. WARNING: ALL files of module AND structured data and documentation will be deleted! -EnterNameOfObjectToDeleteDesc=You can delete an object. WARNING: All files related to object will be deleted! +EnterNameOfModuleToDeleteDesc=You can delete your module. WARNING: All coding files of module (generated or created manually) AND structured data and documentation will be deleted! +EnterNameOfObjectToDeleteDesc=You can delete an object. WARNING: All coding files (generated or created manually) related to object will be deleted! DangerZone=Danger zone BuildPackage=Build package +BuildPackageDesc=You can generate a zip package or your application so your are ready to distribute it on any Dolibarr. You can also distribute it or sell it on marketplace like DoliStore.com. BuildDocumentation=Build documentation ModuleIsNotActive=This module is not activated yet. Go to %s to make it live or click here: -ModuleIsLive=This module has been activated. Any change on it may break a current active feature. +ModuleIsLive=This module has been activated. Any change may break a current live feature. DescriptionLong=Long description EditorName=Name of editor EditorUrl=URL of editor @@ -43,10 +44,11 @@ PathToModulePackage=Path to zip of module/application package PathToModuleDocumentation=Path to file of module/application documentation (%s) SpaceOrSpecialCharAreNotAllowed=Spaces or special characters are not allowed. FileNotYetGenerated=File not yet generated -RegenerateClassAndSql=Erase and regenerate class and sql files +RegenerateClassAndSql=Force update of .class and .sql files RegenerateMissingFiles=Generate missing files SpecificationFile=File of documentation LanguageFile=File for language +ObjectProperties=Object Properties ConfirmDeleteProperty=Are you sure you want to delete the property %s? This will change code in PHP class but also remove column from table definition of object. NotNull=Not NULL NotNullDesc=1=Set database to NOT NULL. -1=Allow null values and force value to NULL if empty ('' or 0). @@ -62,7 +64,8 @@ ReadmeFile=Readme file ChangeLog=ChangeLog file TestClassFile=File for PHP Unit Test class SqlFile=Sql file -PageForLib=File for PHP libraries +PageForLib=File for PHP library +PageForObjLib=File for PHP library dedicated to object SqlFileExtraFields=Sql file for complementary attributes SqlFileKey=Sql file for keys AnObjectAlreadyExistWithThisNameAndDiffCase=An object already exists with this name and a different case @@ -81,8 +84,10 @@ IsAMeasureDesc=Can the value of field be cumulated to get a total into list? (Ex SearchAllDesc=Is the field used to make a search from the quick search tool? (Examples: 1 or 0) SpecDefDesc=Enter here all documentation you want to provide with your module that is not already defined by other tabs. You can use .md or better, the rich .asciidoc syntax. LanguageDefDesc=Enter in this files, all the key and the translation for each language file. -MenusDefDesc=Define here the menus provided by your module (once defined, they are visible into the menu editor %s) -PermissionsDefDesc=Define here the new permissions provided by your module (once defined, they are visible into the default permissions setup %s) +MenusDefDesc=Define here the menus provided by your module +PermissionsDefDesc=Define here the new permissions provided by your module +MenusDefDescTooltip=The menus provided by your module/application are defined into the array $this->menus into the module descriptor file. You can edit manually this file or use the embedded editor.

Note: Once defined (and module re-activated), menus are also visible into the menu editor available to administrator users on %s. +PermissionsDefDescTooltip=The permissions provided by your module/application are defined into the array $this->rights into the module descriptor file. You can edit manually this file or use the embedded editor.

Note: Once defined (and module re-activated), permissions are visible into the default permissions setup %s. HooksDefDesc=Define in the module_parts['hooks'] property, in the module descriptor, the context of hooks you want to manage (list of contexts can be found by a search on 'initHooks(' in core code).
Edit the hook file to add code of your hooked functions (hookable functions can be found by a search on 'executeHooks' in core code). TriggerDefDesc=Define in the trigger file the code you want to execute for each business event executed. SeeIDsInUse=See IDs in use in your installation @@ -109,4 +114,5 @@ UseSpecificEditorName = Use a specific editor name UseSpecificEditorURL = Use a specific editor URL UseSpecificFamily = Use a specific family UseSpecificAuthor = Use a specific author -UseSpecificVersion = Use a specific initial version \ No newline at end of file +UseSpecificVersion = Use a specific initial version +ModuleMustBeEnabled=The module/application must be enabled first \ No newline at end of file diff --git a/htdocs/modulebuilder/index.php b/htdocs/modulebuilder/index.php index 0e80c0ba4ac..0ad297221be 100644 --- a/htdocs/modulebuilder/index.php +++ b/htdocs/modulebuilder/index.php @@ -156,8 +156,7 @@ if ($dirins && $action == 'initmodule' && $modulename) dol_delete_file($destdir.'/scripts/'.strtolower($modulename).'.php'); dol_delete_dir($destdir.'/scripts'); - - // Delete some files related to Object (because the dolCopyDir has copied everything) + // Delete some files related to Object (because the previous dolCopyDir has copied everything) dol_delete_file($destdir.'/myobject_card.php'); dol_delete_file($destdir.'/myobject_note.php'); dol_delete_file($destdir.'/myobject_document.php'); @@ -222,6 +221,39 @@ if ($dirins && $action == 'initmodule' && $modulename) } } +if ($dirins && $action == 'initapi' && !empty($module)) +{ + dol_mkdir($dirins.'/'.strtolower($module).'/class'); + $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template'; + $srcfile = $srcdir.'/class/api_mymodule.class.php'; + $destfile = $dirins.'/'.strtolower($module).'/class/api_'.strtolower($module).'.class.php'; + //var_dump($srcfile);var_dump($destfile); + $result = dol_copy($srcfile, $destfile, 0, 0); + + if ($result > 0) + { + $modulename = ucfirst($module); // Force first letter in uppercase + $objectname = $tabobj; + + //var_dump($phpfileval['fullname']); + $arrayreplacement=array( + 'mymodule'=>strtolower($modulename), + 'MyModule'=>$modulename, + 'MYMODULE'=>strtoupper($modulename), + 'My module'=>$modulename, + 'my module'=>$modulename, + 'Mon module'=>$modulename, + 'mon module'=>$modulename, + 'htdocs/modulebuilder/template'=>strtolower($modulename), + 'myobject'=>strtolower($objectname), + 'MyObject'=>$objectname, + 'MYOBJECT'=>strtoupper($objectname), + '---Put here your own copyright and developer email---'=>dol_print_date($now, '%Y').' '.$user->getFullName($langs).($user->email?' <'.$user->email.'>':'') + ); + + dolReplaceInFile($destfile, $arrayreplacement); + } +} if ($dirins && $action == 'inithook' && !empty($module)) { dol_mkdir($dirins.'/'.strtolower($module).'/class'); @@ -230,6 +262,26 @@ if ($dirins && $action == 'inithook' && !empty($module)) $destfile = $dirins.'/'.strtolower($module).'/class/actions_'.strtolower($module).'.class.php'; //var_dump($srcfile);var_dump($destfile); $result = dol_copy($srcfile, $destfile, 0, 0); + + if ($result > 0) + { + $modulename = ucfirst($module); // Force first letter in uppercase + + //var_dump($phpfileval['fullname']); + $arrayreplacement=array( + 'mymodule'=>strtolower($modulename), + 'MyModule'=>$modulename, + 'MYMODULE'=>strtoupper($modulename), + 'My module'=>$modulename, + 'my module'=>$modulename, + 'Mon module'=>$modulename, + 'mon module'=>$modulename, + 'htdocs/modulebuilder/template'=>strtolower($modulename), + '---Put here your own copyright and developer email---'=>dol_print_date($now, '%Y').' '.$user->getFullName($langs).($user->email?' <'.$user->email.'>':'') + ); + + dolReplaceInFile($destfile, $arrayreplacement); + } } if ($dirins && $action == 'inittrigger' && !empty($module)) { @@ -500,10 +552,10 @@ if ($dirins && $action == 'initobject' && $module && $objectname) 'sql/llx_mymodule_myobject.sql'=>'sql/llx_'.strtolower($module).'_'.strtolower($objectname).'.sql', 'sql/llx_mymodule_myobject_extrafields.sql'=>'sql/llx_'.strtolower($module).'_'.strtolower($objectname).'_extrafields.sql', 'sql/llx_mymodule_myobject.key.sql'=>'sql/llx_'.strtolower($module).'_'.strtolower($objectname).'.key.sql', - 'scripts/myobject.php'=>'scripts/'.strtolower($objectname).'.php', + //'scripts/mymodule.php'=>'scripts/'.strtolower($objectname).'.php', 'img/object_myobject.png'=>'img/object_'.strtolower($objectname).'.png', 'class/myobject.class.php'=>'class/'.strtolower($objectname).'.class.php', - 'class/api_mymodule.class.php'=>'class/api_'.strtolower($module).'.class.php' + //'class/api_mymodule.class.php'=>'class/api_'.strtolower($module).'.class.php' ); foreach($filetogenerate as $srcfile => $destfile) @@ -524,8 +576,8 @@ if ($dirins && $action == 'initobject' && $module && $objectname) } } - if (! $error) - { + //if (! $error) // If there is error copying 1 file, we still have to make the replacement + //{ // Scan for object class files $listofobject = dol_dir_list($destdir.'/class', 'files', 0, '\.class\.php$'); @@ -536,6 +588,7 @@ if ($dirins && $action == 'initobject' && $module && $objectname) if (preg_match('/^actions_/', $fileobj['name'])) continue; $tmpcontent=file_get_contents($fileobj['fullname']); + $reg=array(); if (preg_match('/class\s+([^\s]*)\s+extends\s+CommonObject/ims', $tmpcontent, $reg)) { $objectnameloop = $reg[1]; @@ -587,7 +640,7 @@ if ($dirins && $action == 'initobject' && $module && $objectname) // TODO } - } + //} } if (! $error) @@ -730,11 +783,11 @@ if ($dirins && $action == 'addproperty' && !empty($module) && ! empty($tabobj)) } } - if (GETPOST('regeneratemissing')) + /*if (GETPOST('regeneratemissing')) { setEventMessages($langs->trans("FeatureNotYetAvailable"), null, 'warnings'); $error++; - } + }*/ // Edit the class file to write properties if (! $error) @@ -760,7 +813,7 @@ if ($dirins && $action == 'addproperty' && !empty($module) && ! empty($tabobj)) clearstatcache(true); // Make a redirect to reload all data - header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=objects&module='.$module.'&tabobj='.$objectname.'&nocache='.time()); + header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=objects&module='.$module.($forceddirread?'@'.$dirread:'').'&tabobj='.$objectname.'&nocache='.time()); exit; } @@ -795,7 +848,7 @@ if ($dirins && $action == 'confirm_deleteproperty' && $propertykey) clearstatcache(true); // Make a redirect to reload all data - header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=objects&module='.$module.'&tabobj='.$objectname); + header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=objects&module='.$module.($forceddirread?'@'.$dirread:'').'&tabobj='.$objectname); exit; } @@ -1030,9 +1083,9 @@ if ($action == 'savefile' && empty($cancel)) if ($action == 'set' && $user->admin) { $param=''; - if ($module) $param.='&module='.$module; - if ($tab) $param.='&tab='.$tab; - if ($tabobj) $param.='&tabobj='.$tabobj; + if ($module) $param.='&module='.urlencode($module); + if ($tab) $param.='&tab='.urlencode($tab); + if ($tabobj) $param.='&tabobj='.urlencode($tabobj); $value = GETPOST('value', 'alpha'); $resarray = activateModule($value); @@ -1065,9 +1118,9 @@ if ($action == 'set' && $user->admin) if ($action == 'reset' && $user->admin) { $param=''; - if ($module) $param.='&module='.$module; - if ($tab) $param.='&tab='.$tab; - if ($tabobj) $param.='&tabobj='.$tabobj; + if ($module) $param.='&module='.urlencode($module); + if ($tab) $param.='&tab='.urlencode($tab); + if ($tabobj) $param.='&tabobj='.urlencode($tabobj); $value = GETPOST('value', 'alpha'); $result=unActivateModule($value); @@ -1105,7 +1158,7 @@ $text=$langs->trans("ModuleBuilder"); print load_fiche_titre($text, '', 'title_setup'); -print $langs->trans("ModuleBuilderDesc", 'https://wiki.dolibarr.org/index.php/Module_development#Create_your_module').'
'; +print ''.$langs->trans("ModuleBuilderDesc", 'https://wiki.dolibarr.org/index.php/Module_development#Create_your_module').'
'; $dirsrootforscan=array($dirread); if ($dirread != DOL_DOCUMENT_ROOT && $conf->global->MAIN_FEATURES_LEVEL >=2) { $dirsrootforscan[]=DOL_DOCUMENT_ROOT; } @@ -1310,9 +1363,9 @@ elseif (! empty($module)) $const_name = 'MAIN_MODULE_'.strtoupper($module); $param=''; - if ($tab) $param.= '&tab='.$tab; - if ($module) $param.='&module='.$module; - if ($tabobj) $param.='&tabobj='.$tabobj; + if ($tab) $param.='&tab='.urlencode($tab); + if ($module) $param.='&module='.urlencode($module); + if ($tabobj) $param.='&tabobj='.urlencode($tabobj); $urltomodulesetup=''.$langs->trans('Home').'-'.$langs->trans("Setup").'-'.$langs->trans("Modules").''; $linktoenabledisable=''; @@ -1595,8 +1648,8 @@ elseif (! empty($module)) { $pathtofile = $modulelowercase.'/langs/'.$langfile['relativename']; print ' '.$langs->trans("LanguageFile").' '.basename(dirname($pathtofile)).' : '.$pathtofile.''; - print ''.img_picto($langs->trans("Edit"), 'edit').''; - print ''.img_picto($langs->trans("Delete"), 'delete').''; + print ''.img_picto($langs->trans("Edit"), 'edit').''; + print ''.img_picto($langs->trans("Delete"), 'delete').''; print ''; } print ''; @@ -1698,7 +1751,7 @@ elseif (! empty($module)) print '
'; print '
'; print '
'; - print $langs->trans("Or"); + print $langs->trans("or"); print '
'; print '
'; print '
'; @@ -1782,8 +1835,26 @@ elseif (! empty($module)) print ' '.img_picto($langs->trans("Edit"), 'edit').''; print '
'; print ' '.$langs->trans("ApiClassFile").' : '.($realpathtoapi?'':'').$pathtoapi.($realpathtoapi?'':'').''; - print ' '.img_picto($langs->trans("Edit"), 'edit').''; - print '   '.$langs->trans("GoToApiExplorer").''; + if ($realpathtoapi) + { + print ' '.img_picto($langs->trans("Edit"), 'edit').''; + print '   '; + print ''.img_picto($langs->trans("Delete"), 'delete').''; + print '   '; + if (empty($conf->global->$const_name)) // If module is not activated + { + print ''.$langs->trans("GoToApiExplorer").''; + } + else + { + print ''.$langs->trans("GoToApiExplorer").''; + } + } + else + { + //print ''.$langs->trans("FileNotYetGenerated").' '; + print ''; + } print '
'; print ' '.$langs->trans("TestClassFile").' : '.($realpathtophpunit?'':'').$pathtophpunit.($realpathtophpunit?'':'').''; print ' '.img_picto($langs->trans("Edit"), 'edit').''; @@ -1824,7 +1895,7 @@ elseif (! empty($module)) $urlofcard = dol_buildpath($pathtocard, 1); print '
'; - print ' '.$langs->trans("PageForList").' : '.($realpathtosql?'':'').$pathtolist.($realpathtosql?'':'').''; + print ' '.$langs->trans("PageForList").' : '.($realpathtolist?'':'').$pathtolist.($realpathtolist?'':'').''; print ' '.img_picto($langs->trans("Edit"), 'edit').''; print '
'; print ' '.$langs->trans("PageForCreateEditView").' : '.($realpathtocard?'':'').$pathtocard.($realpathtocard?'':'').'?action=create'; @@ -1840,10 +1911,11 @@ elseif (! empty($module)) print ' '.img_picto($langs->trans("Edit"), 'edit').''; print '
'; + /* This is already on Tab CLI print '
'; print ' '.$langs->trans("ScriptFile").' : '.($realpathtoscript?'':'').$pathtoscript.($realpathtoscript?'':'').''; print ' '.img_picto($langs->trans("Edit"), 'edit').''; - print '
'; + print '
';*/ print '
'; @@ -1888,10 +1960,10 @@ elseif (! empty($module)) print ''; print ''; - print ''; + //print ''; print '

'; - print load_fiche_titre($langs->trans("Properties"), '', ''); + print load_fiche_titre($langs->trans("ObjectProperties"), '', ''); print '
'; @@ -2040,7 +2112,7 @@ elseif (! empty($module)) $format='asciidoc'; if (preg_match('/\.md$/i', $spec['name'])) $format='markdown'; print ' '.$langs->trans("SpecificationFile").' : '.$pathtofile.''; - print ' '.img_picto($langs->trans("Edit"), 'edit').''; + print ' '.img_picto($langs->trans("Edit"), 'edit').''; print '
'; } } @@ -2137,17 +2209,22 @@ elseif (! empty($module)) if ($action != 'editfile' || empty($file)) { - print ''.$langs->trans("MenusDefDesc", ''.$langs->trans('Menus').'').'
'; + print ''; + $htmlhelp=$langs->trans("MenusDefDescTooltip", ''.$langs->trans('Setup').' - '.$langs->trans('Menus').''); + print $form->textwithpicto($langs->trans("MenusDefDesc"), $htmlhelp, 1, 'help', '', 0, 2, 'helpondesc').'
'; + print '
'; print '
'; print ' '.$langs->trans("DescriptorFile").' : '.$pathtofile.''; - print ' '.img_picto($langs->trans("Edit"), 'edit').''; + print ' '.img_picto($langs->trans("Edit"), 'edit').''; print '
'; print '
'; print load_fiche_titre($langs->trans("ListOfMenusEntries"), '', ''); - print 'TODO...'; + // @TODO + print $langs->trans("FeatureNotYetAvailable"); + print '
'; print ''; print ''; @@ -2262,16 +2339,24 @@ elseif (! empty($module)) if ($action != 'editfile' || empty($file)) { - print ''.$langs->trans("PermissionsDefDesc", ''.$langs->trans('DefaultPermissions').'').'
'; + + print ''; + $htmlhelp=$langs->trans("PermissionsDefDescTooltip", ''.$langs->trans('DefaultPermissions').''); + print $form->textwithpicto($langs->trans("PermissionsDefDesc"), $htmlhelp, 1, 'help', '', 0, 2, 'helpondesc').'
'; + print '
'; print '
'; print ' '.$langs->trans("DescriptorFile").' : '.$pathtofile.''; - print ' '.img_picto($langs->trans("Edit"), 'edit').''; + print ' '.img_picto($langs->trans("Edit"), 'edit').''; print '
'; print '
'; print load_fiche_titre($langs->trans("ListOfPermissionsDefined"), '', ''); + + // @TODO + print $langs->trans("FeatureNotYetAvailable"); + print ''; print ''; print ''; @@ -2279,7 +2364,6 @@ elseif (! empty($module)) print ''; print ''; - print 'TODO...'; /* print '
'; print ''; @@ -2391,7 +2475,7 @@ elseif (! empty($module)) $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath']; print ' '.$langs->trans("DescriptorFile").' : '.$pathtofile.''; print ''; print ''; - print ''; + print ''; + print ''; } else { print ''.$langs->trans("FileNotYetGenerated").''; - print ''; + print ''; } print ''; } @@ -2458,8 +2542,8 @@ elseif (! empty($module)) print ''; - print ''; + print ''; + print ''; print ''; } } @@ -2467,7 +2551,7 @@ elseif (! empty($module)) { print ''; + print ''; print ''; } print '
'; - print ''.img_picto($langs->trans("Edit"), 'edit').''; + print ''.img_picto($langs->trans("Edit"), 'edit').''; print '
'; @@ -2400,13 +2484,13 @@ elseif (! empty($module)) if (dol_is_file($dirins.'/'.$pathtohook)) { print ''.$pathtohook.''; - print ''.img_picto($langs->trans("Edit"), 'edit').''.img_picto($langs->trans("Delete"), 'delete').''.img_picto($langs->trans("Edit"), 'edit').''.img_picto($langs->trans("Delete"), 'delete').'
'; print ' '.$langs->trans("TriggersFile").' : '.$pathtofile.''; - print ''.img_picto($langs->trans("Edit"), 'edit').''.img_picto($langs->trans("Delete"), 'delete').''.img_picto($langs->trans("Edit"), 'edit').''.img_picto($langs->trans("Delete"), 'delete').'
'; print ' '.$langs->trans("NoTrigger"); - print '
'; @@ -2518,16 +2602,16 @@ elseif (! empty($module)) $pathtofile = $widget['relpath']; print ' '.$langs->trans("WidgetFile").' : '.$pathtofile.''; - print ' '.img_picto($langs->trans("Edit"), 'edit').''; + print ' '.img_picto($langs->trans("Edit"), 'edit').''; print ''; - print ''.img_picto($langs->trans("Delete"), 'delete').''; + print ''.img_picto($langs->trans("Delete"), 'delete').''; print ''; } } else { print ' '.$langs->trans("NoWidget"); - print ''; + print ''; print ''; } print ''; @@ -2605,15 +2689,15 @@ elseif (! empty($module)) $pathtofile = $clifile['relpath']; print ' '.$langs->trans("CLIFile").' : '.$pathtofile.''; - print ''.img_picto($langs->trans("Edit"), 'edit').''; - print ''.img_picto($langs->trans("Delete"), 'delete').''; + print ''.img_picto($langs->trans("Edit"), 'edit').''; + print ''.img_picto($langs->trans("Delete"), 'delete').''; print ''; } } else { print ' '.$langs->trans("NoCLIFile"); - print ''; + print ''; print ''; } print ''; @@ -2657,7 +2741,7 @@ elseif (! empty($module)) print '
'; print ' '.$langs->trans("DescriptorFile").' : '.$pathtofile.''; - print ' '.img_picto($langs->trans("Edit"), 'edit').''; + print ' '.img_picto($langs->trans("Edit"), 'edit').''; print '
'; print '
'; @@ -2786,8 +2870,8 @@ elseif (! empty($module)) if (preg_match('/\.md$/i', $spec['name'])) $format='markdown'; print ''; print ' '.$langs->trans("SpecificationFile").' : '.$pathtofile.''; - print ''.img_picto($langs->trans("Edit"), 'edit').''; - print ''.img_picto($langs->trans("Delete"), 'delete').''; + print ''.img_picto($langs->trans("Edit"), 'edit').''; + print ''.img_picto($langs->trans("Delete"), 'delete').''; print ''; } } @@ -2795,7 +2879,7 @@ elseif (! empty($module)) { print ''; print ' '.$langs->trans("FileNotYetGenerated"); - print ''; + print ''; print ''; } print ''; @@ -2880,6 +2964,9 @@ elseif (! empty($module)) if ($tab == 'buildpackage') { + print ''.$langs->trans("BuildPackageDesc").''; + print '
'; + if (! class_exists('ZipArchive') && ! defined('ODTPHP_PATHTOPCLZIP')) { print img_warning().' '.$langs->trans("ErrNoZipEngine"); diff --git a/htdocs/modulebuilder/template/class/api_mymodule.class.php b/htdocs/modulebuilder/template/class/api_mymodule.class.php index acf7f65454d..c37a0dba0e1 100644 --- a/htdocs/modulebuilder/template/class/api_mymodule.class.php +++ b/htdocs/modulebuilder/template/class/api_mymodule.class.php @@ -36,14 +36,6 @@ dol_include_once('/mymodule/class/myobject.class.php'); */ class MyModuleApi extends DolibarrApi { - /** - * @var array $FIELDS Mandatory fields, checked when create and update object - */ - static $FIELDS = array( - 'name', - ); - - /** * @var MyObject $myobject {@type MyObject} */ @@ -75,7 +67,7 @@ class MyModuleApi extends DolibarrApi */ public function get($id) { - if(! DolibarrApiAccess::$user->rights->myobject->read) { + if(! DolibarrApiAccess::$user->rights->mymodule->read) { throw new RestException(401); } @@ -84,8 +76,8 @@ class MyModuleApi extends DolibarrApi throw new RestException(404, 'MyObject not found'); } - if( ! DolibarrApi::_checkAccessToResource('myobject', $this->myobject->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + if( ! DolibarrApi::_checkAccessToResource('myobject', $this->myobject->id, 'mymodule_myobject')) { + throw new RestException(401, 'Access to instance id='.$this->myobject->id.' of object not allowed for login '.DolibarrApiAccess::$user->login); } return $this->_cleanObjectDatas($this->myobject); @@ -113,33 +105,37 @@ class MyModuleApi extends DolibarrApi global $db, $conf; $obj_ret = array(); + $tmpobject = new MyObject($db); + + if(! DolibarrApiAccess::$user->rights->bbb->read) { + throw new RestException(401); + } $socid = DolibarrApiAccess::$user->societe_id ? DolibarrApiAccess::$user->societe_id : ''; - $restictonsocid = 0; // Set to 1 if there is a field socid in table of object + $restrictonsocid = 0; // Set to 1 if there is a field socid in table of object // If the internal user must only see his customers, force searching by him $search_sale = 0; - if ($restictonsocid && ! DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) $search_sale = DolibarrApiAccess::$user->id; + if ($restrictonsocid && ! DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) $search_sale = DolibarrApiAccess::$user->id; $sql = "SELECT t.rowid"; - if ($restictonsocid && (!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) $sql .= ", sc.fk_soc, sc.fk_user"; // We need these fields in order to filter by sale (including the case where the user can only see his prospects) - $sql.= " FROM ".MAIN_DB_PREFIX."myobject_mytable as t"; + if ($restrictonsocid && (!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) $sql .= ", sc.fk_soc, sc.fk_user"; // We need these fields in order to filter by sale (including the case where the user can only see his prospects) + $sql.= " FROM ".MAIN_DB_PREFIX.$tmpobject->table_element." as t"; - if ($restictonsocid && (!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) $sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; // We need this table joined to the select in order to filter by sale + if ($restrictonsocid && (!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) $sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; // We need this table joined to the select in order to filter by sale $sql.= " WHERE 1 = 1"; // Example of use $mode //if ($mode == 1) $sql.= " AND s.client IN (1, 3)"; //if ($mode == 2) $sql.= " AND s.client IN (2, 3)"; - $tmpobject = new MyObject($db); if ($tmpobject->ismultientitymanaged) $sql.= ' AND t.entity IN ('.getEntity('myobject').')'; - if ($restictonsocid && (!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) $sql.= " AND t.fk_soc = sc.fk_soc"; - if ($restictonsocid && $socid) $sql.= " AND t.fk_soc = ".$socid; - if ($restictonsocid && $search_sale > 0) $sql.= " AND t.rowid = sc.fk_soc"; // Join for the needed table to filter by sale + if ($restrictonsocid && (!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) $sql.= " AND t.fk_soc = sc.fk_soc"; + if ($restrictonsocid && $socid) $sql.= " AND t.fk_soc = ".$socid; + if ($restrictonsocid && $search_sale > 0) $sql.= " AND t.rowid = sc.fk_soc"; // Join for the needed table to filter by sale // Insert sale filter - if ($restictonsocid && $search_sale > 0) { + if ($restrictonsocid && $search_sale > 0) { $sql .= " AND sc.fk_user = ".$search_sale; } if ($sqlfilters) @@ -176,7 +172,7 @@ class MyModuleApi extends DolibarrApi } } else { - throw new RestException(503, 'Error when retrieve myobject list'); + throw new RestException(503, 'Error when retrieving myobject list: '.$db->lasterror()); } if( ! count($obj_ret)) { throw new RestException(404, 'No myobject found'); @@ -194,7 +190,7 @@ class MyModuleApi extends DolibarrApi */ public function post($request_data = null) { - if(! DolibarrApiAccess::$user->rights->myobject->create) { + if(! DolibarrApiAccess::$user->rights->mymodule->write) { throw new RestException(401); } // Check mandatory fields @@ -220,7 +216,7 @@ class MyModuleApi extends DolibarrApi */ public function put($id, $request_data = null) { - if(! DolibarrApiAccess::$user->rights->myobject->create) { + if(! DolibarrApiAccess::$user->rights->mymodule->write) { throw new RestException(401); } @@ -229,8 +225,8 @@ class MyModuleApi extends DolibarrApi throw new RestException(404, 'MyObject not found'); } - if( ! DolibarrApi::_checkAccessToResource('myobject', $this->myobject->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + if( ! DolibarrApi::_checkAccessToResource('myobject', $this->myobject->id, 'mymodule_myobject')) { + throw new RestException(401, 'Access to instance id='.$this->myobject->id.' of object not allowed for login '.DolibarrApiAccess::$user->login); } foreach($request_data as $field => $value) { @@ -254,11 +250,11 @@ class MyModuleApi extends DolibarrApi * @param int $id MyObject ID * @return array * - * @url DELETE myobject/{id} + * @url DELETE myobjects/{id} */ public function delete($id) { - if (! DolibarrApiAccess::$user->rights->myobject->delete) { + if (! DolibarrApiAccess::$user->rights->mymodule->delete) { throw new RestException(401); } $result = $this->myobject->fetch($id); @@ -266,8 +262,8 @@ class MyModuleApi extends DolibarrApi throw new RestException(404, 'MyObject not found'); } - if (! DolibarrApi::_checkAccessToResource('myobject', $this->myobject->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + if (! DolibarrApi::_checkAccessToResource('myobject', $this->myobject->id, 'mymodule_myobject')) { + throw new RestException(401, 'Access to instance id='.$this->myobject->id.' of object not allowed for login '.DolibarrApiAccess::$user->login); } if (! $this->myobject->delete(DolibarrApiAccess::$user)) @@ -317,7 +313,8 @@ class MyModuleApi extends DolibarrApi private function _validate($data) { $myobject = array(); - foreach (MyObjectApi::$FIELDS as $field) { + foreach ($this->myobject->fields as $field => $propfield) { + if (in_array($field, array('rowid', 'entity', 'date_creation', 'tms', 'fk_user_creat')) || $propfield['notnull'] != 1) continue; // Not a mandatory field if (!isset($data[$field])) throw new RestException(400, "$field field missing"); $myobject[$field] = $data[$field]; diff --git a/htdocs/modulebuilder/template/core/modules/modMyModule.class.php b/htdocs/modulebuilder/template/core/modules/modMyModule.class.php index 8a11a6c87b4..2dd29d10195 100644 --- a/htdocs/modulebuilder/template/core/modules/modMyModule.class.php +++ b/htdocs/modulebuilder/template/core/modules/modMyModule.class.php @@ -170,6 +170,7 @@ class modMyModule extends DolibarrModules // 'stock' to add a tab in stock view // 'thirdparty' to add a tab in third party view // 'user' to add a tab in user view + // Dictionaries $this->dictionaries=array(); /* Example: @@ -195,6 +196,7 @@ class modMyModule extends DolibarrModules 'tabcond'=>array($conf->mymodule->enabled,$conf->mymodule->enabled,$conf->mymodule->enabled) ); */ + // Boxes/Widgets // Add here list of php file(s) stored in mymodule/core/boxes that contains class to show a widget. $this->boxes = array( @@ -206,6 +208,7 @@ class modMyModule extends DolibarrModules //1=>array('file'=>'mymodulewidget2.php@mymodule','note'=>'Widget provided by MyModule'), //2=>array('file'=>'mymodulewidget3.php@mymodule','note'=>'Widget provided by MyModule') ); + // Cronjobs (List of cron jobs entries to add when module is enabled) // unit_frequency must be 60 for minute, 3600 for hour, 86400 for day, 604800 for week $this->cronjobs = array( @@ -228,26 +231,28 @@ class modMyModule extends DolibarrModules // 0=>array('label'=>'My label', 'jobtype'=>'method', 'class'=>'/dir/class/file.class.php', 'objectname'=>'MyClass', 'method'=>'myMethod', 'parameters'=>'param1, param2', 'comment'=>'Comment', 'frequency'=>2, 'unitfrequency'=>3600, 'status'=>0, 'test'=>'$conf->mymodule->enabled', 'priority'=>50), // 1=>array('label'=>'My label', 'jobtype'=>'command', 'command'=>'', 'parameters'=>'param1, param2', 'comment'=>'Comment', 'frequency'=>1, 'unitfrequency'=>3600*24, 'status'=>0, 'test'=>'$conf->mymodule->enabled', 'priority'=>50) // ); + // Permissions $this->rights = array(); // Permission array used by this module $r=0; $this->rights[$r][0] = $this->numero + $r; // Permission id (must not be already used) - $this->rights[$r][1] = 'Read myobject of MyModule'; // Permission label + $this->rights[$r][1] = 'Read objects of MyModule'; // Permission label $this->rights[$r][3] = 1; // Permission by default for new user (0/1) $this->rights[$r][4] = 'read'; // In php code, permission will be checked by test if ($user->rights->mymodule->level1->level2) $this->rights[$r][5] = ''; // In php code, permission will be checked by test if ($user->rights->mymodule->level1->level2) $r++; $this->rights[$r][0] = $this->numero + $r; // Permission id (must not be already used) - $this->rights[$r][1] = 'Create/Update myobject of MyModule'; // Permission label + $this->rights[$r][1] = 'Create/Update objects of MyModule'; // Permission label $this->rights[$r][3] = 1; // Permission by default for new user (0/1) $this->rights[$r][4] = 'write'; // In php code, permission will be checked by test if ($user->rights->mymodule->level1->level2) $this->rights[$r][5] = ''; // In php code, permission will be checked by test if ($user->rights->mymodule->level1->level2) $r++; $this->rights[$r][0] = $this->numero + $r; // Permission id (must not be already used) - $this->rights[$r][1] = 'Delete myobject of MyModule'; // Permission label + $this->rights[$r][1] = 'Delete objects of MyModule'; // Permission label $this->rights[$r][3] = 1; // Permission by default for new user (0/1) $this->rights[$r][4] = 'delete'; // In php code, permission will be checked by test if ($user->rights->mymodule->level1->level2) $this->rights[$r][5] = ''; // In php code, permission will be checked by test if ($user->rights->mymodule->level1->level2) + // Main menu entries $this->menu = array(); // List of menus to add $r=0; @@ -298,6 +303,7 @@ class modMyModule extends DolibarrModules 'user'=>2, // 0=Menu for internal users, 1=external users, 2=both ); END MODULEBUILDER LEFTMENU MYOBJECT */ + // Exports $r=1; /* BEGIN MODULEBUILDER EXPORT MYOBJECT */ @@ -317,6 +323,26 @@ class modMyModule extends DolibarrModules $this->export_sql_end[$r] .=' AND t.entity IN ('.getEntity('myobject').')'; $r++; */ /* END MODULEBUILDER EXPORT MYOBJECT */ + + // Imports + $r=1; + /* BEGIN MODULEBUILDER IMPORT MYOBJECT */ + /* + $langs->load("mymodule@mymodule"); + $this->export_code[$r]=$this->rights_class.'_'.$r; + $this->export_label[$r]='MyObjectLines'; // Translation key (used only if key ExportDataset_xxx_z not found) + $this->export_icon[$r]='myobject@mymodule'; + $keyforclass = 'MyObject'; $keyforclassfile='/mymobule/class/myobject.class.php'; $keyforelement='myobject'; + include DOL_DOCUMENT_ROOT.'/core/commonfieldsinexport.inc.php'; + $keyforselect='myobject'; $keyforaliasextra='extra'; $keyforelement='myobject'; + include DOL_DOCUMENT_ROOT.'/core/extrafieldsinexport.inc.php'; + //$this->export_dependencies_array[$r]=array('mysubobject'=>'ts.rowid', 't.myfield'=>array('t.myfield2','t.myfield3')); // To force to activate one or several fields if we select some fields that need same (like to select a unique key if we ask a field of a child to avoid the DISTINCT to discard them, or for computed field than need several other fields) + $this->export_sql_start[$r]='SELECT DISTINCT '; + $this->export_sql_end[$r] =' FROM '.MAIN_DB_PREFIX.'myobject as t'; + $this->export_sql_end[$r] .=' WHERE 1 = 1'; + $this->export_sql_end[$r] .=' AND t.entity IN ('.getEntity('myobject').')'; + $r++; */ + /* END MODULEBUILDER IMPORT MYOBJECT */ } /** * Function called when module is enabled. diff --git a/htdocs/modulebuilder/template/core/triggers/interface_99_modMyModule_MyModuleTriggers.class.php b/htdocs/modulebuilder/template/core/triggers/interface_99_modMyModule_MyModuleTriggers.class.php index 4388c6399db..1718a6a72d5 100644 --- a/htdocs/modulebuilder/template/core/triggers/interface_99_modMyModule_MyModuleTriggers.class.php +++ b/htdocs/modulebuilder/template/core/triggers/interface_99_modMyModule_MyModuleTriggers.class.php @@ -97,7 +97,7 @@ class InterfaceMyModuleTriggers extends DolibarrTriggers */ public function runTrigger($action, $object, User $user, Translate $langs, Conf $conf) { - if (empty($conf->mymodule->enabled)) return 0; // Module not active, we do nothing + if (empty($conf->mymodule->enabled)) return 0; // If module is not enabled, we do nothing // Put here code you want to execute when a Dolibarr business events occurs. // Data and type of action are stored into $object and $action @@ -302,7 +302,9 @@ class InterfaceMyModuleTriggers extends DolibarrTriggers //case 'SHIPPING_CLOSED': //case 'SHIPPING_REOPEN': //case 'SHIPPING_DELETE': - // break; + + // and more... + default: dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); break;