* Copyright (C) 2018-2019 Nicolas ZABOURI * Copyright (C) 2023 Alexandre Janniaux * Copyright (C) 2024-2026 MDW * Copyright (C) 2024-2026 Frédéric France * * 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 . * * You can also make a direct call the page with parameter like this: * htdocs/modulebuilder/index.php?module=Inventory@/pathtodolibarr/htdocs/product */ /** * \file htdocs/modulebuilder/index.php * \brief Home page for module builder module * * You can add parameter dirins=/home/ldestailleur/git/dolibarr/htdocs/mymodule to force generation of module * into the dirins directory. */ if (!defined('NOSCANPOSTFORINJECTION')) { define('NOSCANPOSTFORINJECTION', '1'); // Do not check anti SQL+XSS injection attack test } // Load Dolibarr environment require '../main.inc.php'; /** * @var Conf $conf * @var DoliDB $db * @var HookManager $hookmanager * @var Societe $mysoc * @var Translate $langs * @var User $user * * @var string $dolibarr_main_document_root * @var string $dolibarr_main_document_root_alt */ ' @phan-var-force string $dolibarr_main_document_root @phan-var-force string $dolibarr_main_document_root_alt '; 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/class/html.formadmin.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/modulebuilder.lib.php'; require_once DOL_DOCUMENT_ROOT.'/modulebuilder/class/NamingContractValidator.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/utils.class.php'; // Load translation files required by the page $langs->loadLangs(array("admin", "modulebuilder", "exports", "other", "cron", "errors", "uxdocumentation")); // GET Parameters $action = GETPOST('action', 'aZ09'); $confirm = GETPOST('confirm', 'alpha'); $cancel = GETPOST('cancel', 'alpha'); $sortfield = GETPOST('sortfield', 'aZ09comma'); $sortorder = GETPOST('sortorder', 'aZ09'); $module = (string) GETPOST('module', 'alpha'); $tab = (string) GETPOST('tab', 'aZ09'); $tabobj = GETPOST('tabobj', 'alpha'); $tabdic = GETPOST('tabdic', 'alpha'); $propertykey = GETPOST('propertykey', 'alpha'); if (empty($module)) { $module = 'initmodule'; } if (empty($tab)) { $tab = 'description'; } '@phan-var-force string $tab'; // Workaround 'empty()' bug of phan if (empty($tabobj)) { $tabobj = 'newobjectifnoobj'; } if (empty($tabdic)) { $tabdic = 'newdicifnodic'; } $file = GETPOST('file', 'alpha'); $find = GETPOST('find', 'alpha'); $modulename = dol_sanitizeFileName(GETPOST('modulename', 'alpha')); $objectname = dol_sanitizeFileName(GETPOST('objectname', 'alpha')); $dicname = dol_sanitizeFileName(GETPOST('dicname', 'alpha')); $editorname = (string) GETPOST('editorname', 'alpha'); $editorurl = (string) GETPOST('editorurl', 'alpha'); $version = (string) GETPOST('version', 'alpha'); $family = (string) GETPOST('family', 'alpha'); $picto = (string) GETPOST('idpicto', 'alpha'); $idmodule = (string) GETPOST('idmodule', 'alpha'); $format = ''; // Prevent undefined in css tab // Security check if (!isModEnabled('modulebuilder')) { accessforbidden('Module ModuleBuilder not enabled'); } if (!$user->hasRight("modulebuilder", "run")) { // after this test $user->hasRight("modulebuilder", "run") is always true, no need to check it more accessforbidden('ModuleBuilderNotAllowed'); } // Dir for custom dirs $tmp = explode(',', $dolibarr_main_document_root_alt); $dirins = $tmp[0]; $dirread = $dirins; $forceddirread = 0; $tmpdir = explode('@', $module); if (!empty($tmpdir[1])) { $module = $tmpdir[0]; $dirread = $tmpdir[1]; $forceddirread = 1; } if (GETPOST('dirins', 'alpha')) { $dirread = $dirins = GETPOST('dirins', 'alpha'); $forceddirread = 1; } $FILEFLAG = 'modulebuilder.txt'; $now = dol_now(); $newmask = 0; if (empty($newmask) && getDolGlobalString('MAIN_UMASK')) { $newmask = getDolGlobalString('MAIN_UMASK'); } if (empty($newmask)) { // This should no happen $newmask = '0664'; } $result = restrictedArea($user, 'modulebuilder', 0); $error = 0; $param = ''; $form = new Form($db); // Define $listofmodules $dirsrootforscan = array($dirread); // Add also the core modules into the list of modules to show/edit if ($dirread != DOL_DOCUMENT_ROOT && (getDolGlobalInt('MAIN_FEATURES_LEVEL') >= 2 || getDolGlobalString('MODULEBUILDER_ADD_DOCUMENT_ROOT'))) { $dirsrootforscan[] = DOL_DOCUMENT_ROOT; } // Search modules to edit $textforlistofdirs = ''."\n"; $listofmodules = array(); '@phan-var-force array $listofmodules'; $i = 0; foreach ($dirsrootforscan as $tmpdirread) { $moduletype = 'external'; if ($tmpdirread == DOL_DOCUMENT_ROOT) { $moduletype = 'internal'; } $dirsincustom = dol_dir_list($tmpdirread, 'directories'); if (is_array($dirsincustom) && count($dirsincustom) > 0) { foreach ($dirsincustom as $dircustomcursor) { $fullname = $dircustomcursor['fullname']; if (dol_is_file($fullname.'/'.$FILEFLAG)) { // Get real name of module (MyModule instead of mymodule) $dirtoscanrel = basename($fullname).'/core/modules/'; $descriptorfiles = dol_dir_list(dirname($fullname).'/'.$dirtoscanrel, 'files', 0, 'mod.*\.class\.php$'); if (empty($descriptorfiles)) { // If descriptor not found into module dir, we look into main module dir. $dirtoscanrel = 'core/modules/'; $descriptorfiles = dol_dir_list($fullname.'/../'.$dirtoscanrel, 'files', 0, 'mod'.strtoupper(basename($fullname)).'\.class\.php$'); } $modulenamewithcase = ''; $moduledescriptorrelpath = ''; $moduledescriptorfullpath = ''; foreach ($descriptorfiles as $descriptorcursor) { $modulenamewithcase = preg_replace('/^mod/', '', $descriptorcursor['name']); $modulenamewithcase = preg_replace('/\.class\.php$/', '', $modulenamewithcase); $moduledescriptorrelpath = $dirtoscanrel.$descriptorcursor['name']; $moduledescriptorfullpath = $descriptorcursor['fullname']; //var_dump($descriptorcursor); } if ($modulenamewithcase) { $listofmodules[$dircustomcursor['name']] = array( 'modulenamewithcase' => $modulenamewithcase, 'moduledescriptorrelpath' => $moduledescriptorrelpath, 'moduledescriptorfullpath' => $moduledescriptorfullpath, 'moduledescriptorrootpath' => $tmpdirread, 'moduletype' => $moduletype ); } //var_dump($listofmodules); } } } if ($forceddirread && empty($listofmodules)) { // $forceddirread is 1 if we forced dir to read with dirins=... or with module=...@mydir $listofmodules[strtolower($module)] = array( 'modulenamewithcase' => $module, 'moduledescriptorrelpath' => 'notyetimplemented', 'moduledescriptorfullpath' => 'notyetimplemented', 'moduledescriptorrootpath' => 'notyetimplemented', ); } // Show description of content $newdircustom = $dirins; if (empty($newdircustom)) { $newdircustom = img_warning(); } // If dirread was forced to somewhere else, by using URL // htdocs/modulebuilder/index.php?module=Inventory@/home/ldestailleur/git/dolibarr/htdocs/product if (empty($i)) { $textforlistofdirs .= $langs->trans("DirScanned").' : '; } else { $textforlistofdirs .= ', '; } $textforlistofdirs .= ''.$tmpdirread.''; if ($tmpdirread == DOL_DOCUMENT_ROOT) { if (getDolGlobalInt('MAIN_FEATURES_LEVEL') >= 2) { $textforlistofdirs .= $form->textwithpicto('', $langs->trans("ConstantIsOn", "MAIN_FEATURES_LEVEL")); } if (getDolGlobalString('MODULEBUILDER_ADD_DOCUMENT_ROOT')) { $textforlistofdirs .= $form->textwithpicto('', $langs->trans("ConstantIsOn", "MODULEBUILDER_ADD_DOCUMENT_ROOT")); } } $i++; } /** * Add management to catch fatal errors - shutdown handler * * @return void */ function moduleBuilderShutdownFunction() { $error = error_get_last(); if ($error && ($error['type'] & (E_ERROR | E_PARSE | E_CORE_ERROR | E_COMPILE_ERROR | E_USER_ERROR))) { // Handle the fatal error echo "Fatal error occurred: {$error['message']} in {$error['file']} on line {$error['line']}"; // If a header was already send, we suppose it is the llx_Header() so we call the llxFooter() if (headers_sent()) { llxFooter(); } } } register_shutdown_function("moduleBuilderShutdownFunction"); /** * Produce copyright replacement string for user * * @param User $user User to produce the copyright notice for. * @param Translate $langs Translation object to use. * @param int $now Date for which the copyright will be generated. * * @return string String to be used as replacement after Copyright (C) */ function getLicenceHeader($user, $langs, $now) { $licInfo = $user->getFullName($langs); $emailTabs = str_repeat("\t", (int) (max(0, (31 - mb_strlen($licInfo)) / 4))); $licInfo .= ($user->email ? $emailTabs.'<'.$user->email.'>' : ''); $licInfo = dol_print_date($now, '%Y')."\t\t".$licInfo; return $licInfo; } /* * Actions */ /** * Post-generation validation -- logs and displays a warning if residual myobject/mymodule tokens remain. * * @param string $destfile Path to the generated file * @param NamingContract $nc Contract used for generation * @return void No return value, warnings reported as event messages */ function modulebuilderValidateGeneratedFile(string $destfile, NamingContract $nc): void { $content = file_get_contents($destfile); if ($content === false) { return; } $validator = new StrictNamingContractValidator(); $errors = $validator->validateContent($content, $destfile); if (!empty($errors)) { dol_syslog( 'ModuleBuilder NamingContract validation warning in ' . $destfile . ': ' . implode('; ', array_slice($errors, 0, 3)), LOG_WARNING ); $safeErrors = array_map('dol_escape_htmltag', array_slice($errors, 0, 5)); setEventMessages(implode('
', $safeErrors), null, 'warnings'); } } if ($dirins && $action == 'initmodule' && $modulename) { // Test on permission already done $modulename = dol_string_nounprintableascii(dol_string_unaccent(ucwords($modulename))); // Force first letter in uppercase $destdir = '/not_set/'; $ncModule = new NamingContract($modulename); if (preg_match('/[^a-z0-9]/i', $modulename)) { $error++; setEventMessages($langs->trans("SpaceOrSpecialCharAreNotAllowed"), null, 'errors'); } if (!$error) { $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template'; $destdir = $dirins.'/'.strtolower($modulename); $arrayreplacement = [ 'mymodule' => $ncModule->moduleNameLower, 'MyModule' => $ncModule->moduleNameCase, ]; $result = dolCopyDir($srcdir, $destdir, '0', 0, $arrayreplacement); //dol_mkdir($destfile); if ($result <= 0) { 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'); } } // Copy last 'html.formsetup.class.php' to backport folder if (getDolGlobalInt('MODULEBUILDER_SUPPORT_COMPATIBILITY_V16')) { $tryToCopyFromSetupClass = true; $backportDest = $destdir .'/backport/v16/core/class'; $backportFileSrc = DOL_DOCUMENT_ROOT.'/core/class/html.formsetup.class.php'; $backportFileDest = $backportDest.'/html.formsetup.class.php'; $result = dol_mkdir($backportDest); if ($result < 0) { $error++; $langs->load("errors"); setEventMessages($langs->trans("ErrorFailToCreateDir", $backportDest), null, 'errors'); $tryToCopyFromSetupClass = false; } if ($tryToCopyFromSetupClass) { $result = dol_copy($backportFileSrc, $backportFileDest); if ($result <= 0) { if ($result < 0) { $error++; $langs->load("errors"); setEventMessages($langs->trans("ErrorFailToCopyFile", $backportFileSrc, $backportFileDest), null, 'errors'); } else { setEventMessages($langs->trans("FileDidAlreadyExist", $backportFileDest), null, 'warnings'); } } } } if (getDolGlobalString('MODULEBUILDER_USE_ABOUT')) { dol_delete_file($destdir.'/admin/about.php'); } // Delete dir and files that can be generated in sub tabs later if we need them (we want a minimal module first) dol_delete_dir_recursive($destdir.'/ajax'); dol_delete_dir_recursive($destdir.'/build/doxygen'); dol_delete_dir_recursive($destdir.'/core/modules/mailings'); dol_delete_dir_recursive($destdir.'/core/modules/'.strtolower($modulename)); dol_delete_dir_recursive($destdir.'/core/tpl'); dol_delete_dir_recursive($destdir.'/core/triggers'); dol_delete_dir_recursive($destdir.'/doc'); //dol_delete_dir_recursive($destdir.'/.tx'); dol_delete_dir_recursive($destdir.'/core/boxes'); dol_delete_file($destdir.'/admin/myobject_extrafields.php'); dol_delete_file($destdir.'/class/actions_'.strtolower($modulename).'.class.php'); dol_delete_file($destdir.'/class/api_'.strtolower($modulename).'.class.php'); dol_delete_file($destdir.'/css/'.strtolower($modulename).'.css.php'); dol_delete_file($destdir.'/js/'.strtolower($modulename).'.js.php'); dol_delete_file($destdir.'/scripts/'.strtolower($modulename).'.php'); dol_delete_file($destdir.'/sql/data.sql'); dol_delete_file($destdir.'/sql/update_x.x.x-y.y.y.sql'); // 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_contact.php'); dol_delete_file($destdir.'/myobject_note.php'); dol_delete_file($destdir.'/myobject_document.php'); dol_delete_file($destdir.'/myobject_agenda.php'); dol_delete_file($destdir.'/myobject_list.php'); dol_delete_file($destdir.'/lib/'.strtolower($modulename).'_myobject.lib.php'); dol_delete_file($destdir.'/test/phpunit/functional/'.$modulename.'FunctionalTest.php'); dol_delete_file($destdir.'/test/phpunit/MyObjectTest.php'); dol_delete_file($destdir.'/sql/llx_'.strtolower($modulename).'_myobject.sql'); dol_delete_file($destdir.'/sql/llx_'.strtolower($modulename).'_myobject_extrafields.sql'); dol_delete_file($destdir.'/sql/llx_'.strtolower($modulename).'_myobject.key.sql'); dol_delete_file($destdir.'/sql/llx_'.strtolower($modulename).'_myobject_extrafields.key.sql'); dol_delete_file($destdir.'/class/myobject.class.php'); dol_delete_file($destdir.'/class/myobjectstats.class.php'); dol_delete_dir($destdir.'/class', 1); dol_delete_dir($destdir.'/css', 1); dol_delete_dir($destdir.'/js', 1); dol_delete_dir($destdir.'/scripts', 1); dol_delete_dir($destdir.'/sql', 1); dol_delete_dir($destdir.'/test/phpunit/functionnal', 1); dol_delete_dir($destdir.'/test/phpunit', 1); dol_delete_dir($destdir.'/test', 1); } // Edit PHP files if (!$error) { $listofphpfilestoedit = dol_dir_list($destdir, 'files', 1, '\.(php|MD|js|sql|txt|xml|lang)$', '', 'fullname', SORT_ASC, 0, 1); $licInfo = getLicenceHeader($user, $langs, $now); foreach ($listofphpfilestoedit as $phpfileval) { //var_dump($phpfileval['fullname']); $arrayreplacement = array_merge( $ncModule->getSubstitutionMap(), [ 'htdocs/modulebuilder/template' => $ncModule->moduleNameLower, '---Put here your own copyright and developer email---' => $licInfo, '---Replace with your own copyright and developer email---' => $licInfo, 'Editor name' => $editorname, 'https://www.example.com' => $editorurl, '$this->version = \'1.0\'' => '$this->version = \'' . $version . '\'', '$this->picto = \'generic\';' => (empty($picto)) ? '$this->picto = \'generic\'' : '$this->picto = \'' . $picto . '\';', 'modulefamily' => $family, // Key '500000' would be cast to int(500000) by PHP, then renumbered to 0 by // array_merge -- causing str_replace to search for '0' instead of '500000'. // Use a string key that matches the exact assignment line to avoid this. '$this->numero = 500000' => '$this->numero = '.$idmodule, ] ); if (getDolGlobalString('MODULEBUILDER_SPECIFIC_AUTHOR')) { $arrayreplacement['---Replace with your own copyright and developer email---'] = dol_print_date($now, '%Y')."\t\t" . getDolGlobalString('MODULEBUILDER_SPECIFIC_AUTHOR'); } // @phan-suppress-next-line PhanPluginSuspiciousParamPosition $result = dolReplaceInFile($phpfileval['fullname'], $arrayreplacement); // @phpstan-ignore-line //var_dump($result); if ($result < 0) { setEventMessages($langs->trans("ErrorFailToMakeReplacementInto", $phpfileval['fullname']), null, 'errors'); } } if (getDolGlobalString('MODULEBUILDER_SPECIFIC_README')) { setEventMessages($langs->trans("ContentOfREADMECustomized"), null, 'warnings'); dol_delete_file($destdir.'/README.md'); file_put_contents($destdir.'/README.md', getDolGlobalString("MODULEBUILDER_SPECIFIC_README")); dolChmod($destdir.'/README.md'); } // for create file to add properties // file_put_contents($destdir.'/'.strtolower($modulename).'propertycard.php',''); // $srcFileCard = DOL_DOCUMENT_ROOT.'/modulebuilder/card.php'; // $destFileCard = $dirins.'/'.strtolower($modulename).'/template/card.php'; // dol_copy($srcFileCard, $destdir.'/'.strtolower($modulename).'propertycard.php', '0',1, $arrayreplacement); } if (!$error) { setEventMessages($langs->trans('ModuleInitialized', $destdir), null); $module = $modulename; clearstatcache(true); if (function_exists('opcache_invalidate')) { opcache_reset(); // remove the include cache hell ! } header("Location: ".$_SERVER["PHP_SELF"].'?module='.$modulename); exit; } } $destdir = '/not_set/'; // Initialize (for static analysis) $destfile = '/not_set/'; // Initialize (for static analysis) $srcfile = '/not_set/'; // Initialize (for static analysis) // init API, PHPUnit if ($dirins && in_array($action, array('initapi', 'initphpunit', 'initpagecontact', 'initpagedocument', 'initpagenote', 'initpageagenda')) && !empty($module) /* && $user->hasRight("modulebuilder", "run") // already checked */) { $modulename = ucfirst($module); // Force first letter in uppercase $objectname = $tabobj; $varnametoupdate = ''; $dirins = $listofmodules[strtolower($module)]['moduledescriptorrootpath']; $destdir = $dirins.'/'.strtolower($module); // Get list of existing objects $objects = dolGetListOfObjectClasses($destdir); if ($action == 'initapi') { // Test on permission already done if (file_exists($dirins.'/'.strtolower($module).'/class/api_'.strtolower($module).'.class.php')) { $result = dol_copy(DOL_DOCUMENT_ROOT.'/modulebuilder/template/class/api_mymodule.class.php', $dirins.'/'.strtolower($module).'/class/api_'.strtolower($module).'.class.php', '0', 1); } 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'; } elseif ($action == 'initphpunit') { // Test on permission already done dol_mkdir($dirins.'/'.strtolower($module).'/test/phpunit'); $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template'; $srcfile = $srcdir.'/test/phpunit/MyObjectTest.php'; $destfile = $dirins.'/'.strtolower($module).'/test/phpunit/'.strtolower($objectname).'Test.php'; } elseif ($action == 'initpagecontact') { // Test on permission already done dol_mkdir($dirins.'/'.strtolower($module)); $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template'; $srcfile = $srcdir.'/myobject_contact.php'; $destfile = $dirins.'/'.strtolower($module).'/'.strtolower($objectname).'_contact.php'; $varnametoupdate = 'showtabofpagecontact'; } elseif ($action == 'initpagedocument') { // Test on permission already done dol_mkdir($dirins.'/'.strtolower($module)); $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template'; $srcfile = $srcdir.'/myobject_document.php'; $destfile = $dirins.'/'.strtolower($module).'/'.strtolower($objectname).'_document.php'; $varnametoupdate = 'showtabofpagedocument'; } elseif ($action == 'initpagenote') { // Test on permission already done dol_mkdir($dirins.'/'.strtolower($module)); $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template'; $srcfile = $srcdir.'/myobject_note.php'; $destfile = $dirins.'/'.strtolower($module).'/'.strtolower($objectname).'_note.php'; $varnametoupdate = 'showtabofpagenote'; } elseif ($action == 'initpageagenda') { // Test on permission already done dol_mkdir($dirins.'/'.strtolower($module)); $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template'; $srcfile = $srcdir.'/myobject_agenda.php'; $destfile = $dirins.'/'.strtolower($module).'/'.strtolower($objectname).'_agenda.php'; $varnametoupdate = 'showtabofpageagenda'; } if (!file_exists($destfile)) { $result = dol_copy($srcfile, $destfile, '0', 0); } if ($result > 0) { //var_dump($phpfileval['fullname']); try { $ncApiObj = new NamingContract($modulename, $objectname); } catch (\InvalidArgumentException $e) { $error++; setEventMessages($langs->trans("SpaceOrSpecialCharAreNotAllowed"), null, 'errors'); $ncApiObj = null; } if (!$error && $ncApiObj !== null) { $arrayreplacement = array_merge( $ncApiObj->getSubstitutionMap(), [ 'htdocs/modulebuilder/template' => $ncApiObj->moduleNameLower, '---Replace with your own copyright and developer email---' => getLicenceHeader($user, $langs, $now), ] ); if ($action == 'initapi') { // Test on permission already done if (count($objects) >= 1) { addObjectsToApiFile($srcfile, $destfile, $objects, $modulename); } // Fix PHPDoc header and class-declaration residuals left by addObjectsToApiFile. // 'MYOBJECT' (uppercase) is excluded to preserve the /* BEGIN MODULEBUILDER API MYOBJECT */ // placeholder that addObjectsToApiFile keeps for future object additions. $headerFix = $arrayreplacement; unset($headerFix['MYOBJECT']); // @phan-suppress-next-line PhanPluginSuspiciousParamPosition dolReplaceInFile($destfile, $headerFix); modulebuilderValidateGeneratedFile($destfile, $ncApiObj); } else { // @phan-suppress-next-line PhanPluginSuspiciousParamPosition dolReplaceInFile($destfile, $arrayreplacement); modulebuilderValidateGeneratedFile($destfile, $ncApiObj); } } if ($varnametoupdate) { // Now we update the object file to set $$varnametoupdate to 1 $srcfile = $dirins.'/'.strtolower($module).'/lib/'.strtolower($module).'_'.strtolower($objectname).'.lib.php'; $arrayreplacement = array('/\$'.preg_quote($varnametoupdate, '/').' = 0;/' => '$'.$varnametoupdate.' = 1;'); // @phan-suppress-next-line PhanPluginSuspiciousParamPosition dolReplaceInFile($srcfile, $arrayreplacement, '', '0', 0, 1); } } else { $langs->load("errors"); setEventMessages($langs->trans('ErrorFailToCreateFile', $destfile), null, 'errors'); } } // init ExtraFields if ($dirins && $action == 'initsqlextrafields' && !empty($module) /* && $user->hasRight("modulebuilder", "run") // already checked */) { $modulename = ucfirst($module); // Force first letter in uppercase $objectname = $tabobj; dol_mkdir($dirins.'/'.strtolower($module).'/sql'); $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template'; $srcfile1 = $srcdir.'/sql/llx_mymodule_myobject_extrafields.sql'; $destfile1 = $dirins.'/'.strtolower($module).'/sql/llx_'.strtolower($module).'_'.strtolower($objectname).'_extrafields.sql'; $result1 = dol_copy($srcfile1, $destfile1, '0', 0); $srcfile2 = $srcdir.'/sql/llx_mymodule_myobject_extrafields.key.sql'; $destfile2 = $dirins.'/'.strtolower($module).'/sql/llx_'.strtolower($module).'_'.strtolower($objectname).'_extrafields.key.sql'; $result2 = dol_copy($srcfile2, $destfile2, '0', 0); if ($result1 > 0 && $result2 > 0) { $modulename = ucfirst($module); // Force first letter in uppercase //var_dump($phpfileval['fullname']); try { $ncSqlObj = new NamingContract($modulename, $objectname); } catch (\InvalidArgumentException $e) { $error++; setEventMessages($langs->trans("SpaceOrSpecialCharAreNotAllowed"), null, 'errors'); $ncSqlObj = null; } if (!$error && $ncSqlObj !== null) { $arrayreplacement = array_merge( $ncSqlObj->getSubstitutionMap(), [ 'htdocs/modulebuilder/template' => $ncSqlObj->moduleNameLower, '---Replace with your own copyright and developer email---' => getLicenceHeader($user, $langs, $now), ] ); dolReplaceInFile($destfile1, $arrayreplacement); dolReplaceInFile($destfile2, $arrayreplacement); modulebuilderValidateGeneratedFile($destfile1, $ncSqlObj); modulebuilderValidateGeneratedFile($destfile2, $ncSqlObj); } } else { $langs->load("errors"); if ($result1 <= 0) { setEventMessages($langs->trans('ErrorFailToCreateFile', $destfile1), null, 'errors'); } if ($result2 <= 0) { setEventMessages($langs->trans('ErrorFailToCreateFile', $destfile2), null, 'errors'); } } // Now we update the object file to set $this->isextrafieldmanaged to 1 $srcfile = $dirins.'/'.strtolower($module).'/class/'.strtolower($objectname).'.class.php'; $arrayreplacement = array('/\$this->isextrafieldmanaged = 0;/' => '$this->isextrafieldmanaged = 1;'); $arrayreplacement = array('/\$isextrafieldmanaged = 0;/' => '$isextrafieldmanaged = 1;'); dolReplaceInFile($srcfile, $arrayreplacement, '', '0', 0, 1); } // init Hook if ($dirins && $action == 'inithook' && !empty($module) /* && $user->hasRight("modulebuilder", "run") // already checked */) { dol_mkdir($dirins.'/'.strtolower($module).'/class'); $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template'; $srcfile = $srcdir.'/class/actions_mymodule.class.php'; $destfile = $dirins.'/'.strtolower($module).'/class/actions_'.strtolower($module).'.class.php'; $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), '---Replace with your own copyright and developer email---' => getLicenceHeader($user, $langs, $now) ); // @phan-suppress-next-line PhanPluginSuspiciousParamPosition dolReplaceInFile($destfile, $arrayreplacement); } else { $langs->load("errors"); setEventMessages($langs->trans('ErrorFailToCreateFile', $destfile), null, 'errors'); } } // init Trigger if ($dirins && $action == 'inittrigger' && !empty($module) /* && $user->hasRight("modulebuilder", "run") // already checked */) { dol_mkdir($dirins.'/'.strtolower($module).'/core/triggers'); $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template'; $srcfile = $srcdir.'/core/triggers/interface_99_modMyModule_MyModuleTriggers.class.php'; $destfile = $dirins.'/'.strtolower($module).'/core/triggers/interface_99_mod'.$module.'_'.$module.'Triggers.class.php'; $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), '---Replace with your own copyright and developer email---' => getLicenceHeader($user, $langs, $now) ); // @phan-suppress-next-line PhanPluginSuspiciousParamPosition dolReplaceInFile($destfile, $arrayreplacement); } else { $langs->load("errors"); setEventMessages($langs->trans('ErrorFailToCreateFile', $destfile), null, 'errors'); } } // init Widget if ($dirins && $action == 'initwidget' && !empty($module) /* && $user->hasRight("modulebuilder", "run") // already checked */) { dol_mkdir($dirins.'/'.strtolower($module).'/core/boxes'); $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template'; $srcfile = $srcdir.'/core/boxes/mymodulewidget1.php'; $destfile = $dirins.'/'.strtolower($module).'/core/boxes/'.strtolower($module).'widget1.php'; $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), '---Replace with your own copyright and developer email---' => getLicenceHeader($user, $langs, $now) ); // @phan-suppress-next-line PhanPluginSuspiciousParamPosition dolReplaceInFile($destfile, $arrayreplacement); } else { $langs->load("errors"); setEventMessages($langs->trans('ErrorFailToCreateFile', $destfile), null, 'errors'); } } // init EmailSelector if ($dirins && $action == 'initemailing' && !empty($module) /* && $user->hasRight("modulebuilder", "run") // already checked */) { dol_mkdir($dirins.'/'.strtolower($module).'/core/modules/mailings'); $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template'; $srcfile = $srcdir.'/core/modules/mailings/mailing_mymodule_selector1.modules.php'; $destfile = $dirins.'/'.strtolower($module).'/core/modules/mailings/mailing_'.strtolower($module).'_selector1.modules.php'; $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), '---Replace with your own copyright and developer email---' => getLicenceHeader($user, $langs, $now) ); // @phan-suppress-next-line PhanPluginSuspiciousParamPosition dolReplaceInFile($destfile, $arrayreplacement); } else { $langs->load("errors"); setEventMessages($langs->trans('ErrorFailToCreateFile', $destfile), null, 'errors'); } } // init CSS if ($dirins && $action == 'initcss' && !empty($module) /* && $user->hasRight("modulebuilder", "run") // already checked */) { dol_mkdir($dirins.'/'.strtolower($module).'/css'); $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template'; $srcfile = $srcdir.'/css/mymodule.css.php'; $destfile = $dirins.'/'.strtolower($module).'/css/'.strtolower($module).'.css.php'; $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), '---Replace with your own copyright and developer email---' => getLicenceHeader($user, $langs, $now) ); // @phan-suppress-next-line PhanPluginSuspiciousParamPosition dolReplaceInFile($destfile, $arrayreplacement); // Update descriptor file to uncomment file $srcfile = $dirins.'/'.strtolower($module).'/core/modules/mod'.$module.'.class.php'; $arrayreplacement = array('/\/\/\s*\''.preg_quote('/'.strtolower($module).'/css/'.strtolower($module).'.css.php', '/').'\'/' => '\'/'.strtolower($module).'/css/'.strtolower($module).'.css.php\''); dolReplaceInFile($srcfile, $arrayreplacement, '', '0', 0, 1); } else { $langs->load("errors"); setEventMessages($langs->trans('ErrorFailToCreateFile', $destfile), null, 'errors'); } } // init JS if ($dirins && $action == 'initjs' && !empty($module) /* && $user->hasRight("modulebuilder", "run") // already checked */) { dol_mkdir($dirins.'/'.strtolower($module).'/js'); $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template'; $srcfile = $srcdir.'/js/mymodule.js.php'; $destfile = $dirins.'/'.strtolower($module).'/js/'.strtolower($module).'.js.php'; $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), '---Replace with your own copyright and developer email---' => getLicenceHeader($user, $langs, $now) ); // @phan-suppress-next-line PhanPluginSuspiciousParamPosition dolReplaceInFile($destfile, $arrayreplacement); // Update descriptor file to uncomment file $srcfile = $dirins.'/'.strtolower($module).'/core/modules/mod'.$module.'.class.php'; $arrayreplacement = array('/\/\/\s*\''.preg_quote('/'.strtolower($module).'/js/'.strtolower($module).'.js.php', '/').'\'/' => '\'/'.strtolower($module).'/js/'.strtolower($module).'.js.php\''); dolReplaceInFile($srcfile, $arrayreplacement, '', '0', 0, 1); } else { $langs->load("errors"); setEventMessages($langs->trans('ErrorFailToCreateFile', $destfile), null, 'errors'); } } // init CLI if ($dirins && $action == 'initcli' && !empty($module) /* && $user->hasRight("modulebuilder", "run") // already checked */) { dol_mkdir($dirins.'/'.strtolower($module).'/scripts'); $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template'; $srcfile = $srcdir.'/scripts/mymodule.php'; $destfile = $dirins.'/'.strtolower($module).'/scripts/'.strtolower($module).'.php'; $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), '__MYCOMPANY_NAME__' => $mysoc->name, '__KEYWORDS__' => $modulename, '__USER_FULLNAME__' => $user->getFullName($langs), '__USER_EMAIL__' => $user->email, '__YYYY-MM-DD__' => dol_print_date($now, 'dayrfc'), '---Replace with your own copyright and developer email---' => getLicenceHeader($user, $langs, $now) ); // @phan-suppress-next-line PhanPluginSuspiciousParamPosition dolReplaceInFile($destfile, $arrayreplacement); } else { $langs->load("errors"); setEventMessages($langs->trans('ErrorFailToCreateFile', $destfile), null, 'errors'); } } $moduledescriptorfile = '/not_set/'; $modulelowercase = null; // init Doc if ($dirins && $action == 'initdoc' && !empty($module) /* && $user->hasRight("modulebuilder", "run") // already checked */) { dol_mkdir($dirins.'/'.strtolower($module).'/doc'); $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template'; $srcfile = $srcdir.'/doc/Documentation.asciidoc'; $destfile = $dirins.'/'.strtolower($module).'/doc/Documentation.asciidoc'; $result = dol_copy($srcfile, $destfile, '0', 0); if ($result > 0) { $modulename = ucfirst($module); // Force first letter in uppercase $modulelowercase = strtolower($module); //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), '__MYCOMPANY_NAME__' => $mysoc->name, '__KEYWORDS__' => $modulename, '__USER_FULLNAME__' => $user->getFullName($langs), '__USER_EMAIL__' => $user->email, '__YYYY-MM-DD__' => dol_print_date($now, 'dayrfc'), '---Replace with your own copyright and developer email---' => getLicenceHeader($user, $langs, $now) ); // @phan-suppress-next-line PhanPluginSuspiciousParamPosition dolReplaceInFile($destfile, $arrayreplacement); // add table of properties $dirins = $listofmodules[strtolower($module)]['moduledescriptorrootpath']; $destdir = $dirins.'/'.strtolower($module); $objects = dolGetListOfObjectClasses($destdir); foreach ($objects as $path => $obj) { writePropsInAsciiDoc($path, $obj, $destfile); } // add table of permissions $moduledescriptorfile = $dirins.'/'.strtolower($module).'/core/modules/mod'.$module.'.class.php'; writePermsInAsciiDoc($moduledescriptorfile, $destfile); // add api urls if file exist if (file_exists($dirins.'/'.strtolower($module).'/class/api_'.strtolower($module).'.class.php')) { $apiFile = $dirins.'/'.strtolower($module).'/class/api_'.strtolower($module).'.class.php'; writeApiUrlsInDoc($apiFile, $destfile); } // add ChangeLog in Doc if (file_exists($dirins.'/'.strtolower($module).'/ChangeLog.md')) { $changeLog = $dirins.'/'.strtolower($module).'/ChangeLog.md'; $string = file_get_contents($changeLog); $replace = explode("\n", $string); $strreplace = array(); foreach ($replace as $line) { if ($line === '') { continue; } if (strpos($line, '##') !== false) { $strreplace[$line] = str_replace('##', '', $line); } else { $strreplace[$line] = $line; } } $stringLog = implode("\n", $strreplace); // @phan-suppress-next-line PhanPluginSuspiciousParamPosition dolReplaceInFile($destfile, array('//include::ChangeLog.md[]' => '','__CHANGELOG__' => $stringLog)); } // Delete old documentation files $FILENAMEDOC = $modulelowercase.'.html'; $FILENAMEDOCPDF = $modulelowercase.'.pdf'; $outputfiledoc = dol_buildpath($modulelowercase, 0).'/doc/'.$FILENAMEDOC; $outputfiledocurl = dol_buildpath($modulelowercase, 1).'/doc/'.$FILENAMEDOC; $outputfiledocpdf = dol_buildpath($modulelowercase, 0).'/doc/'.$FILENAMEDOCPDF; $outputfiledocurlpdf = dol_buildpath($modulelowercase, 1).'/doc/'.$FILENAMEDOCPDF; dol_delete_file($outputfiledoc, 0, 0, 0, null, false, 0); dol_delete_file($outputfiledocpdf, 0, 0, 0, null, false, 0); } else { $langs->load("errors"); setEventMessages($langs->trans('ErrorFailToCreateFile', $destfile), null, 'errors'); } } // add Language if ($dirins && $action == 'addlanguage' && !empty($module) /* && $user->hasRight("modulebuilder", "run") // already checked */) { $newlangcode = GETPOST('newlangcode', 'aZ09'); if ($newlangcode) { $modulelowercase = strtolower($module); // Dir for module $diroflang = dol_buildpath($modulelowercase, 0); if ($diroflang == $dolibarr_main_document_root.'/'.$modulelowercase) { // This is not a custom module, we force diroflang to htdocs root $diroflang = $dolibarr_main_document_root; $srcfile = $diroflang.'/langs/en_US/'.$modulelowercase.'.lang'; $destfile = $diroflang.'/langs/'.$newlangcode.'/'.$modulelowercase.'.lang'; $result = dol_copy($srcfile, $destfile, '0', 0); if ($result < 0) { setEventMessages($langs->trans("ErrorFailToCopyFile", $srcfile, $destfile), null, 'errors'); } } else { $srcdir = $diroflang.'/langs/en_US'; $srcfile = $diroflang.'/langs/en_US/'.$modulelowercase.'.lang'; $destdir = $diroflang.'/langs/'.$newlangcode; $arrayofreplacement = array(); if (!dol_is_dir($srcdir) || !dol_is_file($srcfile)) { $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template/langs/en_US'; $arrayofreplacement = array('mymodule' => $modulelowercase); } $result = dolCopyDir($srcdir, $destdir, '0', 0, $arrayofreplacement); } } else { setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Language")), null, 'errors'); } } // Remove/delete File if ($dirins && $action == 'confirm_removefile' && !empty($module) /* && $user->hasRight("modulebuilder", "run") // already checked */) { $objectname = $tabobj; $dirins = $listofmodules[strtolower($module)]['moduledescriptorrootpath']; $destdir = $dirins.'/'.strtolower($module); $relativefilename = dol_sanitizePathName(GETPOST('file', 'restricthtml')); // Now we delete the file if ($relativefilename) { $dirnametodelete = dirname($relativefilename); $filetodelete = $dirins.'/'.$relativefilename; $dirtodelete = $dirins.'/'.$dirnametodelete; // Get list of existing objects $objects = dolGetListOfObjectClasses($destdir); $keyofobjecttodelete = array_search($objectname, $objects); if ($keyofobjecttodelete !== false) { unset($objects[$keyofobjecttodelete]); } // Delete or modify the file if (strpos($relativefilename, 'api') !== false) { $file_api = $destdir.'/class/api_'.strtolower($module).'.class.php'; $removeFile = removeObjectFromApiFile($file_api, $objects, $objectname); if (count($objects) == 0) { $result = dol_delete_file($filetodelete, 1); } if ($removeFile) { setEventMessages($langs->trans("ApiObjectDeleted"), null); } } else { $result = dol_delete_file($filetodelete, 1); } if (!$result) { setEventMessages($langs->trans("ErrorFailToDeleteFile", basename($filetodelete)), null, 'errors'); } else { // If we delete a .sql file, we delete also the other .sql file if (preg_match('/\.sql$/', $relativefilename)) { if (preg_match('/\.key\.sql$/', $relativefilename)) { $relativefilename = preg_replace('/\.key\.sql$/', '.sql', $relativefilename); $filetodelete = $dirins.'/'.$relativefilename; $result = dol_delete_file($filetodelete, 1); } elseif (preg_match('/\.sql$/', $relativefilename)) { $relativefilename = preg_replace('/\.sql$/', '.key.sql', $relativefilename); $filetodelete = $dirins.'/'.$relativefilename; $result = dol_delete_file($filetodelete, 1); } } if (dol_is_dir_empty($dirtodelete)) { dol_delete_dir($dirtodelete); } // Update descriptor file to comment file if (in_array($tab, array('css', 'js'))) { $srcfile = $dirins.'/'.strtolower($module).'/core/modules/mod'.$module.'.class.php'; $arrayreplacement = array('/^\s*\''.preg_quote('/'.$relativefilename, '/').'\',*/m' => ' // \'/'.$relativefilename.'\','); dolReplaceInFile($srcfile, $arrayreplacement, '', '0', 0, 1); } if (preg_match('/_extrafields/', $relativefilename)) { // Now we update the object file to set $isextrafieldmanaged to 0 $srcfile = $dirins.'/'.strtolower($module).'/class/'.strtolower($objectname).'.class.php'; $arrayreplacement = array('/\$isextrafieldmanaged = 1;/' => '$isextrafieldmanaged = 0;'); dolReplaceInFile($srcfile, $arrayreplacement, '', '0', 0, 1); } // Now we update the lib file to set $showtabofpagexxx to 0 $varnametoupdate = ''; $reg = array(); if (preg_match('/_([a-z]+)\.php$/', $relativefilename, $reg)) { $varnametoupdate = 'showtabofpage'.$reg[1]; } if ($varnametoupdate) { $srcfile = $dirins.'/'.strtolower($module).'/lib/'.strtolower($module).'_'.strtolower($objectname).'.lib.php'; $arrayreplacement = array('/\$'.preg_quote($varnametoupdate, '/').' = 1;/' => '$'.preg_quote($varnametoupdate, '/').' = 0;'); dolReplaceInFile($srcfile, $arrayreplacement, '', '0', 0, 1); } } } } // Init an object if ($dirins && $action == 'initobject' && $module && $objectname) { // Test on permission already done $warning = 0; $objectname = dol_string_nounprintableascii(dol_string_unaccent(ucwords($objectname))); // Force first letter in uppercase $dirins = $dirread = $listofmodules[strtolower($module)]['moduledescriptorrootpath']; $moduletype = $listofmodules[strtolower($module)]['moduletype']; if (preg_match('/[^a-z0-9]/i', $objectname)) { $error++; setEventMessages($langs->trans("SpaceOrSpecialCharAreNotAllowed"), null, 'errors'); $tabobj = 'newobject'; } if (class_exists($objectname)) { // TODO Add a more efficient detection. Scan disk ? $error++; setEventMessages($langs->trans("AnObjectWithThisClassNameAlreadyExists"), null, 'errors'); $tabobj = 'newobject'; } try { $ncObj = new NamingContract($module, $objectname); } catch (\InvalidArgumentException $e) { $error++; setEventMessages($langs->trans("SpaceOrSpecialCharAreNotAllowed"), null, 'errors'); $ncObj = null; } $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template'; $destdir = $dirins.'/'.strtolower($module); // Optional tabs selected by user, and detection of an already generated object (for idempotence warning) $enabledtabs = filterEnabledTabs(GETPOST('enabledtab', 'array'), getModuleBuilderObjectTabs()); $objectalreadyexists = dol_is_file($destdir.'/class/'.strtolower($objectname).'.class.php'); // The dir was not created by init dol_mkdir($destdir.'/class'); dol_mkdir($destdir.'/img'); dol_mkdir($destdir.'/lib'); dol_mkdir($destdir.'/scripts'); dol_mkdir($destdir.'/sql'); dol_mkdir($destdir.'/ajax'); dol_mkdir($destdir.'/stats'); // Scan dir class to find if an object with the same name already exists. if (!$error) { $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 we must reuse an existing table for properties, define $stringforproperties // Generate class file from the table $stringforproperties = ''; $tablename = GETPOST('initfromtablename', 'alpha'); if ($tablename) { $_results = $db->DDLDescTable($tablename); if (empty($_results)) { $error++; $langs->load("errors"); setEventMessages($langs->trans("ErrorTableNotFound", $tablename), null, 'errors'); } else { /** * 'type' field format ('integer', 'integer:ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter[:Sortfield]]]', 'sellist:TableName:LabelFieldName[:KeyFieldName[:KeyFieldParent[:Filter[:Sortfield]]]]', 'varchar(x)', 'double(24,8)', 'real', 'price', 'text', 'text:none', 'html', 'date', 'datetime', 'timestamp', 'duration', 'email', 'phone', 'ip', 'url', 'password') * Note: Filter can be a string like "(t.ref:like:'SO-%') or (t.date_creation:>:'20160101') or (t.nature:is:NULL)" * 'label' the translation key. * 'picto' is code of a picto to show before value in forms * 'enabled' is a condition when the field must be managed (Example: 1 or '$conf->global->MY_SETUP_PARAM' or 'isModEnabled("multicurrency")' ...) * 'position' is the sort order of field. * 'notnull' is set to 1 if not null in database. Set to -1 if we must set data to null if empty ('' or 0). * 'visible' says if field is visible in list (Examples: 0=Not visible, 1=Visible on list and create/update/view forms, 2=Visible on list only, 3=Visible on create/update/view form only (not list), 4=Visible on list and update/view form only (not create). 5=Visible on list and view only (not create/not update). Using a negative value means field is not shown by default on list but can be selected for viewing) * 'noteditable' says if field is not editable (1 or 0) * 'alwayseditable' says if field can be modified also when status is not draft ('1' or '0') * 'default' is a default value for creation (can still be overwritten by the Setup of Default Values if the field is editable in creation form). Note: If default is set to '(PROV)' and field is 'ref', the default value will be set to '(PROVid)' where id is rowid when a new record is created. * 'index' if we want an index in database. * 'foreignkey' => 'tablename.field' if the field is a foreign key (it is recommended to name the field fk_...). * 'searchall' is 1 if we want to search in this field when making a search from the quick search button. * 'isameasure' must be set to 1 or 2 if field can be used for measure. Field type must be summable like integer or double(24,8). Use 1 in most cases, or 2 if you don't want to see the column total into list (for example for percentage) * 'css' and 'cssview' and 'csslist' is the CSS style to use on field. 'css' is used in creation and update. 'cssview' is used in view mode. 'csslist' is used for columns in lists. For example: 'css' => 'minwidth300 maxwidth500 widthcentpercentminusx', 'cssview' => 'wordbreak', 'csslist' => 'tdoverflowmax200' * 'help' is a 'TranslationString' to use to show a tooltip on field. You can also use 'TranslationString:keyfortooltiponlick' for a tooltip on click. * 'showoncombobox' if value of the field must be visible into the label of the combobox that list record * 'disabled' is 1 if we want to have the field locked by a 'disabled' attribute. In most cases, this is never set into the definition of $fields into class, but is set dynamically by some part of code. * 'arrayofkeyval' to set a list of values if type is a list of predefined values. For example: array("0" => "Draft","1" => "Active","-1" => "Cancel"). Note that type can be 'integer' or 'varchar' * 'autofocusoncreate' to have field having the focus on a create form. Only 1 field should have this property set to 1. * 'comment' is not used. You can store here any text of your choice. It is not used by application. * 'validate' is 1 if need to validate with $this->validateField() * 'copytoclipboard' is 1 or 2 to allow to add a picto to copy value into clipboard (1=picto after label, 2=picto after value) */ /*public $fields=array( 'rowid' => array('type' => 'integer', 'label' => 'TechnicalID', 'enabled' => 1, 'visible' => -2, 'notnull' => 1, 'index' => 1, 'position' => 1, 'comment' => 'Id'), 'ref' => array('type' => 'varchar(128)', 'label' => 'Ref', 'enabled' => 1, 'visible' => 1, 'notnull' => 1, 'showoncombobox' => 1, 'index' => 1, 'position' => 10, 'searchall' => 1, 'comment' => 'Reference of object'), 'entity' => array('type' => 'integer', 'label' => 'Entity', 'enabled' => 1, 'visible' => 0, 'default' => 1, 'notnull' => 1, 'index' => 1, 'position' => 20), 'label' => array('type' => 'varchar(255)', 'label' => 'Label', 'enabled' => 1, 'visible' => 1, 'position' => 30, 'searchall' => 1, 'css' => 'minwidth200', 'help' => 'Help text', 'alwayseditable' => '1'), 'amount' => array('type' => 'double(24,8)', 'label' => 'Amount', 'enabled' => 1, 'visible' => 1, 'default' => 'null', 'position' => 40, 'searchall' => 0, 'isameasure' => 1, 'help' => 'Help text'), 'fk_soc' => array('type' => 'integer:Societe:societe/class/societe.class.php', 'label' => 'ThirdParty', 'visible' => 1, 'enabled' => 1, 'position' => 50, 'notnull' => -1, 'index' => 1, 'searchall' => 1, 'help' => 'LinkToThirdparty'), 'description' => array('type' => 'text', 'label' => 'Descrption', 'enabled' => 1, 'visible' => 0, 'position' => 60), 'note_public' => array('type' => 'html', 'label' => 'NotePublic', 'enabled' => 1, 'visible' => 0, 'position' => 61), 'note_private' => array('type' => 'html', 'label' => 'NotePrivate', 'enabled' => 1, 'visible' => 0, 'position' => 62), 'date_creation' => array('type' => 'datetime', 'label' => 'DateCreation', 'enabled' => 1, 'visible' => -2, 'notnull' => 1, 'position' => 500), 'tms' => array('type' => 'timestamp', 'label' => 'DateModification', 'enabled' => 1, 'visible' => -2, 'notnull' => 1, 'position' => 501), //'date_valid' => array('type' => 'datetime', 'label' => 'DateCreation', 'enabled' => 1, 'visible' => -2, 'position' => 502), 'fk_user_creat' => array('type' => 'integer', 'label' => 'UserAuthor', 'enabled' => 1, 'visible' => -2, 'notnull' => 1, 'position' => 510), 'fk_user_modif' => array('type' => 'integer', 'label' => 'UserModif', 'enabled' => 1, 'visible' => -2, 'notnull' => -1, 'position' => 511), //'fk_user_valid' => array('type' => 'integer', 'label' => 'UserValidation', 'enabled' => 1, 'visible' => -1, 'position' => 512), 'import_key' => array('type' => 'varchar(14)', 'label' => 'ImportId', 'enabled' => 1, 'visible' => -2, 'notnull' => -1, 'index' => 0, 'position' => 1000), 'status' => array('type' => 'integer', 'label' => 'Status', 'enabled' => 1, 'visible' => 1, 'notnull' => 1, 'default' => 0, 'index' => 1, 'position' => 1000, 'arrayofkeyval' => array(0 => 'Draft', 1 => 'Active', -1 => 'Cancel')), );*/ $stringforproperties = '// BEGIN MODULEBUILDER PROPERTIES'."\n"; $stringforproperties .= 'public $fields = array('."\n"; $i = 10; while ($obj = $db->fetch_object($_results)) { // fieldname $fieldname = $obj->Field; // type $type = $obj->Type; if ($type == 'int(11)') { $type = 'integer'; } elseif ($type == 'float') { $type = 'real'; } elseif (strstr($type, 'tinyint')) { $type = 'integer'; } elseif (strstr($type, 'url')) { $type = 'varchar(255)'; } elseif ($obj->Field == 'fk_soc') { $type = 'integer:Societe:societe/class/societe.class.php'; } elseif (preg_match('/^fk_proj/', $obj->Field)) { $type = 'integer:Project:projet/class/project.class.php:1:fk_statut=1'; } elseif (preg_match('/^fk_prod/', $obj->Field)) { $type = 'integer:Product:product/class/product.class.php:1'; } elseif ($obj->Field == 'fk_warehouse') { $type = 'integer:Entrepot:product/stock/class/entrepot.class.php'; } elseif (preg_match('/^(fk_user|fk_commercial)/', $obj->Field)) { $type = 'integer:User:user/class/user.class.php'; } // notnull $notnull = ($obj->Null == 'YES' ? 0 : 1); if ($fieldname == 'fk_user_modif') { $notnull = -1; } // label $label = preg_replace('/_/', '', ucfirst($fieldname)); if ($fieldname == 'rowid') { $label = 'TechnicalID'; } if ($fieldname == 'import_key') { $label = 'ImportId'; } if ($fieldname == 'fk_soc') { $label = 'ThirdParty'; } if (in_array($fieldname, array('tms', 'date_modification'))) { $label = 'DateModification'; } if (in_array($fieldname, array('datec', 'date_creation'))) { $label = 'DateCreation'; } if ($fieldname == 'date_valid') { $label = 'DateValidation'; } if ($fieldname == 'datev') { $label = 'DateValidation'; } if ($fieldname == 'note_private') { $label = 'NotePublic'; } if ($fieldname == 'note_public') { $label = 'NotePrivate'; } if ($fieldname == 'fk_user_creat') { $label = 'UserAuthor'; } if ($fieldname == 'fk_user_modif') { $label = 'UserModif'; } if ($fieldname == 'fk_user_valid') { $label = 'UserValidation'; } // visible $visible = -1; if (in_array($fieldname, array('ref', 'label'))) { $visible = 1; } if ($fieldname == 'entity') { $visible = -2; } if ($fieldname == 'entity') { $visible = -2; } if ($fieldname == 'import_key') { $visible = -2; } if ($fieldname == 'fk_user_creat') { $visible = -2; } if ($fieldname == 'fk_user_modif') { $visible = -2; } if (in_array($fieldname, array('ref_ext', 'model_pdf', 'note_public', 'note_private'))) { $visible = 0; } // enabled $enabled = 1; // default $default = ''; if ($fieldname == 'entity') { $default = 1; } // position $position = $i; if (in_array($fieldname, array('status', 'statut', 'fk_status', 'fk_statut'))) { $position = 500; } if ($fieldname == 'import_key') { $position = 900; } // $alwayseditable $alwayseditable = 0; if ($fieldname == 'label') { $alwayseditable = 1; } else { $alwayseditable = 0; } // index $index = 0; if ($fieldname == 'entity') { $index = 1; } // css, cssview, csslist $css = ''; $cssview = ''; $csslist = ''; if (preg_match('/^fk_/', $fieldname)) { $css = 'maxwidth500 widthcentpercentminusxx'; } if ($fieldname == 'label') { $css = 'minwidth300'; $cssview = 'wordbreak'; } if (in_array($fieldname, array('note_public', 'note_private'))) { $cssview = 'wordbreak'; } if (in_array($fieldname, array('ref', 'label')) || preg_match('/integer:/', $type)) { $csslist = 'tdoverflowmax150'; } // type $picto = ''; if (isset($obj->Picto)) { // This should never exists $picto = $obj->Picto; } if (preg_match('/^fk_soc/', $obj->Field)) { $picto = 'company'; } elseif (preg_match('/^fk_contact/', $obj->Field)) { $picto = 'contact'; } elseif (preg_match('/^fk_bank/', $obj->Field)) { $picto = 'bank'; } elseif (preg_match('/^fk_user/', $obj->Field)) { $picto = 'user'; } elseif (preg_match('/^fk_warehouse/', $obj->Field)) { $picto = 'warehouse'; } elseif (preg_match('/^fk_prod/', $obj->Field)) { $picto = 'product'; } elseif (preg_match('/^fk_proj/', $obj->Field)) { $picto = 'project'; } elseif (preg_match('/^fk_task/', $obj->Field)) { $picto = 'task'; } // lang $lang = $module.'@'.$module; // Build the property string $stringforproperties .= "'".$obj->Field."' => array('type' => '".$type."', 'label' => '".$label."',"; if ($default != '') { $stringforproperties .= " 'default' => ".$default.","; } $stringforproperties .= " 'enabled' => ".$enabled.","; $stringforproperties .= " 'visible' => ".$visible; if ($notnull) { $stringforproperties .= ", 'notnull' => ".$notnull; } if ($alwayseditable) { $stringforproperties .= ", 'alwayseditable' => 1"; } if ($fieldname == 'ref' || $fieldname == 'code') { $stringforproperties .= ", 'showoncombobox' => 1"; } $stringforproperties .= ", 'position' => ".$position; if ($index) { $stringforproperties .= ", 'index' => ".$index; } if ($picto) { $stringforproperties .= ", 'picto' => '".$picto."'"; } if ($css) { $stringforproperties .= ", 'css' => '".$css."'"; } if ($cssview) { $stringforproperties .= ", 'cssview' => '".$cssview."'"; } if ($csslist) { $stringforproperties .= ", 'csslist' => '".$csslist."'"; } $stringforproperties .= ", 'lang' => '".$lang."'"; $stringforproperties .= "),\n"; $i += 5; } $stringforproperties .= ');'."\n"; $stringforproperties .= '// END MODULEBUILDER PROPERTIES'."\n"; } } $filetogenerate = array(); if (!$error) { // Copy some files $filetogenerate = []; foreach ([ 'myobject_card.php', 'myobject_note.php', 'myobject_contact.php', 'myobject_document.php', 'myobject_agenda.php', 'myobject_list.php', 'admin/myobject_extrafields.php', 'ajax/myobject.php', 'lib/mymodule_myobject.lib.php', //'test/phpunit/MyObjectTest.php', 'sql/llx_mymodule_myobject.sql', 'sql/llx_mymodule_myobject.key.sql', 'sql/llx_mymodule_myobject_extrafields.sql', 'sql/llx_mymodule_myobject_extrafields.key.sql', //'scripts/mymodule.php', 'class/myobject.class.php', 'class/myobjectstats.class.php', //'class/api_mymodule.class.php', 'stats/myobject_index.php', ] as $templateFile) { $filetogenerate[$templateFile] = $ncObj->applyToFilename($templateFile); } // Exclude tab page files for tabs not selected by user foreach (getModuleBuilderObjectTabs() as $tabkey => $tabinfo) { if (!in_array($tabkey, $enabledtabs, true)) { unset($filetogenerate[$tabinfo['file']]); } } if (GETPOST('includerefgeneration', 'aZ09')) { dol_mkdir($destdir.'/core/modules/'.strtolower($module)); foreach ([ 'core/modules/mymodule/mod_myobject_advanced.php', 'core/modules/mymodule/mod_myobject_standard.php', 'core/modules/mymodule/modules_myobject.php', ] as $templateFile) { $filetogenerate[$templateFile] = $ncObj->applyToFilename($templateFile); } } if (GETPOST('includedocgeneration', 'aZ09')) { dol_mkdir($destdir.'/core/modules/'.strtolower($module)); dol_mkdir($destdir.'/core/modules/'.strtolower($module).'/doc'); foreach ([ 'core/modules/mymodule/doc/doc_generic_myobject_odt.modules.php', 'core/modules/mymodule/doc/pdf_standard_myobject.modules.php', ] as $templateFile) { $filetogenerate[$templateFile] = $ncObj->applyToFilename($templateFile); } } $class = null; if (GETPOST('generatepermissions', 'aZ09')) { $firstobjectname = 'myobject'; $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath']; dol_include_once($pathtofile); $class = 'mod'.$module; $moduleobj = null; if (class_exists($class)) { try { $moduleobj = new $class($db); '@phan-var-force DolibarrModules $moduleobj'; /** @var DolibarrModules $moduleobj */ } catch (Exception $e) { $error++; dol_print_error($db, $e->getMessage()); } } if (is_object($moduleobj)) { $rights = $moduleobj->rights; } else { $rights = []; } $moduledescriptorfile = $destdir.'/core/modules/mod'.$module.'.class.php'; $checkComment = checkExistComment($moduledescriptorfile, 1); if ($checkComment < 0) { setEventMessages($langs->trans("WarningCommentNotFound", $langs->trans("Permissions"), "mod".$module."class.php"), null, 'warnings'); } else { $generatePerms = reWriteAllPermissions($moduledescriptorfile, $rights, null, null, $objectname, $module, -2); if ($generatePerms < 0) { setEventMessages($langs->trans("WarningPermissionAlreadyExist", $langs->transnoentities($objectname)), null, 'warnings'); } } } if (!$error) { foreach ($filetogenerate as $srcfile => $destfile) { $result = dol_copy($srcdir.'/'.$srcfile, $destdir.'/'.$destfile, $newmask, 0); if ($result <= 0) { if ($result < 0) { $warning++; $langs->load("errors"); setEventMessages($langs->trans("ErrorFailToCopyFile", $srcdir.'/'.$srcfile, $destdir.'/'.$destfile), null, 'errors'); } else { // $result == 0 setEventMessages($langs->trans("FileAlreadyExists", $destfile), null, 'warnings'); } } $arrayreplacement = array( '/myobject\.class\.php/' => strtolower($objectname).'.class.php', '/myobject\.lib\.php/' => strtolower($objectname).'.lib.php', ); dolReplaceInFile($destdir.'/'.$destfile, $arrayreplacement, '', '0', 0, 1); } } // Replace property section with $stringforproperties if (!$error && $stringforproperties) { //var_dump($stringforproperties);exit; $arrayreplacement = array( '/\/\/ BEGIN MODULEBUILDER PROPERTIES.*\/\/ END MODULEBUILDER PROPERTIES/ims' => $stringforproperties ); dolReplaceInFile($destdir.'/class/'.strtolower($objectname).'.class.php', $arrayreplacement, '', '0', 0, 1); } // Edit the class 'class/'.strtolower($objectname).'.class.php' if (GETPOST('includerefgeneration', 'aZ09')) { // Replace 'visible' => 1, 'noteditable' => 0, 'default' => '' $arrayreplacement = array( '/\'visible\'s*=>s*1,\s*\'noteditable\'s*=>s*0,\s*\'default\'s*=>s*\'\'/' => "'visible' => 4, 'noteditable' => 1, 'default' => '(PROV)'" ); //var_dump($arrayreplacement);exit; //var_dump($destdir.'/class/'.strtolower($objectname).'.class.php');exit; dolReplaceInFile($destdir.'/class/'.strtolower($objectname).'.class.php', $arrayreplacement, '', '0', 0, 1); $arrayreplacement = array( '/\'models\' => 0,/' => '\'models\' => 1,' ); dolReplaceInFile($destdir.'/core/modules/mod'.$module.'.class.php', $arrayreplacement, '', '0', 0, 1); } // Edit the setup file and the card page if (GETPOST('includedocgeneration', 'aZ09')) { // Replace some var init into some files $arrayreplacement = array( '/\$includedocgeneration = 0;/' => '$includedocgeneration = 1;' ); dolReplaceInFile($destdir.'/class/'.strtolower($objectname).'.class.php', $arrayreplacement, '', '0', 0, 1); dolReplaceInFile($destdir.'/'.strtolower($objectname).'_card.php', $arrayreplacement, '', '0', 0, 1); $arrayreplacement = array( '/\'models\' => 0,/' => '\'models\' => 1,' ); dolReplaceInFile($destdir.'/core/modules/mod'.$module.'.class.php', $arrayreplacement, '', '0', 0, 1); } // TODO Update entries '$myTmpObjects['MyObject'] = array('includerefgeneration' => 0, 'includedocgeneration' => 0);' // Scan for object class files $listofobject = dol_dir_list($destdir.'/class', 'files', 0, '\.class\.php$'); $firstobjectname = ''; $stringtoadd = ''; foreach ($listofobject as $fileobj) { if (preg_match('/^api_/', $fileobj['name'])) { continue; } 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]; if (empty($firstobjectname)) { $firstobjectname = $objectnameloop; } } // Regenerate left menu entry in descriptor for $objectname $stringtoadd = " \$this->menu[\$r++] = array( 'fk_menu' => 'fk_mainmenu=mymodule', 'type' => 'left', 'titre' => 'MyObject', 'prefix' => img_picto('', \$this->picto, 'class=\"paddingright pictofixedwidth valignmiddle\"'), 'mainmenu' => 'mymodule', 'leftmenu' => 'myobject', 'url' => '/mymodule/myobject_list.php', 'langs' => 'mymodule@mymodule', 'position' => 1000 + \$r, 'enabled' => 'isModEnabled(\"mymodule\")', 'perms' => '".(GETPOST('generatepermissions') ? '$user->hasRight("mymodule", "myobject", "read")' : '1')."', 'target' => '', 'user' => 2, 'object' => 'MyObject' ); \$this->menu[\$r++] = array( 'fk_menu' => 'fk_mainmenu=mymodule,fk_leftmenu=myobject', 'type' => 'left', 'titre' => 'List MyObject', 'mainmenu' => 'mymodule', 'leftmenu' => 'mymodule_myobject_list', 'url' => '/mymodule/myobject_list.php', 'langs' => 'mymodule@mymodule', 'position' => 1000 + \$r, 'enabled' => 'isModEnabled(\"mymodule\")', 'perms' => '".(GETPOST('generatepermissions') ? '$user->hasRight("mymodule", "myobject", "read")' : '1')."', 'target' => '', 'user' => 2, 'object' => 'MyObject' ); \$this->menu[\$r++] = array( 'fk_menu' => 'fk_mainmenu=mymodule,fk_leftmenu=myobject', 'type' => 'left', 'titre' => 'New MyObject', 'mainmenu' => 'mymodule', 'leftmenu' => 'mymodule_myobject_new', 'url' => '/mymodule/myobject_card.php?action=create', 'langs' => 'mymodule@mymodule', 'position' => 1000 + \$r, 'enabled' => 'isModEnabled(\"mymodule\")', 'perms' => '".(GETPOST('generatepermissions') ? '$user->hasRight("mymodule", "myobject", "write")' : '1')."', 'target' => '', 'user' => 2, 'object' => 'MyObject' );"; $stringtoadd = $ncObj->applyTo($stringtoadd); $moduledescriptorfile = $destdir.'/core/modules/mod'.$module.'.class.php'; } // TODO Allow a replace with regex using dolReplaceInFile with param arryreplacementisregex to 1 // TODO Avoid duplicate addition // load class and check if menu exist with same object name $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath']; dol_include_once($pathtofile); $class = 'mod'.$module; $moduleobj = null; if (class_exists($class)) { try { $moduleobj = new $class($db); '@phan-var-force DolibarrModules $moduleobj'; /** @var DolibarrModules $moduleobj */ } catch (Exception $e) { $error++; dol_print_error($db, $e->getMessage()); } } if (is_object($moduleobj)) { $menus = $moduleobj->menu; } else { $menus = array(); } $counter = 0 ; foreach ($menus as $menu) { if ($menu['leftmenu'] == strtolower($objectname)) { $counter++; } } if (!$counter) { $checkComment = checkExistComment($moduledescriptorfile, 0); if ($checkComment < 0) { $warning++; setEventMessages($langs->trans("WarningCommentNotFound", $langs->trans("Menus"), basename($moduledescriptorfile)), null, 'warnings'); } else { $arrayofreplacement = array( '/* BEGIN MODULEBUILDER LEFTMENU MYOBJECT */' => '/* BEGIN MODULEBUILDER LEFTMENU '.strtoupper($objectname).' */'.$stringtoadd."\n\t\t".'/* END MODULEBUILDER LEFTMENU '.strtoupper($objectname).' */'."\n\t\t".'/* BEGIN MODULEBUILDER LEFTMENU MYOBJECT */' ); dolReplaceInFile($moduledescriptorfile, $arrayofreplacement); } } // Add module descriptor to list of files to replace "MyObject' string with real name of object. $filetogenerate[] = 'core/modules/mod'.$module.'.class.php'; } if (! $error && GETPOST('nogeneratelines', 'aZ09')) { $checkComment = checkExistComment($moduledescriptorfile, 0); if ($checkComment < 0) { $warning++; setEventMessages($langs->trans("WarningCommentNotFound", $langs->trans("Menus"), basename($moduledescriptorfile)), null, 'warnings'); } else { // File path $TFilePaths = [ $destdir . '/class/' . strtolower($objectname) . '.class.php', $destdir . '/class/api_' . strtolower($module) . '.class.php', $destdir . '/' . strtolower($objectname) . '_card.php' ]; // Pattern to remove everything between the tags $pattern = '/\/\/BEGIN MODULEBUILDER LINES.*?\/\/END MODULEBUILDER LINES\s*/s'; foreach ($TFilePaths as $filePath) { // Skip files that were not generated (e.g. the API class when API generation is disabled); // a missing optional file must not abort the whole object generation. if (file_exists($filePath) && !removePatternFromFile($filePath, $pattern)) { $error++; } } } } // Apply object tab selection on the generated lib file: // selected tabs -> hardcode the show flag to 1 (visible without extra config) ; unselected -> remove flag declaration and tab block if (!$error) { $libdestfile = $destdir.'/'.$ncObj->applyToFilename('lib/mymodule_myobject.lib.php'); foreach (getModuleBuilderObjectTabs() as $tabkey => $tabinfo) { $marker = $tabinfo['marker']; if (in_array($tabkey, $enabledtabs, true)) { $arrayreplacement = array( '/\$'.$tabinfo['var'].' = getDolGlobalInt\([^;]*\);/' => '$'.$tabinfo['var'].' = 1;' ); if (dolReplaceInFile($libdestfile, $arrayreplacement, '', '0', 0, 1) < 0) { $error++; dol_syslog("modulebuilder: failed to activate tab flag '".$tabkey."' in ".$libdestfile, LOG_ERR); } } else { if (!removePatternFromFile($libdestfile, '/\h*\/\/ BEGIN MODULEBUILDER TABFLAG '.$marker.'.*?\/\/ END MODULEBUILDER TABFLAG '.$marker.'\s*/s') || !removePatternFromFile($libdestfile, '/\h*\/\/ BEGIN MODULEBUILDER TAB '.$marker.'.*?\/\/ END MODULEBUILDER TAB '.$marker.'\s*/s')) { $error++; dol_syslog("modulebuilder: failed to purge tab '".$tabkey."' in ".$libdestfile, LOG_ERR); } } } // Agenda has an extra event widget on the card page: purge it too to avoid a dead link when the agenda tab is excluded if (!$error && !in_array('agenda', $enabledtabs, true)) { $carddestfile = $destdir.'/'.$ncObj->applyToFilename('myobject_card.php'); if (!removePatternFromFile($carddestfile, '/\h*\/\/ BEGIN MODULEBUILDER TAB AGENDA.*?\/\/ END MODULEBUILDER TAB AGENDA\s*/s')) { $error++; dol_syslog("modulebuilder: failed to purge agenda widget in ".$carddestfile, LOG_ERR); } } if ($objectalreadyexists) { setEventMessages($langs->trans("WarningTabSelectionOnRegeneration"), null, 'warnings'); } } if (!$error) { // Edit PHP files to make replacement foreach ($filetogenerate as $destfile) { $phpfileval['fullname'] = $destdir.'/'.$destfile; //var_dump($phpfileval['fullname']); $licenceValue = getDolGlobalString('MODULEBUILDER_SPECIFIC_AUTHOR') ? dol_print_date($now, '%Y') . ' ' . getDolGlobalString('MODULEBUILDER_SPECIFIC_AUTHOR') : getLicenceHeader($user, $langs, $now); $arrayreplacement = array_merge( $ncObj->getSubstitutionMap(), [ 'htdocs/modulebuilder/template/' => $ncObj->moduleNameLower, '---Replace with your own copyright and developer email---' => $licenceValue, ] ); if (basename($phpfileval['fullname']) === 'mod'.$module.'.class.php') { // Module descriptor: substitute content but keep the persistent MODULEBUILDER markers intact $result = dolReplaceInFilePreservingModuleBuilderMarkers($phpfileval['fullname'], $arrayreplacement); } else { $result = dolReplaceInFile($phpfileval['fullname'], $arrayreplacement); // @phpstan-ignore-line } //var_dump($result); if ($result < 0) { setEventMessages($langs->trans("ErrorFailToMakeReplacementInto", $phpfileval['fullname']), null, 'errors'); } else { modulebuilderValidateGeneratedFile($phpfileval['fullname'], $ncObj); } } } if (!$error && $ncObj !== null) { // Apply object name substitution to ALL PHP files in the module directory. // initmodule only substitutes the module name; files it creates (e.g. testmodindex.php, // lib/testmod.lib.php, admin/setup.php) still contain myobject/mymodule placeholders // that must be resolved when an object is first added. $licenceValueAll = getDolGlobalString('MODULEBUILDER_SPECIFIC_AUTHOR') ? dol_print_date($now, '%Y') . ' ' . getDolGlobalString('MODULEBUILDER_SPECIFIC_AUTHOR') : getLicenceHeader($user, $langs, $now); $moduleReplacementAll = array_merge( $ncObj->getSubstitutionMap(), [ 'htdocs/modulebuilder/template/' => $ncObj->moduleNameLower, '---Replace with your own copyright and developer email---' => $licenceValueAll, ] ); $allModulePhpFiles = dol_dir_list($destdir, 'files', 1, '\.php$'); // The module descriptor must NOT go through the blanket substitution: it keeps persistent // MYOBJECT/MYMODULE markers (TOPMENU/LEFTMENU) reused when generating subsequent objects, and its // own placeholders are already resolved by initmodule and the dedicated menu/permission blocks. $moduledescriptorbasename = 'mod'.$module.'.class.php'; if (is_array($allModulePhpFiles) && !empty($allModulePhpFiles)) { foreach ($allModulePhpFiles as $phpFileval) { if (basename($phpFileval['fullname']) === $moduledescriptorbasename) { continue; } $result = dolReplaceInFile($phpFileval['fullname'], $moduleReplacementAll); if ($result < 0) { setEventMessages($langs->trans("ErrorFailToMakeReplacementInto", $phpFileval['fullname']), null, 'warnings'); } } } // Delete initmodule placeholder files superseded by initobject-generated files. $moduleLowerForPlaceholder = strtolower($module); foreach ([ $destdir . '/stats/myobject_index.php', $destdir . '/lib/' . $moduleLowerForPlaceholder . '_myobject.lib.php', ] as $placeholder) { if (file_exists($placeholder)) { dol_delete_file($placeholder); } } } $object = null; if (!$error) { // Edit the class file to write properties $object = rebuildObjectClass($destdir, $module, $objectname, $newmask); if (is_numeric($object) && $object <= 0) { $pathoffiletoeditsrc = $destdir.'/class/'.strtolower($objectname).'.class.php'; setEventMessages($langs->trans('ErrorFailToCreateFile', $pathoffiletoeditsrc), null, 'errors'); $warning++; } // check if documentation was generate and add table of properties object $file = $destdir.'/class/'.strtolower($objectname).'.class.php'; $destfile = $destdir.'/doc/Documentation.asciidoc'; if (file_exists($destfile)) { writePropsInAsciiDoc($file, $objectname, $destfile); } } if (!$error && $object !== null) { // Edit sql with new properties $result = rebuildObjectSql($destdir, $module, $objectname, $newmask, '', $object); if ($result <= 0) { setEventMessages($langs->trans('ErrorFailToCreateFile', '.sql'), null); $error++; } } if (!$error) { setEventMessages($langs->trans('FilesForObjectInitialized', $objectname), null); $tabobj = $objectname; } else { $tabobj = 'newobject'; } // check if module is enabled if (isModEnabled(strtolower($module))) { $result = unActivateModule(strtolower($module)); dolibarr_set_const($db, "MAIN_IHM_PARAMS_REV", getDolGlobalInt('MAIN_IHM_PARAMS_REV') + 1, 'chaine', 0, '', $conf->entity); if ($result) { setEventMessages($result, null, 'errors'); } setEventMessages($langs->trans('WarningModuleNeedRefresh', $langs->transnoentities($module)), null, 'warnings'); header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=objects&module='.$module); exit; } } // Add a dictionary if ($dirins && $action == 'initdic' && $module && empty($cancel) /* && $user->hasRight("modulebuilder", "run") // already checked */) { $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath']; $destdir = $dirins.'/'.strtolower($module); $moduledescriptorfile = $dirins.'/'.strtolower($module).'/core/modules/mod'.$module.'.class.php'; if (!GETPOST('dicname')) { $error++; setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Table")), null, 'errors'); } if (!GETPOST('label')) { $error++; setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Label")), null, 'errors'); } if (!$error) { $newdicname = $dicname; if (!preg_match('/^c_/', $newdicname)) { $newdicname = 'c_'.$dicname; } dol_include_once($pathtofile); $class = 'mod'.$module; $moduleobj = null; if (class_exists($class)) { try { $moduleobj = new $class($db); '@phan-var-force DolibarrModules $moduleobj'; /** @var DolibarrModules $moduleobj */ } catch (Exception $e) { $error++; dol_print_error($db, $e->getMessage()); } } else { $error++; } if ($moduleobj === null) { $langs->load("errors"); dol_print_error($db, $langs->trans("ErrorFailedToLoadModuleDescriptorForXXX", $module)); exit; } $dictionaries = $moduleobj->dictionaries; $checkComment = checkExistComment($moduledescriptorfile, 2); if ($checkComment < 0) { setEventMessages($langs->trans("WarningCommentNotFound", $langs->trans("Dictionaries"), "mod".$module."class.php"), null, 'warnings'); } else { createNewDictionnary($module, $moduledescriptorfile, $newdicname, $dictionaries); if (function_exists('opcache_invalidate')) { opcache_reset(); // remove the include cache hell ! } clearstatcache(true); header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=dictionaries&module='.$module.($forceddirread ? '@'.$dirread : '')); exit; } } } // Delete a SQL table if ($dirins && ($action == 'droptable' || $action == 'droptableextrafields') && !empty($module) && !empty($tabobj) /* && $user->hasRight("modulebuilder", "run") // already checked */) { $objectname = $tabobj; $arrayoftables = array(); if ($action == 'droptable') { // Test on permission already done $arrayoftables[] = MAIN_DB_PREFIX.strtolower($module).'_'.strtolower($tabobj); } if ($action == 'droptableextrafields') { // Test on permission already done $arrayoftables[] = MAIN_DB_PREFIX.strtolower($module).'_'.strtolower($tabobj).'_extrafields'; } foreach ($arrayoftables as $tabletodrop) { $nb = -1; $sql = "SELECT COUNT(*) as nb FROM ".$tabletodrop; $resql = $db->query($sql); if ($resql) { $obj = $db->fetch_object($resql); if ($obj) { $nb = (int) $obj->nb; } } else { if ($db->lasterrno() == 'DB_ERROR_NOSUCHTABLE') { setEventMessages($langs->trans("TableDoesNotExists", $tabletodrop), null, 'warnings'); } else { dol_print_error($db); } } if ($nb == 0) { $resql = $db->DDLDropTable($tabletodrop); //var_dump($resql); setEventMessages($langs->trans("TableDropped", $tabletodrop), null, 'mesgs'); } elseif ($nb > 0) { setEventMessages($langs->trans("TableNotEmptyDropCanceled", $tabletodrop), null, 'warnings'); } } } if ($dirins && $action == 'addproperty' && empty($cancel) && !empty($module) && (!empty($tabobj) || !empty(GETPOST('obj'))) /* && $user->hasRight("modulebuilder", "run") // already checked */) { $error = 0; $objectname = (GETPOST('obj') ? GETPOST('obj') : $tabobj); $dirins = $dirread = $listofmodules[strtolower($module)]['moduledescriptorrootpath']; $moduletype = $listofmodules[strtolower($module)]['moduletype']; $srcdir = $dirread.'/'.strtolower($module); $destdir = $dirins.'/'.strtolower($module); dol_mkdir($destdir); $objects = dolGetListOfObjectClasses($destdir); if (!in_array($objectname, array_values($objects))) { $error++; setEventMessages($langs->trans("ErrorObjectNotFound", $langs->transnoentities($objectname)), null, 'errors'); } $addfieldentry = array(); // We click on add property if (!GETPOST('regenerateclasssql') && !GETPOST('regeneratemissing')) { if (!GETPOST('propname', 'aZ09')) { $error++; setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Name")), null, 'errors'); } if (!GETPOST('proplabel', 'alpha')) { $error++; setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Label")), null, 'errors'); } if (!GETPOST('proptype', 'alpha')) { $error++; setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Type")), null, 'errors'); } if (!$error && !GETPOST('regenerateclasssql') && !GETPOST('regeneratemissing')) { // Preserve case for composite types such as 'integer:Societe:societe/class/societe.class.php:1:(...__SHARED_ENTITIES__...)' // because the colon-separated parts include PHP class names (case-sensitive) and __XXX__ substitution // tokens that are uppercase by convention. Only lowercase simple atomic types (#34602). $proptype = GETPOST('proptype', 'alpha'); if (strpos($proptype, ':') === false && strpos($proptype, '_') === false) { $proptype = strtolower($proptype); } $addfieldentry = array( 'name' => GETPOST('propname', 'aZ09'), 'label' => GETPOST('proplabel', 'alpha'), 'type' => $proptype, 'arrayofkeyval' => GETPOST('proparrayofkeyval', 'nohtml'), // Example json string '{"0":"Draft","1":"Active","-1":"Cancel"}' 'visible' => GETPOST('propvisible', 'alphanohtml'), 'enabled' => GETPOST('propenabled', 'alphanohtml'), 'position' => GETPOSTINT('propposition'), 'notnull' => GETPOSTINT('propnotnull'), 'index' => GETPOSTINT('propindex'), 'foreignkey' => GETPOST('propforeignkey', 'alpha'), 'searchall' => GETPOSTINT('propsearchall'), 'isameasure' => GETPOSTINT('propisameasure'), 'showoncombobox' => GETPOSTINT('propshowoncombobox'), 'comment' => GETPOST('propcomment', 'alpha'), 'help' => GETPOST('prophelp', 'alpha'), 'css' => GETPOST('propcss', 'alpha'), // Can be 'maxwidth500 widthcentpercentminusxx' for example 'cssview' => GETPOST('propcssview', 'alpha'), 'csslist' => GETPOST('propcsslist', 'alpha'), 'default' => GETPOST('propdefault', 'restricthtml'), 'noteditable' => GETPOSTINT('propnoteditable'), //'alwayseditable' => GETPOSTINT('propalwayseditable'), 'validate' => GETPOSTINT('propvalidate') ); if (!empty($addfieldentry['arrayofkeyval']) && !is_array($addfieldentry['arrayofkeyval'])) { $tmpdecode = json_decode($addfieldentry['arrayofkeyval'], true); if ($tmpdecode) { // If string is already a json $addfieldentry['arrayofkeyval'] = $tmpdecode; } else { // If string is a list of lines with "key,value" $tmparray = dolExplodeIntoArray($addfieldentry['arrayofkeyval'], "\n", ","); $addfieldentry['arrayofkeyval'] = $tmparray; } } } } /*if (GETPOST('regeneratemissing')) { setEventMessages($langs->trans("FeatureNotYetAvailable"), null, 'warnings'); $error++; }*/ $moduletype = $listofmodules[strtolower($module)]['moduletype']; $object = null; // Edit the class file to write properties if (!$error) { $object = rebuildObjectClass($destdir, $module, $objectname, $newmask, $srcdir, $addfieldentry, $moduletype); if (is_numeric($object) && $object <= 0) { $pathoffiletoeditsrc = $destdir.'/class/'.strtolower($objectname).'.class.php'; setEventMessages($langs->trans('ErrorFailToCreateFile', $pathoffiletoeditsrc), null, 'errors'); $error++; } } // Edit sql with new properties if (!$error && $object !== null) { $result = rebuildObjectSql($destdir, $module, $objectname, $newmask, $srcdir, $object, $moduletype); if ($result <= 0) { setEventMessages($langs->trans('ErrorFailToCreateFile', '.sql'), null, 'errors'); $error++; } } if (!$error) { clearstatcache(true); setEventMessages($langs->trans('FilesForObjectUpdated', $objectname), null); setEventMessages($langs->trans('WarningDatabaseIsNotUpdated'), null); // Make a redirect to reload all data header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=objects&module='.$module.($forceddirread ? '@'.$dirread : '').'&tabobj='.$objectname.'&nocache='.time()); exit; } } if ($dirins && $action == 'confirm_deleteproperty' && $propertykey /* && $user->hasRight("modulebuilder", "run") // already checked */) { $objectname = $tabobj; $dirins = $dirread = $listofmodules[strtolower($module)]['moduledescriptorrootpath']; $moduletype = $listofmodules[strtolower($module)]['moduletype']; $srcdir = $dirread.'/'.strtolower($module); $destdir = $dirins.'/'.strtolower($module); dol_mkdir($destdir); $object = null; // Edit the class file to write properties if (!$error) { $object = rebuildObjectClass($destdir, $module, $objectname, $newmask, $srcdir, array(), $propertykey); if (is_numeric($object) && $object <= 0) { $pathoffiletoeditsrc = $destdir.'/class/'.strtolower($objectname).'.class.php'; setEventMessages($langs->trans('ErrorFailToCreateFile', $pathoffiletoeditsrc), null, 'errors'); $error++; } } // Edit sql with new properties if (!$error && $object !== null) { $result = rebuildObjectSql($destdir, $module, $objectname, $newmask, $srcdir, $object); if ($result <= 0) { setEventMessages($langs->trans('ErrorFailToCreateFile', '.sql'), null, 'errors'); $error++; } } if (!$error) { setEventMessages($langs->trans('FilesForObjectUpdated', $objectname), null); clearstatcache(true); // Make a redirect to reload all data header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=objects&module='.$module.($forceddirread ? '@'.$dirread : '').'&tabobj='.$objectname); exit; } } if ($dirins && $action == 'confirm_deletemodule' /* && $user->hasRight("modulebuilder", "run") // already checked */) { if (preg_match('/[^a-z0-9_]/i', $module)) { $error++; setEventMessages($langs->trans("SpaceOrSpecialCharAreNotAllowed"), null, 'errors'); } if (!$error) { $modulelowercase = strtolower($module); // Dir for module $dir = $dirins.'/'.$modulelowercase; $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath']; // Dir for module $dir = dol_buildpath($modulelowercase, 0); // Zip file to build $FILENAMEZIP = ''; // Load module dol_include_once($pathtofile); $class = 'mod'.$module; $moduleobj = null; if (class_exists($class)) { try { $moduleobj = new $class($db); '@phan-var-force DolibarrModules $moduleobj'; /** @var DolibarrModules $moduleobj */ } catch (Exception $e) { $error++; dol_print_error($db, $e->getMessage()); } } else { $error++; $langs->load("errors"); setEventMessages($langs->trans("ErrorFailedToLoadModuleDescriptorForXXX", $module), null, 'warnings'); } if ($moduleobj) { $moduleobj->remove(); } $result = dol_delete_dir_recursive($dir); if ($result > 0) { setEventMessages($langs->trans("DirWasRemoved", $modulelowercase), null); clearstatcache(true); if (function_exists('opcache_invalidate')) { opcache_reset(); // remove the include cache hell ! } header("Location: ".$_SERVER["PHP_SELF"].'?module=deletemodule'); exit; } else { setEventMessages($langs->trans("PurgeNothingToDelete"), null, 'warnings'); } } $action = ''; $module = 'deletemodule'; } if ($dirins && $action == 'confirm_deleteobject' && $objectname /* && $user->hasRight("modulebuilder", "run") // already checked */) { if (preg_match('/[^a-z0-9_]/i', $objectname)) { $error++; setEventMessages($langs->trans("SpaceOrSpecialCharAreNotAllowed"), null, 'errors'); } if (!$error) { $modulelowercase = strtolower($module); $objectlowercase = strtolower($objectname); // Dir for module $dir = $dirins.'/'.$modulelowercase; // Delete some files try { $ncObjDel = new NamingContract($module, $objectname); } catch (\InvalidArgumentException $e) { $error++; setEventMessages($langs->trans("SpaceOrSpecialCharAreNotAllowed"), null, 'errors'); $ncObjDel = null; } $filetodelete = []; if (!$error && $ncObjDel !== null) { foreach ([ 'myobject_card.php', 'myobject_note.php', 'myobject_contact.php', 'myobject_document.php', 'myobject_agenda.php', 'myobject_list.php', 'admin/myobject_extrafields.php', 'lib/mymodule_myobject.lib.php', 'sql/llx_mymodule_myobject.sql', 'sql/llx_mymodule_myobject_extrafields.sql', 'sql/llx_mymodule_myobject.key.sql', 'sql/llx_mymodule_myobject_extrafields.key.sql', 'scripts/myobject.php', 'class/myobject.class.php', 'class/myobjectstats.class.php', 'core/modules/mymodule/mod_myobject_advanced.php', 'core/modules/mymodule/mod_myobject_standard.php', 'core/modules/mymodule/modules_myobject.php', 'core/modules/mymodule/doc/doc_generic_myobject_odt.modules.php', 'core/modules/mymodule/doc/pdf_standard_myobject.modules.php', 'stats/myobject_index.php', ] as $templateFile) { $filetodelete[$templateFile] = $ncObjDel->applyToFilename($templateFile); } // Exceptions: target filenames differ from simple token substitution $filetodelete['ajax/myobject.lib.php'] = 'ajax/' . $ncObjDel->objectNameLower . '.php'; $filetodelete['test/phpunit/MyObjectTest.php'] = 'test/phpunit/' . $ncObjDel->objectNameLower . 'Test.php'; $filetodelete['class/api_myobject.class.php'] = 'class/api_' . $ncObjDel->moduleNameLower . '.class.php'; } //menu for the object selected // load class and check if menu,permission,documentation exist for this object $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath']; dol_include_once($pathtofile); $class = 'mod'.$module; $moduleobj = null; if (class_exists($class)) { try { $moduleobj = new $class($db); '@phan-var-force DolibarrModules $moduleobj'; /** @var DolibarrModules $moduleobj */ } catch (Exception $e) { $error++; dol_print_error($db, $e->getMessage()); } } else { $error++; $langs->load("errors"); dol_print_error($db, $langs->trans("ErrorFailedToLoadModuleDescriptorForXXX", $module)); exit; } $moduledescriptorfile = $dirins.'/'.strtolower($module).'/core/modules/mod'.$module.'.class.php'; // delete menus linked to the object $menus = $moduleobj->menu; $rewriteMenu = checkExistComment($moduledescriptorfile, 0); if ($rewriteMenu < 0) { setEventMessages($langs->trans("WarningCommentNotFound", $langs->trans("Menus"), "mod".$module."class.php"), null, 'warnings'); } else { reWriteAllMenus($moduledescriptorfile, $menus, $objectname, null, -1); } // regenerate permissions and delete them $permissions = $moduleobj->rights; $rewritePerms = checkExistComment($moduledescriptorfile, 1); if ($rewritePerms < 0) { setEventMessages($langs->trans("WarningCommentNotFound", $langs->trans("Permissions"), "mod".$module."class.php"), null, 'warnings'); } else { reWriteAllPermissions($moduledescriptorfile, $permissions, null, null, $objectname, '', -1); } if ($rewritePerms && $rewriteMenu) { // check if documentation has been generated $file_doc = $dirins.'/'.strtolower($module).'/doc/Documentation.asciidoc'; deletePropsAndPermsFromDoc($file_doc, $objectname); clearstatcache(true); if (function_exists('opcache_invalidate')) { opcache_reset(); // remove the include cache hell ! } $resultko = 0; foreach ($filetodelete as $tmpfiletodelete) { $resulttmp = dol_delete_file($dir.'/'.$tmpfiletodelete, 1, 0, 1); $resulttmp = dol_delete_file($dir.'/'.$tmpfiletodelete.'.back', 1, 0, 1); if (!$resulttmp) { $resultko++; } } if ($resultko == 0) { setEventMessages($langs->trans("FilesDeleted"), null); } else { setEventMessages($langs->trans("ErrorSomeFilesCouldNotBeDeleted"), null, 'warnings'); } } } $action = ''; if (! $error) { $tabobj = 'newobject'; } else { $tabobj = 'deleteobject'; } // check if module is enabled if (isModEnabled(strtolower($module))) { $result = unActivateModule(strtolower($module)); dolibarr_set_const($db, "MAIN_IHM_PARAMS_REV", getDolGlobalInt('MAIN_IHM_PARAMS_REV') + 1, 'chaine', 0, '', $conf->entity); if ($result) { setEventMessages($result, null, 'errors'); } setEventMessages($langs->trans('WarningModuleNeedRefresh', $langs->transnoentities($module)), null, 'warnings'); header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=objects&tabobj=deleteobject&module='.urlencode($module)); exit; } } if (($dirins && $action == 'confirm_deletedictionary' && $dicname) || ($dirins && $action == 'confirm_deletedictionary' && GETPOST('dictionnarykey')) /* && $user->hasRight("modulebuilder", "run") // already checked */) { $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath']; $destdir = $dirins.'/'.strtolower($module); $moduledescriptorfile = $dirins.'/'.strtolower($module).'/core/modules/mod'.$module.'.class.php'; if (preg_match('/[^a-z0-9_]/i', $dicname)) { $error++; setEventMessages($langs->trans("SpaceOrSpecialCharAreNotAllowed"), null, 'errors'); } if (!empty($dicname)) { $newdicname = $dicname; if (!preg_match('/^c_/', $newdicname)) { $newdicname = 'c_'.strtolower($dicname); } } else { $newdicname = null; } dol_include_once($pathtofile); $class = 'mod'.$module; $moduleobj = null; if (class_exists($class)) { try { $moduleobj = new $class($db); '@phan-var-force DolibarrModules $moduleobj'; /** @var DolibarrModules $moduleobj */ } catch (Exception $e) { $error++; dol_print_error($db, $e->getMessage()); } } else { $error++; } if ($moduleobj === null) { $langs->load("errors"); dol_print_error($db, $langs->trans("ErrorFailedToLoadModuleDescriptorForXXX", $module)); exit; } $dicts = $moduleobj->dictionaries; $checkComment = checkExistComment($moduledescriptorfile, 2); if ($checkComment < 0) { $error++; setEventMessages($langs->trans("WarningCommentNotFound", $langs->trans("Dictionaries"), "mod".$module."class.php"), null, 'warnings'); } if (!empty(GETPOST('dictionnarykey'))) { $newdicname = $dicts['tabname'][GETPOSTINT('dictionnarykey') - 1]; } // Lookup the table dicname $checkTable = false; if ($newdicname !== null) { $checkTable = $db->DDLDescTable(MAIN_DB_PREFIX.strtolower($newdicname)); } if (is_bool($checkTable) || $db->num_rows($checkTable) <= 0) { // @phpstan-ignore-line $error++; } // search the key by name $keyToDelete = null; foreach ($dicts['tabname'] as $key => $table) { //var_dump($table." /////// ".$newdicname);exit; if (strtolower($table) === $newdicname) { $keyToDelete = $key; break; } } // delete all dicname's key values from the dictionary if ($keyToDelete !== null) { $keysToDelete = ['tabname', 'tablib', 'tabsql', 'tabsqlsort', 'tabfield', 'tabfieldvalue', 'tabfieldinsert', 'tabrowid', 'tabcond', 'tabhelp']; foreach ($keysToDelete as $key) { unset($dicts[$key][$keyToDelete]); } } else { $error++; setEventMessages($langs->trans("ErrorDictionaryNotFound", ucfirst($dicname)), null, 'errors'); } if (!$error && $newdicname !== null) { // delete table $_results = $db->DDLDropTable(MAIN_DB_PREFIX.strtolower($newdicname)); if ($_results < 0) { dol_print_error($db); $langs->load("errors"); setEventMessages($langs->trans("ErrorTableNotFound", $newdicname), null, 'errors'); } // rebuild file after update dictionaries $result = updateDictionaryInFile($module, $moduledescriptorfile, $dicts); if ($result > 0) { setEventMessages($langs->trans("DictionaryDeleted", ucfirst(substr($newdicname, 2))), null); } if (function_exists('opcache_invalidate')) { opcache_reset(); // remove the include cache hell ! } clearstatcache(true); header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=dictionaries&module='.$module.($forceddirread ? '@'.$dirread : '')); exit; } } if ($dirins && $action == 'updatedictionary' && GETPOST('dictionnarykey') /* && $user->hasRight("modulebuilder", "run") // already checked */) { $keydict = GETPOSTINT('dictionnarykey') - 1 ; $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath']; $destdir = $dirins.'/'.strtolower($module); $moduledescriptorfile = $dirins.'/'.strtolower($module).'/core/modules/mod'.$module.'.class.php'; dol_include_once($pathtofile); $class = 'mod'.$module; $moduleobj = null; if (class_exists($class)) { try { $moduleobj = new $class($db); '@phan-var-force DolibarrModules $moduleobj'; /** @var DolibarrModules $moduleobj */ } catch (Exception $e) { $error++; dol_print_error($db, $e->getMessage()); } } else { $error++; } if ($moduleobj === null) { $langs->load("errors"); dol_print_error($db, $langs->trans("ErrorFailedToLoadModuleDescriptorForXXX", $module)); exit; } $dicts = $moduleobj->dictionaries; if (!empty(GETPOST('tablib')) && GETPOST('tablib') !== $dicts['tablib'][$keydict]) { $dicts['tablib'][$keydict] = ucfirst(strtolower(GETPOST('tablib'))); $checkComment = checkExistComment($moduledescriptorfile, 2); if ($checkComment < 0) { setEventMessages($langs->trans("WarningCommentNotFound", $langs->trans("Dictionaries"), "mod".$module."class.php"), null, 'warnings'); } else { $updateDict = updateDictionaryInFile($module, $moduledescriptorfile, $dicts); if ($updateDict > 0) { setEventMessages($langs->trans("DictionaryNameUpdated", ucfirst(GETPOST('tablib'))), null); } if (function_exists('opcache_invalidate')) { opcache_reset(); // remove the include cache hell ! } clearstatcache(true); header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=dictionaries&module='.$module.($forceddirread ? '@'.$dirread : '')); exit; } } //var_dump(GETPOST('tablib'));exit; } if ($dirins && $action == 'generatedoc' /* && $user->hasRight("modulebuilder", "run") // already checked */) { $modulelowercase = strtolower($module); // Dir for module $dirofmodule = dol_buildpath($modulelowercase, 0).'/doc'; $FILENAMEDOC = strtolower($module).'.html'; $util = new Utils($db); $result = $util->generateDoc($module); if ($result > 0) { setEventMessages($langs->trans("DocFileGeneratedInto", $dirofmodule), null); } else { setEventMessages($util->error, $util->errors, 'errors'); } } if ($dirins && $action == 'generatepackage' /* && $user->hasRight("modulebuilder", "run") // already checked */) { $modulelowercase = strtolower($module); $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath']; // Dir for module $dir = dol_buildpath($modulelowercase, 0); // Zip file to build $FILENAMEZIP = ''; // Load module dol_include_once($pathtofile); $class = 'mod'.$module; $moduleobj = null; if (class_exists($class)) { try { $moduleobj = new $class($db); '@phan-var-force DolibarrModules $moduleobj'; /** @var DolibarrModules $moduleobj */ } catch (Exception $e) { $error++; dol_print_error($db, $e->getMessage()); } } else { $error++; } if ($moduleobj === null) { $langs->load("errors"); dol_print_error($db, $langs->trans("ErrorFailedToLoadModuleDescriptorForXXX", $module)); exit; } $arrayversion = explode('.', $moduleobj->version, 3); if (count($arrayversion)) { $FILENAMEZIP = "module_".$modulelowercase.'-'.$arrayversion[0].(empty($arrayversion[1]) ? '.0' : '.'.$arrayversion[1]).(empty($arrayversion[2]) ? '' : '.'.$arrayversion[2]).'.zip'; $dirofmodule = dol_buildpath($modulelowercase, 0).'/bin'; $outputfilezip = $dirofmodule.'/'.$FILENAMEZIP; if (!dol_is_dir($dirofmodule)) { dol_mkdir($dirofmodule); } // Note: We exclude /bin/ to not include the already generated zip $result = dol_compress_dir($dir, $outputfilezip, 'zip', '/\/bin\/|\.git|\.old|\.back|\.ssh/', $modulelowercase); if ($result > 0) { setEventMessages($langs->trans("ZipFileGeneratedInto", $outputfilezip), null); } else { $error++; $langs->load("errors"); setEventMessages($langs->trans("ErrorFailToGenerateFile", $outputfilezip), null, 'errors'); } } else { $error++; $langs->load("errors"); setEventMessages($langs->trans("ErrorCheckVersionIsDefined"), null, 'errors'); } } // Add permission if ($dirins && $action == 'addright' && !empty($module) && empty($cancel) /* && $user->hasRight("modulebuilder", "run") // already checked */) { $error = 0; // load class and check if right exist $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath']; dol_include_once($pathtofile); $class = 'mod'.$module; $moduleobj = null; if (class_exists($class)) { try { $moduleobj = new $class($db); '@phan-var-force DolibarrModules $moduleobj'; /** @var DolibarrModules $moduleobj */ } catch (Exception $e) { $error++; dol_print_error($db, $e->getMessage()); } } // verify information entered if (!GETPOST('label', 'alpha')) { $error++; setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Label")), null, 'errors'); } if (!GETPOST('permissionObj', 'alpha')) { $error++; setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Rights")), null, 'errors'); } $id = GETPOST('id', 'alpha'); $label = GETPOST('label', 'alpha'); $objectForPerms = strtolower(GETPOST('permissionObj', 'alpha')); $crud = GETPOST('crud', 'alpha'); //check existing object permission $counter = 0; $permsForObject = array(); if (is_object($moduleobj)) { $permissions = $moduleobj->rights; } else { $permissions = array(); } $allObject = array(); $countPerms = count($permissions); for ($i = 0; $i < $countPerms; $i++) { if ($permissions[$i][4] == $objectForPerms) { $counter++; if (count($permsForObject) < 3) { $permsForObject[] = $permissions[$i]; } } $allObject[] = $permissions[$i][4]; } // check if label of object already exists $countPermsObj = count($permsForObject); for ($j = 0; $j < $countPermsObj; $j++) { if (in_array($crud, $permsForObject[$j])) { $error++; setEventMessages($langs->trans("ErrorExistingPermission", $langs->transnoentities($crud), $langs->transnoentities($objectForPerms)), null, 'errors'); } } $rightToAdd = array(); if (!$error) { $key = $countPerms + 1; //prepare right to add $rightToAdd = array( 0 => $id, 1 => $label, 4 => $objectForPerms, 5 => $crud ); if (isModEnabled(strtolower($module))) { $result = unActivateModule(strtolower($module)); dolibarr_set_const($db, "MAIN_IHM_PARAMS_REV", getDolGlobalInt('MAIN_IHM_PARAMS_REV') + 1, 'chaine', 0, '', $conf->entity); if ($result) { setEventMessages($result, null, 'errors'); } setEventMessages($langs->trans('WarningModuleNeedRefresh', $langs->transnoentities($module)), null, 'warnings'); } $moduledescriptorfile = $dirins.'/'.strtolower($module).'/core/modules/mod'.$module.'.class.php'; // Rewriting all permissions section in the descriptor file $rewrite = checkExistComment($moduledescriptorfile, 1); if ($rewrite < 0) { setEventMessages($langs->trans("WarningCommentNotFound", $langs->trans("Permissions"), "mod".$module."class.php"), null, 'warnings'); } else { reWriteAllPermissions($moduledescriptorfile, $permissions, $key, $rightToAdd, '', '', 1); setEventMessages($langs->trans('PermissionAddedSuccesfuly'), null); clearstatcache(true); if (function_exists('opcache_invalidate')) { opcache_reset(); // remove the include cache hell ! } header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=permissions&module='.$module); exit; } } } // Update permission if ($dirins && GETPOST('action') == 'update_right' && GETPOST('modifyright') && empty($cancel) /* && $user->hasRight("modulebuilder", "run") // already checked */) { $error = 0; // load class and check if right exist $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath']; dol_include_once($pathtofile); $class = 'mod'.$module; $moduleobj = null; if (class_exists($class)) { try { $moduleobj = new $class($db); '@phan-var-force DolibarrModules $moduleobj'; /** @var DolibarrModules $moduleobj */ } catch (Exception $e) { $error++; dol_print_error($db, $e->getMessage()); } } // verify information entered if (!GETPOST('label', 'alpha')) { $error++; setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Label")), null, 'errors'); } if (!GETPOST('permissionObj', 'alpha')) { $error++; setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Rights")), null, 'errors'); } $label = GETPOST('label', 'alpha'); $objectForPerms = strtolower(GETPOST('permissionObj', 'alpha')); $crud = GETPOST('crud', 'alpha'); if ($label == "Read objects of $module" && $crud != "read") { $crud = "read"; // $label = "Read objects of $module"; } if ($label == "Create/Update objects of $module" && $crud != "write") { $crud = "write"; // $label = "Create/Update objects of $module"; } if ($label == "Delete objects of $module" && $crud != "delete") { $crud = "delete"; // $label = "Delete objects of $module"; } if (is_object($moduleobj)) { $permissions = $moduleobj->rights; } else { $permissions = []; } $key = GETPOSTINT('counter') - 1; //get permission want to delete from permissions array if (array_key_exists($key, $permissions)) { $x1 = $permissions[$key][1]; $x2 = $permissions[$key][4]; $x3 = $permissions[$key][5]; } else { $x1 = null; $x2 = null; $x3 = null; } //check existing object permission $counter = 0; $permsForObject = array(); // $permissions = $moduleobj->rights; // Already fetched above $firstRight = 0; $existRight = 0; $allObject = array(); $countPerms = count($permissions); for ($i = 0; $i < $countPerms; $i++) { if ($permissions[$i][4] == $objectForPerms) { $counter++; if (count($permsForObject) < 3) { $permsForObject[] = $permissions[$i]; } } $allObject[] = $permissions[$i][4]; } if ($label != $x1 && $crud != $x3) { $countPermsObj = count($permsForObject); for ($j = 0; $j < $countPermsObj; $j++) { if (in_array($label, $permsForObject[$j])) { $error++; setEventMessages($langs->trans("ErrorExistingPermission", $langs->transnoentities($label), $langs->transnoentities($objectForPerms)), null, 'errors'); } } } if (!$error) { if (isModEnabled(strtolower($module))) { $result = unActivateModule(strtolower($module)); dolibarr_set_const($db, "MAIN_IHM_PARAMS_REV", getDolGlobalInt('MAIN_IHM_PARAMS_REV') + 1, 'chaine', 0, '', $conf->entity); if ($result) { setEventMessages($result, null, 'errors'); } setEventMessages($langs->trans('WarningModuleNeedRefresh', $langs->transnoentities($module)), null, 'warnings'); } $moduledescriptorfile = $dirins.'/'.strtolower($module).'/core/modules/mod'.$module.'.class.php'; // rewriting all permissions after update permission needed $rewrite = checkExistComment($moduledescriptorfile, 1); if ($rewrite < 0) { setEventMessages($langs->trans("WarningCommentNotFound", $langs->trans("Permissions"), "mod".$module."class.php"), null, 'warnings'); } else { $rightUpdated = null; // I not set at this point reWriteAllPermissions($moduledescriptorfile, $permissions, $key, $rightUpdated, '', '', 2); setEventMessages($langs->trans('PermissionUpdatedSuccesfuly'), null); clearstatcache(true); if (function_exists('opcache_invalidate')) { opcache_reset(); // remove the include cache hell ! } header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=permissions&module='.$module); exit; } } } // Delete permission if ($dirins && $action == 'confirm_deleteright' && !empty($module) && GETPOSTINT('permskey') /* && $user->hasRight("modulebuilder", "run") // already checked */) { $error = 0; // load class and check if right exist $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath']; dol_include_once($pathtofile); $class = 'mod'.$module; $moduleobj = null; if (class_exists($class)) { try { $moduleobj = new $class($db); '@phan-var-force DolibarrModules $moduleobj'; /** @var DolibarrModules $moduleobj */ } catch (Exception $e) { $error++; dol_print_error($db, $e->getMessage()); } } $permissions = $moduleobj->rights; $key = GETPOSTINT('permskey') - 1; if (!$error) { // check if module is enabled if (isModEnabled(strtolower($module))) { $result = unActivateModule(strtolower($module)); dolibarr_set_const($db, "MAIN_IHM_PARAMS_REV", getDolGlobalInt('MAIN_IHM_PARAMS_REV') + 1, 'chaine', 0, '', $conf->entity); if ($result) { setEventMessages($result, null, 'errors'); } setEventMessages($langs->trans('WarningModuleNeedRefresh', $langs->transnoentities($module)), null, 'warnings'); header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=permissions&module='.$module); exit; } // rewriting all permissions $moduledescriptorfile = $dirins.'/'.strtolower($module).'/core/modules/mod'.$module.'.class.php'; $rewrite = checkExistComment($moduledescriptorfile, 1); if ($rewrite < 0) { setEventMessages($langs->trans("WarningCommentNotFound", $langs->trans("Permissions"), "mod".$module."class.php"), null, 'warnings'); } else { reWriteAllPermissions($moduledescriptorfile, $permissions, $key, null, '', '', 0); setEventMessages($langs->trans('PermissionDeletedSuccesfuly'), null); clearstatcache(true); if (function_exists('opcache_invalidate')) { opcache_reset(); // remove the include cache hell ! } header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=permissions&module='.$module); exit; } } } // Save file if ($action == 'savefile' && empty($cancel) /* && $user->hasRight("modulebuilder", "run") // already checked */) { $relofcustom = basename($dirins); if ($relofcustom) { // Check that relative path ($file) start with name 'custom' if (!preg_match('/^'.$relofcustom.'/', $file)) { $file = $relofcustom.'/'.$file; } $pathoffile = dol_buildpath($file, 0); $pathoffilebackup = dol_buildpath($file.'.back', 0); // Save old version if (dol_is_file($pathoffile)) { dol_copy($pathoffile, $pathoffilebackup, '0', 1); } $check = 'restricthtml'; $srclang = dol_mimetype($pathoffile, '', 3); if ($srclang == 'md') { $check = 'restricthtml'; } if ($srclang == 'lang') { $check = 'restricthtml'; } if ($srclang == 'php') { $check = 'none'; } $content = GETPOST('editfilecontent', $check); // Save file on disk if ($content) { dol_delete_file($pathoffile); $result = file_put_contents($pathoffile, $content); if ($result) { dolChmod($pathoffile, $newmask); setEventMessages($langs->trans("FileSaved"), null); } else { setEventMessages($langs->trans("ErrorFailedToSaveFile"), null, 'errors'); } } else { setEventMessages($langs->trans("ContentCantBeEmpty"), null, 'errors'); //$action='editfile'; $error++; } } } // Enable module if ($action == 'set' && $user->admin /* && $user->hasRight("modulebuilder", "run") // already checked */) { $param = ''; if ($module) { $param .= '&module='.urlencode($module); } $param .= '&tab='.urlencode($tab); $param .= '&tabobj='.urlencode($tabobj); $value = GETPOST('value', 'alpha'); $resarray = activateModule($value, 1, 0); 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 /* && $user->hasRight("modulebuilder", "run") // already checked */) { $param = ''; if ($module) { $param .= '&module='.urlencode($module); } $param .= '&tab='.urlencode($tab); $param .= '&tabobj='.urlencode($tabobj); $value = GETPOST('value', 'alpha'); $result = unActivateModule(strtolower($value)); if ($result) { setEventMessages($result, null, 'errors'); } header("Location: ".$_SERVER["PHP_SELF"]."?".$param); exit; } // Delete menu if ($dirins && $action == 'confirm_deletemenu' && GETPOSTINT('menukey') /* && $user->hasRight("modulebuilder", "run") // already checked */) { // check if module is enabled if (isModEnabled(strtolower($module))) { $result = unActivateModule(strtolower($module)); dolibarr_set_const($db, "MAIN_IHM_PARAMS_REV", getDolGlobalInt('MAIN_IHM_PARAMS_REV') + 1, 'chaine', 0, '', $conf->entity); if ($result) { setEventMessages($result, null, 'errors'); } setEventMessages($langs->trans('WarningModuleNeedRefresh', $langs->transnoentities($module)), null, 'warnings'); header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=menus&module='.$module); exit; } // load class and check if menu exist $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath']; dol_include_once($pathtofile); $class = 'mod'.$module; $moduleobj = null; if (class_exists($class)) { try { $moduleobj = new $class($db); '@phan-var-force DolibarrModules $moduleobj'; /** @var DolibarrModules $moduleobj */ } catch (Exception $e) { $error++; dol_print_error($db, $e->getMessage()); } } // get all objects and convert value to lower case for compare $dir = $listofmodules[strtolower($module)]['moduledescriptorrootpath']; $destdir = $dir.'/'.strtolower($module); $objects = dolGetListOfObjectClasses($destdir); $result = array_map('strtolower', $objects); $menus = $moduleobj->menu; $key = GETPOSTINT('menukey'); $moduledescriptorfile = $dirins.'/'.strtolower($module).'/core/modules/mod'.$module.'.class.php'; $checkcomment = checkExistComment($moduledescriptorfile, 0); if ($checkcomment < 0) { setEventMessages($langs->trans("WarningCommentNotFound", $langs->trans("Menus"), "mod".$module."class.php"), null, 'warnings'); } else { if ($menus[$key]['fk_menu'] === 'fk_mainmenu='.strtolower($module)) { if (in_array(strtolower($menus[$key]['leftmenu']), $result)) { reWriteAllMenus($moduledescriptorfile, $menus, $menus[$key]['leftmenu'], $key, -1); } else { reWriteAllMenus($moduledescriptorfile, $menus, null, $key, 0); } } else { reWriteAllMenus($moduledescriptorfile, $menus, null, $key, 0); } clearstatcache(true); if (function_exists('opcache_invalidate')) { opcache_reset(); // remove the include cache hell ! } setEventMessages($langs->trans('MenuDeletedSuccessfuly'), null); header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=menus&module='.$module); exit; } } // Add menu in module without initial object if ($dirins && $action == 'addmenu' && empty($cancel) /* && $user->hasRight("modulebuilder", "run") // already checked */) { // check if module is enabled if (isModEnabled(strtolower($module))) { $result = unActivateModule(strtolower($module)); dolibarr_set_const($db, "MAIN_IHM_PARAMS_REV", getDolGlobalInt('MAIN_IHM_PARAMS_REV') + 1, 'chaine', 0, '', $conf->entity); if ($result) { setEventMessages($result, null, 'errors'); } setEventMessages($langs->trans('WarningModuleNeedRefresh', $langs->transnoentities($module)), null, 'warnings'); header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=menus&module='.$module); exit; } $error = 0; // load class and check if right exist $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath']; dol_include_once($pathtofile); $class = 'mod'.$module; $moduleobj = null; if (class_exists($class)) { try { $moduleobj = new $class($db); '@phan-var-force DolibarrModules $moduleobj'; /** @var DolibarrModules $moduleobj */ } catch (Exception $e) { $error++; dol_print_error($db, $e->getMessage()); } } // get all menus $menus = $moduleobj->menu; //verify fields required if (!GETPOST('type', 'alpha')) { $error++; setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Type")), null, 'errors'); } if (!GETPOST('titre', 'alpha')) { $error++; setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Title")), null, 'errors'); } if (!GETPOST('user', 'alpha')) { $error++; setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("DetailUser")), null, 'errors'); } if (!GETPOST('url', 'alpha')) { $error++; setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Url")), null, 'errors'); } if (!empty(GETPOST('target'))) { $targets = array('_blank','_self','_parent','_top',''); if (!in_array(GETPOST('target'), $targets)) { $error++; setEventMessages($langs->trans("ErrorFieldValue", $langs->transnoentities("target")), null, 'errors'); } } // check if title or url already exist in menus foreach ($menus as $menu) { if (!empty(GETPOST('url')) && GETPOST('url') == $menu['url']) { $error++; setEventMessages($langs->trans("ErrorFieldExist", $langs->transnoentities("url")), null, 'errors'); break; } if (strtolower(GETPOST('titre')) == strtolower($menu['titre'])) { $error++; setEventMessages($langs->trans("ErrorFieldExist", $langs->transnoentities("titre")), null, 'errors'); break; } } if (GETPOST('type', 'alpha') == 'left' && !empty(GETPOST('lefmenu', 'alpha'))) { if (!str_contains(GETPOST('leftmenu'), strtolower($module))) { $error++; setEventMessages($langs->trans("WarningFieldsMustContains", $langs->transnoentities("LeftmenuId")), null, 'errors'); } } $dirins = $listofmodules[strtolower($module)]['moduledescriptorrootpath']; $destdir = $dirins.'/'.strtolower($module); $objects = dolGetListOfObjectClasses($destdir); if (GETPOST('type', 'alpha') == 'left') { if (empty(GETPOST('leftmenu')) && count($objects) > 0) { $error++; setEventMessages($langs->trans("ErrorCoherenceMenu", $langs->transnoentities("LeftmenuId"), $langs->transnoentities("type")), null, 'errors'); } } if (GETPOST('type', 'alpha') == 'top') { $error++; setEventMessages($langs->trans("ErrorTypeMenu", $langs->transnoentities("type")), null, 'errors'); } $moduledescriptorfile = $dirins.'/'.strtolower($module).'/core/modules/mod'.$module.'.class.php'; if (!$error) { //stock forms in array $menuToAdd = array( 'fk_menu' => GETPOST('fk_menu', 'alpha'), 'type' => GETPOST('type', 'alpha'), 'titre' => ucfirst(GETPOST('titre', 'alpha')), 'prefix' => '', 'mainmenu' => GETPOST('mainmenu', 'alpha'), 'leftmenu' => GETPOST('leftmenu', 'alpha'), 'url' => GETPOST('url', 'alpha'), 'langs' => strtolower($module)."@".strtolower($module), 'position' => '', 'enabled' => GETPOST('enabled', 'alpha'), 'perms' => '$user->hasRight("'.strtolower($module).'", "'.GETPOST('objects', 'alpha').'", "'.GETPOST('perms', 'alpha').'")', 'target' => GETPOST('target', 'alpha'), 'user' => GETPOSTINT('user'), ); if (GETPOST('type') == 'left') { unset($menuToAdd['prefix']); if (empty(GETPOST('fk_menu'))) { $menuToAdd['fk_menu'] = 'fk_mainmenu='.GETPOST('mainmenu', 'alpha'); } else { $menuToAdd['fk_menu'] = 'fk_mainmenu='.GETPOST('mainmenu', 'alpha').',fk_leftmenu='.GETPOST('fk_menu'); } } if (GETPOST('enabled') == '1') { $menuToAdd['enabled'] = 'isModEnabled("'.strtolower($module).'")'; } else { $menuToAdd['enabled'] = "0"; } if (empty(GETPOST('objects'))) { $menuToAdd['perms'] = '1'; } $checkcomment = checkExistComment($moduledescriptorfile, 0); if ($checkcomment < 0) { setEventMessages($langs->trans("WarningCommentNotFound", $langs->trans("Menus"), "mod".$module."class.php"), null, 'warnings'); } else { // Write all menus $result = reWriteAllMenus($moduledescriptorfile, $menus, $menuToAdd, null, 1); clearstatcache(true); if (function_exists('opcache_invalidate')) { opcache_reset(); } /*if ($result < 0) { setEventMessages($langs->trans('ErrorMenuExistValue'), null, 'errors'); header("Location: ".$_SERVER["PHP_SELF"].'?action=editmenu&token='.newToken().'&menukey='.urlencode($key+1).'&tab='.urlencode($tab).'&module='.urlencode($module).'&tabobj='.($key+1)); exit; }*/ header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=menus&module='.$module); setEventMessages($langs->trans('MenuAddedSuccesfuly'), null); exit; } } } // Modify a menu entry if ($dirins && $action == "update_menu" && GETPOSTINT('menukey') && GETPOST('tabobj') /* && $user->hasRight("modulebuilder", "run") // already checked */) { $objectname = GETPOST('tabobj'); $dirins = $listofmodules[strtolower($module)]['moduledescriptorrootpath']; $destdir = $dirins.'/'.strtolower($module); $objects = dolGetListOfObjectClasses($destdir); if (empty($cancel)) { if (isModEnabled(strtolower($module))) { $result = unActivateModule(strtolower($module)); dolibarr_set_const($db, "MAIN_IHM_PARAMS_REV", getDolGlobalInt('MAIN_IHM_PARAMS_REV') + 1, 'chaine', 0, '', $conf->entity); if ($result) { setEventMessages($result, null, 'errors'); } setEventMessages($langs->trans('WarningModuleNeedRefresh', $langs->transnoentities($module)), null, 'warnings'); header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=menus&module='.$module); exit; } $error = 0; // for loading class and the menu wants to modify $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath']; dol_include_once($pathtofile); $class = 'mod'.$module; $moduleobj = null; if (class_exists($class)) { try { $moduleobj = new $class($db); '@phan-var-force DolibarrModules $moduleobj'; /** @var DolibarrModules $moduleobj */ } catch (Exception $e) { $error++; dol_print_error($db, $e->getMessage()); } } $menus = $moduleobj->menu; $key = GETPOSTINT('menukey') - 1; $moduledescriptorfile = $dirins.'/'.strtolower($module).'/core/modules/mod'.$module.'.class.php'; //stock forms in array $menuModify = array( 'fk_menu' => GETPOST('fk_menu', 'alpha'), 'type' => GETPOST('type', 'alpha'), 'titre' => ucfirst(GETPOST('titre', 'alpha')), 'prefix' => '', 'mainmenu' => GETPOST('mainmenu', 'alpha'), 'leftmenu' => $menus[$key]['leftmenu'], 'url' => GETPOST('url', 'alpha'), 'langs' => strtolower($module)."@".strtolower($module), 'position' => '', 'enabled' => GETPOST('enabled', 'alpha'), 'perms' => GETPOST('perms', 'alpha'), 'target' => GETPOST('target', 'alpha'), 'user' => GETPOSTINT('user'), ); if (!empty(GETPOST('fk_menu')) && GETPOST('fk_menu') != $menus[$key]['fk_menu']) { $menuModify['fk_menu'] = 'fk_mainmenu='.GETPOST('mainmenu').',fk_leftmenu='.GETPOST('fk_menu'); } elseif (GETPOST('fk_menu') == $menus[$key]['fk_menu']) { $menuModify['fk_menu'] = $menus[$key]['fk_menu']; } else { $menuModify['fk_menu'] = 'fk_mainmenu='.GETPOST('mainmenu'); } if ($menuModify['enabled'] === '') { $menuModify['enabled'] = '1'; } if ($menuModify['perms'] === '') { $menuModify['perms'] = '1'; } if (GETPOST('type', 'alpha') == 'top') { $error++; setEventMessages($langs->trans("ErrorTypeMenu", $langs->transnoentities("type")), null, 'errors'); } if (!$error) { //update menu $checkComment = checkExistComment($moduledescriptorfile, 0); if ($checkComment < 0) { setEventMessages($langs->trans("WarningCommentNotFound", $langs->trans("Menus"), "mod".$module."class.php"), null, 'warnings'); } else { // Write all menus $result = reWriteAllMenus($moduledescriptorfile, $menus, $menuModify, $key, 2); clearstatcache(true); if (function_exists('opcache_invalidate')) { opcache_reset(); } if ($result < 0) { setEventMessages($langs->trans('ErrorMenuExistValue'), null, 'errors'); //var_dump($_SESSION);exit; header("Location: ".$_SERVER["PHP_SELF"].'?action=editmenu&token='.newToken().'&menukey='.urlencode((string) ($key + 1)).'&tab='.urlencode((string) ($tab)).'&module='.urlencode((string) ($module)).'&tabobj='.($key + 1)); exit; } setEventMessages($langs->trans('MenuUpdatedSuccessfuly'), null); header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=menus&module='.$module); exit; } } } else { $_POST['type'] = ''; // TODO Use a var here and later $_POST['titre'] = ''; $_POST['fk_menu'] = ''; $_POST['leftmenu'] = ''; $_POST['url'] = ''; } } // update properties description of module if ($dirins && $action == "update_props_module" && !empty(GETPOST('keydescription', 'alpha')) && empty($cancel) /* && $user->hasRight("modulebuilder", "run") // already checked */) { if (isModEnabled(strtolower($module))) { $result = unActivateModule(strtolower($module)); dolibarr_set_const($db, "MAIN_IHM_PARAMS_REV", getDolGlobalInt('MAIN_IHM_PARAMS_REV') + 1, 'chaine', 0, '', $conf->entity); if ($result) { setEventMessages($result, null, 'errors'); } setEventMessages($langs->trans('WarningModuleNeedRefresh', $langs->transnoentities($module)), null, 'warnings'); header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=menus&module='.$module); exit; } $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath']; $moduledescriptorfile = $dirins.'/'.strtolower($module).'/core/modules/mod'.$module.'.class.php'; $modulelogfile = $dirins.'/'.strtolower($module).'/ChangeLog.md'; dol_include_once($pathtofile); $class = 'mod'.$module; $moduleobj = null; if (class_exists($class)) { try { $moduleobj = new $class($db); '@phan-var-force DolibarrModules $moduleobj'; /** @var DolibarrModules $moduleobj */ } catch (Exception $e) { $error++; dol_print_error($db, $e->getMessage()); } } $keydescription = GETPOST('keydescription', 'alpha'); switch ($keydescription) { case 'desc': $propertyToUpdate = 'description'; break; case 'version': case 'family': case 'picto': case 'editor_name': case 'editor_url': $propertyToUpdate = $keydescription; break; default: $error = GETPOST('keydescription'); break; } if (isset($propertyToUpdate) && !empty(GETPOST('propsmodule'))) { $newValue = GETPOST('propsmodule'); $patternToFindLine = '^\s*\$this->'.$propertyToUpdate.'\s*='; // Must be a regex string $newLine = "\t\t\$this->$propertyToUpdate = '$newValue';\n"; // Must a real string $fileLines = file($moduledescriptorfile); // Get each line of file into an array $error = 0; $changedone = 0; foreach ($fileLines as &$line) { if (preg_match('/'.$patternToFindLine.'/', $line)) { $result = dolReplaceInFile($moduledescriptorfile, array($line => $newLine)); if ($result > 0) { $changedone++; } elseif ($result <= -1) { $langs->load("errors"); setEventMessages($langs->trans('ErrorFailToEditFile', $moduledescriptorfile), null, 'warnings'); break; } break; } } // To complete also the ChangeLogif we update the version if ($changedone && $propertyToUpdate === 'version') { dolReplaceInFile($modulelogfile, array("## ".$moduleobj->$propertyToUpdate => $newValue)); } clearstatcache(true); if (function_exists('opcache_invalidate')) { opcache_reset(); } if ($changedone) { setEventMessages($langs->trans('PropertyModuleUpdated', $propertyToUpdate), null); } else { setEventMessages($langs->trans('NothingProcessed'), null, 'warnings'); } header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=description&module='.$module); exit; } } /* * View */ $form = new Form($db); $formadmin = new FormAdmin($db); // Set dir where external modules are installed if (!dol_is_dir($dirins)) { dol_mkdir($dirins); } $dirins_ok = (dol_is_dir($dirins)); $help_url = ''; $morejs = array( '/includes/ace/src/ace.js', '/includes/ace/src/ext-statusbar.js', '/includes/ace/src/ext-language_tools.js', //'/includes/ace/src/ext-chromevox.js' ); $morecss = array(); llxHeader('', $langs->trans("ModuleBuilder"), $help_url, '', 0, 0, $morejs, $morecss, '', 'classforhorizontalscrolloftabs'); $text = $langs->trans("ModuleBuilder"); $morehtmlright = ''.img_picto('', 'book', 'class="pictofixedwidth"').$langs->trans("UxComponentsDoc").''; print load_fiche_titre($text, $morehtmlright, 'title_setup'); print '
'; print $langs->trans("ModuleBuilderDesc", 'https://wiki.dolibarr.org/index.php/Module_development').''; print '
'; $message = ''; if (!$dirins) { $message = info_admin($langs->trans("ConfFileMustContainCustom", DOL_DOCUMENT_ROOT.'/custom', DOL_DOCUMENT_ROOT)); $allowfromweb = -1; } else { if ($dirins_ok) { if (!is_writable(dol_osencode($dirins))) { $langs->load("errors"); $message = info_admin($langs->trans("ErrorFailedToWriteInDir", $dirins)); $allowfromweb = 0; } } else { $message = info_admin($langs->trans("NotExistsDirect", $dirins).$langs->trans("InfDirAlt").$langs->trans("InfDirExample")); $allowfromweb = 0; } } if ($message) { print $message; } //print $langs->trans("ModuleBuilderDesc3", count($listofmodules), $FILEFLAG).'
'; $infomodulesfound = '
'.$form->textwithpicto('', $langs->trans("ModuleBuilderDesc3", count($listofmodules)).'

'.$langs->trans("ModuleBuilderDesc4", $FILEFLAG).'
'.$textforlistofdirs).'
'; $dolibarrdataroot = preg_replace('/([\\/]+)$/i', '', DOL_DATA_ROOT); $allowonlineinstall = true; if (dol_is_file($dolibarrdataroot.'/installmodules.lock')) { $allowonlineinstall = false; } if (empty($allowonlineinstall)) { if (getDolGlobalString('MAIN_MESSAGE_INSTALL_MODULES_DISABLED_CONTACT_US')) { // Show clean message $message = info_admin($langs->trans('InstallModuleFromWebHasBeenDisabledContactUs')); } else { // Show technical message $message = info_admin($langs->trans("InstallModuleFromWebHasBeenDisabledByFile", $dolibarrdataroot.'/installmodules.lock'), 0, 0, '1', 'warning'); } print $message; llxFooter(); exit(0); } // Load module descriptor $error = 0; $moduleobj = null; if (!empty($module) && $module != 'initmodule' && $module != 'deletemodule') { $modulelowercase = strtolower($module); $loadclasserrormessage = ''; $class = null; // Load module try { $fullpathdirtodescriptor = $listofmodules[strtolower($module)]['moduledescriptorrelpath']; //throw(new Exception()); dol_include_once($fullpathdirtodescriptor); $class = 'mod'.$module; } catch (Throwable $e) { // This is called in PHP 7 only (includes Error and Exception) $loadclasserrormessage = $e->getMessage()."
\n"; $loadclasserrormessage .= 'File: '.$e->getFile()."
\n"; $loadclasserrormessage .= 'Line: '.$e->getLine()."
\n"; } $moduleobj = null; if (class_exists($class)) { try { $moduleobj = new $class($db); '@phan-var-force DolibarrModules $moduleobj'; /** @var DolibarrModules $moduleobj */ } catch (Exception $e) { $error++; print $e->getMessage(); } } else { if (empty($forceddirread)) { $error++; } $langs->load("errors"); print ''; print img_warning('').' '.$langs->trans("ErrorFailedToLoadModuleDescriptorForXXX", $module).'
'; print $loadclasserrormessage; print '
'; } } // Tabs for all modules $head = array(); $h = 0; $head[$h][0] = $_SERVER["PHP_SELF"].'?module=initmodule'; $head[$h][1] = ''.$langs->trans("NewModule").''; $head[$h][2] = 'initmodule'; $h++; $linktoenabledisable = ''; if (/* is_array($listofmodules) && */ count($listofmodules) > 0) { // Define $linktoenabledisable $modulelowercase = strtolower($module); $param = ''; if ($module) { $param .= '&module='.urlencode($module); } $param .= '&tab='.urlencode($tab); $param .= '&tabobj='.urlencode($tabobj); $urltomodulesetup = ''.$langs->trans('Home').'-'.$langs->trans("Setup").'-'.$langs->trans("Modules").''; // Define $linktoenabledisable to show after module title if (isModEnabled($modulelowercase)) { // If module is already activated $linktoenabledisable .= ''; $linktoenabledisable .= img_picto($langs->trans("Warning").' : '.$langs->trans("ModuleIsLive"), 'switch_on', '', 0, 0, 0, '', 'warning valignmiddle', 1); $linktoenabledisable .= ''; //$linktoenabledisable .= $form->textwithpicto('', $langs->trans("Warning").' : '.$langs->trans("ModuleIsLive"), -1, 'warning'); $objMod = $moduleobj; $backtourlparam = ''; $backtourlparam .= ($backtourlparam ? '&' : '?').'module='.$module; // No urlencode here, done later $backtourlparam .= ($backtourlparam ? '&' : '?').'tab='.$tab; // No urlencode here, done later $backtourl = $_SERVER["PHP_SELF"].$backtourlparam; $regs = array(); if (is_array($objMod->config_page_url)) { $i = 0; foreach ($objMod->config_page_url as $page) { $urlpage = $page; if ($i++) { $linktoenabledisable .= ' '.img_picto(ucfirst($page), "setup").''; // print ''.ucfirst($page).' '; } else { if (preg_match('/^([^@]+)@([^@]+)$/i', $urlpage, $regs)) { $urltouse = dol_buildpath('/'.$regs[2].'/admin/'.$regs[1], 1); $linktoenabledisable .= ' '.img_picto($langs->trans("Setup"), "setup", 'style="padding-right: 8px"', 0, 0, 0, '', '').''; } else { // Case standard admin page (not a page provided by the // module but a page provided by dolibarr) $urltouse = DOL_URL_ROOT.'/admin/'.$urlpage; $linktoenabledisable .= ' '.img_picto($langs->trans("Setup"), "setup", 'style="padding-right: 8px"', 0, 0, 0, '', '').''; } } } } elseif (preg_match('/^([^@]+)@([^@]+)$/i', $objMod->config_page_url, $regs)) { $linktoenabledisable .= '   '.img_picto($langs->trans("Setup"), "setup", 'style="padding-right: 8px"', 0, 0, 0, '', '').''; } } else { if (is_object($moduleobj)) { $linktoenabledisable .= ''; $linktoenabledisable .= img_picto($langs->trans("ModuleIsNotActive", $urltomodulesetup), 'switch_off', 'style="padding-right: 8px"', 0, 0, 0, '', 'classfortooltip valignmiddle', 1); $linktoenabledisable .= "\n"; } } // Loop to show tab of each module foreach ($listofmodules as $tmpmodule => $tmpmodulearray) { $head[$h][0] = $_SERVER["PHP_SELF"].'?module='.$tmpmodulearray['modulenamewithcase'].($forceddirread ? '@'.$dirread : ''); $head[$h][1] = $tmpmodulearray['modulenamewithcase']; $head[$h][2] = $tmpmodulearray['modulenamewithcase']; if ($tmpmodulearray['modulenamewithcase'] == $module) { $head[$h][4] = ''.$linktoenabledisable.''; } $h++; } } $head[$h][0] = $_SERVER["PHP_SELF"].'?module=deletemodule'; $head[$h][1] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("DangerZone"); $head[$h][2] = 'deletemodule'; $h++; print dol_get_fiche_head($head, $module, '', -1, '', 0, $infomodulesfound, '', 8); // Modules if ($module == 'initmodule') { // New module print ''."\n"; print '
'; print ''; print ''; print ''; //print ''.$langs->trans("ModuleBuilderDesc2", 'conf/conf.php', $newdircustom).'
'; print '
'; print '
'; print '
'; print ''.$langs->trans("IdModule").''; print '
'; print ''; print ''; print '     '; print dolButtonToOpenUrlInDialogPopup('popup_modules_id', $langs->transnoentitiesnoconv("SeeIDsInUse"), $langs->transnoentitiesnoconv("SeeIDsInUse"), '/admin/system/modules.php?mainmenu=home&leftmenu=admintools_info&hidetitle=1', '', ''); print ' - '; print ''.$langs->trans("SeeReservedIDsRangeHere").''; print ''; print '
'; print '
'; print ''.$langs->trans("ModuleName").''; print '
'; print ''; print ' '.$form->textwithpicto('', $langs->trans("EnterNameOfModuleDesc")); print '
'; print '
'; print ''.$langs->trans("Description").''; print '
'; print '
'; print '
'; print '
'; print ''.$langs->trans("Version").''; print '
'; print ''; print '
'; print '
'; print ''.$langs->trans("Family").''; print '
'; print ''; print ajax_combobox("family"); print '
'; print '
'; print ''.$langs->trans("Picto").''; print '
'; print ''; print $form->textwithpicto('', $langs->trans("Example").': fa-file, fa-globe, ... any font awesome code.
Advanced syntax is fa-fakey[_faprefix[_facolor[_fasize]]]'); print '     '; print ''; print dolButtonToOpenUrlInDialogPopup('popup_picto_id', $langs->transnoentitiesnoconv("DocIconsList"), $langs->transnoentitiesnoconv("DocIconsList"), '/admin/tools/ui/components/icons.php?hidenavmenu=1&displayMode=icon-only&mode=no-btn#img-picto-section-list', '', ''); print ''; print '
'; print '
'; print ''.$langs->trans("EditorName").''; print '
'; print '
'; print '
'; print '
'; print ''.$langs->trans("EditorUrl").''; print '
'; print '
'; print '
'; print '
'; // End div tagtable print '
'; print ''; print '
'; print '
'; } elseif ($module == 'deletemodule') { print ''."\n"; print '
'; print ''; print ''; print ''; print $langs->trans("EnterNameOfModuleToDeleteDesc").'

'; print ''; print ''; print '
'; } elseif (!empty($module) && $modulelowercase !== null) { // Tabs for module if (!$error) { $dirread = $listofmodules[strtolower($module)]['moduledescriptorrootpath']; $destdir = $dirread.'/'.strtolower($module); $objects = dolGetListOfObjectClasses($destdir); $diroflang = dol_buildpath($modulelowercase, 0)."/langs"; $countLangs = countItemsInDirectory($diroflang, 2); $countDictionaries = (!empty($moduleobj->dictionaries) ? count($moduleobj->dictionaries['tabname']) : 0); $countRights = count($moduleobj->rights); $countMenus = count($moduleobj->menu); $countTriggers = countItemsInDirectory(dol_buildpath($modulelowercase, 0)."/core/triggers"); $countWidgets = countItemsInDirectory(dol_buildpath($modulelowercase, 0)."/core/boxes"); $countEmailingSelectors = countItemsInDirectory(dol_buildpath($modulelowercase, 0)."/core/modules/mailings"); $countCss = countItemsInDirectory(dol_buildpath($modulelowercase, 0)."/css"); $countJs = countItemsInDirectory(dol_buildpath($modulelowercase, 0)."/js"); $countCLI = countItemsInDirectory(dol_buildpath($modulelowercase, 0)."/scripts"); $hasDoc = countItemsInDirectory(dol_buildpath($modulelowercase, 0)."/doc"); //var_dump($moduleobj->dictionaries);exit; $head2 = array(); $h = 0; $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=description&module='.$module.($forceddirread ? '@'.$dirread : ''); $head2[$h][1] = $langs->trans("Description"); $head2[$h][2] = 'description'; $h++; $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=objects&module='.$module.($forceddirread ? '@'.$dirread : ''); $head2[$h][1] = ((!is_array($objects) || count($objects) <= 0) ? $langs->trans("Objects") : $langs->trans("Objects").''.count($objects).""); $head2[$h][2] = 'objects'; $h++; $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=languages&module='.$module.($forceddirread ? '@'.$dirread : ''); $head2[$h][1] = ($countLangs <= 0 ? $langs->trans("Languages") : $langs->trans("Languages").''.$countLangs.""); $head2[$h][2] = 'languages'; $h++; $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=permissions&module='.$module.($forceddirread ? '@'.$dirread : ''); $head2[$h][1] = ($countRights <= 0 ? $langs->trans("Permissions") : $langs->trans("Permissions").''.$countRights.""); $head2[$h][2] = 'permissions'; $h++; $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=dictionaries&module='.$module.($forceddirread ? '@'.$dirread : ''); $head2[$h][1] = ($countDictionaries == 0 ? $langs->trans("Dictionaries") : $langs->trans('Dictionaries').''.$countDictionaries.""); $head2[$h][2] = 'dictionaries'; $h++; $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=tabs&module='.$module.($forceddirread ? '@'.$dirread : ''); $head2[$h][1] = $langs->trans("Tabs"); $head2[$h][2] = 'tabs'; $h++; $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=menus&module='.$module.($forceddirread ? '@'.$dirread : ''); $head2[$h][1] = ($countMenus <= 0 ? $langs->trans("Menus") : $langs->trans("Menus").''.$countMenus.""); $head2[$h][2] = 'menus'; $h++; $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=hooks&module='.$module.($forceddirread ? '@'.$dirread : ''); $head2[$h][1] = $langs->trans("Hooks"); $head2[$h][2] = 'hooks'; $h++; $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=triggers&module='.$module.($forceddirread ? '@'.$dirread : ''); $head2[$h][1] = ($countTriggers <= 0 ? $langs->trans("Triggers") : $langs->trans("Triggers").''.$countTriggers.""); $head2[$h][2] = 'triggers'; $h++; $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=widgets&module='.$module.($forceddirread ? '@'.$dirread : ''); $head2[$h][1] = ($countWidgets <= 0 ? $langs->trans("Widgets") : $langs->trans("Widgets").''.$countWidgets.""); $head2[$h][2] = 'widgets'; $h++; $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=emailings&module='.$module.($forceddirread ? '@'.$dirread : ''); $head2[$h][1] = ($countEmailingSelectors <= 0 ? $langs->trans("EmailingSelectors") : $langs->trans("EmailingSelectors").''.$countEmailingSelectors.""); $head2[$h][2] = 'emailings'; $h++; $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=exportimport&module='.$module.($forceddirread ? '@'.$dirread : ''); $head2[$h][1] = $langs->trans("ImportExportProfiles"); $head2[$h][2] = 'exportimport'; $h++; $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=css&module='.$module.($forceddirread ? '@'.$dirread : ''); $head2[$h][1] = ($countCss <= 0 ? $langs->trans("CSS") : $langs->trans("CSS")." (".$countCss.")"); $head2[$h][2] = 'css'; $h++; $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=js&module='.$module.($forceddirread ? '@'.$dirread : ''); $head2[$h][1] = ($countJs <= 0 ? $langs->trans("JS") : $langs->trans("JS").''.$countJs.""); $head2[$h][2] = 'js'; $h++; $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=cli&module='.$module.($forceddirread ? '@'.$dirread : ''); $head2[$h][1] = ($countCLI <= 0 ? $langs->trans("CLI") : $langs->trans("CLI").''.$countCLI.""); $head2[$h][2] = 'cli'; $h++; $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=cron&module='.$module.($forceddirread ? '@'.$dirread : ''); $head2[$h][1] = $langs->trans("CronList"); $head2[$h][2] = 'cron'; $h++; $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=specifications&module='.$module.($forceddirread ? '@'.$dirread : ''); $head2[$h][1] = ($hasDoc <= 0 ? $langs->trans("Documentation") : $langs->trans("Documentation").''.$hasDoc.""); $head2[$h][2] = 'specifications'; $h++; $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=buildpackage&module='.$module.($forceddirread ? '@'.$dirread : ''); $head2[$h][1] = $langs->trans("BuildPackage"); $head2[$h][2] = 'buildpackage'; $h++; $MAXTABFOROBJECT = 12; print ''; // Note module is inside $dirread if ($tab == 'description') { print ''."\n"; $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath']; $pathtofilereadme = $modulelowercase.'/README.md'; $pathtochangelog = $modulelowercase.'/ChangeLog.md'; $pathtoindex = $modulelowercase.'/'.$modulelowercase.'index.php'; $realpathofmodule = realpath($dirread.'/'.$modulelowercase); if ($action != 'editfile' || empty($file)) { $morehtmlright = ''; if ($realpathofmodule != $dirread.'/'.$modulelowercase) { $morehtmlright = '
'.$form->textwithpicto('', ''.$langs->trans("RealPathOfModule").' : '.$realpathofmodule.'').'
'; } print dol_get_fiche_head($head2, $tab, '', -1, '', 0, $morehtmlright, '', $MAXTABFOROBJECT, 'formodulesuffix'); // Description - level 2 print ''.$langs->trans("ModuleBuilderDesc".$tab).''; print '

'; print ''; print ''; print ''; // List of setup pages $listofsetuppages = dol_dir_list($realpathofmodule.'/admin', 'files', 0, '\.php$'); foreach ($listofsetuppages as $setuppage) { // If this is a page for extrafields setup of an object $reg = array(); if (preg_match('/^([a-z]+)_extrafields.php/', $setuppage['relativename'], $reg)) { // Check that object has $isextrafieldmanaged property set. If not, we should not show this file. $fileofclass = $realpathofmodule.'/class/'.$reg[1].'.class.php'; if (is_readable($fileofclass) && !preg_match('/public\s+\$isextrafieldmanaged\s+=\s+1/', file_get_contents($fileofclass))) { continue; } } //var_dump($setuppage); print ''; } print ''; print ''; print '
'; print ' '.$langs->trans("DescriptorFile").' : '.$pathtofile.''; print ''.img_picto($langs->trans("Edit"), 'edit').''; print '
'.$langs->trans("Index").' : '.$pathtoindex.''; print ''.img_picto($langs->trans("Edit"), 'edit').''; print '
'; print ' '; if ($setuppage['relativename'] == 'about.php') { print $langs->trans("AboutFile"); } else { print $langs->trans("SetupFile"); } print ' : '; print ''.$modulelowercase.'/admin/'.$setuppage['relativename'].''; print ''.img_picto($langs->trans("Edit"), 'edit').''; print '
'.$langs->trans("ReadmeFile").' : '.$pathtofilereadme.''; print ''.img_picto($langs->trans("Edit"), 'edit').''; print '
'.$langs->trans("ChangeLog").' : '.$pathtochangelog.''; print ''.img_picto($langs->trans("Edit"), 'edit').''; print '
'; print '
'; print load_fiche_titre($form->textwithpicto($langs->trans("DescriptorFile"), $langs->transnoentitiesnoconv("File").' '.$pathtofile), '', ''); if (is_object($moduleobj)) { print '
'; print '
'; print '
'; print ''; print ''; print ''; print ''; print ''; print '
'; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''."\n"; print ''; print ''; print ''; print '
'; print $langs->trans("Parameter"); print ''; print $langs->trans("Value"); print '
'; print $langs->trans("IdModule"); print ''; print $moduleobj->numero; print ''; print '   ('; print dolButtonToOpenUrlInDialogPopup('popup_modules_id', $langs->transnoentitiesnoconv("SeeIDsInUse"), $langs->transnoentitiesnoconv("SeeIDsInUse"), '/admin/system/modules.php?mainmenu=home&leftmenu=admintools_info', '', ''); print ' - '.$langs->trans("SeeReservedIDsRangeHere").')'; print ''; print '
'; print $langs->trans("ModuleName"); print ''; print $moduleobj->getName(); print '
'; print $langs->trans("Description"); print ''; if ($action == 'edit_moduledescription' && GETPOST('keydescription', 'alpha') === 'desc') { print ''; print ''; print ''; } else { print $moduleobj->description; print ''.img_edit().''; $moduledescritpionautotrans = $moduleobj->getDesc(); if ($moduledescritpionautotrans != "Module".$moduleobj->name."Desc") { // $moduledescritpionautotrans has been found into a translation file print ' '.$form->textwithpicto('', $langs->trans("ModuleTranslatedIntoLangForKeyInto", "Module".$moduleobj->name."Desc", $moduledescritpionautotrans)); } elseif ($moduledescritpionautotrans != "Module".$moduleobj->numero."Desc") { // $moduledescritpionautotrans has been found into a translation file print ' '.$form->textwithpicto('', $langs->trans("ModuleTranslatedIntoLangForKeyInto", "Module".$moduleobj->numero."Desc", $moduledescritpionautotrans)); } } print '
'; print $langs->trans("Version"); print ''; if ($action == 'edit_moduledescription' && GETPOST('keydescription', 'alpha') === 'version') { print ''; print ''; print ''; } else { print $moduleobj->getVersion(); print ''.img_edit().''; } print '
'; print $langs->trans("Family"); //print "
'crm','financial','hr','projects','products','ecm','technic','interface','other'"; print '
'; if ($action == 'edit_moduledescription' && GETPOST('keydescription', 'alpha') === 'family') { print ''; print ''; print ''; } else { print $moduleobj->family; print ''.img_edit().''; } print '
'; print $langs->trans("Picto"); print ''; if ($action == 'edit_modulepicto' && GETPOST('keydescription', 'alpha') === 'picto') { print ''; print $form->textwithpicto('', $langs->trans("Example").': fa-file, fa-globe, ... any font awesome code.
Advanced syntax is fa-fakey[_faprefix[_facolor[_fasize]]] where faprefix can be far,far, facolor can be a text like \'red\' orvalue like \'#FF0000\' and fasize is CSS font size like \'1em\''); print ''; print ''; print '     '; print ''; print dolButtonToOpenUrlInDialogPopup('popup_picto_id', $langs->transnoentitiesnoconv("DocIconsList"), $langs->transnoentitiesnoconv("DocIconsList"), '/admin/tools/ui/components/icons.php?hidenavmenu=1&displayMode=icon-only&mode=no-btn#img-picto-section-list', '', ''); print ''; } else { print $moduleobj->picto; print '   '.img_picto('', $moduleobj->picto, 'class="valignmiddle pictomodule paddingrightonly"'); print ''.img_edit().''; } print '
'; print $langs->trans("EditorName"); print ''; if ($action == 'edit_moduledescription' && GETPOST('keydescription', 'alpha') === 'editor_name') { print ''; print ''; print ''; } else { print $moduleobj->editor_name; print ''.img_edit().''; } print '
'; print $langs->trans("EditorUrl"); print ''; if ($action == 'edit_moduledescription' && GETPOST('keydescription', 'alpha') === 'editor_url') { print ''; print ''; print ''; } else { if (!empty($moduleobj->editor_url)) { print ''.$moduleobj->editor_url.' '.img_picto('', 'globe').''; } print ''.img_edit().''; } print '
'; print '
'; print '
'; } else { print $langs->trans("ErrorFailedToLoadModuleDescriptorForXXX", $module).'
'; } if (!empty($moduleobj)) { print '

'; // Readme file print load_fiche_titre($form->textwithpicto($langs->trans("ReadmeFile"), $langs->transnoentitiesnoconv("File").' '.$pathtofilereadme), '', ''); print ''; if (dol_is_file($dirread.'/'.$pathtofilereadme)) { print '
'.$moduleobj->getDescLong().'
'; } else { print ''.$langs->trans("ErrorFileNotFound", $pathtofilereadme).''; } print '

'; // ChangeLog print load_fiche_titre($form->textwithpicto($langs->trans("ChangeLog"), $langs->transnoentitiesnoconv("File").' '.$pathtochangelog), '', ''); print ''; if (dol_is_file($dirread.'/'.$pathtochangelog)) { print '
'.$moduleobj->getChangeLog().'
'; } else { print ''.$langs->trans("ErrorFileNotFound", $pathtochangelog).''; } } print dol_get_fiche_end(); } else { // Edit text file $fullpathoffile = dol_buildpath($file, 0, 1); // Description - level 2 $content = ''; if ($fullpathoffile) { $content = file_get_contents($fullpathoffile); } // New module print '
'; print ''; print ''; print ''; print ''; print ''; print dol_get_fiche_head($head2, $tab, '', -1, '', 0, '', '', 0, 'formodulesuffix'); $posCursor = (empty($find)) ? array() : array('find' => $find); $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%', 0, $posCursor); print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'html')); print dol_get_fiche_end(); print '
'; print ''; print '   '; print ''; print '
'; print '
'; } } else { print dol_get_fiche_head($head2, $tab, '', -1, '', 0, '', '', $MAXTABFOROBJECT, 'formodulesuffix'); // Level 2 } if ($tab == 'languages') { print ''."\n"; if ($action != 'editfile' || empty($file)) { print ''.$langs->trans("LanguageDefDesc").'
'; print '
'; print '
'; print ''; print ''; print ''; print ''; print ''; print $formadmin->select_language(getDolGlobalString('MAIN_LANG_DEFAULT'), 'newlangcode', 0, array(), 1, 0, 0, 'minwidth300', 1); print '
'; print '
'; print '
'; print '
'; $modulelowercase = strtolower($module); // Dir for module $diroflang = dol_buildpath($modulelowercase, 0); $diroflang .= '/langs'; $langfiles = dol_dir_list($diroflang, 'files', 1, '\.lang$'); if (!preg_match('/custom/', $dirread)) { // If this is not a module into custom $diroflang = $dirread; $diroflang .= '/langs'; $langfiles = dol_dir_list($diroflang, 'files', 1, $modulelowercase.'\.lang$'); } print ''; foreach ($langfiles as $langfile) { $pathtofile = $modulelowercase.'/langs/'.$langfile['relativename']; if (!preg_match('/custom/', $dirread)) { // If this is not a module into custom $pathtofile = 'langs/'.$langfile['relativename']; } print ''; } print '
'.$langs->trans("LanguageFile").' '.basename(dirname($pathtofile)).' : '.$pathtofile.''; print ''.img_picto($langs->trans("Edit"), 'edit').''; print ''.img_picto($langs->trans("Delete"), 'delete').''; print '
'; } else { // Edit text language file //print $langs->trans("UseAsciiDocFormat").'
'; $fullpathoffile = dol_buildpath($file, 0); $content = file_get_contents($fullpathoffile); // New module print '
'; print ''; print ''; print ''; print ''; print ''; $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%'); print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'text')); print '
'; print '
'; print ''; print '   '; print ''; print '
'; print '
'; } } if ($tab == 'objects') { print ''."\n"; $head3 = array(); $h = 0; // Dir for module $dir = $dirread.'/'.$modulelowercase.'/class'; $head3[$h][0] = $_SERVER["PHP_SELF"].'?tab=objects&module='.$module.($forceddirread ? '@'.$dirread : '').'&tabobj=newobject'; $head3[$h][1] = ''.$langs->trans("NewObjectInModulebuilder").''; $head3[$h][2] = 'newobject'; $h++; // Scan for object class files $listofobject = dol_dir_list($dir, 'files', 0, '\.class\.php$'); $firstobjectname = ''; foreach ($listofobject as $fileobj) { if (preg_match('/^api_/', $fileobj['name'])) { continue; } if (preg_match('/^actions_/', $fileobj['name'])) { continue; } $tmpcontent = file_get_contents($fileobj['fullname']); if (preg_match('/class\s+([^\s]*)\s+extends\s+CommonObject/ims', $tmpcontent, $reg)) { //$objectname = preg_replace('/\.txt$/', '', $fileobj['name']); $objectname = $reg[1]; if (empty($firstobjectname)) { $firstobjectname = $objectname; } $pictoname = 'generic'; if (preg_match('/\$picto\s*=\s*["\']([^"\']+)["\']/', $tmpcontent, $reg)) { $pictoname = $reg[1]; } $head3[$h][0] = $_SERVER["PHP_SELF"].'?tab=objects&module='.$module.($forceddirread ? '@'.$dirread : '').'&tabobj='.$objectname; $head3[$h][1] = img_picto('', $pictoname, 'class="pictofixedwidth valignmiddle"').$objectname; $head3[$h][2] = $objectname; $h++; } } if ($h > 1) { $head3[$h][0] = $_SERVER["PHP_SELF"].'?tab=objects&module='.$module.($forceddirread ? '@'.$dirread : '').'&tabobj=deleteobject'; $head3[$h][1] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("DangerZone"); $head3[$h][2] = 'deleteobject'; $h++; } // If tabobj was not defined, then we check if there is one obj. If yes, we force on it, if no, we will show tab to create new objects. if ($tabobj == 'newobjectifnoobj') { if ($firstobjectname) { $tabobj = $firstobjectname; } else { $tabobj = 'newobject'; } } print dol_get_fiche_head($head3, $tabobj, '', -1, '', 0, '', '', 0, 'forobjectsuffix'); // Level 3 if ($tabobj == 'newobject') { // New object tab print '
'; print ''; print ''; print ''; print ''; // Tabs selected by default = all optional tabs; reflect posted state on redisplay $enabledtabsdefault = GETPOSTISSET('enabledtab') ? GETPOST('enabledtab', 'array') : array_keys(getModuleBuilderObjectTabs()); print ''.$langs->trans("EnterNameOfObjectDesc").'

'; print '
'; print '
'; print ''.$langs->trans("ObjectKey").'   '; print '
'; print ''; print $form->textwithpicto('', $langs->trans("Example").': MyObject, ACamelCaseName, ...'); print '
'; print '
'; print ''.$langs->trans("Picto").'   '; print '
'; print ''; print $form->textwithpicto('', $langs->trans("Example").': fa-file, fa-globe, ... any font awesome code.
Advanced syntax is fa-fakey[_faprefix[_facolor[_fasize]]] where faprefix can be far,far, facolor can be a text like \'red\' orvalue like \'#FF0000\' and fasize is CSS font size like \'1em\''); print ''; print '     '; print dolButtonToOpenUrlInDialogPopup('popup_picto_id', $langs->transnoentitiesnoconv("DocIconsList"), $langs->transnoentitiesnoconv("DocIconsList"), '/admin/tools/ui/components/icons.php?hidenavmenu=1&displayMode=icon-only&mode=no-btn#img-picto-section-list', '', ''); print ''; print '
'; print '
'; print ''.$langs->trans("DefinePropertiesFromExistingTable").'   '; print '
'; print ''; print $form->textwithpicto('', $langs->trans("DefinePropertiesFromExistingTableDesc").'
'.$langs->trans("DefinePropertiesFromExistingTableDesc2")); print '
'; print '
'; print '
'; print '
'; print '
'; print '
'; print '
'; print '
'.$form->textwithpicto($langs->trans("EnabledTabsForObject"), $langs->trans("EnabledTabsForObjectHelp")).'
'; foreach (getModuleBuilderObjectTabs() as $tabkey => $tabinfo) { $checked = in_array($tabkey, $enabledtabsdefault, true) ? ' checked' : ''; print ' '; print '   '; } print '
'; print '
'; print ''; print '
'; print '
'; /* print '
'; print ''.$langs->trans("or").''; print '
'; print '
'; //print ' '; print $langs->trans("InitStructureFromExistingTable"); print ''; print ''; print '
'; */ print '
'; } elseif ($tabobj == 'createproperty') { $attributesUnique = array( 'proplabel' => $form->textwithpicto($langs->trans("Label"), $langs->trans("YouCanUseTranslationKey")), 'propname' => $form->textwithpicto($langs->trans("Code"), $langs->trans("PropertyDesc"), 1, 'help', 'extracss', 0, 3, 'propertyhelp'), 'proptype' => $form->textwithpicto($langs->trans("Type"), $langs->trans("TypeOfFieldsHelpIntro").'

'.$langs->trans("TypeOfFieldsHelp"), 1, 'help', 'extracss', 0, 3, 'typehelp'), 'proparrayofkeyval' => $form->textwithpicto($langs->trans("ArrayOfKeyValues"), $langs->trans("ArrayOfKeyValuesDesc")), 'propnotnull' => $form->textwithpicto($langs->trans("NotNull"), $langs->trans("NotNullDesc")), 'propdefault' => $langs->trans("DefaultValue"), 'propindex' => $langs->trans("DatabaseIndex"), 'propforeignkey' => $form->textwithpicto($langs->trans("ForeignKey"), $langs->trans("ForeignKeyDesc"), 1, 'help', 'extracss', 0, 3, 'foreignkeyhelp'), 'propposition' => $langs->trans("Position"), 'propenabled' => $form->textwithpicto($langs->trans("Enabled"), $langs->trans("EnabledDesc"), 1, 'help', 'extracss', 0, 3, 'enabledhelp'), 'propvisible' => $form->textwithpicto($langs->trans("Visibility"), $langs->trans("VisibleDesc").'

'.$langs->trans("ItCanBeAnExpression"), 1, 'help', 'extracss', 0, 3, 'visiblehelp'), 'propnoteditable' => $langs->trans("NotEditable"), //'propalwayseditable' => $langs->trans("AlwaysEditable"), 'propsearchall' => $form->textwithpicto($langs->trans("SearchAll"), $langs->trans("SearchAllDesc")), 'propisameasure' => $form->textwithpicto($langs->trans("IsAMeasure"), $langs->trans("IsAMeasureDesc")), 'propcss' => $langs->trans("CSSClass"), 'propcssview' => $langs->trans("CSSViewClass"), 'propcsslist' => $langs->trans("CSSListClass"), 'prophelp' => $langs->trans("KeyForTooltip"), 'propshowoncombobox' => $langs->trans("ShowOnCombobox"), //'propvalidate' => $form->textwithpicto($langs->trans("Validate"), $langs->trans("ValidateModBuilderDesc")), 'propcomment' => $langs->trans("Comment"), ); print '
'; print ''; print ''; print ''; print ''; print ''; print ''."\n"; $counter = 0; foreach ($attributesUnique as $key => $attribute) { if ($counter % 2 === 0) { print ''; } if ($key == 'propname' || $key == 'proplabel') { print ''; } elseif ($key == 'proptype') { print ''; //} elseif ($key == 'propvalidate') { // print ''; } elseif ($key == 'propvisible') { print ''; } elseif ($key == 'propenabled') { //$default = "isModEnabled('".strtolower($module)."')"; $default = 1; print ''; } elseif ($key == 'proparrayofkeyval') { print ''; } else { print ''; } $counter++; if ($counter % 2 === 0) { print ''; } } if ($counter % 2 !== 0) { while ($counter % 2 !== 0) { print ''; $counter++; } print ''; } print '
'.$attribute.''.$attribute.''; print ''; //print '
'; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; // Combo with list of fields /* if (empty($formadmin)) { include_once DOL_DOCUMENT_ROOT.'/core/class/html.formadmin.class.php'; $formadmin = new FormAdmin($db); } print $formadmin->selectTypeOfFields($key, GETPOST($key, 'alpha')); */ print ''; print '
'.$attribute.''.$attribute.''.$attribute.''.$attribute.''.$attribute.'

'."\n"; print '
'; print ''; print ''; print '
'; print '
'; // javascript print ''; } elseif ($tabobj == 'deleteobject') { // Delete object tab print '
'; print ''; print ''; print ''; print ''; print ''; print $langs->trans("EnterNameOfObjectToDeleteDesc").'

'; print ''; print ''; print '
'; } else { // tabobj = module if ($action == 'deleteproperty') { $formconfirm = $form->formconfirm( $_SERVER["PHP_SELF"].'?propertykey='.urlencode(GETPOST('propertykey', 'alpha')).'&objectname='.urlencode($objectname).'&tab='.urlencode($tab).'&module='.urlencode($module).'&tabobj='.urlencode($tabobj), $langs->trans('Delete'), $langs->trans('ConfirmDeleteProperty', GETPOST('propertykey', 'alpha')), 'confirm_deleteproperty', '', 0, 1 ); // Print form confirm print $formconfirm; } if ($action != 'editfile' || empty($file)) { try { //$pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath']; $pathtoclass = strtolower($module).'/class/'.strtolower($tabobj).'.class.php'; $pathtoapi = strtolower($module).'/class/api_'.strtolower($module).'.class.php'; $pathtoagenda = strtolower($module).'/'.strtolower($tabobj).'_agenda.php'; $pathtocard = strtolower($module).'/'.strtolower($tabobj).'_card.php'; $pathtodocument = strtolower($module).'/'.strtolower($tabobj).'_document.php'; $pathtolist = strtolower($module).'/'.strtolower($tabobj).'_list.php'; $pathtonote = strtolower($module).'/'.strtolower($tabobj).'_note.php'; $pathtocontact = strtolower($module).'/'.strtolower($tabobj).'_contact.php'; $pathtophpunit = strtolower($module).'/test/phpunit/'.strtolower($tabobj).'Test.php'; // Try to load object class file clearstatcache(true); if (function_exists('opcache_invalidate')) { opcache_invalidate($dirread.'/'.$pathtoclass, true); // remove the include cache hell ! } if (empty($forceddirread) && empty($dirread)) { $result = dol_include_once($pathtoclass); $stringofinclude = "dol_include_once(".$pathtoclass.")"; } else { $result = include_once $dirread.'/'.$pathtoclass; $stringofinclude = "@include_once ".$dirread.'/'.$pathtoclass; } if (class_exists($tabobj)) { try { $tmpobject = @new $tabobj($db); } catch (Exception $e) { dol_syslog('Failed to load Constructor of class: '.$e->getMessage(), LOG_WARNING); } } else { print ''.$langs->trans('Failed to find the class '.$tabobj.' despite the '.$stringofinclude).'

'; } // Define path for sql file $pathtosql = strtolower($module).'/sql/llx_'.strtolower($module).'_'.strtolower($tabobj).'-'.strtolower($module).'.sql'; $result = dol_buildpath($pathtosql); if (! dol_is_file($result)) { $pathtosql = strtolower($module).'/sql/llx_'.strtolower($module).'_'.strtolower($tabobj).'.sql'; $result = dol_buildpath($pathtosql); if (! dol_is_file($result)) { $pathtosql = 'install/mysql/tables/llx_'.strtolower($module).'_'.strtolower($tabobj).'-'.strtolower($module).'.sql'; $result = dol_buildpath($pathtosql); if (! dol_is_file($result)) { $pathtosql = 'install/mysql/tables/llx_'.strtolower($module).'-'.strtolower($module).'.sql'; $result = dol_buildpath($pathtosql); if (! dol_is_file($result)) { $pathtosql = 'install/mysql/tables/llx_'.strtolower($module).'.sql'; $pathtosqlextra = 'install/mysql/tables/llx_'.strtolower($module).'_extrafields.sql'; $result = dol_buildpath($pathtosql); } else { $pathtosqlextra = 'install/mysql/tables/llx_'.strtolower($module).'_extrafields-'.strtolower($module).'.sql'; } } else { $pathtosqlextra = 'install/mysql/tables/llx_'.strtolower($module).'_'.strtolower($tabobj).'_extrafields-'.strtolower($module).'.sql'; } } else { $pathtosqlextra = strtolower($module).'/sql/llx_'.strtolower($module).'_'.strtolower($tabobj).'_extrafields.sql'; } } else { $pathtosqlextra = strtolower($module).'/sql/llx_'.strtolower($module).'_'.strtolower($tabobj).'_extrafields-'.strtolower($module).'.sql'; } $pathtosqlroot = preg_replace('/\/llx_.*$/', '', $pathtosql); $pathtosqlkey = preg_replace('/\.sql$/', '.key.sql', $pathtosql); $pathtosqlextrakey = preg_replace('/\.sql$/', '.key.sql', $pathtosqlextra); $pathtolib = strtolower($module).'/lib/'.strtolower($module).'.lib.php'; $pathtoobjlib = strtolower($module).'/lib/'.strtolower($module).'_'.strtolower($tabobj).'.lib.php'; $tmpobject = $tmpobject ?? null; // @phan-suppress-current-line PhanPluginDuplicateExpressionAssignmentOperation if (is_object($tmpobject) && property_exists($tmpobject, 'picto')) { $pathtopicto = $tmpobject->picto; $realpathtopicto = ''; } else { $pathtopicto = strtolower($module).'/img/object_'.strtolower($tabobj).'.png'; $realpathtopicto = $dirread.'/'.$pathtopicto; } //var_dump($pathtoclass); //var_dump($dirread); $realpathtoclass = $dirread.'/'.$pathtoclass; $realpathtoapi = $dirread.'/'.$pathtoapi; $realpathtoagenda = $dirread.'/'.$pathtoagenda; $realpathtocard = $dirread.'/'.$pathtocard; $realpathtodocument = $dirread.'/'.$pathtodocument; $realpathtolist = $dirread.'/'.$pathtolist; $realpathtonote = $dirread.'/'.$pathtonote; $realpathtocontact = $dirread.'/'.$pathtocontact; $realpathtophpunit = $dirread.'/'.$pathtophpunit; $realpathtosql = $dirread.'/'.$pathtosql; $realpathtosqlextra = $dirread.'/'.$pathtosqlextra; $realpathtosqlkey = $dirread.'/'.$pathtosqlkey; $realpathtosqlextrakey = $dirread.'/'.$pathtosqlextrakey; $realpathtolib = $dirread.'/'.$pathtolib; $realpathtoobjlib = $dirread.'/'.$pathtoobjlib; if (empty($realpathtoapi)) { // For compatibility with some old modules $pathtoapi = strtolower($module).'/class/api_'.strtolower($module).'s.class.php'; $realpathtoapi = $dirread.'/'.$pathtoapi; } $urloflist = dol_buildpath('/'.$pathtolist, 1); $urlofcard = dol_buildpath('/'.$pathtocard, 1); $objs = array(); // Image $htmltooltip = ''; if ($realpathtopicto && dol_is_file($realpathtopicto)) { $htmltooltip .= ' '.$langs->trans("Image").' : '.(dol_is_file($realpathtopicto) ? '' : '').preg_replace('/^'.strtolower($module).'\//', '', $pathtopicto).(dol_is_file($realpathtopicto) ? '' : '').''; $htmltooltip .= '
'; } elseif (!empty($tmpobject)) { $htmltooltip .= ' '.$langs->trans("Image").' : '.img_picto('', $tmpobject->picto, 'class="pictofixedwidth valignmiddle"').$tmpobject->picto; $htmltooltip .= '
'; } $htmltooltip .= ' '.$langs->trans("IsExtraFieldManaged").' : '.yn(empty($tmpobject->isextrafieldmanaged) ? 0 : 1, 1, 2); $htmltooltip .= '
'; $htmltooltip .= ' '.$langs->trans("IsMultiEntityManaged").' : '.yn(empty($tmpobject->ismultientitymanaged) ? 0 : 1, 1, 2); $htmltooltip .= '
'; print ''; print '
'; // Main DAO class file print ' '.$langs->trans("ClassFile").' : '.(dol_is_file($realpathtoclass) ? '' : '').preg_replace('/^'.strtolower($module).'\//', '', $pathtoclass).(dol_is_file($realpathtoclass) ? '' : '').''; print ' '.img_picto($langs->trans("Edit"), 'edit').''; print $form->textwithpicto('', $htmltooltip, 1, 'help', 'valignmiddle', 1); print '
'; // API file print '
'; print ' '.$langs->trans("ApiClassFile").' : '.(dol_is_file($realpathtoapi) ? '' : '').preg_replace('/^'.strtolower($module).'\//', '', $pathtoapi).(dol_is_file($realpathtoapi) ? '' : '').''; if (dol_is_file($realpathtoapi)) { $file = file_get_contents($realpathtoapi); if (preg_match('/var '.$tabobj.'\s+([^\s]*)\s/ims', $file, $objs)) { print ' '.img_picto($langs->trans("Edit"), 'edit').''; print ' '; print ''.img_picto($langs->trans("Delete"), 'delete').''; print $form->textwithpicto('', $langs->trans("InfoForApiFile"), 1, 'warning'); print '   '; // Comparing to null (phan considers $modulelowercase can be null here) if (!isModEnabled($modulelowercase)) { // If module is not activated print ''.$langs->trans("ApiExplorer").''; } else { print ''.$langs->trans("ApiExplorer").''; } } else { print ''.img_picto($langs->trans('AddAPIsForThisObject'), 'generate', 'class="paddingleft"').''; } } else { print ''.img_picto('Generate', 'generate', 'class="paddingleft"').''; } // PHPUnit print '
'; print ' '.$langs->trans("TestClassFile").' : '.(dol_is_file($realpathtophpunit) ? '' : '').preg_replace('/^'.strtolower($module).'\//', '', $pathtophpunit).(dol_is_file($realpathtophpunit) ? '' : '').''; if (dol_is_file($realpathtophpunit)) { print ' '.img_picto($langs->trans("Edit"), 'edit').''; print ' '; print ''.img_picto($langs->trans("Delete"), 'delete').''; } else { print ''.img_picto('Generate', 'generate', 'class="paddingleft"').''; } print '
'; print '
'; print ' '.$langs->trans("PageForLib").' : '.(dol_is_file($realpathtolib) ? '' : '').preg_replace('/^'.strtolower($module).'\//', '', $pathtolib).(dol_is_file($realpathtolib) ? '' : '').''; print ' '.img_picto($langs->trans("Edit"), 'edit').''; print '
'; print ' '.$langs->trans("PageForObjLib").' : '.(dol_is_file($realpathtoobjlib) ? '' : '').preg_replace('/^'.strtolower($module).'\//', '', $pathtoobjlib).(dol_is_file($realpathtoobjlib) ? '' : '').''; print ' '.img_picto($langs->trans("Edit"), 'edit').''; print '
'; print '
'; print ' '.$langs->trans("SqlFile").' : '.(dol_is_file($realpathtosql) ? '' : '').preg_replace('/^'.strtolower($module).'\//', '', $pathtosql).(dol_is_file($realpathtosql) ? '' : '').''; print ' '.img_picto($langs->trans("Edit"), 'edit').''; print '   '.$langs->trans("DropTableIfEmpty").''; //print '   '.$langs->trans("RunSql").''; print '
'; print ' '.$langs->trans("SqlFileKey").' : '.(dol_is_file($realpathtosqlkey) ? '' : '').preg_replace('/^'.strtolower($module).'\//', '', $pathtosqlkey).(dol_is_file($realpathtosqlkey) ? '' : '').''; print ' '.img_picto($langs->trans("Edit"), 'edit').''; //print '   '.$langs->trans("RunSql").''; print '
'; if (!empty($tmpobject->isextrafieldmanaged)) { print ' '.$langs->trans("SqlFileExtraFields").' : '.(dol_is_file($realpathtosqlextra) ? '' : '').preg_replace('/^'.strtolower($module).'\//', '', $pathtosqlextra).(dol_is_file($realpathtosqlextra) && dol_is_file($realpathtosqlextrakey) ? '' : '').''; if (dol_is_file($realpathtosqlextra) && dol_is_file($realpathtosqlextrakey)) { print ' '.img_picto($langs->trans("Edit"), 'edit').''; print ' '; print ''.img_picto($langs->trans("Delete"), 'delete').''; print '   '; print ''.$langs->trans("DropTableIfEmpty").''; } else { print ''.img_picto('Generate', 'generate', 'class="paddingleft"').''; } //print '   '.$langs->trans("RunSql").''; print '
'; print ' '.$langs->trans("SqlFileKeyExtraFields").' : '.(dol_is_file($realpathtosqlextrakey) ? '' : '').preg_replace('/^'.strtolower($module).'\//', '', $pathtosqlextrakey).(dol_is_file($realpathtosqlextra) && dol_is_file($realpathtosqlextrakey) ? '' : '').''; if (dol_is_file($realpathtosqlextra) && dol_is_file($realpathtosqlextrakey)) { print ' '.img_picto($langs->trans("Edit"), 'edit').''; print ' '; print ''.img_picto($langs->trans("Delete"), 'delete').''; } else { print ''.img_picto('Generate', 'generate', 'class="paddingleft"').''; } print '
'; } print '
'; print '
'; print ' '.$langs->trans("PageForList").' : '.(dol_is_file($realpathtolist) ? '' : '').preg_replace('/^'.strtolower($module).'\//', '', $pathtolist).(dol_is_file($realpathtolist) ? '' : '').''; print ' '.img_picto($langs->trans("Edit"), 'edit').''; print '
'; print ' '.$langs->trans("PageForCreateEditView").' : '.(dol_is_file($realpathtocard) ? '' : '').preg_replace('/^'.strtolower($module).'\//', '', $pathtocard).(dol_is_file($realpathtocard) ? '' : '').'?action=create'; print ' '.img_picto($langs->trans("Edit"), 'edit').''; print '
'; // Page contact print ' '.$langs->trans("PageForContactTab").' : '.(dol_is_file($realpathtocontact) ? '' : '').preg_replace('/^'.strtolower($module).'\//', '', $pathtocontact).(dol_is_file($realpathtocontact) ? '' : '').''; print ' '.img_picto($langs->trans("Edit"), 'edit').''; if (dol_is_file($realpathtocontact)) { print ' '; print ''.img_picto($langs->trans("Delete"), 'delete').''; } else { print ''.img_picto('Generate', 'generate', 'class="paddingleft"').''; } print '
'; // Page document print ' '.$langs->trans("PageForDocumentTab").' : '.(dol_is_file($realpathtodocument) ? '' : '').preg_replace('/^'.strtolower($module).'\//', '', $pathtodocument).(dol_is_file($realpathtodocument) ? '' : '').''; print ' '.img_picto($langs->trans("Edit"), 'edit').''; if (dol_is_file($realpathtodocument)) { print ' '; print ''.img_picto($langs->trans("Delete"), 'delete').''; } else { print ''.img_picto('Generate', 'generate', 'class="paddingleft"').''; } print '
'; // Page notes print ' '.$langs->trans("PageForNoteTab").' : '.(dol_is_file($realpathtonote) ? '' : '').preg_replace('/^'.strtolower($module).'\//', '', $pathtonote).(dol_is_file($realpathtonote) ? '' : '').''; print ' '.img_picto($langs->trans("Edit"), 'edit').''; if (dol_is_file($realpathtonote)) { print ' '; print ''.img_picto($langs->trans("Delete"), 'delete').''; } else { print ''.img_picto('Generate', 'generate', 'class="paddingleft"').''; } print '
'; // Page agenda print ' '.$langs->trans("PageForAgendaTab").' : '.(dol_is_file($realpathtoagenda) ? '' : '').preg_replace('/^'.strtolower($module).'\//', '', $pathtoagenda).(dol_is_file($realpathtoagenda) ? '' : '').''; print ' '.img_picto($langs->trans("Edit"), 'edit').''; if (dol_is_file($realpathtoagenda)) { print ' '; print ''.img_picto($langs->trans("Delete"), 'delete').''; } else { print ''.img_picto('Generate', 'generate', 'class="paddingleft"').''; } print '
'; print '
'; print '
'; print '


'; if (!empty($tmpobject)) { $reflector = new ReflectionClass($tabobj); $reflectorproperties = $reflector->getProperties(); // Can also use get_object_vars $reflectorpropdefault = $reflector->getDefaultProperties(); // Can also use get_object_vars //$propstat = $reflector->getStaticProperties(); //var_dump($reflectorpropdefault); print '
'; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print '

'; print '
'; $mod = strtolower($module); $obj = strtolower($tabobj); $newproperty = dolGetButtonTitle($langs->trans('NewProperty'), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/modulebuilder/index.php?tab=objects&module='.urlencode($module).'&tabobj=createproperty&obj='.urlencode($tabobj)); $nbOfProperties = count($reflectorpropdefault['fields']); print_barre_liste($langs->trans("ObjectProperties"), 0, $_SERVER["PHP_SELF"], '', '', '', '', 0, $nbOfProperties, '', 0, $newproperty, 'margintoponly', 0, 0, 0, 1); //var_dump($reflectorpropdefault);exit; print ''."\n"; print '
'; print ''; print ''; if (!empty($conf->main_checkbox_left_column)) { print ''; } print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; //print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; //print ''; print ''; print ''; if (empty($conf->main_checkbox_left_column)) { print ''; } print ''; // We must use $reflectorpropdefault['fields'] to get list of fields because $tmpobject->fields may have been // modified during the constructor and we want value into head of class before constructor is called. //$properties = dol_sort_array($tmpobject->fields, 'position'); $properties = dol_sort_array($reflectorpropdefault['fields'], 'position'); if (!empty($properties)) { // List of existing properties foreach ($properties as $propkey => $propval) { /* If from Reflection if ($propval->class == $tabobj) { $propname=$propval->getName(); $comment=$propval->getDocComment(); $type=gettype($tmpobject->$propname); $default=$propdefault[$propname]; // Discard generic properties if (in_array($propname, array('element', 'childtables', 'table_element', 'table_element_line', 'class_element_line', 'ismultientitymanaged'))) continue; // Keep or not lines if (in_array($propname, array('fk_element', 'lines'))) continue; }*/ $propname = $propkey; $proplabel = $propval['label']; $proptype = $propval['type']; $proparrayofkeyval = !empty($propval['arrayofkeyval']) ? $propval['arrayofkeyval'] : ''; $propnotnull = !empty($propval['notnull']) ? $propval['notnull'] : '0'; $propdefault = !empty($propval['default']) ? $propval['default'] : ''; $propindex = !empty($propval['index']) ? $propval['index'] : ''; $propforeignkey = !empty($propval['foreignkey']) ? $propval['foreignkey'] : ''; $propposition = $propval['position']; $propenabled = $propval['enabled']; $propvisible = $propval['visible']; $propnoteditable = !empty($propval['noteditable']) ? $propval['noteditable'] : 0; //$propalwayseditable = !empty($propval['alwayseditable'])?$propval['alwayseditable']:0; $propsearchall = !empty($propval['searchall']) ? $propval['searchall'] : 0; $propisameasure = !empty($propval['isameasure']) ? $propval['isameasure'] : 0; $propcss = !empty($propval['css']) ? $propval['css'] : ''; $propcssview = !empty($propval['cssview']) ? $propval['cssview'] : ''; $propcsslist = !empty($propval['csslist']) ? $propval['csslist'] : ''; $prophelp = !empty($propval['help']) ? $propval['help'] : ''; $propshowoncombobox = !empty($propval['showoncombobox']) ? $propval['showoncombobox'] : 0; //$propdisabled=$propval['disabled']; $propvalidate = !empty($propval['validate']) ? $propval['validate'] : 0; $propcomment = !empty($propval['comment']) ? $propval['comment'] : ''; print ''."\n"; print ''; if (!empty($conf->main_checkbox_left_column)) { if ($action == 'editproperty' && $propname == $propertykey) { print ''; } else { print ''; } } print ''; if ($action == 'editproperty' && $propname == $propertykey) { print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; /*print '';*/ print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; if (empty($conf->main_checkbox_left_column)) { print ''; } } else { print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; // Visibility print ''; // Readonly print ''; /*print '';*/ print ''; print ''; print ''; print ''; print ''; // Key for tooltop print ''; print ''; /*print '';*/ print ''; print ''; if (empty($conf->main_checkbox_left_column)) { print ''; } } print ''; } } else { if ($tab == 'specifications') { if ($action != 'editfile' || empty($file)) { print ''.$langs->trans("SpecDefDesc").'
'; print '
'; $specs = dol_dir_list(dol_buildpath($modulelowercase.'/doc', 0), 'files', 1, '(\.md|\.asciidoc)$', array('\/temp\/')); foreach ($specs as $spec) { $pathtofile = $modulelowercase.'/doc/'.$spec['relativename']; $format = 'asciidoc'; if (preg_match('/\.md$/i', $spec['name'])) { $format = 'markdown'; } print ' '.$langs->trans("SpecificationFile").' : '.$pathtofile.''; print ' '.img_picto($langs->trans("Edit"), 'edit').''; print '
'; } } else { // Use MD or asciidoc //print $langs->trans("UseAsciiDocFormat").'
'; $fullpathoffile = dol_buildpath($file, 0); $content = file_get_contents($fullpathoffile); // New module print ''; print ''; print ''; print ''; print ''; print ''; $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%'); print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'html')); print '
'; print '
'; print ''; print '   '; print ''; print '
'; print ''; } } $langs->load("errors"); print ''; } print '
'; $htmltext = $langs->trans("PropertyDesc").'

'.$langs->trans("SeeExamples").''; print $form->textwithpicto($langs->trans("Code"), $htmltext, 1, 'help', 'extracss', 0, 3, 'propertyhelp'); print '
'; print $form->textwithpicto($langs->trans("Label"), $langs->trans("YouCanUseTranslationKey")); print ''.$form->textwithpicto($langs->trans("Type"), $langs->trans("TypeOfFieldsHelpIntro").'

'.$langs->trans("TypeOfFieldsHelp"), 1, 'help', 'extracss', 0, 3, 'typehelp').'
'.$form->textwithpicto($langs->trans("ArrayOfKeyValues"), $langs->trans("ArrayOfKeyValuesDesc")).''.$form->textwithpicto($langs->trans("NotNull"), $langs->trans("NotNullDesc")).''.$langs->trans("DefaultValue").''.$langs->trans("DatabaseIndex").''.$form->textwithpicto($langs->trans("ForeignKey"), $langs->trans("ForeignKeyDesc"), 1, 'help', 'extracss', 0, 3, 'foreignkeyhelp').''.$langs->trans("Position").''.$form->textwithpicto($langs->trans("Enabled"), $langs->trans("EnabledDesc"), 1, 'help', 'extracss', 0, 3, 'enabledhelp').''.$form->textwithpicto($langs->trans("Visibility"), $langs->trans("VisibleDesc").'

'.$langs->trans("ItCanBeAnExpression"), 1, 'help', 'extracss', 0, 3, 'visiblehelp').'
'.$langs->trans("NotEditable").''.$langs->trans("AlwaysEditable").''.$form->textwithpicto($langs->trans("SearchAll"), $langs->trans("SearchAllDesc")).''.$form->textwithpicto($langs->trans("IsAMeasure"), $langs->trans("IsAMeasureDesc")).''.$langs->trans("CSSClass").''.$langs->trans("CSSViewClass").''.$langs->trans("CSSListClass").''.$langs->trans("KeyForTooltip").''.$langs->trans("ShowOnCombobox").''.$langs->trans("Disabled").''.$form->textwithpicto($langs->trans("Validate"), $langs->trans("ValidateModBuilderDesc")).''.$langs->trans("Comment").'
'; print ''; print ''; print ''; if ($propname != 'rowid') { print ''.img_edit().''; print ''.img_delete().''; } print ''; print dol_escape_htmltag($propname); print ''; print ''; print ''; print ''; print ''; // Use the samedatalist than for create print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; // Combo with list of fields /* if (empty($formadmin)) { include_once DOL_DOCUMENT_ROOT.'/core/class/html.formadmin.class.php'; $formadmin = new FormAdmin($db); } print $formadmin->selectTypeOfFields($key, GETPOST($key, 'alpha')); */ print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print dol_escape_htmltag($proplabel); print ''; $pictoType = ''; $matches = array(); if (preg_match('/^varchar/', $proptype, $matches)) { $pictoType = 'varchar'; } elseif (preg_match('/^integer:/', $proptype, $matches)) { $pictoType = 'link'; } elseif (strpos($proptype, 'integer') === 0) { $pictoType = substr($proptype, 0, 3); } elseif (strpos($proptype, 'timestamp') === 0) { $pictoType = 'datetime'; } elseif (strpos($proptype, 'real') === 0) { $pictoType = 'double'; } elseif (strpos($proptype, 'stars') === 0) { $pictoType = 'stars'; } print(!empty($pictoType) ? getPictoForType($pictoType) : getPictoForType($proptype)).''.dol_escape_htmltag($proptype).''; print ''; if ($proparrayofkeyval) { print ''; print dol_escape_htmltag(json_encode($proparrayofkeyval, JSON_UNESCAPED_UNICODE)); print ''; } print ''; print dol_escape_htmltag($propnotnull); print ''; print dol_escape_htmltag($propdefault); print ''; print $propindex ? '1' : ''; print ''; print $propforeignkey ? dol_escape_htmltag($propforeignkey) : ''; print ''; print dol_escape_htmltag($propposition); print ''; print $propenabled ? dol_escape_htmltag($propenabled) : ''; print ''; print $propvisible ? dol_escape_htmltag($propvisible) : '0'; print ''; print $propnoteditable ? dol_escape_htmltag($propnoteditable) : ''; print ''; print $propalwayseditable ? dol_escape_htmltag($propalwayseditable) : ''; print ''; print $propsearchall ? '1' : ''; print ''; print $propisameasure ? dol_escape_htmltag($propisameasure) : ''; print ''; print $propcss ? dol_escape_htmltag($propcss) : ''; print ''; print $propcssview ? dol_escape_htmltag($propcssview) : ''; print ''; print $propcsslist ? dol_escape_htmltag($propcsslist) : ''; print ''; print $prophelp ? dol_escape_htmltag($prophelp) : ''; print ''; print $propshowoncombobox ? dol_escape_htmltag($propshowoncombobox) : ''; print ''; print $propdisabled?$propdisabled:''; print ''; print $propvalidate ? dol_escape_htmltag($propvalidate) : ''; print ''; print ''; print dol_escape_htmltag($propcomment); print ''; print ''; if ($propname != 'rowid') { print ''.img_edit().''; print ''.img_delete().''; } print '
'.$langs->trans('ErrorModuleBuilderNoFieldProperty').'
'; print '
'; print ''; } else { $langs->load("errors"); print ''.$langs->trans('ErrorModuleBuilderFailedToInit', $tabobj, (string) $db).''; } } catch (Exception $e) { print 'ee'; print $e->getMessage(); print 'ff'; } } else { if (empty($forceddirread)) { $fullpathoffile = dol_buildpath($file, 0); } else { $fullpathoffile = $dirread.'/'.$file; } $content = file_get_contents($fullpathoffile); // New module print '
'; print ''; print ''; print ''; print ''; print ''; print ''; $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%'); print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'html')); print '
'; print '
'; print ''; print '   '; print ''; print '
'; print '
'; } } print dol_get_fiche_end(); // Level 3 } if ($tab == 'dictionaries') { print ''."\n"; $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath']; $dicts = $moduleobj->dictionaries; if ($action == 'deletedict') { $formconfirm = $form->formconfirm( $_SERVER["PHP_SELF"].'?dictionnarykey='.urlencode((string) (GETPOSTINT('dictionnarykey'))).'&tab='.urlencode((string) ($tab)).'&module='.urlencode((string) ($module)), $langs->trans('Delete'), $langs->trans('Confirm Delete Dictionnary', GETPOST('dictionnarykey', 'alpha')), 'confirm_deletedictionary', '', 0, 1 ); print $formconfirm; } if ($action != 'editfile' || empty($file)) { print ''; $htmlhelp = $langs->trans("DictionariesDefDescTooltip", '{s1}'); $htmlhelp = str_replace('{s1}', ''.$langs->trans('Setup').' - '.$langs->trans('Dictionaries').'', $htmlhelp); print $form->textwithpicto($langs->trans("DictionariesDefDesc"), $htmlhelp, 1, 'help', '', 0, 2, 'helpondesc').'
'; print '
'; print '
'; print ' '.$langs->trans("DescriptorFile").' : '.$pathtofile.''; print ' '.img_picto($langs->trans("Edit"), 'edit').''; print '
'; if (is_array($dicts) && !empty($dicts)) { print ' '.$langs->trans("LanguageFile").' :
'; print ''.$dicts['langs'].''; print '
'; } print '
'; $head3 = array(); $h = 0; // Dir for module //$dir = $dirread.'/'.$modulelowercase.'/class'; $head3[$h][0] = $_SERVER["PHP_SELF"].'?tab=dictionaries&module='.$module.($forceddirread ? '@'.$dirread : '').'&tabdic=newdictionary'; $head3[$h][1] = ''.$langs->trans("NewDictionary").''; $head3[$h][2] = 'newdictionary'; $h++; // Scan for object class files //$listofobject = dol_dir_list($dir, 'files', 0, '\.class\.php$'); $firstdicname = ''; // if (!empty($dicts['tabname'])) { // foreach ($dicts['tabname'] as $key => $dic) { // $dicname = $dic; // $diclabel = $dicts['tablib'][$key]; // if (empty($firstdicname)) { // $firstdicname = $dicname; // } // $head3[$h][0] = $_SERVER["PHP_SELF"].'?tab=dictionaries&module='.$module.($forceddirread ? '@'.$dirread : '').'&tabdic='.$dicname; // $head3[$h][1] = $diclabel; // $head3[$h][2] = $dicname; // $h++; // } // } // if ($h > 1) { // $head3[$h][0] = $_SERVER["PHP_SELF"].'?tab=dictionaries&module='.$module.($forceddirread ? '@'.$dirread : '').'&tabdic=deletedictionary'; // $head3[$h][1] = $langs->trans("DangerZone"); // $head3[$h][2] = 'deletedictionary'; // $h++; // } // If tabobj was not defined, then we check if there is one obj. If yes, we force on it, if no, we will show tab to create new objects. // if ($tabdic == 'newdicifnodic') { // if ($firstdicname) { // $tabdic = $firstdicname; // } else { // $tabdic = 'newdictionary'; // } // } //print dol_get_fiche_head($head3, $tabdic, '', -1, ''); // Level 3 $newdict = dolGetButtonTitle($langs->trans('NewDictionary'), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/modulebuilder/index.php?tab=dictionaries&module='.urlencode($module).'&tabdic=newdictionary'); print_barre_liste($langs->trans("ListOfDictionariesEntries"), 0, $_SERVER["PHP_SELF"], '', '', '', '', 0, '', '', 0, $newdict, '', 0, 0, 0, 1); if ($tabdic != 'newdictionary') { print '
'; print ''; print ''; print ''; print ''; print ''; print '
'; print ''; print ''; print_liste_field_titre("#", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, 'thsticky thstickygrey '); print_liste_field_titre("Table", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder); print_liste_field_titre("Label", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder); print_liste_field_titre("SQL", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder); print_liste_field_titre("SQLSort", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder); print_liste_field_titre("FieldsView", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder); print_liste_field_titre("FieldsEdit", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder); print_liste_field_titre("FieldsInsert", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder); print_liste_field_titre("Rowid", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder); print_liste_field_titre("Condition", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder); print_liste_field_titre("", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder); print "\n"; if (!empty($dicts) && is_array($dicts) && !empty($dicts['tabname']) && is_array($dicts['tabname'])) { $i = 0; $maxi = count($dicts['tabname']); while ($i < $maxi) { if ($action == 'editdict' && $i == GETPOSTINT('dictionnarykey') - 1) { print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; } else { print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; } $i++; } } else { print ''; } print '
'; print($i + 1); print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print '
'; print ''; print '
'; print($i + 1); print ''; print $dicts['tabname'][$i]; print ''; print $dicts['tablib'][$i]; print ''; print $dicts['tabsql'][$i]; print ''; print $dicts['tabsqlsort'][$i]; print ''; print $dicts['tabfield'][$i]; print ''; print $dicts['tabfieldvalue'][$i]; print ''; print $dicts['tabfieldinsert'][$i]; print ''; print $dicts['tabrowid'][$i]; print ''; print $dicts['tabcond'][$i]; print ''; print ''.img_edit().''; print ''.img_delete().''; print '
'.$langs->trans("None").'
'; print '
'; print ''; } if ($tabdic == 'newdictionary') { // New dic tab print '
'; print ''; print ''; print ''; print ''; print ''; print ''.$langs->trans("EnterNameOfDictionaryDesc").'

'; print dol_get_fiche_head(); print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print '
'.$langs->trans("Table").'
'.$langs->trans("Label").'
'.$langs->trans("SQL").'
'.$langs->trans("SQLSort").'
'.$langs->trans("FieldsView").'
'.$langs->trans("FieldsEdit").'
'.$langs->trans("FieldsInsert").'
'.$langs->trans("Rowid").'
'; print ''; print ''; print dol_get_fiche_end(); print '
'; print ''; /*print '
'; print '
'; print '
'; print ''.$langs->trans("or").''; print '
'; print '
'; //print ' '; print $langs->trans("InitStructureFromExistingTable"); print ''; print ''; print '
'; */ } elseif ($tabdic == 'deletedictionary') { // Delete dic tab print '
'; print ''; print ''; print ''; print ''; print $langs->trans("EnterNameOfDictionnaryToDeleteDesc").'

'; print ''; print ''; print '
'; } print dol_get_fiche_end(); } else { $fullpathoffile = dol_buildpath($file, 0); $content = file_get_contents($fullpathoffile); // New module print '
'; print ''; print ''; print ''; print ''; print ''; $posCursor = (empty($find)) ? array() : array('find' => $find); $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%', 0, $posCursor); print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'html')); print '
'; print '
'; print ''; print '   '; print ''; print '
'; print '
'; } } if ($tab == 'menus') { print ''."\n"; $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath']; $dirins = $listofmodules[strtolower($module)]['moduledescriptorrootpath']; $destdir = $dirins.'/'.strtolower($module); $listofobject = dol_dir_list($destdir.'/class', 'files', 0, '\.class\.php$'); $objects = dolGetListOfObjectClasses($destdir); $leftmenus = array(); $menus = $moduleobj->menu; $permissions = $moduleobj->rights; $crud = array('read' => 'CRUDRead', 'write' => 'CRUDCreateWrite', 'delete' => 'Delete'); //grouped permissions $groupedRights = array(); foreach ($permissions as $right) { $key = $right[4]; if (!isset($groupedRights[$key])) { $groupedRights[$key] = array(); } $groupedRights[$key][] = $right; } $groupedRights_json = json_encode($groupedRights); if ($action == 'deletemenu') { $formconfirms = $form->formconfirm( $_SERVER["PHP_SELF"].'?menukey='.urlencode((string) (GETPOSTINT('menukey'))).'&tab='.urlencode((string) ($tab)).'&module='.urlencode((string) ($module)), $langs->trans('Delete'), ($menus[GETPOST('menukey')]['fk_menu'] === 'fk_mainmenu='.strtolower($module) ? $langs->trans('Warning: you will delete all menus linked to this one.', GETPOSTINT('menukey')) : $langs->trans('Confirm Delete Menu', GETPOSTINT('menukey'))), 'confirm_deletemenu', '', 0, 1 ); print $formconfirms; } if ($action != 'editfile' || empty($file)) { print ''; $htmlhelp = $langs->trans("MenusDefDescTooltip", '{s1}'); $htmlhelp = str_replace('{s1}', ''.$langs->trans('Setup').' - '.$langs->trans('Menus').'', $htmlhelp); print $form->textwithpicto($langs->trans("MenusDefDesc"), $htmlhelp, 1, 'help', '', 0, 2, 'helpondesc').'
'; print '
'; print '
'; // Links to editable files print ' '.$langs->trans("DescriptorFile").' : '.$pathtofile.''; print ' '.img_picto($langs->trans("Edit"), 'edit').''; print '
'; // Search all files of modules mentioned by menu $listODifferentUrlsInMenu = array(); foreach ($menus as $obj) { if (preg_match('/^\/'.preg_quote(strtolower($module), '/').'\//', $obj['url']) && !empty($pathoffile)) { if (!empty($listODifferentUrlsInMenu[$pathoffile])) { // Test to avoid to show same file twice. continue; } $pathtofile = $obj['url']; $listODifferentUrlsInMenu[$pathoffile] = $pathtofile; print ' '.$langs->trans("PageLinkedByAMenuEntry").' : '.$pathtofile.''; print ' '.img_picto($langs->trans("Edit"), 'edit').''; print '
'; } } print '
'; print load_fiche_titre($langs->trans("ListOfMenusEntries"), '', ''); print '
'; print ''; print ''; print ''; print ''; print ''; print '
'; print ''; $htmltextenabled = ''.$langs->trans("Examples").':
'; $htmltextenabled .= '1 (module always enabled)
'; $htmltextenabled .= '0 (module always disabled)
'; $htmltextenabled .= 'isModEnabled(\''.dol_escape_htmltag(strtolower($module)).'\') (enabled when module is enabled)'; $htmltextperms = ''.$langs->trans("Examples").':
'; $htmltextperms .= '1 (access always allowed)
'; $htmltextperms .= '$user->hasright(\''.dol_escape_htmltag(strtolower($module)).'\', \'myobject\', \'read\') (access allowed if user has permission module->object->read)'; print ''; print_liste_field_titre("#", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, 'center tdsticky tdstickygray '); print_liste_field_titre("Position", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder); print_liste_field_titre("Title", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, 'center'); print_liste_field_titre("LinkToParentMenu", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, 'minwidth100 '); print_liste_field_titre("mainmenu", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder); print_liste_field_titre("leftmenu", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder); print_liste_field_titre("URL", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, '', $langs->transnoentitiesnoconv('DetailUrl')); print_liste_field_titre("LanguageFile", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder); print_liste_field_titre("Position", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, 'right '); print_liste_field_titre("Enabled", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, 'center ', $langs->trans('DetailEnabled').'

'.$htmltextenabled); print_liste_field_titre("Rights", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, '', $langs->trans('DetailRight').'

'.$htmltextperms); print_liste_field_titre("Target", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, '', $langs->trans('DetailTarget')); print_liste_field_titre("MenuForUsers", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, 'center minwidth100 ', $langs->trans('DetailUser')); print_liste_field_titre("", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, 'center ', $langs->trans('')); print "\n"; $r = count($menus) + 1; // for adding menu on module print ''; print ''; print ''; print ''; print ''; print ''; print ''; // URL print ''; print ''; // Position print ''; // Enabled print ''; // Perms print ''; print ''; print ''; print ''; print ''; // end form for add menu //var_dump($menus); // Loop on each menu entry if (count($menus)) { $i = 0; foreach ($menus as $menu) { $i++; //for get parent in menu $string = dol_escape_htmltag($menu['fk_menu']); $value = substr($string, strpos($string, 'fk_leftmenu=') + strlen('fk_leftmenu=')); $propFk_menu = !empty($menu['fk_menu']) ? $menu['fk_menu'] : GETPOST('fk_menu'); $propTitre = !empty($menu['titre']) ? $menu['titre'] : GETPOST('titre'); $propMainmenu = !empty($menu['mainmenu']) ? $menu['mainmenu'] : GETPOST('mainmenu'); $propLeftmenu = !empty($menu['leftmenu']) ? $menu['leftmenu'] : GETPOST('leftmenu'); $propUrl = !empty($menu['url']) ? $menu['url'] : GETPOST('url', 'alpha'); $propPerms = !empty($menu['perms']) ? $menu['perms'] : GETPOST('perms'); $propUser = !empty($menu['user']) ? $menu['user'] : GETPOST('user'); $propTarget = !empty($menu['target']) ? $menu['target'] : GETPOST('target'); $propEnabled = !empty($menu['enabled']) ? $menu['enabled'] : GETPOST('enabled'); $objPerms = (empty($arguments[1]) ? '' : trim($arguments[1])); $valPerms = (empty($arguments[2]) ? '' : trim($arguments[2])); //$tabobject = ''; // We can't know what is $tabobject in most cases if ($action == 'editmenu' && GETPOSTINT('menukey') == $i) { //var_dump($propPerms);exit; print ''; print ''; print ''; print ''; print ''; print ''; print ''; //print ''; print ''; // Position (top, left) print ''; // Title print ''; // Parent menu print ''; print ''; print ''; // URL print ''; print ''; // Position print ''; // Enabled print ''; // Permissions print ''; // Target print ''; print ''; print ''; print ''; print ''; } else { print ''; print ''; print ''; // Title print ''; // Parent menu print ''; print ''; print ''; print ''; print ''; // Position print ''; // Enabled print ''; // Perms print ''; // Target print ''; print ''; print ''; } print ''; } } else { print ''; } print '
'; print ''; print ''; print ''; print ''; /* print ''; */ print ''; print ''; print ''; print ''; print ''; print '
'; print $i; print ' '; /*print '';*/ print ''; print ''; print ''; $htmltext = ''.$langs->trans("Examples").':
'; $htmltext .= '1 (always enabled)
'; $htmltext .= '0 (always disabled)
'; $htmltext .= 'isModEnabled(\''.dol_escape_htmltag($module).'\') (enabled when module is enabled)
'; print $form->textwithpicto('', $htmltext); /* print ''; */ print '
'; print ''; /* if (!empty($objPerms)) { print ''; print ''; } else { print ''; print ''; }*/ print ''; print ''; print ''; print '
'; print $i; print ''; print dol_escape_htmltag($menu['type']); print ''; print dol_escape_htmltag($menu['titre']); print ''; print dol_escape_htmltag($menu['fk_menu']); print ''; print dol_escape_htmltag($menu['mainmenu']); print ''; print dol_escape_htmltag($menu['leftmenu']); print ''; print dol_escape_htmltag($menu['url']); print ''; print dol_escape_htmltag($menu['langs']); print ''; print dol_escape_htmltag((string) $menu['position']); print ''; print dol_escape_htmltag($menu['enabled']); print ''; print dol_escape_htmltag($langs->trans($menu['perms'])); print ''; print dol_escape_htmltag($menu['target']); print ''; if ($menu['user'] == 2) { print $langs->trans("AllMenus"); } elseif ($menu['user'] == 0) { print $langs->trans('Internal'); } elseif ($menu['user'] == 1) { print $langs->trans('External'); } else { print $menu['user']; // should not happen } print ''; if ($menu['titre'] != 'Module'.$module.'Name') { print ''.img_edit().''; print ''.img_delete().''; } print '
'.$langs->trans("None").'
'; print '
'; print ''; print ''; // display permissions for each object } else { $fullpathoffile = dol_buildpath($file, 0); $content = file_get_contents($fullpathoffile); // New module print '
'; print ''; print ''; print ''; print ''; print ''; $posCursor = (empty($find)) ? array() : array('find' => $find); $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%', 0, $posCursor); print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'html')); print '
'; print '
'; print ''; print '   '; print ''; print '
'; print '
'; } } if ($tab == 'permissions') { print ''."\n"; $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath']; $perms = $moduleobj->rights; // Get list of existing objects $dir = $dirread.'/'.$modulelowercase.'/class'; $listofobject = dol_dir_list($dir, 'files', 0, '\.class\.php$'); $objects = array('myobject'); $reg = array(); foreach ($listofobject as $fileobj) { $tmpcontent = file_get_contents($fileobj['fullname']); if (preg_match('/class\s+([^\s]*)\s+extends\s+CommonObject/ims', $tmpcontent, $reg)) { $objects[$fileobj['fullname']] = $reg[1]; } } // declared select list for actions and labels permissions $crud = array('read' => 'CRUDRead', 'write' => 'CRUDCreateWrite', 'delete' => 'Delete'); $labels = array("Read objects of ".$module, "Create/Update objects of ".$module, "Delete objects of ".$module); $action = GETPOST('action', 'alpha'); if ($action == 'deleteright') { $formconfirm = $form->formconfirm( $_SERVER["PHP_SELF"].'?permskey='.urlencode((string) (GETPOSTINT('permskey'))).'&tab='.urlencode((string) ($tab)).'&module='.urlencode((string) ($module)).'&tabobj='.urlencode((string) ($tabobj)), $langs->trans('Delete'), $langs->trans('Confirm Delete Right', GETPOST('permskey', 'alpha')), 'confirm_deleteright', '', 0, 1 ); print $formconfirm; } if ($action != 'editfile' || empty($file)) { print ''."\n"; print ''; $htmlhelp = $langs->trans("PermissionsDefDescTooltip"); //$htmlhelp = $langs->trans("PermissionsDefDescTooltip", '{s1}'); //$htmlhelp = str_replace('{s1}', ''.$langs->trans('DefaultRights').'', $htmlhelp); 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 '
'; print '
'; print load_fiche_titre($langs->trans("ListOfPermissionsDefined"), '', ''); print ''."\n"; print '
'; print ''; print ''; print ''; print ''; print ''; print '
'; print ''; print ''; print_liste_field_titre("ID", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, "center"); print_liste_field_titre("Object", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, "center"); print_liste_field_titre("CRUD", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, "center"); print_liste_field_titre("Label", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, "center"); print_liste_field_titre("", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, "center"); print "\n"; //form for add new right print ''; print ''; print ''; print ''; print ''; print ''; print ''; if (count($perms)) { $i = 0; foreach ($perms as $perm) { $i++; // section for editing right if ($action == 'edit_right' && $perm[0] == GETPOSTINT('permskey')) { print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; } else { // $perm can be module->object->crud or module->crud print ''; print ''; print ''; print ''; print ''; print ''; print ''; } } } else { print ''; } print '
'; print ''; print ''; print ''; print '
'; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print '
'; print ''; print '
'; print dol_escape_htmltag($perm[0]); print ''; if (in_array($perm[5], array('lire', 'read', 'creer', 'write', 'effacer', 'delete'))) { print dol_escape_htmltag(ucfirst($perm[4])); } else { print ''; // No particular object } print ''; if (in_array($perm[5], array('lire', 'read', 'creer', 'write', 'effacer', 'delete'))) { print ucfirst($langs->trans($perm[5])); } else { print ucfirst($langs->trans($perm[4])); } print ''; print $langs->trans($perm[1]); print ''; print ''.img_edit().''; print ''.img_delete().''; print '
'.$langs->trans("None").'
'; print '
'; print ''; print ''; } else { $fullpathoffile = dol_buildpath($file, 0); $content = file_get_contents($fullpathoffile); // New module print '
'; print ''; print ''; print ''; print ''; print ''; $posCursor = (empty($find)) ? array() : array('find' => $find); $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%', 0, $posCursor); print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'html')); print '
'; print '
'; print ''; print '   '; print ''; print '
'; print '
'; } } if ($tab == 'hooks') { print ''."\n"; if ($action != 'editfile' || empty($file)) { print ''.$langs->trans("HooksDefDesc").'
'; print '
'; print ''; $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath']; print ''; print ''; print ''; } else { print ''.$langs->trans("FileNotYetGenerated").''; print ''.img_picto('Generate', 'generate', 'class="paddingleft"').''; print ''; } print ''; } else { $fullpathoffile = dol_buildpath($file, 0); $content = file_get_contents($fullpathoffile); // New module print '
'; print ''; print ''; print ''; print ''; print ''; $posCursor = (empty($find)) ? array() : array('find' => $find); $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%', 0, $posCursor); print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'html')); print '
'; print '
'; print ''; print '   '; print ''; print '
'; print ''; } } if ($tab == 'triggers') { print ''."\n"; require_once DOL_DOCUMENT_ROOT.'/core/class/interfaces.class.php'; $interfaces = new Interfaces($db); $triggers = $interfaces->getTriggersList(array('/'.strtolower($module).'/core/triggers')); if ($action != 'editfile' || empty($file)) { print ''.$langs->trans("TriggerDefDesc").'
'; print '
'; print '
'; print ' '.$langs->trans("DescriptorFile").' : '.$pathtofile.''; print ''; print ''.img_picto($langs->trans("Edit"), 'edit').''; print '
'; $pathtohook = strtolower($module).'/class/actions_'.strtolower($module).'.class.php'; print ' '.$langs->trans("HooksFile").' : '; if (dol_is_file($dirins.'/'.$pathtohook)) { print ''.$pathtohook.''; print ''.img_picto($langs->trans("Edit"), 'edit').' '; print ''.img_picto($langs->trans("Delete"), 'delete').'
'; $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath']; print ''; if (!empty($triggers)) { foreach ($triggers as $trigger) { $pathtofile = $trigger['relpath']; print ''; print ''; print ''; } } else { print ''; print ''; print ''; } print '
'; print ' '.$langs->trans("DescriptorFile").' : '.$pathtofile.''; print ''; print ''.img_picto($langs->trans("Edit"), 'edit').''; print '
'; print ' '.$langs->trans("TriggersFile").' : '.$pathtofile.''; print ''.img_picto($langs->trans("Edit"), 'edit').''.img_picto($langs->trans("Delete"), 'delete').'
'; print ' '.$langs->trans("TriggersFile"); print ' : '.$langs->trans("FileNotYetGenerated").''; print ''.img_picto('Generate', 'generate', 'class="paddingleft"').'
'; } else { $fullpathoffile = dol_buildpath($file, 0); $content = file_get_contents($fullpathoffile); // New module print '
'; print ''; print ''; print ''; print ''; print ''; $posCursor = (empty($find)) ? array() : array('find' => $find); $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%', 0, $posCursor); print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'html')); print '
'; print '
'; print ''; print '   '; print ''; print '
'; print '
'; } } if ($tab == 'css') { print ''."\n"; if ($action != 'editfile' || empty($file)) { print ''.$langs->trans("CSSDesc").'
'; print '
'; print ''; print ''; print ''; } else { print ''.$langs->trans("FileNotYetGenerated").''; print ''; } print ''; } else { $fullpathoffile = dol_buildpath($file, 0); $content = file_get_contents($fullpathoffile); // New module print ''; print ''; print ''; print ''; print ''; print ''; $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%'); print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'html')); print '
'; print '
'; print ''; print '   '; print ''; print '
'; print ''; } } if ($tab == 'js') { print ''."\n"; if ($action != 'editfile' || empty($file)) { print ''.$langs->trans("JSDesc").'
'; print '
'; print '
'; $pathtohook = strtolower($module).'/css/'.strtolower($module).'.css.php'; print ' '.$langs->trans("CSSFile").' : '; if (dol_is_file($dirins.'/'.$pathtohook)) { print ''.$pathtohook.''; print ''.img_picto($langs->trans("Edit"), 'edit').''.img_picto($langs->trans("Delete"), 'delete').''.img_picto('Generate', 'generate', 'class="paddingleft"').'
'; print ''; print ''; } else { print ''.$langs->trans("FileNotYetGenerated").''; print ''; } print ''; } else { $fullpathoffile = dol_buildpath($file, 0); $content = file_get_contents($fullpathoffile); // New module print ''; print ''; print ''; print ''; print ''; print ''; $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%'); print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'html')); print '
'; print '
'; print ''; print '   '; print ''; print '
'; print ''; } } if ($tab == 'widgets') { print ''."\n"; require_once DOL_DOCUMENT_ROOT.'/core/boxes/modules_boxes.php'; $widgets = ModeleBoxes::getWidgetsList(array('/'.strtolower($module).'/core/boxes')); if ($action != 'editfile' || empty($file)) { print ''.$langs->trans("WidgetDesc").'
'; print '
'; print '
'; $pathtohook = strtolower($module).'/js/'.strtolower($module).'.js.php'; print ' '.$langs->trans("JSFile").' : '; if (dol_is_file($dirins.'/'.$pathtohook)) { print ''.$pathtohook.''; print ''.img_picto($langs->trans("Edit"), 'edit').''.img_picto($langs->trans("Delete"), 'delete').''.img_picto('Generate', 'generate', 'class="paddingleft"').'
'; if (!empty($widgets)) { foreach ($widgets as $widget) { $pathtofile = $widget['relpath']; print ''; print ''; } } else { print ''; } print '
'.$langs->trans("WidgetFile").' : '.$pathtofile.''; print ''.img_picto($langs->trans("Edit"), 'edit').''; print ''.img_picto($langs->trans("Delete"), 'delete').'
'.$langs->trans("WidgetFile").' : '.$langs->trans("NoWidget").''; print ''.img_picto('Generate', 'generate', 'class="paddingleft"').''; print '
'; } else { $fullpathoffile = dol_buildpath($file, 0); $content = file_get_contents($fullpathoffile); // New module print '
'; print ''; print ''; print ''; print ''; print ''; $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%'); print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'html')); print '
'; print '
'; print ''; print '   '; print ''; print '
'; print '
'; } } if ($tab == 'emailings') { print ''."\n"; require_once DOL_DOCUMENT_ROOT.'/core/modules/mailings/modules_mailings.php'; $emailingselectors = MailingTargets::getEmailingSelectorsList(array('/'.strtolower($module).'/core/modules/mailings')); if ($action != 'editfile' || empty($file)) { print ''.$langs->trans("EmailingSelectorDesc").'
'; print '
'; print ''; if (!empty($emailingselectors)) { foreach ($emailingselectors as $emailingselector) { $pathtofile = $emailingselector['relpath']; print ''; print ''; } } else { print ''; } print '
'.$langs->trans("EmailingSelectorFile").' : '.$pathtofile.''; print ''.img_picto($langs->trans("Edit"), 'edit').''; print ''.img_picto($langs->trans("Delete"), 'delete').'
'.$langs->trans("EmailingSelectorFile").' : '.$langs->trans("NoEmailingSelector").''; print ''.img_picto('Generate', 'generate', 'class="paddingleft"').''; print '
'; } else { $fullpathoffile = dol_buildpath($file, 0); $content = file_get_contents($fullpathoffile); // New module print '
'; print ''; print ''; print ''; print ''; print ''; $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%'); print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'html')); print '
'; print '
'; print ''; print '   '; print ''; print '
'; print '
'; } } if ($tab == 'exportimport') { print ''."\n"; $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath']; $exportlist = $moduleobj->export_label; $importlist = $moduleobj->import_label; if ($action != 'editfile' || empty($file)) { print ''.$langs->transnoentities('ImportExportProfiles').'
'; print '
'; print ' '.$langs->trans("DescriptorFile").' ('.$langs->trans("ExportsArea").') : '.$pathtofile.''; print '
'.img_picto($langs->trans("Edit"), 'edit').''; print '
'; print ' '.$langs->trans("DescriptorFile").' ('.$langs->trans("ImportArea").') : '.$pathtofile.''; print ' '.img_picto($langs->trans("Edit"), 'edit').''; print '
'; } else { $fullpathoffile = dol_buildpath($file, 0); $content = file_get_contents($fullpathoffile); // New module print '
'; print ''; print ''; print ''; print ''; print ''; $posCursor = (empty($find)) ? array() : array('find' => $find); $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%', 0, $posCursor); print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'html')); print '
'; print '
'; print ''; print '   '; print ''; print '
'; print '
'; } } if ($tab == 'cli') { print ''."\n"; $clifiles = array(); $i = 0; $dircli = array('/'.strtolower($module).'/scripts'); foreach ($dircli as $reldir) { $dir = dol_buildpath($reldir, 0); $newdir = dol_osencode($dir); // 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; } $handle = opendir($newdir); if (is_resource($handle)) { while (($tmpfile = readdir($handle)) !== false) { if (is_readable($newdir.'/'.$tmpfile) && preg_match('/^(.+)\.php/', $tmpfile, $reg)) { if (preg_match('/\.back$/', $tmpfile)) { continue; } $clifiles[$i]['relpath'] = preg_replace('/^\//', '', $reldir).'/'.$tmpfile; $i++; } } closedir($handle); } } if ($action != 'editfile' || empty($file)) { print ''.$langs->trans("CLIDesc").'
'; print '
'; print ''; if (!empty($clifiles)) { foreach ($clifiles as $clifile) { $pathtofile = $clifile['relpath']; print ''; print ''; print ''; } } else { print ''; } print '
'.$langs->trans("CLIFile").' : '.$pathtofile.''; print ''.img_picto($langs->trans("Edit"), 'edit').''.img_picto($langs->trans("Delete"), 'delete').'
'.$langs->trans("CLIFile").' : '.$langs->trans("FileNotYetGenerated").''; print ''.img_picto('Generate', 'generate', 'class="paddingleft"').''; print '
'; } else { $fullpathoffile = dol_buildpath($file, 0); $content = file_get_contents($fullpathoffile); // New module print '
'; print ''; print ''; print ''; print ''; print ''; $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%'); print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'html')); print '
'; print '
'; print ''; print '   '; print ''; print '
'; print '
'; } } if ($tab == 'cron') { print ''."\n"; $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath']; $cronjobs = $moduleobj->cronjobs; if ($action != 'editfile' || empty($file)) { print ''.str_replace('{s1}', ''.$langs->transnoentities('CronList').'', $langs->trans("CronJobDefDesc", '{s1}')).'
'; print '
'; print ' '.$langs->trans("DescriptorFile").' : '.$pathtofile.''; print ' '.img_picto($langs->trans("Edit"), 'edit').''; print '
'; print '
'; print load_fiche_titre($langs->trans("CronJobProfiles"), '', ''); print '
'; print ''; print ''; print ''; print ''; print ''; print '
'; print ''; print ''; print_liste_field_titre("CronLabel", $_SERVER["PHP_SELF"], "", "", $param, '', $sortfield, $sortorder); print_liste_field_titre("CronTask", '', '', "", $param, '', $sortfield, $sortorder); print_liste_field_titre("CronFrequency", '', "", "", $param, '', $sortfield, $sortorder); print_liste_field_titre("StatusAtInstall", $_SERVER["PHP_SELF"], "", "", $param, '', $sortfield, $sortorder); print_liste_field_titre("Comment", $_SERVER["PHP_SELF"], "", "", $param, '', $sortfield, $sortorder); print "\n"; if (count($cronjobs)) { foreach ($cronjobs as $cron) { print ''; print ''; print ''; print ''; print ''; print ''; print ''; } } else { print ''; } print '
'; print $cron['label']; print ''; $texttoshow = ''; if ($cron['jobtype'] == 'method') { $text = $langs->trans("CronClass"); $texttoshow = $langs->trans('CronModule').': '.$module.'
'; $texttoshow .= $langs->trans('CronClass').': '.$cron['class'].'
'; $texttoshow .= $langs->trans('CronObject').': '.$cron['objectname'].'
'; $texttoshow .= $langs->trans('CronMethod').': '.$cron['method']; $texttoshow .= '
'.$langs->trans('CronArgs').': '.$cron['parameters']; $texttoshow .= '
'.$langs->trans('Comment').': '.$langs->trans($cron['comment']); } elseif ($cron['jobtype'] == 'command') { $text = $langs->trans('CronCommand'); $texttoshow = $langs->trans('CronCommand').': '.dol_trunc($cron['command']); $texttoshow .= '
'.$langs->trans('CronArgs').': '.$cron['parameters']; $texttoshow .= '
'.$langs->trans('Comment').': '.$langs->trans($cron['comment']); } print $form->textwithpicto($text, $texttoshow, 1); print '
'; if ($cron['unitfrequency'] == "60") { print $langs->trans('CronEach')." ".($cron['frequency'])." ".$langs->trans('Minutes'); } if ($cron['unitfrequency'] == "3600") { print $langs->trans('CronEach')." ".($cron['frequency'])." ".$langs->trans('Hours'); } if ($cron['unitfrequency'] == "86400") { print $langs->trans('CronEach')." ".($cron['frequency'])." ".$langs->trans('Days'); } if ($cron['unitfrequency'] == "604800") { print $langs->trans('CronEach')." ".($cron['frequency'])." ".$langs->trans('Weeks'); } print ''; print $cron['status']; print ''; if (!empty($cron['comment'])) { print $cron['comment']; } print '
'.$langs->trans("None").'
'; print '
'; print '
'; } else { $fullpathoffile = dol_buildpath($file, 0); $content = file_get_contents($fullpathoffile); // New module print '
'; print ''; print ''; print ''; print ''; print ''; $posCursor = (empty($find)) ? array() : array('find' => $find); $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%', 0, $posCursor); print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'html')); print '
'; print '
'; print ''; print '   '; print ''; print '
'; print '
'; } } if ($tab == 'specifications') { print ''."\n"; $specs = dol_dir_list(dol_buildpath($modulelowercase.'/doc', 0), 'files', 1, '(\.md|\.asciidoc)$', array('\/temp\/')); if ($action != 'editfile' || empty($file)) { print ''.$langs->trans("SpecDefDesc").'
'; print '
'; print ''; if (is_array($specs) && !empty($specs)) { foreach ($specs as $spec) { $pathtofile = $modulelowercase.'/doc/'.$spec['relativename']; $format = 'asciidoc'; if (preg_match('/\.md$/i', $spec['name'])) { $format = 'markdown'; } print ''; print ''; print ''; } } else { print ''; print ''; } print '
'; print ' '.$langs->trans("SpecificationFile").' : '.$pathtofile.''; print ''.img_picto($langs->trans("Edit"), 'edit').''.img_picto($langs->trans("Delete"), 'delete').'
'; print ' '.$langs->trans("SpecificationFile").' : '.$langs->trans("FileNotYetGenerated").''; print ''.img_picto('Generate', 'generate', 'class="paddingleft"').'
'; } else { // Use MD or asciidoc //print $langs->trans("UseAsciiDocFormat").'
'; $fullpathoffile = dol_buildpath($file, 0); $content = file_get_contents($fullpathoffile); // New module print '
'; print ''; print ''; print ''; print ''; print ''; $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%'); print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'html')); print '
'; print '
'; print ''; print '   '; print ''; print '
'; print '
'; } print '


'; $FILENAMEDOC = $modulelowercase.'.html'; $FILENAMEDOCPDF = $modulelowercase.'.pdf'; $outputfiledoc = dol_buildpath($modulelowercase, 0).'/doc/'.$FILENAMEDOC; $outputfiledocurl = dol_buildpath($modulelowercase, 1).'/doc/'.$FILENAMEDOC; $outputfiledocrel = $modulelowercase.'/doc/'.$FILENAMEDOC; $outputfiledocpdf = dol_buildpath($modulelowercase, 0).'/doc/'.$FILENAMEDOCPDF; $outputfiledocurlpdf = dol_buildpath($modulelowercase, 1).'/doc/'.$FILENAMEDOCPDF; $outputfiledocrelpdf = $modulelowercase.'/doc/'.$FILENAMEDOCPDF; // HTML print ' '.$langs->trans("PathToModuleDocumentation", "HTML").' : '; if (!dol_is_file($outputfiledoc)) { print ''.$langs->trans("FileNotYetGenerated").''; } else { print ''; print ''; print $outputfiledoc; print ''; print ''; print ' ('.$langs->trans("GeneratedOn").' '.dol_print_date(dol_filemtime($outputfiledoc), 'dayhour').')'; print ' '.img_picto($langs->trans("Delete"), 'delete').''; } print '
'; // PDF print ' '.$langs->trans("PathToModuleDocumentation", "PDF").' : '; if (!dol_is_file($outputfiledocpdf)) { print ''.$langs->trans("FileNotYetGenerated").''; } else { print ''; print ''; print $outputfiledocpdf; print ''; print ''; print ' ('.$langs->trans("GeneratedOn").' '.dol_print_date(dol_filemtime($outputfiledocpdf), 'dayhour').')'; print ' '.img_picto($langs->trans("Delete"), 'delete').''; } print '
'; print '
'; print '
'; print ''; print ''; print ''; print ''; print ''; print '
'; } if ($tab == 'buildpackage') { print ''."\n"; print ''.$langs->trans("BuildPackageDesc").''; print '
'; if (!class_exists('ZipArchive') && !defined('ODTPHP_PATHTOPCLZIP')) { print img_warning().' '.$langs->trans("ErrNoZipEngine"); print '
'; } $modulelowercase = strtolower($module); // Zip file to build $FILENAMEZIP = ''; // Load module $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath']; dol_include_once($pathtofile); $class = 'mod'.$module; $moduleobj = null; if (class_exists($class)) { try { $moduleobj = new $class($db); '@phan-var-force DolibarrModules $moduleobj'; /** @var DolibarrModules $moduleobj */ } catch (Exception $e) { $error++; dol_print_error($db, $e->getMessage()); } } if ($moduleobj === null) { $error++; $langs->load("errors"); dol_print_error($db, $langs->trans("ErrorFailedToLoadModuleDescriptorForXXX", $module)); exit; } $outputfilezip = null; $arrayversion = explode('.', $moduleobj->version, 3); if (count($arrayversion)) { $FILENAMEZIP = "module_".$modulelowercase.'-'.$arrayversion[0].(empty($arrayversion[1]) ? '.0' : '.'.$arrayversion[1]).(empty($arrayversion[2]) ? '' : ".".$arrayversion[2]).".zip"; $outputfilezip = dol_buildpath($modulelowercase, 0).'/bin/'.$FILENAMEZIP; } print '
'; print ' '.$langs->trans("PathToModulePackage").' : '; if ($outputfilezip === null || !dol_is_file($outputfilezip)) { print ''.$langs->trans("FileNotYetGenerated").''; } else { $relativepath = $modulelowercase.'/bin/'.$FILENAMEZIP; print ''.$outputfilezip.''; print ' ('.$langs->trans("GeneratedOn").' '.dol_print_date(dol_filemtime($outputfilezip), 'dayhour').')'; print ' '.img_picto($langs->trans("Delete"), 'delete').''; } print ''; print '
'; print '
'; print '
'; print ''; print ''; print ''; print ''; print ''; print '
'; } if ($tab == 'tabs') { $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath']; $tabs = $moduleobj->tabs; if ($action != 'editfile' || empty($file)) { print ''; $htmlhelp = $langs->trans("TabsDefDescTooltip", '{s1}'); $htmlhelp = str_replace('{s1}', ''.$langs->trans('Setup').' - '.$langs->trans('Tabs').'', $htmlhelp); print $form->textwithpicto($langs->trans("TabsDefDesc"), $htmlhelp, 1, 'help', '', 0, 2, 'helpondesc').'
'; print '
'; print '
'; print ' '.$langs->trans("DescriptorFile").' : '.$pathtofile.''; print ' '.img_picto($langs->trans("Edit"), 'edit').''; print '
'; print '
'; print load_fiche_titre($langs->trans("ListOfTabsEntries"), '', ''); print '
'; print ''; print ''; print ''; print ''; print ''; print '
'; print ''; print ''; print_liste_field_titre("ObjectType", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder); print_liste_field_titre("Tab", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder); print_liste_field_titre("Title", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder); print_liste_field_titre("LangFile", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder); print_liste_field_titre("Condition", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder); print_liste_field_titre("Path", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder); print "\n"; if (count($tabs)) { foreach ($tabs as $tab) { $parts = explode(':', $tab['data']); $objectType = $parts[0]; $tabName = $parts[1]; $tabTitle = isset($parts[2]) ? $parts[2] : ''; $langFile = isset($parts[3]) ? $parts[3] : ''; $condition = isset($parts[4]) ? $parts[4] : ''; $path = isset($parts[5]) ? $parts[5] : ''; // If we want to remove the tab, then the format is 'objecttype:tabname:optionalcondition' // See: https://wiki.dolibarr.org/index.php?title=Tabs_system#To_remove_an_existing_tab if ($tabName[0] === '-') { $tabTitle = ''; $condition = isset($parts[2]) ? $parts[2] : ''; } print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; } } else { print ''; } print '
'; print dol_escape_htmltag($parts[0]); print ''; if ($tabName[0] === "+") { print '' . dol_escape_htmltag($tabName) . ''; } else { print '' . dol_escape_htmltag($tabName) . ''; } print ''; print dol_escape_htmltag($tabTitle); print ''; print dol_escape_htmltag($langFile); print ''; print dol_escape_htmltag($condition); print ''; print dol_escape_htmltag($path); print '
'.$langs->trans("None").'
'; print '
'; print '
'; } else { $fullpathoffile = dol_buildpath($file, 0); $content = file_get_contents($fullpathoffile); // New module print '
'; print ''; print ''; print ''; print ''; print ''; $posCursor = (empty($find)) ? array() : array('find' => $find); $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%', 0, $posCursor); print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'html')); print '
'; print '
'; print ''; print '   '; print ''; print '
'; print '
'; } } if ($tab != 'description') { print dol_get_fiche_end(); } } } print dol_get_fiche_end(); // End modules // End of page llxFooter(); $db->close();