dolibarr 25.0.0-alpha
index.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2004-2023 Laurent Destailleur <eldy@users.sourceforge.net>
3 * Copyright (C) 2018-2019 Nicolas ZABOURI <info@inovea-conseil.com>
4 * Copyright (C) 2023 Alexandre Janniaux <alexandre.janniaux@gmail.com>
5 * Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
6 * Copyright (C) 2024-2026 Frédéric France <frederic.france@free.fr>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 *
21 * You can also make a direct call the page with parameter like this:
22 * htdocs/modulebuilder/index.php?module=Inventory@/pathtodolibarr/htdocs/product
23 */
24
33if (!defined('NOSCANPOSTFORINJECTION')) {
34 define('NOSCANPOSTFORINJECTION', '1'); // Do not check anti SQL+XSS injection attack test
35}
36
37// Load Dolibarr environment
38require '../main.inc.php';
39require_once DOL_DOCUMENT_ROOT . '/core/lib/functions.lib.php';
40
52'
53@phan-var-force string $dolibarr_main_document_root
54@phan-var-force string $dolibarr_main_document_root_alt
55';
56require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
57require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
58require_once DOL_DOCUMENT_ROOT.'/core/class/html.formadmin.class.php';
59require_once DOL_DOCUMENT_ROOT.'/core/lib/modulebuilder.lib.php';
60require_once DOL_DOCUMENT_ROOT.'/modulebuilder/class/NamingContractValidator.class.php';
61require_once DOL_DOCUMENT_ROOT.'/modulebuilder/class/RightsSyncService.class.php';
62require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
63require_once DOL_DOCUMENT_ROOT.'/core/class/utils.class.php';
64
65// Load translation files required by the page
66$langs->loadLangs(array("admin", "modulebuilder", "exports", "other", "cron", "errors", "uxdocumentation"));
67
68// GET Parameters
69$action = GETPOST('action', 'aZ09');
70$confirm = GETPOST('confirm', 'alpha');
71$cancel = GETPOST('cancel', 'alpha');
72
73$sortfield = GETPOST('sortfield', 'aZ09comma');
74$sortorder = GETPOST('sortorder', 'aZ09');
75
76$module = (string) GETPOST('module', 'alpha');
77$tab = (string) GETPOST('tab', 'aZ09');
78$tabobj = GETPOST('tabobj', 'alpha');
79$tabdic = GETPOST('tabdic', 'alpha');
80$propertykey = GETPOST('propertykey', 'alpha');
81if (empty($module)) {
82 $module = 'initmodule';
83}
84if (empty($tab)) {
85 $tab = 'description';
86}
87'@phan-var-force string $tab'; // Workaround 'empty()' bug of phan
88if (empty($tabobj)) {
89 $tabobj = 'newobjectifnoobj';
90}
91if (empty($tabdic)) {
92 $tabdic = 'newdicifnodic';
93}
94$file = GETPOST('file', 'alpha');
95$find = GETPOST('find', 'alpha');
96
97$modulename = dol_sanitizeFileName(GETPOST('modulename', 'alpha'));
98$objectname = dol_sanitizeFileName(GETPOST('objectname', 'alpha'));
99$dicname = dol_sanitizeFileName(GETPOST('dicname', 'alpha'));
100$editorname = (string) GETPOST('editorname', 'alpha');
101$editorurl = (string) GETPOST('editorurl', 'alpha');
102$version = (string) GETPOST('version', 'alpha');
103$family = (string) GETPOST('family', 'alpha');
104$picto = (string) GETPOST('idpicto', 'alpha');
105$idmodule = (string) GETPOST('idmodule', 'alpha');
106$format = ''; // Prevent undefined in css tab
107
108// Security check
109if (!isModEnabled('modulebuilder')) {
110 accessforbidden('Module ModuleBuilder not enabled');
111}
112if (!$user->hasRight("modulebuilder", "run")) { // after this test $user->hasRight("modulebuilder", "run") is always true, no need to check it more
113 accessforbidden('ModuleBuilderNotAllowed');
114}
115
116// Dir for custom dirs
117$tmp = explode(',', $dolibarr_main_document_root_alt);
118$dirins = $tmp[0];
119$dirread = $dirins;
120$forceddirread = 0;
121
122$tmpdir = explode('@', $module);
123if (!empty($tmpdir[1])) {
124 $module = $tmpdir[0];
125 $dirread = $tmpdir[1];
126 $forceddirread = 1;
127}
128if (GETPOST('dirins', 'alpha')) {
129 $dirread = $dirins = GETPOST('dirins', 'alpha');
130 $forceddirread = 1;
131}
132
133$FILEFLAG = 'modulebuilder.txt';
134
135$now = dol_now();
136$newmask = 0;
137if (empty($newmask) && getDolGlobalString('MAIN_UMASK')) {
138 $newmask = getDolGlobalString('MAIN_UMASK');
139}
140if (empty($newmask)) { // This should no happen
141 $newmask = '0664';
142}
143
144$result = restrictedArea($user, 'modulebuilder', 0);
145
146$error = 0;
147$param = '';
148
149$form = new Form($db);
150
151// Define $listofmodules
152$dirsrootforscan = array($dirread);
153
154// Add also the core modules into the list of modules to show/edit
155if ($dirread != DOL_DOCUMENT_ROOT && (getDolGlobalInt('MAIN_FEATURES_LEVEL') >= 2 || getDolGlobalString('MODULEBUILDER_ADD_DOCUMENT_ROOT'))) {
156 $dirsrootforscan[] = DOL_DOCUMENT_ROOT;
157}
158
159// Search modules to edit
160$textforlistofdirs = '<!-- Directory scanned -->'."\n";
161$listofmodules = array();
162'@phan-var-force array<string,array{modulenamewithcase:string,moduledescriptorrelpath:string,moduledescriptorfullpath:string,moduledescriptorrootpath,moduletype?:string}> $listofmodules';
163$i = 0;
164foreach ($dirsrootforscan as $tmpdirread) {
165 $moduletype = 'external';
166 if ($tmpdirread == DOL_DOCUMENT_ROOT) {
167 $moduletype = 'internal';
168 }
169
170 $dirsincustom = dol_dir_list($tmpdirread, 'directories');
171 if (is_array($dirsincustom) && count($dirsincustom) > 0) {
172 foreach ($dirsincustom as $dircustomcursor) {
173 $fullname = $dircustomcursor['fullname'];
174 if (dol_is_file($fullname.'/'.$FILEFLAG)) {
175 // Get real name of module (MyModule instead of mymodule)
176 $dirtoscanrel = basename($fullname).'/core/modules/';
177
178 $descriptorfiles = dol_dir_list(dirname($fullname).'/'.$dirtoscanrel, 'files', 0, 'mod.*\.class\.php$');
179 if (empty($descriptorfiles)) { // If descriptor not found into module dir, we look into main module dir.
180 $dirtoscanrel = 'core/modules/';
181 $descriptorfiles = dol_dir_list($fullname.'/../'.$dirtoscanrel, 'files', 0, 'mod'.dol_strtoupper(basename($fullname)).'\.class\.php$');
182 }
183 $modulenamewithcase = '';
184 $moduledescriptorrelpath = '';
185 $moduledescriptorfullpath = '';
186
187 foreach ($descriptorfiles as $descriptorcursor) {
188 $modulenamewithcase = preg_replace('/^mod/', '', $descriptorcursor['name']);
189 $modulenamewithcase = preg_replace('/\.class\.php$/', '', $modulenamewithcase);
190 $moduledescriptorrelpath = $dirtoscanrel.$descriptorcursor['name'];
191 $moduledescriptorfullpath = $descriptorcursor['fullname'];
192 //var_dump($descriptorcursor);
193 }
194 if ($modulenamewithcase) {
195 $listofmodules[$dircustomcursor['name']] = array(
196 'modulenamewithcase' => $modulenamewithcase,
197 'moduledescriptorrelpath' => $moduledescriptorrelpath,
198 'moduledescriptorfullpath' => $moduledescriptorfullpath,
199 'moduledescriptorrootpath' => $tmpdirread,
200 'moduletype' => $moduletype
201 );
202 }
203 //var_dump($listofmodules);
204 }
205 }
206 }
207
208 if ($forceddirread && empty($listofmodules)) { // $forceddirread is 1 if we forced dir to read with dirins=... or with module=...@mydir
209 $listofmodules[dol_strtolower($module)] = array(
210 'modulenamewithcase' => $module,
211 'moduledescriptorrelpath' => 'notyetimplemented',
212 'moduledescriptorfullpath' => 'notyetimplemented',
213 'moduledescriptorrootpath' => 'notyetimplemented',
214 );
215 }
216
217 // Show description of content
218 $newdircustom = $dirins;
219 if (empty($newdircustom)) {
220 $newdircustom = img_warning();
221 }
222 // If dirread was forced to somewhere else, by using URL
223 // htdocs/modulebuilder/index.php?module=Inventory@/home/ldestailleur/git/dolibarr/htdocs/product
224 if (empty($i)) {
225 $textforlistofdirs .= $langs->trans("DirScanned").' : ';
226 } else {
227 $textforlistofdirs .= ', ';
228 }
229 $textforlistofdirs .= '<strong class="wordbreakimp">'.$tmpdirread.'</strong>';
230 if ($tmpdirread == DOL_DOCUMENT_ROOT) {
231 if (getDolGlobalInt('MAIN_FEATURES_LEVEL') >= 2) {
232 $textforlistofdirs .= $form->textwithpicto('', $langs->trans("ConstantIsOn", "MAIN_FEATURES_LEVEL"));
233 }
234 if (getDolGlobalString('MODULEBUILDER_ADD_DOCUMENT_ROOT')) {
235 $textforlistofdirs .= $form->textwithpicto('', $langs->trans("ConstantIsOn", "MODULEBUILDER_ADD_DOCUMENT_ROOT"));
236 }
237 }
238 $i++;
239}
240
247{
248 $error = error_get_last();
249 if ($error && ($error['type'] & (E_ERROR | E_PARSE | E_CORE_ERROR | E_COMPILE_ERROR | E_USER_ERROR))) {
250 // Handle the fatal error
251 echo "Fatal error occurred: {$error['message']} in {$error['file']} on line {$error['line']}";
252 // If a header was already send, we suppose it is the llx_Header() so we call the llxFooter()
253 if (headers_sent()) {
254 llxFooter();
255 }
256 }
257}
258register_shutdown_function("moduleBuilderShutdownFunction");
259
260
270function getLicenceHeader($user, $langs, $now)
271{
272 $licInfo = $user->getFullName($langs);
273 $emailTabs = str_repeat("\t", (int) (max(0, (31 - mb_strlen($licInfo)) / 4)));
274 $licInfo .= ($user->email ? $emailTabs.'<'.$user->email.'>' : '');
275 $licInfo = dol_print_date($now, '%Y')."\t\t".$licInfo;
276 return $licInfo;
277}
278
279
280/*
281 * Actions
282 */
283
291function modulebuilderValidateGeneratedFile(string $destfile, NamingContract $nc): void
292{
293 $content = file_get_contents($destfile);
294 if ($content === false) {
295 return;
296 }
297 $validator = new StrictNamingContractValidator();
298 $errors = $validator->validateContent($content, $destfile);
299 if (!empty($errors)) {
301 'ModuleBuilder NamingContract validation warning in ' . $destfile . ': '
302 . implode('; ', array_slice($errors, 0, 3)),
303 LOG_WARNING
304 );
305 $safeErrors = array_map('dol_escape_htmltag', array_slice($errors, 0, 5));
306 setEventMessages(implode('<br>', $safeErrors), null, 'warnings');
307 }
308}
309
316function modulebuilderSyncRights(RightsSyncCommand $cmd): SyncReport
317{
318 global $langs;
319
320 $service = new DescriptorRightsSyncService();
321 $report = $service->sync($cmd);
322
323 if ($report->hasWarnings()) {
324 $safe = array_map('dol_escape_htmltag', array_slice($report->warnings, 0, 5));
325 setEventMessages($langs->trans('ModuleBuilderPermissionsNormalized').'<br>'.implode('<br>', $safe), null, 'warnings');
326 }
327 if ($report->hasConflicts()) {
328 $safe = array_map('dol_escape_htmltag', array_slice($report->conflicts, 0, 5));
329 setEventMessages($langs->trans('ModuleBuilderPermissionsNotChanged').'<br>'.implode('<br>', $safe), null, 'errors');
330 }
331
332 return $report;
333}
334
335if ($dirins && $action == 'initmodule' && $modulename) { // Test on permission already done
336 $modulename = dol_string_nounprintableascii(dol_string_unaccent(dol_ucwords($modulename))); // Force first letter in uppercase
337 $destdir = '/not_set/';
338 $ncModule = new NamingContract($modulename);
339
340 if (preg_match('/[^a-z0-9]/i', $modulename)) {
341 $error++;
342 setEventMessages($langs->trans("SpaceOrSpecialCharAreNotAllowed"), null, 'errors');
343 }
344
345 if (!$error) {
346 $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template';
347 $destdir = $dirins.'/'.dol_strtolower($modulename);
348
349 $arrayreplacement = [
350 'mymodule' => $ncModule->moduleNameLower,
351 'MyModule' => $ncModule->moduleNameCase,
352 ];
353 $result = dolCopyDir($srcdir, $destdir, '0', 0, $arrayreplacement);
354 //dol_mkdir($destfile);
355 if ($result <= 0) {
356 if ($result < 0) {
357 $error++;
358 $langs->load("errors");
359 setEventMessages($langs->trans("ErrorFailToCopyDir", $srcdir, $destdir), null, 'errors');
360 } else {
361 // $result == 0
362 setEventMessages($langs->trans("AllFilesDidAlreadyExist", $srcdir, $destdir), null, 'warnings');
363 }
364 }
365
366 // Copy last 'html.formsetup.class.php' to backport folder
367 if (getDolGlobalInt('MODULEBUILDER_SUPPORT_COMPATIBILITY_V16')) {
368 $tryToCopyFromSetupClass = true;
369 $backportDest = $destdir .'/backport/v16/core/class';
370 $backportFileSrc = DOL_DOCUMENT_ROOT.'/core/class/html.formsetup.class.php';
371 $backportFileDest = $backportDest.'/html.formsetup.class.php';
372 $result = dol_mkdir($backportDest);
373
374 if ($result < 0) {
375 $error++;
376 $langs->load("errors");
377 setEventMessages($langs->trans("ErrorFailToCreateDir", $backportDest), null, 'errors');
378 $tryToCopyFromSetupClass = false;
379 }
380
381 if ($tryToCopyFromSetupClass) {
382 $result = dol_copy($backportFileSrc, $backportFileDest);
383 if ($result <= 0) {
384 if ($result < 0) {
385 $error++;
386 $langs->load("errors");
387 setEventMessages($langs->trans("ErrorFailToCopyFile", $backportFileSrc, $backportFileDest), null, 'errors');
388 } else {
389 setEventMessages($langs->trans("FileDidAlreadyExist", $backportFileDest), null, 'warnings');
390 }
391 }
392 }
393 }
394
395 if (getDolGlobalString('MODULEBUILDER_USE_ABOUT')) {
396 dol_delete_file($destdir.'/admin/about.php');
397 }
398
399 // Delete dir and files that can be generated in sub tabs later if we need them (we want a minimal module first)
400 dol_delete_dir_recursive($destdir.'/ajax');
401 dol_delete_dir_recursive($destdir.'/build/doxygen');
402 dol_delete_dir_recursive($destdir.'/core/modules/mailings');
403 dol_delete_dir_recursive($destdir.'/core/modules/'.dol_strtolower($modulename));
404 dol_delete_dir_recursive($destdir.'/core/tpl');
405 dol_delete_dir_recursive($destdir.'/core/triggers');
406 dol_delete_dir_recursive($destdir.'/doc');
407 //dol_delete_dir_recursive($destdir.'/.tx');
408 dol_delete_dir_recursive($destdir.'/core/boxes');
409
410 dol_delete_file($destdir.'/admin/myobject_extrafields.php');
411
412 dol_delete_file($destdir.'/class/actions_'.dol_strtolower($modulename).'.class.php');
413 dol_delete_file($destdir.'/class/api_'.dol_strtolower($modulename).'.class.php');
414
415 dol_delete_file($destdir.'/css/'.dol_strtolower($modulename).'.css.php');
416
417 dol_delete_file($destdir.'/js/'.dol_strtolower($modulename).'.js.php');
418
419 dol_delete_file($destdir.'/scripts/'.dol_strtolower($modulename).'.php');
420
421 dol_delete_file($destdir.'/sql/data.sql');
422 dol_delete_file($destdir.'/sql/update_x.x.x-y.y.y.sql');
423
424 // Delete some files related to Object (because the previous dolCopyDir has copied everything)
425 dol_delete_file($destdir.'/myobject_card.php');
426 dol_delete_file($destdir.'/myobject_contact.php');
427 dol_delete_file($destdir.'/myobject_note.php');
428 dol_delete_file($destdir.'/myobject_document.php');
429 dol_delete_file($destdir.'/myobject_agenda.php');
430 dol_delete_file($destdir.'/myobject_list.php');
431 dol_delete_file($destdir.'/lib/'.dol_strtolower($modulename).'_myobject.lib.php');
432 dol_delete_file($destdir.'/test/phpunit/functional/'.$modulename.'FunctionalTest.php');
433 dol_delete_file($destdir.'/test/phpunit/MyObjectTest.php');
434 dol_delete_file($destdir.'/sql/llx_'.dol_strtolower($modulename).'_myobject.sql');
435 dol_delete_file($destdir.'/sql/llx_'.dol_strtolower($modulename).'_myobject_extrafields.sql');
436 dol_delete_file($destdir.'/sql/llx_'.dol_strtolower($modulename).'_myobject.key.sql');
437 dol_delete_file($destdir.'/sql/llx_'.dol_strtolower($modulename).'_myobject_extrafields.key.sql');
438 dol_delete_file($destdir.'/class/myobject.class.php');
439 dol_delete_file($destdir.'/class/myobjectstats.class.php');
440
441 dol_delete_dir($destdir.'/class', 1);
442 dol_delete_dir($destdir.'/css', 1);
443 dol_delete_dir($destdir.'/js', 1);
444 dol_delete_dir($destdir.'/scripts', 1);
445 dol_delete_dir($destdir.'/sql', 1);
446 dol_delete_dir($destdir.'/test/phpunit/functionnal', 1);
447 dol_delete_dir($destdir.'/test/phpunit', 1);
448 dol_delete_dir($destdir.'/test', 1);
449 }
450
451 // Edit PHP files
452 if (!$error) {
453 $listofphpfilestoedit = dol_dir_list($destdir, 'files', 1, '\.(php|MD|js|sql|txt|xml|lang)$', '', 'fullname', SORT_ASC, 0, 1);
454
455 $licInfo = getLicenceHeader($user, $langs, $now);
456 foreach ($listofphpfilestoedit as $phpfileval) {
457 //var_dump($phpfileval['fullname']);
458 $arrayreplacement = array_merge(
459 $ncModule->getSubstitutionMap(),
460 [
461 'htdocs/modulebuilder/template' => $ncModule->moduleNameLower,
462 '---Put here your own copyright and developer email---' => $licInfo,
463 '---Replace with your own copyright and developer email---' => $licInfo,
464 'Editor name' => $editorname,
465 'https://www.example.com' => $editorurl,
466 '$this->version = \'1.0\'' => '$this->version = \'' . $version . '\'',
467 '$this->picto = \'generic\';' => (empty($picto)) ? '$this->picto = \'generic\'' : '$this->picto = \'' . $picto . '\';',
468 'modulefamily' => $family,
469 // Key '500000' would be cast to int(500000) by PHP, then renumbered to 0 by
470 // array_merge -- causing str_replace to search for '0' instead of '500000'.
471 // Use a string key that matches the exact assignment line to avoid this.
472 '$this->numero = 500000' => '$this->numero = '.$idmodule,
473 ]
474 );
475
476 if (getDolGlobalString('MODULEBUILDER_SPECIFIC_AUTHOR')) {
477 $arrayreplacement['---Replace with your own copyright and developer email---'] = dol_print_date($now, '%Y')."\t\t" . getDolGlobalString('MODULEBUILDER_SPECIFIC_AUTHOR');
478 }
479
480 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
481 $result = dolReplaceInFile($phpfileval['fullname'], $arrayreplacement); // @phpstan-ignore-line
482 //var_dump($result);
483 if ($result < 0) {
484 setEventMessages($langs->trans("ErrorFailToMakeReplacementInto", $phpfileval['fullname']), null, 'errors');
485 }
486 }
487
488 if (getDolGlobalString('MODULEBUILDER_SPECIFIC_README')) {
489 setEventMessages($langs->trans("ContentOfREADMECustomized"), null, 'warnings');
490 dol_delete_file($destdir.'/README.md');
491 file_put_contents($destdir.'/README.md', getDolGlobalString("MODULEBUILDER_SPECIFIC_README"));
492 dolChmod($destdir.'/README.md');
493 }
494 // for create file to add properties
495 // file_put_contents($destdir.'/'.dol_strtolower($modulename).'propertycard.php','');
496 // $srcFileCard = DOL_DOCUMENT_ROOT.'/modulebuilder/card.php';
497 // $destFileCard = $dirins.'/'.dol_strtolower($modulename).'/template/card.php';
498 // dol_copy($srcFileCard, $destdir.'/'.dol_strtolower($modulename).'propertycard.php', '0',1, $arrayreplacement);
499 }
500
501 if (!$error) {
502 setEventMessages($langs->trans('ModuleInitialized', $destdir), null);
503 $module = $modulename;
504
505 clearstatcache(true);
506 if (function_exists('opcache_invalidate')) {
507 opcache_reset(); // remove the include cache hell !
508 }
509
510 header("Location: ".$_SERVER["PHP_SELF"].'?module='.$modulename);
511 exit;
512 }
513}
514
515$destdir = '/not_set/'; // Initialize (for static analysis)
516$destfile = '/not_set/'; // Initialize (for static analysis)
517$srcfile = '/not_set/'; // Initialize (for static analysis)
518
519// init API, PHPUnit
520if ($dirins && in_array($action, array('initapi', 'initphpunit', 'initpagecontact', 'initpagedocument', 'initpagenote', 'initpageagenda')) && !empty($module) /* && $user->hasRight("modulebuilder", "run") // already checked */) {
521 $modulename = dol_ucfirst($module); // Force first letter in uppercase
522 $objectname = $tabobj;
523 $varnametoupdate = '';
524 $dirins = $listofmodules[dol_strtolower($module)]['moduledescriptorrootpath'];
525 $destdir = $dirins.'/'.dol_strtolower($module);
526
527 // Get list of existing objects
528 $objects = dolGetListOfObjectClasses($destdir);
529
530
531 if ($action == 'initapi') { // Test on permission already done
532 if (file_exists($dirins.'/'.dol_strtolower($module).'/class/api_'.dol_strtolower($module).'.class.php')) {
533 $result = dol_copy(DOL_DOCUMENT_ROOT.'/modulebuilder/template/class/api_mymodule.class.php', $dirins.'/'.dol_strtolower($module).'/class/api_'.dol_strtolower($module).'.class.php', '0', 1);
534 }
535 dol_mkdir($dirins.'/'.dol_strtolower($module).'/class');
536 $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template';
537 $srcfile = $srcdir.'/class/api_mymodule.class.php';
538 $destfile = $dirins.'/'.dol_strtolower($module).'/class/api_'.dol_strtolower($module).'.class.php';
539 } elseif ($action == 'initphpunit') { // Test on permission already done
540 dol_mkdir($dirins.'/'.dol_strtolower($module).'/test/phpunit');
541 $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template';
542 $srcfile = $srcdir.'/test/phpunit/MyObjectTest.php';
543 $destfile = $dirins.'/'.dol_strtolower($module).'/test/phpunit/'.dol_strtolower($objectname).'Test.php';
544 } elseif ($action == 'initpagecontact') { // Test on permission already done
545 dol_mkdir($dirins.'/'.dol_strtolower($module));
546 $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template';
547 $srcfile = $srcdir.'/myobject_contact.php';
548 $destfile = $dirins.'/'.dol_strtolower($module).'/'.dol_strtolower($objectname).'_contact.php';
549 $varnametoupdate = 'showtabofpagecontact';
550 } elseif ($action == 'initpagedocument') { // Test on permission already done
551 dol_mkdir($dirins.'/'.dol_strtolower($module));
552 $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template';
553 $srcfile = $srcdir.'/myobject_document.php';
554 $destfile = $dirins.'/'.dol_strtolower($module).'/'.dol_strtolower($objectname).'_document.php';
555 $varnametoupdate = 'showtabofpagedocument';
556 } elseif ($action == 'initpagenote') { // Test on permission already done
557 dol_mkdir($dirins.'/'.dol_strtolower($module));
558 $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template';
559 $srcfile = $srcdir.'/myobject_note.php';
560 $destfile = $dirins.'/'.dol_strtolower($module).'/'.dol_strtolower($objectname).'_note.php';
561 $varnametoupdate = 'showtabofpagenote';
562 } elseif ($action == 'initpageagenda') { // Test on permission already done
563 dol_mkdir($dirins.'/'.dol_strtolower($module));
564 $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template';
565 $srcfile = $srcdir.'/myobject_agenda.php';
566 $destfile = $dirins.'/'.dol_strtolower($module).'/'.dol_strtolower($objectname).'_agenda.php';
567 $varnametoupdate = 'showtabofpageagenda';
568 }
569
570 if (!file_exists($destfile)) {
571 $result = dol_copy($srcfile, $destfile, '0', 0);
572 }
573
574 if ($result > 0) {
575 //var_dump($phpfileval['fullname']);
576 try {
577 $ncApiObj = new NamingContract($modulename, $objectname);
578 } catch (\InvalidArgumentException $e) {
579 $error++;
580 setEventMessages($langs->trans("SpaceOrSpecialCharAreNotAllowed"), null, 'errors');
581 $ncApiObj = null;
582 }
583
584 if (!$error && $ncApiObj !== null) {
585 $arrayreplacement = array_merge(
586 $ncApiObj->getSubstitutionMap(),
587 [
588 'htdocs/modulebuilder/template' => $ncApiObj->moduleNameLower,
589 '---Replace with your own copyright and developer email---' => getLicenceHeader($user, $langs, $now),
590 ]
591 );
592
593 if ($action == 'initapi') { // Test on permission already done
594 if (count($objects) >= 1) {
595 addObjectsToApiFile($srcfile, $destfile, $objects, $modulename);
596 }
597 // Fix PHPDoc header and class-declaration residuals left by addObjectsToApiFile.
598 // 'MYOBJECT' (uppercase) is excluded to preserve the /* BEGIN MODULEBUILDER API MYOBJECT */
599 // placeholder that addObjectsToApiFile keeps for future object additions.
600 $headerFix = $arrayreplacement;
601 unset($headerFix['MYOBJECT']);
602 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
603 dolReplaceInFile($destfile, $headerFix);
604 modulebuilderValidateGeneratedFile($destfile, $ncApiObj);
605 } else {
606 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
607 dolReplaceInFile($destfile, $arrayreplacement);
608 modulebuilderValidateGeneratedFile($destfile, $ncApiObj);
609 }
610 }
611
612 if ($varnametoupdate) {
613 // Now we update the object file to set $$varnametoupdate to 1
614 $srcfile = $dirins.'/'.dol_strtolower($module).'/lib/'.dol_strtolower($module).'_'.dol_strtolower($objectname).'.lib.php';
615 $arrayreplacement = array('/\$'.preg_quote($varnametoupdate, '/').' = 0;/' => '$'.$varnametoupdate.' = 1;');
616 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
617 dolReplaceInFile($srcfile, $arrayreplacement, '', '0', 0, 1);
618 }
619 } else {
620 $langs->load("errors");
621 setEventMessages($langs->trans('ErrorFailToCreateFile', $destfile), null, 'errors');
622 }
623}
624
625
626// init ExtraFields
627if ($dirins && $action == 'initsqlextrafields' && !empty($module) /* && $user->hasRight("modulebuilder", "run") // already checked */) {
628 $modulename = dol_ucfirst($module); // Force first letter in uppercase
629 $objectname = $tabobj;
630
631 dol_mkdir($dirins.'/'.dol_strtolower($module).'/sql');
632 $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template';
633 $srcfile1 = $srcdir.'/sql/llx_mymodule_myobject_extrafields.sql';
634 $destfile1 = $dirins.'/'.dol_strtolower($module).'/sql/llx_'.dol_strtolower($module).'_'.dol_strtolower($objectname).'_extrafields.sql';
635 $result1 = dol_copy($srcfile1, $destfile1, '0', 0);
636 $srcfile2 = $srcdir.'/sql/llx_mymodule_myobject_extrafields.key.sql';
637 $destfile2 = $dirins.'/'.dol_strtolower($module).'/sql/llx_'.dol_strtolower($module).'_'.dol_strtolower($objectname).'_extrafields.key.sql';
638 $result2 = dol_copy($srcfile2, $destfile2, '0', 0);
639
640 if ($result1 > 0 && $result2 > 0) {
641 $modulename = dol_ucfirst($module); // Force first letter in uppercase
642
643 //var_dump($phpfileval['fullname']);
644 try {
645 $ncSqlObj = new NamingContract($modulename, $objectname);
646 } catch (\InvalidArgumentException $e) {
647 $error++;
648 setEventMessages($langs->trans("SpaceOrSpecialCharAreNotAllowed"), null, 'errors');
649 $ncSqlObj = null;
650 }
651
652 if (!$error && $ncSqlObj !== null) {
653 $arrayreplacement = array_merge(
654 $ncSqlObj->getSubstitutionMap(),
655 [
656 'htdocs/modulebuilder/template' => $ncSqlObj->moduleNameLower,
657 '---Replace with your own copyright and developer email---' => getLicenceHeader($user, $langs, $now),
658 ]
659 );
660
661 dolReplaceInFile($destfile1, $arrayreplacement);
662 dolReplaceInFile($destfile2, $arrayreplacement);
663 modulebuilderValidateGeneratedFile($destfile1, $ncSqlObj);
664 modulebuilderValidateGeneratedFile($destfile2, $ncSqlObj);
665 }
666 } else {
667 $langs->load("errors");
668 if ($result1 <= 0) {
669 setEventMessages($langs->trans('ErrorFailToCreateFile', $destfile1), null, 'errors');
670 }
671 if ($result2 <= 0) {
672 setEventMessages($langs->trans('ErrorFailToCreateFile', $destfile2), null, 'errors');
673 }
674 }
675
676 // Now we update the object file to set $this->isextrafieldmanaged to 1
677 $srcfile = $dirins.'/'.dol_strtolower($module).'/class/'.dol_strtolower($objectname).'.class.php';
678 $arrayreplacement = array('/\$this->isextrafieldmanaged = 0;/' => '$this->isextrafieldmanaged = 1;');
679 $arrayreplacement = array('/\$isextrafieldmanaged = 0;/' => '$isextrafieldmanaged = 1;');
680 dolReplaceInFile($srcfile, $arrayreplacement, '', '0', 0, 1);
681}
682
683
684// init Hook
685if ($dirins && $action == 'inithook' && !empty($module) /* && $user->hasRight("modulebuilder", "run") // already checked */) {
686 dol_mkdir($dirins.'/'.dol_strtolower($module).'/class');
687 $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template';
688 $srcfile = $srcdir.'/class/actions_mymodule.class.php';
689 $destfile = $dirins.'/'.dol_strtolower($module).'/class/actions_'.dol_strtolower($module).'.class.php';
690 $result = dol_copy($srcfile, $destfile, '0', 0);
691
692 if ($result > 0) {
693 $modulename = dol_ucfirst($module); // Force first letter in uppercase
694
695 //var_dump($phpfileval['fullname']);
696 $arrayreplacement = array(
697 'mymodule' => dol_strtolower($modulename),
698 'MyModule' => $modulename,
699 'MYMODULE' => dol_strtoupper($modulename),
700 'My module' => $modulename,
701 'my module' => $modulename,
702 'Mon module' => $modulename,
703 'mon module' => $modulename,
704 'htdocs/modulebuilder/template' => dol_strtolower($modulename),
705 '---Replace with your own copyright and developer email---' => getLicenceHeader($user, $langs, $now)
706 );
707
708 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
709 dolReplaceInFile($destfile, $arrayreplacement);
710 } else {
711 $langs->load("errors");
712 setEventMessages($langs->trans('ErrorFailToCreateFile', $destfile), null, 'errors');
713 }
714}
715
716
717// init Trigger
718if ($dirins && $action == 'inittrigger' && !empty($module) /* && $user->hasRight("modulebuilder", "run") // already checked */) {
719 dol_mkdir($dirins.'/'.dol_strtolower($module).'/core/triggers');
720 $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template';
721 $srcfile = $srcdir.'/core/triggers/interface_99_modMyModule_MyModuleTriggers.class.php';
722 $destfile = $dirins.'/'.dol_strtolower($module).'/core/triggers/interface_99_mod'.$module.'_'.$module.'Triggers.class.php';
723 $result = dol_copy($srcfile, $destfile, '0', 0);
724
725 if ($result > 0) {
726 $modulename = dol_ucfirst($module); // Force first letter in uppercase
727
728 //var_dump($phpfileval['fullname']);
729 $arrayreplacement = array(
730 'mymodule' => dol_strtolower($modulename),
731 'MyModule' => $modulename,
732 'MYMODULE' => dol_strtoupper($modulename),
733 'My module' => $modulename,
734 'my module' => $modulename,
735 'Mon module' => $modulename,
736 'mon module' => $modulename,
737 'htdocs/modulebuilder/template' => dol_strtolower($modulename),
738 '---Replace with your own copyright and developer email---' => getLicenceHeader($user, $langs, $now)
739 );
740
741 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
742 dolReplaceInFile($destfile, $arrayreplacement);
743 } else {
744 $langs->load("errors");
745 setEventMessages($langs->trans('ErrorFailToCreateFile', $destfile), null, 'errors');
746 }
747}
748
749
750// init Widget
751if ($dirins && $action == 'initwidget' && !empty($module) /* && $user->hasRight("modulebuilder", "run") // already checked */) {
752 dol_mkdir($dirins.'/'.dol_strtolower($module).'/core/boxes');
753 $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template';
754 $srcfile = $srcdir.'/core/boxes/mymodulewidget1.php';
755 $destfile = $dirins.'/'.dol_strtolower($module).'/core/boxes/'.dol_strtolower($module).'widget1.php';
756 $result = dol_copy($srcfile, $destfile, '0', 0);
757
758 if ($result > 0) {
759 $modulename = dol_ucfirst($module); // Force first letter in uppercase
760
761 //var_dump($phpfileval['fullname']);
762 $arrayreplacement = array(
763 'mymodule' => dol_strtolower($modulename),
764 'MyModule' => $modulename,
765 'MYMODULE' => dol_strtoupper($modulename),
766 'My module' => $modulename,
767 'my module' => $modulename,
768 'Mon module' => $modulename,
769 'mon module' => $modulename,
770 'htdocs/modulebuilder/template' => dol_strtolower($modulename),
771 '---Replace with your own copyright and developer email---' => getLicenceHeader($user, $langs, $now)
772 );
773
774 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
775 dolReplaceInFile($destfile, $arrayreplacement);
776 } else {
777 $langs->load("errors");
778 setEventMessages($langs->trans('ErrorFailToCreateFile', $destfile), null, 'errors');
779 }
780}
781
782
783// init EmailSelector
784if ($dirins && $action == 'initemailing' && !empty($module) /* && $user->hasRight("modulebuilder", "run") // already checked */) {
785 dol_mkdir($dirins.'/'.dol_strtolower($module).'/core/modules/mailings');
786 $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template';
787 $srcfile = $srcdir.'/core/modules/mailings/mailing_mymodule_selector1.modules.php';
788 $destfile = $dirins.'/'.dol_strtolower($module).'/core/modules/mailings/mailing_'.dol_strtolower($module).'_selector1.modules.php';
789 $result = dol_copy($srcfile, $destfile, '0', 0);
790
791 if ($result > 0) {
792 $modulename = dol_ucfirst($module); // Force first letter in uppercase
793
794 //var_dump($phpfileval['fullname']);
795 $arrayreplacement = array(
796 'mymodule' => dol_strtolower($modulename),
797 'MyModule' => $modulename,
798 'MYMODULE' => dol_strtoupper($modulename),
799 'My module' => $modulename,
800 'my module' => $modulename,
801 'Mon module' => $modulename,
802 'mon module' => $modulename,
803 'htdocs/modulebuilder/template' => dol_strtolower($modulename),
804 '---Replace with your own copyright and developer email---' => getLicenceHeader($user, $langs, $now)
805 );
806
807 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
808 dolReplaceInFile($destfile, $arrayreplacement);
809 } else {
810 $langs->load("errors");
811 setEventMessages($langs->trans('ErrorFailToCreateFile', $destfile), null, 'errors');
812 }
813}
814
815
816// init CSS
817if ($dirins && $action == 'initcss' && !empty($module) /* && $user->hasRight("modulebuilder", "run") // already checked */) {
818 dol_mkdir($dirins.'/'.dol_strtolower($module).'/css');
819 $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template';
820 $srcfile = $srcdir.'/css/mymodule.css.php';
821 $destfile = $dirins.'/'.dol_strtolower($module).'/css/'.dol_strtolower($module).'.css.php';
822 $result = dol_copy($srcfile, $destfile, '0', 0);
823
824 if ($result > 0) {
825 $modulename = dol_ucfirst($module); // Force first letter in uppercase
826
827 //var_dump($phpfileval['fullname']);
828 $arrayreplacement = array(
829 'mymodule' => dol_strtolower($modulename),
830 'MyModule' => $modulename,
831 'MYMODULE' => dol_strtoupper($modulename),
832 'My module' => $modulename,
833 'my module' => $modulename,
834 'Mon module' => $modulename,
835 'mon module' => $modulename,
836 'htdocs/modulebuilder/template' => dol_strtolower($modulename),
837 '---Replace with your own copyright and developer email---' => getLicenceHeader($user, $langs, $now)
838 );
839
840 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
841 dolReplaceInFile($destfile, $arrayreplacement);
842
843 // Update descriptor file to uncomment file
844 $srcfile = $dirins.'/'.dol_strtolower($module).'/core/modules/mod'.$module.'.class.php';
845 $arrayreplacement = array('/\/\/\s*\''.preg_quote('/'.dol_strtolower($module).'/css/'.dol_strtolower($module).'.css.php', '/').'\'/' => '\'/'.dol_strtolower($module).'/css/'.dol_strtolower($module).'.css.php\'');
846 dolReplaceInFile($srcfile, $arrayreplacement, '', '0', 0, 1);
847 } else {
848 $langs->load("errors");
849 setEventMessages($langs->trans('ErrorFailToCreateFile', $destfile), null, 'errors');
850 }
851}
852
853
854// init JS
855if ($dirins && $action == 'initjs' && !empty($module) /* && $user->hasRight("modulebuilder", "run") // already checked */) {
856 dol_mkdir($dirins.'/'.dol_strtolower($module).'/js');
857 $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template';
858 $srcfile = $srcdir.'/js/mymodule.js.php';
859 $destfile = $dirins.'/'.dol_strtolower($module).'/js/'.dol_strtolower($module).'.js.php';
860 $result = dol_copy($srcfile, $destfile, '0', 0);
861
862 if ($result > 0) {
863 $modulename = dol_ucfirst($module); // Force first letter in uppercase
864
865 //var_dump($phpfileval['fullname']);
866 $arrayreplacement = array(
867 'mymodule' => dol_strtolower($modulename),
868 'MyModule' => $modulename,
869 'MYMODULE' => dol_strtoupper($modulename),
870 'My module' => $modulename,
871 'my module' => $modulename,
872 'Mon module' => $modulename,
873 'mon module' => $modulename,
874 'htdocs/modulebuilder/template' => dol_strtolower($modulename),
875 '---Replace with your own copyright and developer email---' => getLicenceHeader($user, $langs, $now)
876 );
877
878 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
879 dolReplaceInFile($destfile, $arrayreplacement);
880
881 // Update descriptor file to uncomment file
882 $srcfile = $dirins.'/'.dol_strtolower($module).'/core/modules/mod'.$module.'.class.php';
883 $arrayreplacement = array('/\/\/\s*\''.preg_quote('/'.dol_strtolower($module).'/js/'.dol_strtolower($module).'.js.php', '/').'\'/' => '\'/'.dol_strtolower($module).'/js/'.dol_strtolower($module).'.js.php\'');
884 dolReplaceInFile($srcfile, $arrayreplacement, '', '0', 0, 1);
885 } else {
886 $langs->load("errors");
887 setEventMessages($langs->trans('ErrorFailToCreateFile', $destfile), null, 'errors');
888 }
889}
890
891
892// init CLI
893if ($dirins && $action == 'initcli' && !empty($module) /* && $user->hasRight("modulebuilder", "run") // already checked */) {
894 dol_mkdir($dirins.'/'.dol_strtolower($module).'/scripts');
895 $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template';
896 $srcfile = $srcdir.'/scripts/mymodule.php';
897 $destfile = $dirins.'/'.dol_strtolower($module).'/scripts/'.dol_strtolower($module).'.php';
898 $result = dol_copy($srcfile, $destfile, '0', 0);
899
900 if ($result > 0) {
901 $modulename = dol_ucfirst($module); // Force first letter in uppercase
902
903 //var_dump($phpfileval['fullname']);
904 $arrayreplacement = array(
905 'mymodule' => dol_strtolower($modulename),
906 'MyModule' => $modulename,
907 'MYMODULE' => dol_strtoupper($modulename),
908 'My module' => $modulename,
909 'my module' => $modulename,
910 'Mon module' => $modulename,
911 'mon module' => $modulename,
912 'htdocs/modulebuilder/template' => dol_strtolower($modulename),
913 '__MYCOMPANY_NAME__' => $mysoc->name,
914 '__KEYWORDS__' => $modulename,
915 '__USER_FULLNAME__' => $user->getFullName($langs),
916 '__USER_EMAIL__' => $user->email,
917 '__YYYY-MM-DD__' => dol_print_date($now, 'dayrfc'),
918 '---Replace with your own copyright and developer email---' => getLicenceHeader($user, $langs, $now)
919 );
920
921 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
922 dolReplaceInFile($destfile, $arrayreplacement);
923 } else {
924 $langs->load("errors");
925 setEventMessages($langs->trans('ErrorFailToCreateFile', $destfile), null, 'errors');
926 }
927}
928
929
930$moduledescriptorfile = '/not_set/';
931$modulelowercase = null;
932
933// init Doc
934if ($dirins && $action == 'initdoc' && !empty($module) /* && $user->hasRight("modulebuilder", "run") // already checked */) {
935 dol_mkdir($dirins.'/'.dol_strtolower($module).'/doc');
936 $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template';
937 $srcfile = $srcdir.'/doc/Documentation.asciidoc';
938 $destfile = $dirins.'/'.dol_strtolower($module).'/doc/Documentation.asciidoc';
939 $result = dol_copy($srcfile, $destfile, '0', 0);
940
941 if ($result > 0) {
942 $modulename = dol_ucfirst($module); // Force first letter in uppercase
943 $modulelowercase = dol_strtolower($module);
944
945 //var_dump($phpfileval['fullname']);
946 $arrayreplacement = array(
947 'mymodule' => dol_strtolower($modulename),
948 'MyModule' => $modulename,
949 'MYMODULE' => dol_strtoupper($modulename),
950 'My module' => $modulename,
951 'my module' => $modulename,
952 'Mon module' => $modulename,
953 'mon module' => $modulename,
954 'htdocs/modulebuilder/template' => dol_strtolower($modulename),
955 '__MYCOMPANY_NAME__' => $mysoc->name,
956 '__KEYWORDS__' => $modulename,
957 '__USER_FULLNAME__' => $user->getFullName($langs),
958 '__USER_EMAIL__' => $user->email,
959 '__YYYY-MM-DD__' => dol_print_date($now, 'dayrfc'),
960 '---Replace with your own copyright and developer email---' => getLicenceHeader($user, $langs, $now)
961 );
962
963 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
964 dolReplaceInFile($destfile, $arrayreplacement);
965
966 // add table of properties
967 $dirins = $listofmodules[dol_strtolower($module)]['moduledescriptorrootpath'];
968 $destdir = $dirins.'/'.dol_strtolower($module);
969 $objects = dolGetListOfObjectClasses($destdir);
970 foreach ($objects as $path => $obj) {
971 writePropsInAsciiDoc($path, $obj, $destfile);
972 }
973
974 // add table of permissions
975 $moduledescriptorfile = $dirins.'/'.dol_strtolower($module).'/core/modules/mod'.$module.'.class.php';
976 writePermsInAsciiDoc($moduledescriptorfile, $destfile);
977
978 // add api urls if file exist
979 if (file_exists($dirins.'/'.dol_strtolower($module).'/class/api_'.dol_strtolower($module).'.class.php')) {
980 $apiFile = $dirins.'/'.dol_strtolower($module).'/class/api_'.dol_strtolower($module).'.class.php';
981 writeApiUrlsInDoc($apiFile, $destfile);
982 }
983
984 // add ChangeLog in Doc
985 if (file_exists($dirins.'/'.dol_strtolower($module).'/ChangeLog.md')) {
986 $changeLog = $dirins.'/'.dol_strtolower($module).'/ChangeLog.md';
987 $string = file_get_contents($changeLog);
988
989 $replace = explode("\n", $string);
990 $strreplace = array();
991 foreach ($replace as $line) {
992 if ($line === '') {
993 continue;
994 }
995 if (strpos($line, '##') !== false) {
996 $strreplace[$line] = str_replace('##', '', $line);
997 } else {
998 $strreplace[$line] = $line;
999 }
1000 }
1001 $stringLog = implode("\n", $strreplace);
1002 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
1003 dolReplaceInFile($destfile, array('//include::ChangeLog.md[]' => '','__CHANGELOG__' => $stringLog));
1004 }
1005
1006 // Delete old documentation files
1007 $FILENAMEDOC = $modulelowercase.'.html';
1008 $FILENAMEDOCPDF = $modulelowercase.'.pdf';
1009 $outputfiledoc = dol_buildpath($modulelowercase, 0).'/doc/'.$FILENAMEDOC;
1010 $outputfiledocurl = dol_buildpath($modulelowercase, 1).'/doc/'.$FILENAMEDOC;
1011 $outputfiledocpdf = dol_buildpath($modulelowercase, 0).'/doc/'.$FILENAMEDOCPDF;
1012 $outputfiledocurlpdf = dol_buildpath($modulelowercase, 1).'/doc/'.$FILENAMEDOCPDF;
1013
1014 dol_delete_file($outputfiledoc, 0, 0, 0, null, false, 0);
1015 dol_delete_file($outputfiledocpdf, 0, 0, 0, null, false, 0);
1016 } else {
1017 $langs->load("errors");
1018 setEventMessages($langs->trans('ErrorFailToCreateFile', $destfile), null, 'errors');
1019 }
1020}
1021
1022
1023// add Language
1024if ($dirins && $action == 'addlanguage' && !empty($module) /* && $user->hasRight("modulebuilder", "run") // already checked */) {
1025 $newlangcode = GETPOST('newlangcode', 'aZ09');
1026
1027 if ($newlangcode) {
1028 $modulelowercase = dol_strtolower($module);
1029
1030 // Dir for module
1031 $diroflang = dol_buildpath($modulelowercase, 0);
1032
1033 if ($diroflang == $dolibarr_main_document_root.'/'.$modulelowercase) {
1034 // This is not a custom module, we force diroflang to htdocs root
1035 $diroflang = $dolibarr_main_document_root;
1036
1037 $srcfile = $diroflang.'/langs/en_US/'.$modulelowercase.'.lang';
1038 $destfile = $diroflang.'/langs/'.$newlangcode.'/'.$modulelowercase.'.lang';
1039
1040 $result = dol_copy($srcfile, $destfile, '0', 0);
1041 if ($result < 0) {
1042 setEventMessages($langs->trans("ErrorFailToCopyFile", $srcfile, $destfile), null, 'errors');
1043 }
1044 } else {
1045 $srcdir = $diroflang.'/langs/en_US';
1046 $srcfile = $diroflang.'/langs/en_US/'.$modulelowercase.'.lang';
1047 $destdir = $diroflang.'/langs/'.$newlangcode;
1048
1049 $arrayofreplacement = array();
1050 if (!dol_is_dir($srcdir) || !dol_is_file($srcfile)) {
1051 $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template/langs/en_US';
1052 $arrayofreplacement = array('mymodule' => $modulelowercase);
1053 }
1054 $result = dolCopyDir($srcdir, $destdir, '0', 0, $arrayofreplacement);
1055 }
1056 } else {
1057 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Language")), null, 'errors');
1058 }
1059}
1060
1061
1062// Remove/delete File
1063if ($dirins && $action == 'confirm_removefile' && !empty($module) /* && $user->hasRight("modulebuilder", "run") // already checked */) {
1064 $objectname = $tabobj;
1065 $dirins = $listofmodules[dol_strtolower($module)]['moduledescriptorrootpath'];
1066 $destdir = $dirins.'/'.dol_strtolower($module);
1067
1068 $relativefilename = dol_sanitizePathName(GETPOST('file', 'restricthtml'));
1069
1070 // Now we delete the file
1071 if ($relativefilename) {
1072 $dirnametodelete = dirname($relativefilename);
1073 $filetodelete = $dirins.'/'.$relativefilename;
1074 $dirtodelete = $dirins.'/'.$dirnametodelete;
1075
1076 // Get list of existing objects
1077 $objects = dolGetListOfObjectClasses($destdir);
1078
1079 $keyofobjecttodelete = array_search($objectname, $objects);
1080 if ($keyofobjecttodelete !== false) {
1081 unset($objects[$keyofobjecttodelete]);
1082 }
1083
1084 // Delete or modify the file
1085 if (strpos($relativefilename, 'api') !== false) {
1086 $file_api = $destdir.'/class/api_'.dol_strtolower($module).'.class.php';
1087
1088 $removeFile = removeObjectFromApiFile($file_api, $objects, $objectname);
1089
1090 if (count($objects) == 0) {
1091 $result = dol_delete_file($filetodelete, 1);
1092 }
1093
1094 if ($removeFile) {
1095 setEventMessages($langs->trans("ApiObjectDeleted"), null);
1096 }
1097 } else {
1098 $result = dol_delete_file($filetodelete, 1);
1099 }
1100
1101 if (!$result) {
1102 setEventMessages($langs->trans("ErrorFailToDeleteFile", basename($filetodelete)), null, 'errors');
1103 } else {
1104 // If we delete a .sql file, we delete also the other .sql file
1105 if (preg_match('/\.sql$/', $relativefilename)) {
1106 if (preg_match('/\.key\.sql$/', $relativefilename)) {
1107 $relativefilename = preg_replace('/\.key\.sql$/', '.sql', $relativefilename);
1108 $filetodelete = $dirins.'/'.$relativefilename;
1109 $result = dol_delete_file($filetodelete, 1);
1110 } elseif (preg_match('/\.sql$/', $relativefilename)) {
1111 $relativefilename = preg_replace('/\.sql$/', '.key.sql', $relativefilename);
1112 $filetodelete = $dirins.'/'.$relativefilename;
1113 $result = dol_delete_file($filetodelete, 1);
1114 }
1115 }
1116
1117 if (dol_is_dir_empty($dirtodelete)) {
1118 dol_delete_dir($dirtodelete);
1119 }
1120
1121 // Update descriptor file to comment file
1122 if (in_array($tab, array('css', 'js'))) {
1123 $srcfile = $dirins.'/'.dol_strtolower($module).'/core/modules/mod'.$module.'.class.php';
1124 $arrayreplacement = array('/^\s*\''.preg_quote('/'.$relativefilename, '/').'\',*/m' => ' // \'/'.$relativefilename.'\',');
1125 dolReplaceInFile($srcfile, $arrayreplacement, '', '0', 0, 1);
1126 }
1127
1128 if (preg_match('/_extrafields/', $relativefilename)) {
1129 // Now we update the object file to set $isextrafieldmanaged to 0
1130 $srcfile = $dirins.'/'.dol_strtolower($module).'/class/'.dol_strtolower($objectname).'.class.php';
1131 $arrayreplacement = array('/\$isextrafieldmanaged = 1;/' => '$isextrafieldmanaged = 0;');
1132 dolReplaceInFile($srcfile, $arrayreplacement, '', '0', 0, 1);
1133 }
1134
1135 // Now we update the lib file to set $showtabofpagexxx to 0
1136 $varnametoupdate = '';
1137 $reg = array();
1138 if (preg_match('/_([a-z]+)\.php$/', $relativefilename, $reg)) {
1139 $varnametoupdate = 'showtabofpage'.$reg[1];
1140 }
1141 if ($varnametoupdate) {
1142 $srcfile = $dirins.'/'.dol_strtolower($module).'/lib/'.dol_strtolower($module).'_'.dol_strtolower($objectname).'.lib.php';
1143 $arrayreplacement = array('/\$'.preg_quote($varnametoupdate, '/').' = 1;/' => '$'.preg_quote($varnametoupdate, '/').' = 0;');
1144 dolReplaceInFile($srcfile, $arrayreplacement, '', '0', 0, 1);
1145 }
1146 }
1147 }
1148}
1149
1150// Init an object
1151if ($dirins && $action == 'initobject' && $module && $objectname) { // Test on permission already done
1152 $warning = 0;
1153
1154 $objectname = dol_string_nounprintableascii(dol_string_unaccent(dol_ucwords($objectname))); // Force first letter in uppercase
1155
1156 $dirins = $dirread = $listofmodules[dol_strtolower($module)]['moduledescriptorrootpath'];
1157 $moduletype = $listofmodules[dol_strtolower($module)]['moduletype'];
1158
1159 if (preg_match('/[^a-z0-9]/i', $objectname)) {
1160 $error++;
1161 setEventMessages($langs->trans("SpaceOrSpecialCharAreNotAllowed"), null, 'errors');
1162 $tabobj = 'newobject';
1163 }
1164 if (class_exists($objectname)) {
1165 // TODO Add a more efficient detection. Scan disk ?
1166 $error++;
1167 setEventMessages($langs->trans("AnObjectWithThisClassNameAlreadyExists"), null, 'errors');
1168 $tabobj = 'newobject';
1169 }
1170
1171 try {
1172 $ncObj = new NamingContract($module, $objectname);
1173 } catch (\InvalidArgumentException $e) {
1174 $error++;
1175 setEventMessages($langs->trans("SpaceOrSpecialCharAreNotAllowed"), null, 'errors');
1176 $ncObj = null;
1177 }
1178
1179 $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template';
1180 $destdir = $dirins.'/'.dol_strtolower($module);
1181
1182 // Optional tabs and card actions selected by user, and detection of an already generated object (for idempotence warning)
1183 $enabledtabs = filterEnabledKeys(GETPOST('enabledtab', 'array'), getModuleBuilderObjectTabs());
1184 $enabledcardactions = filterEnabledKeys(GETPOST('enabledcardaction', 'array'), getModuleBuilderObjectCardActions());
1185 $objectalreadyexists = dol_is_file($destdir.'/class/'.dol_strtolower($objectname).'.class.php');
1186
1187 // The dir was not created by init
1188 dol_mkdir($destdir.'/class');
1189 dol_mkdir($destdir.'/img');
1190 dol_mkdir($destdir.'/lib');
1191 dol_mkdir($destdir.'/scripts');
1192 dol_mkdir($destdir.'/sql');
1193 dol_mkdir($destdir.'/ajax');
1194 dol_mkdir($destdir.'/stats');
1195
1196 // Scan dir class to find if an object with the same name already exists.
1197 if (!$error) {
1198 $dirlist = dol_dir_list($destdir.'/class', 'files', 0, '\.txt$');
1199 $alreadyfound = false;
1200 foreach ($dirlist as $key => $val) {
1201 $filefound = preg_replace('/\.txt$/', '', $val['name']);
1202 if (dol_strtolower($objectname) == dol_strtolower($filefound) && $objectname != $filefound) {
1203 $alreadyfound = true;
1204 $error++;
1205 setEventMessages($langs->trans("AnObjectAlreadyExistWithThisNameAndDiffCase"), null, 'errors');
1206 break;
1207 }
1208 }
1209 }
1210
1211 // If we must reuse an existing table for properties, define $stringforproperties
1212 // Generate class file from the table
1213 $stringforproperties = '';
1214 $tablename = GETPOST('initfromtablename', 'alpha');
1215 if ($tablename) {
1216 $_results = $db->DDLDescTable($tablename);
1217 if (empty($_results)) {
1218 $error++;
1219 $langs->load("errors");
1220 setEventMessages($langs->trans("ErrorTableNotFound", $tablename), null, 'errors');
1221 } else {
1249 /*public $fields=array(
1250 'rowid' => array('type' => 'integer', 'label' => 'TechnicalID', 'enabled' => 1, 'visible' => -2, 'notnull' => 1, 'index' => 1, 'position' => 1, 'comment' => 'Id'),
1251 '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'),
1252 'entity' => array('type' => 'integer', 'label' => 'Entity', 'enabled' => 1, 'visible' => 0, 'default' => 1, 'notnull' => 1, 'index' => 1, 'position' => 20),
1253 'label' => array('type' => 'varchar(255)', 'label' => 'Label', 'enabled' => 1, 'visible' => 1, 'position' => 30, 'searchall' => 1, 'css' => 'minwidth200', 'help' => 'Help text', 'alwayseditable' => '1'),
1254 'amount' => array('type' => 'double(24,8)', 'label' => 'Amount', 'enabled' => 1, 'visible' => 1, 'default' => 'null', 'position' => 40, 'searchall' => 0, 'isameasure' => 1, 'help' => 'Help text'),
1255 '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'),
1256 'description' => array('type' => 'text', 'label' => 'Descrption', 'enabled' => 1, 'visible' => 0, 'position' => 60),
1257 'note_public' => array('type' => 'html', 'label' => 'NotePublic', 'enabled' => 1, 'visible' => 0, 'position' => 61),
1258 'note_private' => array('type' => 'html', 'label' => 'NotePrivate', 'enabled' => 1, 'visible' => 0, 'position' => 62),
1259 'date_creation' => array('type' => 'datetime', 'label' => 'DateCreation', 'enabled' => 1, 'visible' => -2, 'notnull' => 1, 'position' => 500),
1260 'tms' => array('type' => 'timestamp', 'label' => 'DateModification', 'enabled' => 1, 'visible' => -2, 'notnull' => 1, 'position' => 501),
1261 //'date_valid' => array('type' => 'datetime', 'label' => 'DateCreation', 'enabled' => 1, 'visible' => -2, 'position' => 502),
1262 'fk_user_creat' => array('type' => 'integer', 'label' => 'UserAuthor', 'enabled' => 1, 'visible' => -2, 'notnull' => 1, 'position' => 510),
1263 'fk_user_modif' => array('type' => 'integer', 'label' => 'UserModif', 'enabled' => 1, 'visible' => -2, 'notnull' => -1, 'position' => 511),
1264 //'fk_user_valid' => array('type' => 'integer', 'label' => 'UserValidation', 'enabled' => 1, 'visible' => -1, 'position' => 512),
1265 'import_key' => array('type' => 'varchar(14)', 'label' => 'ImportId', 'enabled' => 1, 'visible' => -2, 'notnull' => -1, 'index' => 0, 'position' => 1000),
1266 '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')),
1267 );*/
1268
1269 $stringforproperties = '// BEGIN MODULEBUILDER PROPERTIES'."\n";
1270 $stringforproperties .= 'public $fields = array('."\n";
1271 $i = 10;
1272 while ($obj = $db->fetch_object($_results)) {
1273 // fieldname
1274 $fieldname = $obj->Field;
1275 // type
1276 $type = $obj->Type;
1277 if ($type == 'int(11)') {
1278 $type = 'integer';
1279 } elseif ($type == 'float') {
1280 $type = 'real';
1281 } elseif (strstr($type, 'tinyint')) {
1282 $type = 'integer';
1283 } elseif (strstr($type, 'url')) {
1284 $type = 'varchar(255)';
1285 } elseif ($obj->Field == 'fk_soc') {
1286 $type = 'integer:Societe:societe/class/societe.class.php';
1287 } elseif (preg_match('/^fk_proj/', $obj->Field)) {
1288 $type = 'integer:Project:projet/class/project.class.php:1:fk_statut=1';
1289 } elseif (preg_match('/^fk_prod/', $obj->Field)) {
1290 $type = 'integer:Product:product/class/product.class.php:1';
1291 } elseif ($obj->Field == 'fk_warehouse') {
1292 $type = 'integer:Entrepot:product/stock/class/entrepot.class.php';
1293 } elseif (preg_match('/^(fk_user|fk_commercial)/', $obj->Field)) {
1294 $type = 'integer:User:user/class/user.class.php';
1295 }
1296
1297 // notnull
1298 $notnull = ($obj->Null == 'YES' ? 0 : 1);
1299 if ($fieldname == 'fk_user_modif') {
1300 $notnull = -1;
1301 }
1302 // label
1303 $label = preg_replace('/_/', '', dol_ucfirst($fieldname));
1304 if ($fieldname == 'rowid') {
1305 $label = 'TechnicalID';
1306 }
1307 if ($fieldname == 'import_key') {
1308 $label = 'ImportId';
1309 }
1310 if ($fieldname == 'fk_soc') {
1311 $label = 'ThirdParty';
1312 }
1313 if (in_array($fieldname, array('tms', 'date_modification'))) {
1314 $label = 'DateModification';
1315 }
1316 if (in_array($fieldname, array('datec', 'date_creation'))) {
1317 $label = 'DateCreation';
1318 }
1319 if ($fieldname == 'date_valid') {
1320 $label = 'DateValidation';
1321 }
1322 if ($fieldname == 'datev') {
1323 $label = 'DateValidation';
1324 }
1325 if ($fieldname == 'note_private') {
1326 $label = 'NotePublic';
1327 }
1328 if ($fieldname == 'note_public') {
1329 $label = 'NotePrivate';
1330 }
1331 if ($fieldname == 'fk_user_creat') {
1332 $label = 'UserAuthor';
1333 }
1334 if ($fieldname == 'fk_user_modif') {
1335 $label = 'UserModif';
1336 }
1337 if ($fieldname == 'fk_user_valid') {
1338 $label = 'UserValidation';
1339 }
1340 // visible
1341 $visible = -1;
1342 if (in_array($fieldname, array('ref', 'label'))) {
1343 $visible = 1;
1344 }
1345 if ($fieldname == 'entity') {
1346 $visible = -2;
1347 }
1348 if ($fieldname == 'entity') {
1349 $visible = -2;
1350 }
1351 if ($fieldname == 'import_key') {
1352 $visible = -2;
1353 }
1354 if ($fieldname == 'fk_user_creat') {
1355 $visible = -2;
1356 }
1357 if ($fieldname == 'fk_user_modif') {
1358 $visible = -2;
1359 }
1360 if (in_array($fieldname, array('ref_ext', 'model_pdf', 'note_public', 'note_private'))) {
1361 $visible = 0;
1362 }
1363 // enabled
1364 $enabled = 1;
1365 // default
1366 $default = '';
1367 if ($fieldname == 'entity') {
1368 $default = 1;
1369 }
1370 // position
1371 $position = $i;
1372 if (in_array($fieldname, array('status', 'statut', 'fk_status', 'fk_statut'))) {
1373 $position = 500;
1374 }
1375 if ($fieldname == 'import_key') {
1376 $position = 900;
1377 }
1378 // $alwayseditable
1379 $alwayseditable = 0;
1380 if ($fieldname == 'label') {
1381 $alwayseditable = 1;
1382 } else {
1383 $alwayseditable = 0;
1384 }
1385 // index
1386 $index = 0;
1387 if ($fieldname == 'entity') {
1388 $index = 1;
1389 }
1390 // css, cssview, csslist
1391 $css = '';
1392 $cssview = '';
1393 $csslist = '';
1394 if (preg_match('/^fk_/', $fieldname)) {
1395 $css = 'maxwidth500 widthcentpercentminusxx';
1396 }
1397 if ($fieldname == 'label') {
1398 $css = 'minwidth300';
1399 $cssview = 'wordbreak';
1400 }
1401 if (in_array($fieldname, array('note_public', 'note_private'))) {
1402 $cssview = 'wordbreak';
1403 }
1404 if (in_array($fieldname, array('ref', 'label')) || preg_match('/integer:/', $type)) {
1405 $csslist = 'tdoverflowmax150';
1406 }
1407
1408 // type
1409 $picto = '';
1410 if (isset($obj->Picto)) { // This should never exists
1411 $picto = $obj->Picto;
1412 }
1413 if (preg_match('/^fk_soc/', $obj->Field)) {
1414 $picto = 'company';
1415 } elseif (preg_match('/^fk_contact/', $obj->Field)) {
1416 $picto = 'contact';
1417 } elseif (preg_match('/^fk_bank/', $obj->Field)) {
1418 $picto = 'bank';
1419 } elseif (preg_match('/^fk_user/', $obj->Field)) {
1420 $picto = 'user';
1421 } elseif (preg_match('/^fk_warehouse/', $obj->Field)) {
1422 $picto = 'warehouse';
1423 } elseif (preg_match('/^fk_prod/', $obj->Field)) {
1424 $picto = 'product';
1425 } elseif (preg_match('/^fk_proj/', $obj->Field)) {
1426 $picto = 'project';
1427 } elseif (preg_match('/^fk_task/', $obj->Field)) {
1428 $picto = 'task';
1429 }
1430
1431 // lang
1432 $lang = $module.'@'.$module;
1433
1434 // Build the property string
1435 $stringforproperties .= "'".$obj->Field."' => array('type' => '".$type."', 'label' => '".$label."',";
1436 if ($default != '') {
1437 $stringforproperties .= " 'default' => ".$default.",";
1438 }
1439 $stringforproperties .= " 'enabled' => ".$enabled.",";
1440 $stringforproperties .= " 'visible' => ".$visible;
1441 if ($notnull) {
1442 $stringforproperties .= ", 'notnull' => ".$notnull;
1443 }
1444 if ($alwayseditable) {
1445 $stringforproperties .= ", 'alwayseditable' => 1";
1446 }
1447 if ($fieldname == 'ref' || $fieldname == 'code') {
1448 $stringforproperties .= ", 'showoncombobox' => 1";
1449 }
1450 $stringforproperties .= ", 'position' => ".$position;
1451 if ($index) {
1452 $stringforproperties .= ", 'index' => ".$index;
1453 }
1454 if ($picto) {
1455 $stringforproperties .= ", 'picto' => '".$picto."'";
1456 }
1457 if ($css) {
1458 $stringforproperties .= ", 'css' => '".$css."'";
1459 }
1460 if ($cssview) {
1461 $stringforproperties .= ", 'cssview' => '".$cssview."'";
1462 }
1463 if ($csslist) {
1464 $stringforproperties .= ", 'csslist' => '".$csslist."'";
1465 }
1466
1467 $stringforproperties .= ", 'lang' => '".$lang."'";
1468
1469 $stringforproperties .= "),\n";
1470 $i += 5;
1471 }
1472 $stringforproperties .= ');'."\n";
1473 $stringforproperties .= '// END MODULEBUILDER PROPERTIES'."\n";
1474 }
1475 }
1476
1477 $filetogenerate = array();
1478 if (!$error) {
1479 // Copy some files
1480 $filetogenerate = [];
1481 foreach ([
1482 'myobject_card.php',
1483 'myobject_note.php',
1484 'myobject_contact.php',
1485 'myobject_document.php',
1486 'myobject_agenda.php',
1487 'myobject_list.php',
1488 'admin/myobject_extrafields.php',
1489 'ajax/myobject.php',
1490 'lib/mymodule_myobject.lib.php',
1491 //'test/phpunit/MyObjectTest.php',
1492 'sql/llx_mymodule_myobject.sql',
1493 'sql/llx_mymodule_myobject.key.sql',
1494 'sql/llx_mymodule_myobject_extrafields.sql',
1495 'sql/llx_mymodule_myobject_extrafields.key.sql',
1496 //'scripts/mymodule.php',
1497 'class/myobject.class.php',
1498 'class/myobjectstats.class.php',
1499 //'class/api_mymodule.class.php',
1500 'stats/myobject_index.php',
1501 ] as $templateFile) {
1502 $filetogenerate[$templateFile] = $ncObj->applyToFilename($templateFile);
1503 }
1504
1505 // Exclude tab page files for tabs not selected by user
1506 foreach (getModuleBuilderObjectTabs() as $tabkey => $tabinfo) {
1507 if (!in_array($tabkey, $enabledtabs, true)) {
1508 unset($filetogenerate[$tabinfo['file']]);
1509 }
1510 }
1511
1512 if (GETPOST('includerefgeneration', 'aZ09')) {
1513 dol_mkdir($destdir.'/core/modules/'.dol_strtolower($module));
1514
1515 foreach ([
1516 'core/modules/mymodule/mod_myobject_advanced.php',
1517 'core/modules/mymodule/mod_myobject_standard.php',
1518 'core/modules/mymodule/modules_myobject.php',
1519 ] as $templateFile) {
1520 $filetogenerate[$templateFile] = $ncObj->applyToFilename($templateFile);
1521 }
1522 }
1523 if (GETPOST('includedocgeneration', 'aZ09')) {
1524 dol_mkdir($destdir.'/core/modules/'.dol_strtolower($module));
1525 dol_mkdir($destdir.'/core/modules/'.dol_strtolower($module).'/doc');
1526
1527 foreach ([
1528 'core/modules/mymodule/doc/doc_generic_myobject_odt.modules.php',
1529 'core/modules/mymodule/doc/pdf_standard_myobject.modules.php',
1530 ] as $templateFile) {
1531 $filetogenerate[$templateFile] = $ncObj->applyToFilename($templateFile);
1532 }
1533 }
1534 $class = null;
1535 if (GETPOST('generatepermissions', 'aZ09')) {
1536 $firstobjectname = 'myobject';
1537 $pathtofile = $listofmodules[dol_strtolower($module)]['moduledescriptorrelpath'];
1538 dol_include_once($pathtofile);
1539 $class = 'mod'.$module;
1540 $moduleobj = null;
1541 if (class_exists($class)) {
1542 try {
1543 $moduleobj = new $class($db);
1544 '@phan-var-force DolibarrModules $moduleobj';
1546 } catch (Exception $e) {
1547 $error++;
1548 dol_print_error($db, $e->getMessage());
1549 }
1550 }
1551 if (is_object($moduleobj)) {
1552 $rights = $moduleobj->rights;
1553 } else {
1554 $rights = [];
1555 }
1556 $moduledescriptorfile = $destdir.'/core/modules/mod'.$module.'.class.php';
1557 $checkComment = checkExistComment($moduledescriptorfile, 1);
1558 if ($checkComment < 0) {
1559 setEventMessages($langs->trans("WarningCommentNotFound", $langs->trans("Permissions"), "mod".$module."class.php"), null, 'warnings');
1560 } else {
1561 $reportPerms = modulebuilderSyncRights(RightsSyncCommand::forObjectCreation($module, $moduledescriptorfile, is_array($rights) ? $rights : array(), $objectname));
1562 if ($reportPerms->skipped > 0) {
1563 setEventMessages($langs->trans("WarningPermissionAlreadyExist", $langs->transnoentities($objectname)), null, 'warnings');
1564 }
1565 }
1566 }
1567
1568 if (!$error) {
1569 foreach ($filetogenerate as $srcfile => $destfile) {
1570 $result = dol_copy($srcdir.'/'.$srcfile, $destdir.'/'.$destfile, $newmask, 0);
1571 if ($result <= 0) {
1572 if ($result < 0) {
1573 $warning++;
1574 $langs->load("errors");
1575 setEventMessages($langs->trans("ErrorFailToCopyFile", $srcdir.'/'.$srcfile, $destdir.'/'.$destfile), null, 'errors');
1576 } else {
1577 // $result == 0
1578 setEventMessages($langs->trans("FileAlreadyExists", $destfile), null, 'warnings');
1579 }
1580 }
1581 $arrayreplacement = array(
1582 '/myobject\.class\.php/' => dol_strtolower($objectname).'.class.php',
1583 '/myobject\.lib\.php/' => dol_strtolower($objectname).'.lib.php',
1584 );
1585
1586 dolReplaceInFile($destdir.'/'.$destfile, $arrayreplacement, '', '0', 0, 1);
1587 }
1588 }
1589
1590 // Replace property section with $stringforproperties
1591 if (!$error && $stringforproperties) {
1592 //var_dump($stringforproperties);exit;
1593 $arrayreplacement = array(
1594 '/\/\/ BEGIN MODULEBUILDER PROPERTIES.*\/\/ END MODULEBUILDER PROPERTIES/ims' => $stringforproperties
1595 );
1596
1597 dolReplaceInFile($destdir.'/class/'.dol_strtolower($objectname).'.class.php', $arrayreplacement, '', '0', 0, 1);
1598 }
1599
1600 // Edit the class 'class/'.dol_strtolower($objectname).'.class.php'
1601 if (GETPOST('includerefgeneration', 'aZ09')) {
1602 // Replace 'visible' => 1, 'noteditable' => 0, 'default' => ''
1603 $arrayreplacement = array(
1604 '/\'visible\'s*=>s*1,\s*\'noteditable\'s*=>s*0,\s*\'default\'s*=>s*\'\'/' => "'visible' => 4, 'noteditable' => 1, 'default' => '(PROV)'"
1605 );
1606 //var_dump($arrayreplacement);exit;
1607 //var_dump($destdir.'/class/'.dol_strtolower($objectname).'.class.php');exit;
1608 dolReplaceInFile($destdir.'/class/'.dol_strtolower($objectname).'.class.php', $arrayreplacement, '', '0', 0, 1);
1609
1610 $arrayreplacement = array(
1611 '/\'models\' => 0,/' => '\'models\' => 1,'
1612 );
1613 dolReplaceInFile($destdir.'/core/modules/mod'.$module.'.class.php', $arrayreplacement, '', '0', 0, 1);
1614 }
1615
1616 // Edit the setup file and the card page
1617 if (GETPOST('includedocgeneration', 'aZ09')) {
1618 // Replace some var init into some files
1619 $arrayreplacement = array(
1620 '/\$includedocgeneration = 0;/' => '$includedocgeneration = 1;'
1621 );
1622 dolReplaceInFile($destdir.'/class/'.dol_strtolower($objectname).'.class.php', $arrayreplacement, '', '0', 0, 1);
1623 dolReplaceInFile($destdir.'/'.dol_strtolower($objectname).'_card.php', $arrayreplacement, '', '0', 0, 1);
1624
1625 $arrayreplacement = array(
1626 '/\'models\' => 0,/' => '\'models\' => 1,'
1627 );
1628
1629 dolReplaceInFile($destdir.'/core/modules/mod'.$module.'.class.php', $arrayreplacement, '', '0', 0, 1);
1630 }
1631
1632 // TODO Update entries '$myTmpObjects['MyObject'] = array('includerefgeneration' => 0, 'includedocgeneration' => 0);'
1633
1634
1635 // Scan for object class files
1636 $listofobject = dol_dir_list($destdir.'/class', 'files', 0, '\.class\.php$');
1637
1638 $firstobjectname = '';
1639 $stringtoadd = '';
1640 foreach ($listofobject as $fileobj) {
1641 if (preg_match('/^api_/', $fileobj['name'])) {
1642 continue;
1643 }
1644 if (preg_match('/^actions_/', $fileobj['name'])) {
1645 continue;
1646 }
1647
1648 $tmpcontent = file_get_contents($fileobj['fullname']);
1649 $reg = array();
1650 if (preg_match('/class\s+([^\s]*)\s+extends\s+CommonObject/ims', $tmpcontent, $reg)) {
1651 $objectnameloop = $reg[1];
1652 if (empty($firstobjectname)) {
1653 $firstobjectname = $objectnameloop;
1654 }
1655 }
1656
1657 // Regenerate left menu entry in descriptor for $objectname
1658 $stringtoadd = "
1659 \$this->menu[\$r++] = array(
1660 'fk_menu' => 'fk_mainmenu=mymodule',
1661 'type' => 'left',
1662 'titre' => 'MyObject',
1663 'prefix' => img_picto('', \$this->picto, 'class=\"paddingright pictofixedwidth valignmiddle\"'),
1664 'mainmenu' => 'mymodule',
1665 'leftmenu' => 'myobject',
1666 'url' => '/mymodule/myobject_list.php',
1667 'langs' => 'mymodule@mymodule',
1668 'position' => 1000 + \$r,
1669 'enabled' => 'isModEnabled(\"mymodule\")',
1670 'perms' => '".(GETPOST('generatepermissions') ? '$user->hasRight("mymodule", "myobject", "read")' : '1')."',
1671 'target' => '',
1672 'user' => 2,
1673 'object' => 'MyObject'
1674 );
1675 \$this->menu[\$r++] = array(
1676 'fk_menu' => 'fk_mainmenu=mymodule,fk_leftmenu=myobject',
1677 'type' => 'left',
1678 'titre' => 'List MyObject',
1679 'mainmenu' => 'mymodule',
1680 'leftmenu' => 'mymodule_myobject_list',
1681 'url' => '/mymodule/myobject_list.php',
1682 'langs' => 'mymodule@mymodule',
1683 'position' => 1000 + \$r,
1684 'enabled' => 'isModEnabled(\"mymodule\")',
1685 'perms' => '".(GETPOST('generatepermissions') ? '$user->hasRight("mymodule", "myobject", "read")' : '1')."',
1686 'target' => '',
1687 'user' => 2,
1688 'object' => 'MyObject'
1689 );
1690 \$this->menu[\$r++] = array(
1691 'fk_menu' => 'fk_mainmenu=mymodule,fk_leftmenu=myobject',
1692 'type' => 'left',
1693 'titre' => 'New MyObject',
1694 'mainmenu' => 'mymodule',
1695 'leftmenu' => 'mymodule_myobject_new',
1696 'url' => '/mymodule/myobject_card.php?action=create',
1697 'langs' => 'mymodule@mymodule',
1698 'position' => 1000 + \$r,
1699 'enabled' => 'isModEnabled(\"mymodule\")',
1700 'perms' => '".(GETPOST('generatepermissions') ? '$user->hasRight("mymodule", "myobject", "write")' : '1')."',
1701 'target' => '',
1702 'user' => 2,
1703 'object' => 'MyObject'
1704 );";
1705 $stringtoadd = $ncObj->applyTo($stringtoadd);
1706
1707 $moduledescriptorfile = $destdir.'/core/modules/mod'.$module.'.class.php';
1708 }
1709 // TODO Allow a replace with regex using dolReplaceInFile with param arryreplacementisregex to 1
1710 // TODO Avoid duplicate addition
1711
1712 // load class and check if menu exist with same object name
1713 $pathtofile = $listofmodules[dol_strtolower($module)]['moduledescriptorrelpath'];
1714 dol_include_once($pathtofile);
1715 $class = 'mod'.$module;
1716 $moduleobj = null;
1717 if (class_exists($class)) {
1718 try {
1719 $moduleobj = new $class($db);
1720 '@phan-var-force DolibarrModules $moduleobj';
1722 } catch (Exception $e) {
1723 $error++;
1724 dol_print_error($db, $e->getMessage());
1725 }
1726 }
1727 if (is_object($moduleobj)) {
1728 $menus = $moduleobj->menu;
1729 } else {
1730 $menus = array();
1731 }
1732 $counter = 0 ;
1733 foreach ($menus as $menu) {
1734 if ($menu['leftmenu'] == dol_strtolower($objectname)) {
1735 $counter++;
1736 }
1737 }
1738 if (!$counter) {
1739 $checkComment = checkExistComment($moduledescriptorfile, 0);
1740 if ($checkComment < 0) {
1741 $warning++;
1742 setEventMessages($langs->trans("WarningCommentNotFound", $langs->trans("Menus"), basename($moduledescriptorfile)), null, 'warnings');
1743 } else {
1744 $arrayofreplacement = array(
1745 '/* BEGIN MODULEBUILDER LEFTMENU MYOBJECT */' => '/* BEGIN MODULEBUILDER LEFTMENU '.dol_strtoupper($objectname).' */'.$stringtoadd."\n\t\t".'/* END MODULEBUILDER LEFTMENU '.dol_strtoupper($objectname).' */'."\n\t\t".'/* BEGIN MODULEBUILDER LEFTMENU MYOBJECT */'
1746 );
1747 dolReplaceInFile($moduledescriptorfile, $arrayofreplacement);
1748 }
1749 }
1750 // Add module descriptor to list of files to replace "MyObject' string with real name of object.
1751 $filetogenerate[] = 'core/modules/mod'.$module.'.class.php';
1752 }
1753
1754 if (! $error && GETPOST('nogeneratelines', 'aZ09')) {
1755 $checkComment = checkExistComment($moduledescriptorfile, 0);
1756 if ($checkComment < 0) {
1757 $warning++;
1758 setEventMessages($langs->trans("WarningCommentNotFound", $langs->trans("Menus"), basename($moduledescriptorfile)), null, 'warnings');
1759 } else {
1760 // File path
1761 $TFilePaths = [
1762 $destdir . '/class/' . dol_strtolower($objectname) . '.class.php',
1763 $destdir . '/class/api_' . dol_strtolower($module) . '.class.php',
1764 $destdir . '/' . dol_strtolower($objectname) . '_card.php'
1765 ];
1766
1767 // Pattern to remove everything between the tags
1769 foreach ($TFilePaths as $filePath) {
1770 // Skip files that were not generated (e.g. the API class when API generation is disabled);
1771 // a missing optional file must not abort the whole object generation.
1772 if (file_exists($filePath) && !removePatternFromFile($filePath, $pattern)) {
1773 $error++;
1774 }
1775 }
1776 }
1777 }
1778
1779 // Apply object tab selection on the generated lib file:
1780 // selected tabs -> hardcode the show flag to 1 (visible without extra config) ; unselected -> remove flag declaration and tab block
1781 if (!$error) {
1782 $libdestfile = $destdir.'/'.$ncObj->applyToFilename('lib/mymodule_myobject.lib.php');
1783 foreach (getModuleBuilderObjectTabs() as $tabkey => $tabinfo) {
1784 $marker = $tabinfo['marker'];
1785 if (in_array($tabkey, $enabledtabs, true)) {
1786 $arrayreplacement = array(
1787 '/\$'.$tabinfo['var'].' = getDolGlobalInt\‍([^;]*\‍);/' => '$'.$tabinfo['var'].' = 1;'
1788 );
1789 if (dolReplaceInFile($libdestfile, $arrayreplacement, '', '0', 0, 1) < 0) {
1790 $error++;
1791 dol_syslog("modulebuilder: failed to activate tab flag '".$tabkey."' in ".$libdestfile, LOG_ERR);
1792 }
1793 } else {
1794 if (!removePatternFromFile($libdestfile, '/\h*\/\/ BEGIN MODULEBUILDER TABFLAG '.$marker.'.*?\/\/ END MODULEBUILDER TABFLAG '.$marker.'\s*/s')
1795 || !removePatternFromFile($libdestfile, '/\h*\/\/ BEGIN MODULEBUILDER TAB '.$marker.'.*?\/\/ END MODULEBUILDER TAB '.$marker.'\s*/s')) {
1796 $error++;
1797 dol_syslog("modulebuilder: failed to purge tab '".$tabkey."' in ".$libdestfile, LOG_ERR);
1798 }
1799 }
1800 }
1801 $carddestfile = $destdir.'/'.$ncObj->applyToFilename('myobject_card.php');
1802
1803 // Agenda has an extra event widget on the card page: purge it too to avoid a dead link when the agenda tab is excluded
1804 if (!$error && !in_array('agenda', $enabledtabs, true)) {
1805 if (!removePatternFromFile($carddestfile, '/\h*\/\/ BEGIN MODULEBUILDER TAB AGENDA.*?\/\/ END MODULEBUILDER TAB AGENDA\s*/s')) {
1806 $error++;
1807 dol_syslog("modulebuilder: failed to purge agenda widget in ".$carddestfile, LOG_ERR);
1808 }
1809 }
1810
1811 // Apply card action selection on the generated card page:
1812 // unselected action -> purge every block it anchors ; selected action shipped commented out -> uncomment it
1813 if (!$error) {
1814 foreach (getModuleBuilderObjectCardActions() as $actionkey => $actioninfo) {
1815 if (!in_array($actionkey, $enabledcardactions, true)) {
1816 if (!removePatternFromFile($carddestfile, getModuleBuilderCardActionBlockPattern($actioninfo['marker']))) {
1817 $error++;
1818 dol_syslog("modulebuilder: failed to purge card action '".$actionkey."' in ".$carddestfile, LOG_ERR);
1819 }
1820 } elseif ($actioninfo['mode'] == 'activate') {
1821 foreach (getModuleBuilderCardActionUncommentPatterns($actioninfo['marker']) as $uncommentpattern) {
1822 if (!removePatternFromFile($carddestfile, $uncommentpattern)) {
1823 $error++;
1824 dol_syslog("modulebuilder: failed to activate card action '".$actionkey."' in ".$carddestfile, LOG_ERR);
1825 }
1826 }
1827 }
1828 }
1829 }
1830
1831 if ($objectalreadyexists) {
1832 setEventMessages($langs->trans("WarningTabSelectionOnRegeneration"), null, 'warnings');
1833 setEventMessages($langs->trans("WarningCardActionSelectionOnRegeneration"), null, 'warnings');
1834 }
1835 }
1836
1837 if (!$error) {
1838 // Edit PHP files to make replacement
1839 foreach ($filetogenerate as $destfile) {
1840 $phpfileval['fullname'] = $destdir.'/'.$destfile;
1841
1842 //var_dump($phpfileval['fullname']);
1843 $licenceValue = getDolGlobalString('MODULEBUILDER_SPECIFIC_AUTHOR')
1844 ? dol_print_date($now, '%Y') . ' ' . getDolGlobalString('MODULEBUILDER_SPECIFIC_AUTHOR')
1845 : getLicenceHeader($user, $langs, $now);
1846
1847 $arrayreplacement = array_merge(
1848 $ncObj->getSubstitutionMap(),
1849 [
1850 'htdocs/modulebuilder/template/' => $ncObj->moduleNameLower,
1851 '---Replace with your own copyright and developer email---' => $licenceValue,
1852 ]
1853 );
1854
1855 if (basename($phpfileval['fullname']) === 'mod'.$module.'.class.php') {
1856 // Module descriptor: substitute content but keep the persistent MODULEBUILDER markers intact
1857 $result = dolReplaceInFilePreservingModuleBuilderMarkers($phpfileval['fullname'], $arrayreplacement);
1858 } else {
1859 $result = dolReplaceInFile($phpfileval['fullname'], $arrayreplacement); // @phpstan-ignore-line
1860 }
1861 //var_dump($result);
1862 if ($result < 0) {
1863 setEventMessages($langs->trans("ErrorFailToMakeReplacementInto", $phpfileval['fullname']), null, 'errors');
1864 } else {
1865 modulebuilderValidateGeneratedFile($phpfileval['fullname'], $ncObj);
1866 }
1867 }
1868 }
1869
1870 if (!$error && $ncObj !== null) {
1871 // Apply object name substitution to ALL PHP files in the module directory.
1872 // initmodule only substitutes the module name; files it creates (e.g. testmodindex.php,
1873 // lib/testmod.lib.php, admin/setup.php) still contain myobject/mymodule placeholders
1874 // that must be resolved when an object is first added.
1875 $licenceValueAll = getDolGlobalString('MODULEBUILDER_SPECIFIC_AUTHOR')
1876 ? dol_print_date($now, '%Y') . ' ' . getDolGlobalString('MODULEBUILDER_SPECIFIC_AUTHOR')
1877 : getLicenceHeader($user, $langs, $now);
1878 $moduleReplacementAll = array_merge(
1879 $ncObj->getSubstitutionMap(),
1880 [
1881 'htdocs/modulebuilder/template/' => $ncObj->moduleNameLower,
1882 '---Replace with your own copyright and developer email---' => $licenceValueAll,
1883 ]
1884 );
1885 $allModulePhpFiles = dol_dir_list($destdir, 'files', 1, '\.php$');
1886 // The module descriptor must NOT go through the blanket substitution: it keeps persistent
1887 // MYOBJECT/MYMODULE markers (TOPMENU/LEFTMENU) reused when generating subsequent objects, and its
1888 // own placeholders are already resolved by initmodule and the dedicated menu/permission blocks.
1889 $moduledescriptorbasename = 'mod'.$module.'.class.php';
1890 if (is_array($allModulePhpFiles) && !empty($allModulePhpFiles)) {
1891 foreach ($allModulePhpFiles as $phpFileval) {
1892 if (basename($phpFileval['fullname']) === $moduledescriptorbasename) {
1893 continue;
1894 }
1895 $result = dolReplaceInFile($phpFileval['fullname'], $moduleReplacementAll);
1896 if ($result < 0) {
1897 setEventMessages($langs->trans("ErrorFailToMakeReplacementInto", $phpFileval['fullname']), null, 'warnings');
1898 }
1899 }
1900 }
1901 // Delete initmodule placeholder files superseded by initobject-generated files.
1902 $moduleLowerForPlaceholder = dol_strtolower($module);
1903 foreach ([
1904 $destdir . '/stats/myobject_index.php',
1905 $destdir . '/lib/' . $moduleLowerForPlaceholder . '_myobject.lib.php',
1906 ] as $placeholder) {
1907 if (file_exists($placeholder)) {
1908 dol_delete_file($placeholder);
1909 }
1910 }
1911 }
1912
1913 $object = null;
1914 if (!$error) {
1915 // Edit the class file to write properties
1916 $object = rebuildObjectClass($destdir, $module, $objectname, $newmask);
1917
1918 if (is_numeric($object) && $object <= 0) {
1919 $pathoffiletoeditsrc = $destdir.'/class/'.dol_strtolower($objectname).'.class.php';
1920 setEventMessages($langs->trans('ErrorFailToCreateFile', $pathoffiletoeditsrc), null, 'errors');
1921 $warning++;
1922 }
1923 // check if documentation was generate and add table of properties object
1924 $file = $destdir.'/class/'.dol_strtolower($objectname).'.class.php';
1925 $destfile = $destdir.'/doc/Documentation.asciidoc';
1926
1927 if (file_exists($destfile)) {
1928 writePropsInAsciiDoc($file, $objectname, $destfile);
1929 }
1930 }
1931 if (!$error && $object !== null) {
1932 // Edit sql with new properties
1933 $result = rebuildObjectSql($destdir, $module, $objectname, $newmask, '', $object);
1934
1935 if ($result <= 0) {
1936 setEventMessages($langs->trans('ErrorFailToCreateFile', '.sql'), null);
1937 $error++;
1938 }
1939 }
1940
1941 if (!$error) {
1942 setEventMessages($langs->trans('FilesForObjectInitialized', $objectname), null);
1943 $tabobj = $objectname;
1944 } else {
1945 $tabobj = 'newobject';
1946 }
1947
1948 // check if module is enabled
1950 $result = unActivateModule(dol_strtolower($module));
1951 dolibarr_set_const($db, "MAIN_IHM_PARAMS_REV", getDolGlobalInt('MAIN_IHM_PARAMS_REV') + 1, 'chaine', 0, '', $conf->entity);
1952 if ($result) {
1953 setEventMessages($result, null, 'errors');
1954 }
1955 setEventMessages($langs->trans('WarningModuleNeedRefresh', $langs->transnoentities($module)), null, 'warnings');
1956 header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=objects&module='.$module);
1957 exit;
1958 }
1959}
1960
1961// Add a dictionary
1962if ($dirins && $action == 'initdic' && $module && empty($cancel) /* && $user->hasRight("modulebuilder", "run") // already checked */) {
1963 $pathtofile = $listofmodules[dol_strtolower($module)]['moduledescriptorrelpath'];
1964 $destdir = $dirins.'/'.dol_strtolower($module);
1965 $moduledescriptorfile = $dirins.'/'.dol_strtolower($module).'/core/modules/mod'.$module.'.class.php';
1966
1967 if (!GETPOST('dicname')) {
1968 $error++;
1969 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Table")), null, 'errors');
1970 }
1971 if (!GETPOST('label')) {
1972 $error++;
1973 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Label")), null, 'errors');
1974 }
1975 if (!$error) {
1976 $newdicname = $dicname;
1977 if (!preg_match('/^c_/', $newdicname)) {
1978 $newdicname = 'c_'.$dicname;
1979 }
1980 dol_include_once($pathtofile);
1981 $class = 'mod'.$module;
1982
1983 $moduleobj = null;
1984 if (class_exists($class)) {
1985 try {
1986 $moduleobj = new $class($db);
1987 '@phan-var-force DolibarrModules $moduleobj';
1989 } catch (Exception $e) {
1990 $error++;
1991 dol_print_error($db, $e->getMessage());
1992 }
1993 } else {
1994 $error++;
1995 }
1996 if ($moduleobj === null) {
1997 $langs->load("errors");
1998 dol_print_error($db, $langs->trans("ErrorFailedToLoadModuleDescriptorForXXX", $module));
1999 exit;
2000 }
2001 $dictionaries = $moduleobj->dictionaries;
2002 $checkComment = checkExistComment($moduledescriptorfile, 2);
2003 if ($checkComment < 0) {
2004 setEventMessages($langs->trans("WarningCommentNotFound", $langs->trans("Dictionaries"), "mod".$module."class.php"), null, 'warnings');
2005 } else {
2006 createNewDictionnary($module, $moduledescriptorfile, $newdicname, $dictionaries);
2007 if (function_exists('opcache_invalidate')) {
2008 opcache_reset(); // remove the include cache hell !
2009 }
2010 clearstatcache(true);
2011 header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=dictionaries&module='.$module.($forceddirread ? '@'.$dirread : ''));
2012 exit;
2013 }
2014 }
2015}
2016
2017// Delete a SQL table
2018if ($dirins && ($action == 'droptable' || $action == 'droptableextrafields') && !empty($module) && !empty($tabobj) /* && $user->hasRight("modulebuilder", "run") // already checked */) {
2019 $objectname = $tabobj;
2020
2021 $arrayoftables = array();
2022 if ($action == 'droptable') { // Test on permission already done
2023 $arrayoftables[] = MAIN_DB_PREFIX.dol_strtolower($module).'_'.dol_strtolower($tabobj);
2024 }
2025 if ($action == 'droptableextrafields') { // Test on permission already done
2026 $arrayoftables[] = MAIN_DB_PREFIX.dol_strtolower($module).'_'.dol_strtolower($tabobj).'_extrafields';
2027 }
2028
2029 foreach ($arrayoftables as $tabletodrop) {
2030 $nb = -1;
2031 $sql = "SELECT COUNT(*) as nb FROM ".$tabletodrop;
2032 $resql = $db->query($sql);
2033 if ($resql) {
2034 $obj = $db->fetch_object($resql);
2035 if ($obj) {
2036 $nb = (int) $obj->nb;
2037 }
2038 } else {
2039 if ($db->lasterrno() == 'DB_ERROR_NOSUCHTABLE') {
2040 setEventMessages($langs->trans("TableDoesNotExists", $tabletodrop), null, 'warnings');
2041 } else {
2042 dol_print_error($db);
2043 }
2044 }
2045 if ($nb == 0) {
2046 $resql = $db->DDLDropTable($tabletodrop);
2047 //var_dump($resql);
2048 setEventMessages($langs->trans("TableDropped", $tabletodrop), null, 'mesgs');
2049 } elseif ($nb > 0) {
2050 setEventMessages($langs->trans("TableNotEmptyDropCanceled", $tabletodrop), null, 'warnings');
2051 }
2052 }
2053}
2054
2055if ($dirins && $action == 'addproperty' && empty($cancel) && !empty($module) && (!empty($tabobj) || !empty(GETPOST('obj'))) /* && $user->hasRight("modulebuilder", "run") // already checked */) {
2056 $error = 0;
2057
2058 $objectname = (GETPOST('obj') ? GETPOST('obj') : $tabobj);
2059
2060 $dirins = $dirread = $listofmodules[dol_strtolower($module)]['moduledescriptorrootpath'];
2061 $moduletype = $listofmodules[dol_strtolower($module)]['moduletype'];
2062
2063 $srcdir = $dirread.'/'.dol_strtolower($module);
2064 $destdir = $dirins.'/'.dol_strtolower($module);
2065 dol_mkdir($destdir);
2066
2067 $objects = dolGetListOfObjectClasses($destdir);
2068 if (!in_array($objectname, array_values($objects))) {
2069 $error++;
2070 setEventMessages($langs->trans("ErrorObjectNotFound", $langs->transnoentities($objectname)), null, 'errors');
2071 }
2072
2073 $addfieldentry = array();
2074
2075 // We click on add property
2076 if (!GETPOST('regenerateclasssql') && !GETPOST('regeneratemissing')) {
2077 if (!GETPOST('propname', 'aZ09')) {
2078 $error++;
2079 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Name")), null, 'errors');
2080 }
2081 if (!GETPOST('proplabel', 'alpha')) {
2082 $error++;
2083 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Label")), null, 'errors');
2084 }
2085 if (!GETPOST('proptype', 'alpha')) {
2086 $error++;
2087 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Type")), null, 'errors');
2088 }
2089
2090
2091 if (!$error && !GETPOST('regenerateclasssql') && !GETPOST('regeneratemissing')) {
2092 // Preserve case for composite types such as 'integer:Societe:societe/class/societe.class.php:1:(...__SHARED_ENTITIES__...)'
2093 // because the colon-separated parts include PHP class names (case-sensitive) and __XXX__ substitution
2094 // tokens that are uppercase by convention. Only lowercase simple atomic types (#34602).
2095 $proptype = GETPOST('proptype', 'alpha');
2096 if (strpos($proptype, ':') === false && strpos($proptype, '_') === false) {
2097 $proptype = dol_strtolower($proptype);
2098 }
2099 $addfieldentry = array(
2100 'name' => GETPOST('propname', 'aZ09'),
2101 'label' => GETPOST('proplabel', 'alpha'),
2102 'type' => $proptype,
2103 'arrayofkeyval' => GETPOST('proparrayofkeyval', 'nohtml'), // Example json string '{"0":"Draft","1":"Active","-1":"Cancel"}'
2104 'visible' => GETPOST('propvisible', 'alphanohtml'),
2105 'enabled' => GETPOST('propenabled', 'alphanohtml'),
2106 'position' => GETPOSTINT('propposition'),
2107 'notnull' => GETPOSTINT('propnotnull'),
2108 'index' => GETPOSTINT('propindex'),
2109 'foreignkey' => GETPOST('propforeignkey', 'alpha'),
2110 'searchall' => GETPOSTINT('propsearchall'),
2111 'isameasure' => GETPOSTINT('propisameasure'),
2112 'showoncombobox' => GETPOSTINT('propshowoncombobox'),
2113 'comment' => GETPOST('propcomment', 'alpha'),
2114 'help' => GETPOST('prophelp', 'alpha'),
2115 'css' => GETPOST('propcss', 'alpha'), // Can be 'maxwidth500 widthcentpercentminusxx' for example
2116 'cssview' => GETPOST('propcssview', 'alpha'),
2117 'csslist' => GETPOST('propcsslist', 'alpha'),
2118 'default' => GETPOST('propdefault', 'restricthtml'),
2119 'noteditable' => GETPOSTINT('propnoteditable'),
2120 //'alwayseditable' => GETPOSTINT('propalwayseditable'),
2121 'validate' => GETPOSTINT('propvalidate')
2122 );
2123
2124 if (!empty($addfieldentry['arrayofkeyval']) && !is_array($addfieldentry['arrayofkeyval'])) {
2125 $tmpdecode = json_decode($addfieldentry['arrayofkeyval'], true);
2126 if ($tmpdecode) { // If string is already a json
2127 $addfieldentry['arrayofkeyval'] = $tmpdecode;
2128 } else { // If string is a list of lines with "key,value"
2129 $tmparray = dolExplodeIntoArray($addfieldentry['arrayofkeyval'], "\n", ",");
2130 $addfieldentry['arrayofkeyval'] = $tmparray;
2131 }
2132 }
2133 }
2134 }
2135
2136 /*if (GETPOST('regeneratemissing'))
2137 {
2138 setEventMessages($langs->trans("FeatureNotYetAvailable"), null, 'warnings');
2139 $error++;
2140 }*/
2141
2142 $moduletype = $listofmodules[dol_strtolower($module)]['moduletype'];
2143
2144 $object = null;
2145 // Edit the class file to write properties
2146 if (!$error) {
2147 $object = rebuildObjectClass($destdir, $module, $objectname, $newmask, $srcdir, $addfieldentry, $moduletype);
2148
2149 if (is_numeric($object) && $object <= 0) {
2150 $pathoffiletoeditsrc = $destdir.'/class/'.dol_strtolower($objectname).'.class.php';
2151 setEventMessages($langs->trans('ErrorFailToCreateFile', $pathoffiletoeditsrc), null, 'errors');
2152 $error++;
2153 }
2154 }
2155
2156 // Edit sql with new properties
2157 if (!$error && $object !== null) {
2158 $result = rebuildObjectSql($destdir, $module, $objectname, $newmask, $srcdir, $object, $moduletype);
2159
2160 if ($result <= 0) {
2161 setEventMessages($langs->trans('ErrorFailToCreateFile', '.sql'), null, 'errors');
2162 $error++;
2163 }
2164 }
2165
2166 if (!$error) {
2167 clearstatcache(true);
2168
2169 setEventMessages($langs->trans('FilesForObjectUpdated', $objectname), null);
2170
2171 setEventMessages($langs->trans('WarningDatabaseIsNotUpdated'), null);
2172
2173 // Make a redirect to reload all data
2174 header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=objects&module='.$module.($forceddirread ? '@'.$dirread : '').'&tabobj='.$objectname.'&nocache='.dol_now());
2175 exit;
2176 }
2177}
2178
2179if ($dirins && $action == 'confirm_deleteproperty' && $propertykey /* && $user->hasRight("modulebuilder", "run") // already checked */) {
2180 $objectname = $tabobj;
2181
2182 $dirins = $dirread = $listofmodules[dol_strtolower($module)]['moduledescriptorrootpath'];
2183 $moduletype = $listofmodules[dol_strtolower($module)]['moduletype'];
2184
2185 $srcdir = $dirread.'/'.dol_strtolower($module);
2186 $destdir = $dirins.'/'.dol_strtolower($module);
2187 dol_mkdir($destdir);
2188
2189 $object = null;
2190 // Edit the class file to write properties
2191 if (!$error) {
2192 $object = rebuildObjectClass($destdir, $module, $objectname, $newmask, $srcdir, array(), $propertykey);
2193
2194 if (is_numeric($object) && $object <= 0) {
2195 $pathoffiletoeditsrc = $destdir.'/class/'.dol_strtolower($objectname).'.class.php';
2196 setEventMessages($langs->trans('ErrorFailToCreateFile', $pathoffiletoeditsrc), null, 'errors');
2197 $error++;
2198 }
2199 }
2200
2201 // Edit sql with new properties
2202 if (!$error && $object !== null) {
2203 $result = rebuildObjectSql($destdir, $module, $objectname, $newmask, $srcdir, $object);
2204
2205 if ($result <= 0) {
2206 setEventMessages($langs->trans('ErrorFailToCreateFile', '.sql'), null, 'errors');
2207 $error++;
2208 }
2209 }
2210
2211 if (!$error) {
2212 setEventMessages($langs->trans('FilesForObjectUpdated', $objectname), null);
2213
2214 clearstatcache(true);
2215
2216 // Make a redirect to reload all data
2217 header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=objects&module='.$module.($forceddirread ? '@'.$dirread : '').'&tabobj='.$objectname);
2218 exit;
2219 }
2220}
2221
2222if ($dirins && $action == 'confirm_deletemodule' /* && $user->hasRight("modulebuilder", "run") // already checked */) {
2223 if (preg_match('/[^a-z0-9_]/i', $module)) {
2224 $error++;
2225 setEventMessages($langs->trans("SpaceOrSpecialCharAreNotAllowed"), null, 'errors');
2226 }
2227
2228 if (!$error) {
2229 $modulelowercase = dol_strtolower($module);
2230
2231 // Dir for module
2232 $dir = $dirins.'/'.$modulelowercase;
2233
2234 $pathtofile = $listofmodules[dol_strtolower($module)]['moduledescriptorrelpath'];
2235
2236 // Dir for module
2237 $dir = dol_buildpath($modulelowercase, 0);
2238
2239 // Zip file to build
2240 $FILENAMEZIP = '';
2241
2242 // Load module
2243 dol_include_once($pathtofile);
2244 $class = 'mod'.$module;
2245
2246 $moduleobj = null;
2247
2248 if (class_exists($class)) {
2249 try {
2250 $moduleobj = new $class($db);
2251 '@phan-var-force DolibarrModules $moduleobj';
2253 } catch (Exception $e) {
2254 $error++;
2255 dol_print_error($db, $e->getMessage());
2256 }
2257 } else {
2258 $error++;
2259 $langs->load("errors");
2260 setEventMessages($langs->trans("ErrorFailedToLoadModuleDescriptorForXXX", $module), null, 'warnings');
2261 }
2262
2263 if ($moduleobj) {
2264 $moduleobj->remove();
2265 }
2266
2267 $result = dol_delete_dir_recursive($dir);
2268
2269 if ($result > 0) {
2270 setEventMessages($langs->trans("DirWasRemoved", $modulelowercase), null);
2271
2272 clearstatcache(true);
2273 if (function_exists('opcache_invalidate')) {
2274 opcache_reset(); // remove the include cache hell !
2275 }
2276
2277 header("Location: ".$_SERVER["PHP_SELF"].'?module=deletemodule');
2278 exit;
2279 } else {
2280 setEventMessages($langs->trans("PurgeNothingToDelete"), null, 'warnings');
2281 }
2282 }
2283
2284 $action = '';
2285 $module = 'deletemodule';
2286}
2287
2288if ($dirins && $action == 'confirm_deleteobject' && $objectname /* && $user->hasRight("modulebuilder", "run") // already checked */) {
2289 if (preg_match('/[^a-z0-9_]/i', $objectname)) {
2290 $error++;
2291 setEventMessages($langs->trans("SpaceOrSpecialCharAreNotAllowed"), null, 'errors');
2292 }
2293
2294 if (!$error) {
2295 $modulelowercase = dol_strtolower($module);
2296 $objectlowercase = dol_strtolower($objectname);
2297
2298 // Dir for module
2299 $dir = $dirins.'/'.$modulelowercase;
2300
2301 // Delete some files
2302 try {
2303 $ncObjDel = new NamingContract($module, $objectname);
2304 } catch (\InvalidArgumentException $e) {
2305 $error++;
2306 setEventMessages($langs->trans("SpaceOrSpecialCharAreNotAllowed"), null, 'errors');
2307 $ncObjDel = null;
2308 }
2309 $filetodelete = [];
2310 if (!$error && $ncObjDel !== null) {
2311 foreach ([
2312 'myobject_card.php',
2313 'myobject_note.php',
2314 'myobject_contact.php',
2315 'myobject_document.php',
2316 'myobject_agenda.php',
2317 'myobject_list.php',
2318 'admin/myobject_extrafields.php',
2319 'lib/mymodule_myobject.lib.php',
2320 'sql/llx_mymodule_myobject.sql',
2321 'sql/llx_mymodule_myobject_extrafields.sql',
2322 'sql/llx_mymodule_myobject.key.sql',
2323 'sql/llx_mymodule_myobject_extrafields.key.sql',
2324 'scripts/myobject.php',
2325 'class/myobject.class.php',
2326 'class/myobjectstats.class.php',
2327 'core/modules/mymodule/mod_myobject_advanced.php',
2328 'core/modules/mymodule/mod_myobject_standard.php',
2329 'core/modules/mymodule/modules_myobject.php',
2330 'core/modules/mymodule/doc/doc_generic_myobject_odt.modules.php',
2331 'core/modules/mymodule/doc/pdf_standard_myobject.modules.php',
2332 'stats/myobject_index.php',
2333 ] as $templateFile) {
2334 $filetodelete[$templateFile] = $ncObjDel->applyToFilename($templateFile);
2335 }
2336 // Exceptions: target filenames differ from simple token substitution
2337 $filetodelete['ajax/myobject.lib.php'] = 'ajax/' . $ncObjDel->objectNameLower . '.php';
2338 $filetodelete['test/phpunit/MyObjectTest.php'] = 'test/phpunit/' . $ncObjDel->objectNameLower . 'Test.php';
2339 $filetodelete['class/api_myobject.class.php'] = 'class/api_' . $ncObjDel->moduleNameLower . '.class.php';
2340 }
2341
2342 //menu for the object selected
2343 // load class and check if menu,permission,documentation exist for this object
2344 $pathtofile = $listofmodules[dol_strtolower($module)]['moduledescriptorrelpath'];
2345 dol_include_once($pathtofile);
2346 $class = 'mod'.$module;
2347 $moduleobj = null;
2348 if (class_exists($class)) {
2349 try {
2350 $moduleobj = new $class($db);
2351 '@phan-var-force DolibarrModules $moduleobj';
2353 } catch (Exception $e) {
2354 $error++;
2355 dol_print_error($db, $e->getMessage());
2356 }
2357 } else {
2358 $error++;
2359 $langs->load("errors");
2360 dol_print_error($db, $langs->trans("ErrorFailedToLoadModuleDescriptorForXXX", $module));
2361 exit;
2362 }
2363 $moduledescriptorfile = $dirins.'/'.dol_strtolower($module).'/core/modules/mod'.$module.'.class.php';
2364
2365 // delete menus linked to the object
2366 $menus = $moduleobj->menu;
2367 $rewriteMenu = checkExistComment($moduledescriptorfile, 0);
2368
2369 if ($rewriteMenu < 0) {
2370 setEventMessages($langs->trans("WarningCommentNotFound", $langs->trans("Menus"), "mod".$module."class.php"), null, 'warnings');
2371 } else {
2372 reWriteAllMenus($moduledescriptorfile, $menus, $objectname, null, -1);
2373 }
2374
2375 // regenerate permissions and delete them
2376 $permissions = $moduleobj->rights;
2377 $rewritePerms = checkExistComment($moduledescriptorfile, 1);
2378 if ($rewritePerms < 0) {
2379 setEventMessages($langs->trans("WarningCommentNotFound", $langs->trans("Permissions"), "mod".$module."class.php"), null, 'warnings');
2380 } else {
2381 $reportPerms = modulebuilderSyncRights(RightsSyncCommand::forObjectDeletion($module, $moduledescriptorfile, is_array($permissions) ? $permissions : array(), $objectname));
2382 // A rights conflict deliberately does not cancel the object deletion below: the warning
2383 // already told the user the leftover rights need a manual cleanup.
2384 }
2385 if ($rewritePerms && $rewriteMenu) {
2386 // check if documentation has been generated
2387 $file_doc = $dirins.'/'.dol_strtolower($module).'/doc/Documentation.asciidoc';
2388 deletePropsAndPermsFromDoc($file_doc, $objectname);
2389
2390 clearstatcache(true);
2391 if (function_exists('opcache_invalidate')) {
2392 opcache_reset(); // remove the include cache hell !
2393 }
2394 $resultko = 0;
2395 foreach ($filetodelete as $tmpfiletodelete) {
2396 $resulttmp = dol_delete_file($dir.'/'.$tmpfiletodelete, 1, 0, 1);
2397 $resulttmp = dol_delete_file($dir.'/'.$tmpfiletodelete.'.back', 1, 0, 1);
2398 if (!$resulttmp) {
2399 $resultko++;
2400 }
2401 }
2402
2403 if ($resultko == 0) {
2404 setEventMessages($langs->trans("FilesDeleted"), null);
2405 } else {
2406 setEventMessages($langs->trans("ErrorSomeFilesCouldNotBeDeleted"), null, 'warnings');
2407 }
2408 }
2409 }
2410
2411 $action = '';
2412 if (! $error) {
2413 $tabobj = 'newobject';
2414 } else {
2415 $tabobj = 'deleteobject';
2416 }
2417
2418 // check if module is enabled
2420 $result = unActivateModule(dol_strtolower($module));
2421 dolibarr_set_const($db, "MAIN_IHM_PARAMS_REV", getDolGlobalInt('MAIN_IHM_PARAMS_REV') + 1, 'chaine', 0, '', $conf->entity);
2422 if ($result) {
2423 setEventMessages($result, null, 'errors');
2424 }
2425 setEventMessages($langs->trans('WarningModuleNeedRefresh', $langs->transnoentities($module)), null, 'warnings');
2426 header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=objects&tabobj=deleteobject&module='.urlencode($module));
2427 exit;
2428 }
2429}
2430
2431if (($dirins && $action == 'confirm_deletedictionary' && $dicname) || ($dirins && $action == 'confirm_deletedictionary' && GETPOST('dictionnarykey')) /* && $user->hasRight("modulebuilder", "run") // already checked */) {
2432 $pathtofile = $listofmodules[dol_strtolower($module)]['moduledescriptorrelpath'];
2433 $destdir = $dirins.'/'.dol_strtolower($module);
2434 $moduledescriptorfile = $dirins.'/'.dol_strtolower($module).'/core/modules/mod'.$module.'.class.php';
2435
2436 if (preg_match('/[^a-z0-9_]/i', $dicname)) {
2437 $error++;
2438 setEventMessages($langs->trans("SpaceOrSpecialCharAreNotAllowed"), null, 'errors');
2439 }
2440
2441 if (!empty($dicname)) {
2442 $newdicname = $dicname;
2443 if (!preg_match('/^c_/', $newdicname)) {
2444 $newdicname = 'c_'.dol_strtolower($dicname);
2445 }
2446 } else {
2447 $newdicname = null;
2448 }
2449
2450 dol_include_once($pathtofile);
2451 $class = 'mod'.$module;
2452
2453 $moduleobj = null;
2454 if (class_exists($class)) {
2455 try {
2456 $moduleobj = new $class($db);
2457 '@phan-var-force DolibarrModules $moduleobj';
2459 } catch (Exception $e) {
2460 $error++;
2461 dol_print_error($db, $e->getMessage());
2462 }
2463 } else {
2464 $error++;
2465 }
2466 if ($moduleobj === null) {
2467 $langs->load("errors");
2468 dol_print_error($db, $langs->trans("ErrorFailedToLoadModuleDescriptorForXXX", $module));
2469 exit;
2470 }
2471
2472 $dicts = $moduleobj->dictionaries;
2473 $checkComment = checkExistComment($moduledescriptorfile, 2);
2474 if ($checkComment < 0) {
2475 $error++;
2476 setEventMessages($langs->trans("WarningCommentNotFound", $langs->trans("Dictionaries"), "mod".$module."class.php"), null, 'warnings');
2477 }
2478
2479 if (!empty(GETPOST('dictionnarykey'))) {
2480 $newdicname = $dicts['tabname'][GETPOSTINT('dictionnarykey') - 1];
2481 }
2482
2483 // Lookup the table dicname
2484 $checkTable = false;
2485 if ($newdicname !== null) {
2486 $checkTable = $db->DDLDescTable(MAIN_DB_PREFIX.dol_strtolower($newdicname));
2487 }
2488
2489 if (is_bool($checkTable) || $db->num_rows($checkTable) <= 0) { // @phpstan-ignore-line
2490 $error++;
2491 }
2492
2493 // search the key by name
2494 $keyToDelete = null;
2495 foreach ($dicts['tabname'] as $key => $table) {
2496 //var_dump($table." /////// ".$newdicname);exit;
2497 if (dol_strtolower($table) === $newdicname) {
2498 $keyToDelete = $key;
2499 break;
2500 }
2501 }
2502 // delete all dicname's key values from the dictionary
2503 if ($keyToDelete !== null) {
2504 $keysToDelete = ['tabname', 'tablib', 'tabsql', 'tabsqlsort', 'tabfield', 'tabfieldvalue', 'tabfieldinsert', 'tabrowid', 'tabcond', 'tabhelp'];
2505 foreach ($keysToDelete as $key) {
2506 unset($dicts[$key][$keyToDelete]);
2507 }
2508 } else {
2509 $error++;
2510 setEventMessages($langs->trans("ErrorDictionaryNotFound", dol_ucfirst($dicname)), null, 'errors');
2511 }
2512 if (!$error && $newdicname !== null) {
2513 // delete table
2514 $_results = $db->DDLDropTable(MAIN_DB_PREFIX.dol_strtolower($newdicname));
2515 if ($_results < 0) {
2516 dol_print_error($db);
2517 $langs->load("errors");
2518 setEventMessages($langs->trans("ErrorTableNotFound", $newdicname), null, 'errors');
2519 }
2520 // rebuild file after update dictionaries
2521 $result = updateDictionaryInFile($module, $moduledescriptorfile, $dicts);
2522 if ($result > 0) {
2523 setEventMessages($langs->trans("DictionaryDeleted", dol_ucfirst(dol_substr($newdicname, 2))), null);
2524 }
2525 if (function_exists('opcache_invalidate')) {
2526 opcache_reset(); // remove the include cache hell !
2527 }
2528 clearstatcache(true);
2529 header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=dictionaries&module='.$module.($forceddirread ? '@'.$dirread : ''));
2530 exit;
2531 }
2532}
2533if ($dirins && $action == 'updatedictionary' && GETPOST('dictionnarykey') /* && $user->hasRight("modulebuilder", "run") // already checked */) {
2534 $keydict = GETPOSTINT('dictionnarykey') - 1 ;
2535
2536 $pathtofile = $listofmodules[dol_strtolower($module)]['moduledescriptorrelpath'];
2537 $destdir = $dirins.'/'.dol_strtolower($module);
2538 $moduledescriptorfile = $dirins.'/'.dol_strtolower($module).'/core/modules/mod'.$module.'.class.php';
2539 dol_include_once($pathtofile);
2540 $class = 'mod'.$module;
2541
2542 $moduleobj = null;
2543 if (class_exists($class)) {
2544 try {
2545 $moduleobj = new $class($db);
2546 '@phan-var-force DolibarrModules $moduleobj';
2548 } catch (Exception $e) {
2549 $error++;
2550 dol_print_error($db, $e->getMessage());
2551 }
2552 } else {
2553 $error++;
2554 }
2555 if ($moduleobj === null) {
2556 $langs->load("errors");
2557 dol_print_error($db, $langs->trans("ErrorFailedToLoadModuleDescriptorForXXX", $module));
2558 exit;
2559 }
2560
2561 $dicts = $moduleobj->dictionaries;
2562 if (!empty(GETPOST('tablib')) && GETPOST('tablib') !== $dicts['tablib'][$keydict]) {
2563 $dicts['tablib'][$keydict] = dol_ucfirst(dol_strtolower(GETPOST('tablib')));
2564 $checkComment = checkExistComment($moduledescriptorfile, 2);
2565 if ($checkComment < 0) {
2566 setEventMessages($langs->trans("WarningCommentNotFound", $langs->trans("Dictionaries"), "mod".$module."class.php"), null, 'warnings');
2567 } else {
2568 $updateDict = updateDictionaryInFile($module, $moduledescriptorfile, $dicts);
2569 if ($updateDict > 0) {
2570 setEventMessages($langs->trans("DictionaryNameUpdated", dol_ucfirst(GETPOST('tablib'))), null);
2571 }
2572 if (function_exists('opcache_invalidate')) {
2573 opcache_reset(); // remove the include cache hell !
2574 }
2575 clearstatcache(true);
2576 header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=dictionaries&module='.$module.($forceddirread ? '@'.$dirread : ''));
2577 exit;
2578 }
2579 }
2580 //var_dump(GETPOST('tablib'));exit;
2581}
2582if ($dirins && $action == 'generatedoc' /* && $user->hasRight("modulebuilder", "run") // already checked */) {
2583 $modulelowercase = dol_strtolower($module);
2584
2585 // Dir for module
2586 $dirofmodule = dol_buildpath($modulelowercase, 0).'/doc';
2587
2588 $FILENAMEDOC = dol_strtolower($module).'.html';
2589
2590 $util = new Utils($db);
2591 $result = $util->generateDoc($module);
2592
2593 if ($result > 0) {
2594 setEventMessages($langs->trans("DocFileGeneratedInto", $dirofmodule), null);
2595 } else {
2596 setEventMessages($util->error, $util->errors, 'errors');
2597 }
2598}
2599
2600if ($dirins && $action == 'generatepackage' /* && $user->hasRight("modulebuilder", "run") // already checked */) {
2601 $modulelowercase = dol_strtolower($module);
2602
2603 $pathtofile = $listofmodules[dol_strtolower($module)]['moduledescriptorrelpath'];
2604
2605 // Dir for module
2606 $dir = dol_buildpath($modulelowercase, 0);
2607
2608 // Zip file to build
2609 $FILENAMEZIP = '';
2610
2611 // Load module
2612 dol_include_once($pathtofile);
2613 $class = 'mod'.$module;
2614
2615 $moduleobj = null;
2616 if (class_exists($class)) {
2617 try {
2618 $moduleobj = new $class($db);
2619 '@phan-var-force DolibarrModules $moduleobj';
2621 } catch (Exception $e) {
2622 $error++;
2623 dol_print_error($db, $e->getMessage());
2624 }
2625 } else {
2626 $error++;
2627 }
2628 if ($moduleobj === null) {
2629 $langs->load("errors");
2630 dol_print_error($db, $langs->trans("ErrorFailedToLoadModuleDescriptorForXXX", $module));
2631 exit;
2632 }
2633
2634 $arrayversion = explode('.', $moduleobj->version, 3);
2635 if (count($arrayversion)) {
2636 $FILENAMEZIP = "module_".$modulelowercase.'-'.$arrayversion[0].(empty($arrayversion[1]) ? '.0' : '.'.$arrayversion[1]).(empty($arrayversion[2]) ? '' : '.'.$arrayversion[2]).'.zip';
2637
2638 $dirofmodule = dol_buildpath($modulelowercase, 0).'/bin';
2639 $outputfilezip = $dirofmodule.'/'.$FILENAMEZIP;
2640
2641 if (!dol_is_dir($dirofmodule)) {
2642 dol_mkdir($dirofmodule);
2643 }
2644 // Note: We exclude /bin/ to not include the already generated zip
2645 $result = dol_compress_dir($dir, $outputfilezip, 'zip', '/\/bin\/|\.git|\.old|\.back|\.ssh/', $modulelowercase);
2646
2647 if ($result > 0) {
2648 setEventMessages($langs->trans("ZipFileGeneratedInto", $outputfilezip), null);
2649 } else {
2650 $error++;
2651 $langs->load("errors");
2652 setEventMessages($langs->trans("ErrorFailToGenerateFile", $outputfilezip), null, 'errors');
2653 }
2654 } else {
2655 $error++;
2656 $langs->load("errors");
2657 setEventMessages($langs->trans("ErrorCheckVersionIsDefined"), null, 'errors');
2658 }
2659}
2660
2661// Add permission
2662if ($dirins && $action == 'addright' && !empty($module) && empty($cancel) /* && $user->hasRight("modulebuilder", "run") // already checked */) {
2663 $error = 0;
2664
2665 // load class and check if right exist
2666 $pathtofile = $listofmodules[dol_strtolower($module)]['moduledescriptorrelpath'];
2667 dol_include_once($pathtofile);
2668 $class = 'mod'.$module;
2669 $moduleobj = null;
2670 if (class_exists($class)) {
2671 try {
2672 $moduleobj = new $class($db);
2673 '@phan-var-force DolibarrModules $moduleobj';
2675 } catch (Exception $e) {
2676 $error++;
2677 dol_print_error($db, $e->getMessage());
2678 }
2679 }
2680
2681 // verify information entered
2682 if (!GETPOST('label', 'alpha')) {
2683 $error++;
2684 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Label")), null, 'errors');
2685 }
2686 if (!GETPOST('permissionObj', 'alpha')) {
2687 $error++;
2688 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Rights")), null, 'errors');
2689 }
2690
2691 $label = GETPOST('label', 'alpha');
2692 $objectForPerms = dol_strtolower(GETPOST('permissionObj', 'alpha'));
2693 $crud = GETPOST('crud', 'alpha');
2694
2695 //check existing object permission
2696 $counter = 0;
2697 $permsForObject = array();
2698 if (is_object($moduleobj)) {
2699 $permissions = $moduleobj->rights;
2700 } else {
2701 $permissions = array();
2702 }
2703 $allObject = array();
2704
2705 $countPerms = count($permissions);
2706
2707 for ($i = 0; $i < $countPerms; $i++) {
2708 if ($permissions[$i][4] == $objectForPerms) {
2709 $counter++;
2710 if (count($permsForObject) < 3) {
2711 $permsForObject[] = $permissions[$i];
2712 }
2713 }
2714 $allObject[] = $permissions[$i][4];
2715 }
2716
2717 // check if label of object already exists
2718 $countPermsObj = count($permsForObject);
2719 for ($j = 0; $j < $countPermsObj; $j++) {
2720 if (in_array($crud, $permsForObject[$j])) {
2721 $error++;
2722 setEventMessages($langs->trans("ErrorExistingPermission", $langs->transnoentities($crud), $langs->transnoentities($objectForPerms)), null, 'errors');
2723 }
2724 }
2725
2726 if (!$error) {
2728 $result = unActivateModule(dol_strtolower($module));
2729 dolibarr_set_const($db, "MAIN_IHM_PARAMS_REV", getDolGlobalInt('MAIN_IHM_PARAMS_REV') + 1, 'chaine', 0, '', $conf->entity);
2730 if ($result) {
2731 setEventMessages($result, null, 'errors');
2732 }
2733 setEventMessages($langs->trans('WarningModuleNeedRefresh', $langs->transnoentities($module)), null, 'warnings');
2734 }
2735
2736 $moduledescriptorfile = $dirins.'/'.dol_strtolower($module).'/core/modules/mod'.$module.'.class.php';
2737 // Rewriting all permissions section in the descriptor file
2738 $rewrite = checkExistComment($moduledescriptorfile, 1);
2739 if ($rewrite < 0) {
2740 setEventMessages($langs->trans("WarningCommentNotFound", $langs->trans("Permissions"), "mod".$module."class.php"), null, 'warnings');
2741 } else {
2742 $reportPerms = modulebuilderSyncRights(RightsSyncCommand::forRightAddition($module, $moduledescriptorfile, $permissions, $objectForPerms, $label, $crud));
2743 if (!$reportPerms->hasConflicts()) {
2744 setEventMessages($langs->trans('PermissionAddedSuccesfuly'), null);
2745
2746 clearstatcache(true);
2747 if (function_exists('opcache_invalidate')) {
2748 opcache_reset(); // remove the include cache hell !
2749 }
2750 header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=permissions&module='.$module);
2751 exit;
2752 }
2753 }
2754 }
2755}
2756
2757
2758// Update permission
2759if ($dirins && GETPOST('action') == 'update_right' && GETPOST('modifyright') && empty($cancel) /* && $user->hasRight("modulebuilder", "run") // already checked */) {
2760 $error = 0;
2761 // load class and check if right exist
2762 $pathtofile = $listofmodules[dol_strtolower($module)]['moduledescriptorrelpath'];
2763 dol_include_once($pathtofile);
2764 $class = 'mod'.$module;
2765 $moduleobj = null;
2766 if (class_exists($class)) {
2767 try {
2768 $moduleobj = new $class($db);
2769 '@phan-var-force DolibarrModules $moduleobj';
2771 } catch (Exception $e) {
2772 $error++;
2773 dol_print_error($db, $e->getMessage());
2774 }
2775 }
2776 // verify information entered
2777 if (!GETPOST('label', 'alpha')) {
2778 $error++;
2779 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Label")), null, 'errors');
2780 }
2781 if (!GETPOST('permissionObj', 'alpha')) {
2782 $error++;
2783 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Rights")), null, 'errors');
2784 }
2785
2786 $label = GETPOST('label', 'alpha');
2787 $objectForPerms = dol_strtolower(GETPOST('permissionObj', 'alpha'));
2788 $crud = GETPOST('crud', 'alpha');
2789
2790
2791 if ($label == "Read objects of $module" && $crud != "read") {
2792 $crud = "read";
2793 // $label = "Read objects of $module";
2794 }
2795 if ($label == "Create/Update objects of $module" && $crud != "write") {
2796 $crud = "write";
2797 // $label = "Create/Update objects of $module";
2798 }
2799 if ($label == "Delete objects of $module" && $crud != "delete") {
2800 $crud = "delete";
2801 // $label = "Delete objects of $module";
2802 }
2803
2804 if (is_object($moduleobj)) {
2805 $permissions = $moduleobj->rights;
2806 } else {
2807 $permissions = [];
2808 }
2809 $key = GETPOSTINT('counter') - 1;
2810 //get permission want to delete from permissions array
2811 if (array_key_exists($key, $permissions)) {
2812 $x1 = $permissions[$key][1];
2813 $x2 = $permissions[$key][4];
2814 $x3 = $permissions[$key][5];
2815 } else {
2816 $x1 = null;
2817 $x2 = null;
2818 $x3 = null;
2819 }
2820 //check existing object permission
2821 $counter = 0;
2822 $permsForObject = array();
2823 // $permissions = $moduleobj->rights; // Already fetched above
2824 $firstRight = 0;
2825 $existRight = 0;
2826 $allObject = array();
2827
2828 $countPerms = count($permissions);
2829 for ($i = 0; $i < $countPerms; $i++) {
2830 if ($permissions[$i][4] == $objectForPerms) {
2831 $counter++;
2832 if (count($permsForObject) < 3) {
2833 $permsForObject[] = $permissions[$i];
2834 }
2835 }
2836 $allObject[] = $permissions[$i][4];
2837 }
2838
2839 if ($label != $x1 && $crud != $x3) {
2840 $countPermsObj = count($permsForObject);
2841 for ($j = 0; $j < $countPermsObj; $j++) {
2842 if (in_array($label, $permsForObject[$j])) {
2843 $error++;
2844 setEventMessages($langs->trans("ErrorExistingPermission", $langs->transnoentities($label), $langs->transnoentities($objectForPerms)), null, 'errors');
2845 }
2846 }
2847 }
2848
2849 if (!$error) {
2851 $result = unActivateModule(dol_strtolower($module));
2852 dolibarr_set_const($db, "MAIN_IHM_PARAMS_REV", getDolGlobalInt('MAIN_IHM_PARAMS_REV') + 1, 'chaine', 0, '', $conf->entity);
2853 if ($result) {
2854 setEventMessages($result, null, 'errors');
2855 }
2856 setEventMessages($langs->trans('WarningModuleNeedRefresh', $langs->transnoentities($module)), null, 'warnings');
2857 }
2858
2859 $moduledescriptorfile = $dirins.'/'.dol_strtolower($module).'/core/modules/mod'.$module.'.class.php';
2860 // rewriting all permissions after update permission needed
2861 $rewrite = checkExistComment($moduledescriptorfile, 1);
2862 if ($rewrite < 0) {
2863 setEventMessages($langs->trans("WarningCommentNotFound", $langs->trans("Permissions"), "mod".$module."class.php"), null, 'warnings');
2864 } else {
2865 $reportPerms = modulebuilderSyncRights(RightsSyncCommand::forRightUpdate($module, $moduledescriptorfile, $permissions, $key, $objectForPerms, $label, $crud));
2866 if (!$reportPerms->hasConflicts()) {
2867 setEventMessages($langs->trans('PermissionUpdatedSuccesfuly'), null);
2868 clearstatcache(true);
2869 if (function_exists('opcache_invalidate')) {
2870 opcache_reset(); // remove the include cache hell !
2871 }
2872 header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=permissions&module='.$module);
2873 exit;
2874 }
2875 }
2876 }
2877}
2878// Delete permission
2879if ($dirins && $action == 'confirm_deleteright' && !empty($module) && GETPOSTINT('permskey') /* && $user->hasRight("modulebuilder", "run") // already checked */) {
2880 $error = 0;
2881 // load class and check if right exist
2882 $pathtofile = $listofmodules[dol_strtolower($module)]['moduledescriptorrelpath'];
2883 dol_include_once($pathtofile);
2884 $class = 'mod'.$module;
2885 $moduleobj = null;
2886 if (class_exists($class)) {
2887 try {
2888 $moduleobj = new $class($db);
2889 '@phan-var-force DolibarrModules $moduleobj';
2891 } catch (Exception $e) {
2892 $error++;
2893 dol_print_error($db, $e->getMessage());
2894 }
2895 }
2896
2897 $permissions = $moduleobj->rights;
2898 $key = GETPOSTINT('permskey') - 1;
2899
2900 if (!$error) {
2901 // check if module is enabled
2903 $result = unActivateModule(dol_strtolower($module));
2904 dolibarr_set_const($db, "MAIN_IHM_PARAMS_REV", getDolGlobalInt('MAIN_IHM_PARAMS_REV') + 1, 'chaine', 0, '', $conf->entity);
2905 if ($result) {
2906 setEventMessages($result, null, 'errors');
2907 }
2908 setEventMessages($langs->trans('WarningModuleNeedRefresh', $langs->transnoentities($module)), null, 'warnings');
2909 header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=permissions&module='.$module);
2910 exit;
2911 }
2912
2913 // rewriting all permissions
2914 $moduledescriptorfile = $dirins.'/'.dol_strtolower($module).'/core/modules/mod'.$module.'.class.php';
2915 $rewrite = checkExistComment($moduledescriptorfile, 1);
2916 if ($rewrite < 0) {
2917 setEventMessages($langs->trans("WarningCommentNotFound", $langs->trans("Permissions"), "mod".$module."class.php"), null, 'warnings');
2918 } else {
2919 $reportPerms = modulebuilderSyncRights(RightsSyncCommand::forRightDeletion($module, $moduledescriptorfile, $permissions, $key));
2920 if (!$reportPerms->hasConflicts()) {
2921 setEventMessages($langs->trans('PermissionDeletedSuccesfuly'), null);
2922
2923 clearstatcache(true);
2924 if (function_exists('opcache_invalidate')) {
2925 opcache_reset(); // remove the include cache hell !
2926 }
2927
2928 header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=permissions&module='.$module);
2929 exit;
2930 }
2931 }
2932 }
2933}
2934// Save file
2935if ($action == 'savefile' && empty($cancel) /* && $user->hasRight("modulebuilder", "run") // already checked */) {
2936 $relofcustom = basename($dirins);
2937
2938 if ($relofcustom) {
2939 // Check that relative path ($file) start with name 'custom'
2940 if (!preg_match('/^'.$relofcustom.'/', $file)) {
2941 $file = $relofcustom.'/'.$file;
2942 }
2943
2944 $pathoffile = dol_buildpath($file, 0);
2945 $pathoffilebackup = dol_buildpath($file.'.back', 0);
2946
2947 // Save old version
2948 if (dol_is_file($pathoffile)) {
2949 dol_copy($pathoffile, $pathoffilebackup, '0', 1);
2950 }
2951
2952 $check = 'restricthtml';
2953 $srclang = dol_mimetype($pathoffile, '', 3);
2954 if ($srclang == 'md') {
2955 $check = 'restricthtml';
2956 }
2957 if ($srclang == 'lang') {
2958 $check = 'restricthtml';
2959 }
2960 if ($srclang == 'php') {
2961 $check = 'none';
2962 }
2963
2964 $content = GETPOST('editfilecontent', $check);
2965
2966 // Save file on disk
2967 if ($content) {
2968 dol_delete_file($pathoffile);
2969 $result = file_put_contents($pathoffile, $content);
2970 if ($result) {
2971 dolChmod($pathoffile, $newmask);
2972
2973 setEventMessages($langs->trans("FileSaved"), null);
2974 } else {
2975 setEventMessages($langs->trans("ErrorFailedToSaveFile"), null, 'errors');
2976 }
2977 } else {
2978 setEventMessages($langs->trans("ContentCantBeEmpty"), null, 'errors');
2979 //$action='editfile';
2980 $error++;
2981 }
2982 }
2983}
2984
2985// Enable module
2986if ($action == 'set' && $user->admin /* && $user->hasRight("modulebuilder", "run") // already checked */) {
2987 $param = '';
2988 if ($module) {
2989 $param .= '&module='.urlencode($module);
2990 }
2991
2992 $param .= '&tab='.urlencode($tab);
2993 $param .= '&tabobj='.urlencode($tabobj);
2994
2995 $value = GETPOST('value', 'alpha');
2996 $resarray = activateModule($value, 1, 0);
2997 if (!empty($resarray['errors'])) {
2998 setEventMessages('', $resarray['errors'], 'errors');
2999 } else {
3000 //var_dump($resarray);exit;
3001 if ($resarray['nbperms'] > 0) {
3002 $tmpsql = "SELECT COUNT(rowid) as nb FROM ".MAIN_DB_PREFIX."user WHERE admin <> 1";
3003 $resqltmp = $db->query($tmpsql);
3004 if ($resqltmp) {
3005 $obj = $db->fetch_object($resqltmp);
3006 //var_dump($obj->nb);exit;
3007 if ($obj && $obj->nb > 1) {
3008 $msg = $langs->trans('ModuleEnabledAdminMustCheckRights');
3009 setEventMessages($msg, null, 'warnings');
3010 }
3011 } else {
3012 dol_print_error($db);
3013 }
3014 }
3015 }
3016 header("Location: ".$_SERVER["PHP_SELF"]."?".$param);
3017 exit;
3018}
3019
3020// Disable module
3021if ($action == 'reset' && $user->admin /* && $user->hasRight("modulebuilder", "run") // already checked */) {
3022 $param = '';
3023 if ($module) {
3024 $param .= '&module='.urlencode($module);
3025 }
3026 $param .= '&tab='.urlencode($tab);
3027 $param .= '&tabobj='.urlencode($tabobj);
3028
3029 $value = GETPOST('value', 'alpha');
3030 $result = unActivateModule(dol_strtolower($value));
3031 if ($result) {
3032 setEventMessages($result, null, 'errors');
3033 }
3034 header("Location: ".$_SERVER["PHP_SELF"]."?".$param);
3035 exit;
3036}
3037
3038// Delete menu
3039if ($dirins && $action == 'confirm_deletemenu' && GETPOSTINT('menukey') /* && $user->hasRight("modulebuilder", "run") // already checked */) {
3040 // check if module is enabled
3042 $result = unActivateModule(dol_strtolower($module));
3043 dolibarr_set_const($db, "MAIN_IHM_PARAMS_REV", getDolGlobalInt('MAIN_IHM_PARAMS_REV') + 1, 'chaine', 0, '', $conf->entity);
3044 if ($result) {
3045 setEventMessages($result, null, 'errors');
3046 }
3047 setEventMessages($langs->trans('WarningModuleNeedRefresh', $langs->transnoentities($module)), null, 'warnings');
3048 header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=menus&module='.$module);
3049 exit;
3050 }
3051 // load class and check if menu exist
3052 $pathtofile = $listofmodules[dol_strtolower($module)]['moduledescriptorrelpath'];
3053 dol_include_once($pathtofile);
3054 $class = 'mod'.$module;
3055 $moduleobj = null;
3056 if (class_exists($class)) {
3057 try {
3058 $moduleobj = new $class($db);
3059 '@phan-var-force DolibarrModules $moduleobj';
3061 } catch (Exception $e) {
3062 $error++;
3063 dol_print_error($db, $e->getMessage());
3064 }
3065 }
3066 // get all objects and convert value to lower case for compare
3067 $dir = $listofmodules[dol_strtolower($module)]['moduledescriptorrootpath'];
3068 $destdir = $dir.'/'.dol_strtolower($module);
3069 $objects = dolGetListOfObjectClasses($destdir);
3070 $result = array_map('dol_strtolower', $objects);
3071
3072 $menus = $moduleobj->menu;
3073 $key = GETPOSTINT('menukey');
3074 $moduledescriptorfile = $dirins.'/'.dol_strtolower($module).'/core/modules/mod'.$module.'.class.php';
3075
3076 $checkcomment = checkExistComment($moduledescriptorfile, 0);
3077 if ($checkcomment < 0) {
3078 setEventMessages($langs->trans("WarningCommentNotFound", $langs->trans("Menus"), "mod".$module."class.php"), null, 'warnings');
3079 } else {
3080 if ($menus[$key]['fk_menu'] === 'fk_mainmenu='.dol_strtolower($module)) {
3081 if (in_array(dol_strtolower($menus[$key]['leftmenu']), $result)) {
3082 reWriteAllMenus($moduledescriptorfile, $menus, $menus[$key]['leftmenu'], $key, -1);
3083 } else {
3084 reWriteAllMenus($moduledescriptorfile, $menus, null, $key, 0);
3085 }
3086 } else {
3087 reWriteAllMenus($moduledescriptorfile, $menus, null, $key, 0);
3088 }
3089
3090 clearstatcache(true);
3091 if (function_exists('opcache_invalidate')) {
3092 opcache_reset(); // remove the include cache hell !
3093 }
3094
3095 setEventMessages($langs->trans('MenuDeletedSuccessfuly'), null);
3096 header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=menus&module='.$module);
3097 exit;
3098 }
3099}
3100
3101// Add menu in module without initial object
3102if ($dirins && $action == 'addmenu' && empty($cancel) /* && $user->hasRight("modulebuilder", "run") // already checked */) {
3103 // check if module is enabled
3105 $result = unActivateModule(dol_strtolower($module));
3106 dolibarr_set_const($db, "MAIN_IHM_PARAMS_REV", getDolGlobalInt('MAIN_IHM_PARAMS_REV') + 1, 'chaine', 0, '', $conf->entity);
3107 if ($result) {
3108 setEventMessages($result, null, 'errors');
3109 }
3110 setEventMessages($langs->trans('WarningModuleNeedRefresh', $langs->transnoentities($module)), null, 'warnings');
3111 header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=menus&module='.$module);
3112 exit;
3113 }
3114 $error = 0;
3115
3116 // load class and check if right exist
3117 $pathtofile = $listofmodules[dol_strtolower($module)]['moduledescriptorrelpath'];
3118 dol_include_once($pathtofile);
3119 $class = 'mod'.$module;
3120 $moduleobj = null;
3121 if (class_exists($class)) {
3122 try {
3123 $moduleobj = new $class($db);
3124 '@phan-var-force DolibarrModules $moduleobj';
3126 } catch (Exception $e) {
3127 $error++;
3128 dol_print_error($db, $e->getMessage());
3129 }
3130 }
3131 // get all menus
3132 $menus = $moduleobj->menu;
3133
3134 //verify fields required
3135 if (!GETPOST('type', 'alpha')) {
3136 $error++;
3137 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Type")), null, 'errors');
3138 }
3139 if (!GETPOST('titre', 'alpha')) {
3140 $error++;
3141 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Title")), null, 'errors');
3142 }
3143 if (!GETPOST('user', 'alpha')) {
3144 $error++;
3145 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("DetailUser")), null, 'errors');
3146 }
3147 if (!GETPOST('url', 'alpha')) {
3148 $error++;
3149 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Url")), null, 'errors');
3150 }
3151 if (!empty(GETPOST('target'))) {
3152 $targets = array('_blank','_self','_parent','_top','');
3153 if (!in_array(GETPOST('target'), $targets)) {
3154 $error++;
3155 setEventMessages($langs->trans("ErrorFieldValue", $langs->transnoentities("target")), null, 'errors');
3156 }
3157 }
3158
3159
3160 // check if title or url already exist in menus
3161
3162 foreach ($menus as $menu) {
3163 if (!empty(GETPOST('url')) && GETPOST('url') == $menu['url']) {
3164 $error++;
3165 setEventMessages($langs->trans("ErrorFieldExist", $langs->transnoentities("url")), null, 'errors');
3166 break;
3167 }
3168 if (dol_strtolower(GETPOST('titre')) == dol_strtolower($menu['titre'])) {
3169 $error++;
3170 setEventMessages($langs->trans("ErrorFieldExist", $langs->transnoentities("titre")), null, 'errors');
3171 break;
3172 }
3173 }
3174
3175 if (GETPOST('type', 'alpha') == 'left' && !empty(GETPOST('lefmenu', 'alpha'))) {
3176 if (!str_contains(GETPOST('leftmenu'), dol_strtolower($module))) {
3177 $error++;
3178 setEventMessages($langs->trans("WarningFieldsMustContains", $langs->transnoentities("LeftmenuId")), null, 'errors');
3179 }
3180 }
3181 $dirins = $listofmodules[dol_strtolower($module)]['moduledescriptorrootpath'];
3182 $destdir = $dirins.'/'.dol_strtolower($module);
3183 $objects = dolGetListOfObjectClasses($destdir);
3184
3185 if (GETPOST('type', 'alpha') == 'left') {
3186 if (empty(GETPOST('leftmenu')) && count($objects) > 0) {
3187 $error++;
3188 setEventMessages($langs->trans("ErrorCoherenceMenu", $langs->transnoentities("LeftmenuId"), $langs->transnoentities("type")), null, 'errors');
3189 }
3190 }
3191 if (GETPOST('type', 'alpha') == 'top') {
3192 $error++;
3193 setEventMessages($langs->trans("ErrorTypeMenu", $langs->transnoentities("type")), null, 'errors');
3194 }
3195
3196 $moduledescriptorfile = $dirins.'/'.dol_strtolower($module).'/core/modules/mod'.$module.'.class.php';
3197 if (!$error) {
3198 //stock forms in array
3199 $menuToAdd = array(
3200 'fk_menu' => GETPOST('fk_menu', 'alpha'),
3201 'type' => GETPOST('type', 'alpha'),
3202 'titre' => dol_ucfirst(GETPOST('titre', 'alpha')),
3203 'prefix' => '',
3204 'mainmenu' => GETPOST('mainmenu', 'alpha'),
3205 'leftmenu' => GETPOST('leftmenu', 'alpha'),
3206 'url' => GETPOST('url', 'alpha'),
3208 'position' => '',
3209 'enabled' => GETPOST('enabled', 'alpha'),
3210 'perms' => '$user->hasRight("'.dol_strtolower($module).'", "'.GETPOST('objects', 'alpha').'", "'.GETPOST('perms', 'alpha').'")',
3211 'target' => GETPOST('target', 'alpha'),
3212 'user' => GETPOSTINT('user'),
3213 );
3214
3215 if (GETPOST('type') == 'left') {
3216 unset($menuToAdd['prefix']);
3217 if (empty(GETPOST('fk_menu'))) {
3218 $menuToAdd['fk_menu'] = 'fk_mainmenu='.GETPOST('mainmenu', 'alpha');
3219 } else {
3220 $menuToAdd['fk_menu'] = 'fk_mainmenu='.GETPOST('mainmenu', 'alpha').',fk_leftmenu='.GETPOST('fk_menu');
3221 }
3222 }
3223 if (GETPOST('enabled') == '1') {
3224 $menuToAdd['enabled'] = 'isModEnabled("'.dol_strtolower($module).'")';
3225 } else {
3226 $menuToAdd['enabled'] = "0";
3227 }
3228 if (empty(GETPOST('objects'))) {
3229 $menuToAdd['perms'] = '1';
3230 }
3231
3232 $checkcomment = checkExistComment($moduledescriptorfile, 0);
3233 if ($checkcomment < 0) {
3234 setEventMessages($langs->trans("WarningCommentNotFound", $langs->trans("Menus"), "mod".$module."class.php"), null, 'warnings');
3235 } else {
3236 // Write all menus
3237 $result = reWriteAllMenus($moduledescriptorfile, $menus, $menuToAdd, null, 1);
3238
3239 clearstatcache(true);
3240 if (function_exists('opcache_invalidate')) {
3241 opcache_reset();
3242 }
3243 /*if ($result < 0) {
3244 setEventMessages($langs->trans('ErrorMenuExistValue'), null, 'errors');
3245 header("Location: ".$_SERVER["PHP_SELF"].'?action=editmenu&token='.newToken().'&menukey='.urlencode($key+1).'&tab='.urlencode($tab).'&module='.urlencode($module).'&tabobj='.($key+1));
3246 exit;
3247 }*/
3248
3249 header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=menus&module='.$module);
3250 setEventMessages($langs->trans('MenuAddedSuccesfuly'), null);
3251 exit;
3252 }
3253 }
3254}
3255
3256// Modify a menu entry
3257if ($dirins && $action == "update_menu" && GETPOSTINT('menukey') && GETPOST('tabobj') /* && $user->hasRight("modulebuilder", "run") // already checked */) {
3258 $objectname = GETPOST('tabobj');
3259 $dirins = $listofmodules[dol_strtolower($module)]['moduledescriptorrootpath'];
3260 $destdir = $dirins.'/'.dol_strtolower($module);
3261 $objects = dolGetListOfObjectClasses($destdir);
3262
3263 if (empty($cancel)) {
3265 $result = unActivateModule(dol_strtolower($module));
3266 dolibarr_set_const($db, "MAIN_IHM_PARAMS_REV", getDolGlobalInt('MAIN_IHM_PARAMS_REV') + 1, 'chaine', 0, '', $conf->entity);
3267 if ($result) {
3268 setEventMessages($result, null, 'errors');
3269 }
3270 setEventMessages($langs->trans('WarningModuleNeedRefresh', $langs->transnoentities($module)), null, 'warnings');
3271 header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=menus&module='.$module);
3272 exit;
3273 }
3274 $error = 0;
3275 // for loading class and the menu wants to modify
3276 $pathtofile = $listofmodules[dol_strtolower($module)]['moduledescriptorrelpath'];
3277 dol_include_once($pathtofile);
3278 $class = 'mod'.$module;
3279 $moduleobj = null;
3280 if (class_exists($class)) {
3281 try {
3282 $moduleobj = new $class($db);
3283 '@phan-var-force DolibarrModules $moduleobj';
3285 } catch (Exception $e) {
3286 $error++;
3287 dol_print_error($db, $e->getMessage());
3288 }
3289 }
3290 $menus = $moduleobj->menu;
3291 $key = GETPOSTINT('menukey') - 1;
3292
3293 $moduledescriptorfile = $dirins.'/'.dol_strtolower($module).'/core/modules/mod'.$module.'.class.php';
3294 //stock forms in array
3295 $menuModify = array(
3296 'fk_menu' => GETPOST('fk_menu', 'alpha'),
3297 'type' => GETPOST('type', 'alpha'),
3298 'titre' => dol_ucfirst(GETPOST('titre', 'alpha')),
3299 'prefix' => '',
3300 'mainmenu' => GETPOST('mainmenu', 'alpha'),
3301 'leftmenu' => $menus[$key]['leftmenu'],
3302 'url' => GETPOST('url', 'alpha'),
3304 'position' => '',
3305 'enabled' => GETPOST('enabled', 'alpha'),
3306 'perms' => GETPOST('perms', 'alpha'),
3307 'target' => GETPOST('target', 'alpha'),
3308 'user' => GETPOSTINT('user'),
3309 );
3310 if (!empty(GETPOST('fk_menu')) && GETPOST('fk_menu') != $menus[$key]['fk_menu']) {
3311 $menuModify['fk_menu'] = 'fk_mainmenu='.GETPOST('mainmenu').',fk_leftmenu='.GETPOST('fk_menu');
3312 } elseif (GETPOST('fk_menu') == $menus[$key]['fk_menu']) {
3313 $menuModify['fk_menu'] = $menus[$key]['fk_menu'];
3314 } else {
3315 $menuModify['fk_menu'] = 'fk_mainmenu='.GETPOST('mainmenu');
3316 }
3317 if ($menuModify['enabled'] === '') {
3318 $menuModify['enabled'] = '1';
3319 }
3320 if ($menuModify['perms'] === '') {
3321 $menuModify['perms'] = '1';
3322 }
3323
3324 if (GETPOST('type', 'alpha') == 'top') {
3325 $error++;
3326 setEventMessages($langs->trans("ErrorTypeMenu", $langs->transnoentities("type")), null, 'errors');
3327 }
3328
3329 if (!$error) {
3330 //update menu
3331 $checkComment = checkExistComment($moduledescriptorfile, 0);
3332
3333 if ($checkComment < 0) {
3334 setEventMessages($langs->trans("WarningCommentNotFound", $langs->trans("Menus"), "mod".$module."class.php"), null, 'warnings');
3335 } else {
3336 // Write all menus
3337 $result = reWriteAllMenus($moduledescriptorfile, $menus, $menuModify, $key, 2);
3338
3339 clearstatcache(true);
3340 if (function_exists('opcache_invalidate')) {
3341 opcache_reset();
3342 }
3343
3344 if ($result < 0) {
3345 setEventMessages($langs->trans('ErrorMenuExistValue'), null, 'errors');
3346 //var_dump($_SESSION);exit;
3347 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));
3348 exit;
3349 }
3350
3351 setEventMessages($langs->trans('MenuUpdatedSuccessfuly'), null);
3352 header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=menus&module='.$module);
3353 exit;
3354 }
3355 }
3356 } else {
3357 $_POST['type'] = ''; // TODO Use a var here and later
3358 $_POST['titre'] = '';
3359 $_POST['fk_menu'] = '';
3360 $_POST['leftmenu'] = '';
3361 $_POST['url'] = '';
3362 }
3363}
3364
3365// update properties description of module
3366if ($dirins && $action == "update_props_module" && !empty(GETPOST('keydescription', 'alpha')) && empty($cancel) /* && $user->hasRight("modulebuilder", "run") // already checked */) {
3368 $result = unActivateModule(dol_strtolower($module));
3369 dolibarr_set_const($db, "MAIN_IHM_PARAMS_REV", getDolGlobalInt('MAIN_IHM_PARAMS_REV') + 1, 'chaine', 0, '', $conf->entity);
3370 if ($result) {
3371 setEventMessages($result, null, 'errors');
3372 }
3373 setEventMessages($langs->trans('WarningModuleNeedRefresh', $langs->transnoentities($module)), null, 'warnings');
3374 header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=menus&module='.$module);
3375 exit;
3376 }
3377 $pathtofile = $listofmodules[dol_strtolower($module)]['moduledescriptorrelpath'];
3378 $moduledescriptorfile = $dirins.'/'.dol_strtolower($module).'/core/modules/mod'.$module.'.class.php';
3379 $modulelogfile = $dirins.'/'.dol_strtolower($module).'/ChangeLog.md';
3380
3381 dol_include_once($pathtofile);
3382
3383 $class = 'mod'.$module;
3384 $moduleobj = null;
3385 if (class_exists($class)) {
3386 try {
3387 $moduleobj = new $class($db);
3388 '@phan-var-force DolibarrModules $moduleobj';
3390 } catch (Exception $e) {
3391 $error++;
3392 dol_print_error($db, $e->getMessage());
3393 }
3394 }
3395
3396 $keydescription = GETPOST('keydescription', 'alpha');
3397 switch ($keydescription) {
3398 case 'desc':
3399 $propertyToUpdate = 'description';
3400 break;
3401 case 'version':
3402 case 'family':
3403 case 'picto':
3404 case 'editor_name':
3405 case 'editor_url':
3406 $propertyToUpdate = $keydescription;
3407 break;
3408 default:
3409 $error = GETPOST('keydescription');
3410 break;
3411 }
3412
3413 if (isset($propertyToUpdate) && !empty(GETPOST('propsmodule'))) {
3414 $newValue = GETPOST('propsmodule');
3415 $patternToFindLine = '^\s*\$this->'.$propertyToUpdate.'\s*='; // Must be a regex string
3416 $newLine = "\t\t\$this->$propertyToUpdate = '$newValue';\n"; // Must a real string
3417
3418 $fileLines = file($moduledescriptorfile); // Get each line of file into an array
3419 $error = 0;
3420 $changedone = 0;
3421 foreach ($fileLines as &$line) {
3422 if (preg_match('/'.$patternToFindLine.'/', $line)) {
3423 $result = dolReplaceInFile($moduledescriptorfile, array($line => $newLine));
3424 if ($result > 0) {
3425 $changedone++;
3426 } elseif ($result <= -1) {
3427 $langs->load("errors");
3428 setEventMessages($langs->trans('ErrorFailToEditFile', $moduledescriptorfile), null, 'warnings');
3429 break;
3430 }
3431 break;
3432 }
3433 }
3434
3435 // To complete also the ChangeLogif we update the version
3436 if ($changedone && $propertyToUpdate === 'version') {
3437 dolReplaceInFile($modulelogfile, array("## ".$moduleobj->$propertyToUpdate => $newValue));
3438 }
3439
3440 clearstatcache(true);
3441 if (function_exists('opcache_invalidate')) {
3442 opcache_reset();
3443 }
3444 if ($changedone) {
3445 setEventMessages($langs->trans('PropertyModuleUpdated', $propertyToUpdate), null);
3446 } else {
3447 setEventMessages($langs->trans('NothingProcessed'), null, 'warnings');
3448 }
3449
3450 header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=description&module='.$module);
3451 exit;
3452 }
3453}
3454
3455
3456/*
3457 * View
3458 */
3459
3460$form = new Form($db);
3461$formadmin = new FormAdmin($db);
3462
3463// Set dir where external modules are installed
3464if (!dol_is_dir($dirins)) {
3465 dol_mkdir($dirins);
3466}
3467$dirins_ok = (dol_is_dir($dirins));
3468
3469$help_url = '';
3470$morejs = array(
3471 '/includes/ace/src/ace.js',
3472 '/includes/ace/src/ext-statusbar.js',
3473 '/includes/ace/src/ext-language_tools.js',
3474 //'/includes/ace/src/ext-chromevox.js'
3475);
3476$morecss = array();
3477
3478llxHeader('', $langs->trans("ModuleBuilder"), $help_url, '', 0, 0, $morejs, $morecss, '', 'classforhorizontalscrolloftabs');
3479
3480
3481$text = $langs->trans("ModuleBuilder");
3482
3483$morehtmlright = '<a href="'.DOL_URL_ROOT.'/admin/tools/ui/index.php" target="_blank" rel="noopener">'.img_picto('', 'book', 'class="pictofixedwidth"').$langs->trans("UxComponentsDoc").'</a>';
3484
3485print load_fiche_titre($text, $morehtmlright, 'title_setup');
3486
3487print '<div class="info hideonsmartphone">';
3488print $langs->trans("ModuleBuilderDesc", 'https://wiki.dolibarr.org/index.php/Module_development').'</span>';
3489print '</div>';
3490
3491
3492$message = '';
3493if (!$dirins) {
3494 $message = info_admin($langs->trans("ConfFileMustContainCustom", DOL_DOCUMENT_ROOT.'/custom', DOL_DOCUMENT_ROOT));
3495 $allowfromweb = -1;
3496} else {
3497 if ($dirins_ok) {
3498 if (!dol_is_writable($dirins)) {
3499 $langs->load("errors");
3500 $message = info_admin($langs->trans("ErrorFailedToWriteInDir", $dirins));
3501 $allowfromweb = 0;
3502 }
3503 } else {
3504 $message = info_admin($langs->trans("NotExistsDirect", $dirins).$langs->trans("InfDirAlt").$langs->trans("InfDirExample"));
3505 $allowfromweb = 0;
3506 }
3507}
3508if ($message) {
3509 print $message;
3510}
3511
3512//print $langs->trans("ModuleBuilderDesc3", count($listofmodules), $FILEFLAG).'<br>';
3513$infomodulesfound = '<div style="padding: 12px 9px 12px">'.$form->textwithpicto('', $langs->trans("ModuleBuilderDesc3", count($listofmodules)).'<br><br>'.$langs->trans("ModuleBuilderDesc4", $FILEFLAG).'<br>'.$textforlistofdirs).'</div>';
3514
3515
3516
3517$dolibarrdataroot = preg_replace('/([\\/]+)$/i', '', DOL_DATA_ROOT);
3518$allowonlineinstall = true;
3519if (dol_is_file($dolibarrdataroot.'/installmodules.lock')) {
3520 $allowonlineinstall = false;
3521}
3522if (empty($allowonlineinstall)) {
3523 if (getDolGlobalString('MAIN_MESSAGE_INSTALL_MODULES_DISABLED_CONTACT_US')) {
3524 // Show clean message
3525 $message = info_admin($langs->trans('InstallModuleFromWebHasBeenDisabledContactUs'));
3526 } else {
3527 // Show technical message
3528 $message = info_admin($langs->trans("InstallModuleFromWebHasBeenDisabledByFile", $dolibarrdataroot.'/installmodules.lock'), 0, 0, '1', 'warning');
3529 }
3530
3531 print $message;
3532
3533 llxFooter();
3534 exit(0);
3535}
3536
3537
3538// Load module descriptor
3539$error = 0;
3541
3542
3543if (!empty($module) && $module != 'initmodule' && $module != 'deletemodule') {
3544 $modulelowercase = dol_strtolower($module);
3545 $loadclasserrormessage = '';
3546
3547 $class = null;
3548 // Load module
3549 try {
3550 $fullpathdirtodescriptor = $listofmodules[dol_strtolower($module)]['moduledescriptorrelpath'];
3551
3552 //throw(new Exception());
3553 dol_include_once($fullpathdirtodescriptor);
3554
3555 $class = 'mod'.$module;
3556 } catch (Throwable $e) { // This is called in PHP 7 only (includes Error and Exception)
3557 $loadclasserrormessage = $e->getMessage()."<br>\n";
3558 $loadclasserrormessage .= 'File: '.$e->getFile()."<br>\n";
3559 $loadclasserrormessage .= 'Line: '.$e->getLine()."<br>\n";
3560 }
3561
3562 $moduleobj = null;
3563 if (class_exists($class)) {
3564 try {
3565 $moduleobj = new $class($db);
3566 '@phan-var-force DolibarrModules $moduleobj';
3568 } catch (Exception $e) {
3569 $error++;
3570 print $e->getMessage();
3571 }
3572 } else {
3573 if (empty($forceddirread)) {
3574 $error++;
3575 }
3576 $langs->load("errors");
3577 print '<!-- ErrorFailedToLoadModuleDescriptorForXXX -->';
3578 print img_warning('').' '.$langs->trans("ErrorFailedToLoadModuleDescriptorForXXX", $module).'<br>';
3579 print $loadclasserrormessage;
3580 print '<br>';
3581 }
3582}
3583
3584
3585// Tabs for all modules
3586$head = array();
3587$h = 0;
3588
3589$head[$h][0] = $_SERVER["PHP_SELF"].'?module=initmodule';
3590$head[$h][1] = '<span class="valignmiddle text-plus-circle">'.$langs->trans("NewModule").'</span><span class="fa fa-plus-circle valignmiddle paddingleft"></span>';
3591$head[$h][2] = 'initmodule';
3592$h++;
3593
3594$linktoenabledisable = '';
3595
3596if (/* is_array($listofmodules) && */ count($listofmodules) > 0) {
3597 // Define $linktoenabledisable
3598 $modulelowercase = dol_strtolower($module);
3599
3600 $param = '';
3601 if ($module) {
3602 $param .= '&module='.urlencode($module);
3603 }
3604
3605 $param .= '&tab='.urlencode($tab);
3606 $param .= '&tabobj='.urlencode($tabobj);
3607
3608 $urltomodulesetup = '<a href="'.DOL_URL_ROOT.'/admin/modules.php?search_keyword='.urlencode($module).'">'.$langs->trans('Home').'-'.$langs->trans("Setup").'-'.$langs->trans("Modules").'</a>';
3609
3610 // Define $linktoenabledisable to show after module title
3611 if (isModEnabled($modulelowercase)) { // If module is already activated
3612 $linktoenabledisable .= '<a class="reposition asetresetmodule valignmiddle" href="'.$_SERVER["PHP_SELF"].'?id='.$moduleobj->numero.'&action=reset&token='.newToken().'&value=mod'.$module.$param.'">';
3613 $linktoenabledisable .= img_picto($langs->trans("Warning").' : '.$langs->trans("ModuleIsLive"), 'switch_on', '', 0, 0, 0, '', 'warning valignmiddle', 1);
3614 $linktoenabledisable .= '</a>';
3615
3616 //$linktoenabledisable .= $form->textwithpicto('', $langs->trans("Warning").' : '.$langs->trans("ModuleIsLive"), -1, 'warning');
3617
3618 $objMod = $moduleobj;
3619 $backtourlparam = '';
3620 $backtourlparam .= ($backtourlparam ? '&' : '?').'module='.$module; // No urlencode here, done later
3621 $backtourlparam .= ($backtourlparam ? '&' : '?').'tab='.$tab; // No urlencode here, done later
3622 $backtourl = $_SERVER["PHP_SELF"].$backtourlparam;
3623
3624 $regs = array();
3625 if (is_array($objMod->config_page_url)) {
3626 $i = 0;
3627 foreach ($objMod->config_page_url as $page) {
3628 $urlpage = $page;
3629 if ($i++) {
3630 $linktoenabledisable .= ' <a class="valignmiddle" href="'.$urlpage.'" title="'.$langs->trans($page).'">'.img_picto(dol_ucfirst($page), "setup").'</a>';
3631 // print '<a href="'.$page.'">'.dol_ucfirst($page).'</a>&nbsp;';
3632 } else {
3633 if (preg_match('/^([^@]+)@([^@]+)$/i', $urlpage, $regs)) {
3634 $urltouse = dol_buildpath('/'.$regs[2].'/admin/'.$regs[1], 1);
3635 $linktoenabledisable .= ' <a class="valignmiddle" href="'.$urltouse.(preg_match('/\?/', $urltouse) ? '&' : '?').'save_lastsearch_values=1&backtopage='.urlencode($backtourl).'" title="'.$langs->trans("Setup").'">'.img_picto($langs->trans("Setup"), "setup", 'style="padding-right: 8px"', 0, 0, 0, '', '').'</a>';
3636 } else {
3637 // Case standard admin page (not a page provided by the
3638 // module but a page provided by dolibarr)
3639 $urltouse = DOL_URL_ROOT.'/admin/'.$urlpage;
3640 $linktoenabledisable .= ' <a class="valignmiddle" href="'.$urltouse.(preg_match('/\?/', $urltouse) ? '&' : '?').'save_lastsearch_values=1&backtopage='.urlencode($backtourl).'" title="'.$langs->trans("Setup").'">'.img_picto($langs->trans("Setup"), "setup", 'style="padding-right: 8px"', 0, 0, 0, '', '').'</a>';
3641 }
3642 }
3643 }
3644 } elseif (preg_match('/^([^@]+)@([^@]+)$/i', $objMod->config_page_url, $regs)) {
3645 $linktoenabledisable .= ' &nbsp; <a class="valignmiddle" href="'.dol_buildpath('/'.$regs[2].'/admin/'.$regs[1], 1).'?save_lastsearch_values=1&backtopage='.urlencode($backtourl).'" title="'.$langs->trans("Setup").'">'.img_picto($langs->trans("Setup"), "setup", 'style="padding-right: 8px"', 0, 0, 0, '', '').'</a>';
3646 }
3647 } else {
3648 if (is_object($moduleobj)) {
3649 $linktoenabledisable .= '<a class="reposition asetresetmodule valignmiddle" href="'.$_SERVER["PHP_SELF"].'?id='.$moduleobj->numero.'&action=set&token='.newToken().'&value=mod'.$module.$param.'">';
3650 $linktoenabledisable .= img_picto($langs->trans("ModuleIsNotActive", $urltomodulesetup), 'switch_off', 'style="padding-right: 8px"', 0, 0, 0, '', 'classfortooltip valignmiddle', 1);
3651 $linktoenabledisable .= "</a>\n";
3652 }
3653 }
3654
3655 // Loop to show tab of each module
3656 foreach ($listofmodules as $tmpmodule => $tmpmodulearray) {
3657 $head[$h][0] = $_SERVER["PHP_SELF"].'?module='.$tmpmodulearray['modulenamewithcase'].($forceddirread ? '@'.$dirread : '');
3658 $head[$h][1] = $tmpmodulearray['modulenamewithcase'];
3659 $head[$h][2] = $tmpmodulearray['modulenamewithcase'];
3660
3661 if ($tmpmodulearray['modulenamewithcase'] == $module) {
3662 $head[$h][4] = '<span class="inline-block valignmiddle">'.$linktoenabledisable.'</span>';
3663 }
3664
3665 $h++;
3666 }
3667}
3668
3669$head[$h][0] = $_SERVER["PHP_SELF"].'?module=deletemodule';
3670$head[$h][1] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("DangerZone");
3671$head[$h][2] = 'deletemodule';
3672$h++;
3673
3674
3675print dol_get_fiche_head($head, $module, '', -1, '', 0, $infomodulesfound, '', 8); // Modules
3676
3677if ($module == 'initmodule') {
3678 // New module
3679 print '<!-- section init module -->'."\n";
3680 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
3681 print '<input type="hidden" name="token" value="'.newToken().'">';
3682 print '<input type="hidden" name="action" value="initmodule">';
3683 print '<input type="hidden" name="module" value="initmodule">';
3684
3685 //print '<span class="opacitymedium">'.$langs->trans("ModuleBuilderDesc2", 'conf/conf.php', $newdircustom).'</span><br>';
3686 print '<br>';
3687
3688 print '<div class="tagtable table-border">';
3689
3690 print '<div class="tagtr"><div class="tagtd paddingright">';
3691 print '<span class="opacitymedium">'.$langs->trans("IdModule").'</span>';
3692 print '</div><div class="tagtd">';
3693 print '<input type="number" min="100000" name="idmodule" class="width100" value="500000">';
3694 print '<span class="opacitymedium small">';
3695 print ' &nbsp; &nbsp; ';
3696 print dolButtonToOpenUrlInDialogPopup('popup_modules_id', $langs->transnoentitiesnoconv("SeeIDsInUse"), $langs->transnoentitiesnoconv("SeeIDsInUse"), '/admin/system/modules.php?mainmenu=home&leftmenu=admintools_info&hidetitle=1', '', '');
3697 print ' - ';
3698 print '<a href="https://wiki.dolibarr.org/index.php/List_of_modules_id" target="_blank" rel="noopener noreferrer external">'.$langs->trans("SeeReservedIDsRangeHere").'</a>';
3699 print '</span>';
3700 print '</div></div>';
3701
3702 print '<div class="tagtr"><div class="tagtd paddingright">';
3703 print '<span class="opacitymedium fieldrequired">'.$langs->trans("ModuleName").'</span>';
3704 print '</div><div class="tagtd">';
3705 print '<input type="text" name="modulename" value="'.dol_escape_htmltag($modulename).'" autofocus>';
3706 print ' '.$form->textwithpicto('', $langs->trans("EnterNameOfModuleDesc"));
3707 print '</div></div>';
3708
3709 print '<div class="tagtr"><div class="tagtd paddingright">';
3710 print '<span class="opacitymedium">'.$langs->trans("Description").'</span>';
3711 print '</div><div class="tagtd">';
3712 print '<input type="text" name="description" value="" class="minwidth500"><br>';
3713 print '</div></div>';
3714
3715 print '<div class="tagtr"><div class="tagtd paddingright">';
3716 print '<span class="opacitymedium">'.$langs->trans("Version").'</span>';
3717 print '</div><div class="tagtd">';
3718 print '<input type="text" name="version" class="width75" value="'.(GETPOSTISSET('version') ? GETPOST('version') : getDolGlobalString('MODULEBUILDER_SPECIFIC_VERSION', '1.0')).'" placeholder="'.dol_escape_htmltag($langs->trans("Version")).'">';
3719 print '</div></div>';
3720
3721 print '<div class="tagtr"><div class="tagtd paddingright">';
3722 print '<span class="opacitymedium">'.$langs->trans("Family").'</span>';
3723 print '</div><div class="tagtd">';
3724 print '<select name="family" id="family" class="minwidth400">';
3725 $arrayoffamilies = array(
3726 'hr' => "ModuleFamilyHr",
3727 'crm' => "ModuleFamilyCrm",
3728 'srm' => "ModuleFamilySrm",
3729 'financial' => 'ModuleFamilyFinancial',
3730 'products' => 'ModuleFamilyProducts',
3731 'projects' => 'ModuleFamilyProjects',
3732 'ecm' => 'ModuleFamilyECM',
3733 'technic' => 'ModuleFamilyTechnic',
3734 'portal' => 'ModuleFamilyPortal',
3735 'interface' => 'ModuleFamilyInterface',
3736 'base' => 'ModuleFamilyBase',
3737 'other' => 'ModuleFamilyOther'
3738 );
3739 foreach ($arrayoffamilies as $key => $value) {
3740 print '<option value="hr"'.($key == getDolGlobalString('MODULEBUILDER_SPECIFIC_FAMILY', 'other') ? ' selected="selected"' : '').' data-html="'.dol_escape_htmltag($langs->trans($value).' <span class="opacitymedium">- '.$key.'</span>').'">'.$langs->trans($value).'</option>';
3741 }
3742 print '</select>';
3743 print ajax_combobox("family");
3744 print '</div></div>';
3745
3746 print '<div class="tagtr"><div class="tagtd paddingright">';
3747 print '<span class="opacitymedium">'.$langs->trans("Picto").'</span>';
3748 print '</div><div class="tagtd">';
3749 print '<input type="text" name="idpicto" value="'.(GETPOSTISSET('idpicto') ? GETPOST('idpicto') : getDolGlobalString('MODULEBUILDER_DEFAULTPICTO', 'fa-file')).'" placeholder="'.dol_escape_htmltag($langs->trans("Picto")).'">';
3750 print $form->textwithpicto('', $langs->trans("Example").': fa-file, fa-globe, ... any font awesome code.<br>Advanced syntax is fa-fakey[_faprefix[_facolor[_fasize]]]');
3751
3752 print ' &nbsp; &nbsp; ';
3753
3754 print '<span class="opacitymedium small">';
3755 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', '', '');
3756 print '</span>';
3757
3758 print '</div></div>';
3759
3760 print '<div class="tagtr"><div class="tagtd paddingright">';
3761 print '<span class="opacitymedium">'.$langs->trans("EditorName").'</span>';
3762 print '</div><div class="tagtd">';
3763 print '<input type="text" name="editorname" value="'.(GETPOSTISSET('editorname') ? GETPOST('editorname') : getDolGlobalString('MODULEBUILDER_SPECIFIC_EDITOR_NAME', $mysoc->name)).'" placeholder="'.dol_escape_htmltag($langs->trans("EditorName")).'" spellcheck="false"><br>';
3764 print '</div></div>';
3765
3766 print '<div class="tagtr"><div class="tagtd paddingright">';
3767 print '<span class="opacitymedium">'.$langs->trans("EditorUrl").'</span>';
3768 print '</div><div class="tagtd">';
3769 print '<input type="text" name="editorurl" value="'.(GETPOSTISSET('editorurl') ? GETPOST('editorurl') : getDolGlobalString('MODULEBUILDER_SPECIFIC_EDITOR_URL', $mysoc->url)).'" placeholder="'.dol_escape_htmltag($langs->trans("EditorUrl")).'" spellcheck="false"><br>';
3770 print '</div></div>';
3771
3772 print '</div>'; // End div tagtable
3773
3774 print '<br><center>';
3775 print '<input type="submit" class="button" name="create" value="'.dol_escape_htmltag($langs->trans("Create")).'"'.($dirins ? '' : ' disabled="disabled"').'>';
3776 print '</center>';
3777 print '</form>';
3778} elseif ($module == 'deletemodule') {
3779 print '<!-- Form to init a module -->'."\n";
3780 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST" name="delete">';
3781 print '<input type="hidden" name="token" value="'.newToken().'">';
3782 print '<input type="hidden" name="action" value="confirm_deletemodule">';
3783 print '<input type="hidden" name="module" value="deletemodule">';
3784
3785 print $langs->trans("EnterNameOfModuleToDeleteDesc").'<br><br>';
3786
3787 print '<input type="text" name="module" placeholder="'.dol_escape_htmltag($langs->trans("ModuleKey")).'" value="" autofocus>';
3788 print '<input type="submit" class="button smallpaddingimp" value="'.$langs->trans("Delete").'"'.($dirins ? '' : ' disabled="disabled"').'>';
3789 print '</form>';
3790} elseif (!empty($module) && $modulelowercase !== null) {
3791 // Tabs for module
3792 if (!$error) {
3793 $dirread = $listofmodules[dol_strtolower($module)]['moduledescriptorrootpath'];
3794 $destdir = $dirread.'/'.dol_strtolower($module);
3795 $objects = dolGetListOfObjectClasses($destdir);
3796 $diroflang = dol_buildpath($modulelowercase, 0)."/langs";
3797 $countLangs = countItemsInDirectory($diroflang, 2);
3798 $countDictionaries = (!empty($moduleobj->dictionaries) ? count($moduleobj->dictionaries['tabname']) : 0);
3799 $countRights = count($moduleobj->rights);
3800 $countMenus = count($moduleobj->menu);
3801 $countTriggers = countItemsInDirectory(dol_buildpath($modulelowercase, 0)."/core/triggers");
3802 $countWidgets = countItemsInDirectory(dol_buildpath($modulelowercase, 0)."/core/boxes");
3803 $countEmailingSelectors = countItemsInDirectory(dol_buildpath($modulelowercase, 0)."/core/modules/mailings");
3804 $countCss = countItemsInDirectory(dol_buildpath($modulelowercase, 0)."/css");
3805 $countJs = countItemsInDirectory(dol_buildpath($modulelowercase, 0)."/js");
3806 $countCLI = countItemsInDirectory(dol_buildpath($modulelowercase, 0)."/scripts");
3807 $hasDoc = countItemsInDirectory(dol_buildpath($modulelowercase, 0)."/doc");
3808 //var_dump($moduleobj->dictionaries);exit;
3809 $head2 = array();
3810 $h = 0;
3811
3812 $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=description&module='.$module.($forceddirread ? '@'.$dirread : '');
3813 $head2[$h][1] = $langs->trans("Description");
3814 $head2[$h][2] = 'description';
3815 $h++;
3816
3817 $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=objects&module='.$module.($forceddirread ? '@'.$dirread : '');
3818 $head2[$h][1] = ((!is_array($objects) || count($objects) <= 0) ? $langs->trans("Objects") : $langs->trans("Objects").'<span class="marginleftonlyshort badge">'.count($objects)."</span>");
3819 $head2[$h][2] = 'objects';
3820 $h++;
3821
3822 $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=languages&module='.$module.($forceddirread ? '@'.$dirread : '');
3823 $head2[$h][1] = ($countLangs <= 0 ? $langs->trans("Languages") : $langs->trans("Languages").'<span class="marginleftonlyshort badge">'.$countLangs."</span>");
3824 $head2[$h][2] = 'languages';
3825 $h++;
3826
3827 $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=permissions&module='.$module.($forceddirread ? '@'.$dirread : '');
3828 $head2[$h][1] = ($countRights <= 0 ? $langs->trans("Permissions") : $langs->trans("Permissions").'<span class="marginleftonlyshort badge">'.$countRights."</span>");
3829 $head2[$h][2] = 'permissions';
3830 $h++;
3831
3832 $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=dictionaries&module='.$module.($forceddirread ? '@'.$dirread : '');
3833 $head2[$h][1] = ($countDictionaries == 0 ? $langs->trans("Dictionaries") : $langs->trans('Dictionaries').'<span class="marginleftonlyshort badge">'.$countDictionaries."</span>");
3834 $head2[$h][2] = 'dictionaries';
3835 $h++;
3836
3837 $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=tabs&module='.$module.($forceddirread ? '@'.$dirread : '');
3838 $head2[$h][1] = $langs->trans("Tabs");
3839 $head2[$h][2] = 'tabs';
3840 $h++;
3841
3842 $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=menus&module='.$module.($forceddirread ? '@'.$dirread : '');
3843 $head2[$h][1] = ($countMenus <= 0 ? $langs->trans("Menus") : $langs->trans("Menus").'<span class="marginleftonlyshort badge">'.$countMenus."</span>");
3844 $head2[$h][2] = 'menus';
3845 $h++;
3846
3847 $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=hooks&module='.$module.($forceddirread ? '@'.$dirread : '');
3848 $head2[$h][1] = $langs->trans("Hooks");
3849 $head2[$h][2] = 'hooks';
3850 $h++;
3851
3852 $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=triggers&module='.$module.($forceddirread ? '@'.$dirread : '');
3853 $head2[$h][1] = ($countTriggers <= 0 ? $langs->trans("Triggers") : $langs->trans("Triggers").'<span class="marginleftonlyshort badge">'.$countTriggers."</span>");
3854 $head2[$h][2] = 'triggers';
3855 $h++;
3856
3857 $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=widgets&module='.$module.($forceddirread ? '@'.$dirread : '');
3858 $head2[$h][1] = ($countWidgets <= 0 ? $langs->trans("Widgets") : $langs->trans("Widgets").'<span class="marginleftonlyshort badge">'.$countWidgets."</span>");
3859 $head2[$h][2] = 'widgets';
3860 $h++;
3861
3862 $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=emailings&module='.$module.($forceddirread ? '@'.$dirread : '');
3863 $head2[$h][1] = ($countEmailingSelectors <= 0 ? $langs->trans("EmailingSelectors") : $langs->trans("EmailingSelectors").'<span class="marginleftonlyshort badge">'.$countEmailingSelectors."</span>");
3864 $head2[$h][2] = 'emailings';
3865 $h++;
3866
3867 $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=exportimport&module='.$module.($forceddirread ? '@'.$dirread : '');
3868 $head2[$h][1] = $langs->trans("ImportExportProfiles");
3869 $head2[$h][2] = 'exportimport';
3870 $h++;
3871
3872 $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=css&module='.$module.($forceddirread ? '@'.$dirread : '');
3873 $head2[$h][1] = ($countCss <= 0 ? $langs->trans("CSS") : $langs->trans("CSS")." (".$countCss.")");
3874 $head2[$h][2] = 'css';
3875 $h++;
3876
3877 $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=js&module='.$module.($forceddirread ? '@'.$dirread : '');
3878 $head2[$h][1] = ($countJs <= 0 ? $langs->trans("JS") : $langs->trans("JS").'<span class="marginleftonlyshort badge">'.$countJs."</span>");
3879 $head2[$h][2] = 'js';
3880 $h++;
3881
3882 $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=cli&module='.$module.($forceddirread ? '@'.$dirread : '');
3883 $head2[$h][1] = ($countCLI <= 0 ? $langs->trans("CLI") : $langs->trans("CLI").'<span class="marginleftonlyshort badge">'.$countCLI."</span>");
3884 $head2[$h][2] = 'cli';
3885 $h++;
3886
3887 $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=cron&module='.$module.($forceddirread ? '@'.$dirread : '');
3888 $head2[$h][1] = $langs->trans("CronList");
3889 $head2[$h][2] = 'cron';
3890 $h++;
3891
3892 $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=specifications&module='.$module.($forceddirread ? '@'.$dirread : '');
3893 $head2[$h][1] = ($hasDoc <= 0 ? $langs->trans("Documentation") : $langs->trans("Documentation").'<span class="marginleftonlyshort badge">'.$hasDoc."</span>");
3894 $head2[$h][2] = 'specifications';
3895 $h++;
3896
3897 $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=buildpackage&module='.$module.($forceddirread ? '@'.$dirread : '');
3898 $head2[$h][1] = $langs->trans("BuildPackage");
3899 $head2[$h][2] = 'buildpackage';
3900 $h++;
3901
3902 $MAXTABFOROBJECT = 12;
3903
3904 print '<!-- Section for a given module -->';
3905
3906 // Note module is inside $dirread
3907
3908 if ($tab == 'description') {
3909 print '<!-- tab=description -->'."\n";
3910 $pathtofile = $listofmodules[dol_strtolower($module)]['moduledescriptorrelpath'];
3911 $pathtofilereadme = $modulelowercase.'/README.md';
3912 $pathtochangelog = $modulelowercase.'/ChangeLog.md';
3913 $pathtoindex = $modulelowercase.'/'.$modulelowercase.'index.php';
3914
3915 $realpathofmodule = realpath($dirread.'/'.$modulelowercase);
3916
3917 if ($action != 'editfile' || empty($file)) {
3918 $morehtmlright = '';
3919 if ($realpathofmodule != $dirread.'/'.$modulelowercase) {
3920 $morehtmlright = '<div style="padding: 12px 9px 12px">'.$form->textwithpicto('', '<span class="opacitymedium">'.$langs->trans("RealPathOfModule").' :</span> <strong class="wordbreak">'.$realpathofmodule.'</strong>').'</div>';
3921 }
3922
3923 print dol_get_fiche_head($head2, $tab, '', -1, '', 0, $morehtmlright, '', $MAXTABFOROBJECT, 'formodulesuffix'); // Description - level 2
3924
3925 print '<span class="opacitymedium">'.$langs->trans("ModuleBuilderDesc".$tab).'</span>';
3926 print '<br><br>';
3927
3928 print '<table>';
3929
3930 print '<tr><td>';
3931 print '<span class="fa fa-file"></span> '.$langs->trans("DescriptorFile").' : <strong class="wordbreak">'.$pathtofile.'</strong>';
3932 print '</td><td><a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format=php&file='.urlencode($pathtofile).'&find=DESCRIPTION_FLAG">'.img_picto($langs->trans("Edit"), 'edit').'</a>';
3933 print '</td></tr>';
3934
3935 print '<tr><td><span class="fa fa-file"></span> '.$langs->trans("Index").' : <strong class="wordbreak">'.$pathtoindex.'</strong>';
3936 print '</td><td><a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format=php&file='.urlencode($pathtoindex).'">'.img_picto($langs->trans("Edit"), 'edit').'</a>';
3937 print '</td></tr>';
3938
3939 // List of setup pages
3940 $listofsetuppages = dol_dir_list($realpathofmodule.'/admin', 'files', 0, '\.php$');
3941 foreach ($listofsetuppages as $setuppage) {
3942 // If this is a page for extrafields setup of an object
3943 $reg = array();
3944 if (preg_match('/^([a-z]+)_extrafields.php/', $setuppage['relativename'], $reg)) {
3945 // Check that object has $isextrafieldmanaged property set. If not, we should not show this file.
3946 $fileofclass = $realpathofmodule.'/class/'.$reg[1].'.class.php';
3947 if (is_readable($fileofclass) && !preg_match('/public\s+\$isextrafieldmanaged\s+=\s+1/', file_get_contents($fileofclass))) {
3948 continue;
3949 }
3950 }
3951
3952 //var_dump($setuppage);
3953 print '<tr><td>';
3954 print '<span class="fa fa-file"></span> ';
3955 if ($setuppage['relativename'] == 'about.php') {
3956 print $langs->trans("AboutFile");
3957 } else {
3958 print $langs->trans("SetupFile");
3959 }
3960 print ' : ';
3961 print '<strong class="wordbreak bold"><a href="'.dol_buildpath($modulelowercase.'/admin/'.$setuppage['relativename'], 1).'" target="_test">'.$modulelowercase.'/admin/'.$setuppage['relativename'].'</a></strong>';
3962 print '</td><td><a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format=php&file='.urlencode($modulelowercase.'/admin/'.$setuppage['relativename']).'">'.img_picto($langs->trans("Edit"), 'edit').'</a>';
3963 print '</td></tr>';
3964 }
3965
3966 print '<tr><td><span class="fa fa-file"></span> '.$langs->trans("ReadmeFile").' : <strong class="wordbreak">'.$pathtofilereadme.'</strong>';
3967 print '</td><td><a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format=markdown&file='.urlencode($pathtofilereadme).'">'.img_picto($langs->trans("Edit"), 'edit').'</a>';
3968 print '</td></tr>';
3969
3970 print '<tr><td><span class="fa fa-file"></span> '.$langs->trans("ChangeLog").' : <strong class="wordbreak">'.$pathtochangelog.'</strong>';
3971 print '</td><td><a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format=markdown&file='.urlencode($pathtochangelog).'">'.img_picto($langs->trans("Edit"), 'edit').'</a>';
3972 print '</td></tr>';
3973
3974 print '</table>';
3975 print '<br>';
3976
3977 print load_fiche_titre($form->textwithpicto($langs->trans("DescriptorFile"), $langs->transnoentitiesnoconv("File").' '.$pathtofile), '', '');
3978
3979 if (is_object($moduleobj)) {
3980 print '<div class="underbanner clearboth"></div>';
3981 print '<div class="fichecenter">';
3982 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
3983 print '<input type="hidden" name="token" value="'.newToken().'">';
3984 print '<input type="hidden" name="action" value="update_props_module">';
3985 print '<input type="hidden" name="module" value="'.dol_escape_htmltag($module).'">';
3986 print '<input type="hidden" name="tab" value="'.dol_escape_htmltag($tab).'">';
3987 print '<input type="hidden" name="keydescription" value="'.dol_escape_htmltag(GETPOST('keydescription', 'alpha')).'">';
3988
3989 print '<div class="div-table-responsive-no-min">';
3990 print '<table class="border centpercent">';
3991 print '<tr class="liste_titre"><td class="titlefield">';
3992 print $langs->trans("Parameter");
3993 print '</td><td>';
3994 print $langs->trans("Value");
3995 print '</td></tr>';
3996
3997 print '<tr><td>';
3998 print $langs->trans("IdModule");
3999 print '</td><td>';
4000 print $moduleobj->numero;
4001 print '<span class="opacitymedium">';
4002 print ' &nbsp; (';
4003 print dolButtonToOpenUrlInDialogPopup('popup_modules_id', $langs->transnoentitiesnoconv("SeeIDsInUse"), $langs->transnoentitiesnoconv("SeeIDsInUse"), '/admin/system/modules.php?mainmenu=home&leftmenu=admintools_info', '', '');
4004 print ' - <a href="https://wiki.dolibarr.org/index.php/List_of_modules_id" target="_blank" rel="noopener noreferrer external">'.$langs->trans("SeeReservedIDsRangeHere").'</a>)';
4005 print '</span>';
4006 print '</td></tr>';
4007
4008 print '<tr><td>';
4009 print $langs->trans("ModuleName");
4010 print '</td><td>';
4011 print $moduleobj->getName();
4012 print '</td></tr>';
4013
4014 print '<tr><td>';
4015 print $langs->trans("Description");
4016 print '</td><td>';
4017 if ($action == 'edit_moduledescription' && GETPOST('keydescription', 'alpha') === 'desc') {
4018 print '<input class="minwidth500" name="propsmodule" value="'.dol_escape_htmltag($moduleobj->description).'" spellcheck="false">';
4019 print '<input class="reposition button smallpaddingimp" type="submit" name="modifydesc" value="'.$langs->trans("Modify").'"/>';
4020 print '<input class="reposition button button-cancel smallpaddingimp" type="submit" name="cancel" value="'.$langs->trans("Cancel").'"/>';
4021 } else {
4022 print $moduleobj->description;
4023 print '<a class="editfielda reposition marginleftonly marginrighttonly paddingright paddingleft" href="'.$_SERVER["PHP_SELF"].'?action=edit_moduledescription&token='.newToken().'&tab='.urlencode($tab).'&module='.urlencode($module).'&keydescription=desc">'.img_edit().'</a>';
4024
4025 $moduledescritpionautotrans = $moduleobj->getDesc();
4026 if ($moduledescritpionautotrans != "Module".$moduleobj->name."Desc") {
4027 // $moduledescritpionautotrans has been found into a translation file
4028 print ' '.$form->textwithpicto('', $langs->trans("ModuleTranslatedIntoLangForKeyInto", "Module".$moduleobj->name."Desc", $moduledescritpionautotrans));
4029 } elseif ($moduledescritpionautotrans != "Module".$moduleobj->numero."Desc") {
4030 // $moduledescritpionautotrans has been found into a translation file
4031 print ' '.$form->textwithpicto('', $langs->trans("ModuleTranslatedIntoLangForKeyInto", "Module".$moduleobj->numero."Desc", $moduledescritpionautotrans));
4032 }
4033 }
4034 print '</td></tr>';
4035
4036 print '<tr><td>';
4037 print $langs->trans("Version");
4038 print '</td><td>';
4039 if ($action == 'edit_moduledescription' && GETPOST('keydescription', 'alpha') === 'version') {
4040 print '<input name="propsmodule" value="'.dol_escape_htmltag($moduleobj->getVersion()).'">';
4041 print '<input class="reposition button smallpaddingimp" type="submit" name="modifyversion" value="'.$langs->trans("Modify").'"/>';
4042 print '<input class="reposition button button-cancel smallpaddingimp" type="submit" name="cancel" value="'.$langs->trans("Cancel").'"/>';
4043 } else {
4044 print $moduleobj->getVersion();
4045 print '<a class="editfielda reposition marginleftonly marginrighttonly paddingright paddingleft" href="'.$_SERVER["PHP_SELF"].'?action=edit_moduledescription&token='.newToken().'&tab='.urlencode($tab).'&module='.urlencode($module).'&keydescription=version">'.img_edit().'</a>';
4046 }
4047 print '</td></tr>';
4048
4049 print '<tr><td>';
4050 print $langs->trans("Family");
4051 //print "<br>'crm','financial','hr','projects','products','ecm','technic','interface','other'";
4052 print '</td><td>';
4053 if ($action == 'edit_moduledescription' && GETPOST('keydescription', 'alpha') === 'family') {
4054 print '<select name="propsmodule" id="family" class="minwidth400">';
4055 $arrayoffamilies = array(
4056 'hr' => "ModuleFamilyHr",
4057 'crm' => "ModuleFamilyCrm",
4058 'srm' => "ModuleFamilySrm",
4059 'financial' => 'ModuleFamilyFinancial',
4060 'products' => 'ModuleFamilyProducts',
4061 'projects' => 'ModuleFamilyProjects',
4062 'ecm' => 'ModuleFamilyECM',
4063 'technic' => 'ModuleFamilyTechnic',
4064 'portal' => 'ModuleFamilyPortal',
4065 'interface' => 'ModuleFamilyInterface',
4066 'base' => 'ModuleFamilyBase',
4067 'other' => 'ModuleFamilyOther'
4068 );
4069 print '<option value="'.$moduleobj->family.'" data-html="'.dol_escape_htmltag($langs->trans($arrayoffamilies[$moduleobj->family]).' <span class="opacitymedium">- '.$moduleobj->family.'</span>').'">'.$langs->trans($arrayoffamilies[$moduleobj->family]).'</option>';
4070 foreach ($arrayoffamilies as $key => $value) {
4071 if ($key != $moduleobj->family) {
4072 print '<option value="'.$key.'" data-html="'.dol_escape_htmltag($langs->trans($value).' <span class="opacitymedium">- '.$key.'</span>').'">'.$langs->trans($value).'</option>';
4073 }
4074 }
4075 print '</select>';
4076 print '<input class="reposition button smallpaddingimp" type="submit" name="modifyfamily" value="'.$langs->trans("Modify").'"/>';
4077 print '<input class="reposition button button-cancel smallpaddingimp" type="submit" name="cancel" value="'.$langs->trans("Cancel").'"/>';
4078 } else {
4079 print $moduleobj->family;
4080 print '<a class="editfielda reposition marginleftonly marginrighttonly paddingright paddingleft" href="'.$_SERVER["PHP_SELF"].'?action=edit_moduledescription&token='.newToken().'&tab='.urlencode($tab).'&module='.urlencode($module).'&keydescription=family">'.img_edit().'</a>';
4081 }
4082 print '</td></tr>';
4083
4084 print '<!-- picto of module -->'."\n";
4085 print '<tr><td>';
4086 print $langs->trans("Picto");
4087 print '</td><td>';
4088 if ($action == 'edit_modulepicto' && GETPOST('keydescription', 'alpha') === 'picto') {
4089 print '<input class="minwidth200 maxwidth500" name="propsmodule" value="'.dol_escape_htmltag($moduleobj->picto).'" spellcheck="false">';
4090
4091 print $form->textwithpicto('', $langs->trans("Example").': fa-file, fa-globe, ... any font awesome code.<br>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\'');
4092
4093 print '<input class="reposition button smallpaddingimp" type="submit" name="modifypicto" value="'.$langs->trans("Modify").'"/>';
4094 print '<input class="reposition button button-cancel smallpaddingimp" type="submit" name="cancel" value="'.$langs->trans("Cancel").'"/>';
4095
4096 print ' &nbsp; &nbsp; ';
4097
4098 print '<span class="opacitymedium small">';
4099 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', '', '');
4100 print '</span>';
4101 } else {
4102 print $moduleobj->picto;
4103 print ' &nbsp; '.img_picto('', $moduleobj->picto, 'class="valignmiddle pictomodule paddingrightonly"');
4104 print '<a class="editfielda reposition marginleftonly marginrighttonly paddingright paddingleft" href="'.$_SERVER["PHP_SELF"].'?action=edit_modulepicto&token='.newToken().'&tab='.urlencode($tab).'&module='.urlencode($module).'&keydescription=picto">'.img_edit().'</a>';
4105 }
4106 print '</td></tr>';
4107
4108 print '<tr><td>';
4109 print $langs->trans("EditorName");
4110 print '</td><td>';
4111 if ($action == 'edit_moduledescription' && GETPOST('keydescription', 'alpha') === 'editor_name') {
4112 print '<input name="propsmodule" value="'.dol_escape_htmltag($moduleobj->editor_name).'" spellcheck="false">';
4113 print '<input class="reposition button smallpaddingimp" type="submit" name="modifyname" value="'.$langs->trans("Modify").'"/>';
4114 print '<input class="reposition button button-cancel smallpaddingimp" type="submit" name="cancel" value="'.$langs->trans("Cancel").'"/>';
4115 } else {
4116 print $moduleobj->editor_name;
4117 print '<a class="editfielda reposition marginleftonly marginrighttonly paddingright paddingleft" href="'.$_SERVER["PHP_SELF"].'?action=edit_moduledescription&token='.newToken().'&tab='.urlencode($tab).'&module='.urlencode($module).'&keydescription=editor_name">'.img_edit().'</a>';
4118 }
4119 print '</td></tr>';
4120
4121 print '<tr><td>';
4122 print $langs->trans("EditorUrl");
4123 print '</td><td>';
4124 if ($action == 'edit_moduledescription' && GETPOST('keydescription', 'alpha') === 'editor_url') {
4125 print '<input name="propsmodule" value="'.dol_escape_htmltag($moduleobj->editor_url).'" spellcheck="false">';
4126 print '<input class="reposition button smallpaddingimp" type="submit" name="modifyeditorurl" value="'.$langs->trans("Modify").'"/>';
4127 print '<input class="reposition button button-cancel smallpaddingimp" type="submit" name="cancel" value="'.$langs->trans("Cancel").'"/>';
4128 } else {
4129 if (!empty($moduleobj->editor_url)) {
4130 print '<a href="'.$moduleobj->editor_url.'" target="_blank" rel="noopener">'.$moduleobj->editor_url.' '.img_picto('', 'globe').'</a>';
4131 }
4132 print '<a class="editfielda reposition marginleftonly marginrighttonly paddingright paddingleft" href="'.$_SERVER["PHP_SELF"].'?action=edit_moduledescription&token='.newToken().'&tab='.urlencode($tab).'&module='.urlencode($module).'&keydescription=editor_url">'.img_edit().'</a>';
4133 }
4134 print '</td></tr>';
4135
4136 print '</table>';
4137 print '</div>';
4138 print '</form>';
4139 } else {
4140 print $langs->trans("ErrorFailedToLoadModuleDescriptorForXXX", $module).'<br>';
4141 }
4142
4143 if (!empty($moduleobj)) {
4144 print '<br><br>';
4145
4146 // Readme file
4147 print load_fiche_titre($form->textwithpicto($langs->trans("ReadmeFile"), $langs->transnoentitiesnoconv("File").' '.$pathtofilereadme), '', '');
4148
4149 print '<!-- readme file -->';
4150 if (dol_is_file($dirread.'/'.$pathtofilereadme)) {
4151 print '<div class="underbanner clearboth"></div><div class="fichecenter">'.$moduleobj->getDescLong().'</div>';
4152 } else {
4153 print '<span class="opacitymedium">'.$langs->trans("ErrorFileNotFound", $pathtofilereadme).'</span>';
4154 }
4155
4156 print '<br><br>';
4157
4158 // ChangeLog
4159 print load_fiche_titre($form->textwithpicto($langs->trans("ChangeLog"), $langs->transnoentitiesnoconv("File").' '.$pathtochangelog), '', '');
4160
4161 print '<!-- changelog file -->';
4162 if (dol_is_file($dirread.'/'.$pathtochangelog)) {
4163 print '<div class="underbanner clearboth"></div><div class="fichecenter">'.$moduleobj->getChangeLog().'</div>';
4164 } else {
4165 print '<span class="opacitymedium">'.$langs->trans("ErrorFileNotFound", $pathtochangelog).'</span>';
4166 }
4167 }
4168
4169 print dol_get_fiche_end();
4170 } else { // Edit text file
4171 $fullpathoffile = dol_buildpath($file, 0, 1); // Description - level 2
4172
4173 $content = '';
4174 if ($fullpathoffile) {
4175 $content = file_get_contents($fullpathoffile);
4176 }
4177
4178 // New module
4179 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
4180 print '<input type="hidden" name="token" value="'.newToken().'">';
4181 print '<input type="hidden" name="action" value="savefile">';
4182 print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
4183 print '<input type="hidden" name="tab" value="'.$tab.'">';
4184 print '<input type="hidden" name="module" value="'.$module.'">';
4185
4186 print dol_get_fiche_head($head2, $tab, '', -1, '', 0, '', '', 0, 'formodulesuffix');
4187
4188 $posCursor = (empty($find)) ? array() : array('find' => $find);
4189 $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%', 0, $posCursor);
4190 print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'html'));
4191
4192 print dol_get_fiche_end();
4193
4194 print '<center>';
4195 print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
4196 print ' &nbsp; ';
4197 print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
4198 print '</center>';
4199
4200 print '</form>';
4201 }
4202 } else {
4203 print dol_get_fiche_head($head2, $tab, '', -1, '', 0, '', '', $MAXTABFOROBJECT, 'formodulesuffix'); // Level 2
4204 }
4205
4206 if ($tab == 'languages') {
4207 print '<!-- tab=languages -->'."\n";
4208 if ($action != 'editfile' || empty($file)) {
4209 print '<span class="opacitymedium">'.$langs->trans("LanguageDefDesc").'</span><br>';
4210 print '<br>';
4211
4212
4213 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
4214 print '<input type="hidden" name="token" value="'.newToken().'">';
4215 print '<input type="hidden" name="action" value="addlanguage">';
4216 print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
4217 print '<input type="hidden" name="tab" value="'.$tab.'">';
4218 print '<input type="hidden" name="module" value="'.$module.'">';
4219 print $formadmin->select_language(getDolGlobalString('MAIN_LANG_DEFAULT'), 'newlangcode', 0, array(), 1, 0, 0, 'minwidth300', 1);
4220 print '<input type="submit" name="addlanguage" class="button smallpaddingimp" value="'.dol_escape_htmltag($langs->trans("AddLanguageFile")).'"><br>';
4221 print '</form>';
4222
4223 print '<br>';
4224 print '<br>';
4225
4226 $modulelowercase = dol_strtolower($module);
4227
4228 // Dir for module
4229 $diroflang = dol_buildpath($modulelowercase, 0);
4230 $diroflang .= '/langs';
4231 $langfiles = dol_dir_list($diroflang, 'files', 1, '\.lang$');
4232
4233 if (!preg_match('/custom/', $dirread)) {
4234 // If this is not a module into custom
4235 $diroflang = $dirread;
4236 $diroflang .= '/langs';
4237 $langfiles = dol_dir_list($diroflang, 'files', 1, $modulelowercase.'\.lang$');
4238 }
4239
4240 print '<table class="none">';
4241 foreach ($langfiles as $langfile) {
4242 $pathtofile = $modulelowercase.'/langs/'.$langfile['relativename'];
4243 if (!preg_match('/custom/', $dirread)) { // If this is not a module into custom
4244 $pathtofile = 'langs/'.$langfile['relativename'];
4245 }
4246 print '<tr><td><span class="fa fa-file"></span> '.$langs->trans("LanguageFile").' '.basename(dirname($pathtofile)).' : <strong class="wordbreak">'.$pathtofile.'</strong>';
4247 print '</td><td><a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format=ini&file='.urlencode($pathtofile).'">'.img_picto($langs->trans("Edit"), 'edit').'</a>';
4248 print '</td><td><a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=confirm_removefile&token='.newToken().'&file='.urlencode($pathtofile).'">'.img_picto($langs->trans("Delete"), 'delete').'</a>';
4249 print '</td>';
4250 }
4251 print '</table>';
4252 } else {
4253 // Edit text language file
4254
4255 //print $langs->trans("UseAsciiDocFormat").'<br>';
4256
4257 $fullpathoffile = dol_buildpath($file, 0);
4258
4259 $content = file_get_contents($fullpathoffile);
4260
4261 // New module
4262 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
4263 print '<input type="hidden" name="token" value="'.newToken().'">';
4264 print '<input type="hidden" name="action" value="savefile">';
4265 print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
4266 print '<input type="hidden" name="tab" value="'.$tab.'">';
4267 print '<input type="hidden" name="module" value="'.$module.'">';
4268
4269 $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%');
4270 print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'text'));
4271 print '<br>';
4272 print '<center>';
4273 print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
4274 print ' &nbsp; ';
4275 print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
4276 print '</center>';
4277
4278 print '</form>';
4279 }
4280 }
4281
4282 if ($tab == 'objects') {
4283 print '<!-- tab=objects -->'."\n";
4284 $head3 = array();
4285 $h = 0;
4286
4287 // Dir for module
4288 $dir = $dirread.'/'.$modulelowercase.'/class';
4289
4290 $head3[$h][0] = $_SERVER["PHP_SELF"].'?tab=objects&module='.$module.($forceddirread ? '@'.$dirread : '').'&tabobj=newobject';
4291 $head3[$h][1] = '<span class="valignmiddle text-plus-circle">'.$langs->trans("NewObjectInModulebuilder").'</span><span class="fa fa-plus-circle valignmiddle paddingleft"></span>';
4292 $head3[$h][2] = 'newobject';
4293 $h++;
4294
4295 // Scan for object class files
4296 $listofobject = dol_dir_list($dir, 'files', 0, '\.class\.php$');
4297
4298 $firstobjectname = '';
4299 foreach ($listofobject as $fileobj) {
4300 if (preg_match('/^api_/', $fileobj['name'])) {
4301 continue;
4302 }
4303 if (preg_match('/^actions_/', $fileobj['name'])) {
4304 continue;
4305 }
4306
4307 $tmpcontent = file_get_contents($fileobj['fullname']);
4308 if (preg_match('/class\s+([^\s]*)\s+extends\s+CommonObject/ims', $tmpcontent, $reg)) {
4309 //$objectname = preg_replace('/\.txt$/', '', $fileobj['name']);
4310 $objectname = $reg[1];
4311 if (empty($firstobjectname)) {
4312 $firstobjectname = $objectname;
4313 }
4314 $pictoname = 'generic';
4315 if (preg_match('/\$picto\s*=\s*["\']([^"\']+)["\']/', $tmpcontent, $reg)) {
4316 $pictoname = $reg[1];
4317 }
4318
4319 $head3[$h][0] = $_SERVER["PHP_SELF"].'?tab=objects&module='.$module.($forceddirread ? '@'.$dirread : '').'&tabobj='.$objectname;
4320 $head3[$h][1] = img_picto('', $pictoname, 'class="pictofixedwidth valignmiddle"').$objectname;
4321 $head3[$h][2] = $objectname;
4322 $h++;
4323 }
4324 }
4325
4326 if ($h > 1) {
4327 $head3[$h][0] = $_SERVER["PHP_SELF"].'?tab=objects&module='.$module.($forceddirread ? '@'.$dirread : '').'&tabobj=deleteobject';
4328 $head3[$h][1] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("DangerZone");
4329 $head3[$h][2] = 'deleteobject';
4330 $h++;
4331 }
4332
4333 // 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.
4334 if ($tabobj == 'newobjectifnoobj') {
4335 if ($firstobjectname) {
4336 $tabobj = $firstobjectname;
4337 } else {
4338 $tabobj = 'newobject';
4339 }
4340 }
4341
4342 print dol_get_fiche_head($head3, $tabobj, '', -1, '', 0, '', '', 0, 'forobjectsuffix'); // Level 3
4343
4344
4345 if ($tabobj == 'newobject') {
4346 // New object tab
4347 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
4348 print '<input type="hidden" name="token" value="'.newToken().'">';
4349 print '<input type="hidden" name="action" value="initobject">';
4350 print '<input type="hidden" name="tab" value="objects">';
4351 print '<input type="hidden" name="module" value="'.dol_escape_htmltag($module).'">';
4352
4353 // Tabs selected by default = all optional tabs; reflect posted state on redisplay
4354 $enabledtabsdefault = GETPOSTISSET('enabledtab') ? GETPOST('enabledtab', 'array') : array_keys(getModuleBuilderObjectTabs());
4355 // Not array_keys() here: an action shipped commented out in the template stays off by default
4356 $enabledcardactionsdefault = GETPOSTISSET('enabledcardaction') ? GETPOST('enabledcardaction', 'array') : getModuleBuilderDefaultEnabledKeys(getModuleBuilderObjectCardActions());
4357
4358 print '<span class="opacitymedium">'.$langs->trans("EnterNameOfObjectDesc").'</span><br><br>';
4359
4360 print '<div class="tagtable">';
4361
4362 print '<div class="tagtr"><div class="tagtd">';
4363 print '<span class="opacitymedium">'.$langs->trans("ObjectKey").'</span> &nbsp; ';
4364 print '</div><div class="tagtd">';
4365 print '<input type="text" name="objectname" maxlength="64" value="'.dol_escape_htmltag(GETPOSTISSET('objectname') ? GETPOST('objectname', 'alpha') : $modulename).'" required autofocus>';
4366 print $form->textwithpicto('', $langs->trans("Example").': MyObject, ACamelCaseName, ...');
4367 print '</div></div>';
4368
4369 print '<div class="tagtr"><div class="tagtd">';
4370 print '<span class="opacitymedium">'.$langs->trans("Picto").'</span> &nbsp; ';
4371 print '</div><div class="tagtd">';
4372 print '<input type="text" name="idpicto" value="fa-file" placeholder="'.dol_escape_htmltag($langs->trans("Picto")).'">';
4373
4374 print $form->textwithpicto('', $langs->trans("Example").': fa-file, fa-globe, ... any font awesome code.<br>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\'');
4375
4376 print '<span class="opacitymedium small">';
4377 print ' &nbsp; &nbsp; ';
4378 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', '', '');
4379 print '</span>';
4380
4381 print '</div></div>';
4382
4383 print '<div class="tagtr"><div class="tagtd">';
4384 print '<span class="opacitymedium">'.$langs->trans("DefinePropertiesFromExistingTable").'</span> &nbsp; ';
4385 print '</div><div class="tagtd">';
4386 print '<input type="text" name="initfromtablename" value="'.GETPOST('initfromtablename').'" placeholder="'.$langs->trans("TableName").'">';
4387 print $form->textwithpicto('', $langs->trans("DefinePropertiesFromExistingTableDesc").'<br>'.$langs->trans("DefinePropertiesFromExistingTableDesc2"));
4388 print '</div></div>';
4389
4390 print '</div>';
4391
4392 print '<br>';
4393 print '<input type="checkbox" name="includerefgeneration" id="includerefgeneration" value="includerefgeneration"> <label class="margintoponly" for="includerefgeneration">'.$form->textwithpicto($langs->trans("IncludeRefGeneration"), $langs->trans("IncludeRefGenerationHelp")).'</label><br>';
4394 print '<input type="checkbox" name="includedocgeneration" id="includedocgeneration" value="includedocgeneration"> <label for="includedocgeneration">'.$form->textwithpicto($langs->trans("IncludeDocGeneration"), $langs->trans("IncludeDocGenerationHelp")).'</label><br>';
4395 print '<input type="checkbox" name="generatepermissions" id="generatepermissions" value="generatepermissions"> <label for="generatepermissions">'.$form->textwithpicto($langs->trans("GeneratePermissions"), $langs->trans("GeneratePermissionsHelp")).'</label><br>';
4396 print '<input type="checkbox" name="nogeneratelines" id="nogeneratelines" value="nogeneratelines"> <label for="nogeneratelines">'.$form->textwithpicto($langs->trans("NoGenerateLines"), $langs->trans("NoGenerateLinesHelp")).'</label><br>';
4397 print '<br><span class="opacitymedium">'.$form->textwithpicto($langs->trans("EnabledTabsForObject"), $langs->trans("EnabledTabsForObjectHelp")).'</span><br>';
4398 foreach (getModuleBuilderObjectTabs() as $tabkey => $tabinfo) {
4399 $checked = in_array($tabkey, $enabledtabsdefault, true) ? ' checked' : '';
4400 print '<input type="checkbox" name="enabledtab[]" id="enabledtab_'.$tabkey.'" value="'.dol_escape_htmltag($tabkey).'"'.$checked.'> ';
4401 print '<label for="enabledtab_'.$tabkey.'">'.dol_escape_htmltag($langs->trans($tabinfo['label'])).'</label> &nbsp; ';
4402 }
4403 print '<br>';
4404 print '<br><span class="opacitymedium">'.$form->textwithpicto($langs->trans("EnabledCardActionsForObject"), $langs->trans("EnabledCardActionsForObjectHelp")).'</span><br>';
4405 foreach (getModuleBuilderObjectCardActions() as $actionkey => $actioninfo) {
4406 $checked = in_array($actionkey, $enabledcardactionsdefault, true) ? ' checked' : '';
4407 print '<input type="checkbox" name="enabledcardaction[]" id="enabledcardaction_'.$actionkey.'" value="'.dol_escape_htmltag($actionkey).'"'.$checked.'> ';
4408 print '<label for="enabledcardaction_'.$actionkey.'">'.dol_escape_htmltag($langs->trans($actioninfo['label'])).'</label> &nbsp; ';
4409 }
4410 print '<br>';
4411 print '<br>';
4412 print '<input type="submit" class="button small" name="create" value="'.dol_escape_htmltag($langs->trans("GenerateCode")).'"'.($dirins ? '' : ' disabled="disabled"').'>';
4413 print '<br>';
4414 print '<br>';
4415 /*
4416 print '<br>';
4417 print '<span class="opacitymedium">'.$langs->trans("or").'</span>';
4418 print '<br>';
4419 print '<br>';
4420 //print '<input type="checkbox" name="initfromtablecheck"> ';
4421 print $langs->trans("InitStructureFromExistingTable");
4422 print '<input type="text" name="initfromtablename" value="" placeholder="'.$langs->trans("TableName").'">';
4423 print '<input type="submit" class="button smallpaddingimp" name="createtablearray" value="'.dol_escape_htmltag($langs->trans("GenerateCode")).'"'.($dirins ? '' : ' disabled="disabled"').'>';
4424 print '<br>';
4425 */
4426
4427 print '</form>';
4428 } elseif ($tabobj == 'createproperty') {
4429 $attributesUnique = array(
4430 'proplabel' => $form->textwithpicto($langs->trans("Label"), $langs->trans("YouCanUseTranslationKey")),
4431 'propname' => $form->textwithpicto($langs->trans("Code"), $langs->trans("PropertyDesc"), 1, 'help', 'extracss', 0, 3, 'propertyhelp'),
4432 'proptype' => $form->textwithpicto($langs->trans("Type"), $langs->trans("TypeOfFieldsHelpIntro").'<br><br>'.$langs->trans("TypeOfFieldsHelp"), 1, 'help', 'extracss', 0, 3, 'typehelp'),
4433 'proparrayofkeyval' => $form->textwithpicto($langs->trans("ArrayOfKeyValues"), $langs->trans("ArrayOfKeyValuesDesc")),
4434 'propnotnull' => $form->textwithpicto($langs->trans("NotNull"), $langs->trans("NotNullDesc")),
4435 'propdefault' => $langs->trans("DefaultValue"),
4436 'propindex' => $langs->trans("DatabaseIndex"),
4437 'propforeignkey' => $form->textwithpicto($langs->trans("ForeignKey"), $langs->trans("ForeignKeyDesc"), 1, 'help', 'extracss', 0, 3, 'foreignkeyhelp'),
4438 'propposition' => $langs->trans("Position"),
4439 'propenabled' => $form->textwithpicto($langs->trans("Enabled"), $langs->trans("EnabledDesc"), 1, 'help', 'extracss', 0, 3, 'enabledhelp'),
4440 'propvisible' => $form->textwithpicto($langs->trans("Visibility"), $langs->trans("VisibleDesc").'<br><br>'.$langs->trans("ItCanBeAnExpression"), 1, 'help', 'extracss', 0, 3, 'visiblehelp'),
4441 'propnoteditable' => $langs->trans("NotEditable"),
4442 //'propalwayseditable' => $langs->trans("AlwaysEditable"),
4443 'propsearchall' => $form->textwithpicto($langs->trans("SearchAll"), $langs->trans("SearchAllDesc")),
4444 'propisameasure' => $form->textwithpicto($langs->trans("IsAMeasure"), $langs->trans("IsAMeasureDesc")),
4445 'propcss' => $langs->trans("CSSClass"),
4446 'propcssview' => $langs->trans("CSSViewClass"),
4447 'propcsslist' => $langs->trans("CSSListClass"),
4448 'prophelp' => $langs->trans("KeyForTooltip"),
4449 'propshowoncombobox' => $langs->trans("ShowOnCombobox"),
4450 //'propvalidate' => $form->textwithpicto($langs->trans("Validate"), $langs->trans("ValidateModBuilderDesc")),
4451 'propcomment' => $langs->trans("Comment"),
4452 );
4453 print '<form action="'.$_SERVER["PHP_SELF"].'?tab=objects&module='.urlencode($module).'&tabobj=createproperty&obj='.urlencode(GETPOST('obj')).'" method="POST">';
4454 print '<input type="hidden" name="token" value="'.newToken().'">';
4455 print '<input type="hidden" name="action" value="addproperty">';
4456 print '<input type="hidden" name="tab" value="objects">';
4457 print '<input type="hidden" name="module" value="'.dol_escape_htmltag($module).'">';
4458 print '<input type="hidden" name="obj" value="'.dol_escape_htmltag(GETPOST('obj')).'">';
4459
4460 print '<table class="border centpercent tableforfieldcreate">'."\n";
4461 $counter = 0;
4462 foreach ($attributesUnique as $key => $attribute) {
4463 if ($counter % 2 === 0) {
4464 print '<tr>';
4465 }
4466 if ($key == 'propname' || $key == 'proplabel') {
4467 print '<td class="titlefieldcreate fieldrequired">'.$attribute.'</td><td class="valuefieldcreate maxwidth50"><input class="maxwidth200" id="'.$key.'" type="text" name="'.$key.'" value="'.dol_escape_htmltag(GETPOST($key, 'alpha')).'"></td>';
4468 } elseif ($key == 'proptype') {
4469 print '<td class="titlefieldcreate fieldrequired">'.$attribute.'</td><td class="valuefieldcreate maxwidth50">';
4470 print '<input class="maxwidth200" name="'.$key.'" id="'.$key.'" list="datalist'.$key.'" type="text" value="'.dol_escape_htmltag(GETPOST($key, 'alpha')).'">';
4471 //print '<div id="suggestions"></div>';
4472 print '<datalist id="datalist'.$key.'">';
4473 print '<option>varchar(128)</option>';
4474 print '<option>email</option>';
4475 print '<option>phone</option>';
4476 print '<option>ip</option>';
4477 print '<option>url</option>';
4478 print '<option>password</option>';
4479 print '<option>text</option>';
4480 print '<option>html</option>';
4481 print '<option>date</option>';
4482 print '<option>datetime</option>';
4483 print '<option>integer</option>';
4484 print '<option>stars(5)</option>';
4485 print '<option>double(28,4)</option>';
4486 print '<option>real</option>';
4487 print '<option>integer:ClassName:RelativePath/To/ClassFile.class.php[:1[:FILTER]]</option>';
4488 // Combo with list of fields
4489 /*
4490 if (empty($formadmin)) {
4491 include_once DOL_DOCUMENT_ROOT.'/core/class/html.formadmin.class.php';
4492 $formadmin = new FormAdmin($db);
4493 }
4494 print $formadmin->selectTypeOfFields($key, GETPOST($key, 'alpha'));
4495 */
4496 print '</datalist>';
4497 print '</td>';
4498 //} elseif ($key == 'propvalidate') {
4499 // print '<td class="titlefieldcreate">'.$attribute.'</td><td class="valuefieldcreate maxwidth50"><input type="number" step="1" min="0" max="1" class="text maxwidth100" value="'.dol_escape_htmltag(GETPOST($key, 'alpha')).'"></td>';
4500 } elseif ($key == 'propvisible') {
4501 print '<td class="titlefieldcreate">'.$attribute.'</td><td class="valuefieldcreate"><input class="maxwidth200" type="text" name="'.$key.'" value="'.dol_escape_htmltag(GETPOSTISSET($key) ? GETPOST($key, 'alpha') : "1").'"></td>';
4502 } elseif ($key == 'propenabled') {
4503 //$default = "isModEnabled('".dol_strtolower($module)."')";
4504 $default = 1;
4505 print '<td class="titlefieldcreate">'.$attribute.'</td><td class="valuefieldcreate"><input class="maxwidth200" type="text" name="'.$key.'" value="'.dol_escape_htmltag(GETPOSTISSET($key) ? GETPOST($key, 'alpha') : $default).'"></td>';
4506 } elseif ($key == 'proparrayofkeyval') {
4507 print '<td class="titlefieldcreate tdproparrayofkeyval">'.$attribute.'</td><td class="valuefieldcreate"><textarea class="maxwidth200" name="'.$key.'">'.dol_escape_htmltag(GETPOSTISSET($key) ? GETPOST($key, 'alpha') : "").'</textarea></td>';
4508 } else {
4509 print '<td class="titlefieldcreate">'.$attribute.'</td><td class="valuefieldcreate"><input class="maxwidth200" type="text" name="'.$key.'" value="'.dol_escape_htmltag(GETPOSTISSET($key) ? GETPOST($key, 'alpha') : '').'"></td>';
4510 }
4511 $counter++;
4512 if ($counter % 2 === 0) {
4513 print '</tr>';
4514 }
4515 }
4516 if ($counter % 2 !== 0) {
4517 while ($counter % 2 !== 0) {
4518 print '<td></td>';
4519 $counter++;
4520 }
4521 print '</tr>';
4522 }
4523 print '</table><br>'."\n";
4524 print '<div class="center">';
4525 print '<input type="submit" class="button button-save" name="add" value="' . dol_escape_htmltag($langs->trans('Create')) . '">';
4526 print '<input type="button" class="button button-cancel" name="cancel" value="' . dol_escape_htmltag($langs->trans('Cancel')) . '" onclick="goBack()">';
4527 print '</div>';
4528 print '</form>';
4529 // javascript
4530 print '<script>
4531 function goBack() {
4532 var url = "'.$_SERVER["PHP_SELF"].'?tab=objects&module='.urlencode($module).'";
4533 window.location.href = url;
4534 }
4535 $(document).ready(function() {
4536 $("#proplabel").on("keyup", function() {
4537 console.log("key up on label");
4538 s = cleanString($("#proplabel").val());
4539 $("#propname").val(s);
4540 });
4541
4542 function cleanString( stringtoclean )
4543 {
4544 // allow "a-z", "A-Z", "0-9" and "_"
4545 stringtoclean = stringtoclean.replace(/[^a-z0-9_]+/ig, "");
4546 stringtoclean = stringtoclean.toLowerCase();
4547 if (!isNaN(stringtoclean)) {
4548 return ""
4549 }
4550 while ( stringtoclean.length > 1 && !isNaN( stringtoclean.charAt(0)) ){
4551 stringtoclean = stringtoclean.dol_substr(1)
4552 }
4553 if (stringtoclean.length > 28) {
4554 stringtoclean = stringtoclean.substring(0, 27);
4555 }
4556 return stringtoclean;
4557 }
4558
4559 });';
4560 print '</script>';
4561 } elseif ($tabobj == 'deleteobject') {
4562 // Delete object tab
4563 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
4564 print '<input type="hidden" name="token" value="'.newToken().'">';
4565 print '<input type="hidden" name="action" value="confirm_deleteobject">';
4566 print '<input type="hidden" name="tab" value="objects">';
4567 print '<input type="hidden" name="tabobj" value="deleteobject">';
4568 print '<input type="hidden" name="module" value="'.dol_escape_htmltag($module).'">';
4569
4570 print $langs->trans("EnterNameOfObjectToDeleteDesc").'<br><br>';
4571
4572 print '<input type="text" class="valignmiddle" name="objectname" value="" placeholder="'.dol_escape_htmltag($langs->trans("ObjectKey")).'" autofocus>';
4573 print '<input type="submit" class="button smallpaddingimp" name="delete" value="'.dol_escape_htmltag($langs->trans("Delete")).'"'.($dirins ? '' : ' disabled="disabled"').'>';
4574 print '</form>';
4575 } else {
4576 // tabobj = module
4577 if ($action == 'deleteproperty') {
4578 $formconfirm = $form->formconfirm(
4579 $_SERVER["PHP_SELF"].'?propertykey='.urlencode(GETPOST('propertykey', 'alpha')).'&objectname='.urlencode($objectname).'&tab='.urlencode($tab).'&module='.urlencode($module).'&tabobj='.urlencode($tabobj),
4580 $langs->trans('Delete'),
4581 $langs->trans('ConfirmDeleteProperty', GETPOST('propertykey', 'alpha')),
4582 'confirm_deleteproperty',
4583 '',
4584 0,
4585 1
4586 );
4587
4588 // Print form confirm
4589 print $formconfirm;
4590 }
4591 if ($action != 'editfile' || empty($file)) {
4592 try {
4593 //$pathtofile = $listofmodules[dol_strtolower($module)]['moduledescriptorrelpath'];
4594
4595 $pathtoclass = dol_strtolower($module).'/class/'.dol_strtolower($tabobj).'.class.php';
4596 $pathtoapi = dol_strtolower($module).'/class/api_'.dol_strtolower($module).'.class.php';
4597 $pathtoagenda = dol_strtolower($module).'/'.dol_strtolower($tabobj).'_agenda.php';
4598 $pathtocard = dol_strtolower($module).'/'.dol_strtolower($tabobj).'_card.php';
4599 $pathtodocument = dol_strtolower($module).'/'.dol_strtolower($tabobj).'_document.php';
4600 $pathtolist = dol_strtolower($module).'/'.dol_strtolower($tabobj).'_list.php';
4601 $pathtonote = dol_strtolower($module).'/'.dol_strtolower($tabobj).'_note.php';
4602 $pathtocontact = dol_strtolower($module).'/'.dol_strtolower($tabobj).'_contact.php';
4603 $pathtophpunit = dol_strtolower($module).'/test/phpunit/'.dol_strtolower($tabobj).'Test.php';
4604
4605 // Try to load object class file
4606 clearstatcache(true);
4607 if (function_exists('opcache_invalidate')) {
4608 opcache_invalidate($dirread.'/'.$pathtoclass, true); // remove the include cache hell !
4609 }
4610
4611 if (empty($forceddirread) && empty($dirread)) {
4612 $result = dol_include_once($pathtoclass);
4613 $stringofinclude = "dol_include_once(".$pathtoclass.")";
4614 } else {
4615 $result = include_once $dirread.'/'.$pathtoclass;
4616 $stringofinclude = "@include_once ".$dirread.'/'.$pathtoclass;
4617 }
4618
4619 if (class_exists($tabobj)) {
4620 try {
4621 $tmpobject = @new $tabobj($db);
4622 } catch (Exception $e) {
4623 dol_syslog('Failed to load Constructor of class: '.$e->getMessage(), LOG_WARNING);
4624 }
4625 } else {
4626 print '<span class="warning">'.$langs->trans('Failed to find the class '.$tabobj.' despite the '.$stringofinclude).'</span><br><br>';
4627 }
4628
4629 // Define path for sql file
4630 $pathtosql = dol_strtolower($module).'/sql/llx_'.dol_strtolower($module).'_'.dol_strtolower($tabobj).'-'.dol_strtolower($module).'.sql';
4631 $result = dol_buildpath($pathtosql);
4632 if (! dol_is_file($result)) {
4633 $pathtosql = dol_strtolower($module).'/sql/llx_'.dol_strtolower($module).'_'.dol_strtolower($tabobj).'.sql';
4634 $result = dol_buildpath($pathtosql);
4635 if (! dol_is_file($result)) {
4636 $pathtosql = 'install/mysql/tables/llx_'.dol_strtolower($module).'_'.dol_strtolower($tabobj).'-'.dol_strtolower($module).'.sql';
4637 $result = dol_buildpath($pathtosql);
4638 if (! dol_is_file($result)) {
4639 $pathtosql = 'install/mysql/tables/llx_'.dol_strtolower($module).'-'.dol_strtolower($module).'.sql';
4640 $result = dol_buildpath($pathtosql);
4641 if (! dol_is_file($result)) {
4642 $pathtosql = 'install/mysql/tables/llx_'.dol_strtolower($module).'.sql';
4643 $pathtosqlextra = 'install/mysql/tables/llx_'.dol_strtolower($module).'_extrafields.sql';
4644 $result = dol_buildpath($pathtosql);
4645 } else {
4646 $pathtosqlextra = 'install/mysql/tables/llx_'.dol_strtolower($module).'_extrafields-'.dol_strtolower($module).'.sql';
4647 }
4648 } else {
4649 $pathtosqlextra = 'install/mysql/tables/llx_'.dol_strtolower($module).'_'.dol_strtolower($tabobj).'_extrafields-'.dol_strtolower($module).'.sql';
4650 }
4651 } else {
4652 $pathtosqlextra = dol_strtolower($module).'/sql/llx_'.dol_strtolower($module).'_'.dol_strtolower($tabobj).'_extrafields.sql';
4653 }
4654 } else {
4655 $pathtosqlextra = dol_strtolower($module).'/sql/llx_'.dol_strtolower($module).'_'.dol_strtolower($tabobj).'_extrafields-'.dol_strtolower($module).'.sql';
4656 }
4657 $pathtosqlroot = preg_replace('/\/llx_.*$/', '', $pathtosql);
4658
4659 $pathtosqlkey = preg_replace('/\.sql$/', '.key.sql', $pathtosql);
4660 $pathtosqlextrakey = preg_replace('/\.sql$/', '.key.sql', $pathtosqlextra);
4661
4662 $pathtolib = dol_strtolower($module).'/lib/'.dol_strtolower($module).'.lib.php';
4663 $pathtoobjlib = dol_strtolower($module).'/lib/'.dol_strtolower($module).'_'.dol_strtolower($tabobj).'.lib.php';
4664
4665 $tmpobject = $tmpobject ?? null; // @phan-suppress-current-line PhanPluginDuplicateExpressionAssignmentOperation
4666 if (is_object($tmpobject) && property_exists($tmpobject, 'picto')) {
4667 $pathtopicto = $tmpobject->picto;
4668 $realpathtopicto = '';
4669 } else {
4670 $pathtopicto = dol_strtolower($module).'/img/object_'.dol_strtolower($tabobj).'.png';
4671 $realpathtopicto = $dirread.'/'.$pathtopicto;
4672 }
4673
4674 //var_dump($pathtoclass);
4675 //var_dump($dirread);
4676 $realpathtoclass = $dirread.'/'.$pathtoclass;
4677 $realpathtoapi = $dirread.'/'.$pathtoapi;
4678 $realpathtoagenda = $dirread.'/'.$pathtoagenda;
4679 $realpathtocard = $dirread.'/'.$pathtocard;
4680 $realpathtodocument = $dirread.'/'.$pathtodocument;
4681 $realpathtolist = $dirread.'/'.$pathtolist;
4682 $realpathtonote = $dirread.'/'.$pathtonote;
4683 $realpathtocontact = $dirread.'/'.$pathtocontact;
4684 $realpathtophpunit = $dirread.'/'.$pathtophpunit;
4685 $realpathtosql = $dirread.'/'.$pathtosql;
4686 $realpathtosqlextra = $dirread.'/'.$pathtosqlextra;
4687 $realpathtosqlkey = $dirread.'/'.$pathtosqlkey;
4688 $realpathtosqlextrakey = $dirread.'/'.$pathtosqlextrakey;
4689 $realpathtolib = $dirread.'/'.$pathtolib;
4690 $realpathtoobjlib = $dirread.'/'.$pathtoobjlib;
4691
4692 if (empty($realpathtoapi)) { // For compatibility with some old modules
4693 $pathtoapi = dol_strtolower($module).'/class/api_'.dol_strtolower($module).'s.class.php';
4694 $realpathtoapi = $dirread.'/'.$pathtoapi;
4695 }
4696
4697 $urloflist = dol_buildpath('/'.$pathtolist, 1);
4698 $urlofcard = dol_buildpath('/'.$pathtocard, 1);
4699
4700 $objs = array();
4701
4702 // Image
4703 $htmltooltip = '';
4704 if ($realpathtopicto && dol_is_file($realpathtopicto)) {
4705 $htmltooltip .= '<span class="fa fa-file-image-o"></span> '.$langs->trans("Image").' : <strong>'.(dol_is_file($realpathtopicto) ? '' : '<strike>').preg_replace('/^'.dol_strtolower($module).'\//', '', $pathtopicto).(dol_is_file($realpathtopicto) ? '' : '</strike>').'</strong>';
4706 $htmltooltip .= '<br>';
4707 } elseif (!empty($tmpobject)) {
4708 $htmltooltip .= '<span class="fa fa-file-image-o"></span> '.$langs->trans("Image").' : '.img_picto('', $tmpobject->picto, 'class="pictofixedwidth valignmiddle"').$tmpobject->picto;
4709 $htmltooltip .= '<br>';
4710 }
4711 $htmltooltip .= '<span class="fa fa-file-image-o"></span> '.$langs->trans("IsExtraFieldManaged").' : '.yn(empty($tmpobject->isextrafieldmanaged) ? 0 : 1, 1, 2);
4712 $htmltooltip .= '<br>';
4713 $htmltooltip .= '<span class="fa fa-file-image-o"></span> '.$langs->trans("IsMultiEntityManaged").' : '.yn(empty($tmpobject->ismultientitymanaged) ? 0 : 1, 1, 2);
4714 $htmltooltip .= '<br>';
4715
4716 print '<!-- section for object -->';
4717 print '<div class="fichehalfleft smallxxx">';
4718 // Main DAO class file
4719 print '<span class="fa fa-file"></span> '.$langs->trans("ClassFile").' : <strong>'.(dol_is_file($realpathtoclass) ? '' : '<strike>').preg_replace('/^'.dol_strtolower($module).'\//', '', $pathtoclass).(dol_is_file($realpathtoclass) ? '' : '</strike>').'</strong>';
4720 print ' <a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format=php&file='.urlencode($pathtoclass).'">'.img_picto($langs->trans("Edit"), 'edit').'</a>';
4721 print $form->textwithpicto('', $htmltooltip, 1, 'help', 'valignmiddle', 1);
4722 print '<br>';
4723
4724 // API file
4725 print '<br>';
4726 print '<span class="fa fa-file"></span> '.$langs->trans("ApiClassFile").' : <strong class="wordbreak">'.(dol_is_file($realpathtoapi) ? '' : '<strike><span class="opacitymedium">').preg_replace('/^'.dol_strtolower($module).'\//', '', $pathtoapi).(dol_is_file($realpathtoapi) ? '' : '</span></strike>').'</strong>';
4727 if (dol_is_file($realpathtoapi)) {
4728 $file = file_get_contents($realpathtoapi);
4729 if (preg_match('/var '.$tabobj.'\s+([^\s]*)\s/ims', $file, $objs)) {
4730 print ' <a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format=php&file='.urlencode($pathtoapi).'">'.img_picto($langs->trans("Edit"), 'edit').'</a>';
4731 print ' ';
4732 print '<a class="reposition editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=confirm_removefile&token='.newToken().'&file='.urlencode($pathtoapi).'">'.img_picto($langs->trans("Delete"), 'delete').'</a>';
4733 print $form->textwithpicto('', $langs->trans("InfoForApiFile"), 1, 'warning');
4734 print ' &nbsp; ';
4735 // Comparing to null (phan considers $modulelowercase can be null here)
4736 if (!isModEnabled($modulelowercase)) { // If module is not activated
4737 print '<a href="#" class="classfortooltip" target="apiexplorer" title="'.$langs->trans("ModuleMustBeEnabled", $module).'"><strike>'.$langs->trans("ApiExplorer").'</strike></a>';
4738 } else {
4739 print '<a href="'.DOL_URL_ROOT.'/api/index.php/explorer/" target="apiexplorer">'.$langs->trans("ApiExplorer").'</a>';
4740 }
4741 } else {
4742 print '<a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=initapi&token='.newToken().'&format=php&file='.urlencode($pathtoapi).'">'.img_picto($langs->trans('AddAPIsForThisObject'), 'generate', 'class="paddingleft"').'</a>';
4743 }
4744 } else {
4745 print '<a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=initapi&token='.newToken().'&format=php&file='.urlencode($pathtoapi).'">'.img_picto('Generate', 'generate', 'class="paddingleft"').'</a>';
4746 }
4747 // PHPUnit
4748 print '<br>';
4749 print '<span class="fa fa-file"></span> '.$langs->trans("TestClassFile").' : <strong class="wordbreak">'.(dol_is_file($realpathtophpunit) ? '' : '<strike><span class="opacitymedium">').preg_replace('/^'.dol_strtolower($module).'\//', '', $pathtophpunit).(dol_is_file($realpathtophpunit) ? '' : '</span></strike>').'</strong>';
4750 if (dol_is_file($realpathtophpunit)) {
4751 print ' <a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format=php&file='.urlencode($pathtophpunit).'">'.img_picto($langs->trans("Edit"), 'edit').'</a>';
4752 print ' ';
4753 print '<a class="reposition editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=confirm_removefile&token='.newToken().'&file='.urlencode($pathtophpunit).'">'.img_picto($langs->trans("Delete"), 'delete').'</a>';
4754 } else {
4755 print '<a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=initphpunit&token='.newToken().'&format=php&file='.urlencode($pathtophpunit).'">'.img_picto('Generate', 'generate', 'class="paddingleft"').'</a>';
4756 }
4757 print '<br>';
4758
4759 print '<br>';
4760
4761 print '<span class="fa fa-file"></span> '.$langs->trans("PageForLib").' : <strong class="wordbreak">'.(dol_is_file($realpathtolib) ? '' : '<strike>').preg_replace('/^'.dol_strtolower($module).'\//', '', $pathtolib).(dol_is_file($realpathtolib) ? '' : '</strike>').'</strong>';
4762 print ' <a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format=php&file='.urlencode($pathtolib).'">'.img_picto($langs->trans("Edit"), 'edit').'</a>';
4763 print '<br>';
4764 print '<span class="fa fa-file"></span> '.$langs->trans("PageForObjLib").' : <strong class="wordbreak">'.(dol_is_file($realpathtoobjlib) ? '' : '<strike>').preg_replace('/^'.dol_strtolower($module).'\//', '', $pathtoobjlib).(dol_is_file($realpathtoobjlib) ? '' : '</strike>').'</strong>';
4765 print ' <a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format=php&file='.urlencode($pathtoobjlib).'">'.img_picto($langs->trans("Edit"), 'edit').'</a>';
4766 print '<br>';
4767
4768 print '<br>';
4769 print '<span class="fa fa-file"></span> '.$langs->trans("SqlFile").' : <strong class="wordbreak">'.(dol_is_file($realpathtosql) ? '' : '<strike>').preg_replace('/^'.dol_strtolower($module).'\//', '', $pathtosql).(dol_is_file($realpathtosql) ? '' : '</strike>').'</strong>';
4770 print ' <a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format=sql&file='.urlencode($pathtosql).'">'.img_picto($langs->trans("Edit"), 'edit').'</a>';
4771 print ' &nbsp; <a class="reposition" href="'.$_SERVER["PHP_SELF"].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=droptable&token='.newToken().'">'.$langs->trans("DropTableIfEmpty").'</a>';
4772 //print ' &nbsp; <a href="'.$_SERVER["PHP_SELF"].'">'.$langs->trans("RunSql").'</a>';
4773 print '<br>';
4774 print '<span class="fa fa-file"></span> '.$langs->trans("SqlFileKey").' : <strong class="wordbreak">'.(dol_is_file($realpathtosqlkey) ? '' : '<strike>').preg_replace('/^'.dol_strtolower($module).'\//', '', $pathtosqlkey).(dol_is_file($realpathtosqlkey) ? '' : '</strike>').'</strong>';
4775 print ' <a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format=sql&file='.urlencode($pathtosqlkey).'">'.img_picto($langs->trans("Edit"), 'edit').'</a>';
4776 //print ' &nbsp; <a href="'.$_SERVER["PHP_SELF"].'">'.$langs->trans("RunSql").'</a>';
4777 print '<br>';
4778 if (!empty($tmpobject->isextrafieldmanaged)) {
4779 print '<span class="fa fa-file"></span> '.$langs->trans("SqlFileExtraFields").' : <strong class="wordbreak">'.(dol_is_file($realpathtosqlextra) ? '' : '<strike><span class="opacitymedium">').preg_replace('/^'.dol_strtolower($module).'\//', '', $pathtosqlextra).(dol_is_file($realpathtosqlextra) && dol_is_file($realpathtosqlextrakey) ? '' : '</span></strike>').'</strong>';
4780 if (dol_is_file($realpathtosqlextra) && dol_is_file($realpathtosqlextrakey)) {
4781 print ' <a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&file='.urlencode($pathtosqlextra).'">'.img_picto($langs->trans("Edit"), 'edit').'</a>';
4782 print ' ';
4783 print '<a class="reposition editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=confirm_removefile&token='.newToken().'&file='.urlencode($pathtosqlextra).'">'.img_picto($langs->trans("Delete"), 'delete').'</a>';
4784 print ' &nbsp; ';
4785 print '<a class="reposition editfielda" href="'.$_SERVER["PHP_SELF"].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=droptableextrafields&token='.newToken().'">'.$langs->trans("DropTableIfEmpty").'</a>';
4786 } else {
4787 print '<a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=initsqlextrafields&token='.newToken().'&format=sql&file='.urlencode($pathtosqlextra).'">'.img_picto('Generate', 'generate', 'class="paddingleft"').'</a>';
4788 }
4789
4790 //print ' &nbsp; <a href="'.$_SERVER["PHP_SELF"].'">'.$langs->trans("RunSql").'</a>';
4791 print '<br>';
4792 print '<span class="fa fa-file"></span> '.$langs->trans("SqlFileKeyExtraFields").' : <strong class="wordbreak">'.(dol_is_file($realpathtosqlextrakey) ? '' : '<strike><span class="opacitymedium">').preg_replace('/^'.dol_strtolower($module).'\//', '', $pathtosqlextrakey).(dol_is_file($realpathtosqlextra) && dol_is_file($realpathtosqlextrakey) ? '' : '</span></strike>').'</strong>';
4793 if (dol_is_file($realpathtosqlextra) && dol_is_file($realpathtosqlextrakey)) {
4794 print ' <a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format=sql&file='.urlencode($pathtosqlextrakey).'">'.img_picto($langs->trans("Edit"), 'edit').'</a>';
4795 print ' ';
4796 print '<a class="reposition editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=confirm_removefile&token='.newToken().'&file='.urlencode($pathtosqlextrakey).'">'.img_picto($langs->trans("Delete"), 'delete').'</a>';
4797 } else {
4798 print '<a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=initsqlextrafields&token='.newToken().'&format=sql&file='.urlencode($pathtosqlextra).'">'.img_picto('Generate', 'generate', 'class="paddingleft"').'</a>';
4799 }
4800 print '<br>';
4801 }
4802 print '</div>';
4803
4804 print '<div class="fichehalfleft smallxxxx">';
4805 print '<span class="fa fa-file"></span> '.$langs->trans("PageForList").' : <strong class="wordbreak"><a href="'.$urloflist.'" target="_test">'.(dol_is_file($realpathtolist) ? '' : '<strike><span class="opacitymedium">').preg_replace('/^'.dol_strtolower($module).'\//', '', $pathtolist).(dol_is_file($realpathtolist) ? '' : '</span></strike>').'</a></strong>';
4806 print ' <a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format=php&file='.urlencode($pathtolist).'">'.img_picto($langs->trans("Edit"), 'edit').'</a>';
4807 print '<br>';
4808 print '<span class="fa fa-file"></span> '.$langs->trans("PageForCreateEditView").' : <strong class="wordbreak"><a href="'.$urlofcard.'?action=create" target="_test">'.(dol_is_file($realpathtocard) ? '' : '<strike>').preg_replace('/^'.dol_strtolower($module).'\//', '', $pathtocard).(dol_is_file($realpathtocard) ? '' : '</strike>').'?action=create</a></strong>';
4809 print ' <a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format=php&file='.urlencode($pathtocard).'">'.img_picto($langs->trans("Edit"), 'edit').'</a>';
4810 print '<br>';
4811 // Page contact
4812 print '<span class="fa fa-file"></span> '.$langs->trans("PageForContactTab").' : <strong class="wordbreak">'.(dol_is_file($realpathtocontact) ? '' : '<strike><span class="opacitymedium">').preg_replace('/^'.dol_strtolower($module).'\//', '', $pathtocontact).(dol_is_file($realpathtocontact) ? '' : '</span></strike>').'</strong>';
4813 print ' <a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format=php&file='.urlencode($pathtocontact).'">'.img_picto($langs->trans("Edit"), 'edit').'</a>';
4814 if (dol_is_file($realpathtocontact)) {
4815 print ' ';
4816 print '<a class="reposition editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=confirm_removefile&token='.newToken().'&file='.urlencode($pathtocontact).'">'.img_picto($langs->trans("Delete"), 'delete').'</a>';
4817 } else {
4818 print '<a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=initpagecontact&token='.newToken().'&format=php&file='.urlencode($pathtocontact).'">'.img_picto('Generate', 'generate', 'class="paddingleft"').'</a>';
4819 }
4820 print '<br>';
4821 // Page document
4822 print '<span class="fa fa-file"></span> '.$langs->trans("PageForDocumentTab").' : <strong class="wordbreak">'.(dol_is_file($realpathtodocument) ? '' : '<strike><span class="opacitymedium">').preg_replace('/^'.dol_strtolower($module).'\//', '', $pathtodocument).(dol_is_file($realpathtodocument) ? '' : '</span></strike>').'</strong>';
4823 print ' <a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format=php&file='.urlencode($pathtodocument).'">'.img_picto($langs->trans("Edit"), 'edit').'</a>';
4824 if (dol_is_file($realpathtodocument)) {
4825 print ' ';
4826 print '<a class="reposition editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=confirm_removefile&token='.newToken().'&file='.urlencode($pathtodocument).'">'.img_picto($langs->trans("Delete"), 'delete').'</a>';
4827 } else {
4828 print '<a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=initpagedocument&token='.newToken().'&format=php&file='.urlencode($pathtocontact).'">'.img_picto('Generate', 'generate', 'class="paddingleft"').'</a>';
4829 }
4830 print '<br>';
4831 // Page notes
4832 print '<span class="fa fa-file"></span> '.$langs->trans("PageForNoteTab").' : <strong class="wordbreak">'.(dol_is_file($realpathtonote) ? '' : '<strike><span class="opacitymedium">').preg_replace('/^'.dol_strtolower($module).'\//', '', $pathtonote).(dol_is_file($realpathtonote) ? '' : '</span></strike>').'</strong>';
4833 print ' <a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format=php&file='.urlencode($pathtonote).'">'.img_picto($langs->trans("Edit"), 'edit').'</a>';
4834 if (dol_is_file($realpathtonote)) {
4835 print ' ';
4836 print '<a class="reposition editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=confirm_removefile&token='.newToken().'&file='.urlencode($pathtonote).'">'.img_picto($langs->trans("Delete"), 'delete').'</a>';
4837 } else {
4838 print '<a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=initpagenote&token='.newToken().'&format=php&file='.urlencode($pathtocontact).'">'.img_picto('Generate', 'generate', 'class="paddingleft"').'</a>';
4839 }
4840 print '<br>';
4841 // Page agenda
4842 print '<span class="fa fa-file"></span> '.$langs->trans("PageForAgendaTab").' : <strong class="wordbreak">'.(dol_is_file($realpathtoagenda) ? '' : '<strike><span class="opacitymedium">').preg_replace('/^'.dol_strtolower($module).'\//', '', $pathtoagenda).(dol_is_file($realpathtoagenda) ? '' : '</span></strike>').'</strong>';
4843 print ' <a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&format=php&token='.newToken().'&file='.urlencode($pathtoagenda).'">'.img_picto($langs->trans("Edit"), 'edit').'</a>';
4844 if (dol_is_file($realpathtoagenda)) {
4845 print ' ';
4846 print '<a class="reposition editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=confirm_removefile&token='.newToken().'&file='.urlencode($pathtoagenda).'">'.img_picto($langs->trans("Delete"), 'delete').'</a>';
4847 } else {
4848 print '<a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&tabobj='.$tabobj.'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=initpageagenda&token='.newToken().'&format=php&file='.urlencode($pathtocontact).'">'.img_picto('Generate', 'generate', 'class="paddingleft"').'</a>';
4849 }
4850 print '<br>';
4851 print '<br>';
4852
4853 print '</div>';
4854
4855 print '<br><br><br>';
4856
4857 if (!empty($tmpobject)) {
4858 $reflector = new ReflectionClass($tabobj);
4859 $reflectorproperties = $reflector->getProperties(); // Can also use get_object_vars
4860 $reflectorpropdefault = $reflector->getDefaultProperties(); // Can also use get_object_vars
4861 //$propstat = $reflector->getStaticProperties();
4862 //var_dump($reflectorpropdefault);
4863
4864 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
4865 print '<input type="hidden" name="token" value="'.newToken().'">';
4866 print '<input type="hidden" name="action" value="addproperty">';
4867 print '<input type="hidden" name="tab" value="objects">';
4868 print '<input type="hidden" name="page_y" value="">';
4869 print '<input type="hidden" name="module" value="'.dol_escape_htmltag($module.($forceddirread ? '@'.$dirread : '')).'">';
4870 print '<input type="hidden" name="tabobj" value="'.dol_escape_htmltag($tabobj).'">';
4871
4872 print '<input class="button smallpaddingimp" type="submit" name="regenerateclasssql" value="'.$langs->trans("RegenerateClassAndSql").'">';
4873 print '<br><br class="clearboth">';
4874 print '<br class="clearboth">';
4875
4876 $mod = dol_strtolower($module);
4877 $obj = dol_strtolower($tabobj);
4878 $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));
4879 $nbOfProperties = count($reflectorpropdefault['fields']);
4880
4881 print_barre_liste($langs->trans("ObjectProperties"), 0, $_SERVER["PHP_SELF"], '', '', '', '', 0, $nbOfProperties, '', 0, $newproperty, 'margintoponly', 0, 0, 0, 1);
4882
4883 //var_dump($reflectorpropdefault);exit;
4884 print '<!-- Table with properties of object -->'."\n";
4885 print '<div class="div-table-responsive">';
4886 print '<table class="noborder small">';
4887 print '<tr class="liste_titre">';
4888 if (!empty($conf->main_checkbox_left_column)) {
4889 print '<th class="tdstickyright tdstickyghostwhite"></th>';
4890 }
4891 print '<th class="tdsticky tdstickygray">';
4892 $htmltext = $langs->trans("PropertyDesc").'<br><br><a class="" href="https://wiki.dolibarr.org/index.php/Language_and_development_rules#Table_and_fields_structures" target="_blank" rel="noopener noreferrer external">'.$langs->trans("SeeExamples").'</a>';
4893 print $form->textwithpicto($langs->trans("Code"), $htmltext, 1, 'help', 'extracss', 0, 3, 'propertyhelp');
4894 print '</th>';
4895 print '<th>';
4896 print $form->textwithpicto($langs->trans("Label"), $langs->trans("YouCanUseTranslationKey"));
4897 print '</th>';
4898 print '<th>'.$form->textwithpicto($langs->trans("Type"), $langs->trans("TypeOfFieldsHelpIntro").'<br><br>'.$langs->trans("TypeOfFieldsHelp"), 1, 'help', 'extracss', 0, 3, 'typehelp').'</th>';
4899 print '<th>'.$form->textwithpicto($langs->trans("ArrayOfKeyValues"), $langs->trans("ArrayOfKeyValuesDesc")).'</th>';
4900 print '<th class="center">'.$form->textwithpicto($langs->trans("NotNull"), $langs->trans("NotNullDesc")).'</th>';
4901 print '<th class="center">'.$langs->trans("DefaultValue").'</th>';
4902 print '<th class="center">'.$langs->trans("DatabaseIndex").'</th>';
4903 print '<th class="center">'.$form->textwithpicto($langs->trans("ForeignKey"), $langs->trans("ForeignKeyDesc"), 1, 'help', 'extracss', 0, 3, 'foreignkeyhelp').'</th>';
4904 print '<th class="right">'.$langs->trans("Position").'</th>';
4905 print '<th class="center">'.$form->textwithpicto($langs->trans("Enabled"), $langs->trans("EnabledDesc"), 1, 'help', 'extracss', 0, 3, 'enabledhelp').'</th>';
4906 print '<th class="center">'.$form->textwithpicto($langs->trans("Visibility"), $langs->trans("VisibleDesc").'<br><br>'.$langs->trans("ItCanBeAnExpression"), 1, 'help', 'extracss', 0, 3, 'visiblehelp').'</th>';
4907 print '<th class="center">'.$langs->trans("NotEditable").'</th>';
4908 //print '<th class="center">'.$langs->trans("AlwaysEditable").'</th>';
4909 print '<th class="center">'.$form->textwithpicto($langs->trans("SearchAll"), $langs->trans("SearchAllDesc")).'</th>';
4910 print '<th class="center">'.$form->textwithpicto($langs->trans("IsAMeasure"), $langs->trans("IsAMeasureDesc")).'</th>';
4911 print '<th class="center">'.$langs->trans("CSSClass").'</th>';
4912 print '<th class="center">'.$langs->trans("CSSViewClass").'</th>';
4913 print '<th class="center">'.$langs->trans("CSSListClass").'</th>';
4914 print '<th>'.$langs->trans("KeyForTooltip").'</th>';
4915 print '<th class="center">'.$langs->trans("ShowOnCombobox").'</th>';
4916 //print '<th class="center">'.$langs->trans("Disabled").'</th>';
4917 print '<th>'.$form->textwithpicto($langs->trans("Validate"), $langs->trans("ValidateModBuilderDesc")).'</th>';
4918 print '<th>'.$langs->trans("Comment").'</th>';
4919 if (empty($conf->main_checkbox_left_column)) {
4920 print '<th class="tdstickyright tdstickyghostwhite"></th>';
4921 }
4922 print '</tr>';
4923
4924 // We must use $reflectorpropdefault['fields'] to get list of fields because $tmpobject->fields may have been
4925 // modified during the constructor and we want value into head of class before constructor is called.
4926 //$properties = dol_sort_array($tmpobject->fields, 'position');
4927 $properties = dol_sort_array($reflectorpropdefault['fields'], 'position');
4928 if (!empty($properties)) {
4929 // List of existing properties
4930 foreach ($properties as $propkey => $propval) {
4931 /* If from Reflection
4932 if ($propval->class == $tabobj)
4933 {
4934 $propname=$propval->getName();
4935 $comment=$propval->getDocComment();
4936 $type=gettype($tmpobject->$propname);
4937 $default=$propdefault[$propname];
4938 // Discard generic properties
4939 if (in_array($propname, array('element', 'childtables', 'table_element', 'table_element_line', 'class_element_line', 'ismultientitymanaged'))) continue;
4940
4941 // Keep or not lines
4942 if (in_array($propname, array('fk_element', 'lines'))) continue;
4943 }*/
4944
4945 $propname = $propkey;
4946 $proplabel = $propval['label'];
4947 $proptype = $propval['type'];
4948 $proparrayofkeyval = !empty($propval['arrayofkeyval']) ? $propval['arrayofkeyval'] : '';
4949 $propnotnull = !empty($propval['notnull']) ? $propval['notnull'] : '0';
4950 $propdefault = !empty($propval['default']) ? $propval['default'] : '';
4951 $propindex = !empty($propval['index']) ? $propval['index'] : '';
4952 $propforeignkey = !empty($propval['foreignkey']) ? $propval['foreignkey'] : '';
4953 $propposition = $propval['position'];
4954 $propenabled = $propval['enabled'];
4955 $propvisible = $propval['visible'];
4956 $propnoteditable = !empty($propval['noteditable']) ? $propval['noteditable'] : 0;
4957 //$propalwayseditable = !empty($propval['alwayseditable'])?$propval['alwayseditable']:0;
4958 $propsearchall = !empty($propval['searchall']) ? $propval['searchall'] : 0;
4959 $propisameasure = !empty($propval['isameasure']) ? $propval['isameasure'] : 0;
4960 $propcss = !empty($propval['css']) ? $propval['css'] : '';
4961 $propcssview = !empty($propval['cssview']) ? $propval['cssview'] : '';
4962 $propcsslist = !empty($propval['csslist']) ? $propval['csslist'] : '';
4963 $prophelp = !empty($propval['help']) ? $propval['help'] : '';
4964 $propshowoncombobox = !empty($propval['showoncombobox']) ? $propval['showoncombobox'] : 0;
4965 //$propdisabled=$propval['disabled'];
4966 $propvalidate = !empty($propval['validate']) ? $propval['validate'] : 0;
4967 $propcomment = !empty($propval['comment']) ? $propval['comment'] : '';
4968
4969 print '<!-- line for object property -->'."\n";
4970 print '<tr class="oddeven">';
4971
4972 if (!empty($conf->main_checkbox_left_column)) {
4973 if ($action == 'editproperty' && $propname == $propertykey) {
4974 print '<td class="center minwidth75 tdstickyright tdstickyghostwhite">';
4975 print '<input class="reposition button smallpaddingimp" type="submit" name="edit" value="'.$langs->trans("Save").'">';
4976 print '<input class="reposition button button-cancel smallpaddingimp" type="submit" name="cancel" value="'.$langs->trans("Cancel").'">';
4977 print '</td>';
4978 } else {
4979 print '<td class="center minwidth75 tdstickyright tdstickyghostwhite">';
4980 if ($propname != 'rowid') {
4981 print '<a class="editfielda reposition marginleftonly marginrighttonly paddingright paddingleft" href="'.$_SERVER["PHP_SELF"].'?action=editproperty&token='.newToken().'&propertykey='.urlencode($propname).'&tab='.urlencode($tab).'&module='.urlencode($module).'&tabobj='.urlencode($tabobj).'">'.img_edit().'</a>';
4982 print '<a class="reposition marginleftonly marginrighttonly paddingright paddingleft" href="'.$_SERVER["PHP_SELF"].'?action=deleteproperty&token='.newToken().'&propertykey='.urlencode($propname).'&tab='.urlencode($tab).'&module='.urlencode($module).'&tabobj='.urlencode($tabobj).'">'.img_delete().'</a>';
4983 }
4984 print '</td>';
4985 }
4986 }
4987 print '<td class="tdsticky tdstickygray">';
4988 print dol_escape_htmltag($propname);
4989 print '</td>';
4990 if ($action == 'editproperty' && $propname == $propertykey) {
4991 print '<td>';
4992 print '<input type="hidden" name="propname" value="'.dol_escape_htmltag($propname).'">';
4993 print '<input name="proplabel" class="maxwidth125" value="'.dol_escape_htmltag($proplabel).'">';
4994 print '</td>';
4995 print '<td class="tdoverflowmax150">';
4996 print '<input name="proptype" id="proptype" class="maxwidth125" value="'.dol_escape_htmltag($proptype).'" list="datalistproptype"></input>';
4997 // Use the samedatalist than for create
4998 print '<datalist id="datalistproptype">';
4999 print '<option>varchar(128)</option>';
5000 print '<option>email</option>';
5001 print '<option>phone</option>';
5002 print '<option>ip</option>';
5003 print '<option>url</option>';
5004 print '<option>password</option>';
5005 print '<option>text</option>';
5006 print '<option>html</option>';
5007 print '<option>date</option>';
5008 print '<option>datetime</option>';
5009 print '<option>integer</option>';
5010 print '<option>stars(5)</option>';
5011 print '<option>double(28,4)</option>';
5012 print '<option>real</option>';
5013 print '<option>integer:ClassName:RelativePath/To/ClassFile.class.php[:1[:FILTER]]</option>';
5014 // Combo with list of fields
5015 /*
5016 if (empty($formadmin)) {
5017 include_once DOL_DOCUMENT_ROOT.'/core/class/html.formadmin.class.php';
5018 $formadmin = new FormAdmin($db);
5019 }
5020 print $formadmin->selectTypeOfFields($key, GETPOST($key, 'alpha'));
5021 */
5022 print '</datalist>';
5023
5024 print '</td>';
5025 print '<td class="tdoverflowmax200">';
5026 print '<textarea name="proparrayofkeyval">';
5027 if (isset($proparrayofkeyval)) {
5028 if (is_array($proparrayofkeyval) || $proparrayofkeyval != '') {
5029 print dol_escape_htmltag(json_encode($proparrayofkeyval, JSON_UNESCAPED_UNICODE));
5030 }
5031 }
5032 print '</textarea>';
5033 print '</td>';
5034 print '<td>';
5035 print '<input class="center width50" name="propnotnull" value="'.dol_escape_htmltag($propnotnull).'">';
5036 print '</td>';
5037 print '<td>';
5038 print '<input class="maxwidth50" name="propdefault" value="'.dol_escape_htmltag($propdefault).'">';
5039 print '</td>';
5040 print '<td class="center">';
5041 print '<input class="center maxwidth50" name="propindex" value="'.dol_escape_htmltag($propindex).'">';
5042 print '</td>';
5043 print '<td>';
5044 print '<input class="center maxwidth100" name="propforeignkey" value="'.dol_escape_htmltag($propforeignkey).'">';
5045 print '</td>';
5046 print '<td>';
5047 print '<input class="right width50" name="propposition" value="'.dol_escape_htmltag($propposition).'">';
5048 print '</td>';
5049 print '<td>';
5050 print '<input class="center width75" name="propenabled" value="'.dol_escape_htmltag($propenabled).'">';
5051 print '</td>';
5052 print '<td>';
5053 print '<input class="center width75" name="propvisible" value="'.dol_escape_htmltag($propvisible).'">';
5054 print '</td>';
5055 print '<td>';
5056 print '<input class="center width50" name="propnoteditable" size="2" value="'.dol_escape_htmltag($propnoteditable).'">';
5057 print '</td>';
5058 /*print '<td>';
5059 print '<input class="center" name="propalwayseditable" size="2" value="'.dol_escape_htmltag($propalwayseditable).'">';
5060 print '</td>';*/
5061 print '<td>';
5062 print '<input class="center width50" name="propsearchall" value="'.dol_escape_htmltag($propsearchall).'">';
5063 print '</td>';
5064 print '<td>';
5065 print '<input class="center width50" name="propisameasure" value="'.dol_escape_htmltag($propisameasure).'">';
5066 print '</td>';
5067 print '<td>';
5068 print '<input class="center maxwidth50" name="propcss" value="'.dol_escape_htmltag($propcss).'">';
5069 print '</td>';
5070 print '<td>';
5071 print '<input class="center maxwidth50" name="propcssview" value="'.dol_escape_htmltag($propcssview).'">';
5072 print '</td>';
5073 print '<td>';
5074 print '<input class="center maxwidth50" name="propcsslist" value="'.dol_escape_htmltag($propcsslist).'">';
5075 print '</td>';
5076 print '<td>';
5077 print '<input class="maxwidth100" name="prophelp" value="'.dol_escape_htmltag($prophelp).'">';
5078 print '</td>';
5079 print '<td>';
5080 print '<input class="center maxwidth50" name="propshowoncombobox" value="'.dol_escape_htmltag($propshowoncombobox).'">';
5081 print '</td>';
5082 print '<td>';
5083 print '<input type="number" step="1" min="0" max="1" class="text maxwidth100" name="propvalidate" value="'.dol_escape_htmltag($propvalidate).'">';
5084 print '</td>';
5085 print '<td>';
5086 print '<input class="maxwidth100" name="propcomment" value="'.dol_escape_htmltag($propcomment).'">';
5087 print '</td>';
5088 if (empty($conf->main_checkbox_left_column)) {
5089 print '<td class="center minwidth75 tdstickyright tdstickyghostwhite">';
5090 print '<input class="reposition button smallpaddingimp" type="submit" name="edit" value="'.$langs->trans("Save").'">';
5091 print '<input class="reposition button button-cancel smallpaddingimp" type="submit" name="cancel" value="'.$langs->trans("Cancel").'">';
5092 print '</td>';
5093 }
5094 } else {
5095 print '<td class="tdoverflowmax200" title="'.dol_escape_htmltag($proplabel).'">';
5096 print dol_escape_htmltag($proplabel);
5097 print '</td>';
5098 print '<td class="tdoverflowmax200">';
5099 $pictoType = '';
5100 $matches = array();
5101 if (preg_match('/^varchar/', $proptype, $matches)) {
5102 $pictoType = 'varchar';
5103 } elseif (preg_match('/^integer:/', $proptype, $matches)) {
5104 $pictoType = 'link';
5105 } elseif (strpos($proptype, 'integer') === 0) {
5106 $pictoType = dol_substr($proptype, 0, 3);
5107 } elseif (strpos($proptype, 'timestamp') === 0) {
5108 $pictoType = 'datetime';
5109 } elseif (strpos($proptype, 'real') === 0) {
5110 $pictoType = 'double';
5111 } elseif (strpos($proptype, 'stars') === 0) {
5112 $pictoType = 'stars';
5113 }
5114 print(!empty($pictoType) ? getPictoForType($pictoType) : getPictoForType($proptype)).'<span title="'.dol_escape_htmltag($proptype).'">'.dol_escape_htmltag($proptype).'</span>';
5115 print '</td>';
5116 print '<td class="tdoverflowmax200">';
5117 if ($proparrayofkeyval) {
5118 print '<span title="'.dol_escape_htmltag(json_encode($proparrayofkeyval, JSON_UNESCAPED_UNICODE)).'">';
5119 print dol_escape_htmltag(json_encode($proparrayofkeyval, JSON_UNESCAPED_UNICODE));
5120 print '</span>';
5121 }
5122 print '</td>';
5123 print '<td class="center">';
5124 print dol_escape_htmltag($propnotnull);
5125 print '</td>';
5126 print '<td>';
5127 print dol_escape_htmltag($propdefault);
5128 print '</td>';
5129 print '<td class="center">';
5130 print $propindex ? '1' : '';
5131 print '</td>';
5132 print '<td class="center">';
5133 print $propforeignkey ? dol_escape_htmltag($propforeignkey) : '';
5134 print '</td>';
5135 print '<td class="right">';
5136 print dol_escape_htmltag($propposition);
5137 print '</td>';
5138 print '<td class="center tdoverflowmax100" title="'.($propnoteditable ? dol_escape_htmltag($propnoteditable) : '').'">';
5139 print $propenabled ? dol_escape_htmltag($propenabled) : '';
5140 print '</td>';
5141 // Visibility
5142 print '<td class="center tdoverflowmax100" title="'.($propvisible ? dol_escape_htmltag($propvisible) : '0').'">';
5143 print $propvisible ? dol_escape_htmltag($propvisible) : '0';
5144 print '</td>';
5145 // Readonly
5146 print '<td class="center tdoverflowmax100" title="'.($propnoteditable ? dol_escape_htmltag($propnoteditable) : '').'">';
5147 print $propnoteditable ? dol_escape_htmltag($propnoteditable) : '';
5148 print '</td>';
5149 /*print '<td class="center">';
5150 print $propalwayseditable ? dol_escape_htmltag($propalwayseditable) : '';
5151 print '</td>';*/
5152 print '<td class="center">';
5153 print $propsearchall ? '1' : '';
5154 print '</td>';
5155 print '<td class="center">';
5156 print $propisameasure ? dol_escape_htmltag($propisameasure) : '';
5157 print '</td>';
5158 print '<td class="center tdoverflowmax100" title="'.($propcss ? dol_escape_htmltag($propcss) : '').'">';
5159 print $propcss ? dol_escape_htmltag($propcss) : '';
5160 print '</td>';
5161 print '<td class="center tdoverflowmax100" title="'.($propcssview ? dol_escape_htmltag($propcssview) : '').'">';
5162 print $propcssview ? dol_escape_htmltag($propcssview) : '';
5163 print '</td>';
5164 print '<td class="center tdoverflowmax100" title="'.($propcsslist ? dol_escape_htmltag($propcsslist) : '').'">';
5165 print $propcsslist ? dol_escape_htmltag($propcsslist) : '';
5166 print '</td>';
5167 // Key for tooltop
5168 print '<td class="tdoverflowmax150" title="'.($prophelp ? dol_escape_htmltag($prophelp) : '').'">';
5169 print $prophelp ? dol_escape_htmltag($prophelp) : '';
5170 print '</td>';
5171 print '<td class="center">';
5172 print $propshowoncombobox ? dol_escape_htmltag($propshowoncombobox) : '';
5173 print '</td>';
5174 /*print '<td class="center">';
5175 print $propdisabled?$propdisabled:'';
5176 print '</td>';*/
5177 print '<td class="center">';
5178 print $propvalidate ? dol_escape_htmltag($propvalidate) : '';
5179 print '</td>';
5180 print '<td class="tdoverflowmax200">';
5181 print '<span title="'.dol_escape_htmltag($propcomment).'">';
5182 print dol_escape_htmltag($propcomment);
5183 print '</span>';
5184 print '</td>';
5185 if (empty($conf->main_checkbox_left_column)) {
5186 print '<td class="center minwidth75 tdstickyright tdstickyghostwhite">';
5187 if ($propname != 'rowid') {
5188 print '<a class="editfielda reposition marginleftonly marginrighttonly paddingright paddingleft" href="'.$_SERVER["PHP_SELF"].'?action=editproperty&token='.newToken().'&propertykey='.urlencode($propname).'&tab='.urlencode($tab).'&module='.urlencode($module).'&tabobj='.urlencode($tabobj).'">'.img_edit().'</a>';
5189 print '<a class="reposition marginleftonly marginrighttonly paddingright paddingleft" href="'.$_SERVER["PHP_SELF"].'?action=deleteproperty&token='.newToken().'&propertykey='.urlencode($propname).'&tab='.urlencode($tab).'&module='.urlencode($module).'&tabobj='.urlencode($tabobj).'">'.img_delete().'</a>';
5190 }
5191 print '</td>';
5192 }
5193 }
5194 print '</tr>';
5195 }
5196 } else {
5197 if ($tab == 'specifications') {
5198 if ($action != 'editfile' || empty($file)) {
5199 print '<span class="opacitymedium">'.$langs->trans("SpecDefDesc").'</span><br>';
5200 print '<br>';
5201
5202 $specs = dol_dir_list(dol_buildpath($modulelowercase.'/doc', 0), 'files', 1, '(\.md|\.asciidoc)$', array('\/temp\/'));
5203
5204 foreach ($specs as $spec) {
5205 $pathtofile = $modulelowercase.'/doc/'.$spec['relativename'];
5206 $format = 'asciidoc';
5207 if (preg_match('/\.md$/i', $spec['name'])) {
5208 $format = 'markdown';
5209 }
5210 print '<span class="fa fa-file"></span> '.$langs->trans("SpecificationFile").' : <strong class="wordbreak">'.$pathtofile.'</strong>';
5211 print ' <a href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format='.$format.'&file='.urlencode($pathtofile).'">'.img_picto($langs->trans("Edit"), 'edit').'</a>';
5212 print '<br>';
5213 }
5214 } else {
5215 // Use MD or asciidoc
5216
5217 //print $langs->trans("UseAsciiDocFormat").'<br>';
5218
5219 $fullpathoffile = dol_buildpath($file, 0);
5220
5221 $content = file_get_contents($fullpathoffile);
5222
5223 // New module
5224 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
5225 print '<input type="hidden" name="token" value="'.newToken().'">';
5226 print '<input type="hidden" name="action" value="savefile">';
5227 print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
5228 print '<input type="hidden" name="tab" value="'.$tab.'">';
5229 print '<input type="hidden" name="module" value="'.$module.'">';
5230
5231 $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%');
5232 print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'html'));
5233 print '<br>';
5234 print '<center>';
5235 print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
5236 print ' &nbsp; ';
5237 print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
5238 print '</center>';
5239
5240 print '</form>';
5241 }
5242 }
5243 $langs->load("errors");
5244 print '<tr><td><span class="warning">'.$langs->trans('ErrorModuleBuilderNoFieldProperty').'</warning></td></tr>';
5245 }
5246 print '</table>';
5247 print '</div>';
5248
5249 print '</form>';
5250 } else {
5251 $langs->load("errors");
5252 print '<span class="warning">'.$langs->trans('ErrorModuleBuilderFailedToInit', $tabobj, (string) $db).'</warning>';
5253 }
5254 } catch (Exception $e) {
5255 print 'ee';
5256 print $e->getMessage();
5257 print 'ff';
5258 }
5259 } else {
5260 if (empty($forceddirread)) {
5261 $fullpathoffile = dol_buildpath($file, 0);
5262 } else {
5263 $fullpathoffile = $dirread.'/'.$file;
5264 }
5265
5266 $content = file_get_contents($fullpathoffile);
5267
5268 // New module
5269 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
5270 print '<input type="hidden" name="token" value="'.newToken().'">';
5271 print '<input type="hidden" name="action" value="savefile">';
5272 print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
5273 print '<input type="hidden" name="tab" value="'.$tab.'">';
5274 print '<input type="hidden" name="tabobj" value="'.dol_escape_htmltag($tabobj).'">';
5275 print '<input type="hidden" name="module" value="'.$module.($forceddirread ? '@'.$dirread : '').'">';
5276
5277 $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%');
5278 print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'html'));
5279 print '<br>';
5280 print '<center>';
5281 print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
5282 print ' &nbsp; ';
5283 print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
5284 print '</center>';
5285
5286 print '</form>';
5287 }
5288 }
5289
5290 print dol_get_fiche_end(); // Level 3
5291 }
5292
5293 if ($tab == 'dictionaries') {
5294 print '<!-- tab=dictionaries -->'."\n";
5295 $pathtofile = $listofmodules[dol_strtolower($module)]['moduledescriptorrelpath'];
5296
5297 $dicts = $moduleobj->dictionaries;
5298
5299 if ($action == 'deletedict') {
5300 $formconfirm = $form->formconfirm(
5301 $_SERVER["PHP_SELF"].'?dictionnarykey='.urlencode((string) (GETPOSTINT('dictionnarykey'))).'&tab='.urlencode((string) ($tab)).'&module='.urlencode((string) ($module)),
5302 $langs->trans('Delete'),
5303 $langs->trans('Confirm Delete Dictionnary', GETPOST('dictionnarykey', 'alpha')),
5304 'confirm_deletedictionary',
5305 '',
5306 0,
5307 1
5308 );
5309 print $formconfirm;
5310 }
5311
5312 if ($action != 'editfile' || empty($file)) {
5313 print '<span class="opacitymedium">';
5314 $htmlhelp = $langs->trans("DictionariesDefDescTooltip", '{s1}');
5315 $htmlhelp = str_replace('{s1}', '<a target="adminbis" class="nofocusvisible" href="'.DOL_URL_ROOT.'/admin/dict.php">'.$langs->trans('Setup').' - '.$langs->trans('Dictionaries').'</a>', $htmlhelp);
5316 print $form->textwithpicto($langs->trans("DictionariesDefDesc"), $htmlhelp, 1, 'help', '', 0, 2, 'helpondesc').'<br>';
5317 print '</span>';
5318 print '<br>';
5319
5320 print '<span class="fa fa-file"></span> '.$langs->trans("DescriptorFile").' : <strong class="wordbreak">'.$pathtofile.'</strong>';
5321 print ' <a class="editfielda paddingleft paddingright" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format=php&file='.urlencode($pathtofile).'&find=DICTIONARIES">'.img_picto($langs->trans("Edit"), 'edit').'</a>';
5322 print '<br>';
5323 if (is_array($dicts) && !empty($dicts)) {
5324 print '<span class="fa fa-file"></span> '.$langs->trans("LanguageFile").' :</span> ';
5325 print '<strong class="wordbreak">'.$dicts['langs'].'</strong>';
5326 print '<br>';
5327 }
5328 print '<br>';
5329
5330 $head3 = array();
5331 $h = 0;
5332
5333 // Dir for module
5334 //$dir = $dirread.'/'.$modulelowercase.'/class';
5335
5336 $head3[$h][0] = $_SERVER["PHP_SELF"].'?tab=dictionaries&module='.$module.($forceddirread ? '@'.$dirread : '').'&tabdic=newdictionary';
5337 $head3[$h][1] = '<span class="valignmiddle text-plus-circle">'.$langs->trans("NewDictionary").'</span><span class="fa fa-plus-circle valignmiddle paddingleft"></span>';
5338 $head3[$h][2] = 'newdictionary';
5339 $h++;
5340
5341 // Scan for object class files
5342 //$listofobject = dol_dir_list($dir, 'files', 0, '\.class\.php$');
5343
5344 $firstdicname = '';
5345 // if (!empty($dicts['tabname'])) {
5346 // foreach ($dicts['tabname'] as $key => $dic) {
5347 // $dicname = $dic;
5348 // $diclabel = $dicts['tablib'][$key];
5349
5350 // if (empty($firstdicname)) {
5351 // $firstdicname = $dicname;
5352 // }
5353
5354 // $head3[$h][0] = $_SERVER["PHP_SELF"].'?tab=dictionaries&module='.$module.($forceddirread ? '@'.$dirread : '').'&tabdic='.$dicname;
5355 // $head3[$h][1] = $diclabel;
5356 // $head3[$h][2] = $dicname;
5357 // $h++;
5358 // }
5359 // }
5360
5361 // if ($h > 1) {
5362 // $head3[$h][0] = $_SERVER["PHP_SELF"].'?tab=dictionaries&module='.$module.($forceddirread ? '@'.$dirread : '').'&tabdic=deletedictionary';
5363 // $head3[$h][1] = $langs->trans("DangerZone");
5364 // $head3[$h][2] = 'deletedictionary';
5365 // $h++;
5366 // }
5367
5368 // 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.
5369 // if ($tabdic == 'newdicifnodic') {
5370 // if ($firstdicname) {
5371 // $tabdic = $firstdicname;
5372 // } else {
5373 // $tabdic = 'newdictionary';
5374 // }
5375 // }
5376 //print dol_get_fiche_head($head3, $tabdic, '', -1, ''); // Level 3
5377
5378
5379 $newdict = dolGetButtonTitle($langs->trans('NewDictionary'), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/modulebuilder/index.php?tab=dictionaries&module='.urlencode($module).'&tabdic=newdictionary');
5380 print_barre_liste($langs->trans("ListOfDictionariesEntries"), 0, $_SERVER["PHP_SELF"], '', '', '', '', 0, '', '', 0, $newdict, '', 0, 0, 0, 1);
5381
5382 if ($tabdic != 'newdictionary') {
5383 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
5384 print '<input type="hidden" name="token" value="'.newToken().'">';
5385 print '<input type="hidden" name="action" value="addDictionary">';
5386 print '<input type="hidden" name="tab" value="dictionaries">';
5387 print '<input type="hidden" name="module" value="'.dol_escape_htmltag($module).'">';
5388 print '<input type="hidden" name="tabdic" value="'.dol_escape_htmltag($tabdic).'">';
5389
5390 print '<div class="div-table-responsive">';
5391 print '<table class="noborder">';
5392
5393 print '<tr class="liste_titre">';
5394 print_liste_field_titre("#", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, 'thsticky thstickygrey ');
5395 print_liste_field_titre("Table", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
5396 print_liste_field_titre("Label", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
5397 print_liste_field_titre("SQL", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
5398 print_liste_field_titre("SQLSort", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
5399 print_liste_field_titre("FieldsView", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
5400 print_liste_field_titre("FieldsEdit", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
5401 print_liste_field_titre("FieldsInsert", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
5402 print_liste_field_titre("Rowid", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
5403 print_liste_field_titre("Condition", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
5404 print_liste_field_titre("", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
5405 print "</tr>\n";
5406
5407 if (!empty($dicts) && is_array($dicts) && !empty($dicts['tabname']) && is_array($dicts['tabname'])) {
5408 $i = 0;
5409 $maxi = count($dicts['tabname']);
5410 while ($i < $maxi) {
5411 if ($action == 'editdict' && $i == GETPOSTINT('dictionnarykey') - 1) {
5412 print '<tr class="oddeven">';
5413 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
5414 print '<input type="hidden" name="token" value="'.newToken().'">';
5415 print '<input type="hidden" name="tab" value="dictionaries">';
5416 print '<input type="hidden" name="module" value="'.dol_escape_htmltag($module).'">';
5417 print '<input type="hidden" name="action" value="updatedictionary">';
5418 print '<input type="hidden" name="dictionnarykey" value="'.($i + 1).'">';
5419
5420 print '<td class="tdsticky tdstickygray">';
5421 print($i + 1);
5422 print '</td>';
5423
5424 print '<td>';
5425 print '<input type="text" name="tabname" value="'.$dicts['tabname'][$i].'" readonly class="tdstickygray">';
5426 print '</td>';
5427
5428 print '<td>';
5429 print '<input type="text" name="tablib" value="'.$dicts['tablib'][$i].'">';
5430 print '</td>';
5431
5432 print '<td>';
5433 print '<input type="text" name="tabsql" value="'.$dicts['tabsql'][$i].'" readonly class="tdstickygray">';
5434 print '</td>';
5435
5436 print '<td>';
5437 print '<select name="tabsqlsort">';
5438 print '<option value="'.dol_escape_htmltag($dicts['tabsqlsort'][$i]).'">'.$dicts['tabsqlsort'][$i].'</option>';
5439 print '</select>';
5440 print '</td>';
5441
5442 print '<td><select name="tabfield" >';
5443 print '<option value="'.dol_escape_htmltag($dicts['tabfield'][$i]).'">'.$dicts['tabfield'][$i].'</option>';
5444 print '</select></td>';
5445
5446 print '<td><select name="tabfieldvalue" >';
5447 print '<option value="'.dol_escape_htmltag($dicts['tabfieldvalue'][$i]).'">'.$dicts['tabfieldvalue'][$i].'</option>';
5448 print '</select></td>';
5449
5450 print '<td><select name="tabfieldinsert" >';
5451 print '<option value="'.dol_escape_htmltag($dicts['tabfieldinsert'][$i]).'">'.$dicts['tabfieldinsert'][$i].'</option>';
5452 print '</select></td>';
5453
5454 print '<td>';
5455 print '<input type="text" name="tabrowid" value="'.dol_escape_htmltag($dicts['tabrowid'][$i]).'" readonly class="tdstickygray">';
5456 print '</td>';
5457
5458 print '<td>';
5459 print '<input type="text" name="tabcond" value="'.dol_escape_htmltag((empty($dicts['tabcond'][$i]) ? 'disabled' : 'enabled')).'" readonly class="tdstickygray">';
5460 print '</td>';
5461
5462 print '<td class="center minwidth75 tdstickyright tdstickyghostwhite">';
5463 print '<input id ="updatedict" class="reposition button smallpaddingimp" type="submit" name="updatedict" value="'.$langs->trans("Modify").'"/>';
5464 print '<br>';
5465 print '<input class="reposition button button-cancel smallpaddingimp" type="submit" name="cancel" value="'.$langs->trans("Cancel").'"/>';
5466 print '</td>';
5467
5468 print '</form>';
5469 print '</tr>';
5470 } else {
5471 print '<tr class="oddeven">';
5472
5473 print '<td class="tdsticky tdstickygray">';
5474 print($i + 1);
5475 print '</td>';
5476
5477 print '<td>';
5478 print $dicts['tabname'][$i];
5479 print '</td>';
5480
5481 print '<td>';
5482 print $dicts['tablib'][$i];
5483 print '</td>';
5484
5485 print '<td>';
5486 print $dicts['tabsql'][$i];
5487 print '</td>';
5488
5489 print '<td>';
5490 print $dicts['tabsqlsort'][$i];
5491 print '</td>';
5492
5493 print '<td>';
5494 print $dicts['tabfield'][$i];
5495 print '</td>';
5496
5497 print '<td>';
5498 print $dicts['tabfieldvalue'][$i];
5499 print '</td>';
5500
5501 print '<td>';
5502 print $dicts['tabfieldinsert'][$i];
5503 print '</td>';
5504
5505 print '<td >';
5506 print $dicts['tabrowid'][$i];
5507 print '</td>';
5508
5509 print '<td >';
5510 print $dicts['tabcond'][$i];
5511 print '</td>';
5512
5513 print '<td class="center minwidth75 tdstickyright tdstickyghostwhite">';
5514 print '<a class="editfielda reposition marginleftonly marginrighttonly paddingright paddingleft" href="'.$_SERVER["PHP_SELF"].'?action=editdict&token='.newToken().'&dictionnarykey='.urlencode((string) ($i + 1)).'&tab='.urlencode((string) ($tab)).'&module='.urlencode((string) ($module)).'">'.img_edit().'</a>';
5515 print '<a class="marginleftonly marginrighttonly paddingright paddingleft" href="'.$_SERVER["PHP_SELF"].'?action=deletedict&token='.newToken().'&dictionnarykey='.urlencode((string) ($i + 1)).'&tab='.urlencode((string) ($tab)).'&module='.urlencode((string) ($module)).'">'.img_delete().'</a>';
5516 print '</td>';
5517
5518 print '</tr>';
5519 }
5520 $i++;
5521 }
5522 } else {
5523 print '<tr><td colspan="11"><span class="opacitymedium">'.$langs->trans("None").'</span></td></tr>';
5524 }
5525
5526 print '</table>';
5527 print '</div>';
5528
5529 print '</form>';
5530 }
5531
5532 if ($tabdic == 'newdictionary') {
5533 // New dic tab
5534 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
5535 print '<input type="hidden" name="token" value="'.newToken().'">';
5536 print '<input type="hidden" name="action" value="initdic">';
5537 print '<input type="hidden" name="tab" value="dictionaries">';
5538 print '<input type="hidden" name="tabdic" value="'.$tabdic.'">';
5539
5540 print '<input type="hidden" name="module" value="'.dol_escape_htmltag($module).'">';
5541
5542 print '<span class="opacitymedium">'.$langs->trans("EnterNameOfDictionaryDesc").'</span><br><br>';
5543
5544 print dol_get_fiche_head();
5545 print '<table class="border centpercent">';
5546 print '<tbody>';
5547 print '<tr><td class="titlefieldcreate fieldrequired">'.$langs->trans("Table").'</td><td><input type="text" name="dicname" maxlength="64" value="'.dol_escape_htmltag(GETPOST('dicname', 'alpha') ? GETPOST('dicname', 'alpha') : $modulename).'" placeholder="'.dol_escape_htmltag($langs->trans("DicKey")).'" autofocus></td>';
5548 print '<tr><td class="titlefieldcreate fieldrequired">'.$langs->trans("Label").'</td><td><input type="text" name="label" value="'.dol_escape_htmltag(GETPOST('label', 'alpha')).'"></td></tr>';
5549 print '<tr><td class="titlefieldcreate">'.$langs->trans("SQL").'</td><td><input type="text" style="width:50%;" name="sql" value="'.dol_escape_htmltag(GETPOST('sql', 'alpha')).'"></td></tr>';
5550 print '<tr><td class="titlefieldcreate">'.$langs->trans("SQLSort").'</td><td><input type="text" name="sqlsort" value="'.dol_escape_htmltag(GETPOST('sqlsort', 'alpha')).'" readonly></td></tr>';
5551 print '<tr><td class="titlefieldcreate">'.$langs->trans("FieldsView").'</td><td><input type="text" name="field" value="'.dol_escape_htmltag(GETPOST('field', 'alpha')).'"></td></tr>';
5552 print '<tr><td class="titlefieldcreate">'.$langs->trans("FieldsEdit").'</td><td><input type="text" name="fieldvalue" value="'.dol_escape_htmltag(GETPOST('fieldvalue', 'alpha')).'"></td></tr>';
5553 print '<tr><td class="titlefieldcreate">'.$langs->trans("FieldsInsert").'</td><td><input type="text" name="fieldinsert" value="'.dol_escape_htmltag(GETPOST('fieldinsert', 'alpha')).'"></td></tr>';
5554 print '<tr><td class="titlefieldcreate">'.$langs->trans("Rowid").'</td><td><input type="text" name="rowid" value="'.dol_escape_htmltag(GETPOST('rowid', 'alpha')).'"></td></tr>';
5555 print '<tr></tr>';
5556 print '</tbody></table>';
5557 print '<input type="submit" class="button" name="create" value="'.dol_escape_htmltag($langs->trans("GenerateCode")).'"'.($dirins ? '' : ' disabled="disabled"').'>';
5558 print '<input id="cancel" type="submit" class="button" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
5559 print dol_get_fiche_end();
5560 print '</form>';
5561 print '<script>
5562 $(document).ready(function() {
5563 $("input[name=\'dicname\']").on("blur", function() {
5564 if ($(this).val().length > 0) {
5565 $("input[name=\'label\']").val($(this).val());
5566 $("input[name=\'sql\']").val("SELECT f.rowid as rowid, f.code, f.label, f.active FROM llx_c_" + $(this).val() + " as f");
5567 $("input[name=\'sqlsort\']").val("label ASC");
5568 $("input[name=\'field\']").val("code,label");
5569 $("input[name=\'fieldvalue\']").val("code,label");
5570 $("input[name=\'fieldinsert\']").val("code,label");
5571 $("input[name=\'rowid\']").val("rowid");
5572 } else {
5573 $("input[name=\'label\']").val("");
5574 $("input[name=\'sql\']").val("");
5575 $("input[name=\'sqlsort\']").val("");
5576 $("input[name=\'field\']").val("");
5577 $("input[name=\'fieldvalue\']").val("");
5578 $("input[name=\'fieldinsert\']").val("");
5579 $("input[name=\'rowid\']").val("");
5580 }
5581 });
5582 $("input[id=\'cancel\']").click(function() {
5583 window.history.back();
5584 });
5585 });
5586 </script>';
5587
5588 /*print '<br>';
5589 print '<br>';
5590 print '<br>';
5591 print '<span class="opacitymedium">'.$langs->trans("or").'</span>';
5592 print '<br>';
5593 print '<br>';
5594 //print '<input type="checkbox" name="initfromtablecheck"> ';
5595 print $langs->trans("InitStructureFromExistingTable");
5596 print '<input type="text" name="initfromtablename" value="" placeholder="'.$langs->trans("TableName").'">';
5597 print '<input type="submit" class="button smallpaddingimp" name="createtablearray" value="'.dol_escape_htmltag($langs->trans("GenerateCode")).'"'.($dirins ? '' : ' disabled="disabled"').'>';
5598 print '<br>';
5599 */
5600 } elseif ($tabdic == 'deletedictionary') {
5601 // Delete dic tab
5602 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
5603 print '<input type="hidden" name="token" value="'.newToken().'">';
5604 print '<input type="hidden" name="action" value="confirm_deletedictionary">';
5605 print '<input type="hidden" name="tab" value="dictionaries">';
5606 print '<input type="hidden" name="module" value="'.dol_escape_htmltag($module).'">';
5607
5608 print $langs->trans("EnterNameOfDictionnaryToDeleteDesc").'<br><br>';
5609
5610 print '<input type="text" name="dicname" value="'.dol_escape_htmltag($modulename).'" placeholder="'.dol_escape_htmltag($langs->trans("DicKey")).'">';
5611 print '<input type="submit" class="button smallpaddingimp" name="delete" value="'.dol_escape_htmltag($langs->trans("Delete")).'"'.($dirins ? '' : ' disabled="disabled"').'>';
5612 print '</form>';
5613 }
5614
5615 print dol_get_fiche_end();
5616 } else {
5617 $fullpathoffile = dol_buildpath($file, 0);
5618
5619 $content = file_get_contents($fullpathoffile);
5620
5621 // New module
5622 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
5623 print '<input type="hidden" name="token" value="'.newToken().'">';
5624 print '<input type="hidden" name="action" value="savefile">';
5625 print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
5626 print '<input type="hidden" name="tab" value="'.$tab.'">';
5627 print '<input type="hidden" name="module" value="'.$module.'">';
5628
5629 $posCursor = (empty($find)) ? array() : array('find' => $find);
5630 $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%', 0, $posCursor);
5631 print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'html'));
5632 print '<br>';
5633 print '<center>';
5634 print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
5635 print ' &nbsp; ';
5636 print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
5637 print '</center>';
5638
5639 print '</form>';
5640 }
5641 }
5642
5643 if ($tab == 'menus') {
5644 print '<!-- tab=menus -->'."\n";
5645 $pathtofile = $listofmodules[dol_strtolower($module)]['moduledescriptorrelpath'];
5646 $dirins = $listofmodules[dol_strtolower($module)]['moduledescriptorrootpath'];
5647 $destdir = $dirins.'/'.dol_strtolower($module);
5648 $listofobject = dol_dir_list($destdir.'/class', 'files', 0, '\.class\.php$');
5649 $objects = dolGetListOfObjectClasses($destdir);
5650
5651 $leftmenus = array();
5652
5653 $menus = $moduleobj->menu;
5654
5655 $permissions = $moduleobj->rights;
5656 $crud = array('read' => 'CRUDRead', 'write' => 'CRUDCreateWrite', 'delete' => 'Delete');
5657
5658 //grouped permissions
5659 $groupedRights = array();
5660 foreach ($permissions as $right) {
5661 $key = $right[4];
5662 if (!isset($groupedRights[$key])) {
5663 $groupedRights[$key] = array();
5664 }
5665 $groupedRights[$key][] = $right;
5666 }
5667 $groupedRights_json = json_encode($groupedRights);
5668
5669 if ($action == 'deletemenu') {
5670 $formconfirms = $form->formconfirm(
5671 $_SERVER["PHP_SELF"].'?menukey='.urlencode((string) (GETPOSTINT('menukey'))).'&tab='.urlencode((string) ($tab)).'&module='.urlencode((string) ($module)),
5672 $langs->trans('Delete'),
5673 ($menus[GETPOST('menukey')]['fk_menu'] === 'fk_mainmenu='.dol_strtolower($module) ? $langs->trans('Warning: you will delete all menus linked to this one.', GETPOSTINT('menukey')) : $langs->trans('Confirm Delete Menu', GETPOSTINT('menukey'))),
5674 'confirm_deletemenu',
5675 '',
5676 0,
5677 1
5678 );
5679 print $formconfirms;
5680 }
5681 if ($action != 'editfile' || empty($file)) {
5682 print '<span class="opacitymedium">';
5683 $htmlhelp = $langs->trans("MenusDefDescTooltip", '{s1}');
5684 $htmlhelp = str_replace('{s1}', '<a target="adminbis" class="nofocusvisible" href="'.DOL_URL_ROOT.'/admin/menus/index.php">'.$langs->trans('Setup').' - '.$langs->trans('Menus').'</a>', $htmlhelp);
5685 print $form->textwithpicto($langs->trans("MenusDefDesc"), $htmlhelp, 1, 'help', '', 0, 2, 'helpondesc').'<br>';
5686 print '</span>';
5687 print '<br>';
5688
5689 // Links to editable files
5690 print '<span class="fa fa-file"></span> '.$langs->trans("DescriptorFile").' : <strong class="wordbreak">'.$pathtofile.'</strong>';
5691 print ' <a class="editfielda paddingleft paddingright" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format=php&file='.urlencode($pathtofile).'&find=TOPMENU">'.img_picto($langs->trans("Edit"), 'edit').'</a>';
5692 print '<br>';
5693
5694 // Search all files of modules mentioned by menu
5695 $listODifferentUrlsInMenu = array();
5696 foreach ($menus as $obj) {
5697 if (preg_match('/^\/'.preg_quote(dol_strtolower($module), '/').'\//', $obj['url']) && !empty($pathoffile)) {
5698 if (!empty($listODifferentUrlsInMenu[$pathoffile])) { // Test to avoid to show same file twice.
5699 continue;
5700 }
5701 $pathtofile = $obj['url'];
5702 $listODifferentUrlsInMenu[$pathoffile] = $pathtofile;
5703 print '<span class="fa fa-file"></span> '.$langs->trans("PageLinkedByAMenuEntry").' : <strong class="wordbreak">'.$pathtofile.'</strong>';
5704 print ' <a class="editfielda paddingleft paddingright" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format=php&file='.urlencode($pathtofile).'&find=TOPMENU">'.img_picto($langs->trans("Edit"), 'edit').'</a>';
5705 print '<br>';
5706 }
5707 }
5708
5709
5710 print '<br>';
5711 print load_fiche_titre($langs->trans("ListOfMenusEntries"), '', '');
5712
5713 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
5714 print '<input type="hidden" name="token" value="'.newToken().'">';
5715 print '<input type="hidden" name="action" value="addmenu">';
5716 print '<input type="hidden" name="tab" value="menus">';
5717 print '<input type="hidden" name="module" value="'.dol_escape_htmltag($module).'">';
5718 print '<input type="hidden" name="tabobj" value="'.dol_escape_htmltag($tabobj).'">';
5719
5720 print '<div class="div-table-responsive">';
5721 print '<table class="noborder small">';
5722
5723 $htmltextenabled = '<u>'.$langs->trans("Examples").':</u><br>';
5724 $htmltextenabled .= '1 <span class="opacitymedium">(module always enabled)</span><br>';
5725 $htmltextenabled .= '0 <span class="opacitymedium">(module always disabled)</span><br>';
5726 $htmltextenabled .= 'isModEnabled(\''.dol_escape_htmltag(dol_strtolower($module)).'\') <span class="opacitymedium">(enabled when module is enabled)</span>';
5727 $htmltextperms = '<u>'.$langs->trans("Examples").':</u><br>';
5728 $htmltextperms .= '1 <span class="opacitymedium">(access always allowed)</span><br>';
5729 $htmltextperms .= '$user->hasright(\''.dol_escape_htmltag(dol_strtolower($module)).'\', \'myobject\', \'read\') <span class="opacitymedium">(access allowed if user has permission module->object->read)</span>';
5730
5731 print '<tr class="liste_titre">';
5732 print_liste_field_titre("#", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, 'center tdsticky tdstickygray ');
5733 print_liste_field_titre("Position", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
5734 print_liste_field_titre("Title", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, 'center');
5735 print_liste_field_titre("LinkToParentMenu", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, 'minwidth100 ');
5736 print_liste_field_titre("mainmenu", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
5737 print_liste_field_titre("leftmenu", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
5738 print_liste_field_titre("URL", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, '', $langs->transnoentitiesnoconv('DetailUrl'));
5739 print_liste_field_titre("LanguageFile", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
5740 print_liste_field_titre("Position", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, 'right ');
5741 print_liste_field_titre("Enabled", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, 'center ', $langs->trans('DetailEnabled').'<br><br>'.$htmltextenabled);
5742 print_liste_field_titre("Rights", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, '', $langs->trans('DetailRight').'<br><br>'.$htmltextperms);
5743 print_liste_field_titre("Target", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, '', $langs->trans('DetailTarget'));
5744 print_liste_field_titre("MenuForUsers", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, 'center minwidth100 ', $langs->trans('DetailUser'));
5745 print_liste_field_titre("", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, 'center ', $langs->trans(''));
5746 print "</tr>\n";
5747
5748 $r = count($menus) + 1;
5749 // for adding menu on module
5750 print '<tr>';
5751 print '<td class="center tdsticky tdstickygray"><input type="hidden" readonly class="center maxwidth50" name="propenabled" value="#"></td>';
5752 print '<td class="center">';
5753 print '<select class="maxwidth50" name="type">';
5754 print '<option value="">'.$langs->trans("........").'</option><option value="'.dol_escape_htmltag("left").'">left</option><option value="'.dol_escape_htmltag("top").'">top</option>';
5755 print '</select></td>';
5756 print '<td class="left"><input type="text" class="left maxwidth100" name="titre" value="'.dol_escape_htmltag(GETPOST('titre', 'alpha')).'"></td>';
5757 print '<td class="left">';
5758 print '<select name="fk_menu">';
5759 print '<option value="">'.$langs->trans("........").'</option>';
5760 foreach ($menus as $obj) {
5761 if ($obj['type'] == 'left' && !empty($obj['leftmenu'])) {
5762 print "<option value=".dol_strtolower($obj['leftmenu']).">".$obj['leftmenu']."</option>";
5763 }
5764 }
5765 print '</select>';
5766 print '</td>';
5767 print '<td class="left"><input type="text" class="left maxwidth50" name="mainmenu" value="'.(empty(GETPOST('mainmenu')) ? dol_strtolower($module) : dol_escape_htmltag(GETPOST('mainmenu', 'alpha'))).'"></td>';
5768 print '<td class="center"><input id="leftmenu" type="text" class="left maxwidth50" name="leftmenu" value="'.dol_escape_htmltag(GETPOST('leftmenu', 'alpha')).'"></td>';
5769 // URL
5770 print '<td class="left"><input id="url" type="text" class="left maxwidth100" name="url" value="'.dol_escape_htmltag(GETPOST('url', 'alpha')).'"></td>';
5771 print '<td class="left"><input type="text" class="left maxwidth75" name="langs" value="'.dol_strtolower($module).'@'.dol_strtolower($module).'" readonly></td>';
5772 // Position
5773 print '<td class="center"><input type="text" class="center maxwidth50 tdstickygray" name="position" value="'.(1000 + $r).'" readonly></td>';
5774 // Enabled
5775 print '<td class="center">';
5776 print '<input type="enabled" class="maxwidth125" value="'.dol_escape_htmltag(GETPOSTISSET('enabled') ? GETPOST('enabled') : 'isModEnabled(\''.$module.'\')').'">';
5777 /*
5778 print '<select class="maxwidth" name="enabled">';
5779 print '<option value="1" selected>'.$langs->trans("Show").'</option>';
5780 print '<option value="0">'.$langs->trans("Hide").'</option>';
5781 print '</select>';
5782 */
5783 print '</td>';
5784 // Perms
5785 print '<td class="left">';
5786 print '<select class="maxwidth" name="objects" id="objects">';
5787 print '<option value=""></option>';
5788 if (is_array($objects)) {
5789 foreach ($objects as $value) {
5790 print '<option value="'.dol_strtolower($value).'">'.dol_escape_htmltag(dol_strtolower($value)).'</option>';
5791 }
5792 }
5793 print '</select>';
5794 print '<select class="maxwidth hideobject" name="perms" id="perms">';
5795 print '</select>';
5796 print '</td>';
5797 print '<td class="center"><input type="text" class="center maxwidth50" name="target" value="'.dol_escape_htmltag(GETPOST('target', 'alpha')).'"></td>';
5798 print '<td class="center"><select class="maxwidth10" name="user"><option value="2">'.$langs->trans("AllMenus").'</option><option value="0">'.$langs->trans("Internal").'</option><option value="1">'.$langs->trans("External").'</option></select></td>';
5799
5800 print '<td class="center minwidth75 tdstickyright tdstickyghostwhite">';
5801 print '<input type="submit" class="button" name="add" value="'.$langs->trans("Add").'">';
5802 print '</td>';
5803 print '</tr>';
5804 // end form for add menu
5805
5806 //var_dump($menus);
5807
5808 // Loop on each menu entry
5809 if (count($menus)) {
5810 $i = 0;
5811 foreach ($menus as $menu) {
5812 $i++;
5813 //for get parent in menu
5814 $string = dol_escape_htmltag($menu['fk_menu']);
5815 $value = dol_substr($string, strpos($string, 'fk_leftmenu=') + dol_strlen('fk_leftmenu='));
5816
5817 $propFk_menu = !empty($menu['fk_menu']) ? $menu['fk_menu'] : GETPOST('fk_menu');
5818 $propTitre = !empty($menu['titre']) ? $menu['titre'] : GETPOST('titre');
5819 $propMainmenu = !empty($menu['mainmenu']) ? $menu['mainmenu'] : GETPOST('mainmenu');
5820 $propLeftmenu = !empty($menu['leftmenu']) ? $menu['leftmenu'] : GETPOST('leftmenu');
5821 $propUrl = !empty($menu['url']) ? $menu['url'] : GETPOST('url', 'alpha');
5822 $propPerms = !empty($menu['perms']) ? $menu['perms'] : GETPOST('perms');
5823 $propUser = !empty($menu['user']) ? $menu['user'] : GETPOST('user');
5824 $propTarget = !empty($menu['target']) ? $menu['target'] : GETPOST('target');
5825 $propEnabled = !empty($menu['enabled']) ? $menu['enabled'] : GETPOST('enabled');
5826
5827 $objPerms = (empty($arguments[1]) ? '' : trim($arguments[1]));
5828 $valPerms = (empty($arguments[2]) ? '' : trim($arguments[2]));
5829
5830 //$tabobject = ''; // We can't know what is $tabobject in most cases
5831
5832 if ($action == 'editmenu' && GETPOSTINT('menukey') == $i) {
5833 //var_dump($propPerms);exit;
5834 print '<tr class="oddeven">';
5835 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
5836 print '<input type="hidden" name="token" value="'.newToken().'">';
5837 print '<input type="hidden" name="action" value="update_menu">';
5838 print '<input type="hidden" name="tab" value="menus">';
5839 print '<input type="hidden" name="module" value="'.dol_escape_htmltag($module).'">';
5840 print '<input type="hidden" name="menukey" value="'.$i.'"/>';
5841 //print '<input type="hidden" name="tabobject" value="'.dol_escape_htmltag($tabobject).'">';
5842 print '<td class="tdsticky tdstickygray">';
5843 print $i;
5844 print '</td>';
5845 // Position (top, left)
5846 print '<td class="center">
5847 <select class="center maxwidth50" name="type">
5848 <option value="'.dol_escape_htmltag($menu['type']).'">
5849 '.dol_escape_htmltag($menu['type']).'
5850 </option>';
5851 print '<option value="'.($menu['type'] == 'left' ? 'top' : 'left').'">';
5852 if ($menu['type'] == 'left') {
5853 print 'top';
5854 } else {
5855 print 'left';
5856 }
5857 print '</option></select></td>';
5858 // Title
5859 print '<td><input type="text" class="left maxwidth100" name="titre" value="'.dol_escape_htmltag($propTitre).'"></td>';
5860 // Parent menu
5861 print '<td>';
5862 /*print '<select name="fk_menu" class="left maxwidth">';
5863 print '<option value="'.dol_escape_htmltag($propFk_menu).'">'.dol_escape_htmltag($value).'</option>';
5864 foreach ($menus as $obj) {
5865 if ($obj['type'] == 'left' && $obj['leftmenu'] != $value && $obj['leftmenu'] != $menu['leftmenu']) {
5866 print "<option value=".dol_strtolower($obj['leftmenu']).">".$obj['leftmenu']."</option>";
5867 }
5868 }
5869 print '</select>';*/
5870 print '<input type="text" name="fk_menu" class="maxwidth150" value="'.dol_escape_htmltag($propFk_menu).'">';
5871 print '</td>';
5872 print '<td><input type="text" class="left maxwidth50" name="mainmenu" value="'.dol_escape_htmltag($propMainmenu).'" readonly></td>';
5873 print '<td><input type="text" class="left maxwidth50" name="leftmenu" value="'.dol_escape_htmltag($propLeftmenu).'" readonly></td>';
5874 // URL
5875 print '<td><input type="text" class="left maxwidth250" name="url" value="'.dol_escape_htmltag($propUrl).'"></td>';
5876 print '<td><input type="text" class="left maxwidth50" name="langs" value="'.dol_strtolower($module).'@'.dol_strtolower($module).'" readonly></td>';
5877 // Position
5878 print '<td class="center"><input type="text" class="center maxwidth50 tdstickygray" name="position" value="'.($menu['position']).'" readonly></td>';
5879 // Enabled
5880 print '<td class="nowraponall">';
5881 print '<input type="text" class="maxwidth125" name="enabled" value="'.dol_escape_htmltag($propEnabled != '' ? $propEnabled : "isModEnabled('".dol_escape_htmltag($module)."')").'">';
5882 $htmltext = '<u>'.$langs->trans("Examples").':</u><br>';
5883 $htmltext .= '1 <span class="opacitymedium">(always enabled)</span><br>';
5884 $htmltext .= '0 <span class="opacitymedium">(always disabled)</span><br>';
5885 $htmltext .= 'isModEnabled(\''.dol_escape_htmltag($module).'\') <span class="opacitymedium">(enabled when module is enabled)</span><br>';
5886 print $form->textwithpicto('', $htmltext);
5887 /*
5888 print '<select class="maxwidth50" name="enabledselect">';
5889 print '<option value="1">1 (always enabled)</option>';
5890 print '<option value="0">0 (always disabled)</option>';
5891 print '<option value="isModEnabled(\''.dol_escape_htmltag($module).'\')" >isModEnabled(\''.dol_escape_htmltag($module).'\')</option>';
5892 print '</select>';
5893 */
5894 print '</td>';
5895 // Permissions
5896 print '<td class="nowraponall">';
5897 print '<input type="text" name="perms" value="'.dol_escape_htmltag($propPerms).'">';
5898 /*
5899 if (!empty($objPerms)) {
5900 print '<input type="hidden" name="objects" value="'.$objPerms.'" />';
5901 print '<select class="center maxwidth50" name="perms">';
5902 if (!empty($valPerms)) {
5903 print '<option selected value="'.dol_escape_htmltag($valPerms).'">'.dol_escape_htmltag($langs->trans($crud[$valPerms])).'</option>';
5904 foreach ($crud as $key => $val) {
5905 if ($valPerms != $key) {
5906 print '<option value="'.dol_escape_htmltag($key).'">'.dol_escape_htmltag($langs->trans($val)).'</option>';
5907 }
5908 }
5909 }
5910 print '</select>';
5911 } else {
5912 print '<select class="center maxwidth50" name="objects">';
5913 print '<option></option>';
5914 foreach ($objects as $obj) {
5915 print '<option value="'.dol_escape_htmltag(dol_strtolower($obj)).'">'.dol_escape_htmltag($obj).'</option>';
5916 }
5917 print '</select>';
5918 print '<select class="center maxwidth50" name="perms">';
5919 foreach ($crud as $key => $val) {
5920 print '<option value="'.dol_escape_htmltag($key).'">'.dol_escape_htmltag($key).'</option>';
5921 }
5922 print '</select>';
5923 }*/
5924 print '</td>';
5925 // Target
5926 print '<td class="center"><input type="text" class="center maxwidth50" name="target" value="'.dol_escape_htmltag($propTarget).'"></td>';
5927 print '<td class="center"><select class="center maxwidth10" name="user"><option value="2">'.$langs->trans("AllMenus").'</option><option value="0">'.$langs->trans("Internal").'</option><option value="1">'.$langs->trans("External").'</option></select></td>';
5928 print '<td class="center minwidth75 tdstickyright tdstickyghostwhite maxwidth75">';
5929 print '<input class="reposition button smallpaddingimp" type="submit" name="edit" value="'.$langs->trans("Modify").'">';
5930 print '<input class="reposition button button-cancel smallpaddingimp" type="submit" name="cancel" value="'.$langs->trans("Cancel").'">';
5931 print '</td>';
5932 print '</form>';
5933 print '</tr>';
5934 } else {
5935 print '<tr class="oddeven">';
5936
5937 print '<td class="tdsticky tdstickygray">';
5938 print $i;
5939 print '</td>';
5940
5941 print '<td class="center">';
5942 print dol_escape_htmltag($menu['type']);
5943 print '</td>';
5944
5945 // Title
5946 print '<td>';
5947 print dol_escape_htmltag($menu['titre']);
5948 print '</td>';
5949
5950 // Parent menu
5951 print '<td class="tdoverflowmax100" title="'.dol_escape_htmltag($menu['fk_menu']).'">';
5952 print dol_escape_htmltag($menu['fk_menu']);
5953 print '</td>';
5954
5955 print '<td>';
5956 print dol_escape_htmltag($menu['mainmenu']);
5957 print '</td>';
5958
5959 print '<td>';
5960 print dol_escape_htmltag($menu['leftmenu']);
5961 print '</td>';
5962
5963 print '<td class="tdoverflowmax250" title="'.dol_escape_htmltag($menu['url']).'">';
5964 print dol_escape_htmltag($menu['url']);
5965 print '</td>';
5966
5967 print '<td>';
5968 print dol_escape_htmltag($menu['langs']);
5969 print '</td>';
5970
5971 // Position
5972 print '<td class="center">';
5973 print dol_escape_htmltag((string) $menu['position']);
5974 print '</td>';
5975
5976 // Enabled
5977 print '<td class="tdoverflowmax200" title="'.dol_escape_htmltag($menu['enabled']).'">';
5978 print dol_escape_htmltag($menu['enabled']);
5979 print '</td>';
5980
5981 // Perms
5982 print '<td class="tdoverflowmax200" title="'.dol_escape_htmltag($menu['perms']).'">';
5983 print dol_escape_htmltag($langs->trans($menu['perms']));
5984 print '</td>';
5985
5986 // Target
5987 print '<td class="center tdoverflowmax200" title="'.dol_escape_htmltag($menu['target']).'">';
5988 print dol_escape_htmltag($menu['target']);
5989 print '</td>';
5990
5991 print '<td class="center">';
5992 if ($menu['user'] == 2) {
5993 print $langs->trans("AllMenus");
5994 } elseif ($menu['user'] == 0) {
5995 print $langs->trans('Internal');
5996 } elseif ($menu['user'] == 1) {
5997 print $langs->trans('External');
5998 } else {
5999 print $menu['user']; // should not happen
6000 }
6001 print '</td>';
6002 print '<td class="center minwidth75 tdstickyright tdstickyghostwhite">';
6003 if ($menu['titre'] != 'Module'.$module.'Name') {
6004 print '<a class="editfielda reposition marginleftonly marginrighttonly paddingright paddingleft" href="'.$_SERVER["PHP_SELF"].'?action=editmenu&token='.newToken().'&menukey='.urlencode((string) ($i)).'&tab='.urlencode((string) ($tab)).'&module='.urlencode((string) ($module)).'&tabobj='.urlencode((string) ($tabobj)).'">'.img_edit().'</a>';
6005 print '<a class="deletefielda reposition marginleftonly marginrighttonly paddingright paddingleft" href="'.$_SERVER["PHP_SELF"].'?action=deletemenu&token='.newToken().'&menukey='.urlencode((string) ($i - 1)).'&tab='.urlencode((string) ($tab)).'&module='.urlencode((string) ($module)).'">'.img_delete().'</a>';
6006 }
6007 print '</td>';
6008 }
6009 print '</tr>';
6010 }
6011 } else {
6012 print '<tr><td colspan="14"><span class="opacitymedium">'.$langs->trans("None").'</span></td></tr>';
6013 }
6014
6015 print '</table>';
6016 print '</div>';
6017 print '</form>';
6018
6019
6020 print '<script>
6021 $(document).ready(function() {
6022 //for fill in auto url
6023 $("#leftmenu").on("input", function() {
6024 var inputLeftMenu = $("#leftmenu").val();
6025 if (inputLeftMenu !== \'\') {
6026 var url = \''.dol_escape_js(dol_strtolower($module)).'\' + inputLeftMenu + \'.php\';
6027 $("#url").val(url);
6028 }else {
6029 $("#url").val("");
6030 }
6031 });
6032
6033 var groupedRights = ' . $groupedRights_json . ';
6034 var objectsSelect = $("select[id=\'objects\']");
6035 var permsSelect = $("select[id=\'perms\']");
6036
6037 objectsSelect.change(function() {
6038 var selectedObject = $(this).val();
6039
6040 permsSelect.empty();
6041
6042 var rights = groupedRights[selectedObject];
6043
6044 if (rights) {
6045 for (var i = 0; i < rights.length; i++) {
6046 var right = rights[i];
6047 var option = $("<option></option>").attr("value", right[5]).text(right[5]);
6048 permsSelect.append(option);
6049 }
6050 } else {
6051 var option = $("<option></option>").attr("value", "read").text("read");
6052 permsSelect.append(option);
6053 }
6054
6055 if (selectedObject !== "" && selectedObject !== null && rights) {
6056 permsSelect.show();
6057 } else {
6058 permsSelect.hide();
6059 }
6060 if (objectsSelect.val() === "" || objectsSelect.val() === null) {
6061 permsSelect.hide();
6062 }
6063 });
6064 });
6065 </script>';
6066
6067 // display permissions for each object
6068 } else {
6069 $fullpathoffile = dol_buildpath($file, 0);
6070
6071 $content = file_get_contents($fullpathoffile);
6072
6073 // New module
6074 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
6075 print '<input type="hidden" name="token" value="'.newToken().'">';
6076 print '<input type="hidden" name="action" value="savefile">';
6077 print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
6078 print '<input type="hidden" name="tab" value="'.$tab.'">';
6079 print '<input type="hidden" name="module" value="'.$module.'">';
6080
6081 $posCursor = (empty($find)) ? array() : array('find' => $find);
6082 $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%', 0, $posCursor);
6083 print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'html'));
6084 print '<br>';
6085 print '<center>';
6086 print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
6087 print ' &nbsp; ';
6088 print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
6089 print '</center>';
6090
6091 print '</form>';
6092 }
6093 }
6094
6095 if ($tab == 'permissions') {
6096 print '<!-- tab=permissions -->'."\n";
6097 $pathtofile = $listofmodules[dol_strtolower($module)]['moduledescriptorrelpath'];
6098
6099 $perms = $moduleobj->rights;
6100
6101 // Get list of existing objects
6102 $dir = $dirread.'/'.$modulelowercase.'/class';
6103 $listofobject = dol_dir_list($dir, 'files', 0, '\.class\.php$');
6104 $objects = array('myobject');
6105 $reg = array();
6106 foreach ($listofobject as $fileobj) {
6107 $tmpcontent = file_get_contents($fileobj['fullname']);
6108 if (preg_match('/class\s+([^\s]*)\s+extends\s+CommonObject/ims', $tmpcontent, $reg)) {
6109 $objects[$fileobj['fullname']] = $reg[1];
6110 }
6111 }
6112
6113 // declared select list for actions and labels permissions
6114 $crud = array('read' => 'CRUDRead', 'write' => 'CRUDCreateWrite', 'delete' => 'Delete');
6115 $labels = array("Read objects of ".$module, "Create/Update objects of ".$module, "Delete objects of ".$module);
6116
6117 $action = GETPOST('action', 'alpha');
6118
6119 if ($action == 'deleteright') {
6120 $formconfirm = $form->formconfirm(
6121 $_SERVER["PHP_SELF"].'?permskey='.urlencode((string) (GETPOSTINT('permskey'))).'&tab='.urlencode((string) ($tab)).'&module='.urlencode((string) ($module)).'&tabobj='.urlencode((string) ($tabobj)),
6122 $langs->trans('Delete'),
6123 $langs->trans('Confirm Delete Right', GETPOST('permskey', 'alpha')),
6124 'confirm_deleteright',
6125 '',
6126 0,
6127 1
6128 );
6129 print $formconfirm;
6130 }
6131
6132 if ($action != 'editfile' || empty($file)) {
6133 print '<!-- Tab to manage permissions -->'."\n";
6134 print '<span class="opacitymedium">';
6135 $htmlhelp = $langs->trans("PermissionsDefDescTooltip");
6136 //$htmlhelp = $langs->trans("PermissionsDefDescTooltip", '{s1}');
6137 //$htmlhelp = str_replace('{s1}', '<a target="adminbis" class="nofocusvisible" href="'.DOL_URL_ROOT.'/admin/perms.php">'.$langs->trans('DefaultRights').'</a>', $htmlhelp);
6138 print $form->textwithpicto($langs->trans("PermissionsDefDesc"), $htmlhelp, 1, 'help', '', 0, 2, 'helpondesc').'<br>';
6139 print '</span>';
6140 print '<br>';
6141
6142 print '<span class="fa fa-file"></span> '.$langs->trans("DescriptorFile").' : <strong class="wordbreak">'.$pathtofile.'</strong>';
6143 print ' <a class="editfielda paddingleft paddingright" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format=php&file='.urlencode($pathtofile).'&find=PERMISSIONS">'.img_picto($langs->trans("Edit"), 'edit').'</a>';
6144 print '<br>';
6145
6146 print '<br>';
6147 print load_fiche_titre($langs->trans("ListOfPermissionsDefined"), '', '');
6148
6149 print '<!-- form to add permissions -->'."\n";
6150 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
6151 print '<input type="hidden" name="token" value="'.newToken().'">';
6152 print '<input type="hidden" name="action" value="addright">';
6153 print '<input type="hidden" name="tab" value="permissions">';
6154 print '<input type="hidden" name="module" value="'.dol_escape_htmltag($module).'">';
6155 print '<input type="hidden" name="tabobj" value="'.dol_escape_htmltag($tabobj).'">';
6156
6157 print '<div class="div-table-responsive">';
6158 print '<table class="noborder">';
6159
6160 print '<tr class="liste_titre">';
6161 print_liste_field_titre("ID", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, "center");
6162 print_liste_field_titre("Object", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, "center");
6163 print_liste_field_titre("CRUD", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, "center");
6164 print_liste_field_titre("Label", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, "center");
6165 print_liste_field_titre("", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, "center");
6166 print "</tr>\n";
6167
6168 //form for add new right
6169 print '<tr class="small">';
6170 print '<td><input type="hidden" readonly name="id" class="width75" value="0"></td>';
6171
6172 print '<td><select class="minwidth100" name="permissionObj" id="permissionObj">';
6173 print '<option value=""></option>';
6174 foreach ($objects as $obj) {
6175 if ($obj != 'myobject') {
6176 print '<option value="'.$obj.'">'.$obj.'</option>';
6177 }
6178 }
6179 print '</select></td>';
6180
6181 print '<td><select class="maxwidth75" name="crud" id="crud">';
6182 print '<option value=""></option>';
6183 foreach ($crud as $key => $val) {
6184 print '<option value="'.$key.'">'.$langs->trans($val).'</option>';
6185 }
6186 print '</td>';
6187
6188 print '<td >';
6189 print '<input type="text" name="label" id="label" class="minwidth200">';
6190 print '</td>';
6191
6192 print '<td class="center minwidth75 tdstickyright tdstickyghostwhite">';
6193 print '<input type="submit" class="button" name="add" value="'.$langs->trans("Add").'">';
6194 print '</td>';
6195 print '</tr>';
6196
6197 if (count($perms)) {
6198 $i = 0;
6199 foreach ($perms as $perm) {
6200 $i++;
6201
6202 // section for editing right
6203 if ($action == 'edit_right' && $perm[0] == GETPOSTINT('permskey')) {
6204 print '<tr class="oddeven">';
6205 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST" name="modifPerms">';
6206 print '<input type="hidden" name="token" value="'.newToken().'">';
6207 print '<input type="hidden" name="tab" value="permissions">';
6208 print '<input type="hidden" name="module" value="'.dol_escape_htmltag($module).'">';
6209 print '<input type="hidden" name="tabobj" value="'.dol_escape_htmltag($tabobj).'">';
6210 print '<input type="hidden" name="action" value="update_right">';
6211 print '<input type="hidden" name="counter" value="'.$i.'">';
6212
6213 print '<input type="hidden" name="permskey" value="'.$perm[0].'">';
6214
6215 print '<td class="tdsticky tdstickygray">';
6216 print '<input class="width75" type="text" readonly value="'.dol_escape_htmltag($perm[0]).'"/>';
6217 print '</td>';
6218
6219 print '<td>';
6220 print '<select name="crud">';
6221 print '<option value="'.dol_escape_htmltag($perm[5]).'">'.$langs->trans($perm[5]).'</option>';
6222 foreach ($crud as $i => $x) {
6223 if ($perm[5] != $i) {
6224 print '<option value="'.$i.'">'.$langs->trans(dol_ucfirst($x)).'</option>';
6225 }
6226 }
6227 print '</select>';
6228 print '</td>';
6229
6230 print '<td><select name="permissionObj" >';
6231 print '<option value="'.dol_escape_htmltag($perm[4]).'">'.dol_ucfirst($perm[4]).'</option>';
6232 print '</select></td>';
6233
6234 print '<td>';
6235 print '<input type="text" name="label" value="'.dol_escape_htmltag($perm[1]).'">';
6236 print '</td>';
6237
6238 print '<td class="center minwidth75 tdstickyright tdstickyghostwhite">';
6239 print '<input id ="modifyPerm" class="reposition button smallpaddingimp" type="submit" name="modifyright" value="'.$langs->trans("Modify").'"/>';
6240 print '<br>';
6241 print '<input class="reposition button button-cancel smallpaddingimp" type="submit" name="cancel" value="'.$langs->trans("Cancel").'"/>';
6242 print '</td>';
6243
6244 print '</form>';
6245 print '</tr>';
6246 } else {
6247 // $perm can be module->object->crud or module->crud
6248 print '<tr class="oddeven">';
6249
6250 print '<td>';
6251 print dol_escape_htmltag($perm[0]);
6252 print '</td>';
6253
6254 print '<td>';
6255 if (in_array($perm[5], array('lire', 'read', 'creer', 'write', 'effacer', 'delete'))) {
6256 print dol_escape_htmltag(dol_ucfirst($perm[4]));
6257 } else {
6258 print ''; // No particular object
6259 }
6260 print '</td>';
6261
6262 print '<td>';
6263 if (in_array($perm[5], array('lire', 'read', 'creer', 'write', 'effacer', 'delete'))) {
6264 print dol_ucfirst($langs->trans($perm[5]));
6265 } else {
6266 print dol_ucfirst($langs->trans($perm[4]));
6267 }
6268 print '</td>';
6269
6270 print '<td>';
6271 print $langs->trans($perm[1]);
6272 print '</td>';
6273
6274 print '<td class="center minwidth75 tdstickyright tdstickyghostwhite">';
6275 print '<a class="editfielda reposition marginleftonly marginrighttonly paddingright paddingleft" href="'.$_SERVER["PHP_SELF"].'?action=edit_right&token='.newToken().'&permskey='.urlencode($perm[0]).'&tab='.urlencode($tab).'&module='.urlencode($module).'&tabobj='.urlencode($tabobj).'">'.img_edit().'</a>';
6276 print '<a class="marginleftonly marginrighttonly paddingright paddingleft" href="'.$_SERVER["PHP_SELF"].'?action=deleteright&token='.newToken().'&permskey='.urlencode((string) ($i)).'&tab='.urlencode((string) ($tab)).'&module='.urlencode((string) ($module)).'&tabobj='.urlencode((string) ($tabobj)).'">'.img_delete().'</a>';
6277
6278 print '</td>';
6279
6280 print '</tr>';
6281 }
6282 }
6283 } else {
6284 print '<tr><td colspan="5"><span class="opacitymedium">'.$langs->trans("None").'</span></td></tr>';
6285 }
6286
6287 print '</table>';
6288 print '</div>';
6289
6290 print '</form>';
6291 print '<script>
6292 function updateInputField() {
6293 value1 = $("#crud").val();
6294 value2 = $("#permissionObj").val();
6295
6296 // Check if both selections are made
6297 if (value1 && value2) {
6298 switch(value1.toLowerCase()){
6299 case "read":
6300 $("#label").val("Read "+value2+" object of '.dol_ucfirst($module).'")
6301 break;
6302 case "write":
6303 $("#label").val("Create/Update "+value2+" object of '.dol_ucfirst($module).'")
6304 break;
6305 case "delete":
6306 $("#label").val("Delete "+value2+" object of '.dol_ucfirst($module).'")
6307 break;
6308 default:
6309 $("#label").val("")
6310 }
6311 }
6312 }
6313
6314 $("#crud, #permissionObj").change(function(){
6315 console.log("We change selection");
6316 updateInputField();
6317 });
6318
6319 </script>';
6320 } else {
6321 $fullpathoffile = dol_buildpath($file, 0);
6322
6323 $content = file_get_contents($fullpathoffile);
6324
6325 // New module
6326 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
6327 print '<input type="hidden" name="token" value="'.newToken().'">';
6328 print '<input type="hidden" name="action" value="savefile">';
6329 print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
6330 print '<input type="hidden" name="tab" value="'.$tab.'">';
6331 print '<input type="hidden" name="module" value="'.$module.'">';
6332
6333 $posCursor = (empty($find)) ? array() : array('find' => $find);
6334 $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%', 0, $posCursor);
6335 print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'html'));
6336 print '<br>';
6337 print '<center>';
6338 print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
6339 print ' &nbsp; ';
6340 print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
6341 print '</center>';
6342
6343 print '</form>';
6344 }
6345 }
6346
6347 if ($tab == 'hooks') {
6348 print '<!-- tab=hooks -->'."\n";
6349 if ($action != 'editfile' || empty($file)) {
6350 print '<span class="opacitymedium">'.$langs->trans("HooksDefDesc").'</span><br>';
6351 print '<br>';
6352
6353 print '<table>';
6354
6355 $pathtofile = $listofmodules[dol_strtolower($module)]['moduledescriptorrelpath'];
6356 print '<tr><td>';
6357 print '<span class="fa fa-file"></span> '.$langs->trans("DescriptorFile").' : <strong class="wordbreak">'.$pathtofile.'</strong>';
6358 print '</td><td>';
6359 print '<a class="editfielda paddingleft paddingright" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format=php&file='.urlencode($pathtofile).'&find=HOOKSCONTEXTS">'.img_picto($langs->trans("Edit"), 'edit').'</a>';
6360 print '</td></tr>';
6361
6362 print '<tr><td>';
6363 $pathtohook = dol_strtolower($module).'/class/actions_'.dol_strtolower($module).'.class.php';
6364 print '<span class="fa fa-file"></span> '.$langs->trans("HooksFile").' : ';
6365 if (dol_is_file($dirins.'/'.$pathtohook)) {
6366 print '<strong class="wordbreak">'.$pathtohook.'</strong>';
6367 print '</td>';
6368 print '<td><a class="editfielda paddingleft paddingright" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format=php&file='.urlencode($pathtohook).'">'.img_picto($langs->trans("Edit"), 'edit').'</a> ';
6369 print '<a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=confirm_removefile&token='.newToken().'&file='.urlencode($pathtohook).'">'.img_picto($langs->trans("Delete"), 'delete').'</a></td>';
6370 } else {
6371 print '<span class="opacitymedium">'.$langs->trans("FileNotYetGenerated").'</span>';
6372 print '<a href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=inithook&token='.newToken().'&format=php&file='.urlencode($pathtohook).'">'.img_picto('Generate', 'generate', 'class="paddingleft"').'</td>';
6373 print '<td></td>';
6374 }
6375 print '</tr>';
6376 } else {
6377 $fullpathoffile = dol_buildpath($file, 0);
6378
6379 $content = file_get_contents($fullpathoffile);
6380
6381 // New module
6382 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
6383 print '<input type="hidden" name="token" value="'.newToken().'">';
6384 print '<input type="hidden" name="action" value="savefile">';
6385 print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
6386 print '<input type="hidden" name="tab" value="'.$tab.'">';
6387 print '<input type="hidden" name="module" value="'.$module.'">';
6388
6389 $posCursor = (empty($find)) ? array() : array('find' => $find);
6390 $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%', 0, $posCursor);
6391 print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'html'));
6392 print '<br>';
6393 print '<center>';
6394 print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
6395 print ' &nbsp; ';
6396 print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
6397 print '</center>';
6398
6399 print '</form>';
6400 }
6401 }
6402
6403 if ($tab == 'triggers') {
6404 print '<!-- tab=triggers -->'."\n";
6405 require_once DOL_DOCUMENT_ROOT.'/core/class/interfaces.class.php';
6406
6407 $interfaces = new Interfaces($db);
6408 $triggers = $interfaces->getTriggersList(array('/'.dol_strtolower($module).'/core/triggers'));
6409
6410 if ($action != 'editfile' || empty($file)) {
6411 print '<span class="opacitymedium">'.$langs->trans("TriggerDefDesc").'</span><br>';
6412 print '<br>';
6413
6414 print '<table>';
6415
6416 $pathtofile = $listofmodules[dol_strtolower($module)]['moduledescriptorrelpath'];
6417 print '<tr><td>';
6418 print '<span class="fa fa-file"></span> '.$langs->trans("DescriptorFile").' : <strong class="wordbreak">'.$pathtofile.'</strong>';
6419 print '</td><td>';
6420 print '<a class="editfielda paddingleft paddingright" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format=php&file='.urlencode($pathtofile).'&find=module_parts">'.img_picto($langs->trans("Edit"), 'edit').'</a>';
6421 print '</td></tr>';
6422
6423 if (!empty($triggers)) {
6424 foreach ($triggers as $trigger) {
6425 $pathtofile = $trigger['relpath'];
6426
6427 print '<tr><td>';
6428 print '<span class="fa fa-file"></span> '.$langs->trans("TriggersFile").' : <strong class="wordbreak">'.$pathtofile.'</strong>';
6429 print '</td><td><a class="editfielda paddingleft paddingright" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format=php&file='.urlencode($pathtofile).'">'.img_picto($langs->trans("Edit"), 'edit').'</a></td>';
6430 print '<td><a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=confirm_removefile&token='.newToken().'&file='.urlencode($pathtofile).'">'.img_picto($langs->trans("Delete"), 'delete').'</a></td>';
6431 print '</tr>';
6432 }
6433 } else {
6434 print '<tr><td>';
6435 print '<span class="fa fa-file"></span> '.$langs->trans("TriggersFile");
6436 print ' : <span class="opacitymedium">'.$langs->trans("FileNotYetGenerated").'</span>';
6437 print '<a href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=inittrigger&token='.newToken().'&format=php">'.img_picto('Generate', 'generate', 'class="paddingleft"').'</a></td>';
6438 print '<td></td>';
6439 print '</tr>';
6440 }
6441
6442 print '</table>';
6443 } else {
6444 $fullpathoffile = dol_buildpath($file, 0);
6445
6446 $content = file_get_contents($fullpathoffile);
6447
6448 // New module
6449 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
6450 print '<input type="hidden" name="token" value="'.newToken().'">';
6451 print '<input type="hidden" name="action" value="savefile">';
6452 print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
6453 print '<input type="hidden" name="tab" value="'.$tab.'">';
6454 print '<input type="hidden" name="module" value="'.$module.'">';
6455
6456 $posCursor = (empty($find)) ? array() : array('find' => $find);
6457 $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%', 0, $posCursor);
6458 print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'html'));
6459 print '<br>';
6460 print '<center>';
6461 print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
6462 print ' &nbsp; ';
6463 print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
6464 print '</center>';
6465
6466 print '</form>';
6467 }
6468 }
6469
6470 if ($tab == 'css') {
6471 print '<!-- tab=css -->'."\n";
6472 if ($action != 'editfile' || empty($file)) {
6473 print '<span class="opacitymedium">'.$langs->trans("CSSDesc").'</span><br>';
6474 print '<br>';
6475
6476 print '<table>';
6477
6478 print '<tr><td>';
6479 $pathtohook = dol_strtolower($module).'/css/'.dol_strtolower($module).'.css.php';
6480 print '<span class="fa fa-file"></span> '.$langs->trans("CSSFile").' : ';
6481 if (dol_is_file($dirins.'/'.$pathtohook)) {
6482 print '<strong class="wordbreak">'.$pathtohook.'</strong>';
6483 print '</td><td><a class="editfielda paddingleft paddingright" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format=php&file='.urlencode($pathtohook).'">'.img_picto($langs->trans("Edit"), 'edit').'</a></td>';
6484 print '</td><td><a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=confirm_removefile&token='.newToken().'&format='.$format.'&file='.urlencode($pathtohook).'">'.img_picto($langs->trans("Delete"), 'delete').'</a></td>';
6485 } else {
6486 print '<span class="opacitymedium">'.$langs->trans("FileNotYetGenerated").'</span>';
6487 print '</td><td><a href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=initcss&token='.newToken().'&format=php&file='.urlencode($pathtohook).'">'.img_picto('Generate', 'generate', 'class="paddingleft"').'</a></td>';
6488 }
6489 print '</tr>';
6490 } else {
6491 $fullpathoffile = dol_buildpath($file, 0);
6492
6493 $content = file_get_contents($fullpathoffile);
6494
6495 // New module
6496 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
6497 print '<input type="hidden" name="token" value="'.newToken().'">';
6498 print '<input type="hidden" name="action" value="savefile">';
6499 print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
6500 print '<input type="hidden" name="tab" value="'.$tab.'">';
6501 print '<input type="hidden" name="module" value="'.$module.'">';
6502
6503 $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%');
6504 print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'html'));
6505 print '<br>';
6506 print '<center>';
6507 print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
6508 print ' &nbsp; ';
6509 print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
6510 print '</center>';
6511
6512 print '</form>';
6513 }
6514 }
6515
6516 if ($tab == 'js') {
6517 print '<!-- tab=js -->'."\n";
6518 if ($action != 'editfile' || empty($file)) {
6519 print '<span class="opacitymedium">'.$langs->trans("JSDesc").'</span><br>';
6520 print '<br>';
6521
6522 print '<table>';
6523
6524 print '<tr><td>';
6525 $pathtohook = dol_strtolower($module).'/js/'.dol_strtolower($module).'.js.php';
6526 print '<span class="fa fa-file"></span> '.$langs->trans("JSFile").' : ';
6527 if (dol_is_file($dirins.'/'.$pathtohook)) {
6528 print '<strong class="wordbreak">'.$pathtohook.'</strong>';
6529 print '</td><td><a class="editfielda paddingleft paddingright" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format=php&file='.urlencode($pathtohook).'">'.img_picto($langs->trans("Edit"), 'edit').'</a></td>';
6530 print '</td><td><a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=confirm_removefile&token='.newToken().'&file='.urlencode($pathtohook).'">'.img_picto($langs->trans("Delete"), 'delete').'</a></td>';
6531 } else {
6532 print '<span class="opacitymedium">'.$langs->trans("FileNotYetGenerated").'</span>';
6533 print '</td><td><a href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=initjs&token='.newToken().'&format=php&file='.urlencode($pathtohook).'">'.img_picto('Generate', 'generate', 'class="paddingleft"').'</a></td>';
6534 }
6535 print '</tr>';
6536 } else {
6537 $fullpathoffile = dol_buildpath($file, 0);
6538
6539 $content = file_get_contents($fullpathoffile);
6540
6541 // New module
6542 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
6543 print '<input type="hidden" name="token" value="'.newToken().'">';
6544 print '<input type="hidden" name="action" value="savefile">';
6545 print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
6546 print '<input type="hidden" name="tab" value="'.$tab.'">';
6547 print '<input type="hidden" name="module" value="'.$module.'">';
6548
6549 $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%');
6550 print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'html'));
6551 print '<br>';
6552 print '<center>';
6553 print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
6554 print ' &nbsp; ';
6555 print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
6556 print '</center>';
6557
6558 print '</form>';
6559 }
6560 }
6561
6562 if ($tab == 'widgets') {
6563 print '<!-- tab=widgets -->'."\n";
6564 require_once DOL_DOCUMENT_ROOT.'/core/boxes/modules_boxes.php';
6565
6566 $widgets = ModeleBoxes::getWidgetsList(array('/'.dol_strtolower($module).'/core/boxes'));
6567
6568 if ($action != 'editfile' || empty($file)) {
6569 print '<span class="opacitymedium">'.$langs->trans("WidgetDesc").'</span><br>';
6570 print '<br>';
6571
6572 print '<table>';
6573 if (!empty($widgets)) {
6574 foreach ($widgets as $widget) {
6575 $pathtofile = $widget['relpath'];
6576
6577 print '<tr><td><span class="fa fa-file"></span> '.$langs->trans("WidgetFile").' : <strong class="wordbreak">'.$pathtofile.'</strong>';
6578 print '</td><td><a class="editfielda paddingleft paddingright" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format=php&file='.urlencode($pathtofile).'">'.img_picto($langs->trans("Edit"), 'edit').'</a>';
6579 print '</td><td><a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=confirm_removefile&token='.newToken().'&file='.urlencode($pathtofile).'">'.img_picto($langs->trans("Delete"), 'delete').'</a></td>';
6580 print '</tr>';
6581 }
6582 } else {
6583 print '<tr><td><span class="fa fa-file"></span> '.$langs->trans("WidgetFile").' : <span class="opacitymedium">'.$langs->trans("NoWidget").'</span>';
6584 print '</td><td><a href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=initwidget&token='.newToken().'&format=php">'.img_picto('Generate', 'generate', 'class="paddingleft"').'</a>';
6585 print '</td></tr>';
6586 }
6587 print '</table>';
6588 } else {
6589 $fullpathoffile = dol_buildpath($file, 0);
6590
6591 $content = file_get_contents($fullpathoffile);
6592
6593 // New module
6594 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
6595 print '<input type="hidden" name="token" value="'.newToken().'">';
6596 print '<input type="hidden" name="action" value="savefile">';
6597 print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
6598 print '<input type="hidden" name="tab" value="'.$tab.'">';
6599 print '<input type="hidden" name="module" value="'.$module.'">';
6600
6601 $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%');
6602 print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'html'));
6603 print '<br>';
6604 print '<center>';
6605 print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
6606 print ' &nbsp; ';
6607 print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
6608 print '</center>';
6609
6610 print '</form>';
6611 }
6612 }
6613
6614 if ($tab == 'emailings') {
6615 print '<!-- tab=emailings -->'."\n";
6616 require_once DOL_DOCUMENT_ROOT.'/core/modules/mailings/modules_mailings.php';
6617
6618 $emailingselectors = MailingTargets::getEmailingSelectorsList(array('/'.dol_strtolower($module).'/core/modules/mailings'));
6619
6620 if ($action != 'editfile' || empty($file)) {
6621 print '<span class="opacitymedium">'.$langs->trans("EmailingSelectorDesc").'</span><br>';
6622 print '<br>';
6623
6624 print '<table>';
6625 if (!empty($emailingselectors)) {
6626 foreach ($emailingselectors as $emailingselector) {
6627 $pathtofile = $emailingselector['relpath'];
6628
6629 print '<tr><td><span class="fa fa-file"></span> '.$langs->trans("EmailingSelectorFile").' : <strong class="wordbreak">'.$pathtofile.'</strong>';
6630 print '</td><td><a class="editfielda paddingleft paddingright" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format=php&file='.urlencode($pathtofile).'">'.img_picto($langs->trans("Edit"), 'edit').'</a>';
6631 print '</td><td><a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=confirm_removefile&token='.newToken().'&file='.urlencode($pathtofile).'">'.img_picto($langs->trans("Delete"), 'delete').'</a></td>';
6632 print '</tr>';
6633 }
6634 } else {
6635 print '<tr><td><span class="fa fa-file"></span> '.$langs->trans("EmailingSelectorFile").' : <span class="opacitymedium">'.$langs->trans("NoEmailingSelector").'</span>';
6636 print '</td><td><a href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=initemailing&token='.newToken().'&format=php">'.img_picto('Generate', 'generate', 'class="paddingleft"').'</a>';
6637 print '</td></tr>';
6638 }
6639 print '</table>';
6640 } else {
6641 $fullpathoffile = dol_buildpath($file, 0);
6642
6643 $content = file_get_contents($fullpathoffile);
6644
6645 // New module
6646 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
6647 print '<input type="hidden" name="token" value="'.newToken().'">';
6648 print '<input type="hidden" name="action" value="savefile">';
6649 print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
6650 print '<input type="hidden" name="tab" value="'.$tab.'">';
6651 print '<input type="hidden" name="module" value="'.$module.'">';
6652
6653 $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%');
6654 print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'html'));
6655 print '<br>';
6656 print '<center>';
6657 print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
6658 print ' &nbsp; ';
6659 print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
6660 print '</center>';
6661
6662 print '</form>';
6663 }
6664 }
6665
6666 if ($tab == 'exportimport') {
6667 print '<!-- tab=exportimport -->'."\n";
6668 $pathtofile = $listofmodules[dol_strtolower($module)]['moduledescriptorrelpath'];
6669
6670 $exportlist = $moduleobj->export_label;
6671 $importlist = $moduleobj->import_label;
6672
6673 if ($action != 'editfile' || empty($file)) {
6674 print '<span class="opacitymedium">'.$langs->transnoentities('ImportExportProfiles').'</span><br>';
6675 print '<br>';
6676
6677 print '<span class="fa fa-file"></span> '.$langs->trans("DescriptorFile").' ('.$langs->trans("ExportsArea").') : <strong class="wordbreak">'.$pathtofile.'</strong>';
6678 print ' <a class="editfielda paddingleft paddingright" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format=php&file='.urlencode($pathtofile).'&find=EXPORT">'.img_picto($langs->trans("Edit"), 'edit').'</a>';
6679 print '<br>';
6680 print '<span class="fa fa-file"></span> '.$langs->trans("DescriptorFile").' ('.$langs->trans("ImportArea").') : <strong class="wordbreak">'.$pathtofile.'</strong>';
6681 print ' <a class="editfielda paddingleft paddingright" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format=php&file='.urlencode($pathtofile).'&find=IMPORT">'.img_picto($langs->trans("Edit"), 'edit').'</a>';
6682 print '<br>';
6683 } else {
6684 $fullpathoffile = dol_buildpath($file, 0);
6685
6686 $content = file_get_contents($fullpathoffile);
6687
6688 // New module
6689 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
6690 print '<input type="hidden" name="token" value="'.newToken().'">';
6691 print '<input type="hidden" name="action" value="savefile">';
6692 print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
6693 print '<input type="hidden" name="tab" value="'.$tab.'">';
6694 print '<input type="hidden" name="module" value="'.$module.'">';
6695
6696 $posCursor = (empty($find)) ? array() : array('find' => $find);
6697 $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%', 0, $posCursor);
6698 print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'html'));
6699 print '<br>';
6700 print '<center>';
6701 print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
6702 print ' &nbsp; ';
6703 print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
6704 print '</center>';
6705
6706 print '</form>';
6707 }
6708 }
6709
6710 if ($tab == 'cli') {
6711 print '<!-- tab=cli -->'."\n";
6712 $clifiles = array();
6713 $i = 0;
6714
6715 $dircli = array('/'.dol_strtolower($module).'/scripts');
6716
6717 foreach ($dircli as $reldir) {
6718 $dir = dol_buildpath($reldir, 0);
6719 $newdir = dol_osencode($dir);
6720
6721 // Check if directory exists (we do not use dol_is_dir to avoid loading files.lib.php at each call)
6722 if (!dol_is_dir($newdir)) {
6723 continue;
6724 }
6725
6726 $handle = opendir($newdir);
6727
6728 if (is_resource($handle)) {
6729 while (($tmpfile = readdir($handle)) !== false) {
6730 if (is_readable($newdir.'/'.$tmpfile) && preg_match('/^(.+)\.php/', $tmpfile, $reg)) {
6731 if (preg_match('/\.back$/', $tmpfile)) {
6732 continue;
6733 }
6734
6735 $clifiles[$i]['relpath'] = preg_replace('/^\//', '', $reldir).'/'.$tmpfile;
6736
6737 $i++;
6738 }
6739 }
6740 closedir($handle);
6741 }
6742 }
6743
6744 if ($action != 'editfile' || empty($file)) {
6745 print '<span class="opacitymedium">'.$langs->trans("CLIDesc").'</span><br>';
6746 print '<br>';
6747
6748 print '<table>';
6749 if (!empty($clifiles)) {
6750 foreach ($clifiles as $clifile) {
6751 $pathtofile = $clifile['relpath'];
6752
6753 print '<tr><td><span class="fa fa-file"></span> '.$langs->trans("CLIFile").' : <strong class="wordbreak">'.$pathtofile.'</strong>';
6754 print '</td><td><a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format=php&file='.urlencode($pathtofile).'">'.img_picto($langs->trans("Edit"), 'edit').'</a></td>';
6755 print '<td><a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=confirm_removefile&token='.newToken().'&file='.urlencode($pathtofile).'">'.img_picto($langs->trans("Delete"), 'delete').'</a></td>';
6756 print '</tr>';
6757 }
6758 } else {
6759 print '<tr><td><span class="fa fa-file"></span> '.$langs->trans("CLIFile").' : <span class="opacitymedium">'.$langs->trans("FileNotYetGenerated").'</span>';
6760 print '</td><td><a href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=initcli&token='.newToken().'&format=php">'.img_picto('Generate', 'generate', 'class="paddingleft"').'</a>';
6761 print '</td></tr>';
6762 }
6763 print '</table>';
6764 } else {
6765 $fullpathoffile = dol_buildpath($file, 0);
6766
6767 $content = file_get_contents($fullpathoffile);
6768
6769 // New module
6770 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
6771 print '<input type="hidden" name="token" value="'.newToken().'">';
6772 print '<input type="hidden" name="action" value="savefile">';
6773 print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
6774 print '<input type="hidden" name="tab" value="'.$tab.'">';
6775 print '<input type="hidden" name="module" value="'.$module.'">';
6776
6777 $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%');
6778 print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'html'));
6779 print '<br>';
6780 print '<center>';
6781 print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
6782 print ' &nbsp; ';
6783 print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
6784 print '</center>';
6785
6786 print '</form>';
6787 }
6788 }
6789
6790 if ($tab == 'cron') {
6791 print '<!-- tab=cron -->'."\n";
6792 $pathtofile = $listofmodules[dol_strtolower($module)]['moduledescriptorrelpath'];
6793
6794 $cronjobs = $moduleobj->cronjobs;
6795
6796 if ($action != 'editfile' || empty($file)) {
6797 print '<span class="opacitymedium">'.str_replace('{s1}', '<a target="adminbis" class="nofocusvisible" href="'.DOL_URL_ROOT.'/cron/list.php">'.$langs->transnoentities('CronList').'</a>', $langs->trans("CronJobDefDesc", '{s1}')).'</span><br>';
6798 print '<br>';
6799
6800 print '<span class="fa fa-file"></span> '.$langs->trans("DescriptorFile").' : <strong class="wordbreak">'.$pathtofile.'</strong>';
6801 print ' <a class="editfielda paddingleft paddingright" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format=php&file='.urlencode($pathtofile).'&find=CRON">'.img_picto($langs->trans("Edit"), 'edit').'</a>';
6802 print '<br>';
6803
6804 print '<br>';
6805 print load_fiche_titre($langs->trans("CronJobProfiles"), '', '');
6806
6807 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
6808 print '<input type="hidden" name="token" value="'.newToken().'">';
6809 print '<input type="hidden" name="action" value="addproperty">';
6810 print '<input type="hidden" name="tab" value="objects">';
6811 print '<input type="hidden" name="module" value="'.dol_escape_htmltag($module).'">';
6812 print '<input type="hidden" name="tabobj" value="'.dol_escape_htmltag($tabobj).'">';
6813
6814 print '<div class="div-table-responsive">';
6815 print '<table class="noborder">';
6816
6817 print '<tr class="liste_titre">';
6818 print_liste_field_titre("CronLabel", $_SERVER["PHP_SELF"], "", "", $param, '', $sortfield, $sortorder);
6819 print_liste_field_titre("CronTask", '', '', "", $param, '', $sortfield, $sortorder);
6820 print_liste_field_titre("CronFrequency", '', "", "", $param, '', $sortfield, $sortorder);
6821 print_liste_field_titre("StatusAtInstall", $_SERVER["PHP_SELF"], "", "", $param, '', $sortfield, $sortorder);
6822 print_liste_field_titre("Comment", $_SERVER["PHP_SELF"], "", "", $param, '', $sortfield, $sortorder);
6823 print "</tr>\n";
6824
6825 if (count($cronjobs)) {
6826 foreach ($cronjobs as $cron) {
6827 print '<tr class="oddeven">';
6828
6829 print '<td>';
6830 print $cron['label'];
6831 print '</td>';
6832
6833 print '<td>';
6834 $texttoshow = '';
6835 if ($cron['jobtype'] == 'method') {
6836 $text = $langs->trans("CronClass");
6837 $texttoshow = $langs->trans('CronModule').': '.$module.'<br>';
6838 $texttoshow .= $langs->trans('CronClass').': '.$cron['class'].'<br>';
6839 $texttoshow .= $langs->trans('CronObject').': '.$cron['objectname'].'<br>';
6840 $texttoshow .= $langs->trans('CronMethod').': '.$cron['method'];
6841 $texttoshow .= '<br>'.$langs->trans('CronArgs').': '.$cron['parameters'];
6842 $texttoshow .= '<br>'.$langs->trans('Comment').': '.$langs->trans($cron['comment']);
6843 } elseif ($cron['jobtype'] == 'command') {
6844 $text = $langs->trans('CronCommand');
6845 $texttoshow = $langs->trans('CronCommand').': '.dol_trunc($cron['command']);
6846 $texttoshow .= '<br>'.$langs->trans('CronArgs').': '.$cron['parameters'];
6847 $texttoshow .= '<br>'.$langs->trans('Comment').': '.$langs->trans($cron['comment']);
6848 }
6849 print $form->textwithpicto($text, $texttoshow, 1);
6850 print '</td>';
6851
6852 print '<td>';
6853 if ($cron['unitfrequency'] == "60") {
6854 print $langs->trans('CronEach')." ".($cron['frequency'])." ".$langs->trans('Minutes');
6855 }
6856 if ($cron['unitfrequency'] == "3600") {
6857 print $langs->trans('CronEach')." ".($cron['frequency'])." ".$langs->trans('Hours');
6858 }
6859 if ($cron['unitfrequency'] == "86400") {
6860 print $langs->trans('CronEach')." ".($cron['frequency'])." ".$langs->trans('Days');
6861 }
6862 if ($cron['unitfrequency'] == "604800") {
6863 print $langs->trans('CronEach')." ".($cron['frequency'])." ".$langs->trans('Weeks');
6864 }
6865 print '</td>';
6866
6867 print '<td>';
6868 print $cron['status'];
6869 print '</td>';
6870
6871 print '<td>';
6872 if (!empty($cron['comment'])) {
6873 print $cron['comment'];
6874 }
6875 print '</td>';
6876
6877 print '</tr>';
6878 }
6879 } else {
6880 print '<tr><td colspan="5"><span class="opacitymedium">'.$langs->trans("None").'</span></td></tr>';
6881 }
6882
6883 print '</table>';
6884 print '</div>';
6885
6886 print '</form>';
6887 } else {
6888 $fullpathoffile = dol_buildpath($file, 0);
6889
6890 $content = file_get_contents($fullpathoffile);
6891
6892 // New module
6893 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
6894 print '<input type="hidden" name="token" value="'.newToken().'">';
6895 print '<input type="hidden" name="action" value="savefile">';
6896 print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
6897 print '<input type="hidden" name="tab" value="'.$tab.'">';
6898 print '<input type="hidden" name="module" value="'.$module.'">';
6899
6900 $posCursor = (empty($find)) ? array() : array('find' => $find);
6901 $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%', 0, $posCursor);
6902 print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'html'));
6903 print '<br>';
6904 print '<center>';
6905 print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
6906 print ' &nbsp; ';
6907 print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
6908 print '</center>';
6909
6910 print '</form>';
6911 }
6912 }
6913
6914 if ($tab == 'specifications') {
6915 print '<!-- tab=specifications -->'."\n";
6916 $specs = dol_dir_list(dol_buildpath($modulelowercase.'/doc', 0), 'files', 1, '(\.md|\.asciidoc)$', array('\/temp\/'));
6917
6918 if ($action != 'editfile' || empty($file)) {
6919 print '<span class="opacitymedium">'.$langs->trans("SpecDefDesc").'</span><br>';
6920 print '<br>';
6921
6922 print '<table>';
6923 if (is_array($specs) && !empty($specs)) {
6924 foreach ($specs as $spec) {
6925 $pathtofile = $modulelowercase.'/doc/'.$spec['relativename'];
6926 $format = 'asciidoc';
6927 if (preg_match('/\.md$/i', $spec['name'])) {
6928 $format = 'markdown';
6929 }
6930 print '<tr><td>';
6931 print '<span class="fa fa-file"></span> '.$langs->trans("SpecificationFile").' : <strong class="wordbreak">'.$pathtofile.'</strong>';
6932 print '</td><td><a class="editfielda paddingleft paddingright" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&token='.newToken().'&format='.$format.'&file='.urlencode($pathtofile).'">'.img_picto($langs->trans("Edit"), 'edit').'</a></td>';
6933 print '<td><a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=confirm_removefile&token='.newToken().'&format='.$format.'&file='.urlencode($pathtofile).'">'.img_picto($langs->trans("Delete"), 'delete').'</a></td>';
6934 print '</tr>';
6935 }
6936 } else {
6937 print '<tr><td>';
6938 print '<span class="fa fa-file"></span> '.$langs->trans("SpecificationFile").' : <span class="opacitymedium">'.$langs->trans("FileNotYetGenerated").'</span>';
6939 print '</td><td><a href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=initdoc&token='.newToken().'&format=php">'.img_picto('Generate', 'generate', 'class="paddingleft"').'</a></td>';
6940 print '</tr>';
6941 }
6942 print '</table>';
6943 } else {
6944 // Use MD or asciidoc
6945
6946 //print $langs->trans("UseAsciiDocFormat").'<br>';
6947
6948 $fullpathoffile = dol_buildpath($file, 0);
6949
6950 $content = file_get_contents($fullpathoffile);
6951
6952 // New module
6953 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
6954 print '<input type="hidden" name="token" value="'.newToken().'">';
6955 print '<input type="hidden" name="action" value="savefile">';
6956 print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
6957 print '<input type="hidden" name="tab" value="'.$tab.'">';
6958 print '<input type="hidden" name="module" value="'.$module.'">';
6959
6960 $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%');
6961 print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'html'));
6962 print '<br>';
6963 print '<center>';
6964 print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
6965 print ' &nbsp; ';
6966 print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
6967 print '</center>';
6968
6969 print '</form>';
6970 }
6971
6972 print '<br><br><br>';
6973
6974 $FILENAMEDOC = $modulelowercase.'.html';
6975 $FILENAMEDOCPDF = $modulelowercase.'.pdf';
6976 $outputfiledoc = dol_buildpath($modulelowercase, 0).'/doc/'.$FILENAMEDOC;
6977 $outputfiledocurl = dol_buildpath($modulelowercase, 1).'/doc/'.$FILENAMEDOC;
6978 $outputfiledocrel = $modulelowercase.'/doc/'.$FILENAMEDOC;
6979 $outputfiledocpdf = dol_buildpath($modulelowercase, 0).'/doc/'.$FILENAMEDOCPDF;
6980 $outputfiledocurlpdf = dol_buildpath($modulelowercase, 1).'/doc/'.$FILENAMEDOCPDF;
6981 $outputfiledocrelpdf = $modulelowercase.'/doc/'.$FILENAMEDOCPDF;
6982
6983 // HTML
6984 print '<span class="fa fa-file"></span> '.$langs->trans("PathToModuleDocumentation", "HTML").' : ';
6985 if (!dol_is_file($outputfiledoc)) {
6986 print '<span class="opacitymedium">'.$langs->trans("FileNotYetGenerated").'</span>';
6987 } else {
6988 print '<strong>';
6989 print '<a href="'.$outputfiledocurl.'" target="_blank" rel="noopener noreferrer">';
6990 print $outputfiledoc;
6991 print '</a>';
6992 print '</strong>';
6993 print ' <span class="opacitymedium">('.$langs->trans("GeneratedOn").' '.dol_print_date(dol_filemtime($outputfiledoc), 'dayhour').')</span>';
6994 print ' <a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=confirm_removefile&token='.newToken().'&format='.$format.'&file='.urlencode($outputfiledocrel).'">'.img_picto($langs->trans("Delete"), 'delete').'</a>';
6995 }
6996 print '</strong><br>';
6997
6998 // PDF
6999 print '<span class="fa fa-file"></span> '.$langs->trans("PathToModuleDocumentation", "PDF").' : ';
7000 if (!dol_is_file($outputfiledocpdf)) {
7001 print '<span class="opacitymedium">'.$langs->trans("FileNotYetGenerated").'</span>';
7002 } else {
7003 print '<strong>';
7004 print '<a href="'.$outputfiledocurlpdf.'" target="_blank" rel="noopener noreferrer">';
7005 print $outputfiledocpdf;
7006 print '</a>';
7007 print '</strong>';
7008 print ' <span class="opacitymedium">('.$langs->trans("GeneratedOn").' '.dol_print_date(dol_filemtime($outputfiledocpdf), 'dayhour').')</span>';
7009 print ' <a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=confirm_removefile&token='.newToken().'&format='.$format.'&file='.urlencode($outputfiledocrelpdf).'">'.img_picto($langs->trans("Delete"), 'delete').'</a>';
7010 }
7011 print '</strong><br>';
7012
7013 print '<br>';
7014
7015 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST" name="generatedoc">';
7016 print '<input type="hidden" name="token" value="'.newToken().'">';
7017 print '<input type="hidden" name="action" value="generatedoc">';
7018 print '<input type="hidden" name="tab" value="'.dol_escape_htmltag($tab).'">';
7019 print '<input type="hidden" name="module" value="'.dol_escape_htmltag($module).'">';
7020 print '<input type="submit" class="button" name="generatedoc" value="'.$langs->trans("BuildDocumentation").'"';
7021 if (!is_array($specs) || empty($specs)) {
7022 print ' disabled="disabled"';
7023 }
7024 print '>';
7025 print '</form>';
7026 }
7027
7028 if ($tab == 'buildpackage') {
7029 print '<!-- tab=buildpackage -->'."\n";
7030 print '<span class="opacitymedium">'.$langs->trans("BuildPackageDesc").'</span>';
7031 print '<br>';
7032
7033 if (!class_exists('ZipArchive') && !defined('ODTPHP_PATHTOPCLZIP')) {
7034 print img_warning().' '.$langs->trans("ErrNoZipEngine");
7035 print '<br>';
7036 }
7037
7038 $modulelowercase = dol_strtolower($module);
7039
7040 // Zip file to build
7041 $FILENAMEZIP = '';
7042
7043 // Load module
7044 $pathtofile = $listofmodules[dol_strtolower($module)]['moduledescriptorrelpath'];
7045 dol_include_once($pathtofile);
7046 $class = 'mod'.$module;
7047 $moduleobj = null;
7048 if (class_exists($class)) {
7049 try {
7050 $moduleobj = new $class($db);
7051 '@phan-var-force DolibarrModules $moduleobj';
7053 } catch (Exception $e) {
7054 $error++;
7055 dol_print_error($db, $e->getMessage());
7056 }
7057 }
7058 if ($moduleobj === null) {
7059 $error++;
7060 $langs->load("errors");
7061 dol_print_error($db, $langs->trans("ErrorFailedToLoadModuleDescriptorForXXX", $module));
7062 exit;
7063 }
7064
7065 $outputfilezip = null;
7066 $arrayversion = explode('.', $moduleobj->version, 3);
7067 if (count($arrayversion)) {
7068 $FILENAMEZIP = "module_".$modulelowercase.'-'.$arrayversion[0].(empty($arrayversion[1]) ? '.0' : '.'.$arrayversion[1]).(empty($arrayversion[2]) ? '' : ".".$arrayversion[2]).".zip";
7069 $outputfilezip = dol_buildpath($modulelowercase, 0).'/bin/'.$FILENAMEZIP;
7070 }
7071
7072 print '<br>';
7073
7074 print '<span class="fa fa-file"></span> '.$langs->trans("PathToModulePackage").' : ';
7075 if ($outputfilezip === null || !dol_is_file($outputfilezip)) {
7076 print '<span class="opacitymedium">'.$langs->trans("FileNotYetGenerated").'</span>';
7077 } else {
7078 $relativepath = $modulelowercase.'/bin/'.$FILENAMEZIP;
7079 print '<strong><a href="'.DOL_URL_ROOT.'/document.php?modulepart=packages&file='.urlencode($relativepath).'">'.$outputfilezip.'</a></strong>';
7080 print ' <span class="opacitymedium">('.$langs->trans("GeneratedOn").' '.dol_print_date(dol_filemtime($outputfilezip), 'dayhour').')</span>';
7081 print ' <a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=confirm_removefile&token='.newToken().'&file='.urlencode($relativepath).'">'.img_picto($langs->trans("Delete"), 'delete').'</a>';
7082 }
7083 print '</strong>';
7084
7085 print '<br>';
7086
7087 print '<br>';
7088
7089 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST" name="generatepackage">';
7090 print '<input type="hidden" name="token" value="'.newToken().'">';
7091 print '<input type="hidden" name="action" value="generatepackage">';
7092 print '<input type="hidden" name="tab" value="'.dol_escape_htmltag($tab).'">';
7093 print '<input type="hidden" name="module" value="'.dol_escape_htmltag($module).'">';
7094 print '<input type="submit" class="button" name="generatepackage" value="'.$langs->trans("BuildPackage").'">';
7095 print '</form>';
7096 }
7097
7098 if ($tab == 'tabs') {
7099 $pathtofile = $listofmodules[dol_strtolower($module)]['moduledescriptorrelpath'];
7100
7101 $tabs = $moduleobj->tabs;
7102
7103 if ($action != 'editfile' || empty($file)) {
7104 print '<span class="opacitymedium">';
7105 $htmlhelp = $langs->trans("TabsDefDescTooltip", '{s1}');
7106 $htmlhelp = str_replace('{s1}', '<a target="adminbis" class="nofocusvisible" href="'.DOL_URL_ROOT.'/admin/menus/index.php">'.$langs->trans('Setup').' - '.$langs->trans('Tabs').'</a>', $htmlhelp);
7107 print $form->textwithpicto($langs->trans("TabsDefDesc"), $htmlhelp, 1, 'help', '', 0, 2, 'helpondesc').'<br>';
7108 print '</span>';
7109 print '<br>';
7110
7111 print '<span class="fa fa-file"></span> '.$langs->trans("DescriptorFile").' : <strong>'.$pathtofile.'</strong>';
7112 print ' <a class="editfielda paddingleft paddingright" href="'.$_SERVER['PHP_SELF'].'?tab='.urlencode($tab).'&module='.$module.($forceddirread ? '@'.$dirread : '').'&action=editfile&format=php&file='.urlencode($pathtofile).'&find=TABS">'.img_picto($langs->trans("Edit"), 'edit').'</a>';
7113 print '<br>';
7114
7115 print '<br>';
7116 print load_fiche_titre($langs->trans("ListOfTabsEntries"), '', '');
7117
7118 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
7119 print '<input type="hidden" name="token" value="'.newToken().'">';
7120 print '<input type="hidden" name="action" value="addproperty">';
7121 print '<input type="hidden" name="tab" value="objects">';
7122 print '<input type="hidden" name="module" value="'.dol_escape_htmltag($module).'">';
7123 print '<input type="hidden" name="tabobj" value="'.dol_escape_htmltag($tabobj).'">';
7124
7125 print '<div class="div-table-responsive">';
7126 print '<table class="noborder small">';
7127
7128 print '<tr class="liste_titre">';
7129 print_liste_field_titre("ObjectType", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
7130 print_liste_field_titre("Tab", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
7131 print_liste_field_titre("Title", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
7132 print_liste_field_titre("LangFile", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
7133 print_liste_field_titre("Condition", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
7134 print_liste_field_titre("Path", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
7135 print "</tr>\n";
7136
7137 if (count($tabs)) {
7138 foreach ($tabs as $tab) {
7139 $parts = explode(':', $tab['data']);
7140
7141 $objectType = $parts[0];
7142 $tabName = $parts[1];
7143 $tabTitle = isset($parts[2]) ? $parts[2] : '';
7144 $langFile = isset($parts[3]) ? $parts[3] : '';
7145 $condition = isset($parts[4]) ? $parts[4] : '';
7146 $path = isset($parts[5]) ? $parts[5] : '';
7147
7148 // If we want to remove the tab, then the format is 'objecttype:tabname:optionalcondition'
7149 // See: https://wiki.dolibarr.org/index.php?title=Tabs_system#To_remove_an_existing_tab
7150 if ($tabName[0] === '-') {
7151 $tabTitle = '';
7152 $condition = isset($parts[2]) ? $parts[2] : '';
7153 }
7154
7155 print '<tr class="oddeven">';
7156
7157 print '<td>';
7158 print dol_escape_htmltag($parts[0]);
7159 print '</td>';
7160
7161 print '<td>';
7162 if ($tabName[0] === "+") {
7163 print '<span class="badge badge-status4 badge-status">' . dol_escape_htmltag($tabName) . '</span>';
7164 } else {
7165 print '<span class="badge badge-status8 badge-status">' . dol_escape_htmltag($tabName) . '</span>';
7166 }
7167 print '</td>';
7168
7169 print '<td>';
7170 print dol_escape_htmltag($tabTitle);
7171 print '</td>';
7172
7173 print '<td>';
7174 print dol_escape_htmltag($langFile);
7175 print '</td>';
7176
7177 print '<td>';
7178 print dol_escape_htmltag($condition);
7179 print '</td>';
7180
7181 print '<td>';
7182 print dol_escape_htmltag($path);
7183 print '</td>';
7184
7185 print '</tr>';
7186 }
7187 } else {
7188 print '<tr><td colspan="5"><span class="opacitymedium">'.$langs->trans("None").'</span></td></tr>';
7189 }
7190
7191 print '</table>';
7192 print '</div>';
7193
7194 print '</form>';
7195 } else {
7196 $fullpathoffile = dol_buildpath($file, 0);
7197
7198 $content = file_get_contents($fullpathoffile);
7199
7200 // New module
7201 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
7202 print '<input type="hidden" name="token" value="'.newToken().'">';
7203 print '<input type="hidden" name="action" value="savefile">';
7204 print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
7205 print '<input type="hidden" name="tab" value="'.$tab.'">';
7206 print '<input type="hidden" name="module" value="'.$module.'">';
7207
7208 $posCursor = (empty($find)) ? array() : array('find' => $find);
7209 $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%', 0, $posCursor);
7210 print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'html'));
7211 print '<br>';
7212 print '<center>';
7213 print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
7214 print ' &nbsp; ';
7215 print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
7216 print '</center>';
7217
7218 print '</form>';
7219 }
7220 }
7221
7222 if ($tab != 'description') {
7223 print dol_get_fiche_end();
7224 }
7225 }
7226}
7227
7228print dol_get_fiche_end(); // End modules
7229
7230
7231// End of page
7232llxFooter();
7233$db->close();
if(! $sortfield) if(! $sortorder) $object
Definition account.php:100
$propal type
'integer', 'integer:ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter[:Sortfield]]]',...
Definition propal.php:280
dolibarr_set_const($db, $name, $value, $type='chaine', $visible=0, $note='', $entity=1)
Insert a parameter (key,value) into database (delete old key then insert it again).
ajax_combobox($htmlname, $events=array(), $minLengthToAutocomplete=0, $forcefocus=0, $widthTypeOfAutocomplete='resolve', $idforemptyvalue='-1', $morecss='', $placeholder='')
Convert a html select field into an ajax combobox.
Definition ajax.lib.php:477
llxFooter($comment='', $zone='private', $disabledoutputofmessages=0)
Empty footer.
Definition wrapper.php:91
if(!defined('NOREQUIRESOC')) if(!defined( 'NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined( 'NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined( 'NOREQUIREAJAX')) llxHeader($head='', $title='', $help_url='', $target='', $disablejs=0, $disablehead=0, $arrayofjs='', $arrayofcss='', $morequerystring='', $morecssonbody='', $replacemainareaby='', $disablenofollow=0, $disablenoindex=0)
Empty header.
Definition wrapper.php:73
print $object position
Definition edit.php:206
Syncs rights straight into the mod<Module>.class.php descriptor file.
Class to manage a WYSIWYG editor.
Class to generate html code for admin pages.
Class to manage generation of HTML components Only common components must be here.
Class to manage triggers.
static getEmailingSelectorsList($forcedir=null)
Return list of widget.
static getWidgetsList($forcedirwidget=null)
Return list of widget.
Immutable value object holding all case variants of a module/object pair.
Immutable request describing one permissions sync to perform on a module descriptor.
static forObjectDeletion(string $module, string $descriptorFile, array $permissions, string $objectName)
Drop every right attached to an object being deleted.
static forRightDeletion(string $module, string $descriptorFile, array $permissions, int $rightKey)
Remove one right, addressed by its index in the rights array.
static forRightUpdate(string $module, string $descriptorFile, array $permissions, int $rightKey, string $objectName, string $label, string $crud)
Replace one right, addressed by its index in the rights array.
static forRightAddition(string $module, string $descriptorFile, array $permissions, string $objectName, string $label, string $crud)
Append one right to the descriptor.
static forObjectCreation(string $module, string $descriptorFile, array $permissions, string $objectName)
Declare the three CRUD rights of a newly generated object.
Strict implementation — reports any residual myobject/mymodule token as a warning.
Immutable outcome of a permissions sync run.
Class to manage utility methods.
if(! $sortfield) if(! $sortorder) $module
Definition list.php:193
global $mysoc
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $conf
The main.inc.php has been included so the following variable are now defined:
removePatternFromFile(string $filePath, string $pattern)
Removes content from a file that matches a given pattern.
dol_filemtime($pathoffile)
Return time of a file.
dol_copy($srcfile, $destfile, $newmask='0', $overwriteifexists=1, $testvirus=0, $indexdatabase=0)
Copy a file to another file.
dol_delete_file($file, $disableglob=0, $nophperrors=0, $nohook=0, $object=null, $allowdotdot=false, $indexdatabase=1, $nolog=0)
Remove a file or several files with a mask.
dol_is_writable($folderorfile)
Test if directory or filename is writable.
dol_delete_dir($dir, $nophperrors=0)
Remove a directory (not recursive, so content must be empty).
dol_delete_dir_recursive($dir, $count=0, $nophperrors=0, $onlysub=0, &$countdeleted=0, $indexdatabase=1, $nolog=0, $level=0)
Remove a directory $dir and its subdirectories (or only files and subdirectories)
dolCopyDir($srcfile, $destfile, $newmask, $overwriteifexists, $arrayreplacement=null, $excludesubdir=0, $excludefileext=null, $excludearchivefiles=0)
Copy a dir to another dir.
dol_is_file($pathoffile)
Return if path is a file.
dol_dir_list($utf8_path, $types="all", $recursive=0, $filter="", $excludefilter=null, $sortcriteria="name", $sortorder=SORT_ASC, $mode=0, $nohook=0, $relativename="", $donotfollowsymlinks=0, $nbsecondsold=0)
Scan a directory and return a list of files/directories.
Definition files.lib.php:65
dol_is_dir($folder)
Test if filename is a directory.
dolReplaceInFile($srcfile, $arrayreplacement, $destfile='', $newmask='0', $indexdatabase=0, $arrayreplacementisregex=0)
Make replacement of strings into a file.
dol_is_dir_empty($dir)
Return if path is empty.
dol_now($mode='gmt')
Return date for now.
dolExplodeIntoArray($string, $delimiter=';', $kv='=')
Split a string with 2 keys into key array.
dol_ucfirst($string, $encoding="UTF-8")
Convert first character of the first word of a string to upper.
dol_strtolower($string, $encoding="UTF-8")
Convert a string to lower.
dol_mimetype($file, $default='application/octet-stream', $mode=0)
Return MIME type of a file from its name with extension.
dol_osencode($str)
Return a string encoded into OS filesystem encoding.
dol_sanitizePathName($str, $newstr='_', $unaccent=0, $allowdash=0)
Clean a string to use it as a path name.
dol_sanitizeFileName($str, $newstr='_', $unaccent=1, $includequotes=0, $allowdash=0)
Clean a string to use it as a file name.
dol_strlen($string, $stringencoding='UTF-8')
Make a strlen call.
dolChmod($filepath, $newmask='')
Change mod of a file.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
dol_sort_array(&$array, $index, $order='asc', $natsort=0, $case_sensitive=0, $keepindex=0)
Advanced sort array by the value of a given key, which produces ascending (default) or descending out...
if(!function_exists( 'dol_getprefix')) dol_include_once($relpath, $classname='')
Make an include_once using default root and alternate root if it fails.
newToken()
Return the value of token currently saved into session with name 'newtoken'.
dol_string_unaccent($str)
Clean a string from all accent characters to be used as ref, login or by dol_sanitizeFileName.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0, $nodefault=0)
Return value of a param into GET or POST supervariable.
dol_strtoupper($string, $encoding="UTF-8")
Convert a string to upper.
dol_substr($string, $start, $length=null, $stringencoding='', $trunconbytes=0)
Make a substring.
GETPOSTINT($paramname, $method=0, $nodefault=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
dol_string_nounprintableascii($str, $removetabcrlf=1)
Clean a string from all non printable ASCII chars (0x00-0x1F and 0x7F).
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false, $decorate=0)
Output date in a string format according to outputlangs (or langs if not defined).
dol_trunc($string, $size=40, $trunc='right', $stringencoding='UTF-8', $nodot=0, $display=0)
Truncate a string to a particular length adding '...' if string larger than length.
GETPOSTISSET($paramname)
Return true if we are in a context of submitting the parameter $paramname from a POST of a form.
dol_ucwords($string, $encoding="UTF-8")
Convert first character of all the words of a string to upper.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
isModEnabled($module)
Is Dolibarr module enabled.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
dol_mkdir($dir, $dataroot='', $newmask='')
Creation of a directory (this can create recursive subdir)
treeview li table
No Email.
a disabled
print_liste_field_titre($name, $file="", $field="", $begin="", $param="", $moreattrib="", $sortfield="", $sortorder="", $prefix="", $tooltip="", $forcenowrapcolumntitle=0)
Show title line of an array.
dol_get_fiche_head($links=array(), $active='', $title='', $notab=0, $picto='', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limittoshow=0, $moretabssuffix='', $dragdropfile=0, $morecssdiv='')
Show tabs of a record.
Definition html.lib.php:540
dolButtonToOpenUrlInDialogPopup($name, $label, $buttonstring, $url, $disabled='', $morecss='classlink button bordertransp', $jsonopen='', $jsonclose='', $accesskey='')
Return HTML code to output a button to open a dialog popup box.
Definition html.lib.php:435
dolGetButtonTitle($label, $helpText='', $iconClass='fa fa-file', $url='', $id='', $status=1, $params=array())
Function dolGetButtonTitle : this kind of buttons are used in title in list.
dol_get_fiche_end($notab=0)
Return tab footer of a card.
Definition html.lib.php:738
getPictoForType($key, $morecss='')
Return the picto for a data type.
load_fiche_titre($title, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='', $morecssonpicto='widthpictotitle')
Load a title with picto.
info_admin($text, $infoonimgalt=0, $nodiv=0, $admin='1', $morecss='hideonsmartphone', $textfordropdown='', $picto='', $textonpictotooltip='', $cssfordropdown='info_admin')
Show information in HTML for admin users or standard users.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Definition html.lib.php:181
$moduleobj
Definition index.php:3540
getLicenceHeader($user, $langs, $now)
Produce copyright replacement string for user.
Definition index.php:270
modulebuilderValidateGeneratedFile(string $destfile, NamingContract $nc)
Post-generation validation – logs and displays a warning if residual myobject/mymodule tokens remain.
Definition index.php:291
foreach( $dirsrootforscan as $tmpdirread) moduleBuilderShutdownFunction()
Add management to catch fatal errors - shutdown handler.
Definition index.php:246
getModuleBuilderDefaultEnabledKeys($map)
Return the keys enabled by default in a ModuleBuilder generation map.
updateDictionaryInFile($module, $file, $dicts)
Updates a dictionary in a module descriptor file.
deletePropsAndPermsFromDoc($file, $objectname)
Delete property and permissions from documentation ascii file if we delete an object.
getModuleBuilderCardActionUncommentPatterns($marker)
Build the regular expressions removing the comment fence of a card action generated in 'activate' mod...
createNewDictionnary($modulename, $file, $namedic, $dictionnaires=null)
Create a new dictionary table.
filterEnabledKeys($requested, $map)
Filter a list of requested keys against a known map of generable elements.
countItemsInDirectory($path, $type=1)
count directories or files in modulebuilder folder
getModuleBuilderCardActionBlockPattern($marker)
Build the regular expression matching every block of a card action in the object card template.
writePermsInAsciiDoc($file, $destfile)
Write all permissions of each object in AsciiDoc format.
reWriteAllMenus($file, $menus, $menuWantTo, $key, $action)
rebuildObjectSql($destdir, $module, $objectname, $newmask, $readdir='', $object=null, $moduletype='external')
Save data into a memory area shared by all users, all sessions on server.
writeApiUrlsInDoc($file_api, $file_doc)
Generate Urls and add them to documentation module.
dolGetListOfObjectClasses($destdir)
Get list of existing objects from a directory.
getModuleBuilderLinesBlockPattern()
Return the regular expression matching a block of object lines code in the templates,...
writePropsInAsciiDoc($file, $objectname, $destfile)
Write all properties of the object in AsciiDoc format.
removeObjectFromApiFile($file, $objects, $objectname)
Remove Object variables and methods from API_Module File.
getModuleBuilderObjectCardActions()
Return the map of optional action buttons that can be generated on the card page of a ModuleBuilder o...
dolReplaceInFilePreservingModuleBuilderMarkers($file, $arrayreplacement)
Apply substitutions to a module descriptor file while preserving the MODULEBUILDER comment markers.
rebuildObjectClass($destdir, $module, $objectname, $newmask, $readdir='', $addfieldentry=array(), $delfieldentry='')
Regenerate files .class.php.
checkExistComment($file, $number)
Function to check if comment BEGIN and END exists in modMyModule class.
getModuleBuilderObjectTabs()
Return the map of optional tabs that can be generated for a ModuleBuilder object.
addObjectsToApiFile($srcfile, $file, $objects, $modulename)
Add Object in ModuleApi File.
$conf db user
Active Directory does not allow anonymous connections.
Definition repair.php:141
$conf db name
Only used if Module[ID]Name translation string is not found.
Definition repair.php:140
restrictedArea(User $user, $features, $object=0, $tableandshare='', $feature2='', $dbt_keyfield='fk_soc', $dbt_select='rowid', $isdraft=0, $nodie=0, $mode='')
Check permissions of a user to show a page and an object.
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program.