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';
50'
51@phan-var-force string $dolibarr_main_document_root
52@phan-var-force string $dolibarr_main_document_root_alt
53';
54require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
55require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
56require_once DOL_DOCUMENT_ROOT.'/core/class/html.formadmin.class.php';
57require_once DOL_DOCUMENT_ROOT.'/core/lib/modulebuilder.lib.php';
58require_once DOL_DOCUMENT_ROOT.'/modulebuilder/class/NamingContractValidator.class.php';
59require_once DOL_DOCUMENT_ROOT.'/modulebuilder/class/RightsSyncService.class.php';
60require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
61require_once DOL_DOCUMENT_ROOT.'/core/class/utils.class.php';
62
63// Load translation files required by the page
64$langs->loadLangs(array("admin", "modulebuilder", "exports", "other", "cron", "errors", "uxdocumentation"));
65
66// GET Parameters
67$action = GETPOST('action', 'aZ09');
68$confirm = GETPOST('confirm', 'alpha');
69$cancel = GETPOST('cancel', 'alpha');
70
71$sortfield = GETPOST('sortfield', 'aZ09comma');
72$sortorder = GETPOST('sortorder', 'aZ09');
73
74$module = (string) GETPOST('module', 'alpha');
75$tab = (string) GETPOST('tab', 'aZ09');
76$tabobj = GETPOST('tabobj', 'alpha');
77$tabdic = GETPOST('tabdic', 'alpha');
78$propertykey = GETPOST('propertykey', 'alpha');
79if (empty($module)) {
80 $module = 'initmodule';
81}
82if (empty($tab)) {
83 $tab = 'description';
84}
85'@phan-var-force string $tab'; // Workaround 'empty()' bug of phan
86if (empty($tabobj)) {
87 $tabobj = 'newobjectifnoobj';
88}
89if (empty($tabdic)) {
90 $tabdic = 'newdicifnodic';
91}
92$file = GETPOST('file', 'alpha');
93$find = GETPOST('find', 'alpha');
94
95$modulename = dol_sanitizeFileName(GETPOST('modulename', 'alpha'));
96$objectname = dol_sanitizeFileName(GETPOST('objectname', 'alpha'));
97$dicname = dol_sanitizeFileName(GETPOST('dicname', 'alpha'));
98$editorname = (string) GETPOST('editorname', 'alpha');
99$editorurl = (string) GETPOST('editorurl', 'alpha');
100$version = (string) GETPOST('version', 'alpha');
101$family = (string) GETPOST('family', 'alpha');
102$picto = (string) GETPOST('idpicto', 'alpha');
103$idmodule = (string) GETPOST('idmodule', 'alpha');
104$format = ''; // Prevent undefined in css tab
105
106// Security check
107if (!isModEnabled('modulebuilder')) {
108 accessforbidden('Module ModuleBuilder not enabled');
109}
110if (!$user->hasRight("modulebuilder", "run")) { // after this test $user->hasRight("modulebuilder", "run") is always true, no need to check it more
111 accessforbidden('ModuleBuilderNotAllowed');
112}
113
114// Dir for custom dirs
115$tmp = explode(',', $dolibarr_main_document_root_alt);
116$dirins = $tmp[0];
117$dirread = $dirins;
118$forceddirread = 0;
119
120$tmpdir = explode('@', $module);
121if (!empty($tmpdir[1])) {
122 $module = $tmpdir[0];
123 $dirread = $tmpdir[1];
124 $forceddirread = 1;
125}
126if (GETPOST('dirins', 'alpha')) {
127 $dirread = $dirins = GETPOST('dirins', 'alpha');
128 $forceddirread = 1;
129}
130
131$FILEFLAG = 'modulebuilder.txt';
132
133$now = dol_now();
134$newmask = 0;
135if (empty($newmask) && getDolGlobalString('MAIN_UMASK')) {
136 $newmask = getDolGlobalString('MAIN_UMASK');
137}
138if (empty($newmask)) { // This should no happen
139 $newmask = '0664';
140}
141
142$result = restrictedArea($user, 'modulebuilder', 0);
143
144$error = 0;
145$param = '';
146
147$form = new Form($db);
148
149// Define $listofmodules
150$dirsrootforscan = array($dirread);
151
152// Add also the core modules into the list of modules to show/edit
153if ($dirread != DOL_DOCUMENT_ROOT && (getDolGlobalInt('MAIN_FEATURES_LEVEL') >= 2 || getDolGlobalString('MODULEBUILDER_ADD_DOCUMENT_ROOT'))) {
154 $dirsrootforscan[] = DOL_DOCUMENT_ROOT;
155}
156
157// Search modules to edit
158$textforlistofdirs = '<!-- Directory scanned -->'."\n";
159$listofmodules = array();
160'@phan-var-force array<string,array{modulenamewithcase:string,moduledescriptorrelpath:string,moduledescriptorfullpath:string,moduledescriptorrootpath,moduletype?:string}> $listofmodules';
161$i = 0;
162foreach ($dirsrootforscan as $tmpdirread) {
163 $moduletype = 'external';
164 if ($tmpdirread == DOL_DOCUMENT_ROOT) {
165 $moduletype = 'internal';
166 }
167
168 $dirsincustom = dol_dir_list($tmpdirread, 'directories');
169 if (is_array($dirsincustom) && count($dirsincustom) > 0) {
170 foreach ($dirsincustom as $dircustomcursor) {
171 $fullname = $dircustomcursor['fullname'];
172 if (dol_is_file($fullname.'/'.$FILEFLAG)) {
173 // Get real name of module (MyModule instead of mymodule)
174 $dirtoscanrel = basename($fullname).'/core/modules/';
175
176 $descriptorfiles = dol_dir_list(dirname($fullname).'/'.$dirtoscanrel, 'files', 0, 'mod.*\.class\.php$');
177 if (empty($descriptorfiles)) { // If descriptor not found into module dir, we look into main module dir.
178 $dirtoscanrel = 'core/modules/';
179 $descriptorfiles = dol_dir_list($fullname.'/../'.$dirtoscanrel, 'files', 0, 'mod'.strtoupper(basename($fullname)).'\.class\.php$');
180 }
181 $modulenamewithcase = '';
182 $moduledescriptorrelpath = '';
183 $moduledescriptorfullpath = '';
184
185 foreach ($descriptorfiles as $descriptorcursor) {
186 $modulenamewithcase = preg_replace('/^mod/', '', $descriptorcursor['name']);
187 $modulenamewithcase = preg_replace('/\.class\.php$/', '', $modulenamewithcase);
188 $moduledescriptorrelpath = $dirtoscanrel.$descriptorcursor['name'];
189 $moduledescriptorfullpath = $descriptorcursor['fullname'];
190 //var_dump($descriptorcursor);
191 }
192 if ($modulenamewithcase) {
193 $listofmodules[$dircustomcursor['name']] = array(
194 'modulenamewithcase' => $modulenamewithcase,
195 'moduledescriptorrelpath' => $moduledescriptorrelpath,
196 'moduledescriptorfullpath' => $moduledescriptorfullpath,
197 'moduledescriptorrootpath' => $tmpdirread,
198 'moduletype' => $moduletype
199 );
200 }
201 //var_dump($listofmodules);
202 }
203 }
204 }
205
206 if ($forceddirread && empty($listofmodules)) { // $forceddirread is 1 if we forced dir to read with dirins=... or with module=...@mydir
207 $listofmodules[strtolower($module)] = array(
208 'modulenamewithcase' => $module,
209 'moduledescriptorrelpath' => 'notyetimplemented',
210 'moduledescriptorfullpath' => 'notyetimplemented',
211 'moduledescriptorrootpath' => 'notyetimplemented',
212 );
213 }
214
215 // Show description of content
216 $newdircustom = $dirins;
217 if (empty($newdircustom)) {
218 $newdircustom = img_warning();
219 }
220 // If dirread was forced to somewhere else, by using URL
221 // htdocs/modulebuilder/index.php?module=Inventory@/home/ldestailleur/git/dolibarr/htdocs/product
222 if (empty($i)) {
223 $textforlistofdirs .= $langs->trans("DirScanned").' : ';
224 } else {
225 $textforlistofdirs .= ', ';
226 }
227 $textforlistofdirs .= '<strong class="wordbreakimp">'.$tmpdirread.'</strong>';
228 if ($tmpdirread == DOL_DOCUMENT_ROOT) {
229 if (getDolGlobalInt('MAIN_FEATURES_LEVEL') >= 2) {
230 $textforlistofdirs .= $form->textwithpicto('', $langs->trans("ConstantIsOn", "MAIN_FEATURES_LEVEL"));
231 }
232 if (getDolGlobalString('MODULEBUILDER_ADD_DOCUMENT_ROOT')) {
233 $textforlistofdirs .= $form->textwithpicto('', $langs->trans("ConstantIsOn", "MODULEBUILDER_ADD_DOCUMENT_ROOT"));
234 }
235 }
236 $i++;
237}
238
245{
246 $error = error_get_last();
247 if ($error && ($error['type'] & (E_ERROR | E_PARSE | E_CORE_ERROR | E_COMPILE_ERROR | E_USER_ERROR))) {
248 // Handle the fatal error
249 echo "Fatal error occurred: {$error['message']} in {$error['file']} on line {$error['line']}";
250 // If a header was already send, we suppose it is the llx_Header() so we call the llxFooter()
251 if (headers_sent()) {
252 llxFooter();
253 }
254 }
255}
256register_shutdown_function("moduleBuilderShutdownFunction");
257
258
268function getLicenceHeader($user, $langs, $now)
269{
270 $licInfo = $user->getFullName($langs);
271 $emailTabs = str_repeat("\t", (int) (max(0, (31 - mb_strlen($licInfo)) / 4)));
272 $licInfo .= ($user->email ? $emailTabs.'<'.$user->email.'>' : '');
273 $licInfo = dol_print_date($now, '%Y')."\t\t".$licInfo;
274 return $licInfo;
275}
276
277
278/*
279 * Actions
280 */
281
289function modulebuilderValidateGeneratedFile(string $destfile, NamingContract $nc): void
290{
291 $content = file_get_contents($destfile);
292 if ($content === false) {
293 return;
294 }
295 $validator = new StrictNamingContractValidator();
296 $errors = $validator->validateContent($content, $destfile);
297 if (!empty($errors)) {
299 'ModuleBuilder NamingContract validation warning in ' . $destfile . ': '
300 . implode('; ', array_slice($errors, 0, 3)),
301 LOG_WARNING
302 );
303 $safeErrors = array_map('dol_escape_htmltag', array_slice($errors, 0, 5));
304 setEventMessages(implode('<br>', $safeErrors), null, 'warnings');
305 }
306}
307
314function modulebuilderSyncRights(RightsSyncCommand $cmd): SyncReport
315{
316 global $langs;
317
318 $service = new DescriptorRightsSyncService();
319 $report = $service->sync($cmd);
320
321 if ($report->hasWarnings()) {
322 $safe = array_map('dol_escape_htmltag', array_slice($report->warnings, 0, 5));
323 setEventMessages($langs->trans('ModuleBuilderPermissionsNormalized').'<br>'.implode('<br>', $safe), null, 'warnings');
324 }
325 if ($report->hasConflicts()) {
326 $safe = array_map('dol_escape_htmltag', array_slice($report->conflicts, 0, 5));
327 setEventMessages($langs->trans('ModuleBuilderPermissionsNotChanged').'<br>'.implode('<br>', $safe), null, 'errors');
328 }
329
330 return $report;
331}
332
333if ($dirins && $action == 'initmodule' && $modulename) { // Test on permission already done
334 $modulename = dol_string_nounprintableascii(dol_string_unaccent(ucwords($modulename))); // Force first letter in uppercase
335 $destdir = '/not_set/';
336 $ncModule = new NamingContract($modulename);
337
338 if (preg_match('/[^a-z0-9]/i', $modulename)) {
339 $error++;
340 setEventMessages($langs->trans("SpaceOrSpecialCharAreNotAllowed"), null, 'errors');
341 }
342
343 if (!$error) {
344 $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template';
345 $destdir = $dirins.'/'.strtolower($modulename);
346
347 $arrayreplacement = [
348 'mymodule' => $ncModule->moduleNameLower,
349 'MyModule' => $ncModule->moduleNameCase,
350 ];
351 $result = dolCopyDir($srcdir, $destdir, '0', 0, $arrayreplacement);
352 //dol_mkdir($destfile);
353 if ($result <= 0) {
354 if ($result < 0) {
355 $error++;
356 $langs->load("errors");
357 setEventMessages($langs->trans("ErrorFailToCopyDir", $srcdir, $destdir), null, 'errors');
358 } else {
359 // $result == 0
360 setEventMessages($langs->trans("AllFilesDidAlreadyExist", $srcdir, $destdir), null, 'warnings');
361 }
362 }
363
364 // Copy last 'html.formsetup.class.php' to backport folder
365 if (getDolGlobalInt('MODULEBUILDER_SUPPORT_COMPATIBILITY_V16')) {
366 $tryToCopyFromSetupClass = true;
367 $backportDest = $destdir .'/backport/v16/core/class';
368 $backportFileSrc = DOL_DOCUMENT_ROOT.'/core/class/html.formsetup.class.php';
369 $backportFileDest = $backportDest.'/html.formsetup.class.php';
370 $result = dol_mkdir($backportDest);
371
372 if ($result < 0) {
373 $error++;
374 $langs->load("errors");
375 setEventMessages($langs->trans("ErrorFailToCreateDir", $backportDest), null, 'errors');
376 $tryToCopyFromSetupClass = false;
377 }
378
379 if ($tryToCopyFromSetupClass) {
380 $result = dol_copy($backportFileSrc, $backportFileDest);
381 if ($result <= 0) {
382 if ($result < 0) {
383 $error++;
384 $langs->load("errors");
385 setEventMessages($langs->trans("ErrorFailToCopyFile", $backportFileSrc, $backportFileDest), null, 'errors');
386 } else {
387 setEventMessages($langs->trans("FileDidAlreadyExist", $backportFileDest), null, 'warnings');
388 }
389 }
390 }
391 }
392
393 if (getDolGlobalString('MODULEBUILDER_USE_ABOUT')) {
394 dol_delete_file($destdir.'/admin/about.php');
395 }
396
397 // Delete dir and files that can be generated in sub tabs later if we need them (we want a minimal module first)
398 dol_delete_dir_recursive($destdir.'/ajax');
399 dol_delete_dir_recursive($destdir.'/build/doxygen');
400 dol_delete_dir_recursive($destdir.'/core/modules/mailings');
401 dol_delete_dir_recursive($destdir.'/core/modules/'.strtolower($modulename));
402 dol_delete_dir_recursive($destdir.'/core/tpl');
403 dol_delete_dir_recursive($destdir.'/core/triggers');
404 dol_delete_dir_recursive($destdir.'/doc');
405 //dol_delete_dir_recursive($destdir.'/.tx');
406 dol_delete_dir_recursive($destdir.'/core/boxes');
407
408 dol_delete_file($destdir.'/admin/myobject_extrafields.php');
409
410 dol_delete_file($destdir.'/class/actions_'.strtolower($modulename).'.class.php');
411 dol_delete_file($destdir.'/class/api_'.strtolower($modulename).'.class.php');
412
413 dol_delete_file($destdir.'/css/'.strtolower($modulename).'.css.php');
414
415 dol_delete_file($destdir.'/js/'.strtolower($modulename).'.js.php');
416
417 dol_delete_file($destdir.'/scripts/'.strtolower($modulename).'.php');
418
419 dol_delete_file($destdir.'/sql/data.sql');
420 dol_delete_file($destdir.'/sql/update_x.x.x-y.y.y.sql');
421
422 // Delete some files related to Object (because the previous dolCopyDir has copied everything)
423 dol_delete_file($destdir.'/myobject_card.php');
424 dol_delete_file($destdir.'/myobject_contact.php');
425 dol_delete_file($destdir.'/myobject_note.php');
426 dol_delete_file($destdir.'/myobject_document.php');
427 dol_delete_file($destdir.'/myobject_agenda.php');
428 dol_delete_file($destdir.'/myobject_list.php');
429 dol_delete_file($destdir.'/lib/'.strtolower($modulename).'_myobject.lib.php');
430 dol_delete_file($destdir.'/test/phpunit/functional/'.$modulename.'FunctionalTest.php');
431 dol_delete_file($destdir.'/test/phpunit/MyObjectTest.php');
432 dol_delete_file($destdir.'/sql/llx_'.strtolower($modulename).'_myobject.sql');
433 dol_delete_file($destdir.'/sql/llx_'.strtolower($modulename).'_myobject_extrafields.sql');
434 dol_delete_file($destdir.'/sql/llx_'.strtolower($modulename).'_myobject.key.sql');
435 dol_delete_file($destdir.'/sql/llx_'.strtolower($modulename).'_myobject_extrafields.key.sql');
436 dol_delete_file($destdir.'/class/myobject.class.php');
437 dol_delete_file($destdir.'/class/myobjectstats.class.php');
438
439 dol_delete_dir($destdir.'/class', 1);
440 dol_delete_dir($destdir.'/css', 1);
441 dol_delete_dir($destdir.'/js', 1);
442 dol_delete_dir($destdir.'/scripts', 1);
443 dol_delete_dir($destdir.'/sql', 1);
444 dol_delete_dir($destdir.'/test/phpunit/functionnal', 1);
445 dol_delete_dir($destdir.'/test/phpunit', 1);
446 dol_delete_dir($destdir.'/test', 1);
447 }
448
449 // Edit PHP files
450 if (!$error) {
451 $listofphpfilestoedit = dol_dir_list($destdir, 'files', 1, '\.(php|MD|js|sql|txt|xml|lang)$', '', 'fullname', SORT_ASC, 0, 1);
452
453 $licInfo = getLicenceHeader($user, $langs, $now);
454 foreach ($listofphpfilestoedit as $phpfileval) {
455 //var_dump($phpfileval['fullname']);
456 $arrayreplacement = array_merge(
457 $ncModule->getSubstitutionMap(),
458 [
459 'htdocs/modulebuilder/template' => $ncModule->moduleNameLower,
460 '---Put here your own copyright and developer email---' => $licInfo,
461 '---Replace with your own copyright and developer email---' => $licInfo,
462 'Editor name' => $editorname,
463 'https://www.example.com' => $editorurl,
464 '$this->version = \'1.0\'' => '$this->version = \'' . $version . '\'',
465 '$this->picto = \'generic\';' => (empty($picto)) ? '$this->picto = \'generic\'' : '$this->picto = \'' . $picto . '\';',
466 'modulefamily' => $family,
467 // Key '500000' would be cast to int(500000) by PHP, then renumbered to 0 by
468 // array_merge -- causing str_replace to search for '0' instead of '500000'.
469 // Use a string key that matches the exact assignment line to avoid this.
470 '$this->numero = 500000' => '$this->numero = '.$idmodule,
471 ]
472 );
473
474 if (getDolGlobalString('MODULEBUILDER_SPECIFIC_AUTHOR')) {
475 $arrayreplacement['---Replace with your own copyright and developer email---'] = dol_print_date($now, '%Y')."\t\t" . getDolGlobalString('MODULEBUILDER_SPECIFIC_AUTHOR');
476 }
477
478 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
479 $result = dolReplaceInFile($phpfileval['fullname'], $arrayreplacement); // @phpstan-ignore-line
480 //var_dump($result);
481 if ($result < 0) {
482 setEventMessages($langs->trans("ErrorFailToMakeReplacementInto", $phpfileval['fullname']), null, 'errors');
483 }
484 }
485
486 if (getDolGlobalString('MODULEBUILDER_SPECIFIC_README')) {
487 setEventMessages($langs->trans("ContentOfREADMECustomized"), null, 'warnings');
488 dol_delete_file($destdir.'/README.md');
489 file_put_contents($destdir.'/README.md', getDolGlobalString("MODULEBUILDER_SPECIFIC_README"));
490 dolChmod($destdir.'/README.md');
491 }
492 // for create file to add properties
493 // file_put_contents($destdir.'/'.strtolower($modulename).'propertycard.php','');
494 // $srcFileCard = DOL_DOCUMENT_ROOT.'/modulebuilder/card.php';
495 // $destFileCard = $dirins.'/'.strtolower($modulename).'/template/card.php';
496 // dol_copy($srcFileCard, $destdir.'/'.strtolower($modulename).'propertycard.php', '0',1, $arrayreplacement);
497 }
498
499 if (!$error) {
500 setEventMessages($langs->trans('ModuleInitialized', $destdir), null);
501 $module = $modulename;
502
503 clearstatcache(true);
504 if (function_exists('opcache_invalidate')) {
505 opcache_reset(); // remove the include cache hell !
506 }
507
508 header("Location: ".$_SERVER["PHP_SELF"].'?module='.$modulename);
509 exit;
510 }
511}
512
513$destdir = '/not_set/'; // Initialize (for static analysis)
514$destfile = '/not_set/'; // Initialize (for static analysis)
515$srcfile = '/not_set/'; // Initialize (for static analysis)
516
517// init API, PHPUnit
518if ($dirins && in_array($action, array('initapi', 'initphpunit', 'initpagecontact', 'initpagedocument', 'initpagenote', 'initpageagenda')) && !empty($module) /* && $user->hasRight("modulebuilder", "run") // already checked */) {
519 $modulename = ucfirst($module); // Force first letter in uppercase
520 $objectname = $tabobj;
521 $varnametoupdate = '';
522 $dirins = $listofmodules[strtolower($module)]['moduledescriptorrootpath'];
523 $destdir = $dirins.'/'.strtolower($module);
524
525 // Get list of existing objects
526 $objects = dolGetListOfObjectClasses($destdir);
527
528
529 if ($action == 'initapi') { // Test on permission already done
530 if (file_exists($dirins.'/'.strtolower($module).'/class/api_'.strtolower($module).'.class.php')) {
531 $result = dol_copy(DOL_DOCUMENT_ROOT.'/modulebuilder/template/class/api_mymodule.class.php', $dirins.'/'.strtolower($module).'/class/api_'.strtolower($module).'.class.php', '0', 1);
532 }
533 dol_mkdir($dirins.'/'.strtolower($module).'/class');
534 $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template';
535 $srcfile = $srcdir.'/class/api_mymodule.class.php';
536 $destfile = $dirins.'/'.strtolower($module).'/class/api_'.strtolower($module).'.class.php';
537 } elseif ($action == 'initphpunit') { // Test on permission already done
538 dol_mkdir($dirins.'/'.strtolower($module).'/test/phpunit');
539 $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template';
540 $srcfile = $srcdir.'/test/phpunit/MyObjectTest.php';
541 $destfile = $dirins.'/'.strtolower($module).'/test/phpunit/'.strtolower($objectname).'Test.php';
542 } elseif ($action == 'initpagecontact') { // Test on permission already done
543 dol_mkdir($dirins.'/'.strtolower($module));
544 $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template';
545 $srcfile = $srcdir.'/myobject_contact.php';
546 $destfile = $dirins.'/'.strtolower($module).'/'.strtolower($objectname).'_contact.php';
547 $varnametoupdate = 'showtabofpagecontact';
548 } elseif ($action == 'initpagedocument') { // Test on permission already done
549 dol_mkdir($dirins.'/'.strtolower($module));
550 $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template';
551 $srcfile = $srcdir.'/myobject_document.php';
552 $destfile = $dirins.'/'.strtolower($module).'/'.strtolower($objectname).'_document.php';
553 $varnametoupdate = 'showtabofpagedocument';
554 } elseif ($action == 'initpagenote') { // Test on permission already done
555 dol_mkdir($dirins.'/'.strtolower($module));
556 $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template';
557 $srcfile = $srcdir.'/myobject_note.php';
558 $destfile = $dirins.'/'.strtolower($module).'/'.strtolower($objectname).'_note.php';
559 $varnametoupdate = 'showtabofpagenote';
560 } elseif ($action == 'initpageagenda') { // Test on permission already done
561 dol_mkdir($dirins.'/'.strtolower($module));
562 $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template';
563 $srcfile = $srcdir.'/myobject_agenda.php';
564 $destfile = $dirins.'/'.strtolower($module).'/'.strtolower($objectname).'_agenda.php';
565 $varnametoupdate = 'showtabofpageagenda';
566 }
567
568 if (!file_exists($destfile)) {
569 $result = dol_copy($srcfile, $destfile, '0', 0);
570 }
571
572 if ($result > 0) {
573 //var_dump($phpfileval['fullname']);
574 try {
575 $ncApiObj = new NamingContract($modulename, $objectname);
576 } catch (\InvalidArgumentException $e) {
577 $error++;
578 setEventMessages($langs->trans("SpaceOrSpecialCharAreNotAllowed"), null, 'errors');
579 $ncApiObj = null;
580 }
581
582 if (!$error && $ncApiObj !== null) {
583 $arrayreplacement = array_merge(
584 $ncApiObj->getSubstitutionMap(),
585 [
586 'htdocs/modulebuilder/template' => $ncApiObj->moduleNameLower,
587 '---Replace with your own copyright and developer email---' => getLicenceHeader($user, $langs, $now),
588 ]
589 );
590
591 if ($action == 'initapi') { // Test on permission already done
592 if (count($objects) >= 1) {
593 addObjectsToApiFile($srcfile, $destfile, $objects, $modulename);
594 }
595 // Fix PHPDoc header and class-declaration residuals left by addObjectsToApiFile.
596 // 'MYOBJECT' (uppercase) is excluded to preserve the /* BEGIN MODULEBUILDER API MYOBJECT */
597 // placeholder that addObjectsToApiFile keeps for future object additions.
598 $headerFix = $arrayreplacement;
599 unset($headerFix['MYOBJECT']);
600 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
601 dolReplaceInFile($destfile, $headerFix);
602 modulebuilderValidateGeneratedFile($destfile, $ncApiObj);
603 } else {
604 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
605 dolReplaceInFile($destfile, $arrayreplacement);
606 modulebuilderValidateGeneratedFile($destfile, $ncApiObj);
607 }
608 }
609
610 if ($varnametoupdate) {
611 // Now we update the object file to set $$varnametoupdate to 1
612 $srcfile = $dirins.'/'.strtolower($module).'/lib/'.strtolower($module).'_'.strtolower($objectname).'.lib.php';
613 $arrayreplacement = array('/\$'.preg_quote($varnametoupdate, '/').' = 0;/' => '$'.$varnametoupdate.' = 1;');
614 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
615 dolReplaceInFile($srcfile, $arrayreplacement, '', '0', 0, 1);
616 }
617 } else {
618 $langs->load("errors");
619 setEventMessages($langs->trans('ErrorFailToCreateFile', $destfile), null, 'errors');
620 }
621}
622
623
624// init ExtraFields
625if ($dirins && $action == 'initsqlextrafields' && !empty($module) /* && $user->hasRight("modulebuilder", "run") // already checked */) {
626 $modulename = ucfirst($module); // Force first letter in uppercase
627 $objectname = $tabobj;
628
629 dol_mkdir($dirins.'/'.strtolower($module).'/sql');
630 $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template';
631 $srcfile1 = $srcdir.'/sql/llx_mymodule_myobject_extrafields.sql';
632 $destfile1 = $dirins.'/'.strtolower($module).'/sql/llx_'.strtolower($module).'_'.strtolower($objectname).'_extrafields.sql';
633 $result1 = dol_copy($srcfile1, $destfile1, '0', 0);
634 $srcfile2 = $srcdir.'/sql/llx_mymodule_myobject_extrafields.key.sql';
635 $destfile2 = $dirins.'/'.strtolower($module).'/sql/llx_'.strtolower($module).'_'.strtolower($objectname).'_extrafields.key.sql';
636 $result2 = dol_copy($srcfile2, $destfile2, '0', 0);
637
638 if ($result1 > 0 && $result2 > 0) {
639 $modulename = ucfirst($module); // Force first letter in uppercase
640
641 //var_dump($phpfileval['fullname']);
642 try {
643 $ncSqlObj = new NamingContract($modulename, $objectname);
644 } catch (\InvalidArgumentException $e) {
645 $error++;
646 setEventMessages($langs->trans("SpaceOrSpecialCharAreNotAllowed"), null, 'errors');
647 $ncSqlObj = null;
648 }
649
650 if (!$error && $ncSqlObj !== null) {
651 $arrayreplacement = array_merge(
652 $ncSqlObj->getSubstitutionMap(),
653 [
654 'htdocs/modulebuilder/template' => $ncSqlObj->moduleNameLower,
655 '---Replace with your own copyright and developer email---' => getLicenceHeader($user, $langs, $now),
656 ]
657 );
658
659 dolReplaceInFile($destfile1, $arrayreplacement);
660 dolReplaceInFile($destfile2, $arrayreplacement);
661 modulebuilderValidateGeneratedFile($destfile1, $ncSqlObj);
662 modulebuilderValidateGeneratedFile($destfile2, $ncSqlObj);
663 }
664 } else {
665 $langs->load("errors");
666 if ($result1 <= 0) {
667 setEventMessages($langs->trans('ErrorFailToCreateFile', $destfile1), null, 'errors');
668 }
669 if ($result2 <= 0) {
670 setEventMessages($langs->trans('ErrorFailToCreateFile', $destfile2), null, 'errors');
671 }
672 }
673
674 // Now we update the object file to set $this->isextrafieldmanaged to 1
675 $srcfile = $dirins.'/'.strtolower($module).'/class/'.strtolower($objectname).'.class.php';
676 $arrayreplacement = array('/\$this->isextrafieldmanaged = 0;/' => '$this->isextrafieldmanaged = 1;');
677 $arrayreplacement = array('/\$isextrafieldmanaged = 0;/' => '$isextrafieldmanaged = 1;');
678 dolReplaceInFile($srcfile, $arrayreplacement, '', '0', 0, 1);
679}
680
681
682// init Hook
683if ($dirins && $action == 'inithook' && !empty($module) /* && $user->hasRight("modulebuilder", "run") // already checked */) {
684 dol_mkdir($dirins.'/'.strtolower($module).'/class');
685 $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template';
686 $srcfile = $srcdir.'/class/actions_mymodule.class.php';
687 $destfile = $dirins.'/'.strtolower($module).'/class/actions_'.strtolower($module).'.class.php';
688 $result = dol_copy($srcfile, $destfile, '0', 0);
689
690 if ($result > 0) {
691 $modulename = ucfirst($module); // Force first letter in uppercase
692
693 //var_dump($phpfileval['fullname']);
694 $arrayreplacement = array(
695 'mymodule' => strtolower($modulename),
696 'MyModule' => $modulename,
697 'MYMODULE' => strtoupper($modulename),
698 'My module' => $modulename,
699 'my module' => $modulename,
700 'Mon module' => $modulename,
701 'mon module' => $modulename,
702 'htdocs/modulebuilder/template' => strtolower($modulename),
703 '---Replace with your own copyright and developer email---' => getLicenceHeader($user, $langs, $now)
704 );
705
706 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
707 dolReplaceInFile($destfile, $arrayreplacement);
708 } else {
709 $langs->load("errors");
710 setEventMessages($langs->trans('ErrorFailToCreateFile', $destfile), null, 'errors');
711 }
712}
713
714
715// init Trigger
716if ($dirins && $action == 'inittrigger' && !empty($module) /* && $user->hasRight("modulebuilder", "run") // already checked */) {
717 dol_mkdir($dirins.'/'.strtolower($module).'/core/triggers');
718 $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template';
719 $srcfile = $srcdir.'/core/triggers/interface_99_modMyModule_MyModuleTriggers.class.php';
720 $destfile = $dirins.'/'.strtolower($module).'/core/triggers/interface_99_mod'.$module.'_'.$module.'Triggers.class.php';
721 $result = dol_copy($srcfile, $destfile, '0', 0);
722
723 if ($result > 0) {
724 $modulename = ucfirst($module); // Force first letter in uppercase
725
726 //var_dump($phpfileval['fullname']);
727 $arrayreplacement = array(
728 'mymodule' => strtolower($modulename),
729 'MyModule' => $modulename,
730 'MYMODULE' => strtoupper($modulename),
731 'My module' => $modulename,
732 'my module' => $modulename,
733 'Mon module' => $modulename,
734 'mon module' => $modulename,
735 'htdocs/modulebuilder/template' => strtolower($modulename),
736 '---Replace with your own copyright and developer email---' => getLicenceHeader($user, $langs, $now)
737 );
738
739 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
740 dolReplaceInFile($destfile, $arrayreplacement);
741 } else {
742 $langs->load("errors");
743 setEventMessages($langs->trans('ErrorFailToCreateFile', $destfile), null, 'errors');
744 }
745}
746
747
748// init Widget
749if ($dirins && $action == 'initwidget' && !empty($module) /* && $user->hasRight("modulebuilder", "run") // already checked */) {
750 dol_mkdir($dirins.'/'.strtolower($module).'/core/boxes');
751 $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template';
752 $srcfile = $srcdir.'/core/boxes/mymodulewidget1.php';
753 $destfile = $dirins.'/'.strtolower($module).'/core/boxes/'.strtolower($module).'widget1.php';
754 $result = dol_copy($srcfile, $destfile, '0', 0);
755
756 if ($result > 0) {
757 $modulename = ucfirst($module); // Force first letter in uppercase
758
759 //var_dump($phpfileval['fullname']);
760 $arrayreplacement = array(
761 'mymodule' => strtolower($modulename),
762 'MyModule' => $modulename,
763 'MYMODULE' => strtoupper($modulename),
764 'My module' => $modulename,
765 'my module' => $modulename,
766 'Mon module' => $modulename,
767 'mon module' => $modulename,
768 'htdocs/modulebuilder/template' => strtolower($modulename),
769 '---Replace with your own copyright and developer email---' => getLicenceHeader($user, $langs, $now)
770 );
771
772 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
773 dolReplaceInFile($destfile, $arrayreplacement);
774 } else {
775 $langs->load("errors");
776 setEventMessages($langs->trans('ErrorFailToCreateFile', $destfile), null, 'errors');
777 }
778}
779
780
781// init EmailSelector
782if ($dirins && $action == 'initemailing' && !empty($module) /* && $user->hasRight("modulebuilder", "run") // already checked */) {
783 dol_mkdir($dirins.'/'.strtolower($module).'/core/modules/mailings');
784 $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template';
785 $srcfile = $srcdir.'/core/modules/mailings/mailing_mymodule_selector1.modules.php';
786 $destfile = $dirins.'/'.strtolower($module).'/core/modules/mailings/mailing_'.strtolower($module).'_selector1.modules.php';
787 $result = dol_copy($srcfile, $destfile, '0', 0);
788
789 if ($result > 0) {
790 $modulename = ucfirst($module); // Force first letter in uppercase
791
792 //var_dump($phpfileval['fullname']);
793 $arrayreplacement = array(
794 'mymodule' => strtolower($modulename),
795 'MyModule' => $modulename,
796 'MYMODULE' => strtoupper($modulename),
797 'My module' => $modulename,
798 'my module' => $modulename,
799 'Mon module' => $modulename,
800 'mon module' => $modulename,
801 'htdocs/modulebuilder/template' => strtolower($modulename),
802 '---Replace with your own copyright and developer email---' => getLicenceHeader($user, $langs, $now)
803 );
804
805 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
806 dolReplaceInFile($destfile, $arrayreplacement);
807 } else {
808 $langs->load("errors");
809 setEventMessages($langs->trans('ErrorFailToCreateFile', $destfile), null, 'errors');
810 }
811}
812
813
814// init CSS
815if ($dirins && $action == 'initcss' && !empty($module) /* && $user->hasRight("modulebuilder", "run") // already checked */) {
816 dol_mkdir($dirins.'/'.strtolower($module).'/css');
817 $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template';
818 $srcfile = $srcdir.'/css/mymodule.css.php';
819 $destfile = $dirins.'/'.strtolower($module).'/css/'.strtolower($module).'.css.php';
820 $result = dol_copy($srcfile, $destfile, '0', 0);
821
822 if ($result > 0) {
823 $modulename = ucfirst($module); // Force first letter in uppercase
824
825 //var_dump($phpfileval['fullname']);
826 $arrayreplacement = array(
827 'mymodule' => strtolower($modulename),
828 'MyModule' => $modulename,
829 'MYMODULE' => strtoupper($modulename),
830 'My module' => $modulename,
831 'my module' => $modulename,
832 'Mon module' => $modulename,
833 'mon module' => $modulename,
834 'htdocs/modulebuilder/template' => strtolower($modulename),
835 '---Replace with your own copyright and developer email---' => getLicenceHeader($user, $langs, $now)
836 );
837
838 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
839 dolReplaceInFile($destfile, $arrayreplacement);
840
841 // Update descriptor file to uncomment file
842 $srcfile = $dirins.'/'.strtolower($module).'/core/modules/mod'.$module.'.class.php';
843 $arrayreplacement = array('/\/\/\s*\''.preg_quote('/'.strtolower($module).'/css/'.strtolower($module).'.css.php', '/').'\'/' => '\'/'.strtolower($module).'/css/'.strtolower($module).'.css.php\'');
844 dolReplaceInFile($srcfile, $arrayreplacement, '', '0', 0, 1);
845 } else {
846 $langs->load("errors");
847 setEventMessages($langs->trans('ErrorFailToCreateFile', $destfile), null, 'errors');
848 }
849}
850
851
852// init JS
853if ($dirins && $action == 'initjs' && !empty($module) /* && $user->hasRight("modulebuilder", "run") // already checked */) {
854 dol_mkdir($dirins.'/'.strtolower($module).'/js');
855 $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template';
856 $srcfile = $srcdir.'/js/mymodule.js.php';
857 $destfile = $dirins.'/'.strtolower($module).'/js/'.strtolower($module).'.js.php';
858 $result = dol_copy($srcfile, $destfile, '0', 0);
859
860 if ($result > 0) {
861 $modulename = ucfirst($module); // Force first letter in uppercase
862
863 //var_dump($phpfileval['fullname']);
864 $arrayreplacement = array(
865 'mymodule' => strtolower($modulename),
866 'MyModule' => $modulename,
867 'MYMODULE' => strtoupper($modulename),
868 'My module' => $modulename,
869 'my module' => $modulename,
870 'Mon module' => $modulename,
871 'mon module' => $modulename,
872 'htdocs/modulebuilder/template' => strtolower($modulename),
873 '---Replace with your own copyright and developer email---' => getLicenceHeader($user, $langs, $now)
874 );
875
876 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
877 dolReplaceInFile($destfile, $arrayreplacement);
878
879 // Update descriptor file to uncomment file
880 $srcfile = $dirins.'/'.strtolower($module).'/core/modules/mod'.$module.'.class.php';
881 $arrayreplacement = array('/\/\/\s*\''.preg_quote('/'.strtolower($module).'/js/'.strtolower($module).'.js.php', '/').'\'/' => '\'/'.strtolower($module).'/js/'.strtolower($module).'.js.php\'');
882 dolReplaceInFile($srcfile, $arrayreplacement, '', '0', 0, 1);
883 } else {
884 $langs->load("errors");
885 setEventMessages($langs->trans('ErrorFailToCreateFile', $destfile), null, 'errors');
886 }
887}
888
889
890// init CLI
891if ($dirins && $action == 'initcli' && !empty($module) /* && $user->hasRight("modulebuilder", "run") // already checked */) {
892 dol_mkdir($dirins.'/'.strtolower($module).'/scripts');
893 $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template';
894 $srcfile = $srcdir.'/scripts/mymodule.php';
895 $destfile = $dirins.'/'.strtolower($module).'/scripts/'.strtolower($module).'.php';
896 $result = dol_copy($srcfile, $destfile, '0', 0);
897
898 if ($result > 0) {
899 $modulename = ucfirst($module); // Force first letter in uppercase
900
901 //var_dump($phpfileval['fullname']);
902 $arrayreplacement = array(
903 'mymodule' => strtolower($modulename),
904 'MyModule' => $modulename,
905 'MYMODULE' => strtoupper($modulename),
906 'My module' => $modulename,
907 'my module' => $modulename,
908 'Mon module' => $modulename,
909 'mon module' => $modulename,
910 'htdocs/modulebuilder/template' => strtolower($modulename),
911 '__MYCOMPANY_NAME__' => $mysoc->name,
912 '__KEYWORDS__' => $modulename,
913 '__USER_FULLNAME__' => $user->getFullName($langs),
914 '__USER_EMAIL__' => $user->email,
915 '__YYYY-MM-DD__' => dol_print_date($now, 'dayrfc'),
916 '---Replace with your own copyright and developer email---' => getLicenceHeader($user, $langs, $now)
917 );
918
919 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
920 dolReplaceInFile($destfile, $arrayreplacement);
921 } else {
922 $langs->load("errors");
923 setEventMessages($langs->trans('ErrorFailToCreateFile', $destfile), null, 'errors');
924 }
925}
926
927
928$moduledescriptorfile = '/not_set/';
929$modulelowercase = null;
930
931// init Doc
932if ($dirins && $action == 'initdoc' && !empty($module) /* && $user->hasRight("modulebuilder", "run") // already checked */) {
933 dol_mkdir($dirins.'/'.strtolower($module).'/doc');
934 $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template';
935 $srcfile = $srcdir.'/doc/Documentation.asciidoc';
936 $destfile = $dirins.'/'.strtolower($module).'/doc/Documentation.asciidoc';
937 $result = dol_copy($srcfile, $destfile, '0', 0);
938
939 if ($result > 0) {
940 $modulename = ucfirst($module); // Force first letter in uppercase
941 $modulelowercase = strtolower($module);
942
943 //var_dump($phpfileval['fullname']);
944 $arrayreplacement = array(
945 'mymodule' => strtolower($modulename),
946 'MyModule' => $modulename,
947 'MYMODULE' => strtoupper($modulename),
948 'My module' => $modulename,
949 'my module' => $modulename,
950 'Mon module' => $modulename,
951 'mon module' => $modulename,
952 'htdocs/modulebuilder/template' => strtolower($modulename),
953 '__MYCOMPANY_NAME__' => $mysoc->name,
954 '__KEYWORDS__' => $modulename,
955 '__USER_FULLNAME__' => $user->getFullName($langs),
956 '__USER_EMAIL__' => $user->email,
957 '__YYYY-MM-DD__' => dol_print_date($now, 'dayrfc'),
958 '---Replace with your own copyright and developer email---' => getLicenceHeader($user, $langs, $now)
959 );
960
961 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
962 dolReplaceInFile($destfile, $arrayreplacement);
963
964 // add table of properties
965 $dirins = $listofmodules[strtolower($module)]['moduledescriptorrootpath'];
966 $destdir = $dirins.'/'.strtolower($module);
967 $objects = dolGetListOfObjectClasses($destdir);
968 foreach ($objects as $path => $obj) {
969 writePropsInAsciiDoc($path, $obj, $destfile);
970 }
971
972 // add table of permissions
973 $moduledescriptorfile = $dirins.'/'.strtolower($module).'/core/modules/mod'.$module.'.class.php';
974 writePermsInAsciiDoc($moduledescriptorfile, $destfile);
975
976 // add api urls if file exist
977 if (file_exists($dirins.'/'.strtolower($module).'/class/api_'.strtolower($module).'.class.php')) {
978 $apiFile = $dirins.'/'.strtolower($module).'/class/api_'.strtolower($module).'.class.php';
979 writeApiUrlsInDoc($apiFile, $destfile);
980 }
981
982 // add ChangeLog in Doc
983 if (file_exists($dirins.'/'.strtolower($module).'/ChangeLog.md')) {
984 $changeLog = $dirins.'/'.strtolower($module).'/ChangeLog.md';
985 $string = file_get_contents($changeLog);
986
987 $replace = explode("\n", $string);
988 $strreplace = array();
989 foreach ($replace as $line) {
990 if ($line === '') {
991 continue;
992 }
993 if (strpos($line, '##') !== false) {
994 $strreplace[$line] = str_replace('##', '', $line);
995 } else {
996 $strreplace[$line] = $line;
997 }
998 }
999 $stringLog = implode("\n", $strreplace);
1000 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
1001 dolReplaceInFile($destfile, array('//include::ChangeLog.md[]' => '','__CHANGELOG__' => $stringLog));
1002 }
1003
1004 // Delete old documentation files
1005 $FILENAMEDOC = $modulelowercase.'.html';
1006 $FILENAMEDOCPDF = $modulelowercase.'.pdf';
1007 $outputfiledoc = dol_buildpath($modulelowercase, 0).'/doc/'.$FILENAMEDOC;
1008 $outputfiledocurl = dol_buildpath($modulelowercase, 1).'/doc/'.$FILENAMEDOC;
1009 $outputfiledocpdf = dol_buildpath($modulelowercase, 0).'/doc/'.$FILENAMEDOCPDF;
1010 $outputfiledocurlpdf = dol_buildpath($modulelowercase, 1).'/doc/'.$FILENAMEDOCPDF;
1011
1012 dol_delete_file($outputfiledoc, 0, 0, 0, null, false, 0);
1013 dol_delete_file($outputfiledocpdf, 0, 0, 0, null, false, 0);
1014 } else {
1015 $langs->load("errors");
1016 setEventMessages($langs->trans('ErrorFailToCreateFile', $destfile), null, 'errors');
1017 }
1018}
1019
1020
1021// add Language
1022if ($dirins && $action == 'addlanguage' && !empty($module) /* && $user->hasRight("modulebuilder", "run") // already checked */) {
1023 $newlangcode = GETPOST('newlangcode', 'aZ09');
1024
1025 if ($newlangcode) {
1026 $modulelowercase = strtolower($module);
1027
1028 // Dir for module
1029 $diroflang = dol_buildpath($modulelowercase, 0);
1030
1031 if ($diroflang == $dolibarr_main_document_root.'/'.$modulelowercase) {
1032 // This is not a custom module, we force diroflang to htdocs root
1033 $diroflang = $dolibarr_main_document_root;
1034
1035 $srcfile = $diroflang.'/langs/en_US/'.$modulelowercase.'.lang';
1036 $destfile = $diroflang.'/langs/'.$newlangcode.'/'.$modulelowercase.'.lang';
1037
1038 $result = dol_copy($srcfile, $destfile, '0', 0);
1039 if ($result < 0) {
1040 setEventMessages($langs->trans("ErrorFailToCopyFile", $srcfile, $destfile), null, 'errors');
1041 }
1042 } else {
1043 $srcdir = $diroflang.'/langs/en_US';
1044 $srcfile = $diroflang.'/langs/en_US/'.$modulelowercase.'.lang';
1045 $destdir = $diroflang.'/langs/'.$newlangcode;
1046
1047 $arrayofreplacement = array();
1048 if (!dol_is_dir($srcdir) || !dol_is_file($srcfile)) {
1049 $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template/langs/en_US';
1050 $arrayofreplacement = array('mymodule' => $modulelowercase);
1051 }
1052 $result = dolCopyDir($srcdir, $destdir, '0', 0, $arrayofreplacement);
1053 }
1054 } else {
1055 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Language")), null, 'errors');
1056 }
1057}
1058
1059
1060// Remove/delete File
1061if ($dirins && $action == 'confirm_removefile' && !empty($module) /* && $user->hasRight("modulebuilder", "run") // already checked */) {
1062 $objectname = $tabobj;
1063 $dirins = $listofmodules[strtolower($module)]['moduledescriptorrootpath'];
1064 $destdir = $dirins.'/'.strtolower($module);
1065
1066 $relativefilename = dol_sanitizePathName(GETPOST('file', 'restricthtml'));
1067
1068 // Now we delete the file
1069 if ($relativefilename) {
1070 $dirnametodelete = dirname($relativefilename);
1071 $filetodelete = $dirins.'/'.$relativefilename;
1072 $dirtodelete = $dirins.'/'.$dirnametodelete;
1073
1074 // Get list of existing objects
1075 $objects = dolGetListOfObjectClasses($destdir);
1076
1077 $keyofobjecttodelete = array_search($objectname, $objects);
1078 if ($keyofobjecttodelete !== false) {
1079 unset($objects[$keyofobjecttodelete]);
1080 }
1081
1082 // Delete or modify the file
1083 if (strpos($relativefilename, 'api') !== false) {
1084 $file_api = $destdir.'/class/api_'.strtolower($module).'.class.php';
1085
1086 $removeFile = removeObjectFromApiFile($file_api, $objects, $objectname);
1087
1088 if (count($objects) == 0) {
1089 $result = dol_delete_file($filetodelete, 1);
1090 }
1091
1092 if ($removeFile) {
1093 setEventMessages($langs->trans("ApiObjectDeleted"), null);
1094 }
1095 } else {
1096 $result = dol_delete_file($filetodelete, 1);
1097 }
1098
1099 if (!$result) {
1100 setEventMessages($langs->trans("ErrorFailToDeleteFile", basename($filetodelete)), null, 'errors');
1101 } else {
1102 // If we delete a .sql file, we delete also the other .sql file
1103 if (preg_match('/\.sql$/', $relativefilename)) {
1104 if (preg_match('/\.key\.sql$/', $relativefilename)) {
1105 $relativefilename = preg_replace('/\.key\.sql$/', '.sql', $relativefilename);
1106 $filetodelete = $dirins.'/'.$relativefilename;
1107 $result = dol_delete_file($filetodelete, 1);
1108 } elseif (preg_match('/\.sql$/', $relativefilename)) {
1109 $relativefilename = preg_replace('/\.sql$/', '.key.sql', $relativefilename);
1110 $filetodelete = $dirins.'/'.$relativefilename;
1111 $result = dol_delete_file($filetodelete, 1);
1112 }
1113 }
1114
1115 if (dol_is_dir_empty($dirtodelete)) {
1116 dol_delete_dir($dirtodelete);
1117 }
1118
1119 // Update descriptor file to comment file
1120 if (in_array($tab, array('css', 'js'))) {
1121 $srcfile = $dirins.'/'.strtolower($module).'/core/modules/mod'.$module.'.class.php';
1122 $arrayreplacement = array('/^\s*\''.preg_quote('/'.$relativefilename, '/').'\',*/m' => ' // \'/'.$relativefilename.'\',');
1123 dolReplaceInFile($srcfile, $arrayreplacement, '', '0', 0, 1);
1124 }
1125
1126 if (preg_match('/_extrafields/', $relativefilename)) {
1127 // Now we update the object file to set $isextrafieldmanaged to 0
1128 $srcfile = $dirins.'/'.strtolower($module).'/class/'.strtolower($objectname).'.class.php';
1129 $arrayreplacement = array('/\$isextrafieldmanaged = 1;/' => '$isextrafieldmanaged = 0;');
1130 dolReplaceInFile($srcfile, $arrayreplacement, '', '0', 0, 1);
1131 }
1132
1133 // Now we update the lib file to set $showtabofpagexxx to 0
1134 $varnametoupdate = '';
1135 $reg = array();
1136 if (preg_match('/_([a-z]+)\.php$/', $relativefilename, $reg)) {
1137 $varnametoupdate = 'showtabofpage'.$reg[1];
1138 }
1139 if ($varnametoupdate) {
1140 $srcfile = $dirins.'/'.strtolower($module).'/lib/'.strtolower($module).'_'.strtolower($objectname).'.lib.php';
1141 $arrayreplacement = array('/\$'.preg_quote($varnametoupdate, '/').' = 1;/' => '$'.preg_quote($varnametoupdate, '/').' = 0;');
1142 dolReplaceInFile($srcfile, $arrayreplacement, '', '0', 0, 1);
1143 }
1144 }
1145 }
1146}
1147
1148// Init an object
1149if ($dirins && $action == 'initobject' && $module && $objectname) { // Test on permission already done
1150 $warning = 0;
1151
1152 $objectname = dol_string_nounprintableascii(dol_string_unaccent(ucwords($objectname))); // Force first letter in uppercase
1153
1154 $dirins = $dirread = $listofmodules[strtolower($module)]['moduledescriptorrootpath'];
1155 $moduletype = $listofmodules[strtolower($module)]['moduletype'];
1156
1157 if (preg_match('/[^a-z0-9]/i', $objectname)) {
1158 $error++;
1159 setEventMessages($langs->trans("SpaceOrSpecialCharAreNotAllowed"), null, 'errors');
1160 $tabobj = 'newobject';
1161 }
1162 if (class_exists($objectname)) {
1163 // TODO Add a more efficient detection. Scan disk ?
1164 $error++;
1165 setEventMessages($langs->trans("AnObjectWithThisClassNameAlreadyExists"), null, 'errors');
1166 $tabobj = 'newobject';
1167 }
1168
1169 try {
1170 $ncObj = new NamingContract($module, $objectname);
1171 } catch (\InvalidArgumentException $e) {
1172 $error++;
1173 setEventMessages($langs->trans("SpaceOrSpecialCharAreNotAllowed"), null, 'errors');
1174 $ncObj = null;
1175 }
1176
1177 $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template';
1178 $destdir = $dirins.'/'.strtolower($module);
1179
1180 // Optional tabs selected by user, and detection of an already generated object (for idempotence warning)
1181 $enabledtabs = filterEnabledTabs(GETPOST('enabledtab', 'array'), getModuleBuilderObjectTabs());
1182 $objectalreadyexists = dol_is_file($destdir.'/class/'.strtolower($objectname).'.class.php');
1183
1184 // The dir was not created by init
1185 dol_mkdir($destdir.'/class');
1186 dol_mkdir($destdir.'/img');
1187 dol_mkdir($destdir.'/lib');
1188 dol_mkdir($destdir.'/scripts');
1189 dol_mkdir($destdir.'/sql');
1190 dol_mkdir($destdir.'/ajax');
1191 dol_mkdir($destdir.'/stats');
1192
1193 // Scan dir class to find if an object with the same name already exists.
1194 if (!$error) {
1195 $dirlist = dol_dir_list($destdir.'/class', 'files', 0, '\.txt$');
1196 $alreadyfound = false;
1197 foreach ($dirlist as $key => $val) {
1198 $filefound = preg_replace('/\.txt$/', '', $val['name']);
1199 if (strtolower($objectname) == strtolower($filefound) && $objectname != $filefound) {
1200 $alreadyfound = true;
1201 $error++;
1202 setEventMessages($langs->trans("AnObjectAlreadyExistWithThisNameAndDiffCase"), null, 'errors');
1203 break;
1204 }
1205 }
1206 }
1207
1208 // If we must reuse an existing table for properties, define $stringforproperties
1209 // Generate class file from the table
1210 $stringforproperties = '';
1211 $tablename = GETPOST('initfromtablename', 'alpha');
1212 if ($tablename) {
1213 $_results = $db->DDLDescTable($tablename);
1214 if (empty($_results)) {
1215 $error++;
1216 $langs->load("errors");
1217 setEventMessages($langs->trans("ErrorTableNotFound", $tablename), null, 'errors');
1218 } else {
1246 /*public $fields=array(
1247 'rowid' => array('type' => 'integer', 'label' => 'TechnicalID', 'enabled' => 1, 'visible' => -2, 'notnull' => 1, 'index' => 1, 'position' => 1, 'comment' => 'Id'),
1248 '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'),
1249 'entity' => array('type' => 'integer', 'label' => 'Entity', 'enabled' => 1, 'visible' => 0, 'default' => 1, 'notnull' => 1, 'index' => 1, 'position' => 20),
1250 'label' => array('type' => 'varchar(255)', 'label' => 'Label', 'enabled' => 1, 'visible' => 1, 'position' => 30, 'searchall' => 1, 'css' => 'minwidth200', 'help' => 'Help text', 'alwayseditable' => '1'),
1251 'amount' => array('type' => 'double(24,8)', 'label' => 'Amount', 'enabled' => 1, 'visible' => 1, 'default' => 'null', 'position' => 40, 'searchall' => 0, 'isameasure' => 1, 'help' => 'Help text'),
1252 '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'),
1253 'description' => array('type' => 'text', 'label' => 'Descrption', 'enabled' => 1, 'visible' => 0, 'position' => 60),
1254 'note_public' => array('type' => 'html', 'label' => 'NotePublic', 'enabled' => 1, 'visible' => 0, 'position' => 61),
1255 'note_private' => array('type' => 'html', 'label' => 'NotePrivate', 'enabled' => 1, 'visible' => 0, 'position' => 62),
1256 'date_creation' => array('type' => 'datetime', 'label' => 'DateCreation', 'enabled' => 1, 'visible' => -2, 'notnull' => 1, 'position' => 500),
1257 'tms' => array('type' => 'timestamp', 'label' => 'DateModification', 'enabled' => 1, 'visible' => -2, 'notnull' => 1, 'position' => 501),
1258 //'date_valid' => array('type' => 'datetime', 'label' => 'DateCreation', 'enabled' => 1, 'visible' => -2, 'position' => 502),
1259 'fk_user_creat' => array('type' => 'integer', 'label' => 'UserAuthor', 'enabled' => 1, 'visible' => -2, 'notnull' => 1, 'position' => 510),
1260 'fk_user_modif' => array('type' => 'integer', 'label' => 'UserModif', 'enabled' => 1, 'visible' => -2, 'notnull' => -1, 'position' => 511),
1261 //'fk_user_valid' => array('type' => 'integer', 'label' => 'UserValidation', 'enabled' => 1, 'visible' => -1, 'position' => 512),
1262 'import_key' => array('type' => 'varchar(14)', 'label' => 'ImportId', 'enabled' => 1, 'visible' => -2, 'notnull' => -1, 'index' => 0, 'position' => 1000),
1263 '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')),
1264 );*/
1265
1266 $stringforproperties = '// BEGIN MODULEBUILDER PROPERTIES'."\n";
1267 $stringforproperties .= 'public $fields = array('."\n";
1268 $i = 10;
1269 while ($obj = $db->fetch_object($_results)) {
1270 // fieldname
1271 $fieldname = $obj->Field;
1272 // type
1273 $type = $obj->Type;
1274 if ($type == 'int(11)') {
1275 $type = 'integer';
1276 } elseif ($type == 'float') {
1277 $type = 'real';
1278 } elseif (strstr($type, 'tinyint')) {
1279 $type = 'integer';
1280 } elseif (strstr($type, 'url')) {
1281 $type = 'varchar(255)';
1282 } elseif ($obj->Field == 'fk_soc') {
1283 $type = 'integer:Societe:societe/class/societe.class.php';
1284 } elseif (preg_match('/^fk_proj/', $obj->Field)) {
1285 $type = 'integer:Project:projet/class/project.class.php:1:fk_statut=1';
1286 } elseif (preg_match('/^fk_prod/', $obj->Field)) {
1287 $type = 'integer:Product:product/class/product.class.php:1';
1288 } elseif ($obj->Field == 'fk_warehouse') {
1289 $type = 'integer:Entrepot:product/stock/class/entrepot.class.php';
1290 } elseif (preg_match('/^(fk_user|fk_commercial)/', $obj->Field)) {
1291 $type = 'integer:User:user/class/user.class.php';
1292 }
1293
1294 // notnull
1295 $notnull = ($obj->Null == 'YES' ? 0 : 1);
1296 if ($fieldname == 'fk_user_modif') {
1297 $notnull = -1;
1298 }
1299 // label
1300 $label = preg_replace('/_/', '', ucfirst($fieldname));
1301 if ($fieldname == 'rowid') {
1302 $label = 'TechnicalID';
1303 }
1304 if ($fieldname == 'import_key') {
1305 $label = 'ImportId';
1306 }
1307 if ($fieldname == 'fk_soc') {
1308 $label = 'ThirdParty';
1309 }
1310 if (in_array($fieldname, array('tms', 'date_modification'))) {
1311 $label = 'DateModification';
1312 }
1313 if (in_array($fieldname, array('datec', 'date_creation'))) {
1314 $label = 'DateCreation';
1315 }
1316 if ($fieldname == 'date_valid') {
1317 $label = 'DateValidation';
1318 }
1319 if ($fieldname == 'datev') {
1320 $label = 'DateValidation';
1321 }
1322 if ($fieldname == 'note_private') {
1323 $label = 'NotePublic';
1324 }
1325 if ($fieldname == 'note_public') {
1326 $label = 'NotePrivate';
1327 }
1328 if ($fieldname == 'fk_user_creat') {
1329 $label = 'UserAuthor';
1330 }
1331 if ($fieldname == 'fk_user_modif') {
1332 $label = 'UserModif';
1333 }
1334 if ($fieldname == 'fk_user_valid') {
1335 $label = 'UserValidation';
1336 }
1337 // visible
1338 $visible = -1;
1339 if (in_array($fieldname, array('ref', 'label'))) {
1340 $visible = 1;
1341 }
1342 if ($fieldname == 'entity') {
1343 $visible = -2;
1344 }
1345 if ($fieldname == 'entity') {
1346 $visible = -2;
1347 }
1348 if ($fieldname == 'import_key') {
1349 $visible = -2;
1350 }
1351 if ($fieldname == 'fk_user_creat') {
1352 $visible = -2;
1353 }
1354 if ($fieldname == 'fk_user_modif') {
1355 $visible = -2;
1356 }
1357 if (in_array($fieldname, array('ref_ext', 'model_pdf', 'note_public', 'note_private'))) {
1358 $visible = 0;
1359 }
1360 // enabled
1361 $enabled = 1;
1362 // default
1363 $default = '';
1364 if ($fieldname == 'entity') {
1365 $default = 1;
1366 }
1367 // position
1368 $position = $i;
1369 if (in_array($fieldname, array('status', 'statut', 'fk_status', 'fk_statut'))) {
1370 $position = 500;
1371 }
1372 if ($fieldname == 'import_key') {
1373 $position = 900;
1374 }
1375 // $alwayseditable
1376 $alwayseditable = 0;
1377 if ($fieldname == 'label') {
1378 $alwayseditable = 1;
1379 } else {
1380 $alwayseditable = 0;
1381 }
1382 // index
1383 $index = 0;
1384 if ($fieldname == 'entity') {
1385 $index = 1;
1386 }
1387 // css, cssview, csslist
1388 $css = '';
1389 $cssview = '';
1390 $csslist = '';
1391 if (preg_match('/^fk_/', $fieldname)) {
1392 $css = 'maxwidth500 widthcentpercentminusxx';
1393 }
1394 if ($fieldname == 'label') {
1395 $css = 'minwidth300';
1396 $cssview = 'wordbreak';
1397 }
1398 if (in_array($fieldname, array('note_public', 'note_private'))) {
1399 $cssview = 'wordbreak';
1400 }
1401 if (in_array($fieldname, array('ref', 'label')) || preg_match('/integer:/', $type)) {
1402 $csslist = 'tdoverflowmax150';
1403 }
1404
1405 // type
1406 $picto = '';
1407 if (isset($obj->Picto)) { // This should never exists
1408 $picto = $obj->Picto;
1409 }
1410 if (preg_match('/^fk_soc/', $obj->Field)) {
1411 $picto = 'company';
1412 } elseif (preg_match('/^fk_contact/', $obj->Field)) {
1413 $picto = 'contact';
1414 } elseif (preg_match('/^fk_bank/', $obj->Field)) {
1415 $picto = 'bank';
1416 } elseif (preg_match('/^fk_user/', $obj->Field)) {
1417 $picto = 'user';
1418 } elseif (preg_match('/^fk_warehouse/', $obj->Field)) {
1419 $picto = 'warehouse';
1420 } elseif (preg_match('/^fk_prod/', $obj->Field)) {
1421 $picto = 'product';
1422 } elseif (preg_match('/^fk_proj/', $obj->Field)) {
1423 $picto = 'project';
1424 } elseif (preg_match('/^fk_task/', $obj->Field)) {
1425 $picto = 'task';
1426 }
1427
1428 // lang
1429 $lang = $module.'@'.$module;
1430
1431 // Build the property string
1432 $stringforproperties .= "'".$obj->Field."' => array('type' => '".$type."', 'label' => '".$label."',";
1433 if ($default != '') {
1434 $stringforproperties .= " 'default' => ".$default.",";
1435 }
1436 $stringforproperties .= " 'enabled' => ".$enabled.",";
1437 $stringforproperties .= " 'visible' => ".$visible;
1438 if ($notnull) {
1439 $stringforproperties .= ", 'notnull' => ".$notnull;
1440 }
1441 if ($alwayseditable) {
1442 $stringforproperties .= ", 'alwayseditable' => 1";
1443 }
1444 if ($fieldname == 'ref' || $fieldname == 'code') {
1445 $stringforproperties .= ", 'showoncombobox' => 1";
1446 }
1447 $stringforproperties .= ", 'position' => ".$position;
1448 if ($index) {
1449 $stringforproperties .= ", 'index' => ".$index;
1450 }
1451 if ($picto) {
1452 $stringforproperties .= ", 'picto' => '".$picto."'";
1453 }
1454 if ($css) {
1455 $stringforproperties .= ", 'css' => '".$css."'";
1456 }
1457 if ($cssview) {
1458 $stringforproperties .= ", 'cssview' => '".$cssview."'";
1459 }
1460 if ($csslist) {
1461 $stringforproperties .= ", 'csslist' => '".$csslist."'";
1462 }
1463
1464 $stringforproperties .= ", 'lang' => '".$lang."'";
1465
1466 $stringforproperties .= "),\n";
1467 $i += 5;
1468 }
1469 $stringforproperties .= ');'."\n";
1470 $stringforproperties .= '// END MODULEBUILDER PROPERTIES'."\n";
1471 }
1472 }
1473
1474 $filetogenerate = array();
1475 if (!$error) {
1476 // Copy some files
1477 $filetogenerate = [];
1478 foreach ([
1479 'myobject_card.php',
1480 'myobject_note.php',
1481 'myobject_contact.php',
1482 'myobject_document.php',
1483 'myobject_agenda.php',
1484 'myobject_list.php',
1485 'admin/myobject_extrafields.php',
1486 'ajax/myobject.php',
1487 'lib/mymodule_myobject.lib.php',
1488 //'test/phpunit/MyObjectTest.php',
1489 'sql/llx_mymodule_myobject.sql',
1490 'sql/llx_mymodule_myobject.key.sql',
1491 'sql/llx_mymodule_myobject_extrafields.sql',
1492 'sql/llx_mymodule_myobject_extrafields.key.sql',
1493 //'scripts/mymodule.php',
1494 'class/myobject.class.php',
1495 'class/myobjectstats.class.php',
1496 //'class/api_mymodule.class.php',
1497 'stats/myobject_index.php',
1498 ] as $templateFile) {
1499 $filetogenerate[$templateFile] = $ncObj->applyToFilename($templateFile);
1500 }
1501
1502 // Exclude tab page files for tabs not selected by user
1503 foreach (getModuleBuilderObjectTabs() as $tabkey => $tabinfo) {
1504 if (!in_array($tabkey, $enabledtabs, true)) {
1505 unset($filetogenerate[$tabinfo['file']]);
1506 }
1507 }
1508
1509 if (GETPOST('includerefgeneration', 'aZ09')) {
1510 dol_mkdir($destdir.'/core/modules/'.strtolower($module));
1511
1512 foreach ([
1513 'core/modules/mymodule/mod_myobject_advanced.php',
1514 'core/modules/mymodule/mod_myobject_standard.php',
1515 'core/modules/mymodule/modules_myobject.php',
1516 ] as $templateFile) {
1517 $filetogenerate[$templateFile] = $ncObj->applyToFilename($templateFile);
1518 }
1519 }
1520 if (GETPOST('includedocgeneration', 'aZ09')) {
1521 dol_mkdir($destdir.'/core/modules/'.strtolower($module));
1522 dol_mkdir($destdir.'/core/modules/'.strtolower($module).'/doc');
1523
1524 foreach ([
1525 'core/modules/mymodule/doc/doc_generic_myobject_odt.modules.php',
1526 'core/modules/mymodule/doc/pdf_standard_myobject.modules.php',
1527 ] as $templateFile) {
1528 $filetogenerate[$templateFile] = $ncObj->applyToFilename($templateFile);
1529 }
1530 }
1531 $class = null;
1532 if (GETPOST('generatepermissions', 'aZ09')) {
1533 $firstobjectname = 'myobject';
1534 $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
1535 dol_include_once($pathtofile);
1536 $class = 'mod'.$module;
1537 $moduleobj = null;
1538 if (class_exists($class)) {
1539 try {
1540 $moduleobj = new $class($db);
1541 '@phan-var-force DolibarrModules $moduleobj';
1543 } catch (Exception $e) {
1544 $error++;
1545 dol_print_error($db, $e->getMessage());
1546 }
1547 }
1548 if (is_object($moduleobj)) {
1549 $rights = $moduleobj->rights;
1550 } else {
1551 $rights = [];
1552 }
1553 $moduledescriptorfile = $destdir.'/core/modules/mod'.$module.'.class.php';
1554 $checkComment = checkExistComment($moduledescriptorfile, 1);
1555 if ($checkComment < 0) {
1556 setEventMessages($langs->trans("WarningCommentNotFound", $langs->trans("Permissions"), "mod".$module."class.php"), null, 'warnings');
1557 } else {
1558 $reportPerms = modulebuilderSyncRights(RightsSyncCommand::forObjectCreation($module, $moduledescriptorfile, is_array($rights) ? $rights : array(), $objectname));
1559 if ($reportPerms->skipped > 0) {
1560 setEventMessages($langs->trans("WarningPermissionAlreadyExist", $langs->transnoentities($objectname)), null, 'warnings');
1561 }
1562 }
1563 }
1564
1565 if (!$error) {
1566 foreach ($filetogenerate as $srcfile => $destfile) {
1567 $result = dol_copy($srcdir.'/'.$srcfile, $destdir.'/'.$destfile, $newmask, 0);
1568 if ($result <= 0) {
1569 if ($result < 0) {
1570 $warning++;
1571 $langs->load("errors");
1572 setEventMessages($langs->trans("ErrorFailToCopyFile", $srcdir.'/'.$srcfile, $destdir.'/'.$destfile), null, 'errors');
1573 } else {
1574 // $result == 0
1575 setEventMessages($langs->trans("FileAlreadyExists", $destfile), null, 'warnings');
1576 }
1577 }
1578 $arrayreplacement = array(
1579 '/myobject\.class\.php/' => strtolower($objectname).'.class.php',
1580 '/myobject\.lib\.php/' => strtolower($objectname).'.lib.php',
1581 );
1582
1583 dolReplaceInFile($destdir.'/'.$destfile, $arrayreplacement, '', '0', 0, 1);
1584 }
1585 }
1586
1587 // Replace property section with $stringforproperties
1588 if (!$error && $stringforproperties) {
1589 //var_dump($stringforproperties);exit;
1590 $arrayreplacement = array(
1591 '/\/\/ BEGIN MODULEBUILDER PROPERTIES.*\/\/ END MODULEBUILDER PROPERTIES/ims' => $stringforproperties
1592 );
1593
1594 dolReplaceInFile($destdir.'/class/'.strtolower($objectname).'.class.php', $arrayreplacement, '', '0', 0, 1);
1595 }
1596
1597 // Edit the class 'class/'.strtolower($objectname).'.class.php'
1598 if (GETPOST('includerefgeneration', 'aZ09')) {
1599 // Replace 'visible' => 1, 'noteditable' => 0, 'default' => ''
1600 $arrayreplacement = array(
1601 '/\'visible\'s*=>s*1,\s*\'noteditable\'s*=>s*0,\s*\'default\'s*=>s*\'\'/' => "'visible' => 4, 'noteditable' => 1, 'default' => '(PROV)'"
1602 );
1603 //var_dump($arrayreplacement);exit;
1604 //var_dump($destdir.'/class/'.strtolower($objectname).'.class.php');exit;
1605 dolReplaceInFile($destdir.'/class/'.strtolower($objectname).'.class.php', $arrayreplacement, '', '0', 0, 1);
1606
1607 $arrayreplacement = array(
1608 '/\'models\' => 0,/' => '\'models\' => 1,'
1609 );
1610 dolReplaceInFile($destdir.'/core/modules/mod'.$module.'.class.php', $arrayreplacement, '', '0', 0, 1);
1611 }
1612
1613 // Edit the setup file and the card page
1614 if (GETPOST('includedocgeneration', 'aZ09')) {
1615 // Replace some var init into some files
1616 $arrayreplacement = array(
1617 '/\$includedocgeneration = 0;/' => '$includedocgeneration = 1;'
1618 );
1619 dolReplaceInFile($destdir.'/class/'.strtolower($objectname).'.class.php', $arrayreplacement, '', '0', 0, 1);
1620 dolReplaceInFile($destdir.'/'.strtolower($objectname).'_card.php', $arrayreplacement, '', '0', 0, 1);
1621
1622 $arrayreplacement = array(
1623 '/\'models\' => 0,/' => '\'models\' => 1,'
1624 );
1625
1626 dolReplaceInFile($destdir.'/core/modules/mod'.$module.'.class.php', $arrayreplacement, '', '0', 0, 1);
1627 }
1628
1629 // TODO Update entries '$myTmpObjects['MyObject'] = array('includerefgeneration' => 0, 'includedocgeneration' => 0);'
1630
1631
1632 // Scan for object class files
1633 $listofobject = dol_dir_list($destdir.'/class', 'files', 0, '\.class\.php$');
1634
1635 $firstobjectname = '';
1636 $stringtoadd = '';
1637 foreach ($listofobject as $fileobj) {
1638 if (preg_match('/^api_/', $fileobj['name'])) {
1639 continue;
1640 }
1641 if (preg_match('/^actions_/', $fileobj['name'])) {
1642 continue;
1643 }
1644
1645 $tmpcontent = file_get_contents($fileobj['fullname']);
1646 $reg = array();
1647 if (preg_match('/class\s+([^\s]*)\s+extends\s+CommonObject/ims', $tmpcontent, $reg)) {
1648 $objectnameloop = $reg[1];
1649 if (empty($firstobjectname)) {
1650 $firstobjectname = $objectnameloop;
1651 }
1652 }
1653
1654 // Regenerate left menu entry in descriptor for $objectname
1655 $stringtoadd = "
1656 \$this->menu[\$r++] = array(
1657 'fk_menu' => 'fk_mainmenu=mymodule',
1658 'type' => 'left',
1659 'titre' => 'MyObject',
1660 'prefix' => img_picto('', \$this->picto, 'class=\"paddingright pictofixedwidth valignmiddle\"'),
1661 'mainmenu' => 'mymodule',
1662 'leftmenu' => 'myobject',
1663 'url' => '/mymodule/myobject_list.php',
1664 'langs' => 'mymodule@mymodule',
1665 'position' => 1000 + \$r,
1666 'enabled' => 'isModEnabled(\"mymodule\")',
1667 'perms' => '".(GETPOST('generatepermissions') ? '$user->hasRight("mymodule", "myobject", "read")' : '1')."',
1668 'target' => '',
1669 'user' => 2,
1670 'object' => 'MyObject'
1671 );
1672 \$this->menu[\$r++] = array(
1673 'fk_menu' => 'fk_mainmenu=mymodule,fk_leftmenu=myobject',
1674 'type' => 'left',
1675 'titre' => 'List MyObject',
1676 'mainmenu' => 'mymodule',
1677 'leftmenu' => 'mymodule_myobject_list',
1678 'url' => '/mymodule/myobject_list.php',
1679 'langs' => 'mymodule@mymodule',
1680 'position' => 1000 + \$r,
1681 'enabled' => 'isModEnabled(\"mymodule\")',
1682 'perms' => '".(GETPOST('generatepermissions') ? '$user->hasRight("mymodule", "myobject", "read")' : '1')."',
1683 'target' => '',
1684 'user' => 2,
1685 'object' => 'MyObject'
1686 );
1687 \$this->menu[\$r++] = array(
1688 'fk_menu' => 'fk_mainmenu=mymodule,fk_leftmenu=myobject',
1689 'type' => 'left',
1690 'titre' => 'New MyObject',
1691 'mainmenu' => 'mymodule',
1692 'leftmenu' => 'mymodule_myobject_new',
1693 'url' => '/mymodule/myobject_card.php?action=create',
1694 'langs' => 'mymodule@mymodule',
1695 'position' => 1000 + \$r,
1696 'enabled' => 'isModEnabled(\"mymodule\")',
1697 'perms' => '".(GETPOST('generatepermissions') ? '$user->hasRight("mymodule", "myobject", "write")' : '1')."',
1698 'target' => '',
1699 'user' => 2,
1700 'object' => 'MyObject'
1701 );";
1702 $stringtoadd = $ncObj->applyTo($stringtoadd);
1703
1704 $moduledescriptorfile = $destdir.'/core/modules/mod'.$module.'.class.php';
1705 }
1706 // TODO Allow a replace with regex using dolReplaceInFile with param arryreplacementisregex to 1
1707 // TODO Avoid duplicate addition
1708
1709 // load class and check if menu exist with same object name
1710 $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
1711 dol_include_once($pathtofile);
1712 $class = 'mod'.$module;
1713 $moduleobj = null;
1714 if (class_exists($class)) {
1715 try {
1716 $moduleobj = new $class($db);
1717 '@phan-var-force DolibarrModules $moduleobj';
1719 } catch (Exception $e) {
1720 $error++;
1721 dol_print_error($db, $e->getMessage());
1722 }
1723 }
1724 if (is_object($moduleobj)) {
1725 $menus = $moduleobj->menu;
1726 } else {
1727 $menus = array();
1728 }
1729 $counter = 0 ;
1730 foreach ($menus as $menu) {
1731 if ($menu['leftmenu'] == strtolower($objectname)) {
1732 $counter++;
1733 }
1734 }
1735 if (!$counter) {
1736 $checkComment = checkExistComment($moduledescriptorfile, 0);
1737 if ($checkComment < 0) {
1738 $warning++;
1739 setEventMessages($langs->trans("WarningCommentNotFound", $langs->trans("Menus"), basename($moduledescriptorfile)), null, 'warnings');
1740 } else {
1741 $arrayofreplacement = array(
1742 '/* BEGIN MODULEBUILDER LEFTMENU MYOBJECT */' => '/* BEGIN MODULEBUILDER LEFTMENU '.strtoupper($objectname).' */'.$stringtoadd."\n\t\t".'/* END MODULEBUILDER LEFTMENU '.strtoupper($objectname).' */'."\n\t\t".'/* BEGIN MODULEBUILDER LEFTMENU MYOBJECT */'
1743 );
1744 dolReplaceInFile($moduledescriptorfile, $arrayofreplacement);
1745 }
1746 }
1747 // Add module descriptor to list of files to replace "MyObject' string with real name of object.
1748 $filetogenerate[] = 'core/modules/mod'.$module.'.class.php';
1749 }
1750
1751 if (! $error && GETPOST('nogeneratelines', 'aZ09')) {
1752 $checkComment = checkExistComment($moduledescriptorfile, 0);
1753 if ($checkComment < 0) {
1754 $warning++;
1755 setEventMessages($langs->trans("WarningCommentNotFound", $langs->trans("Menus"), basename($moduledescriptorfile)), null, 'warnings');
1756 } else {
1757 // File path
1758 $TFilePaths = [
1759 $destdir . '/class/' . strtolower($objectname) . '.class.php',
1760 $destdir . '/class/api_' . strtolower($module) . '.class.php',
1761 $destdir . '/' . strtolower($objectname) . '_card.php'
1762 ];
1763
1764 // Pattern to remove everything between the tags
1765 $pattern = '/\/\/BEGIN MODULEBUILDER LINES.*?\/\/END MODULEBUILDER LINES\s*/s';
1766 foreach ($TFilePaths as $filePath) {
1767 // Skip files that were not generated (e.g. the API class when API generation is disabled);
1768 // a missing optional file must not abort the whole object generation.
1769 if (file_exists($filePath) && !removePatternFromFile($filePath, $pattern)) {
1770 $error++;
1771 }
1772 }
1773 }
1774 }
1775
1776 // Apply object tab selection on the generated lib file:
1777 // selected tabs -> hardcode the show flag to 1 (visible without extra config) ; unselected -> remove flag declaration and tab block
1778 if (!$error) {
1779 $libdestfile = $destdir.'/'.$ncObj->applyToFilename('lib/mymodule_myobject.lib.php');
1780 foreach (getModuleBuilderObjectTabs() as $tabkey => $tabinfo) {
1781 $marker = $tabinfo['marker'];
1782 if (in_array($tabkey, $enabledtabs, true)) {
1783 $arrayreplacement = array(
1784 '/\$'.$tabinfo['var'].' = getDolGlobalInt\‍([^;]*\‍);/' => '$'.$tabinfo['var'].' = 1;'
1785 );
1786 if (dolReplaceInFile($libdestfile, $arrayreplacement, '', '0', 0, 1) < 0) {
1787 $error++;
1788 dol_syslog("modulebuilder: failed to activate tab flag '".$tabkey."' in ".$libdestfile, LOG_ERR);
1789 }
1790 } else {
1791 if (!removePatternFromFile($libdestfile, '/\h*\/\/ BEGIN MODULEBUILDER TABFLAG '.$marker.'.*?\/\/ END MODULEBUILDER TABFLAG '.$marker.'\s*/s')
1792 || !removePatternFromFile($libdestfile, '/\h*\/\/ BEGIN MODULEBUILDER TAB '.$marker.'.*?\/\/ END MODULEBUILDER TAB '.$marker.'\s*/s')) {
1793 $error++;
1794 dol_syslog("modulebuilder: failed to purge tab '".$tabkey."' in ".$libdestfile, LOG_ERR);
1795 }
1796 }
1797 }
1798 // Agenda has an extra event widget on the card page: purge it too to avoid a dead link when the agenda tab is excluded
1799 if (!$error && !in_array('agenda', $enabledtabs, true)) {
1800 $carddestfile = $destdir.'/'.$ncObj->applyToFilename('myobject_card.php');
1801 if (!removePatternFromFile($carddestfile, '/\h*\/\/ BEGIN MODULEBUILDER TAB AGENDA.*?\/\/ END MODULEBUILDER TAB AGENDA\s*/s')) {
1802 $error++;
1803 dol_syslog("modulebuilder: failed to purge agenda widget in ".$carddestfile, LOG_ERR);
1804 }
1805 }
1806 if ($objectalreadyexists) {
1807 setEventMessages($langs->trans("WarningTabSelectionOnRegeneration"), null, 'warnings');
1808 }
1809 }
1810
1811 if (!$error) {
1812 // Edit PHP files to make replacement
1813 foreach ($filetogenerate as $destfile) {
1814 $phpfileval['fullname'] = $destdir.'/'.$destfile;
1815
1816 //var_dump($phpfileval['fullname']);
1817 $licenceValue = getDolGlobalString('MODULEBUILDER_SPECIFIC_AUTHOR')
1818 ? dol_print_date($now, '%Y') . ' ' . getDolGlobalString('MODULEBUILDER_SPECIFIC_AUTHOR')
1819 : getLicenceHeader($user, $langs, $now);
1820
1821 $arrayreplacement = array_merge(
1822 $ncObj->getSubstitutionMap(),
1823 [
1824 'htdocs/modulebuilder/template/' => $ncObj->moduleNameLower,
1825 '---Replace with your own copyright and developer email---' => $licenceValue,
1826 ]
1827 );
1828
1829 if (basename($phpfileval['fullname']) === 'mod'.$module.'.class.php') {
1830 // Module descriptor: substitute content but keep the persistent MODULEBUILDER markers intact
1831 $result = dolReplaceInFilePreservingModuleBuilderMarkers($phpfileval['fullname'], $arrayreplacement);
1832 } else {
1833 $result = dolReplaceInFile($phpfileval['fullname'], $arrayreplacement); // @phpstan-ignore-line
1834 }
1835 //var_dump($result);
1836 if ($result < 0) {
1837 setEventMessages($langs->trans("ErrorFailToMakeReplacementInto", $phpfileval['fullname']), null, 'errors');
1838 } else {
1839 modulebuilderValidateGeneratedFile($phpfileval['fullname'], $ncObj);
1840 }
1841 }
1842 }
1843
1844 if (!$error && $ncObj !== null) {
1845 // Apply object name substitution to ALL PHP files in the module directory.
1846 // initmodule only substitutes the module name; files it creates (e.g. testmodindex.php,
1847 // lib/testmod.lib.php, admin/setup.php) still contain myobject/mymodule placeholders
1848 // that must be resolved when an object is first added.
1849 $licenceValueAll = getDolGlobalString('MODULEBUILDER_SPECIFIC_AUTHOR')
1850 ? dol_print_date($now, '%Y') . ' ' . getDolGlobalString('MODULEBUILDER_SPECIFIC_AUTHOR')
1851 : getLicenceHeader($user, $langs, $now);
1852 $moduleReplacementAll = array_merge(
1853 $ncObj->getSubstitutionMap(),
1854 [
1855 'htdocs/modulebuilder/template/' => $ncObj->moduleNameLower,
1856 '---Replace with your own copyright and developer email---' => $licenceValueAll,
1857 ]
1858 );
1859 $allModulePhpFiles = dol_dir_list($destdir, 'files', 1, '\.php$');
1860 // The module descriptor must NOT go through the blanket substitution: it keeps persistent
1861 // MYOBJECT/MYMODULE markers (TOPMENU/LEFTMENU) reused when generating subsequent objects, and its
1862 // own placeholders are already resolved by initmodule and the dedicated menu/permission blocks.
1863 $moduledescriptorbasename = 'mod'.$module.'.class.php';
1864 if (is_array($allModulePhpFiles) && !empty($allModulePhpFiles)) {
1865 foreach ($allModulePhpFiles as $phpFileval) {
1866 if (basename($phpFileval['fullname']) === $moduledescriptorbasename) {
1867 continue;
1868 }
1869 $result = dolReplaceInFile($phpFileval['fullname'], $moduleReplacementAll);
1870 if ($result < 0) {
1871 setEventMessages($langs->trans("ErrorFailToMakeReplacementInto", $phpFileval['fullname']), null, 'warnings');
1872 }
1873 }
1874 }
1875 // Delete initmodule placeholder files superseded by initobject-generated files.
1876 $moduleLowerForPlaceholder = strtolower($module);
1877 foreach ([
1878 $destdir . '/stats/myobject_index.php',
1879 $destdir . '/lib/' . $moduleLowerForPlaceholder . '_myobject.lib.php',
1880 ] as $placeholder) {
1881 if (file_exists($placeholder)) {
1882 dol_delete_file($placeholder);
1883 }
1884 }
1885 }
1886
1887 $object = null;
1888 if (!$error) {
1889 // Edit the class file to write properties
1890 $object = rebuildObjectClass($destdir, $module, $objectname, $newmask);
1891
1892 if (is_numeric($object) && $object <= 0) {
1893 $pathoffiletoeditsrc = $destdir.'/class/'.strtolower($objectname).'.class.php';
1894 setEventMessages($langs->trans('ErrorFailToCreateFile', $pathoffiletoeditsrc), null, 'errors');
1895 $warning++;
1896 }
1897 // check if documentation was generate and add table of properties object
1898 $file = $destdir.'/class/'.strtolower($objectname).'.class.php';
1899 $destfile = $destdir.'/doc/Documentation.asciidoc';
1900
1901 if (file_exists($destfile)) {
1902 writePropsInAsciiDoc($file, $objectname, $destfile);
1903 }
1904 }
1905 if (!$error && $object !== null) {
1906 // Edit sql with new properties
1907 $result = rebuildObjectSql($destdir, $module, $objectname, $newmask, '', $object);
1908
1909 if ($result <= 0) {
1910 setEventMessages($langs->trans('ErrorFailToCreateFile', '.sql'), null);
1911 $error++;
1912 }
1913 }
1914
1915 if (!$error) {
1916 setEventMessages($langs->trans('FilesForObjectInitialized', $objectname), null);
1917 $tabobj = $objectname;
1918 } else {
1919 $tabobj = 'newobject';
1920 }
1921
1922 // check if module is enabled
1923 if (isModEnabled(strtolower($module))) {
1924 $result = unActivateModule(strtolower($module));
1925 dolibarr_set_const($db, "MAIN_IHM_PARAMS_REV", getDolGlobalInt('MAIN_IHM_PARAMS_REV') + 1, 'chaine', 0, '', $conf->entity);
1926 if ($result) {
1927 setEventMessages($result, null, 'errors');
1928 }
1929 setEventMessages($langs->trans('WarningModuleNeedRefresh', $langs->transnoentities($module)), null, 'warnings');
1930 header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=objects&module='.$module);
1931 exit;
1932 }
1933}
1934
1935// Add a dictionary
1936if ($dirins && $action == 'initdic' && $module && empty($cancel) /* && $user->hasRight("modulebuilder", "run") // already checked */) {
1937 $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
1938 $destdir = $dirins.'/'.strtolower($module);
1939 $moduledescriptorfile = $dirins.'/'.strtolower($module).'/core/modules/mod'.$module.'.class.php';
1940
1941 if (!GETPOST('dicname')) {
1942 $error++;
1943 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Table")), null, 'errors');
1944 }
1945 if (!GETPOST('label')) {
1946 $error++;
1947 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Label")), null, 'errors');
1948 }
1949 if (!$error) {
1950 $newdicname = $dicname;
1951 if (!preg_match('/^c_/', $newdicname)) {
1952 $newdicname = 'c_'.$dicname;
1953 }
1954 dol_include_once($pathtofile);
1955 $class = 'mod'.$module;
1956
1957 $moduleobj = null;
1958 if (class_exists($class)) {
1959 try {
1960 $moduleobj = new $class($db);
1961 '@phan-var-force DolibarrModules $moduleobj';
1963 } catch (Exception $e) {
1964 $error++;
1965 dol_print_error($db, $e->getMessage());
1966 }
1967 } else {
1968 $error++;
1969 }
1970 if ($moduleobj === null) {
1971 $langs->load("errors");
1972 dol_print_error($db, $langs->trans("ErrorFailedToLoadModuleDescriptorForXXX", $module));
1973 exit;
1974 }
1975 $dictionaries = $moduleobj->dictionaries;
1976 $checkComment = checkExistComment($moduledescriptorfile, 2);
1977 if ($checkComment < 0) {
1978 setEventMessages($langs->trans("WarningCommentNotFound", $langs->trans("Dictionaries"), "mod".$module."class.php"), null, 'warnings');
1979 } else {
1980 createNewDictionnary($module, $moduledescriptorfile, $newdicname, $dictionaries);
1981 if (function_exists('opcache_invalidate')) {
1982 opcache_reset(); // remove the include cache hell !
1983 }
1984 clearstatcache(true);
1985 header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=dictionaries&module='.$module.($forceddirread ? '@'.$dirread : ''));
1986 exit;
1987 }
1988 }
1989}
1990
1991// Delete a SQL table
1992if ($dirins && ($action == 'droptable' || $action == 'droptableextrafields') && !empty($module) && !empty($tabobj) /* && $user->hasRight("modulebuilder", "run") // already checked */) {
1993 $objectname = $tabobj;
1994
1995 $arrayoftables = array();
1996 if ($action == 'droptable') { // Test on permission already done
1997 $arrayoftables[] = MAIN_DB_PREFIX.strtolower($module).'_'.strtolower($tabobj);
1998 }
1999 if ($action == 'droptableextrafields') { // Test on permission already done
2000 $arrayoftables[] = MAIN_DB_PREFIX.strtolower($module).'_'.strtolower($tabobj).'_extrafields';
2001 }
2002
2003 foreach ($arrayoftables as $tabletodrop) {
2004 $nb = -1;
2005 $sql = "SELECT COUNT(*) as nb FROM ".$tabletodrop;
2006 $resql = $db->query($sql);
2007 if ($resql) {
2008 $obj = $db->fetch_object($resql);
2009 if ($obj) {
2010 $nb = (int) $obj->nb;
2011 }
2012 } else {
2013 if ($db->lasterrno() == 'DB_ERROR_NOSUCHTABLE') {
2014 setEventMessages($langs->trans("TableDoesNotExists", $tabletodrop), null, 'warnings');
2015 } else {
2017 }
2018 }
2019 if ($nb == 0) {
2020 $resql = $db->DDLDropTable($tabletodrop);
2021 //var_dump($resql);
2022 setEventMessages($langs->trans("TableDropped", $tabletodrop), null, 'mesgs');
2023 } elseif ($nb > 0) {
2024 setEventMessages($langs->trans("TableNotEmptyDropCanceled", $tabletodrop), null, 'warnings');
2025 }
2026 }
2027}
2028
2029if ($dirins && $action == 'addproperty' && empty($cancel) && !empty($module) && (!empty($tabobj) || !empty(GETPOST('obj'))) /* && $user->hasRight("modulebuilder", "run") // already checked */) {
2030 $error = 0;
2031
2032 $objectname = (GETPOST('obj') ? GETPOST('obj') : $tabobj);
2033
2034 $dirins = $dirread = $listofmodules[strtolower($module)]['moduledescriptorrootpath'];
2035 $moduletype = $listofmodules[strtolower($module)]['moduletype'];
2036
2037 $srcdir = $dirread.'/'.strtolower($module);
2038 $destdir = $dirins.'/'.strtolower($module);
2039 dol_mkdir($destdir);
2040
2041 $objects = dolGetListOfObjectClasses($destdir);
2042 if (!in_array($objectname, array_values($objects))) {
2043 $error++;
2044 setEventMessages($langs->trans("ErrorObjectNotFound", $langs->transnoentities($objectname)), null, 'errors');
2045 }
2046
2047 $addfieldentry = array();
2048
2049 // We click on add property
2050 if (!GETPOST('regenerateclasssql') && !GETPOST('regeneratemissing')) {
2051 if (!GETPOST('propname', 'aZ09')) {
2052 $error++;
2053 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Name")), null, 'errors');
2054 }
2055 if (!GETPOST('proplabel', 'alpha')) {
2056 $error++;
2057 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Label")), null, 'errors');
2058 }
2059 if (!GETPOST('proptype', 'alpha')) {
2060 $error++;
2061 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Type")), null, 'errors');
2062 }
2063
2064
2065 if (!$error && !GETPOST('regenerateclasssql') && !GETPOST('regeneratemissing')) {
2066 // Preserve case for composite types such as 'integer:Societe:societe/class/societe.class.php:1:(...__SHARED_ENTITIES__...)'
2067 // because the colon-separated parts include PHP class names (case-sensitive) and __XXX__ substitution
2068 // tokens that are uppercase by convention. Only lowercase simple atomic types (#34602).
2069 $proptype = GETPOST('proptype', 'alpha');
2070 if (strpos($proptype, ':') === false && strpos($proptype, '_') === false) {
2071 $proptype = strtolower($proptype);
2072 }
2073 $addfieldentry = array(
2074 'name' => GETPOST('propname', 'aZ09'),
2075 'label' => GETPOST('proplabel', 'alpha'),
2076 'type' => $proptype,
2077 'arrayofkeyval' => GETPOST('proparrayofkeyval', 'nohtml'), // Example json string '{"0":"Draft","1":"Active","-1":"Cancel"}'
2078 'visible' => GETPOST('propvisible', 'alphanohtml'),
2079 'enabled' => GETPOST('propenabled', 'alphanohtml'),
2080 'position' => GETPOSTINT('propposition'),
2081 'notnull' => GETPOSTINT('propnotnull'),
2082 'index' => GETPOSTINT('propindex'),
2083 'foreignkey' => GETPOST('propforeignkey', 'alpha'),
2084 'searchall' => GETPOSTINT('propsearchall'),
2085 'isameasure' => GETPOSTINT('propisameasure'),
2086 'showoncombobox' => GETPOSTINT('propshowoncombobox'),
2087 'comment' => GETPOST('propcomment', 'alpha'),
2088 'help' => GETPOST('prophelp', 'alpha'),
2089 'css' => GETPOST('propcss', 'alpha'), // Can be 'maxwidth500 widthcentpercentminusxx' for example
2090 'cssview' => GETPOST('propcssview', 'alpha'),
2091 'csslist' => GETPOST('propcsslist', 'alpha'),
2092 'default' => GETPOST('propdefault', 'restricthtml'),
2093 'noteditable' => GETPOSTINT('propnoteditable'),
2094 //'alwayseditable' => GETPOSTINT('propalwayseditable'),
2095 'validate' => GETPOSTINT('propvalidate')
2096 );
2097
2098 if (!empty($addfieldentry['arrayofkeyval']) && !is_array($addfieldentry['arrayofkeyval'])) {
2099 $tmpdecode = json_decode($addfieldentry['arrayofkeyval'], true);
2100 if ($tmpdecode) { // If string is already a json
2101 $addfieldentry['arrayofkeyval'] = $tmpdecode;
2102 } else { // If string is a list of lines with "key,value"
2103 $tmparray = dolExplodeIntoArray($addfieldentry['arrayofkeyval'], "\n", ",");
2104 $addfieldentry['arrayofkeyval'] = $tmparray;
2105 }
2106 }
2107 }
2108 }
2109
2110 /*if (GETPOST('regeneratemissing'))
2111 {
2112 setEventMessages($langs->trans("FeatureNotYetAvailable"), null, 'warnings');
2113 $error++;
2114 }*/
2115
2116 $moduletype = $listofmodules[strtolower($module)]['moduletype'];
2117
2118 $object = null;
2119 // Edit the class file to write properties
2120 if (!$error) {
2121 $object = rebuildObjectClass($destdir, $module, $objectname, $newmask, $srcdir, $addfieldentry, $moduletype);
2122
2123 if (is_numeric($object) && $object <= 0) {
2124 $pathoffiletoeditsrc = $destdir.'/class/'.strtolower($objectname).'.class.php';
2125 setEventMessages($langs->trans('ErrorFailToCreateFile', $pathoffiletoeditsrc), null, 'errors');
2126 $error++;
2127 }
2128 }
2129
2130 // Edit sql with new properties
2131 if (!$error && $object !== null) {
2132 $result = rebuildObjectSql($destdir, $module, $objectname, $newmask, $srcdir, $object, $moduletype);
2133
2134 if ($result <= 0) {
2135 setEventMessages($langs->trans('ErrorFailToCreateFile', '.sql'), null, 'errors');
2136 $error++;
2137 }
2138 }
2139
2140 if (!$error) {
2141 clearstatcache(true);
2142
2143 setEventMessages($langs->trans('FilesForObjectUpdated', $objectname), null);
2144
2145 setEventMessages($langs->trans('WarningDatabaseIsNotUpdated'), null);
2146
2147 // Make a redirect to reload all data
2148 header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=objects&module='.$module.($forceddirread ? '@'.$dirread : '').'&tabobj='.$objectname.'&nocache='.time());
2149 exit;
2150 }
2151}
2152
2153if ($dirins && $action == 'confirm_deleteproperty' && $propertykey /* && $user->hasRight("modulebuilder", "run") // already checked */) {
2154 $objectname = $tabobj;
2155
2156 $dirins = $dirread = $listofmodules[strtolower($module)]['moduledescriptorrootpath'];
2157 $moduletype = $listofmodules[strtolower($module)]['moduletype'];
2158
2159 $srcdir = $dirread.'/'.strtolower($module);
2160 $destdir = $dirins.'/'.strtolower($module);
2161 dol_mkdir($destdir);
2162
2163 $object = null;
2164 // Edit the class file to write properties
2165 if (!$error) {
2166 $object = rebuildObjectClass($destdir, $module, $objectname, $newmask, $srcdir, array(), $propertykey);
2167
2168 if (is_numeric($object) && $object <= 0) {
2169 $pathoffiletoeditsrc = $destdir.'/class/'.strtolower($objectname).'.class.php';
2170 setEventMessages($langs->trans('ErrorFailToCreateFile', $pathoffiletoeditsrc), null, 'errors');
2171 $error++;
2172 }
2173 }
2174
2175 // Edit sql with new properties
2176 if (!$error && $object !== null) {
2177 $result = rebuildObjectSql($destdir, $module, $objectname, $newmask, $srcdir, $object);
2178
2179 if ($result <= 0) {
2180 setEventMessages($langs->trans('ErrorFailToCreateFile', '.sql'), null, 'errors');
2181 $error++;
2182 }
2183 }
2184
2185 if (!$error) {
2186 setEventMessages($langs->trans('FilesForObjectUpdated', $objectname), null);
2187
2188 clearstatcache(true);
2189
2190 // Make a redirect to reload all data
2191 header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=objects&module='.$module.($forceddirread ? '@'.$dirread : '').'&tabobj='.$objectname);
2192 exit;
2193 }
2194}
2195
2196if ($dirins && $action == 'confirm_deletemodule' /* && $user->hasRight("modulebuilder", "run") // already checked */) {
2197 if (preg_match('/[^a-z0-9_]/i', $module)) {
2198 $error++;
2199 setEventMessages($langs->trans("SpaceOrSpecialCharAreNotAllowed"), null, 'errors');
2200 }
2201
2202 if (!$error) {
2203 $modulelowercase = strtolower($module);
2204
2205 // Dir for module
2206 $dir = $dirins.'/'.$modulelowercase;
2207
2208 $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
2209
2210 // Dir for module
2211 $dir = dol_buildpath($modulelowercase, 0);
2212
2213 // Zip file to build
2214 $FILENAMEZIP = '';
2215
2216 // Load module
2217 dol_include_once($pathtofile);
2218 $class = 'mod'.$module;
2219
2220 $moduleobj = null;
2221
2222 if (class_exists($class)) {
2223 try {
2224 $moduleobj = new $class($db);
2225 '@phan-var-force DolibarrModules $moduleobj';
2227 } catch (Exception $e) {
2228 $error++;
2229 dol_print_error($db, $e->getMessage());
2230 }
2231 } else {
2232 $error++;
2233 $langs->load("errors");
2234 setEventMessages($langs->trans("ErrorFailedToLoadModuleDescriptorForXXX", $module), null, 'warnings');
2235 }
2236
2237 if ($moduleobj) {
2238 $moduleobj->remove();
2239 }
2240
2241 $result = dol_delete_dir_recursive($dir);
2242
2243 if ($result > 0) {
2244 setEventMessages($langs->trans("DirWasRemoved", $modulelowercase), null);
2245
2246 clearstatcache(true);
2247 if (function_exists('opcache_invalidate')) {
2248 opcache_reset(); // remove the include cache hell !
2249 }
2250
2251 header("Location: ".$_SERVER["PHP_SELF"].'?module=deletemodule');
2252 exit;
2253 } else {
2254 setEventMessages($langs->trans("PurgeNothingToDelete"), null, 'warnings');
2255 }
2256 }
2257
2258 $action = '';
2259 $module = 'deletemodule';
2260}
2261
2262if ($dirins && $action == 'confirm_deleteobject' && $objectname /* && $user->hasRight("modulebuilder", "run") // already checked */) {
2263 if (preg_match('/[^a-z0-9_]/i', $objectname)) {
2264 $error++;
2265 setEventMessages($langs->trans("SpaceOrSpecialCharAreNotAllowed"), null, 'errors');
2266 }
2267
2268 if (!$error) {
2269 $modulelowercase = strtolower($module);
2270 $objectlowercase = strtolower($objectname);
2271
2272 // Dir for module
2273 $dir = $dirins.'/'.$modulelowercase;
2274
2275 // Delete some files
2276 try {
2277 $ncObjDel = new NamingContract($module, $objectname);
2278 } catch (\InvalidArgumentException $e) {
2279 $error++;
2280 setEventMessages($langs->trans("SpaceOrSpecialCharAreNotAllowed"), null, 'errors');
2281 $ncObjDel = null;
2282 }
2283 $filetodelete = [];
2284 if (!$error && $ncObjDel !== null) {
2285 foreach ([
2286 'myobject_card.php',
2287 'myobject_note.php',
2288 'myobject_contact.php',
2289 'myobject_document.php',
2290 'myobject_agenda.php',
2291 'myobject_list.php',
2292 'admin/myobject_extrafields.php',
2293 'lib/mymodule_myobject.lib.php',
2294 'sql/llx_mymodule_myobject.sql',
2295 'sql/llx_mymodule_myobject_extrafields.sql',
2296 'sql/llx_mymodule_myobject.key.sql',
2297 'sql/llx_mymodule_myobject_extrafields.key.sql',
2298 'scripts/myobject.php',
2299 'class/myobject.class.php',
2300 'class/myobjectstats.class.php',
2301 'core/modules/mymodule/mod_myobject_advanced.php',
2302 'core/modules/mymodule/mod_myobject_standard.php',
2303 'core/modules/mymodule/modules_myobject.php',
2304 'core/modules/mymodule/doc/doc_generic_myobject_odt.modules.php',
2305 'core/modules/mymodule/doc/pdf_standard_myobject.modules.php',
2306 'stats/myobject_index.php',
2307 ] as $templateFile) {
2308 $filetodelete[$templateFile] = $ncObjDel->applyToFilename($templateFile);
2309 }
2310 // Exceptions: target filenames differ from simple token substitution
2311 $filetodelete['ajax/myobject.lib.php'] = 'ajax/' . $ncObjDel->objectNameLower . '.php';
2312 $filetodelete['test/phpunit/MyObjectTest.php'] = 'test/phpunit/' . $ncObjDel->objectNameLower . 'Test.php';
2313 $filetodelete['class/api_myobject.class.php'] = 'class/api_' . $ncObjDel->moduleNameLower . '.class.php';
2314 }
2315
2316 //menu for the object selected
2317 // load class and check if menu,permission,documentation exist for this object
2318 $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
2319 dol_include_once($pathtofile);
2320 $class = 'mod'.$module;
2321 $moduleobj = null;
2322 if (class_exists($class)) {
2323 try {
2324 $moduleobj = new $class($db);
2325 '@phan-var-force DolibarrModules $moduleobj';
2327 } catch (Exception $e) {
2328 $error++;
2329 dol_print_error($db, $e->getMessage());
2330 }
2331 } else {
2332 $error++;
2333 $langs->load("errors");
2334 dol_print_error($db, $langs->trans("ErrorFailedToLoadModuleDescriptorForXXX", $module));
2335 exit;
2336 }
2337 $moduledescriptorfile = $dirins.'/'.strtolower($module).'/core/modules/mod'.$module.'.class.php';
2338
2339 // delete menus linked to the object
2340 $menus = $moduleobj->menu;
2341 $rewriteMenu = checkExistComment($moduledescriptorfile, 0);
2342
2343 if ($rewriteMenu < 0) {
2344 setEventMessages($langs->trans("WarningCommentNotFound", $langs->trans("Menus"), "mod".$module."class.php"), null, 'warnings');
2345 } else {
2346 reWriteAllMenus($moduledescriptorfile, $menus, $objectname, null, -1);
2347 }
2348
2349 // regenerate permissions and delete them
2350 $permissions = $moduleobj->rights;
2351 $rewritePerms = checkExistComment($moduledescriptorfile, 1);
2352 if ($rewritePerms < 0) {
2353 setEventMessages($langs->trans("WarningCommentNotFound", $langs->trans("Permissions"), "mod".$module."class.php"), null, 'warnings');
2354 } else {
2355 $reportPerms = modulebuilderSyncRights(RightsSyncCommand::forObjectDeletion($module, $moduledescriptorfile, is_array($permissions) ? $permissions : array(), $objectname));
2356 // A rights conflict deliberately does not cancel the object deletion below: the warning
2357 // already told the user the leftover rights need a manual cleanup.
2358 }
2359 if ($rewritePerms && $rewriteMenu) {
2360 // check if documentation has been generated
2361 $file_doc = $dirins.'/'.strtolower($module).'/doc/Documentation.asciidoc';
2362 deletePropsAndPermsFromDoc($file_doc, $objectname);
2363
2364 clearstatcache(true);
2365 if (function_exists('opcache_invalidate')) {
2366 opcache_reset(); // remove the include cache hell !
2367 }
2368 $resultko = 0;
2369 foreach ($filetodelete as $tmpfiletodelete) {
2370 $resulttmp = dol_delete_file($dir.'/'.$tmpfiletodelete, 1, 0, 1);
2371 $resulttmp = dol_delete_file($dir.'/'.$tmpfiletodelete.'.back', 1, 0, 1);
2372 if (!$resulttmp) {
2373 $resultko++;
2374 }
2375 }
2376
2377 if ($resultko == 0) {
2378 setEventMessages($langs->trans("FilesDeleted"), null);
2379 } else {
2380 setEventMessages($langs->trans("ErrorSomeFilesCouldNotBeDeleted"), null, 'warnings');
2381 }
2382 }
2383 }
2384
2385 $action = '';
2386 if (! $error) {
2387 $tabobj = 'newobject';
2388 } else {
2389 $tabobj = 'deleteobject';
2390 }
2391
2392 // check if module is enabled
2393 if (isModEnabled(strtolower($module))) {
2394 $result = unActivateModule(strtolower($module));
2395 dolibarr_set_const($db, "MAIN_IHM_PARAMS_REV", getDolGlobalInt('MAIN_IHM_PARAMS_REV') + 1, 'chaine', 0, '', $conf->entity);
2396 if ($result) {
2397 setEventMessages($result, null, 'errors');
2398 }
2399 setEventMessages($langs->trans('WarningModuleNeedRefresh', $langs->transnoentities($module)), null, 'warnings');
2400 header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=objects&tabobj=deleteobject&module='.urlencode($module));
2401 exit;
2402 }
2403}
2404
2405if (($dirins && $action == 'confirm_deletedictionary' && $dicname) || ($dirins && $action == 'confirm_deletedictionary' && GETPOST('dictionnarykey')) /* && $user->hasRight("modulebuilder", "run") // already checked */) {
2406 $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
2407 $destdir = $dirins.'/'.strtolower($module);
2408 $moduledescriptorfile = $dirins.'/'.strtolower($module).'/core/modules/mod'.$module.'.class.php';
2409
2410 if (preg_match('/[^a-z0-9_]/i', $dicname)) {
2411 $error++;
2412 setEventMessages($langs->trans("SpaceOrSpecialCharAreNotAllowed"), null, 'errors');
2413 }
2414
2415 if (!empty($dicname)) {
2416 $newdicname = $dicname;
2417 if (!preg_match('/^c_/', $newdicname)) {
2418 $newdicname = 'c_'.strtolower($dicname);
2419 }
2420 } else {
2421 $newdicname = null;
2422 }
2423
2424 dol_include_once($pathtofile);
2425 $class = 'mod'.$module;
2426
2427 $moduleobj = null;
2428 if (class_exists($class)) {
2429 try {
2430 $moduleobj = new $class($db);
2431 '@phan-var-force DolibarrModules $moduleobj';
2433 } catch (Exception $e) {
2434 $error++;
2435 dol_print_error($db, $e->getMessage());
2436 }
2437 } else {
2438 $error++;
2439 }
2440 if ($moduleobj === null) {
2441 $langs->load("errors");
2442 dol_print_error($db, $langs->trans("ErrorFailedToLoadModuleDescriptorForXXX", $module));
2443 exit;
2444 }
2445
2446 $dicts = $moduleobj->dictionaries;
2447 $checkComment = checkExistComment($moduledescriptorfile, 2);
2448 if ($checkComment < 0) {
2449 $error++;
2450 setEventMessages($langs->trans("WarningCommentNotFound", $langs->trans("Dictionaries"), "mod".$module."class.php"), null, 'warnings');
2451 }
2452
2453 if (!empty(GETPOST('dictionnarykey'))) {
2454 $newdicname = $dicts['tabname'][GETPOSTINT('dictionnarykey') - 1];
2455 }
2456
2457 // Lookup the table dicname
2458 $checkTable = false;
2459 if ($newdicname !== null) {
2460 $checkTable = $db->DDLDescTable(MAIN_DB_PREFIX.strtolower($newdicname));
2461 }
2462
2463 if (is_bool($checkTable) || $db->num_rows($checkTable) <= 0) { // @phpstan-ignore-line
2464 $error++;
2465 }
2466
2467 // search the key by name
2468 $keyToDelete = null;
2469 foreach ($dicts['tabname'] as $key => $table) {
2470 //var_dump($table." /////// ".$newdicname);exit;
2471 if (strtolower($table) === $newdicname) {
2472 $keyToDelete = $key;
2473 break;
2474 }
2475 }
2476 // delete all dicname's key values from the dictionary
2477 if ($keyToDelete !== null) {
2478 $keysToDelete = ['tabname', 'tablib', 'tabsql', 'tabsqlsort', 'tabfield', 'tabfieldvalue', 'tabfieldinsert', 'tabrowid', 'tabcond', 'tabhelp'];
2479 foreach ($keysToDelete as $key) {
2480 unset($dicts[$key][$keyToDelete]);
2481 }
2482 } else {
2483 $error++;
2484 setEventMessages($langs->trans("ErrorDictionaryNotFound", ucfirst($dicname)), null, 'errors');
2485 }
2486 if (!$error && $newdicname !== null) {
2487 // delete table
2488 $_results = $db->DDLDropTable(MAIN_DB_PREFIX.strtolower($newdicname));
2489 if ($_results < 0) {
2491 $langs->load("errors");
2492 setEventMessages($langs->trans("ErrorTableNotFound", $newdicname), null, 'errors');
2493 }
2494 // rebuild file after update dictionaries
2495 $result = updateDictionaryInFile($module, $moduledescriptorfile, $dicts);
2496 if ($result > 0) {
2497 setEventMessages($langs->trans("DictionaryDeleted", ucfirst(substr($newdicname, 2))), null);
2498 }
2499 if (function_exists('opcache_invalidate')) {
2500 opcache_reset(); // remove the include cache hell !
2501 }
2502 clearstatcache(true);
2503 header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=dictionaries&module='.$module.($forceddirread ? '@'.$dirread : ''));
2504 exit;
2505 }
2506}
2507if ($dirins && $action == 'updatedictionary' && GETPOST('dictionnarykey') /* && $user->hasRight("modulebuilder", "run") // already checked */) {
2508 $keydict = GETPOSTINT('dictionnarykey') - 1 ;
2509
2510 $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
2511 $destdir = $dirins.'/'.strtolower($module);
2512 $moduledescriptorfile = $dirins.'/'.strtolower($module).'/core/modules/mod'.$module.'.class.php';
2513 dol_include_once($pathtofile);
2514 $class = 'mod'.$module;
2515
2516 $moduleobj = null;
2517 if (class_exists($class)) {
2518 try {
2519 $moduleobj = new $class($db);
2520 '@phan-var-force DolibarrModules $moduleobj';
2522 } catch (Exception $e) {
2523 $error++;
2524 dol_print_error($db, $e->getMessage());
2525 }
2526 } else {
2527 $error++;
2528 }
2529 if ($moduleobj === null) {
2530 $langs->load("errors");
2531 dol_print_error($db, $langs->trans("ErrorFailedToLoadModuleDescriptorForXXX", $module));
2532 exit;
2533 }
2534
2535 $dicts = $moduleobj->dictionaries;
2536 if (!empty(GETPOST('tablib')) && GETPOST('tablib') !== $dicts['tablib'][$keydict]) {
2537 $dicts['tablib'][$keydict] = ucfirst(strtolower(GETPOST('tablib')));
2538 $checkComment = checkExistComment($moduledescriptorfile, 2);
2539 if ($checkComment < 0) {
2540 setEventMessages($langs->trans("WarningCommentNotFound", $langs->trans("Dictionaries"), "mod".$module."class.php"), null, 'warnings');
2541 } else {
2542 $updateDict = updateDictionaryInFile($module, $moduledescriptorfile, $dicts);
2543 if ($updateDict > 0) {
2544 setEventMessages($langs->trans("DictionaryNameUpdated", ucfirst(GETPOST('tablib'))), null);
2545 }
2546 if (function_exists('opcache_invalidate')) {
2547 opcache_reset(); // remove the include cache hell !
2548 }
2549 clearstatcache(true);
2550 header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=dictionaries&module='.$module.($forceddirread ? '@'.$dirread : ''));
2551 exit;
2552 }
2553 }
2554 //var_dump(GETPOST('tablib'));exit;
2555}
2556if ($dirins && $action == 'generatedoc' /* && $user->hasRight("modulebuilder", "run") // already checked */) {
2557 $modulelowercase = strtolower($module);
2558
2559 // Dir for module
2560 $dirofmodule = dol_buildpath($modulelowercase, 0).'/doc';
2561
2562 $FILENAMEDOC = strtolower($module).'.html';
2563
2564 $util = new Utils($db);
2565 $result = $util->generateDoc($module);
2566
2567 if ($result > 0) {
2568 setEventMessages($langs->trans("DocFileGeneratedInto", $dirofmodule), null);
2569 } else {
2570 setEventMessages($util->error, $util->errors, 'errors');
2571 }
2572}
2573
2574if ($dirins && $action == 'generatepackage' /* && $user->hasRight("modulebuilder", "run") // already checked */) {
2575 $modulelowercase = strtolower($module);
2576
2577 $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
2578
2579 // Dir for module
2580 $dir = dol_buildpath($modulelowercase, 0);
2581
2582 // Zip file to build
2583 $FILENAMEZIP = '';
2584
2585 // Load module
2586 dol_include_once($pathtofile);
2587 $class = 'mod'.$module;
2588
2589 $moduleobj = null;
2590 if (class_exists($class)) {
2591 try {
2592 $moduleobj = new $class($db);
2593 '@phan-var-force DolibarrModules $moduleobj';
2595 } catch (Exception $e) {
2596 $error++;
2597 dol_print_error($db, $e->getMessage());
2598 }
2599 } else {
2600 $error++;
2601 }
2602 if ($moduleobj === null) {
2603 $langs->load("errors");
2604 dol_print_error($db, $langs->trans("ErrorFailedToLoadModuleDescriptorForXXX", $module));
2605 exit;
2606 }
2607
2608 $arrayversion = explode('.', $moduleobj->version, 3);
2609 if (count($arrayversion)) {
2610 $FILENAMEZIP = "module_".$modulelowercase.'-'.$arrayversion[0].(empty($arrayversion[1]) ? '.0' : '.'.$arrayversion[1]).(empty($arrayversion[2]) ? '' : '.'.$arrayversion[2]).'.zip';
2611
2612 $dirofmodule = dol_buildpath($modulelowercase, 0).'/bin';
2613 $outputfilezip = $dirofmodule.'/'.$FILENAMEZIP;
2614
2615 if (!dol_is_dir($dirofmodule)) {
2616 dol_mkdir($dirofmodule);
2617 }
2618 // Note: We exclude /bin/ to not include the already generated zip
2619 $result = dol_compress_dir($dir, $outputfilezip, 'zip', '/\/bin\/|\.git|\.old|\.back|\.ssh/', $modulelowercase);
2620
2621 if ($result > 0) {
2622 setEventMessages($langs->trans("ZipFileGeneratedInto", $outputfilezip), null);
2623 } else {
2624 $error++;
2625 $langs->load("errors");
2626 setEventMessages($langs->trans("ErrorFailToGenerateFile", $outputfilezip), null, 'errors');
2627 }
2628 } else {
2629 $error++;
2630 $langs->load("errors");
2631 setEventMessages($langs->trans("ErrorCheckVersionIsDefined"), null, 'errors');
2632 }
2633}
2634
2635// Add permission
2636if ($dirins && $action == 'addright' && !empty($module) && empty($cancel) /* && $user->hasRight("modulebuilder", "run") // already checked */) {
2637 $error = 0;
2638
2639 // load class and check if right exist
2640 $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
2641 dol_include_once($pathtofile);
2642 $class = 'mod'.$module;
2643 $moduleobj = null;
2644 if (class_exists($class)) {
2645 try {
2646 $moduleobj = new $class($db);
2647 '@phan-var-force DolibarrModules $moduleobj';
2649 } catch (Exception $e) {
2650 $error++;
2651 dol_print_error($db, $e->getMessage());
2652 }
2653 }
2654
2655 // verify information entered
2656 if (!GETPOST('label', 'alpha')) {
2657 $error++;
2658 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Label")), null, 'errors');
2659 }
2660 if (!GETPOST('permissionObj', 'alpha')) {
2661 $error++;
2662 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Rights")), null, 'errors');
2663 }
2664
2665 $label = GETPOST('label', 'alpha');
2666 $objectForPerms = strtolower(GETPOST('permissionObj', 'alpha'));
2667 $crud = GETPOST('crud', 'alpha');
2668
2669 //check existing object permission
2670 $counter = 0;
2671 $permsForObject = array();
2672 if (is_object($moduleobj)) {
2673 $permissions = $moduleobj->rights;
2674 } else {
2675 $permissions = array();
2676 }
2677 $allObject = array();
2678
2679 $countPerms = count($permissions);
2680
2681 for ($i = 0; $i < $countPerms; $i++) {
2682 if ($permissions[$i][4] == $objectForPerms) {
2683 $counter++;
2684 if (count($permsForObject) < 3) {
2685 $permsForObject[] = $permissions[$i];
2686 }
2687 }
2688 $allObject[] = $permissions[$i][4];
2689 }
2690
2691 // check if label of object already exists
2692 $countPermsObj = count($permsForObject);
2693 for ($j = 0; $j < $countPermsObj; $j++) {
2694 if (in_array($crud, $permsForObject[$j])) {
2695 $error++;
2696 setEventMessages($langs->trans("ErrorExistingPermission", $langs->transnoentities($crud), $langs->transnoentities($objectForPerms)), null, 'errors');
2697 }
2698 }
2699
2700 if (!$error) {
2701 if (isModEnabled(strtolower($module))) {
2702 $result = unActivateModule(strtolower($module));
2703 dolibarr_set_const($db, "MAIN_IHM_PARAMS_REV", getDolGlobalInt('MAIN_IHM_PARAMS_REV') + 1, 'chaine', 0, '', $conf->entity);
2704 if ($result) {
2705 setEventMessages($result, null, 'errors');
2706 }
2707 setEventMessages($langs->trans('WarningModuleNeedRefresh', $langs->transnoentities($module)), null, 'warnings');
2708 }
2709
2710 $moduledescriptorfile = $dirins.'/'.strtolower($module).'/core/modules/mod'.$module.'.class.php';
2711 // Rewriting all permissions section in the descriptor file
2712 $rewrite = checkExistComment($moduledescriptorfile, 1);
2713 if ($rewrite < 0) {
2714 setEventMessages($langs->trans("WarningCommentNotFound", $langs->trans("Permissions"), "mod".$module."class.php"), null, 'warnings');
2715 } else {
2716 $reportPerms = modulebuilderSyncRights(RightsSyncCommand::forRightAddition($module, $moduledescriptorfile, $permissions, $objectForPerms, $label, $crud));
2717 if (!$reportPerms->hasConflicts()) {
2718 setEventMessages($langs->trans('PermissionAddedSuccesfuly'), null);
2719
2720 clearstatcache(true);
2721 if (function_exists('opcache_invalidate')) {
2722 opcache_reset(); // remove the include cache hell !
2723 }
2724 header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=permissions&module='.$module);
2725 exit;
2726 }
2727 }
2728 }
2729}
2730
2731
2732// Update permission
2733if ($dirins && GETPOST('action') == 'update_right' && GETPOST('modifyright') && empty($cancel) /* && $user->hasRight("modulebuilder", "run") // already checked */) {
2734 $error = 0;
2735 // load class and check if right exist
2736 $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
2737 dol_include_once($pathtofile);
2738 $class = 'mod'.$module;
2739 $moduleobj = null;
2740 if (class_exists($class)) {
2741 try {
2742 $moduleobj = new $class($db);
2743 '@phan-var-force DolibarrModules $moduleobj';
2745 } catch (Exception $e) {
2746 $error++;
2747 dol_print_error($db, $e->getMessage());
2748 }
2749 }
2750 // verify information entered
2751 if (!GETPOST('label', 'alpha')) {
2752 $error++;
2753 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Label")), null, 'errors');
2754 }
2755 if (!GETPOST('permissionObj', 'alpha')) {
2756 $error++;
2757 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Rights")), null, 'errors');
2758 }
2759
2760 $label = GETPOST('label', 'alpha');
2761 $objectForPerms = strtolower(GETPOST('permissionObj', 'alpha'));
2762 $crud = GETPOST('crud', 'alpha');
2763
2764
2765 if ($label == "Read objects of $module" && $crud != "read") {
2766 $crud = "read";
2767 // $label = "Read objects of $module";
2768 }
2769 if ($label == "Create/Update objects of $module" && $crud != "write") {
2770 $crud = "write";
2771 // $label = "Create/Update objects of $module";
2772 }
2773 if ($label == "Delete objects of $module" && $crud != "delete") {
2774 $crud = "delete";
2775 // $label = "Delete objects of $module";
2776 }
2777
2778 if (is_object($moduleobj)) {
2779 $permissions = $moduleobj->rights;
2780 } else {
2781 $permissions = [];
2782 }
2783 $key = GETPOSTINT('counter') - 1;
2784 //get permission want to delete from permissions array
2785 if (array_key_exists($key, $permissions)) {
2786 $x1 = $permissions[$key][1];
2787 $x2 = $permissions[$key][4];
2788 $x3 = $permissions[$key][5];
2789 } else {
2790 $x1 = null;
2791 $x2 = null;
2792 $x3 = null;
2793 }
2794 //check existing object permission
2795 $counter = 0;
2796 $permsForObject = array();
2797 // $permissions = $moduleobj->rights; // Already fetched above
2798 $firstRight = 0;
2799 $existRight = 0;
2800 $allObject = array();
2801
2802 $countPerms = count($permissions);
2803 for ($i = 0; $i < $countPerms; $i++) {
2804 if ($permissions[$i][4] == $objectForPerms) {
2805 $counter++;
2806 if (count($permsForObject) < 3) {
2807 $permsForObject[] = $permissions[$i];
2808 }
2809 }
2810 $allObject[] = $permissions[$i][4];
2811 }
2812
2813 if ($label != $x1 && $crud != $x3) {
2814 $countPermsObj = count($permsForObject);
2815 for ($j = 0; $j < $countPermsObj; $j++) {
2816 if (in_array($label, $permsForObject[$j])) {
2817 $error++;
2818 setEventMessages($langs->trans("ErrorExistingPermission", $langs->transnoentities($label), $langs->transnoentities($objectForPerms)), null, 'errors');
2819 }
2820 }
2821 }
2822
2823 if (!$error) {
2824 if (isModEnabled(strtolower($module))) {
2825 $result = unActivateModule(strtolower($module));
2826 dolibarr_set_const($db, "MAIN_IHM_PARAMS_REV", getDolGlobalInt('MAIN_IHM_PARAMS_REV') + 1, 'chaine', 0, '', $conf->entity);
2827 if ($result) {
2828 setEventMessages($result, null, 'errors');
2829 }
2830 setEventMessages($langs->trans('WarningModuleNeedRefresh', $langs->transnoentities($module)), null, 'warnings');
2831 }
2832
2833 $moduledescriptorfile = $dirins.'/'.strtolower($module).'/core/modules/mod'.$module.'.class.php';
2834 // rewriting all permissions after update permission needed
2835 $rewrite = checkExistComment($moduledescriptorfile, 1);
2836 if ($rewrite < 0) {
2837 setEventMessages($langs->trans("WarningCommentNotFound", $langs->trans("Permissions"), "mod".$module."class.php"), null, 'warnings');
2838 } else {
2839 $reportPerms = modulebuilderSyncRights(RightsSyncCommand::forRightUpdate($module, $moduledescriptorfile, $permissions, $key, $objectForPerms, $label, $crud));
2840 if (!$reportPerms->hasConflicts()) {
2841 setEventMessages($langs->trans('PermissionUpdatedSuccesfuly'), null);
2842 clearstatcache(true);
2843 if (function_exists('opcache_invalidate')) {
2844 opcache_reset(); // remove the include cache hell !
2845 }
2846 header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=permissions&module='.$module);
2847 exit;
2848 }
2849 }
2850 }
2851}
2852// Delete permission
2853if ($dirins && $action == 'confirm_deleteright' && !empty($module) && GETPOSTINT('permskey') /* && $user->hasRight("modulebuilder", "run") // already checked */) {
2854 $error = 0;
2855 // load class and check if right exist
2856 $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
2857 dol_include_once($pathtofile);
2858 $class = 'mod'.$module;
2859 $moduleobj = null;
2860 if (class_exists($class)) {
2861 try {
2862 $moduleobj = new $class($db);
2863 '@phan-var-force DolibarrModules $moduleobj';
2865 } catch (Exception $e) {
2866 $error++;
2867 dol_print_error($db, $e->getMessage());
2868 }
2869 }
2870
2871 $permissions = $moduleobj->rights;
2872 $key = GETPOSTINT('permskey') - 1;
2873
2874 if (!$error) {
2875 // check if module is enabled
2876 if (isModEnabled(strtolower($module))) {
2877 $result = unActivateModule(strtolower($module));
2878 dolibarr_set_const($db, "MAIN_IHM_PARAMS_REV", getDolGlobalInt('MAIN_IHM_PARAMS_REV') + 1, 'chaine', 0, '', $conf->entity);
2879 if ($result) {
2880 setEventMessages($result, null, 'errors');
2881 }
2882 setEventMessages($langs->trans('WarningModuleNeedRefresh', $langs->transnoentities($module)), null, 'warnings');
2883 header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=permissions&module='.$module);
2884 exit;
2885 }
2886
2887 // rewriting all permissions
2888 $moduledescriptorfile = $dirins.'/'.strtolower($module).'/core/modules/mod'.$module.'.class.php';
2889 $rewrite = checkExistComment($moduledescriptorfile, 1);
2890 if ($rewrite < 0) {
2891 setEventMessages($langs->trans("WarningCommentNotFound", $langs->trans("Permissions"), "mod".$module."class.php"), null, 'warnings');
2892 } else {
2893 $reportPerms = modulebuilderSyncRights(RightsSyncCommand::forRightDeletion($module, $moduledescriptorfile, $permissions, $key));
2894 if (!$reportPerms->hasConflicts()) {
2895 setEventMessages($langs->trans('PermissionDeletedSuccesfuly'), null);
2896
2897 clearstatcache(true);
2898 if (function_exists('opcache_invalidate')) {
2899 opcache_reset(); // remove the include cache hell !
2900 }
2901
2902 header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=permissions&module='.$module);
2903 exit;
2904 }
2905 }
2906 }
2907}
2908// Save file
2909if ($action == 'savefile' && empty($cancel) /* && $user->hasRight("modulebuilder", "run") // already checked */) {
2910 $relofcustom = basename($dirins);
2911
2912 if ($relofcustom) {
2913 // Check that relative path ($file) start with name 'custom'
2914 if (!preg_match('/^'.$relofcustom.'/', $file)) {
2915 $file = $relofcustom.'/'.$file;
2916 }
2917
2918 $pathoffile = dol_buildpath($file, 0);
2919 $pathoffilebackup = dol_buildpath($file.'.back', 0);
2920
2921 // Save old version
2922 if (dol_is_file($pathoffile)) {
2923 dol_copy($pathoffile, $pathoffilebackup, '0', 1);
2924 }
2925
2926 $check = 'restricthtml';
2927 $srclang = dol_mimetype($pathoffile, '', 3);
2928 if ($srclang == 'md') {
2929 $check = 'restricthtml';
2930 }
2931 if ($srclang == 'lang') {
2932 $check = 'restricthtml';
2933 }
2934 if ($srclang == 'php') {
2935 $check = 'none';
2936 }
2937
2938 $content = GETPOST('editfilecontent', $check);
2939
2940 // Save file on disk
2941 if ($content) {
2942 dol_delete_file($pathoffile);
2943 $result = file_put_contents($pathoffile, $content);
2944 if ($result) {
2945 dolChmod($pathoffile, $newmask);
2946
2947 setEventMessages($langs->trans("FileSaved"), null);
2948 } else {
2949 setEventMessages($langs->trans("ErrorFailedToSaveFile"), null, 'errors');
2950 }
2951 } else {
2952 setEventMessages($langs->trans("ContentCantBeEmpty"), null, 'errors');
2953 //$action='editfile';
2954 $error++;
2955 }
2956 }
2957}
2958
2959// Enable module
2960if ($action == 'set' && $user->admin /* && $user->hasRight("modulebuilder", "run") // already checked */) {
2961 $param = '';
2962 if ($module) {
2963 $param .= '&module='.urlencode($module);
2964 }
2965
2966 $param .= '&tab='.urlencode($tab);
2967 $param .= '&tabobj='.urlencode($tabobj);
2968
2969 $value = GETPOST('value', 'alpha');
2970 $resarray = activateModule($value, 1, 0);
2971 if (!empty($resarray['errors'])) {
2972 setEventMessages('', $resarray['errors'], 'errors');
2973 } else {
2974 //var_dump($resarray);exit;
2975 if ($resarray['nbperms'] > 0) {
2976 $tmpsql = "SELECT COUNT(rowid) as nb FROM ".MAIN_DB_PREFIX."user WHERE admin <> 1";
2977 $resqltmp = $db->query($tmpsql);
2978 if ($resqltmp) {
2979 $obj = $db->fetch_object($resqltmp);
2980 //var_dump($obj->nb);exit;
2981 if ($obj && $obj->nb > 1) {
2982 $msg = $langs->trans('ModuleEnabledAdminMustCheckRights');
2983 setEventMessages($msg, null, 'warnings');
2984 }
2985 } else {
2987 }
2988 }
2989 }
2990 header("Location: ".$_SERVER["PHP_SELF"]."?".$param);
2991 exit;
2992}
2993
2994// Disable module
2995if ($action == 'reset' && $user->admin /* && $user->hasRight("modulebuilder", "run") // already checked */) {
2996 $param = '';
2997 if ($module) {
2998 $param .= '&module='.urlencode($module);
2999 }
3000 $param .= '&tab='.urlencode($tab);
3001 $param .= '&tabobj='.urlencode($tabobj);
3002
3003 $value = GETPOST('value', 'alpha');
3004 $result = unActivateModule(strtolower($value));
3005 if ($result) {
3006 setEventMessages($result, null, 'errors');
3007 }
3008 header("Location: ".$_SERVER["PHP_SELF"]."?".$param);
3009 exit;
3010}
3011
3012// Delete menu
3013if ($dirins && $action == 'confirm_deletemenu' && GETPOSTINT('menukey') /* && $user->hasRight("modulebuilder", "run") // already checked */) {
3014 // check if module is enabled
3015 if (isModEnabled(strtolower($module))) {
3016 $result = unActivateModule(strtolower($module));
3017 dolibarr_set_const($db, "MAIN_IHM_PARAMS_REV", getDolGlobalInt('MAIN_IHM_PARAMS_REV') + 1, 'chaine', 0, '', $conf->entity);
3018 if ($result) {
3019 setEventMessages($result, null, 'errors');
3020 }
3021 setEventMessages($langs->trans('WarningModuleNeedRefresh', $langs->transnoentities($module)), null, 'warnings');
3022 header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=menus&module='.$module);
3023 exit;
3024 }
3025 // load class and check if menu exist
3026 $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
3027 dol_include_once($pathtofile);
3028 $class = 'mod'.$module;
3029 $moduleobj = null;
3030 if (class_exists($class)) {
3031 try {
3032 $moduleobj = new $class($db);
3033 '@phan-var-force DolibarrModules $moduleobj';
3035 } catch (Exception $e) {
3036 $error++;
3037 dol_print_error($db, $e->getMessage());
3038 }
3039 }
3040 // get all objects and convert value to lower case for compare
3041 $dir = $listofmodules[strtolower($module)]['moduledescriptorrootpath'];
3042 $destdir = $dir.'/'.strtolower($module);
3043 $objects = dolGetListOfObjectClasses($destdir);
3044 $result = array_map('strtolower', $objects);
3045
3046 $menus = $moduleobj->menu;
3047 $key = GETPOSTINT('menukey');
3048 $moduledescriptorfile = $dirins.'/'.strtolower($module).'/core/modules/mod'.$module.'.class.php';
3049
3050 $checkcomment = checkExistComment($moduledescriptorfile, 0);
3051 if ($checkcomment < 0) {
3052 setEventMessages($langs->trans("WarningCommentNotFound", $langs->trans("Menus"), "mod".$module."class.php"), null, 'warnings');
3053 } else {
3054 if ($menus[$key]['fk_menu'] === 'fk_mainmenu='.strtolower($module)) {
3055 if (in_array(strtolower($menus[$key]['leftmenu']), $result)) {
3056 reWriteAllMenus($moduledescriptorfile, $menus, $menus[$key]['leftmenu'], $key, -1);
3057 } else {
3058 reWriteAllMenus($moduledescriptorfile, $menus, null, $key, 0);
3059 }
3060 } else {
3061 reWriteAllMenus($moduledescriptorfile, $menus, null, $key, 0);
3062 }
3063
3064 clearstatcache(true);
3065 if (function_exists('opcache_invalidate')) {
3066 opcache_reset(); // remove the include cache hell !
3067 }
3068
3069 setEventMessages($langs->trans('MenuDeletedSuccessfuly'), null);
3070 header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=menus&module='.$module);
3071 exit;
3072 }
3073}
3074
3075// Add menu in module without initial object
3076if ($dirins && $action == 'addmenu' && empty($cancel) /* && $user->hasRight("modulebuilder", "run") // already checked */) {
3077 // check if module is enabled
3078 if (isModEnabled(strtolower($module))) {
3079 $result = unActivateModule(strtolower($module));
3080 dolibarr_set_const($db, "MAIN_IHM_PARAMS_REV", getDolGlobalInt('MAIN_IHM_PARAMS_REV') + 1, 'chaine', 0, '', $conf->entity);
3081 if ($result) {
3082 setEventMessages($result, null, 'errors');
3083 }
3084 setEventMessages($langs->trans('WarningModuleNeedRefresh', $langs->transnoentities($module)), null, 'warnings');
3085 header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=menus&module='.$module);
3086 exit;
3087 }
3088 $error = 0;
3089
3090 // load class and check if right exist
3091 $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
3092 dol_include_once($pathtofile);
3093 $class = 'mod'.$module;
3094 $moduleobj = null;
3095 if (class_exists($class)) {
3096 try {
3097 $moduleobj = new $class($db);
3098 '@phan-var-force DolibarrModules $moduleobj';
3100 } catch (Exception $e) {
3101 $error++;
3102 dol_print_error($db, $e->getMessage());
3103 }
3104 }
3105 // get all menus
3106 $menus = $moduleobj->menu;
3107
3108 //verify fields required
3109 if (!GETPOST('type', 'alpha')) {
3110 $error++;
3111 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Type")), null, 'errors');
3112 }
3113 if (!GETPOST('titre', 'alpha')) {
3114 $error++;
3115 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Title")), null, 'errors');
3116 }
3117 if (!GETPOST('user', 'alpha')) {
3118 $error++;
3119 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("DetailUser")), null, 'errors');
3120 }
3121 if (!GETPOST('url', 'alpha')) {
3122 $error++;
3123 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Url")), null, 'errors');
3124 }
3125 if (!empty(GETPOST('target'))) {
3126 $targets = array('_blank','_self','_parent','_top','');
3127 if (!in_array(GETPOST('target'), $targets)) {
3128 $error++;
3129 setEventMessages($langs->trans("ErrorFieldValue", $langs->transnoentities("target")), null, 'errors');
3130 }
3131 }
3132
3133
3134 // check if title or url already exist in menus
3135
3136 foreach ($menus as $menu) {
3137 if (!empty(GETPOST('url')) && GETPOST('url') == $menu['url']) {
3138 $error++;
3139 setEventMessages($langs->trans("ErrorFieldExist", $langs->transnoentities("url")), null, 'errors');
3140 break;
3141 }
3142 if (strtolower(GETPOST('titre')) == strtolower($menu['titre'])) {
3143 $error++;
3144 setEventMessages($langs->trans("ErrorFieldExist", $langs->transnoentities("titre")), null, 'errors');
3145 break;
3146 }
3147 }
3148
3149 if (GETPOST('type', 'alpha') == 'left' && !empty(GETPOST('lefmenu', 'alpha'))) {
3150 if (!str_contains(GETPOST('leftmenu'), strtolower($module))) {
3151 $error++;
3152 setEventMessages($langs->trans("WarningFieldsMustContains", $langs->transnoentities("LeftmenuId")), null, 'errors');
3153 }
3154 }
3155 $dirins = $listofmodules[strtolower($module)]['moduledescriptorrootpath'];
3156 $destdir = $dirins.'/'.strtolower($module);
3157 $objects = dolGetListOfObjectClasses($destdir);
3158
3159 if (GETPOST('type', 'alpha') == 'left') {
3160 if (empty(GETPOST('leftmenu')) && count($objects) > 0) {
3161 $error++;
3162 setEventMessages($langs->trans("ErrorCoherenceMenu", $langs->transnoentities("LeftmenuId"), $langs->transnoentities("type")), null, 'errors');
3163 }
3164 }
3165 if (GETPOST('type', 'alpha') == 'top') {
3166 $error++;
3167 setEventMessages($langs->trans("ErrorTypeMenu", $langs->transnoentities("type")), null, 'errors');
3168 }
3169
3170 $moduledescriptorfile = $dirins.'/'.strtolower($module).'/core/modules/mod'.$module.'.class.php';
3171 if (!$error) {
3172 //stock forms in array
3173 $menuToAdd = array(
3174 'fk_menu' => GETPOST('fk_menu', 'alpha'),
3175 'type' => GETPOST('type', 'alpha'),
3176 'titre' => ucfirst(GETPOST('titre', 'alpha')),
3177 'prefix' => '',
3178 'mainmenu' => GETPOST('mainmenu', 'alpha'),
3179 'leftmenu' => GETPOST('leftmenu', 'alpha'),
3180 'url' => GETPOST('url', 'alpha'),
3181 'langs' => strtolower($module)."@".strtolower($module),
3182 'position' => '',
3183 'enabled' => GETPOST('enabled', 'alpha'),
3184 'perms' => '$user->hasRight("'.strtolower($module).'", "'.GETPOST('objects', 'alpha').'", "'.GETPOST('perms', 'alpha').'")',
3185 'target' => GETPOST('target', 'alpha'),
3186 'user' => GETPOSTINT('user'),
3187 );
3188
3189 if (GETPOST('type') == 'left') {
3190 unset($menuToAdd['prefix']);
3191 if (empty(GETPOST('fk_menu'))) {
3192 $menuToAdd['fk_menu'] = 'fk_mainmenu='.GETPOST('mainmenu', 'alpha');
3193 } else {
3194 $menuToAdd['fk_menu'] = 'fk_mainmenu='.GETPOST('mainmenu', 'alpha').',fk_leftmenu='.GETPOST('fk_menu');
3195 }
3196 }
3197 if (GETPOST('enabled') == '1') {
3198 $menuToAdd['enabled'] = 'isModEnabled("'.strtolower($module).'")';
3199 } else {
3200 $menuToAdd['enabled'] = "0";
3201 }
3202 if (empty(GETPOST('objects'))) {
3203 $menuToAdd['perms'] = '1';
3204 }
3205
3206 $checkcomment = checkExistComment($moduledescriptorfile, 0);
3207 if ($checkcomment < 0) {
3208 setEventMessages($langs->trans("WarningCommentNotFound", $langs->trans("Menus"), "mod".$module."class.php"), null, 'warnings');
3209 } else {
3210 // Write all menus
3211 $result = reWriteAllMenus($moduledescriptorfile, $menus, $menuToAdd, null, 1);
3212
3213 clearstatcache(true);
3214 if (function_exists('opcache_invalidate')) {
3215 opcache_reset();
3216 }
3217 /*if ($result < 0) {
3218 setEventMessages($langs->trans('ErrorMenuExistValue'), null, 'errors');
3219 header("Location: ".$_SERVER["PHP_SELF"].'?action=editmenu&token='.newToken().'&menukey='.urlencode($key+1).'&tab='.urlencode($tab).'&module='.urlencode($module).'&tabobj='.($key+1));
3220 exit;
3221 }*/
3222
3223 header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=menus&module='.$module);
3224 setEventMessages($langs->trans('MenuAddedSuccesfuly'), null);
3225 exit;
3226 }
3227 }
3228}
3229
3230// Modify a menu entry
3231if ($dirins && $action == "update_menu" && GETPOSTINT('menukey') && GETPOST('tabobj') /* && $user->hasRight("modulebuilder", "run") // already checked */) {
3232 $objectname = GETPOST('tabobj');
3233 $dirins = $listofmodules[strtolower($module)]['moduledescriptorrootpath'];
3234 $destdir = $dirins.'/'.strtolower($module);
3235 $objects = dolGetListOfObjectClasses($destdir);
3236
3237 if (empty($cancel)) {
3238 if (isModEnabled(strtolower($module))) {
3239 $result = unActivateModule(strtolower($module));
3240 dolibarr_set_const($db, "MAIN_IHM_PARAMS_REV", getDolGlobalInt('MAIN_IHM_PARAMS_REV') + 1, 'chaine', 0, '', $conf->entity);
3241 if ($result) {
3242 setEventMessages($result, null, 'errors');
3243 }
3244 setEventMessages($langs->trans('WarningModuleNeedRefresh', $langs->transnoentities($module)), null, 'warnings');
3245 header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=menus&module='.$module);
3246 exit;
3247 }
3248 $error = 0;
3249 // for loading class and the menu wants to modify
3250 $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
3251 dol_include_once($pathtofile);
3252 $class = 'mod'.$module;
3253 $moduleobj = null;
3254 if (class_exists($class)) {
3255 try {
3256 $moduleobj = new $class($db);
3257 '@phan-var-force DolibarrModules $moduleobj';
3259 } catch (Exception $e) {
3260 $error++;
3261 dol_print_error($db, $e->getMessage());
3262 }
3263 }
3264 $menus = $moduleobj->menu;
3265 $key = GETPOSTINT('menukey') - 1;
3266
3267 $moduledescriptorfile = $dirins.'/'.strtolower($module).'/core/modules/mod'.$module.'.class.php';
3268 //stock forms in array
3269 $menuModify = array(
3270 'fk_menu' => GETPOST('fk_menu', 'alpha'),
3271 'type' => GETPOST('type', 'alpha'),
3272 'titre' => ucfirst(GETPOST('titre', 'alpha')),
3273 'prefix' => '',
3274 'mainmenu' => GETPOST('mainmenu', 'alpha'),
3275 'leftmenu' => $menus[$key]['leftmenu'],
3276 'url' => GETPOST('url', 'alpha'),
3277 'langs' => strtolower($module)."@".strtolower($module),
3278 'position' => '',
3279 'enabled' => GETPOST('enabled', 'alpha'),
3280 'perms' => GETPOST('perms', 'alpha'),
3281 'target' => GETPOST('target', 'alpha'),
3282 'user' => GETPOSTINT('user'),
3283 );
3284 if (!empty(GETPOST('fk_menu')) && GETPOST('fk_menu') != $menus[$key]['fk_menu']) {
3285 $menuModify['fk_menu'] = 'fk_mainmenu='.GETPOST('mainmenu').',fk_leftmenu='.GETPOST('fk_menu');
3286 } elseif (GETPOST('fk_menu') == $menus[$key]['fk_menu']) {
3287 $menuModify['fk_menu'] = $menus[$key]['fk_menu'];
3288 } else {
3289 $menuModify['fk_menu'] = 'fk_mainmenu='.GETPOST('mainmenu');
3290 }
3291 if ($menuModify['enabled'] === '') {
3292 $menuModify['enabled'] = '1';
3293 }
3294 if ($menuModify['perms'] === '') {
3295 $menuModify['perms'] = '1';
3296 }
3297
3298 if (GETPOST('type', 'alpha') == 'top') {
3299 $error++;
3300 setEventMessages($langs->trans("ErrorTypeMenu", $langs->transnoentities("type")), null, 'errors');
3301 }
3302
3303 if (!$error) {
3304 //update menu
3305 $checkComment = checkExistComment($moduledescriptorfile, 0);
3306
3307 if ($checkComment < 0) {
3308 setEventMessages($langs->trans("WarningCommentNotFound", $langs->trans("Menus"), "mod".$module."class.php"), null, 'warnings');
3309 } else {
3310 // Write all menus
3311 $result = reWriteAllMenus($moduledescriptorfile, $menus, $menuModify, $key, 2);
3312
3313 clearstatcache(true);
3314 if (function_exists('opcache_invalidate')) {
3315 opcache_reset();
3316 }
3317
3318 if ($result < 0) {
3319 setEventMessages($langs->trans('ErrorMenuExistValue'), null, 'errors');
3320 //var_dump($_SESSION);exit;
3321 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));
3322 exit;
3323 }
3324
3325 setEventMessages($langs->trans('MenuUpdatedSuccessfuly'), null);
3326 header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=menus&module='.$module);
3327 exit;
3328 }
3329 }
3330 } else {
3331 $_POST['type'] = ''; // TODO Use a var here and later
3332 $_POST['titre'] = '';
3333 $_POST['fk_menu'] = '';
3334 $_POST['leftmenu'] = '';
3335 $_POST['url'] = '';
3336 }
3337}
3338
3339// update properties description of module
3340if ($dirins && $action == "update_props_module" && !empty(GETPOST('keydescription', 'alpha')) && empty($cancel) /* && $user->hasRight("modulebuilder", "run") // already checked */) {
3341 if (isModEnabled(strtolower($module))) {
3342 $result = unActivateModule(strtolower($module));
3343 dolibarr_set_const($db, "MAIN_IHM_PARAMS_REV", getDolGlobalInt('MAIN_IHM_PARAMS_REV') + 1, 'chaine', 0, '', $conf->entity);
3344 if ($result) {
3345 setEventMessages($result, null, 'errors');
3346 }
3347 setEventMessages($langs->trans('WarningModuleNeedRefresh', $langs->transnoentities($module)), null, 'warnings');
3348 header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=menus&module='.$module);
3349 exit;
3350 }
3351 $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
3352 $moduledescriptorfile = $dirins.'/'.strtolower($module).'/core/modules/mod'.$module.'.class.php';
3353 $modulelogfile = $dirins.'/'.strtolower($module).'/ChangeLog.md';
3354
3355 dol_include_once($pathtofile);
3356
3357 $class = 'mod'.$module;
3358 $moduleobj = null;
3359 if (class_exists($class)) {
3360 try {
3361 $moduleobj = new $class($db);
3362 '@phan-var-force DolibarrModules $moduleobj';
3364 } catch (Exception $e) {
3365 $error++;
3366 dol_print_error($db, $e->getMessage());
3367 }
3368 }
3369
3370 $keydescription = GETPOST('keydescription', 'alpha');
3371 switch ($keydescription) {
3372 case 'desc':
3373 $propertyToUpdate = 'description';
3374 break;
3375 case 'version':
3376 case 'family':
3377 case 'picto':
3378 case 'editor_name':
3379 case 'editor_url':
3380 $propertyToUpdate = $keydescription;
3381 break;
3382 default:
3383 $error = GETPOST('keydescription');
3384 break;
3385 }
3386
3387 if (isset($propertyToUpdate) && !empty(GETPOST('propsmodule'))) {
3388 $newValue = GETPOST('propsmodule');
3389 $patternToFindLine = '^\s*\$this->'.$propertyToUpdate.'\s*='; // Must be a regex string
3390 $newLine = "\t\t\$this->$propertyToUpdate = '$newValue';\n"; // Must a real string
3391
3392 $fileLines = file($moduledescriptorfile); // Get each line of file into an array
3393 $error = 0;
3394 $changedone = 0;
3395 foreach ($fileLines as &$line) {
3396 if (preg_match('/'.$patternToFindLine.'/', $line)) {
3397 $result = dolReplaceInFile($moduledescriptorfile, array($line => $newLine));
3398 if ($result > 0) {
3399 $changedone++;
3400 } elseif ($result <= -1) {
3401 $langs->load("errors");
3402 setEventMessages($langs->trans('ErrorFailToEditFile', $moduledescriptorfile), null, 'warnings');
3403 break;
3404 }
3405 break;
3406 }
3407 }
3408
3409 // To complete also the ChangeLogif we update the version
3410 if ($changedone && $propertyToUpdate === 'version') {
3411 dolReplaceInFile($modulelogfile, array("## ".$moduleobj->$propertyToUpdate => $newValue));
3412 }
3413
3414 clearstatcache(true);
3415 if (function_exists('opcache_invalidate')) {
3416 opcache_reset();
3417 }
3418 if ($changedone) {
3419 setEventMessages($langs->trans('PropertyModuleUpdated', $propertyToUpdate), null);
3420 } else {
3421 setEventMessages($langs->trans('NothingProcessed'), null, 'warnings');
3422 }
3423
3424 header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=description&module='.$module);
3425 exit;
3426 }
3427}
3428
3429
3430/*
3431 * View
3432 */
3433
3434$form = new Form($db);
3435$formadmin = new FormAdmin($db);
3436
3437// Set dir where external modules are installed
3438if (!dol_is_dir($dirins)) {
3439 dol_mkdir($dirins);
3440}
3441$dirins_ok = (dol_is_dir($dirins));
3442
3443$help_url = '';
3444$morejs = array(
3445 '/includes/ace/src/ace.js',
3446 '/includes/ace/src/ext-statusbar.js',
3447 '/includes/ace/src/ext-language_tools.js',
3448 //'/includes/ace/src/ext-chromevox.js'
3449);
3450$morecss = array();
3451
3452llxHeader('', $langs->trans("ModuleBuilder"), $help_url, '', 0, 0, $morejs, $morecss, '', 'classforhorizontalscrolloftabs');
3453
3454
3455$text = $langs->trans("ModuleBuilder");
3456
3457$morehtmlright = '<a href="'.DOL_URL_ROOT.'/admin/tools/ui/index.php" target="_blank" rel="noopener">'.img_picto('', 'book', 'class="pictofixedwidth"').$langs->trans("UxComponentsDoc").'</a>';
3458
3459print load_fiche_titre($text, $morehtmlright, 'title_setup');
3460
3461print '<div class="info hideonsmartphone">';
3462print $langs->trans("ModuleBuilderDesc", 'https://wiki.dolibarr.org/index.php/Module_development').'</span>';
3463print '</div>';
3464
3465
3466$message = '';
3467if (!$dirins) {
3468 $message = info_admin($langs->trans("ConfFileMustContainCustom", DOL_DOCUMENT_ROOT.'/custom', DOL_DOCUMENT_ROOT));
3469 $allowfromweb = -1;
3470} else {
3471 if ($dirins_ok) {
3472 if (!is_writable(dol_osencode($dirins))) {
3473 $langs->load("errors");
3474 $message = info_admin($langs->trans("ErrorFailedToWriteInDir", $dirins));
3475 $allowfromweb = 0;
3476 }
3477 } else {
3478 $message = info_admin($langs->trans("NotExistsDirect", $dirins).$langs->trans("InfDirAlt").$langs->trans("InfDirExample"));
3479 $allowfromweb = 0;
3480 }
3481}
3482if ($message) {
3483 print $message;
3484}
3485
3486//print $langs->trans("ModuleBuilderDesc3", count($listofmodules), $FILEFLAG).'<br>';
3487$infomodulesfound = '<div style="padding: 12px 9px 12px">'.$form->textwithpicto('', $langs->trans("ModuleBuilderDesc3", count($listofmodules)).'<br><br>'.$langs->trans("ModuleBuilderDesc4", $FILEFLAG).'<br>'.$textforlistofdirs).'</div>';
3488
3489
3490
3491$dolibarrdataroot = preg_replace('/([\\/]+)$/i', '', DOL_DATA_ROOT);
3492$allowonlineinstall = true;
3493if (dol_is_file($dolibarrdataroot.'/installmodules.lock')) {
3494 $allowonlineinstall = false;
3495}
3496if (empty($allowonlineinstall)) {
3497 if (getDolGlobalString('MAIN_MESSAGE_INSTALL_MODULES_DISABLED_CONTACT_US')) {
3498 // Show clean message
3499 $message = info_admin($langs->trans('InstallModuleFromWebHasBeenDisabledContactUs'));
3500 } else {
3501 // Show technical message
3502 $message = info_admin($langs->trans("InstallModuleFromWebHasBeenDisabledByFile", $dolibarrdataroot.'/installmodules.lock'), 0, 0, '1', 'warning');
3503 }
3504
3505 print $message;
3506
3507 llxFooter();
3508 exit(0);
3509}
3510
3511
3512// Load module descriptor
3513$error = 0;
3515
3516
3517if (!empty($module) && $module != 'initmodule' && $module != 'deletemodule') {
3518 $modulelowercase = strtolower($module);
3519 $loadclasserrormessage = '';
3520
3521 $class = null;
3522 // Load module
3523 try {
3524 $fullpathdirtodescriptor = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
3525
3526 //throw(new Exception());
3527 dol_include_once($fullpathdirtodescriptor);
3528
3529 $class = 'mod'.$module;
3530 } catch (Throwable $e) { // This is called in PHP 7 only (includes Error and Exception)
3531 $loadclasserrormessage = $e->getMessage()."<br>\n";
3532 $loadclasserrormessage .= 'File: '.$e->getFile()."<br>\n";
3533 $loadclasserrormessage .= 'Line: '.$e->getLine()."<br>\n";
3534 }
3535
3536 $moduleobj = null;
3537 if (class_exists($class)) {
3538 try {
3539 $moduleobj = new $class($db);
3540 '@phan-var-force DolibarrModules $moduleobj';
3542 } catch (Exception $e) {
3543 $error++;
3544 print $e->getMessage();
3545 }
3546 } else {
3547 if (empty($forceddirread)) {
3548 $error++;
3549 }
3550 $langs->load("errors");
3551 print '<!-- ErrorFailedToLoadModuleDescriptorForXXX -->';
3552 print img_warning('').' '.$langs->trans("ErrorFailedToLoadModuleDescriptorForXXX", $module).'<br>';
3553 print $loadclasserrormessage;
3554 print '<br>';
3555 }
3556}
3557
3558
3559// Tabs for all modules
3560$head = array();
3561$h = 0;
3562
3563$head[$h][0] = $_SERVER["PHP_SELF"].'?module=initmodule';
3564$head[$h][1] = '<span class="valignmiddle text-plus-circle">'.$langs->trans("NewModule").'</span><span class="fa fa-plus-circle valignmiddle paddingleft"></span>';
3565$head[$h][2] = 'initmodule';
3566$h++;
3567
3568$linktoenabledisable = '';
3569
3570if (/* is_array($listofmodules) && */ count($listofmodules) > 0) {
3571 // Define $linktoenabledisable
3572 $modulelowercase = strtolower($module);
3573
3574 $param = '';
3575 if ($module) {
3576 $param .= '&module='.urlencode($module);
3577 }
3578
3579 $param .= '&tab='.urlencode($tab);
3580 $param .= '&tabobj='.urlencode($tabobj);
3581
3582 $urltomodulesetup = '<a href="'.DOL_URL_ROOT.'/admin/modules.php?search_keyword='.urlencode($module).'">'.$langs->trans('Home').'-'.$langs->trans("Setup").'-'.$langs->trans("Modules").'</a>';
3583
3584 // Define $linktoenabledisable to show after module title
3585 if (isModEnabled($modulelowercase)) { // If module is already activated
3586 $linktoenabledisable .= '<a class="reposition asetresetmodule valignmiddle" href="'.$_SERVER["PHP_SELF"].'?id='.$moduleobj->numero.'&action=reset&token='.newToken().'&value=mod'.$module.$param.'">';
3587 $linktoenabledisable .= img_picto($langs->trans("Warning").' : '.$langs->trans("ModuleIsLive"), 'switch_on', '', 0, 0, 0, '', 'warning valignmiddle', 1);
3588 $linktoenabledisable .= '</a>';
3589
3590 //$linktoenabledisable .= $form->textwithpicto('', $langs->trans("Warning").' : '.$langs->trans("ModuleIsLive"), -1, 'warning');
3591
3592 $objMod = $moduleobj;
3593 $backtourlparam = '';
3594 $backtourlparam .= ($backtourlparam ? '&' : '?').'module='.$module; // No urlencode here, done later
3595 $backtourlparam .= ($backtourlparam ? '&' : '?').'tab='.$tab; // No urlencode here, done later
3596 $backtourl = $_SERVER["PHP_SELF"].$backtourlparam;
3597
3598 $regs = array();
3599 if (is_array($objMod->config_page_url)) {
3600 $i = 0;
3601 foreach ($objMod->config_page_url as $page) {
3602 $urlpage = $page;
3603 if ($i++) {
3604 $linktoenabledisable .= ' <a class="valignmiddle" href="'.$urlpage.'" title="'.$langs->trans($page).'">'.img_picto(ucfirst($page), "setup").'</a>';
3605 // print '<a href="'.$page.'">'.ucfirst($page).'</a>&nbsp;';
3606 } else {
3607 if (preg_match('/^([^@]+)@([^@]+)$/i', $urlpage, $regs)) {
3608 $urltouse = dol_buildpath('/'.$regs[2].'/admin/'.$regs[1], 1);
3609 $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>';
3610 } else {
3611 // Case standard admin page (not a page provided by the
3612 // module but a page provided by dolibarr)
3613 $urltouse = DOL_URL_ROOT.'/admin/'.$urlpage;
3614 $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>';
3615 }
3616 }
3617 }
3618 } elseif (preg_match('/^([^@]+)@([^@]+)$/i', $objMod->config_page_url, $regs)) {
3619 $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>';
3620 }
3621 } else {
3622 if (is_object($moduleobj)) {
3623 $linktoenabledisable .= '<a class="reposition asetresetmodule valignmiddle" href="'.$_SERVER["PHP_SELF"].'?id='.$moduleobj->numero.'&action=set&token='.newToken().'&value=mod'.$module.$param.'">';
3624 $linktoenabledisable .= img_picto($langs->trans("ModuleIsNotActive", $urltomodulesetup), 'switch_off', 'style="padding-right: 8px"', 0, 0, 0, '', 'classfortooltip valignmiddle', 1);
3625 $linktoenabledisable .= "</a>\n";
3626 }
3627 }
3628
3629 // Loop to show tab of each module
3630 foreach ($listofmodules as $tmpmodule => $tmpmodulearray) {
3631 $head[$h][0] = $_SERVER["PHP_SELF"].'?module='.$tmpmodulearray['modulenamewithcase'].($forceddirread ? '@'.$dirread : '');
3632 $head[$h][1] = $tmpmodulearray['modulenamewithcase'];
3633 $head[$h][2] = $tmpmodulearray['modulenamewithcase'];
3634
3635 if ($tmpmodulearray['modulenamewithcase'] == $module) {
3636 $head[$h][4] = '<span class="inline-block valignmiddle">'.$linktoenabledisable.'</span>';
3637 }
3638
3639 $h++;
3640 }
3641}
3642
3643$head[$h][0] = $_SERVER["PHP_SELF"].'?module=deletemodule';
3644$head[$h][1] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("DangerZone");
3645$head[$h][2] = 'deletemodule';
3646$h++;
3647
3648
3649print dol_get_fiche_head($head, $module, '', -1, '', 0, $infomodulesfound, '', 8); // Modules
3650
3651if ($module == 'initmodule') {
3652 // New module
3653 print '<!-- section init module -->'."\n";
3654 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
3655 print '<input type="hidden" name="token" value="'.newToken().'">';
3656 print '<input type="hidden" name="action" value="initmodule">';
3657 print '<input type="hidden" name="module" value="initmodule">';
3658
3659 //print '<span class="opacitymedium">'.$langs->trans("ModuleBuilderDesc2", 'conf/conf.php', $newdircustom).'</span><br>';
3660 print '<br>';
3661
3662 print '<div class="tagtable table-border">';
3663
3664 print '<div class="tagtr"><div class="tagtd paddingright">';
3665 print '<span class="opacitymedium">'.$langs->trans("IdModule").'</span>';
3666 print '</div><div class="tagtd">';
3667 print '<input type="number" min="100000" name="idmodule" class="width100" value="500000">';
3668 print '<span class="opacitymedium small">';
3669 print ' &nbsp; &nbsp; ';
3670 print dolButtonToOpenUrlInDialogPopup('popup_modules_id', $langs->transnoentitiesnoconv("SeeIDsInUse"), $langs->transnoentitiesnoconv("SeeIDsInUse"), '/admin/system/modules.php?mainmenu=home&leftmenu=admintools_info&hidetitle=1', '', '');
3671 print ' - ';
3672 print '<a href="https://wiki.dolibarr.org/index.php/List_of_modules_id" target="_blank" rel="noopener noreferrer external">'.$langs->trans("SeeReservedIDsRangeHere").'</a>';
3673 print '</span>';
3674 print '</div></div>';
3675
3676 print '<div class="tagtr"><div class="tagtd paddingright">';
3677 print '<span class="opacitymedium fieldrequired">'.$langs->trans("ModuleName").'</span>';
3678 print '</div><div class="tagtd">';
3679 print '<input type="text" name="modulename" value="'.dol_escape_htmltag($modulename).'" autofocus>';
3680 print ' '.$form->textwithpicto('', $langs->trans("EnterNameOfModuleDesc"));
3681 print '</div></div>';
3682
3683 print '<div class="tagtr"><div class="tagtd paddingright">';
3684 print '<span class="opacitymedium">'.$langs->trans("Description").'</span>';
3685 print '</div><div class="tagtd">';
3686 print '<input type="text" name="description" value="" class="minwidth500"><br>';
3687 print '</div></div>';
3688
3689 print '<div class="tagtr"><div class="tagtd paddingright">';
3690 print '<span class="opacitymedium">'.$langs->trans("Version").'</span>';
3691 print '</div><div class="tagtd">';
3692 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")).'">';
3693 print '</div></div>';
3694
3695 print '<div class="tagtr"><div class="tagtd paddingright">';
3696 print '<span class="opacitymedium">'.$langs->trans("Family").'</span>';
3697 print '</div><div class="tagtd">';
3698 print '<select name="family" id="family" class="minwidth400">';
3699 $arrayoffamilies = array(
3700 'hr' => "ModuleFamilyHr",
3701 'crm' => "ModuleFamilyCrm",
3702 'srm' => "ModuleFamilySrm",
3703 'financial' => 'ModuleFamilyFinancial',
3704 'products' => 'ModuleFamilyProducts',
3705 'projects' => 'ModuleFamilyProjects',
3706 'ecm' => 'ModuleFamilyECM',
3707 'technic' => 'ModuleFamilyTechnic',
3708 'portal' => 'ModuleFamilyPortal',
3709 'interface' => 'ModuleFamilyInterface',
3710 'base' => 'ModuleFamilyBase',
3711 'other' => 'ModuleFamilyOther'
3712 );
3713 foreach ($arrayoffamilies as $key => $value) {
3714 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>';
3715 }
3716 print '</select>';
3717 print ajax_combobox("family");
3718 print '</div></div>';
3719
3720 print '<div class="tagtr"><div class="tagtd paddingright">';
3721 print '<span class="opacitymedium">'.$langs->trans("Picto").'</span>';
3722 print '</div><div class="tagtd">';
3723 print '<input type="text" name="idpicto" value="'.(GETPOSTISSET('idpicto') ? GETPOST('idpicto') : getDolGlobalString('MODULEBUILDER_DEFAULTPICTO', 'fa-file')).'" placeholder="'.dol_escape_htmltag($langs->trans("Picto")).'">';
3724 print $form->textwithpicto('', $langs->trans("Example").': fa-file, fa-globe, ... any font awesome code.<br>Advanced syntax is fa-fakey[_faprefix[_facolor[_fasize]]]');
3725
3726 print ' &nbsp; &nbsp; ';
3727
3728 print '<span class="opacitymedium small">';
3729 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', '', '');
3730 print '</span>';
3731
3732 print '</div></div>';
3733
3734 print '<div class="tagtr"><div class="tagtd paddingright">';
3735 print '<span class="opacitymedium">'.$langs->trans("EditorName").'</span>';
3736 print '</div><div class="tagtd">';
3737 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>';
3738 print '</div></div>';
3739
3740 print '<div class="tagtr"><div class="tagtd paddingright">';
3741 print '<span class="opacitymedium">'.$langs->trans("EditorUrl").'</span>';
3742 print '</div><div class="tagtd">';
3743 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>';
3744 print '</div></div>';
3745
3746 print '</div>'; // End div tagtable
3747
3748 print '<br><center>';
3749 print '<input type="submit" class="button" name="create" value="'.dol_escape_htmltag($langs->trans("Create")).'"'.($dirins ? '' : ' disabled="disabled"').'>';
3750 print '</center>';
3751 print '</form>';
3752} elseif ($module == 'deletemodule') {
3753 print '<!-- Form to init a module -->'."\n";
3754 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST" name="delete">';
3755 print '<input type="hidden" name="token" value="'.newToken().'">';
3756 print '<input type="hidden" name="action" value="confirm_deletemodule">';
3757 print '<input type="hidden" name="module" value="deletemodule">';
3758
3759 print $langs->trans("EnterNameOfModuleToDeleteDesc").'<br><br>';
3760
3761 print '<input type="text" name="module" placeholder="'.dol_escape_htmltag($langs->trans("ModuleKey")).'" value="" autofocus>';
3762 print '<input type="submit" class="button smallpaddingimp" value="'.$langs->trans("Delete").'"'.($dirins ? '' : ' disabled="disabled"').'>';
3763 print '</form>';
3764} elseif (!empty($module) && $modulelowercase !== null) {
3765 // Tabs for module
3766 if (!$error) {
3767 $dirread = $listofmodules[strtolower($module)]['moduledescriptorrootpath'];
3768 $destdir = $dirread.'/'.strtolower($module);
3769 $objects = dolGetListOfObjectClasses($destdir);
3770 $diroflang = dol_buildpath($modulelowercase, 0)."/langs";
3771 $countLangs = countItemsInDirectory($diroflang, 2);
3772 $countDictionaries = (!empty($moduleobj->dictionaries) ? count($moduleobj->dictionaries['tabname']) : 0);
3773 $countRights = count($moduleobj->rights);
3774 $countMenus = count($moduleobj->menu);
3775 $countTriggers = countItemsInDirectory(dol_buildpath($modulelowercase, 0)."/core/triggers");
3776 $countWidgets = countItemsInDirectory(dol_buildpath($modulelowercase, 0)."/core/boxes");
3777 $countEmailingSelectors = countItemsInDirectory(dol_buildpath($modulelowercase, 0)."/core/modules/mailings");
3778 $countCss = countItemsInDirectory(dol_buildpath($modulelowercase, 0)."/css");
3779 $countJs = countItemsInDirectory(dol_buildpath($modulelowercase, 0)."/js");
3780 $countCLI = countItemsInDirectory(dol_buildpath($modulelowercase, 0)."/scripts");
3781 $hasDoc = countItemsInDirectory(dol_buildpath($modulelowercase, 0)."/doc");
3782 //var_dump($moduleobj->dictionaries);exit;
3783 $head2 = array();
3784 $h = 0;
3785
3786 $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=description&module='.$module.($forceddirread ? '@'.$dirread : '');
3787 $head2[$h][1] = $langs->trans("Description");
3788 $head2[$h][2] = 'description';
3789 $h++;
3790
3791 $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=objects&module='.$module.($forceddirread ? '@'.$dirread : '');
3792 $head2[$h][1] = ((!is_array($objects) || count($objects) <= 0) ? $langs->trans("Objects") : $langs->trans("Objects").'<span class="marginleftonlyshort badge">'.count($objects)."</span>");
3793 $head2[$h][2] = 'objects';
3794 $h++;
3795
3796 $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=languages&module='.$module.($forceddirread ? '@'.$dirread : '');
3797 $head2[$h][1] = ($countLangs <= 0 ? $langs->trans("Languages") : $langs->trans("Languages").'<span class="marginleftonlyshort badge">'.$countLangs."</span>");
3798 $head2[$h][2] = 'languages';
3799 $h++;
3800
3801 $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=permissions&module='.$module.($forceddirread ? '@'.$dirread : '');
3802 $head2[$h][1] = ($countRights <= 0 ? $langs->trans("Permissions") : $langs->trans("Permissions").'<span class="marginleftonlyshort badge">'.$countRights."</span>");
3803 $head2[$h][2] = 'permissions';
3804 $h++;
3805
3806 $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=dictionaries&module='.$module.($forceddirread ? '@'.$dirread : '');
3807 $head2[$h][1] = ($countDictionaries == 0 ? $langs->trans("Dictionaries") : $langs->trans('Dictionaries').'<span class="marginleftonlyshort badge">'.$countDictionaries."</span>");
3808 $head2[$h][2] = 'dictionaries';
3809 $h++;
3810
3811 $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=tabs&module='.$module.($forceddirread ? '@'.$dirread : '');
3812 $head2[$h][1] = $langs->trans("Tabs");
3813 $head2[$h][2] = 'tabs';
3814 $h++;
3815
3816 $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=menus&module='.$module.($forceddirread ? '@'.$dirread : '');
3817 $head2[$h][1] = ($countMenus <= 0 ? $langs->trans("Menus") : $langs->trans("Menus").'<span class="marginleftonlyshort badge">'.$countMenus."</span>");
3818 $head2[$h][2] = 'menus';
3819 $h++;
3820
3821 $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=hooks&module='.$module.($forceddirread ? '@'.$dirread : '');
3822 $head2[$h][1] = $langs->trans("Hooks");
3823 $head2[$h][2] = 'hooks';
3824 $h++;
3825
3826 $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=triggers&module='.$module.($forceddirread ? '@'.$dirread : '');
3827 $head2[$h][1] = ($countTriggers <= 0 ? $langs->trans("Triggers") : $langs->trans("Triggers").'<span class="marginleftonlyshort badge">'.$countTriggers."</span>");
3828 $head2[$h][2] = 'triggers';
3829 $h++;
3830
3831 $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=widgets&module='.$module.($forceddirread ? '@'.$dirread : '');
3832 $head2[$h][1] = ($countWidgets <= 0 ? $langs->trans("Widgets") : $langs->trans("Widgets").'<span class="marginleftonlyshort badge">'.$countWidgets."</span>");
3833 $head2[$h][2] = 'widgets';
3834 $h++;
3835
3836 $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=emailings&module='.$module.($forceddirread ? '@'.$dirread : '');
3837 $head2[$h][1] = ($countEmailingSelectors <= 0 ? $langs->trans("EmailingSelectors") : $langs->trans("EmailingSelectors").'<span class="marginleftonlyshort badge">'.$countEmailingSelectors."</span>");
3838 $head2[$h][2] = 'emailings';
3839 $h++;
3840
3841 $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=exportimport&module='.$module.($forceddirread ? '@'.$dirread : '');
3842 $head2[$h][1] = $langs->trans("ImportExportProfiles");
3843 $head2[$h][2] = 'exportimport';
3844 $h++;
3845
3846 $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=css&module='.$module.($forceddirread ? '@'.$dirread : '');
3847 $head2[$h][1] = ($countCss <= 0 ? $langs->trans("CSS") : $langs->trans("CSS")." (".$countCss.")");
3848 $head2[$h][2] = 'css';
3849 $h++;
3850
3851 $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=js&module='.$module.($forceddirread ? '@'.$dirread : '');
3852 $head2[$h][1] = ($countJs <= 0 ? $langs->trans("JS") : $langs->trans("JS").'<span class="marginleftonlyshort badge">'.$countJs."</span>");
3853 $head2[$h][2] = 'js';
3854 $h++;
3855
3856 $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=cli&module='.$module.($forceddirread ? '@'.$dirread : '');
3857 $head2[$h][1] = ($countCLI <= 0 ? $langs->trans("CLI") : $langs->trans("CLI").'<span class="marginleftonlyshort badge">'.$countCLI."</span>");
3858 $head2[$h][2] = 'cli';
3859 $h++;
3860
3861 $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=cron&module='.$module.($forceddirread ? '@'.$dirread : '');
3862 $head2[$h][1] = $langs->trans("CronList");
3863 $head2[$h][2] = 'cron';
3864 $h++;
3865
3866 $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=specifications&module='.$module.($forceddirread ? '@'.$dirread : '');
3867 $head2[$h][1] = ($hasDoc <= 0 ? $langs->trans("Documentation") : $langs->trans("Documentation").'<span class="marginleftonlyshort badge">'.$hasDoc."</span>");
3868 $head2[$h][2] = 'specifications';
3869 $h++;
3870
3871 $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=buildpackage&module='.$module.($forceddirread ? '@'.$dirread : '');
3872 $head2[$h][1] = $langs->trans("BuildPackage");
3873 $head2[$h][2] = 'buildpackage';
3874 $h++;
3875
3876 $MAXTABFOROBJECT = 12;
3877
3878 print '<!-- Section for a given module -->';
3879
3880 // Note module is inside $dirread
3881
3882 if ($tab == 'description') {
3883 print '<!-- tab=description -->'."\n";
3884 $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
3885 $pathtofilereadme = $modulelowercase.'/README.md';
3886 $pathtochangelog = $modulelowercase.'/ChangeLog.md';
3887 $pathtoindex = $modulelowercase.'/'.$modulelowercase.'index.php';
3888
3889 $realpathofmodule = realpath($dirread.'/'.$modulelowercase);
3890
3891 if ($action != 'editfile' || empty($file)) {
3892 $morehtmlright = '';
3893 if ($realpathofmodule != $dirread.'/'.$modulelowercase) {
3894 $morehtmlright = '<div style="padding: 12px 9px 12px">'.$form->textwithpicto('', '<span class="opacitymedium">'.$langs->trans("RealPathOfModule").' :</span> <strong class="wordbreak">'.$realpathofmodule.'</strong>').'</div>';
3895 }
3896
3897 print dol_get_fiche_head($head2, $tab, '', -1, '', 0, $morehtmlright, '', $MAXTABFOROBJECT, 'formodulesuffix'); // Description - level 2
3898
3899 print '<span class="opacitymedium">'.$langs->trans("ModuleBuilderDesc".$tab).'</span>';
3900 print '<br><br>';
3901
3902 print '<table>';
3903
3904 print '<tr><td>';
3905 print '<span class="fa fa-file"></span> '.$langs->trans("DescriptorFile").' : <strong class="wordbreak">'.$pathtofile.'</strong>';
3906 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>';
3907 print '</td></tr>';
3908
3909 print '<tr><td><span class="fa fa-file"></span> '.$langs->trans("Index").' : <strong class="wordbreak">'.$pathtoindex.'</strong>';
3910 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($pathtoindex).'">'.img_picto($langs->trans("Edit"), 'edit').'</a>';
3911 print '</td></tr>';
3912
3913 // List of setup pages
3914 $listofsetuppages = dol_dir_list($realpathofmodule.'/admin', 'files', 0, '\.php$');
3915 foreach ($listofsetuppages as $setuppage) {
3916 // If this is a page for extrafields setup of an object
3917 $reg = array();
3918 if (preg_match('/^([a-z]+)_extrafields.php/', $setuppage['relativename'], $reg)) {
3919 // Check that object has $isextrafieldmanaged property set. If not, we should not show this file.
3920 $fileofclass = $realpathofmodule.'/class/'.$reg[1].'.class.php';
3921 if (is_readable($fileofclass) && !preg_match('/public\s+\$isextrafieldmanaged\s+=\s+1/', file_get_contents($fileofclass))) {
3922 continue;
3923 }
3924 }
3925
3926 //var_dump($setuppage);
3927 print '<tr><td>';
3928 print '<span class="fa fa-file"></span> ';
3929 if ($setuppage['relativename'] == 'about.php') {
3930 print $langs->trans("AboutFile");
3931 } else {
3932 print $langs->trans("SetupFile");
3933 }
3934 print ' : ';
3935 print '<strong class="wordbreak bold"><a href="'.dol_buildpath($modulelowercase.'/admin/'.$setuppage['relativename'], 1).'" target="_test">'.$modulelowercase.'/admin/'.$setuppage['relativename'].'</a></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($modulelowercase.'/admin/'.$setuppage['relativename']).'">'.img_picto($langs->trans("Edit"), 'edit').'</a>';
3937 print '</td></tr>';
3938 }
3939
3940 print '<tr><td><span class="fa fa-file"></span> '.$langs->trans("ReadmeFile").' : <strong class="wordbreak">'.$pathtofilereadme.'</strong>';
3941 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>';
3942 print '</td></tr>';
3943
3944 print '<tr><td><span class="fa fa-file"></span> '.$langs->trans("ChangeLog").' : <strong class="wordbreak">'.$pathtochangelog.'</strong>';
3945 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>';
3946 print '</td></tr>';
3947
3948 print '</table>';
3949 print '<br>';
3950
3951 print load_fiche_titre($form->textwithpicto($langs->trans("DescriptorFile"), $langs->transnoentitiesnoconv("File").' '.$pathtofile), '', '');
3952
3953 if (is_object($moduleobj)) {
3954 print '<div class="underbanner clearboth"></div>';
3955 print '<div class="fichecenter">';
3956 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
3957 print '<input type="hidden" name="token" value="'.newToken().'">';
3958 print '<input type="hidden" name="action" value="update_props_module">';
3959 print '<input type="hidden" name="module" value="'.dol_escape_htmltag($module).'">';
3960 print '<input type="hidden" name="tab" value="'.dol_escape_htmltag($tab).'">';
3961 print '<input type="hidden" name="keydescription" value="'.dol_escape_htmltag(GETPOST('keydescription', 'alpha')).'">';
3962
3963 print '<div class="div-table-responsive-no-min">';
3964 print '<table class="border centpercent">';
3965 print '<tr class="liste_titre"><td class="titlefield">';
3966 print $langs->trans("Parameter");
3967 print '</td><td>';
3968 print $langs->trans("Value");
3969 print '</td></tr>';
3970
3971 print '<tr><td>';
3972 print $langs->trans("IdModule");
3973 print '</td><td>';
3974 print $moduleobj->numero;
3975 print '<span class="opacitymedium">';
3976 print ' &nbsp; (';
3977 print dolButtonToOpenUrlInDialogPopup('popup_modules_id', $langs->transnoentitiesnoconv("SeeIDsInUse"), $langs->transnoentitiesnoconv("SeeIDsInUse"), '/admin/system/modules.php?mainmenu=home&leftmenu=admintools_info', '', '');
3978 print ' - <a href="https://wiki.dolibarr.org/index.php/List_of_modules_id" target="_blank" rel="noopener noreferrer external">'.$langs->trans("SeeReservedIDsRangeHere").'</a>)';
3979 print '</span>';
3980 print '</td></tr>';
3981
3982 print '<tr><td>';
3983 print $langs->trans("ModuleName");
3984 print '</td><td>';
3985 print $moduleobj->getName();
3986 print '</td></tr>';
3987
3988 print '<tr><td>';
3989 print $langs->trans("Description");
3990 print '</td><td>';
3991 if ($action == 'edit_moduledescription' && GETPOST('keydescription', 'alpha') === 'desc') {
3992 print '<input class="minwidth500" name="propsmodule" value="'.dol_escape_htmltag($moduleobj->description).'" spellcheck="false">';
3993 print '<input class="reposition button smallpaddingimp" type="submit" name="modifydesc" value="'.$langs->trans("Modify").'"/>';
3994 print '<input class="reposition button button-cancel smallpaddingimp" type="submit" name="cancel" value="'.$langs->trans("Cancel").'"/>';
3995 } else {
3996 print $moduleobj->description;
3997 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>';
3998
3999 $moduledescritpionautotrans = $moduleobj->getDesc();
4000 if ($moduledescritpionautotrans != "Module".$moduleobj->name."Desc") {
4001 // $moduledescritpionautotrans has been found into a translation file
4002 print ' '.$form->textwithpicto('', $langs->trans("ModuleTranslatedIntoLangForKeyInto", "Module".$moduleobj->name."Desc", $moduledescritpionautotrans));
4003 } elseif ($moduledescritpionautotrans != "Module".$moduleobj->numero."Desc") {
4004 // $moduledescritpionautotrans has been found into a translation file
4005 print ' '.$form->textwithpicto('', $langs->trans("ModuleTranslatedIntoLangForKeyInto", "Module".$moduleobj->numero."Desc", $moduledescritpionautotrans));
4006 }
4007 }
4008 print '</td></tr>';
4009
4010 print '<tr><td>';
4011 print $langs->trans("Version");
4012 print '</td><td>';
4013 if ($action == 'edit_moduledescription' && GETPOST('keydescription', 'alpha') === 'version') {
4014 print '<input name="propsmodule" value="'.dol_escape_htmltag($moduleobj->getVersion()).'">';
4015 print '<input class="reposition button smallpaddingimp" type="submit" name="modifyversion" value="'.$langs->trans("Modify").'"/>';
4016 print '<input class="reposition button button-cancel smallpaddingimp" type="submit" name="cancel" value="'.$langs->trans("Cancel").'"/>';
4017 } else {
4018 print $moduleobj->getVersion();
4019 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>';
4020 }
4021 print '</td></tr>';
4022
4023 print '<tr><td>';
4024 print $langs->trans("Family");
4025 //print "<br>'crm','financial','hr','projects','products','ecm','technic','interface','other'";
4026 print '</td><td>';
4027 if ($action == 'edit_moduledescription' && GETPOST('keydescription', 'alpha') === 'family') {
4028 print '<select name="propsmodule" id="family" class="minwidth400">';
4029 $arrayoffamilies = array(
4030 'hr' => "ModuleFamilyHr",
4031 'crm' => "ModuleFamilyCrm",
4032 'srm' => "ModuleFamilySrm",
4033 'financial' => 'ModuleFamilyFinancial',
4034 'products' => 'ModuleFamilyProducts',
4035 'projects' => 'ModuleFamilyProjects',
4036 'ecm' => 'ModuleFamilyECM',
4037 'technic' => 'ModuleFamilyTechnic',
4038 'portal' => 'ModuleFamilyPortal',
4039 'interface' => 'ModuleFamilyInterface',
4040 'base' => 'ModuleFamilyBase',
4041 'other' => 'ModuleFamilyOther'
4042 );
4043 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>';
4044 foreach ($arrayoffamilies as $key => $value) {
4045 if ($key != $moduleobj->family) {
4046 print '<option value="'.$key.'" data-html="'.dol_escape_htmltag($langs->trans($value).' <span class="opacitymedium">- '.$key.'</span>').'">'.$langs->trans($value).'</option>';
4047 }
4048 }
4049 print '</select>';
4050 print '<input class="reposition button smallpaddingimp" type="submit" name="modifyfamily" value="'.$langs->trans("Modify").'"/>';
4051 print '<input class="reposition button button-cancel smallpaddingimp" type="submit" name="cancel" value="'.$langs->trans("Cancel").'"/>';
4052 } else {
4053 print $moduleobj->family;
4054 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>';
4055 }
4056 print '</td></tr>';
4057
4058 print '<!-- picto of module -->'."\n";
4059 print '<tr><td>';
4060 print $langs->trans("Picto");
4061 print '</td><td>';
4062 if ($action == 'edit_modulepicto' && GETPOST('keydescription', 'alpha') === 'picto') {
4063 print '<input class="minwidth200 maxwidth500" name="propsmodule" value="'.dol_escape_htmltag($moduleobj->picto).'" spellcheck="false">';
4064
4065 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\'');
4066
4067 print '<input class="reposition button smallpaddingimp" type="submit" name="modifypicto" value="'.$langs->trans("Modify").'"/>';
4068 print '<input class="reposition button button-cancel smallpaddingimp" type="submit" name="cancel" value="'.$langs->trans("Cancel").'"/>';
4069
4070 print ' &nbsp; &nbsp; ';
4071
4072 print '<span class="opacitymedium small">';
4073 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', '', '');
4074 print '</span>';
4075 } else {
4076 print $moduleobj->picto;
4077 print ' &nbsp; '.img_picto('', $moduleobj->picto, 'class="valignmiddle pictomodule paddingrightonly"');
4078 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>';
4079 }
4080 print '</td></tr>';
4081
4082 print '<tr><td>';
4083 print $langs->trans("EditorName");
4084 print '</td><td>';
4085 if ($action == 'edit_moduledescription' && GETPOST('keydescription', 'alpha') === 'editor_name') {
4086 print '<input name="propsmodule" value="'.dol_escape_htmltag($moduleobj->editor_name).'" spellcheck="false">';
4087 print '<input class="reposition button smallpaddingimp" type="submit" name="modifyname" value="'.$langs->trans("Modify").'"/>';
4088 print '<input class="reposition button button-cancel smallpaddingimp" type="submit" name="cancel" value="'.$langs->trans("Cancel").'"/>';
4089 } else {
4090 print $moduleobj->editor_name;
4091 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>';
4092 }
4093 print '</td></tr>';
4094
4095 print '<tr><td>';
4096 print $langs->trans("EditorUrl");
4097 print '</td><td>';
4098 if ($action == 'edit_moduledescription' && GETPOST('keydescription', 'alpha') === 'editor_url') {
4099 print '<input name="propsmodule" value="'.dol_escape_htmltag($moduleobj->editor_url).'" spellcheck="false">';
4100 print '<input class="reposition button smallpaddingimp" type="submit" name="modifyeditorurl" value="'.$langs->trans("Modify").'"/>';
4101 print '<input class="reposition button button-cancel smallpaddingimp" type="submit" name="cancel" value="'.$langs->trans("Cancel").'"/>';
4102 } else {
4103 if (!empty($moduleobj->editor_url)) {
4104 print '<a href="'.$moduleobj->editor_url.'" target="_blank" rel="noopener">'.$moduleobj->editor_url.' '.img_picto('', 'globe').'</a>';
4105 }
4106 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>';
4107 }
4108 print '</td></tr>';
4109
4110 print '</table>';
4111 print '</div>';
4112 print '</form>';
4113 } else {
4114 print $langs->trans("ErrorFailedToLoadModuleDescriptorForXXX", $module).'<br>';
4115 }
4116
4117 if (!empty($moduleobj)) {
4118 print '<br><br>';
4119
4120 // Readme file
4121 print load_fiche_titre($form->textwithpicto($langs->trans("ReadmeFile"), $langs->transnoentitiesnoconv("File").' '.$pathtofilereadme), '', '');
4122
4123 print '<!-- readme file -->';
4124 if (dol_is_file($dirread.'/'.$pathtofilereadme)) {
4125 print '<div class="underbanner clearboth"></div><div class="fichecenter">'.$moduleobj->getDescLong().'</div>';
4126 } else {
4127 print '<span class="opacitymedium">'.$langs->trans("ErrorFileNotFound", $pathtofilereadme).'</span>';
4128 }
4129
4130 print '<br><br>';
4131
4132 // ChangeLog
4133 print load_fiche_titre($form->textwithpicto($langs->trans("ChangeLog"), $langs->transnoentitiesnoconv("File").' '.$pathtochangelog), '', '');
4134
4135 print '<!-- changelog file -->';
4136 if (dol_is_file($dirread.'/'.$pathtochangelog)) {
4137 print '<div class="underbanner clearboth"></div><div class="fichecenter">'.$moduleobj->getChangeLog().'</div>';
4138 } else {
4139 print '<span class="opacitymedium">'.$langs->trans("ErrorFileNotFound", $pathtochangelog).'</span>';
4140 }
4141 }
4142
4143 print dol_get_fiche_end();
4144 } else { // Edit text file
4145 $fullpathoffile = dol_buildpath($file, 0, 1); // Description - level 2
4146
4147 $content = '';
4148 if ($fullpathoffile) {
4149 $content = file_get_contents($fullpathoffile);
4150 }
4151
4152 // New module
4153 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
4154 print '<input type="hidden" name="token" value="'.newToken().'">';
4155 print '<input type="hidden" name="action" value="savefile">';
4156 print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
4157 print '<input type="hidden" name="tab" value="'.$tab.'">';
4158 print '<input type="hidden" name="module" value="'.$module.'">';
4159
4160 print dol_get_fiche_head($head2, $tab, '', -1, '', 0, '', '', 0, 'formodulesuffix');
4161
4162 $posCursor = (empty($find)) ? array() : array('find' => $find);
4163 $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%', 0, $posCursor);
4164 print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'html'));
4165
4166 print dol_get_fiche_end();
4167
4168 print '<center>';
4169 print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
4170 print ' &nbsp; ';
4171 print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
4172 print '</center>';
4173
4174 print '</form>';
4175 }
4176 } else {
4177 print dol_get_fiche_head($head2, $tab, '', -1, '', 0, '', '', $MAXTABFOROBJECT, 'formodulesuffix'); // Level 2
4178 }
4179
4180 if ($tab == 'languages') {
4181 print '<!-- tab=languages -->'."\n";
4182 if ($action != 'editfile' || empty($file)) {
4183 print '<span class="opacitymedium">'.$langs->trans("LanguageDefDesc").'</span><br>';
4184 print '<br>';
4185
4186
4187 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
4188 print '<input type="hidden" name="token" value="'.newToken().'">';
4189 print '<input type="hidden" name="action" value="addlanguage">';
4190 print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
4191 print '<input type="hidden" name="tab" value="'.$tab.'">';
4192 print '<input type="hidden" name="module" value="'.$module.'">';
4193 print $formadmin->select_language(getDolGlobalString('MAIN_LANG_DEFAULT'), 'newlangcode', 0, array(), 1, 0, 0, 'minwidth300', 1);
4194 print '<input type="submit" name="addlanguage" class="button smallpaddingimp" value="'.dol_escape_htmltag($langs->trans("AddLanguageFile")).'"><br>';
4195 print '</form>';
4196
4197 print '<br>';
4198 print '<br>';
4199
4200 $modulelowercase = strtolower($module);
4201
4202 // Dir for module
4203 $diroflang = dol_buildpath($modulelowercase, 0);
4204 $diroflang .= '/langs';
4205 $langfiles = dol_dir_list($diroflang, 'files', 1, '\.lang$');
4206
4207 if (!preg_match('/custom/', $dirread)) {
4208 // If this is not a module into custom
4209 $diroflang = $dirread;
4210 $diroflang .= '/langs';
4211 $langfiles = dol_dir_list($diroflang, 'files', 1, $modulelowercase.'\.lang$');
4212 }
4213
4214 print '<table class="none">';
4215 foreach ($langfiles as $langfile) {
4216 $pathtofile = $modulelowercase.'/langs/'.$langfile['relativename'];
4217 if (!preg_match('/custom/', $dirread)) { // If this is not a module into custom
4218 $pathtofile = 'langs/'.$langfile['relativename'];
4219 }
4220 print '<tr><td><span class="fa fa-file"></span> '.$langs->trans("LanguageFile").' '.basename(dirname($pathtofile)).' : <strong class="wordbreak">'.$pathtofile.'</strong>';
4221 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>';
4222 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>';
4223 print '</td>';
4224 }
4225 print '</table>';
4226 } else {
4227 // Edit text language file
4228
4229 //print $langs->trans("UseAsciiDocFormat").'<br>';
4230
4231 $fullpathoffile = dol_buildpath($file, 0);
4232
4233 $content = file_get_contents($fullpathoffile);
4234
4235 // New module
4236 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
4237 print '<input type="hidden" name="token" value="'.newToken().'">';
4238 print '<input type="hidden" name="action" value="savefile">';
4239 print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
4240 print '<input type="hidden" name="tab" value="'.$tab.'">';
4241 print '<input type="hidden" name="module" value="'.$module.'">';
4242
4243 $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%');
4244 print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'text'));
4245 print '<br>';
4246 print '<center>';
4247 print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
4248 print ' &nbsp; ';
4249 print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
4250 print '</center>';
4251
4252 print '</form>';
4253 }
4254 }
4255
4256 if ($tab == 'objects') {
4257 print '<!-- tab=objects -->'."\n";
4258 $head3 = array();
4259 $h = 0;
4260
4261 // Dir for module
4262 $dir = $dirread.'/'.$modulelowercase.'/class';
4263
4264 $head3[$h][0] = $_SERVER["PHP_SELF"].'?tab=objects&module='.$module.($forceddirread ? '@'.$dirread : '').'&tabobj=newobject';
4265 $head3[$h][1] = '<span class="valignmiddle text-plus-circle">'.$langs->trans("NewObjectInModulebuilder").'</span><span class="fa fa-plus-circle valignmiddle paddingleft"></span>';
4266 $head3[$h][2] = 'newobject';
4267 $h++;
4268
4269 // Scan for object class files
4270 $listofobject = dol_dir_list($dir, 'files', 0, '\.class\.php$');
4271
4272 $firstobjectname = '';
4273 foreach ($listofobject as $fileobj) {
4274 if (preg_match('/^api_/', $fileobj['name'])) {
4275 continue;
4276 }
4277 if (preg_match('/^actions_/', $fileobj['name'])) {
4278 continue;
4279 }
4280
4281 $tmpcontent = file_get_contents($fileobj['fullname']);
4282 if (preg_match('/class\s+([^\s]*)\s+extends\s+CommonObject/ims', $tmpcontent, $reg)) {
4283 //$objectname = preg_replace('/\.txt$/', '', $fileobj['name']);
4284 $objectname = $reg[1];
4285 if (empty($firstobjectname)) {
4286 $firstobjectname = $objectname;
4287 }
4288 $pictoname = 'generic';
4289 if (preg_match('/\$picto\s*=\s*["\']([^"\']+)["\']/', $tmpcontent, $reg)) {
4290 $pictoname = $reg[1];
4291 }
4292
4293 $head3[$h][0] = $_SERVER["PHP_SELF"].'?tab=objects&module='.$module.($forceddirread ? '@'.$dirread : '').'&tabobj='.$objectname;
4294 $head3[$h][1] = img_picto('', $pictoname, 'class="pictofixedwidth valignmiddle"').$objectname;
4295 $head3[$h][2] = $objectname;
4296 $h++;
4297 }
4298 }
4299
4300 if ($h > 1) {
4301 $head3[$h][0] = $_SERVER["PHP_SELF"].'?tab=objects&module='.$module.($forceddirread ? '@'.$dirread : '').'&tabobj=deleteobject';
4302 $head3[$h][1] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("DangerZone");
4303 $head3[$h][2] = 'deleteobject';
4304 $h++;
4305 }
4306
4307 // 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.
4308 if ($tabobj == 'newobjectifnoobj') {
4309 if ($firstobjectname) {
4310 $tabobj = $firstobjectname;
4311 } else {
4312 $tabobj = 'newobject';
4313 }
4314 }
4315
4316 print dol_get_fiche_head($head3, $tabobj, '', -1, '', 0, '', '', 0, 'forobjectsuffix'); // Level 3
4317
4318
4319 if ($tabobj == 'newobject') {
4320 // New object tab
4321 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
4322 print '<input type="hidden" name="token" value="'.newToken().'">';
4323 print '<input type="hidden" name="action" value="initobject">';
4324 print '<input type="hidden" name="tab" value="objects">';
4325 print '<input type="hidden" name="module" value="'.dol_escape_htmltag($module).'">';
4326
4327 // Tabs selected by default = all optional tabs; reflect posted state on redisplay
4328 $enabledtabsdefault = GETPOSTISSET('enabledtab') ? GETPOST('enabledtab', 'array') : array_keys(getModuleBuilderObjectTabs());
4329
4330 print '<span class="opacitymedium">'.$langs->trans("EnterNameOfObjectDesc").'</span><br><br>';
4331
4332 print '<div class="tagtable">';
4333
4334 print '<div class="tagtr"><div class="tagtd">';
4335 print '<span class="opacitymedium">'.$langs->trans("ObjectKey").'</span> &nbsp; ';
4336 print '</div><div class="tagtd">';
4337 print '<input type="text" name="objectname" maxlength="64" value="'.dol_escape_htmltag(GETPOSTISSET('objectname') ? GETPOST('objectname', 'alpha') : $modulename).'" required autofocus>';
4338 print $form->textwithpicto('', $langs->trans("Example").': MyObject, ACamelCaseName, ...');
4339 print '</div></div>';
4340
4341 print '<div class="tagtr"><div class="tagtd">';
4342 print '<span class="opacitymedium">'.$langs->trans("Picto").'</span> &nbsp; ';
4343 print '</div><div class="tagtd">';
4344 print '<input type="text" name="idpicto" value="fa-file" placeholder="'.dol_escape_htmltag($langs->trans("Picto")).'">';
4345
4346 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\'');
4347
4348 print '<span class="opacitymedium small">';
4349 print ' &nbsp; &nbsp; ';
4350 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', '', '');
4351 print '</span>';
4352
4353 print '</div></div>';
4354
4355 print '<div class="tagtr"><div class="tagtd">';
4356 print '<span class="opacitymedium">'.$langs->trans("DefinePropertiesFromExistingTable").'</span> &nbsp; ';
4357 print '</div><div class="tagtd">';
4358 print '<input type="text" name="initfromtablename" value="'.GETPOST('initfromtablename').'" placeholder="'.$langs->trans("TableName").'">';
4359 print $form->textwithpicto('', $langs->trans("DefinePropertiesFromExistingTableDesc").'<br>'.$langs->trans("DefinePropertiesFromExistingTableDesc2"));
4360 print '</div></div>';
4361
4362 print '</div>';
4363
4364 print '<br>';
4365 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>';
4366 print '<input type="checkbox" name="includedocgeneration" id="includedocgeneration" value="includedocgeneration"> <label for="includedocgeneration">'.$form->textwithpicto($langs->trans("IncludeDocGeneration"), $langs->trans("IncludeDocGenerationHelp")).'</label><br>';
4367 print '<input type="checkbox" name="generatepermissions" id="generatepermissions" value="generatepermissions"> <label for="generatepermissions">'.$form->textwithpicto($langs->trans("GeneratePermissions"), $langs->trans("GeneratePermissionsHelp")).'</label><br>';
4368 print '<input type="checkbox" name="nogeneratelines" id="nogeneratelines" value="nogeneratelines"> <label for="nogeneratelines">'.$form->textwithpicto($langs->trans("NoGenerateLines"), $langs->trans("NoGenerateLinesHelp")).'</label><br>';
4369 print '<br><span class="opacitymedium">'.$form->textwithpicto($langs->trans("EnabledTabsForObject"), $langs->trans("EnabledTabsForObjectHelp")).'</span><br>';
4370 foreach (getModuleBuilderObjectTabs() as $tabkey => $tabinfo) {
4371 $checked = in_array($tabkey, $enabledtabsdefault, true) ? ' checked' : '';
4372 print '<input type="checkbox" name="enabledtab[]" id="enabledtab_'.$tabkey.'" value="'.dol_escape_htmltag($tabkey).'"'.$checked.'> ';
4373 print '<label for="enabledtab_'.$tabkey.'">'.dol_escape_htmltag($langs->trans($tabinfo['label'])).'</label> &nbsp; ';
4374 }
4375 print '<br>';
4376 print '<br>';
4377 print '<input type="submit" class="button small" name="create" value="'.dol_escape_htmltag($langs->trans("GenerateCode")).'"'.($dirins ? '' : ' disabled="disabled"').'>';
4378 print '<br>';
4379 print '<br>';
4380 /*
4381 print '<br>';
4382 print '<span class="opacitymedium">'.$langs->trans("or").'</span>';
4383 print '<br>';
4384 print '<br>';
4385 //print '<input type="checkbox" name="initfromtablecheck"> ';
4386 print $langs->trans("InitStructureFromExistingTable");
4387 print '<input type="text" name="initfromtablename" value="" placeholder="'.$langs->trans("TableName").'">';
4388 print '<input type="submit" class="button smallpaddingimp" name="createtablearray" value="'.dol_escape_htmltag($langs->trans("GenerateCode")).'"'.($dirins ? '' : ' disabled="disabled"').'>';
4389 print '<br>';
4390 */
4391
4392 print '</form>';
4393 } elseif ($tabobj == 'createproperty') {
4394 $attributesUnique = array(
4395 'proplabel' => $form->textwithpicto($langs->trans("Label"), $langs->trans("YouCanUseTranslationKey")),
4396 'propname' => $form->textwithpicto($langs->trans("Code"), $langs->trans("PropertyDesc"), 1, 'help', 'extracss', 0, 3, 'propertyhelp'),
4397 'proptype' => $form->textwithpicto($langs->trans("Type"), $langs->trans("TypeOfFieldsHelpIntro").'<br><br>'.$langs->trans("TypeOfFieldsHelp"), 1, 'help', 'extracss', 0, 3, 'typehelp'),
4398 'proparrayofkeyval' => $form->textwithpicto($langs->trans("ArrayOfKeyValues"), $langs->trans("ArrayOfKeyValuesDesc")),
4399 'propnotnull' => $form->textwithpicto($langs->trans("NotNull"), $langs->trans("NotNullDesc")),
4400 'propdefault' => $langs->trans("DefaultValue"),
4401 'propindex' => $langs->trans("DatabaseIndex"),
4402 'propforeignkey' => $form->textwithpicto($langs->trans("ForeignKey"), $langs->trans("ForeignKeyDesc"), 1, 'help', 'extracss', 0, 3, 'foreignkeyhelp'),
4403 'propposition' => $langs->trans("Position"),
4404 'propenabled' => $form->textwithpicto($langs->trans("Enabled"), $langs->trans("EnabledDesc"), 1, 'help', 'extracss', 0, 3, 'enabledhelp'),
4405 'propvisible' => $form->textwithpicto($langs->trans("Visibility"), $langs->trans("VisibleDesc").'<br><br>'.$langs->trans("ItCanBeAnExpression"), 1, 'help', 'extracss', 0, 3, 'visiblehelp'),
4406 'propnoteditable' => $langs->trans("NotEditable"),
4407 //'propalwayseditable' => $langs->trans("AlwaysEditable"),
4408 'propsearchall' => $form->textwithpicto($langs->trans("SearchAll"), $langs->trans("SearchAllDesc")),
4409 'propisameasure' => $form->textwithpicto($langs->trans("IsAMeasure"), $langs->trans("IsAMeasureDesc")),
4410 'propcss' => $langs->trans("CSSClass"),
4411 'propcssview' => $langs->trans("CSSViewClass"),
4412 'propcsslist' => $langs->trans("CSSListClass"),
4413 'prophelp' => $langs->trans("KeyForTooltip"),
4414 'propshowoncombobox' => $langs->trans("ShowOnCombobox"),
4415 //'propvalidate' => $form->textwithpicto($langs->trans("Validate"), $langs->trans("ValidateModBuilderDesc")),
4416 'propcomment' => $langs->trans("Comment"),
4417 );
4418 print '<form action="'.$_SERVER["PHP_SELF"].'?tab=objects&module='.urlencode($module).'&tabobj=createproperty&obj='.urlencode(GETPOST('obj')).'" method="POST">';
4419 print '<input type="hidden" name="token" value="'.newToken().'">';
4420 print '<input type="hidden" name="action" value="addproperty">';
4421 print '<input type="hidden" name="tab" value="objects">';
4422 print '<input type="hidden" name="module" value="'.dol_escape_htmltag($module).'">';
4423 print '<input type="hidden" name="obj" value="'.dol_escape_htmltag(GETPOST('obj')).'">';
4424
4425 print '<table class="border centpercent tableforfieldcreate">'."\n";
4426 $counter = 0;
4427 foreach ($attributesUnique as $key => $attribute) {
4428 if ($counter % 2 === 0) {
4429 print '<tr>';
4430 }
4431 if ($key == 'propname' || $key == 'proplabel') {
4432 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>';
4433 } elseif ($key == 'proptype') {
4434 print '<td class="titlefieldcreate fieldrequired">'.$attribute.'</td><td class="valuefieldcreate maxwidth50">';
4435 print '<input class="maxwidth200" name="'.$key.'" id="'.$key.'" list="datalist'.$key.'" type="text" value="'.dol_escape_htmltag(GETPOST($key, 'alpha')).'">';
4436 //print '<div id="suggestions"></div>';
4437 print '<datalist id="datalist'.$key.'">';
4438 print '<option>varchar(128)</option>';
4439 print '<option>email</option>';
4440 print '<option>phone</option>';
4441 print '<option>ip</option>';
4442 print '<option>url</option>';
4443 print '<option>password</option>';
4444 print '<option>text</option>';
4445 print '<option>html</option>';
4446 print '<option>date</option>';
4447 print '<option>datetime</option>';
4448 print '<option>integer</option>';
4449 print '<option>stars(5)</option>';
4450 print '<option>double(28,4)</option>';
4451 print '<option>real</option>';
4452 print '<option>integer:ClassName:RelativePath/To/ClassFile.class.php[:1[:FILTER]]</option>';
4453 // Combo with list of fields
4454 /*
4455 if (empty($formadmin)) {
4456 include_once DOL_DOCUMENT_ROOT.'/core/class/html.formadmin.class.php';
4457 $formadmin = new FormAdmin($db);
4458 }
4459 print $formadmin->selectTypeOfFields($key, GETPOST($key, 'alpha'));
4460 */
4461 print '</datalist>';
4462 print '</td>';
4463 //} elseif ($key == 'propvalidate') {
4464 // 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>';
4465 } elseif ($key == 'propvisible') {
4466 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>';
4467 } elseif ($key == 'propenabled') {
4468 //$default = "isModEnabled('".strtolower($module)."')";
4469 $default = 1;
4470 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>';
4471 } elseif ($key == 'proparrayofkeyval') {
4472 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>';
4473 } else {
4474 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>';
4475 }
4476 $counter++;
4477 if ($counter % 2 === 0) {
4478 print '</tr>';
4479 }
4480 }
4481 if ($counter % 2 !== 0) {
4482 while ($counter % 2 !== 0) {
4483 print '<td></td>';
4484 $counter++;
4485 }
4486 print '</tr>';
4487 }
4488 print '</table><br>'."\n";
4489 print '<div class="center">';
4490 print '<input type="submit" class="button button-save" name="add" value="' . dol_escape_htmltag($langs->trans('Create')) . '">';
4491 print '<input type="button" class="button button-cancel" name="cancel" value="' . dol_escape_htmltag($langs->trans('Cancel')) . '" onclick="goBack()">';
4492 print '</div>';
4493 print '</form>';
4494 // javascript
4495 print '<script>
4496 function goBack() {
4497 var url = "'.$_SERVER["PHP_SELF"].'?tab=objects&module='.urlencode($module).'";
4498 window.location.href = url;
4499 }
4500 $(document).ready(function() {
4501 $("#proplabel").on("keyup", function() {
4502 console.log("key up on label");
4503 s = cleanString($("#proplabel").val());
4504 $("#propname").val(s);
4505 });
4506
4507 function cleanString( stringtoclean )
4508 {
4509 // allow "a-z", "A-Z", "0-9" and "_"
4510 stringtoclean = stringtoclean.replace(/[^a-z0-9_]+/ig, "");
4511 stringtoclean = stringtoclean.toLowerCase();
4512 if (!isNaN(stringtoclean)) {
4513 return ""
4514 }
4515 while ( stringtoclean.length > 1 && !isNaN( stringtoclean.charAt(0)) ){
4516 stringtoclean = stringtoclean.substr(1)
4517 }
4518 if (stringtoclean.length > 28) {
4519 stringtoclean = stringtoclean.substring(0, 27);
4520 }
4521 return stringtoclean;
4522 }
4523
4524 });';
4525 print '</script>';
4526 } elseif ($tabobj == 'deleteobject') {
4527 // Delete object tab
4528 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
4529 print '<input type="hidden" name="token" value="'.newToken().'">';
4530 print '<input type="hidden" name="action" value="confirm_deleteobject">';
4531 print '<input type="hidden" name="tab" value="objects">';
4532 print '<input type="hidden" name="tabobj" value="deleteobject">';
4533 print '<input type="hidden" name="module" value="'.dol_escape_htmltag($module).'">';
4534
4535 print $langs->trans("EnterNameOfObjectToDeleteDesc").'<br><br>';
4536
4537 print '<input type="text" class="valignmiddle" name="objectname" value="" placeholder="'.dol_escape_htmltag($langs->trans("ObjectKey")).'" autofocus>';
4538 print '<input type="submit" class="button smallpaddingimp" name="delete" value="'.dol_escape_htmltag($langs->trans("Delete")).'"'.($dirins ? '' : ' disabled="disabled"').'>';
4539 print '</form>';
4540 } else {
4541 // tabobj = module
4542 if ($action == 'deleteproperty') {
4543 $formconfirm = $form->formconfirm(
4544 $_SERVER["PHP_SELF"].'?propertykey='.urlencode(GETPOST('propertykey', 'alpha')).'&objectname='.urlencode($objectname).'&tab='.urlencode($tab).'&module='.urlencode($module).'&tabobj='.urlencode($tabobj),
4545 $langs->trans('Delete'),
4546 $langs->trans('ConfirmDeleteProperty', GETPOST('propertykey', 'alpha')),
4547 'confirm_deleteproperty',
4548 '',
4549 0,
4550 1
4551 );
4552
4553 // Print form confirm
4554 print $formconfirm;
4555 }
4556 if ($action != 'editfile' || empty($file)) {
4557 try {
4558 //$pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
4559
4560 $pathtoclass = strtolower($module).'/class/'.strtolower($tabobj).'.class.php';
4561 $pathtoapi = strtolower($module).'/class/api_'.strtolower($module).'.class.php';
4562 $pathtoagenda = strtolower($module).'/'.strtolower($tabobj).'_agenda.php';
4563 $pathtocard = strtolower($module).'/'.strtolower($tabobj).'_card.php';
4564 $pathtodocument = strtolower($module).'/'.strtolower($tabobj).'_document.php';
4565 $pathtolist = strtolower($module).'/'.strtolower($tabobj).'_list.php';
4566 $pathtonote = strtolower($module).'/'.strtolower($tabobj).'_note.php';
4567 $pathtocontact = strtolower($module).'/'.strtolower($tabobj).'_contact.php';
4568 $pathtophpunit = strtolower($module).'/test/phpunit/'.strtolower($tabobj).'Test.php';
4569
4570 // Try to load object class file
4571 clearstatcache(true);
4572 if (function_exists('opcache_invalidate')) {
4573 opcache_invalidate($dirread.'/'.$pathtoclass, true); // remove the include cache hell !
4574 }
4575
4576 if (empty($forceddirread) && empty($dirread)) {
4577 $result = dol_include_once($pathtoclass);
4578 $stringofinclude = "dol_include_once(".$pathtoclass.")";
4579 } else {
4580 $result = include_once $dirread.'/'.$pathtoclass;
4581 $stringofinclude = "@include_once ".$dirread.'/'.$pathtoclass;
4582 }
4583
4584 if (class_exists($tabobj)) {
4585 try {
4586 $tmpobject = @new $tabobj($db);
4587 } catch (Exception $e) {
4588 dol_syslog('Failed to load Constructor of class: '.$e->getMessage(), LOG_WARNING);
4589 }
4590 } else {
4591 print '<span class="warning">'.$langs->trans('Failed to find the class '.$tabobj.' despite the '.$stringofinclude).'</span><br><br>';
4592 }
4593
4594 // Define path for sql file
4595 $pathtosql = strtolower($module).'/sql/llx_'.strtolower($module).'_'.strtolower($tabobj).'-'.strtolower($module).'.sql';
4596 $result = dol_buildpath($pathtosql);
4597 if (! dol_is_file($result)) {
4598 $pathtosql = strtolower($module).'/sql/llx_'.strtolower($module).'_'.strtolower($tabobj).'.sql';
4599 $result = dol_buildpath($pathtosql);
4600 if (! dol_is_file($result)) {
4601 $pathtosql = 'install/mysql/tables/llx_'.strtolower($module).'_'.strtolower($tabobj).'-'.strtolower($module).'.sql';
4602 $result = dol_buildpath($pathtosql);
4603 if (! dol_is_file($result)) {
4604 $pathtosql = 'install/mysql/tables/llx_'.strtolower($module).'-'.strtolower($module).'.sql';
4605 $result = dol_buildpath($pathtosql);
4606 if (! dol_is_file($result)) {
4607 $pathtosql = 'install/mysql/tables/llx_'.strtolower($module).'.sql';
4608 $pathtosqlextra = 'install/mysql/tables/llx_'.strtolower($module).'_extrafields.sql';
4609 $result = dol_buildpath($pathtosql);
4610 } else {
4611 $pathtosqlextra = 'install/mysql/tables/llx_'.strtolower($module).'_extrafields-'.strtolower($module).'.sql';
4612 }
4613 } else {
4614 $pathtosqlextra = 'install/mysql/tables/llx_'.strtolower($module).'_'.strtolower($tabobj).'_extrafields-'.strtolower($module).'.sql';
4615 }
4616 } else {
4617 $pathtosqlextra = strtolower($module).'/sql/llx_'.strtolower($module).'_'.strtolower($tabobj).'_extrafields.sql';
4618 }
4619 } else {
4620 $pathtosqlextra = strtolower($module).'/sql/llx_'.strtolower($module).'_'.strtolower($tabobj).'_extrafields-'.strtolower($module).'.sql';
4621 }
4622 $pathtosqlroot = preg_replace('/\/llx_.*$/', '', $pathtosql);
4623
4624 $pathtosqlkey = preg_replace('/\.sql$/', '.key.sql', $pathtosql);
4625 $pathtosqlextrakey = preg_replace('/\.sql$/', '.key.sql', $pathtosqlextra);
4626
4627 $pathtolib = strtolower($module).'/lib/'.strtolower($module).'.lib.php';
4628 $pathtoobjlib = strtolower($module).'/lib/'.strtolower($module).'_'.strtolower($tabobj).'.lib.php';
4629
4630 $tmpobject = $tmpobject ?? null; // @phan-suppress-current-line PhanPluginDuplicateExpressionAssignmentOperation
4631 if (is_object($tmpobject) && property_exists($tmpobject, 'picto')) {
4632 $pathtopicto = $tmpobject->picto;
4633 $realpathtopicto = '';
4634 } else {
4635 $pathtopicto = strtolower($module).'/img/object_'.strtolower($tabobj).'.png';
4636 $realpathtopicto = $dirread.'/'.$pathtopicto;
4637 }
4638
4639 //var_dump($pathtoclass);
4640 //var_dump($dirread);
4641 $realpathtoclass = $dirread.'/'.$pathtoclass;
4642 $realpathtoapi = $dirread.'/'.$pathtoapi;
4643 $realpathtoagenda = $dirread.'/'.$pathtoagenda;
4644 $realpathtocard = $dirread.'/'.$pathtocard;
4645 $realpathtodocument = $dirread.'/'.$pathtodocument;
4646 $realpathtolist = $dirread.'/'.$pathtolist;
4647 $realpathtonote = $dirread.'/'.$pathtonote;
4648 $realpathtocontact = $dirread.'/'.$pathtocontact;
4649 $realpathtophpunit = $dirread.'/'.$pathtophpunit;
4650 $realpathtosql = $dirread.'/'.$pathtosql;
4651 $realpathtosqlextra = $dirread.'/'.$pathtosqlextra;
4652 $realpathtosqlkey = $dirread.'/'.$pathtosqlkey;
4653 $realpathtosqlextrakey = $dirread.'/'.$pathtosqlextrakey;
4654 $realpathtolib = $dirread.'/'.$pathtolib;
4655 $realpathtoobjlib = $dirread.'/'.$pathtoobjlib;
4656
4657 if (empty($realpathtoapi)) { // For compatibility with some old modules
4658 $pathtoapi = strtolower($module).'/class/api_'.strtolower($module).'s.class.php';
4659 $realpathtoapi = $dirread.'/'.$pathtoapi;
4660 }
4661
4662 $urloflist = dol_buildpath('/'.$pathtolist, 1);
4663 $urlofcard = dol_buildpath('/'.$pathtocard, 1);
4664
4665 $objs = array();
4666
4667 // Image
4668 $htmltooltip = '';
4669 if ($realpathtopicto && dol_is_file($realpathtopicto)) {
4670 $htmltooltip .= '<span class="fa fa-file-image-o"></span> '.$langs->trans("Image").' : <strong>'.(dol_is_file($realpathtopicto) ? '' : '<strike>').preg_replace('/^'.strtolower($module).'\//', '', $pathtopicto).(dol_is_file($realpathtopicto) ? '' : '</strike>').'</strong>';
4671 $htmltooltip .= '<br>';
4672 } elseif (!empty($tmpobject)) {
4673 $htmltooltip .= '<span class="fa fa-file-image-o"></span> '.$langs->trans("Image").' : '.img_picto('', $tmpobject->picto, 'class="pictofixedwidth valignmiddle"').$tmpobject->picto;
4674 $htmltooltip .= '<br>';
4675 }
4676 $htmltooltip .= '<span class="fa fa-file-image-o"></span> '.$langs->trans("IsExtraFieldManaged").' : '.yn(empty($tmpobject->isextrafieldmanaged) ? 0 : 1, 1, 2);
4677 $htmltooltip .= '<br>';
4678 $htmltooltip .= '<span class="fa fa-file-image-o"></span> '.$langs->trans("IsMultiEntityManaged").' : '.yn(empty($tmpobject->ismultientitymanaged) ? 0 : 1, 1, 2);
4679 $htmltooltip .= '<br>';
4680
4681 print '<!-- section for object -->';
4682 print '<div class="fichehalfleft smallxxx">';
4683 // Main DAO class file
4684 print '<span class="fa fa-file"></span> '.$langs->trans("ClassFile").' : <strong>'.(dol_is_file($realpathtoclass) ? '' : '<strike>').preg_replace('/^'.strtolower($module).'\//', '', $pathtoclass).(dol_is_file($realpathtoclass) ? '' : '</strike>').'</strong>';
4685 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>';
4686 print $form->textwithpicto('', $htmltooltip, 1, 'help', 'valignmiddle', 1);
4687 print '<br>';
4688
4689 // API file
4690 print '<br>';
4691 print '<span class="fa fa-file"></span> '.$langs->trans("ApiClassFile").' : <strong class="wordbreak">'.(dol_is_file($realpathtoapi) ? '' : '<strike><span class="opacitymedium">').preg_replace('/^'.strtolower($module).'\//', '', $pathtoapi).(dol_is_file($realpathtoapi) ? '' : '</span></strike>').'</strong>';
4692 if (dol_is_file($realpathtoapi)) {
4693 $file = file_get_contents($realpathtoapi);
4694 if (preg_match('/var '.$tabobj.'\s+([^\s]*)\s/ims', $file, $objs)) {
4695 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>';
4696 print ' ';
4697 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>';
4698 print $form->textwithpicto('', $langs->trans("InfoForApiFile"), 1, 'warning');
4699 print ' &nbsp; ';
4700 // Comparing to null (phan considers $modulelowercase can be null here)
4701 if (!isModEnabled($modulelowercase)) { // If module is not activated
4702 print '<a href="#" class="classfortooltip" target="apiexplorer" title="'.$langs->trans("ModuleMustBeEnabled", $module).'"><strike>'.$langs->trans("ApiExplorer").'</strike></a>';
4703 } else {
4704 print '<a href="'.DOL_URL_ROOT.'/api/index.php/explorer/" target="apiexplorer">'.$langs->trans("ApiExplorer").'</a>';
4705 }
4706 } else {
4707 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>';
4708 }
4709 } else {
4710 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>';
4711 }
4712 // PHPUnit
4713 print '<br>';
4714 print '<span class="fa fa-file"></span> '.$langs->trans("TestClassFile").' : <strong class="wordbreak">'.(dol_is_file($realpathtophpunit) ? '' : '<strike><span class="opacitymedium">').preg_replace('/^'.strtolower($module).'\//', '', $pathtophpunit).(dol_is_file($realpathtophpunit) ? '' : '</span></strike>').'</strong>';
4715 if (dol_is_file($realpathtophpunit)) {
4716 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>';
4717 print ' ';
4718 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>';
4719 } else {
4720 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>';
4721 }
4722 print '<br>';
4723
4724 print '<br>';
4725
4726 print '<span class="fa fa-file"></span> '.$langs->trans("PageForLib").' : <strong class="wordbreak">'.(dol_is_file($realpathtolib) ? '' : '<strike>').preg_replace('/^'.strtolower($module).'\//', '', $pathtolib).(dol_is_file($realpathtolib) ? '' : '</strike>').'</strong>';
4727 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>';
4728 print '<br>';
4729 print '<span class="fa fa-file"></span> '.$langs->trans("PageForObjLib").' : <strong class="wordbreak">'.(dol_is_file($realpathtoobjlib) ? '' : '<strike>').preg_replace('/^'.strtolower($module).'\//', '', $pathtoobjlib).(dol_is_file($realpathtoobjlib) ? '' : '</strike>').'</strong>';
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($pathtoobjlib).'">'.img_picto($langs->trans("Edit"), 'edit').'</a>';
4731 print '<br>';
4732
4733 print '<br>';
4734 print '<span class="fa fa-file"></span> '.$langs->trans("SqlFile").' : <strong class="wordbreak">'.(dol_is_file($realpathtosql) ? '' : '<strike>').preg_replace('/^'.strtolower($module).'\//', '', $pathtosql).(dol_is_file($realpathtosql) ? '' : '</strike>').'</strong>';
4735 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>';
4736 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>';
4737 //print ' &nbsp; <a href="'.$_SERVER["PHP_SELF"].'">'.$langs->trans("RunSql").'</a>';
4738 print '<br>';
4739 print '<span class="fa fa-file"></span> '.$langs->trans("SqlFileKey").' : <strong class="wordbreak">'.(dol_is_file($realpathtosqlkey) ? '' : '<strike>').preg_replace('/^'.strtolower($module).'\//', '', $pathtosqlkey).(dol_is_file($realpathtosqlkey) ? '' : '</strike>').'</strong>';
4740 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>';
4741 //print ' &nbsp; <a href="'.$_SERVER["PHP_SELF"].'">'.$langs->trans("RunSql").'</a>';
4742 print '<br>';
4743 if (!empty($tmpobject->isextrafieldmanaged)) {
4744 print '<span class="fa fa-file"></span> '.$langs->trans("SqlFileExtraFields").' : <strong class="wordbreak">'.(dol_is_file($realpathtosqlextra) ? '' : '<strike><span class="opacitymedium">').preg_replace('/^'.strtolower($module).'\//', '', $pathtosqlextra).(dol_is_file($realpathtosqlextra) && dol_is_file($realpathtosqlextrakey) ? '' : '</span></strike>').'</strong>';
4745 if (dol_is_file($realpathtosqlextra) && dol_is_file($realpathtosqlextrakey)) {
4746 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>';
4747 print ' ';
4748 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>';
4749 print ' &nbsp; ';
4750 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>';
4751 } else {
4752 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>';
4753 }
4754
4755 //print ' &nbsp; <a href="'.$_SERVER["PHP_SELF"].'">'.$langs->trans("RunSql").'</a>';
4756 print '<br>';
4757 print '<span class="fa fa-file"></span> '.$langs->trans("SqlFileKeyExtraFields").' : <strong class="wordbreak">'.(dol_is_file($realpathtosqlextrakey) ? '' : '<strike><span class="opacitymedium">').preg_replace('/^'.strtolower($module).'\//', '', $pathtosqlextrakey).(dol_is_file($realpathtosqlextra) && dol_is_file($realpathtosqlextrakey) ? '' : '</span></strike>').'</strong>';
4758 if (dol_is_file($realpathtosqlextra) && dol_is_file($realpathtosqlextrakey)) {
4759 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>';
4760 print ' ';
4761 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>';
4762 } else {
4763 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>';
4764 }
4765 print '<br>';
4766 }
4767 print '</div>';
4768
4769 print '<div class="fichehalfleft smallxxxx">';
4770 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('/^'.strtolower($module).'\//', '', $pathtolist).(dol_is_file($realpathtolist) ? '' : '</span></strike>').'</a></strong>';
4771 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>';
4772 print '<br>';
4773 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('/^'.strtolower($module).'\//', '', $pathtocard).(dol_is_file($realpathtocard) ? '' : '</strike>').'?action=create</a></strong>';
4774 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>';
4775 print '<br>';
4776 // Page contact
4777 print '<span class="fa fa-file"></span> '.$langs->trans("PageForContactTab").' : <strong class="wordbreak">'.(dol_is_file($realpathtocontact) ? '' : '<strike><span class="opacitymedium">').preg_replace('/^'.strtolower($module).'\//', '', $pathtocontact).(dol_is_file($realpathtocontact) ? '' : '</span></strike>').'</strong>';
4778 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>';
4779 if (dol_is_file($realpathtocontact)) {
4780 print ' ';
4781 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>';
4782 } else {
4783 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>';
4784 }
4785 print '<br>';
4786 // Page document
4787 print '<span class="fa fa-file"></span> '.$langs->trans("PageForDocumentTab").' : <strong class="wordbreak">'.(dol_is_file($realpathtodocument) ? '' : '<strike><span class="opacitymedium">').preg_replace('/^'.strtolower($module).'\//', '', $pathtodocument).(dol_is_file($realpathtodocument) ? '' : '</span></strike>').'</strong>';
4788 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>';
4789 if (dol_is_file($realpathtodocument)) {
4790 print ' ';
4791 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>';
4792 } else {
4793 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>';
4794 }
4795 print '<br>';
4796 // Page notes
4797 print '<span class="fa fa-file"></span> '.$langs->trans("PageForNoteTab").' : <strong class="wordbreak">'.(dol_is_file($realpathtonote) ? '' : '<strike><span class="opacitymedium">').preg_replace('/^'.strtolower($module).'\//', '', $pathtonote).(dol_is_file($realpathtonote) ? '' : '</span></strike>').'</strong>';
4798 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>';
4799 if (dol_is_file($realpathtonote)) {
4800 print ' ';
4801 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>';
4802 } else {
4803 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>';
4804 }
4805 print '<br>';
4806 // Page agenda
4807 print '<span class="fa fa-file"></span> '.$langs->trans("PageForAgendaTab").' : <strong class="wordbreak">'.(dol_is_file($realpathtoagenda) ? '' : '<strike><span class="opacitymedium">').preg_replace('/^'.strtolower($module).'\//', '', $pathtoagenda).(dol_is_file($realpathtoagenda) ? '' : '</span></strike>').'</strong>';
4808 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>';
4809 if (dol_is_file($realpathtoagenda)) {
4810 print ' ';
4811 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>';
4812 } else {
4813 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>';
4814 }
4815 print '<br>';
4816 print '<br>';
4817
4818 print '</div>';
4819
4820 print '<br><br><br>';
4821
4822 if (!empty($tmpobject)) {
4823 $reflector = new ReflectionClass($tabobj);
4824 $reflectorproperties = $reflector->getProperties(); // Can also use get_object_vars
4825 $reflectorpropdefault = $reflector->getDefaultProperties(); // Can also use get_object_vars
4826 //$propstat = $reflector->getStaticProperties();
4827 //var_dump($reflectorpropdefault);
4828
4829 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
4830 print '<input type="hidden" name="token" value="'.newToken().'">';
4831 print '<input type="hidden" name="action" value="addproperty">';
4832 print '<input type="hidden" name="tab" value="objects">';
4833 print '<input type="hidden" name="page_y" value="">';
4834 print '<input type="hidden" name="module" value="'.dol_escape_htmltag($module.($forceddirread ? '@'.$dirread : '')).'">';
4835 print '<input type="hidden" name="tabobj" value="'.dol_escape_htmltag($tabobj).'">';
4836
4837 print '<input class="button smallpaddingimp" type="submit" name="regenerateclasssql" value="'.$langs->trans("RegenerateClassAndSql").'">';
4838 print '<br><br class="clearboth">';
4839 print '<br class="clearboth">';
4840
4841 $mod = strtolower($module);
4842 $obj = strtolower($tabobj);
4843 $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));
4844 $nbOfProperties = count($reflectorpropdefault['fields']);
4845
4846 print_barre_liste($langs->trans("ObjectProperties"), 0, $_SERVER["PHP_SELF"], '', '', '', '', 0, $nbOfProperties, '', 0, $newproperty, 'margintoponly', 0, 0, 0, 1);
4847
4848 //var_dump($reflectorpropdefault);exit;
4849 print '<!-- Table with properties of object -->'."\n";
4850 print '<div class="div-table-responsive">';
4851 print '<table class="noborder small">';
4852 print '<tr class="liste_titre">';
4853 if (!empty($conf->main_checkbox_left_column)) {
4854 print '<th class="tdstickyright tdstickyghostwhite"></th>';
4855 }
4856 print '<th class="tdsticky tdstickygray">';
4857 $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>';
4858 print $form->textwithpicto($langs->trans("Code"), $htmltext, 1, 'help', 'extracss', 0, 3, 'propertyhelp');
4859 print '</th>';
4860 print '<th>';
4861 print $form->textwithpicto($langs->trans("Label"), $langs->trans("YouCanUseTranslationKey"));
4862 print '</th>';
4863 print '<th>'.$form->textwithpicto($langs->trans("Type"), $langs->trans("TypeOfFieldsHelpIntro").'<br><br>'.$langs->trans("TypeOfFieldsHelp"), 1, 'help', 'extracss', 0, 3, 'typehelp').'</th>';
4864 print '<th>'.$form->textwithpicto($langs->trans("ArrayOfKeyValues"), $langs->trans("ArrayOfKeyValuesDesc")).'</th>';
4865 print '<th class="center">'.$form->textwithpicto($langs->trans("NotNull"), $langs->trans("NotNullDesc")).'</th>';
4866 print '<th class="center">'.$langs->trans("DefaultValue").'</th>';
4867 print '<th class="center">'.$langs->trans("DatabaseIndex").'</th>';
4868 print '<th class="center">'.$form->textwithpicto($langs->trans("ForeignKey"), $langs->trans("ForeignKeyDesc"), 1, 'help', 'extracss', 0, 3, 'foreignkeyhelp').'</th>';
4869 print '<th class="right">'.$langs->trans("Position").'</th>';
4870 print '<th class="center">'.$form->textwithpicto($langs->trans("Enabled"), $langs->trans("EnabledDesc"), 1, 'help', 'extracss', 0, 3, 'enabledhelp').'</th>';
4871 print '<th class="center">'.$form->textwithpicto($langs->trans("Visibility"), $langs->trans("VisibleDesc").'<br><br>'.$langs->trans("ItCanBeAnExpression"), 1, 'help', 'extracss', 0, 3, 'visiblehelp').'</th>';
4872 print '<th class="center">'.$langs->trans("NotEditable").'</th>';
4873 //print '<th class="center">'.$langs->trans("AlwaysEditable").'</th>';
4874 print '<th class="center">'.$form->textwithpicto($langs->trans("SearchAll"), $langs->trans("SearchAllDesc")).'</th>';
4875 print '<th class="center">'.$form->textwithpicto($langs->trans("IsAMeasure"), $langs->trans("IsAMeasureDesc")).'</th>';
4876 print '<th class="center">'.$langs->trans("CSSClass").'</th>';
4877 print '<th class="center">'.$langs->trans("CSSViewClass").'</th>';
4878 print '<th class="center">'.$langs->trans("CSSListClass").'</th>';
4879 print '<th>'.$langs->trans("KeyForTooltip").'</th>';
4880 print '<th class="center">'.$langs->trans("ShowOnCombobox").'</th>';
4881 //print '<th class="center">'.$langs->trans("Disabled").'</th>';
4882 print '<th>'.$form->textwithpicto($langs->trans("Validate"), $langs->trans("ValidateModBuilderDesc")).'</th>';
4883 print '<th>'.$langs->trans("Comment").'</th>';
4884 if (empty($conf->main_checkbox_left_column)) {
4885 print '<th class="tdstickyright tdstickyghostwhite"></th>';
4886 }
4887 print '</tr>';
4888
4889 // We must use $reflectorpropdefault['fields'] to get list of fields because $tmpobject->fields may have been
4890 // modified during the constructor and we want value into head of class before constructor is called.
4891 //$properties = dol_sort_array($tmpobject->fields, 'position');
4892 $properties = dol_sort_array($reflectorpropdefault['fields'], 'position');
4893 if (!empty($properties)) {
4894 // List of existing properties
4895 foreach ($properties as $propkey => $propval) {
4896 /* If from Reflection
4897 if ($propval->class == $tabobj)
4898 {
4899 $propname=$propval->getName();
4900 $comment=$propval->getDocComment();
4901 $type=gettype($tmpobject->$propname);
4902 $default=$propdefault[$propname];
4903 // Discard generic properties
4904 if (in_array($propname, array('element', 'childtables', 'table_element', 'table_element_line', 'class_element_line', 'ismultientitymanaged'))) continue;
4905
4906 // Keep or not lines
4907 if (in_array($propname, array('fk_element', 'lines'))) continue;
4908 }*/
4909
4910 $propname = $propkey;
4911 $proplabel = $propval['label'];
4912 $proptype = $propval['type'];
4913 $proparrayofkeyval = !empty($propval['arrayofkeyval']) ? $propval['arrayofkeyval'] : '';
4914 $propnotnull = !empty($propval['notnull']) ? $propval['notnull'] : '0';
4915 $propdefault = !empty($propval['default']) ? $propval['default'] : '';
4916 $propindex = !empty($propval['index']) ? $propval['index'] : '';
4917 $propforeignkey = !empty($propval['foreignkey']) ? $propval['foreignkey'] : '';
4918 $propposition = $propval['position'];
4919 $propenabled = $propval['enabled'];
4920 $propvisible = $propval['visible'];
4921 $propnoteditable = !empty($propval['noteditable']) ? $propval['noteditable'] : 0;
4922 //$propalwayseditable = !empty($propval['alwayseditable'])?$propval['alwayseditable']:0;
4923 $propsearchall = !empty($propval['searchall']) ? $propval['searchall'] : 0;
4924 $propisameasure = !empty($propval['isameasure']) ? $propval['isameasure'] : 0;
4925 $propcss = !empty($propval['css']) ? $propval['css'] : '';
4926 $propcssview = !empty($propval['cssview']) ? $propval['cssview'] : '';
4927 $propcsslist = !empty($propval['csslist']) ? $propval['csslist'] : '';
4928 $prophelp = !empty($propval['help']) ? $propval['help'] : '';
4929 $propshowoncombobox = !empty($propval['showoncombobox']) ? $propval['showoncombobox'] : 0;
4930 //$propdisabled=$propval['disabled'];
4931 $propvalidate = !empty($propval['validate']) ? $propval['validate'] : 0;
4932 $propcomment = !empty($propval['comment']) ? $propval['comment'] : '';
4933
4934 print '<!-- line for object property -->'."\n";
4935 print '<tr class="oddeven">';
4936
4937 if (!empty($conf->main_checkbox_left_column)) {
4938 if ($action == 'editproperty' && $propname == $propertykey) {
4939 print '<td class="center minwidth75 tdstickyright tdstickyghostwhite">';
4940 print '<input class="reposition button smallpaddingimp" type="submit" name="edit" value="'.$langs->trans("Save").'">';
4941 print '<input class="reposition button button-cancel smallpaddingimp" type="submit" name="cancel" value="'.$langs->trans("Cancel").'">';
4942 print '</td>';
4943 } else {
4944 print '<td class="center minwidth75 tdstickyright tdstickyghostwhite">';
4945 if ($propname != 'rowid') {
4946 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>';
4947 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>';
4948 }
4949 print '</td>';
4950 }
4951 }
4952 print '<td class="tdsticky tdstickygray">';
4953 print dol_escape_htmltag($propname);
4954 print '</td>';
4955 if ($action == 'editproperty' && $propname == $propertykey) {
4956 print '<td>';
4957 print '<input type="hidden" name="propname" value="'.dol_escape_htmltag($propname).'">';
4958 print '<input name="proplabel" class="maxwidth125" value="'.dol_escape_htmltag($proplabel).'">';
4959 print '</td>';
4960 print '<td class="tdoverflowmax150">';
4961 print '<input name="proptype" id="proptype" class="maxwidth125" value="'.dol_escape_htmltag($proptype).'" list="datalistproptype"></input>';
4962 // Use the samedatalist than for create
4963 print '<datalist id="datalistproptype">';
4964 print '<option>varchar(128)</option>';
4965 print '<option>email</option>';
4966 print '<option>phone</option>';
4967 print '<option>ip</option>';
4968 print '<option>url</option>';
4969 print '<option>password</option>';
4970 print '<option>text</option>';
4971 print '<option>html</option>';
4972 print '<option>date</option>';
4973 print '<option>datetime</option>';
4974 print '<option>integer</option>';
4975 print '<option>stars(5)</option>';
4976 print '<option>double(28,4)</option>';
4977 print '<option>real</option>';
4978 print '<option>integer:ClassName:RelativePath/To/ClassFile.class.php[:1[:FILTER]]</option>';
4979 // Combo with list of fields
4980 /*
4981 if (empty($formadmin)) {
4982 include_once DOL_DOCUMENT_ROOT.'/core/class/html.formadmin.class.php';
4983 $formadmin = new FormAdmin($db);
4984 }
4985 print $formadmin->selectTypeOfFields($key, GETPOST($key, 'alpha'));
4986 */
4987 print '</datalist>';
4988
4989 print '</td>';
4990 print '<td class="tdoverflowmax200">';
4991 print '<textarea name="proparrayofkeyval">';
4992 if (isset($proparrayofkeyval)) {
4993 if (is_array($proparrayofkeyval) || $proparrayofkeyval != '') {
4994 print dol_escape_htmltag(json_encode($proparrayofkeyval, JSON_UNESCAPED_UNICODE));
4995 }
4996 }
4997 print '</textarea>';
4998 print '</td>';
4999 print '<td>';
5000 print '<input class="center width50" name="propnotnull" value="'.dol_escape_htmltag($propnotnull).'">';
5001 print '</td>';
5002 print '<td>';
5003 print '<input class="maxwidth50" name="propdefault" value="'.dol_escape_htmltag($propdefault).'">';
5004 print '</td>';
5005 print '<td class="center">';
5006 print '<input class="center maxwidth50" name="propindex" value="'.dol_escape_htmltag($propindex).'">';
5007 print '</td>';
5008 print '<td>';
5009 print '<input class="center maxwidth100" name="propforeignkey" value="'.dol_escape_htmltag($propforeignkey).'">';
5010 print '</td>';
5011 print '<td>';
5012 print '<input class="right width50" name="propposition" value="'.dol_escape_htmltag($propposition).'">';
5013 print '</td>';
5014 print '<td>';
5015 print '<input class="center width75" name="propenabled" value="'.dol_escape_htmltag($propenabled).'">';
5016 print '</td>';
5017 print '<td>';
5018 print '<input class="center width75" name="propvisible" value="'.dol_escape_htmltag($propvisible).'">';
5019 print '</td>';
5020 print '<td>';
5021 print '<input class="center width50" name="propnoteditable" size="2" value="'.dol_escape_htmltag($propnoteditable).'">';
5022 print '</td>';
5023 /*print '<td>';
5024 print '<input class="center" name="propalwayseditable" size="2" value="'.dol_escape_htmltag($propalwayseditable).'">';
5025 print '</td>';*/
5026 print '<td>';
5027 print '<input class="center width50" name="propsearchall" value="'.dol_escape_htmltag($propsearchall).'">';
5028 print '</td>';
5029 print '<td>';
5030 print '<input class="center width50" name="propisameasure" value="'.dol_escape_htmltag($propisameasure).'">';
5031 print '</td>';
5032 print '<td>';
5033 print '<input class="center maxwidth50" name="propcss" value="'.dol_escape_htmltag($propcss).'">';
5034 print '</td>';
5035 print '<td>';
5036 print '<input class="center maxwidth50" name="propcssview" value="'.dol_escape_htmltag($propcssview).'">';
5037 print '</td>';
5038 print '<td>';
5039 print '<input class="center maxwidth50" name="propcsslist" value="'.dol_escape_htmltag($propcsslist).'">';
5040 print '</td>';
5041 print '<td>';
5042 print '<input class="maxwidth100" name="prophelp" value="'.dol_escape_htmltag($prophelp).'">';
5043 print '</td>';
5044 print '<td>';
5045 print '<input class="center maxwidth50" name="propshowoncombobox" value="'.dol_escape_htmltag($propshowoncombobox).'">';
5046 print '</td>';
5047 print '<td>';
5048 print '<input type="number" step="1" min="0" max="1" class="text maxwidth100" name="propvalidate" value="'.dol_escape_htmltag($propvalidate).'">';
5049 print '</td>';
5050 print '<td>';
5051 print '<input class="maxwidth100" name="propcomment" value="'.dol_escape_htmltag($propcomment).'">';
5052 print '</td>';
5053 if (empty($conf->main_checkbox_left_column)) {
5054 print '<td class="center minwidth75 tdstickyright tdstickyghostwhite">';
5055 print '<input class="reposition button smallpaddingimp" type="submit" name="edit" value="'.$langs->trans("Save").'">';
5056 print '<input class="reposition button button-cancel smallpaddingimp" type="submit" name="cancel" value="'.$langs->trans("Cancel").'">';
5057 print '</td>';
5058 }
5059 } else {
5060 print '<td class="tdoverflowmax200" title="'.dol_escape_htmltag($proplabel).'">';
5061 print dol_escape_htmltag($proplabel);
5062 print '</td>';
5063 print '<td class="tdoverflowmax200">';
5064 $pictoType = '';
5065 $matches = array();
5066 if (preg_match('/^varchar/', $proptype, $matches)) {
5067 $pictoType = 'varchar';
5068 } elseif (preg_match('/^integer:/', $proptype, $matches)) {
5069 $pictoType = 'link';
5070 } elseif (strpos($proptype, 'integer') === 0) {
5071 $pictoType = substr($proptype, 0, 3);
5072 } elseif (strpos($proptype, 'timestamp') === 0) {
5073 $pictoType = 'datetime';
5074 } elseif (strpos($proptype, 'real') === 0) {
5075 $pictoType = 'double';
5076 } elseif (strpos($proptype, 'stars') === 0) {
5077 $pictoType = 'stars';
5078 }
5079 print(!empty($pictoType) ? getPictoForType($pictoType) : getPictoForType($proptype)).'<span title="'.dol_escape_htmltag($proptype).'">'.dol_escape_htmltag($proptype).'</span>';
5080 print '</td>';
5081 print '<td class="tdoverflowmax200">';
5082 if ($proparrayofkeyval) {
5083 print '<span title="'.dol_escape_htmltag(json_encode($proparrayofkeyval, JSON_UNESCAPED_UNICODE)).'">';
5084 print dol_escape_htmltag(json_encode($proparrayofkeyval, JSON_UNESCAPED_UNICODE));
5085 print '</span>';
5086 }
5087 print '</td>';
5088 print '<td class="center">';
5089 print dol_escape_htmltag($propnotnull);
5090 print '</td>';
5091 print '<td>';
5092 print dol_escape_htmltag($propdefault);
5093 print '</td>';
5094 print '<td class="center">';
5095 print $propindex ? '1' : '';
5096 print '</td>';
5097 print '<td class="center">';
5098 print $propforeignkey ? dol_escape_htmltag($propforeignkey) : '';
5099 print '</td>';
5100 print '<td class="right">';
5101 print dol_escape_htmltag($propposition);
5102 print '</td>';
5103 print '<td class="center tdoverflowmax100" title="'.($propnoteditable ? dol_escape_htmltag($propnoteditable) : '').'">';
5104 print $propenabled ? dol_escape_htmltag($propenabled) : '';
5105 print '</td>';
5106 // Visibility
5107 print '<td class="center tdoverflowmax100" title="'.($propvisible ? dol_escape_htmltag($propvisible) : '0').'">';
5108 print $propvisible ? dol_escape_htmltag($propvisible) : '0';
5109 print '</td>';
5110 // Readonly
5111 print '<td class="center tdoverflowmax100" title="'.($propnoteditable ? dol_escape_htmltag($propnoteditable) : '').'">';
5112 print $propnoteditable ? dol_escape_htmltag($propnoteditable) : '';
5113 print '</td>';
5114 /*print '<td class="center">';
5115 print $propalwayseditable ? dol_escape_htmltag($propalwayseditable) : '';
5116 print '</td>';*/
5117 print '<td class="center">';
5118 print $propsearchall ? '1' : '';
5119 print '</td>';
5120 print '<td class="center">';
5121 print $propisameasure ? dol_escape_htmltag($propisameasure) : '';
5122 print '</td>';
5123 print '<td class="center tdoverflowmax100" title="'.($propcss ? dol_escape_htmltag($propcss) : '').'">';
5124 print $propcss ? dol_escape_htmltag($propcss) : '';
5125 print '</td>';
5126 print '<td class="center tdoverflowmax100" title="'.($propcssview ? dol_escape_htmltag($propcssview) : '').'">';
5127 print $propcssview ? dol_escape_htmltag($propcssview) : '';
5128 print '</td>';
5129 print '<td class="center tdoverflowmax100" title="'.($propcsslist ? dol_escape_htmltag($propcsslist) : '').'">';
5130 print $propcsslist ? dol_escape_htmltag($propcsslist) : '';
5131 print '</td>';
5132 // Key for tooltop
5133 print '<td class="tdoverflowmax150" title="'.($prophelp ? dol_escape_htmltag($prophelp) : '').'">';
5134 print $prophelp ? dol_escape_htmltag($prophelp) : '';
5135 print '</td>';
5136 print '<td class="center">';
5137 print $propshowoncombobox ? dol_escape_htmltag($propshowoncombobox) : '';
5138 print '</td>';
5139 /*print '<td class="center">';
5140 print $propdisabled?$propdisabled:'';
5141 print '</td>';*/
5142 print '<td class="center">';
5143 print $propvalidate ? dol_escape_htmltag($propvalidate) : '';
5144 print '</td>';
5145 print '<td class="tdoverflowmax200">';
5146 print '<span title="'.dol_escape_htmltag($propcomment).'">';
5147 print dol_escape_htmltag($propcomment);
5148 print '</span>';
5149 print '</td>';
5150 if (empty($conf->main_checkbox_left_column)) {
5151 print '<td class="center minwidth75 tdstickyright tdstickyghostwhite">';
5152 if ($propname != 'rowid') {
5153 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>';
5154 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>';
5155 }
5156 print '</td>';
5157 }
5158 }
5159 print '</tr>';
5160 }
5161 } else {
5162 if ($tab == 'specifications') {
5163 if ($action != 'editfile' || empty($file)) {
5164 print '<span class="opacitymedium">'.$langs->trans("SpecDefDesc").'</span><br>';
5165 print '<br>';
5166
5167 $specs = dol_dir_list(dol_buildpath($modulelowercase.'/doc', 0), 'files', 1, '(\.md|\.asciidoc)$', array('\/temp\/'));
5168
5169 foreach ($specs as $spec) {
5170 $pathtofile = $modulelowercase.'/doc/'.$spec['relativename'];
5171 $format = 'asciidoc';
5172 if (preg_match('/\.md$/i', $spec['name'])) {
5173 $format = 'markdown';
5174 }
5175 print '<span class="fa fa-file"></span> '.$langs->trans("SpecificationFile").' : <strong class="wordbreak">'.$pathtofile.'</strong>';
5176 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>';
5177 print '<br>';
5178 }
5179 } else {
5180 // Use MD or asciidoc
5181
5182 //print $langs->trans("UseAsciiDocFormat").'<br>';
5183
5184 $fullpathoffile = dol_buildpath($file, 0);
5185
5186 $content = file_get_contents($fullpathoffile);
5187
5188 // New module
5189 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
5190 print '<input type="hidden" name="token" value="'.newToken().'">';
5191 print '<input type="hidden" name="action" value="savefile">';
5192 print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
5193 print '<input type="hidden" name="tab" value="'.$tab.'">';
5194 print '<input type="hidden" name="module" value="'.$module.'">';
5195
5196 $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%');
5197 print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'html'));
5198 print '<br>';
5199 print '<center>';
5200 print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
5201 print ' &nbsp; ';
5202 print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
5203 print '</center>';
5204
5205 print '</form>';
5206 }
5207 }
5208 $langs->load("errors");
5209 print '<tr><td><span class="warning">'.$langs->trans('ErrorModuleBuilderNoFieldProperty').'</warning></td></tr>';
5210 }
5211 print '</table>';
5212 print '</div>';
5213
5214 print '</form>';
5215 } else {
5216 $langs->load("errors");
5217 print '<span class="warning">'.$langs->trans('ErrorModuleBuilderFailedToInit', $tabobj, (string) $db).'</warning>';
5218 }
5219 } catch (Exception $e) {
5220 print 'ee';
5221 print $e->getMessage();
5222 print 'ff';
5223 }
5224 } else {
5225 if (empty($forceddirread)) {
5226 $fullpathoffile = dol_buildpath($file, 0);
5227 } else {
5228 $fullpathoffile = $dirread.'/'.$file;
5229 }
5230
5231 $content = file_get_contents($fullpathoffile);
5232
5233 // New module
5234 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
5235 print '<input type="hidden" name="token" value="'.newToken().'">';
5236 print '<input type="hidden" name="action" value="savefile">';
5237 print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
5238 print '<input type="hidden" name="tab" value="'.$tab.'">';
5239 print '<input type="hidden" name="tabobj" value="'.dol_escape_htmltag($tabobj).'">';
5240 print '<input type="hidden" name="module" value="'.$module.($forceddirread ? '@'.$dirread : '').'">';
5241
5242 $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%');
5243 print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'html'));
5244 print '<br>';
5245 print '<center>';
5246 print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
5247 print ' &nbsp; ';
5248 print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
5249 print '</center>';
5250
5251 print '</form>';
5252 }
5253 }
5254
5255 print dol_get_fiche_end(); // Level 3
5256 }
5257
5258 if ($tab == 'dictionaries') {
5259 print '<!-- tab=dictionaries -->'."\n";
5260 $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
5261
5262 $dicts = $moduleobj->dictionaries;
5263
5264 if ($action == 'deletedict') {
5265 $formconfirm = $form->formconfirm(
5266 $_SERVER["PHP_SELF"].'?dictionnarykey='.urlencode((string) (GETPOSTINT('dictionnarykey'))).'&tab='.urlencode((string) ($tab)).'&module='.urlencode((string) ($module)),
5267 $langs->trans('Delete'),
5268 $langs->trans('Confirm Delete Dictionnary', GETPOST('dictionnarykey', 'alpha')),
5269 'confirm_deletedictionary',
5270 '',
5271 0,
5272 1
5273 );
5274 print $formconfirm;
5275 }
5276
5277 if ($action != 'editfile' || empty($file)) {
5278 print '<span class="opacitymedium">';
5279 $htmlhelp = $langs->trans("DictionariesDefDescTooltip", '{s1}');
5280 $htmlhelp = str_replace('{s1}', '<a target="adminbis" class="nofocusvisible" href="'.DOL_URL_ROOT.'/admin/dict.php">'.$langs->trans('Setup').' - '.$langs->trans('Dictionaries').'</a>', $htmlhelp);
5281 print $form->textwithpicto($langs->trans("DictionariesDefDesc"), $htmlhelp, 1, 'help', '', 0, 2, 'helpondesc').'<br>';
5282 print '</span>';
5283 print '<br>';
5284
5285 print '<span class="fa fa-file"></span> '.$langs->trans("DescriptorFile").' : <strong class="wordbreak">'.$pathtofile.'</strong>';
5286 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>';
5287 print '<br>';
5288 if (is_array($dicts) && !empty($dicts)) {
5289 print '<span class="fa fa-file"></span> '.$langs->trans("LanguageFile").' :</span> ';
5290 print '<strong class="wordbreak">'.$dicts['langs'].'</strong>';
5291 print '<br>';
5292 }
5293 print '<br>';
5294
5295 $head3 = array();
5296 $h = 0;
5297
5298 // Dir for module
5299 //$dir = $dirread.'/'.$modulelowercase.'/class';
5300
5301 $head3[$h][0] = $_SERVER["PHP_SELF"].'?tab=dictionaries&module='.$module.($forceddirread ? '@'.$dirread : '').'&tabdic=newdictionary';
5302 $head3[$h][1] = '<span class="valignmiddle text-plus-circle">'.$langs->trans("NewDictionary").'</span><span class="fa fa-plus-circle valignmiddle paddingleft"></span>';
5303 $head3[$h][2] = 'newdictionary';
5304 $h++;
5305
5306 // Scan for object class files
5307 //$listofobject = dol_dir_list($dir, 'files', 0, '\.class\.php$');
5308
5309 $firstdicname = '';
5310 // if (!empty($dicts['tabname'])) {
5311 // foreach ($dicts['tabname'] as $key => $dic) {
5312 // $dicname = $dic;
5313 // $diclabel = $dicts['tablib'][$key];
5314
5315 // if (empty($firstdicname)) {
5316 // $firstdicname = $dicname;
5317 // }
5318
5319 // $head3[$h][0] = $_SERVER["PHP_SELF"].'?tab=dictionaries&module='.$module.($forceddirread ? '@'.$dirread : '').'&tabdic='.$dicname;
5320 // $head3[$h][1] = $diclabel;
5321 // $head3[$h][2] = $dicname;
5322 // $h++;
5323 // }
5324 // }
5325
5326 // if ($h > 1) {
5327 // $head3[$h][0] = $_SERVER["PHP_SELF"].'?tab=dictionaries&module='.$module.($forceddirread ? '@'.$dirread : '').'&tabdic=deletedictionary';
5328 // $head3[$h][1] = $langs->trans("DangerZone");
5329 // $head3[$h][2] = 'deletedictionary';
5330 // $h++;
5331 // }
5332
5333 // 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.
5334 // if ($tabdic == 'newdicifnodic') {
5335 // if ($firstdicname) {
5336 // $tabdic = $firstdicname;
5337 // } else {
5338 // $tabdic = 'newdictionary';
5339 // }
5340 // }
5341 //print dol_get_fiche_head($head3, $tabdic, '', -1, ''); // Level 3
5342
5343
5344 $newdict = dolGetButtonTitle($langs->trans('NewDictionary'), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/modulebuilder/index.php?tab=dictionaries&module='.urlencode($module).'&tabdic=newdictionary');
5345 print_barre_liste($langs->trans("ListOfDictionariesEntries"), 0, $_SERVER["PHP_SELF"], '', '', '', '', 0, '', '', 0, $newdict, '', 0, 0, 0, 1);
5346
5347 if ($tabdic != 'newdictionary') {
5348 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
5349 print '<input type="hidden" name="token" value="'.newToken().'">';
5350 print '<input type="hidden" name="action" value="addDictionary">';
5351 print '<input type="hidden" name="tab" value="dictionaries">';
5352 print '<input type="hidden" name="module" value="'.dol_escape_htmltag($module).'">';
5353 print '<input type="hidden" name="tabdic" value="'.dol_escape_htmltag($tabdic).'">';
5354
5355 print '<div class="div-table-responsive">';
5356 print '<table class="noborder">';
5357
5358 print '<tr class="liste_titre">';
5359 print_liste_field_titre("#", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, 'thsticky thstickygrey ');
5360 print_liste_field_titre("Table", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
5361 print_liste_field_titre("Label", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
5362 print_liste_field_titre("SQL", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
5363 print_liste_field_titre("SQLSort", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
5364 print_liste_field_titre("FieldsView", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
5365 print_liste_field_titre("FieldsEdit", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
5366 print_liste_field_titre("FieldsInsert", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
5367 print_liste_field_titre("Rowid", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
5368 print_liste_field_titre("Condition", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
5369 print_liste_field_titre("", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
5370 print "</tr>\n";
5371
5372 if (!empty($dicts) && is_array($dicts) && !empty($dicts['tabname']) && is_array($dicts['tabname'])) {
5373 $i = 0;
5374 $maxi = count($dicts['tabname']);
5375 while ($i < $maxi) {
5376 if ($action == 'editdict' && $i == GETPOSTINT('dictionnarykey') - 1) {
5377 print '<tr class="oddeven">';
5378 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
5379 print '<input type="hidden" name="token" value="'.newToken().'">';
5380 print '<input type="hidden" name="tab" value="dictionaries">';
5381 print '<input type="hidden" name="module" value="'.dol_escape_htmltag($module).'">';
5382 print '<input type="hidden" name="action" value="updatedictionary">';
5383 print '<input type="hidden" name="dictionnarykey" value="'.($i + 1).'">';
5384
5385 print '<td class="tdsticky tdstickygray">';
5386 print($i + 1);
5387 print '</td>';
5388
5389 print '<td>';
5390 print '<input type="text" name="tabname" value="'.$dicts['tabname'][$i].'" readonly class="tdstickygray">';
5391 print '</td>';
5392
5393 print '<td>';
5394 print '<input type="text" name="tablib" value="'.$dicts['tablib'][$i].'">';
5395 print '</td>';
5396
5397 print '<td>';
5398 print '<input type="text" name="tabsql" value="'.$dicts['tabsql'][$i].'" readonly class="tdstickygray">';
5399 print '</td>';
5400
5401 print '<td>';
5402 print '<select name="tabsqlsort">';
5403 print '<option value="'.dol_escape_htmltag($dicts['tabsqlsort'][$i]).'">'.$dicts['tabsqlsort'][$i].'</option>';
5404 print '</select>';
5405 print '</td>';
5406
5407 print '<td><select name="tabfield" >';
5408 print '<option value="'.dol_escape_htmltag($dicts['tabfield'][$i]).'">'.$dicts['tabfield'][$i].'</option>';
5409 print '</select></td>';
5410
5411 print '<td><select name="tabfieldvalue" >';
5412 print '<option value="'.dol_escape_htmltag($dicts['tabfieldvalue'][$i]).'">'.$dicts['tabfieldvalue'][$i].'</option>';
5413 print '</select></td>';
5414
5415 print '<td><select name="tabfieldinsert" >';
5416 print '<option value="'.dol_escape_htmltag($dicts['tabfieldinsert'][$i]).'">'.$dicts['tabfieldinsert'][$i].'</option>';
5417 print '</select></td>';
5418
5419 print '<td>';
5420 print '<input type="text" name="tabrowid" value="'.dol_escape_htmltag($dicts['tabrowid'][$i]).'" readonly class="tdstickygray">';
5421 print '</td>';
5422
5423 print '<td>';
5424 print '<input type="text" name="tabcond" value="'.dol_escape_htmltag((empty($dicts['tabcond'][$i]) ? 'disabled' : 'enabled')).'" readonly class="tdstickygray">';
5425 print '</td>';
5426
5427 print '<td class="center minwidth75 tdstickyright tdstickyghostwhite">';
5428 print '<input id ="updatedict" class="reposition button smallpaddingimp" type="submit" name="updatedict" value="'.$langs->trans("Modify").'"/>';
5429 print '<br>';
5430 print '<input class="reposition button button-cancel smallpaddingimp" type="submit" name="cancel" value="'.$langs->trans("Cancel").'"/>';
5431 print '</td>';
5432
5433 print '</form>';
5434 print '</tr>';
5435 } else {
5436 print '<tr class="oddeven">';
5437
5438 print '<td class="tdsticky tdstickygray">';
5439 print($i + 1);
5440 print '</td>';
5441
5442 print '<td>';
5443 print $dicts['tabname'][$i];
5444 print '</td>';
5445
5446 print '<td>';
5447 print $dicts['tablib'][$i];
5448 print '</td>';
5449
5450 print '<td>';
5451 print $dicts['tabsql'][$i];
5452 print '</td>';
5453
5454 print '<td>';
5455 print $dicts['tabsqlsort'][$i];
5456 print '</td>';
5457
5458 print '<td>';
5459 print $dicts['tabfield'][$i];
5460 print '</td>';
5461
5462 print '<td>';
5463 print $dicts['tabfieldvalue'][$i];
5464 print '</td>';
5465
5466 print '<td>';
5467 print $dicts['tabfieldinsert'][$i];
5468 print '</td>';
5469
5470 print '<td >';
5471 print $dicts['tabrowid'][$i];
5472 print '</td>';
5473
5474 print '<td >';
5475 print $dicts['tabcond'][$i];
5476 print '</td>';
5477
5478 print '<td class="center minwidth75 tdstickyright tdstickyghostwhite">';
5479 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>';
5480 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>';
5481 print '</td>';
5482
5483 print '</tr>';
5484 }
5485 $i++;
5486 }
5487 } else {
5488 print '<tr><td colspan="11"><span class="opacitymedium">'.$langs->trans("None").'</span></td></tr>';
5489 }
5490
5491 print '</table>';
5492 print '</div>';
5493
5494 print '</form>';
5495 }
5496
5497 if ($tabdic == 'newdictionary') {
5498 // New dic tab
5499 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
5500 print '<input type="hidden" name="token" value="'.newToken().'">';
5501 print '<input type="hidden" name="action" value="initdic">';
5502 print '<input type="hidden" name="tab" value="dictionaries">';
5503 print '<input type="hidden" name="tabdic" value="'.$tabdic.'">';
5504
5505 print '<input type="hidden" name="module" value="'.dol_escape_htmltag($module).'">';
5506
5507 print '<span class="opacitymedium">'.$langs->trans("EnterNameOfDictionaryDesc").'</span><br><br>';
5508
5509 print dol_get_fiche_head();
5510 print '<table class="border centpercent">';
5511 print '<tbody>';
5512 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>';
5513 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>';
5514 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>';
5515 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>';
5516 print '<tr><td class="titlefieldcreate">'.$langs->trans("FieldsView").'</td><td><input type="text" name="field" value="'.dol_escape_htmltag(GETPOST('field', 'alpha')).'"></td></tr>';
5517 print '<tr><td class="titlefieldcreate">'.$langs->trans("FieldsEdit").'</td><td><input type="text" name="fieldvalue" value="'.dol_escape_htmltag(GETPOST('fieldvalue', 'alpha')).'"></td></tr>';
5518 print '<tr><td class="titlefieldcreate">'.$langs->trans("FieldsInsert").'</td><td><input type="text" name="fieldinsert" value="'.dol_escape_htmltag(GETPOST('fieldinsert', 'alpha')).'"></td></tr>';
5519 print '<tr><td class="titlefieldcreate">'.$langs->trans("Rowid").'</td><td><input type="text" name="rowid" value="'.dol_escape_htmltag(GETPOST('rowid', 'alpha')).'"></td></tr>';
5520 print '<tr></tr>';
5521 print '</tbody></table>';
5522 print '<input type="submit" class="button" name="create" value="'.dol_escape_htmltag($langs->trans("GenerateCode")).'"'.($dirins ? '' : ' disabled="disabled"').'>';
5523 print '<input id="cancel" type="submit" class="button" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
5524 print dol_get_fiche_end();
5525 print '</form>';
5526 print '<script>
5527 $(document).ready(function() {
5528 $("input[name=\'dicname\']").on("blur", function() {
5529 if ($(this).val().length > 0) {
5530 $("input[name=\'label\']").val($(this).val());
5531 $("input[name=\'sql\']").val("SELECT f.rowid as rowid, f.code, f.label, f.active FROM llx_c_" + $(this).val() + " as f");
5532 $("input[name=\'sqlsort\']").val("label ASC");
5533 $("input[name=\'field\']").val("code,label");
5534 $("input[name=\'fieldvalue\']").val("code,label");
5535 $("input[name=\'fieldinsert\']").val("code,label");
5536 $("input[name=\'rowid\']").val("rowid");
5537 } else {
5538 $("input[name=\'label\']").val("");
5539 $("input[name=\'sql\']").val("");
5540 $("input[name=\'sqlsort\']").val("");
5541 $("input[name=\'field\']").val("");
5542 $("input[name=\'fieldvalue\']").val("");
5543 $("input[name=\'fieldinsert\']").val("");
5544 $("input[name=\'rowid\']").val("");
5545 }
5546 });
5547 $("input[id=\'cancel\']").click(function() {
5548 window.history.back();
5549 });
5550 });
5551 </script>';
5552
5553 /*print '<br>';
5554 print '<br>';
5555 print '<br>';
5556 print '<span class="opacitymedium">'.$langs->trans("or").'</span>';
5557 print '<br>';
5558 print '<br>';
5559 //print '<input type="checkbox" name="initfromtablecheck"> ';
5560 print $langs->trans("InitStructureFromExistingTable");
5561 print '<input type="text" name="initfromtablename" value="" placeholder="'.$langs->trans("TableName").'">';
5562 print '<input type="submit" class="button smallpaddingimp" name="createtablearray" value="'.dol_escape_htmltag($langs->trans("GenerateCode")).'"'.($dirins ? '' : ' disabled="disabled"').'>';
5563 print '<br>';
5564 */
5565 } elseif ($tabdic == 'deletedictionary') {
5566 // Delete dic tab
5567 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
5568 print '<input type="hidden" name="token" value="'.newToken().'">';
5569 print '<input type="hidden" name="action" value="confirm_deletedictionary">';
5570 print '<input type="hidden" name="tab" value="dictionaries">';
5571 print '<input type="hidden" name="module" value="'.dol_escape_htmltag($module).'">';
5572
5573 print $langs->trans("EnterNameOfDictionnaryToDeleteDesc").'<br><br>';
5574
5575 print '<input type="text" name="dicname" value="'.dol_escape_htmltag($modulename).'" placeholder="'.dol_escape_htmltag($langs->trans("DicKey")).'">';
5576 print '<input type="submit" class="button smallpaddingimp" name="delete" value="'.dol_escape_htmltag($langs->trans("Delete")).'"'.($dirins ? '' : ' disabled="disabled"').'>';
5577 print '</form>';
5578 }
5579
5580 print dol_get_fiche_end();
5581 } else {
5582 $fullpathoffile = dol_buildpath($file, 0);
5583
5584 $content = file_get_contents($fullpathoffile);
5585
5586 // New module
5587 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
5588 print '<input type="hidden" name="token" value="'.newToken().'">';
5589 print '<input type="hidden" name="action" value="savefile">';
5590 print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
5591 print '<input type="hidden" name="tab" value="'.$tab.'">';
5592 print '<input type="hidden" name="module" value="'.$module.'">';
5593
5594 $posCursor = (empty($find)) ? array() : array('find' => $find);
5595 $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%', 0, $posCursor);
5596 print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'html'));
5597 print '<br>';
5598 print '<center>';
5599 print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
5600 print ' &nbsp; ';
5601 print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
5602 print '</center>';
5603
5604 print '</form>';
5605 }
5606 }
5607
5608 if ($tab == 'menus') {
5609 print '<!-- tab=menus -->'."\n";
5610 $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
5611 $dirins = $listofmodules[strtolower($module)]['moduledescriptorrootpath'];
5612 $destdir = $dirins.'/'.strtolower($module);
5613 $listofobject = dol_dir_list($destdir.'/class', 'files', 0, '\.class\.php$');
5614 $objects = dolGetListOfObjectClasses($destdir);
5615
5616 $leftmenus = array();
5617
5618 $menus = $moduleobj->menu;
5619
5620 $permissions = $moduleobj->rights;
5621 $crud = array('read' => 'CRUDRead', 'write' => 'CRUDCreateWrite', 'delete' => 'Delete');
5622
5623 //grouped permissions
5624 $groupedRights = array();
5625 foreach ($permissions as $right) {
5626 $key = $right[4];
5627 if (!isset($groupedRights[$key])) {
5628 $groupedRights[$key] = array();
5629 }
5630 $groupedRights[$key][] = $right;
5631 }
5632 $groupedRights_json = json_encode($groupedRights);
5633
5634 if ($action == 'deletemenu') {
5635 $formconfirms = $form->formconfirm(
5636 $_SERVER["PHP_SELF"].'?menukey='.urlencode((string) (GETPOSTINT('menukey'))).'&tab='.urlencode((string) ($tab)).'&module='.urlencode((string) ($module)),
5637 $langs->trans('Delete'),
5638 ($menus[GETPOST('menukey')]['fk_menu'] === 'fk_mainmenu='.strtolower($module) ? $langs->trans('Warning: you will delete all menus linked to this one.', GETPOSTINT('menukey')) : $langs->trans('Confirm Delete Menu', GETPOSTINT('menukey'))),
5639 'confirm_deletemenu',
5640 '',
5641 0,
5642 1
5643 );
5644 print $formconfirms;
5645 }
5646 if ($action != 'editfile' || empty($file)) {
5647 print '<span class="opacitymedium">';
5648 $htmlhelp = $langs->trans("MenusDefDescTooltip", '{s1}');
5649 $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);
5650 print $form->textwithpicto($langs->trans("MenusDefDesc"), $htmlhelp, 1, 'help', '', 0, 2, 'helpondesc').'<br>';
5651 print '</span>';
5652 print '<br>';
5653
5654 // Links to editable files
5655 print '<span class="fa fa-file"></span> '.$langs->trans("DescriptorFile").' : <strong class="wordbreak">'.$pathtofile.'</strong>';
5656 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>';
5657 print '<br>';
5658
5659 // Search all files of modules mentioned by menu
5660 $listODifferentUrlsInMenu = array();
5661 foreach ($menus as $obj) {
5662 if (preg_match('/^\/'.preg_quote(strtolower($module), '/').'\//', $obj['url']) && !empty($pathoffile)) {
5663 if (!empty($listODifferentUrlsInMenu[$pathoffile])) { // Test to avoid to show same file twice.
5664 continue;
5665 }
5666 $pathtofile = $obj['url'];
5667 $listODifferentUrlsInMenu[$pathoffile] = $pathtofile;
5668 print '<span class="fa fa-file"></span> '.$langs->trans("PageLinkedByAMenuEntry").' : <strong class="wordbreak">'.$pathtofile.'</strong>';
5669 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>';
5670 print '<br>';
5671 }
5672 }
5673
5674
5675 print '<br>';
5676 print load_fiche_titre($langs->trans("ListOfMenusEntries"), '', '');
5677
5678 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
5679 print '<input type="hidden" name="token" value="'.newToken().'">';
5680 print '<input type="hidden" name="action" value="addmenu">';
5681 print '<input type="hidden" name="tab" value="menus">';
5682 print '<input type="hidden" name="module" value="'.dol_escape_htmltag($module).'">';
5683 print '<input type="hidden" name="tabobj" value="'.dol_escape_htmltag($tabobj).'">';
5684
5685 print '<div class="div-table-responsive">';
5686 print '<table class="noborder small">';
5687
5688 $htmltextenabled = '<u>'.$langs->trans("Examples").':</u><br>';
5689 $htmltextenabled .= '1 <span class="opacitymedium">(module always enabled)</span><br>';
5690 $htmltextenabled .= '0 <span class="opacitymedium">(module always disabled)</span><br>';
5691 $htmltextenabled .= 'isModEnabled(\''.dol_escape_htmltag(strtolower($module)).'\') <span class="opacitymedium">(enabled when module is enabled)</span>';
5692 $htmltextperms = '<u>'.$langs->trans("Examples").':</u><br>';
5693 $htmltextperms .= '1 <span class="opacitymedium">(access always allowed)</span><br>';
5694 $htmltextperms .= '$user->hasright(\''.dol_escape_htmltag(strtolower($module)).'\', \'myobject\', \'read\') <span class="opacitymedium">(access allowed if user has permission module->object->read)</span>';
5695
5696 print '<tr class="liste_titre">';
5697 print_liste_field_titre("#", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, 'center tdsticky tdstickygray ');
5698 print_liste_field_titre("Position", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
5699 print_liste_field_titre("Title", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, 'center');
5700 print_liste_field_titre("LinkToParentMenu", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, 'minwidth100 ');
5701 print_liste_field_titre("mainmenu", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
5702 print_liste_field_titre("leftmenu", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
5703 print_liste_field_titre("URL", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, '', $langs->transnoentitiesnoconv('DetailUrl'));
5704 print_liste_field_titre("LanguageFile", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
5705 print_liste_field_titre("Position", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, 'right ');
5706 print_liste_field_titre("Enabled", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, 'center ', $langs->trans('DetailEnabled').'<br><br>'.$htmltextenabled);
5707 print_liste_field_titre("Rights", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, '', $langs->trans('DetailRight').'<br><br>'.$htmltextperms);
5708 print_liste_field_titre("Target", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, '', $langs->trans('DetailTarget'));
5709 print_liste_field_titre("MenuForUsers", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, 'center minwidth100 ', $langs->trans('DetailUser'));
5710 print_liste_field_titre("", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, 'center ', $langs->trans(''));
5711 print "</tr>\n";
5712
5713 $r = count($menus) + 1;
5714 // for adding menu on module
5715 print '<tr>';
5716 print '<td class="center tdsticky tdstickygray"><input type="hidden" readonly class="center maxwidth50" name="propenabled" value="#"></td>';
5717 print '<td class="center">';
5718 print '<select class="maxwidth50" name="type">';
5719 print '<option value="">'.$langs->trans("........").'</option><option value="'.dol_escape_htmltag("left").'">left</option><option value="'.dol_escape_htmltag("top").'">top</option>';
5720 print '</select></td>';
5721 print '<td class="left"><input type="text" class="left maxwidth100" name="titre" value="'.dol_escape_htmltag(GETPOST('titre', 'alpha')).'"></td>';
5722 print '<td class="left">';
5723 print '<select name="fk_menu">';
5724 print '<option value="">'.$langs->trans("........").'</option>';
5725 foreach ($menus as $obj) {
5726 if ($obj['type'] == 'left' && !empty($obj['leftmenu'])) {
5727 print "<option value=".strtolower($obj['leftmenu']).">".$obj['leftmenu']."</option>";
5728 }
5729 }
5730 print '</select>';
5731 print '</td>';
5732 print '<td class="left"><input type="text" class="left maxwidth50" name="mainmenu" value="'.(empty(GETPOST('mainmenu')) ? strtolower($module) : dol_escape_htmltag(GETPOST('mainmenu', 'alpha'))).'"></td>';
5733 print '<td class="center"><input id="leftmenu" type="text" class="left maxwidth50" name="leftmenu" value="'.dol_escape_htmltag(GETPOST('leftmenu', 'alpha')).'"></td>';
5734 // URL
5735 print '<td class="left"><input id="url" type="text" class="left maxwidth100" name="url" value="'.dol_escape_htmltag(GETPOST('url', 'alpha')).'"></td>';
5736 print '<td class="left"><input type="text" class="left maxwidth75" name="langs" value="'.strtolower($module).'@'.strtolower($module).'" readonly></td>';
5737 // Position
5738 print '<td class="center"><input type="text" class="center maxwidth50 tdstickygray" name="position" value="'.(1000 + $r).'" readonly></td>';
5739 // Enabled
5740 print '<td class="center">';
5741 print '<input type="enabled" class="maxwidth125" value="'.dol_escape_htmltag(GETPOSTISSET('enabled') ? GETPOST('enabled') : 'isModEnabled(\''.$module.'\')').'">';
5742 /*
5743 print '<select class="maxwidth" name="enabled">';
5744 print '<option value="1" selected>'.$langs->trans("Show").'</option>';
5745 print '<option value="0">'.$langs->trans("Hide").'</option>';
5746 print '</select>';
5747 */
5748 print '</td>';
5749 // Perms
5750 print '<td class="left">';
5751 print '<select class="maxwidth" name="objects" id="objects">';
5752 print '<option value=""></option>';
5753 if (is_array($objects)) {
5754 foreach ($objects as $value) {
5755 print '<option value="'.strtolower($value).'">'.dol_escape_htmltag(strtolower($value)).'</option>';
5756 }
5757 }
5758 print '</select>';
5759 print '<select class="maxwidth hideobject" name="perms" id="perms">';
5760 print '</select>';
5761 print '</td>';
5762 print '<td class="center"><input type="text" class="center maxwidth50" name="target" value="'.dol_escape_htmltag(GETPOST('target', 'alpha')).'"></td>';
5763 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>';
5764
5765 print '<td class="center minwidth75 tdstickyright tdstickyghostwhite">';
5766 print '<input type="submit" class="button" name="add" value="'.$langs->trans("Add").'">';
5767 print '</td>';
5768 print '</tr>';
5769 // end form for add menu
5770
5771 //var_dump($menus);
5772
5773 // Loop on each menu entry
5774 if (count($menus)) {
5775 $i = 0;
5776 foreach ($menus as $menu) {
5777 $i++;
5778 //for get parent in menu
5779 $string = dol_escape_htmltag($menu['fk_menu']);
5780 $value = substr($string, strpos($string, 'fk_leftmenu=') + strlen('fk_leftmenu='));
5781
5782 $propFk_menu = !empty($menu['fk_menu']) ? $menu['fk_menu'] : GETPOST('fk_menu');
5783 $propTitre = !empty($menu['titre']) ? $menu['titre'] : GETPOST('titre');
5784 $propMainmenu = !empty($menu['mainmenu']) ? $menu['mainmenu'] : GETPOST('mainmenu');
5785 $propLeftmenu = !empty($menu['leftmenu']) ? $menu['leftmenu'] : GETPOST('leftmenu');
5786 $propUrl = !empty($menu['url']) ? $menu['url'] : GETPOST('url', 'alpha');
5787 $propPerms = !empty($menu['perms']) ? $menu['perms'] : GETPOST('perms');
5788 $propUser = !empty($menu['user']) ? $menu['user'] : GETPOST('user');
5789 $propTarget = !empty($menu['target']) ? $menu['target'] : GETPOST('target');
5790 $propEnabled = !empty($menu['enabled']) ? $menu['enabled'] : GETPOST('enabled');
5791
5792 $objPerms = (empty($arguments[1]) ? '' : trim($arguments[1]));
5793 $valPerms = (empty($arguments[2]) ? '' : trim($arguments[2]));
5794
5795 //$tabobject = ''; // We can't know what is $tabobject in most cases
5796
5797 if ($action == 'editmenu' && GETPOSTINT('menukey') == $i) {
5798 //var_dump($propPerms);exit;
5799 print '<tr class="oddeven">';
5800 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
5801 print '<input type="hidden" name="token" value="'.newToken().'">';
5802 print '<input type="hidden" name="action" value="update_menu">';
5803 print '<input type="hidden" name="tab" value="menus">';
5804 print '<input type="hidden" name="module" value="'.dol_escape_htmltag($module).'">';
5805 print '<input type="hidden" name="menukey" value="'.$i.'"/>';
5806 //print '<input type="hidden" name="tabobject" value="'.dol_escape_htmltag($tabobject).'">';
5807 print '<td class="tdsticky tdstickygray">';
5808 print $i;
5809 print '</td>';
5810 // Position (top, left)
5811 print '<td class="center">
5812 <select class="center maxwidth50" name="type">
5813 <option value="'.dol_escape_htmltag($menu['type']).'">
5814 '.dol_escape_htmltag($menu['type']).'
5815 </option>';
5816 print '<option value="'.($menu['type'] == 'left' ? 'top' : 'left').'">';
5817 if ($menu['type'] == 'left') {
5818 print 'top';
5819 } else {
5820 print 'left';
5821 }
5822 print '</option></select></td>';
5823 // Title
5824 print '<td><input type="text" class="left maxwidth100" name="titre" value="'.dol_escape_htmltag($propTitre).'"></td>';
5825 // Parent menu
5826 print '<td>';
5827 /*print '<select name="fk_menu" class="left maxwidth">';
5828 print '<option value="'.dol_escape_htmltag($propFk_menu).'">'.dol_escape_htmltag($value).'</option>';
5829 foreach ($menus as $obj) {
5830 if ($obj['type'] == 'left' && $obj['leftmenu'] != $value && $obj['leftmenu'] != $menu['leftmenu']) {
5831 print "<option value=".strtolower($obj['leftmenu']).">".$obj['leftmenu']."</option>";
5832 }
5833 }
5834 print '</select>';*/
5835 print '<input type="text" name="fk_menu" class="maxwidth150" value="'.dol_escape_htmltag($propFk_menu).'">';
5836 print '</td>';
5837 print '<td><input type="text" class="left maxwidth50" name="mainmenu" value="'.dol_escape_htmltag($propMainmenu).'" readonly></td>';
5838 print '<td><input type="text" class="left maxwidth50" name="leftmenu" value="'.dol_escape_htmltag($propLeftmenu).'" readonly></td>';
5839 // URL
5840 print '<td><input type="text" class="left maxwidth250" name="url" value="'.dol_escape_htmltag($propUrl).'"></td>';
5841 print '<td><input type="text" class="left maxwidth50" name="langs" value="'.strtolower($module).'@'.strtolower($module).'" readonly></td>';
5842 // Position
5843 print '<td class="center"><input type="text" class="center maxwidth50 tdstickygray" name="position" value="'.($menu['position']).'" readonly></td>';
5844 // Enabled
5845 print '<td class="nowraponall">';
5846 print '<input type="text" class="maxwidth125" name="enabled" value="'.dol_escape_htmltag($propEnabled != '' ? $propEnabled : "isModEnabled('".dol_escape_htmltag($module)."')").'">';
5847 $htmltext = '<u>'.$langs->trans("Examples").':</u><br>';
5848 $htmltext .= '1 <span class="opacitymedium">(always enabled)</span><br>';
5849 $htmltext .= '0 <span class="opacitymedium">(always disabled)</span><br>';
5850 $htmltext .= 'isModEnabled(\''.dol_escape_htmltag($module).'\') <span class="opacitymedium">(enabled when module is enabled)</span><br>';
5851 print $form->textwithpicto('', $htmltext);
5852 /*
5853 print '<select class="maxwidth50" name="enabledselect">';
5854 print '<option value="1">1 (always enabled)</option>';
5855 print '<option value="0">0 (always disabled)</option>';
5856 print '<option value="isModEnabled(\''.dol_escape_htmltag($module).'\')" >isModEnabled(\''.dol_escape_htmltag($module).'\')</option>';
5857 print '</select>';
5858 */
5859 print '</td>';
5860 // Permissions
5861 print '<td class="nowraponall">';
5862 print '<input type="text" name="perms" value="'.dol_escape_htmltag($propPerms).'">';
5863 /*
5864 if (!empty($objPerms)) {
5865 print '<input type="hidden" name="objects" value="'.$objPerms.'" />';
5866 print '<select class="center maxwidth50" name="perms">';
5867 if (!empty($valPerms)) {
5868 print '<option selected value="'.dol_escape_htmltag($valPerms).'">'.dol_escape_htmltag($langs->trans($crud[$valPerms])).'</option>';
5869 foreach ($crud as $key => $val) {
5870 if ($valPerms != $key) {
5871 print '<option value="'.dol_escape_htmltag($key).'">'.dol_escape_htmltag($langs->trans($val)).'</option>';
5872 }
5873 }
5874 }
5875 print '</select>';
5876 } else {
5877 print '<select class="center maxwidth50" name="objects">';
5878 print '<option></option>';
5879 foreach ($objects as $obj) {
5880 print '<option value="'.dol_escape_htmltag(strtolower($obj)).'">'.dol_escape_htmltag($obj).'</option>';
5881 }
5882 print '</select>';
5883 print '<select class="center maxwidth50" name="perms">';
5884 foreach ($crud as $key => $val) {
5885 print '<option value="'.dol_escape_htmltag($key).'">'.dol_escape_htmltag($key).'</option>';
5886 }
5887 print '</select>';
5888 }*/
5889 print '</td>';
5890 // Target
5891 print '<td class="center"><input type="text" class="center maxwidth50" name="target" value="'.dol_escape_htmltag($propTarget).'"></td>';
5892 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>';
5893 print '<td class="center minwidth75 tdstickyright tdstickyghostwhite maxwidth75">';
5894 print '<input class="reposition button smallpaddingimp" type="submit" name="edit" value="'.$langs->trans("Modify").'">';
5895 print '<input class="reposition button button-cancel smallpaddingimp" type="submit" name="cancel" value="'.$langs->trans("Cancel").'">';
5896 print '</td>';
5897 print '</form>';
5898 print '</tr>';
5899 } else {
5900 print '<tr class="oddeven">';
5901
5902 print '<td class="tdsticky tdstickygray">';
5903 print $i;
5904 print '</td>';
5905
5906 print '<td class="center">';
5907 print dol_escape_htmltag($menu['type']);
5908 print '</td>';
5909
5910 // Title
5911 print '<td>';
5912 print dol_escape_htmltag($menu['titre']);
5913 print '</td>';
5914
5915 // Parent menu
5916 print '<td class="tdoverflowmax100" title="'.dol_escape_htmltag($menu['fk_menu']).'">';
5917 print dol_escape_htmltag($menu['fk_menu']);
5918 print '</td>';
5919
5920 print '<td>';
5921 print dol_escape_htmltag($menu['mainmenu']);
5922 print '</td>';
5923
5924 print '<td>';
5925 print dol_escape_htmltag($menu['leftmenu']);
5926 print '</td>';
5927
5928 print '<td class="tdoverflowmax250" title="'.dol_escape_htmltag($menu['url']).'">';
5929 print dol_escape_htmltag($menu['url']);
5930 print '</td>';
5931
5932 print '<td>';
5933 print dol_escape_htmltag($menu['langs']);
5934 print '</td>';
5935
5936 // Position
5937 print '<td class="center">';
5938 print dol_escape_htmltag((string) $menu['position']);
5939 print '</td>';
5940
5941 // Enabled
5942 print '<td class="tdoverflowmax200" title="'.dol_escape_htmltag($menu['enabled']).'">';
5943 print dol_escape_htmltag($menu['enabled']);
5944 print '</td>';
5945
5946 // Perms
5947 print '<td class="tdoverflowmax200" title="'.dol_escape_htmltag($menu['perms']).'">';
5948 print dol_escape_htmltag($langs->trans($menu['perms']));
5949 print '</td>';
5950
5951 // Target
5952 print '<td class="center tdoverflowmax200" title="'.dol_escape_htmltag($menu['target']).'">';
5953 print dol_escape_htmltag($menu['target']);
5954 print '</td>';
5955
5956 print '<td class="center">';
5957 if ($menu['user'] == 2) {
5958 print $langs->trans("AllMenus");
5959 } elseif ($menu['user'] == 0) {
5960 print $langs->trans('Internal');
5961 } elseif ($menu['user'] == 1) {
5962 print $langs->trans('External');
5963 } else {
5964 print $menu['user']; // should not happen
5965 }
5966 print '</td>';
5967 print '<td class="center minwidth75 tdstickyright tdstickyghostwhite">';
5968 if ($menu['titre'] != 'Module'.$module.'Name') {
5969 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>';
5970 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>';
5971 }
5972 print '</td>';
5973 }
5974 print '</tr>';
5975 }
5976 } else {
5977 print '<tr><td colspan="14"><span class="opacitymedium">'.$langs->trans("None").'</span></td></tr>';
5978 }
5979
5980 print '</table>';
5981 print '</div>';
5982 print '</form>';
5983
5984
5985 print '<script>
5986 $(document).ready(function() {
5987 //for fill in auto url
5988 $("#leftmenu").on("input", function() {
5989 var inputLeftMenu = $("#leftmenu").val();
5990 if (inputLeftMenu !== \'\') {
5991 var url = \''.dol_escape_js(strtolower($module)).'\' + inputLeftMenu + \'.php\';
5992 $("#url").val(url);
5993 }else {
5994 $("#url").val("");
5995 }
5996 });
5997
5998 var groupedRights = ' . $groupedRights_json . ';
5999 var objectsSelect = $("select[id=\'objects\']");
6000 var permsSelect = $("select[id=\'perms\']");
6001
6002 objectsSelect.change(function() {
6003 var selectedObject = $(this).val();
6004
6005 permsSelect.empty();
6006
6007 var rights = groupedRights[selectedObject];
6008
6009 if (rights) {
6010 for (var i = 0; i < rights.length; i++) {
6011 var right = rights[i];
6012 var option = $("<option></option>").attr("value", right[5]).text(right[5]);
6013 permsSelect.append(option);
6014 }
6015 } else {
6016 var option = $("<option></option>").attr("value", "read").text("read");
6017 permsSelect.append(option);
6018 }
6019
6020 if (selectedObject !== "" && selectedObject !== null && rights) {
6021 permsSelect.show();
6022 } else {
6023 permsSelect.hide();
6024 }
6025 if (objectsSelect.val() === "" || objectsSelect.val() === null) {
6026 permsSelect.hide();
6027 }
6028 });
6029 });
6030 </script>';
6031
6032 // display permissions for each object
6033 } else {
6034 $fullpathoffile = dol_buildpath($file, 0);
6035
6036 $content = file_get_contents($fullpathoffile);
6037
6038 // New module
6039 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
6040 print '<input type="hidden" name="token" value="'.newToken().'">';
6041 print '<input type="hidden" name="action" value="savefile">';
6042 print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
6043 print '<input type="hidden" name="tab" value="'.$tab.'">';
6044 print '<input type="hidden" name="module" value="'.$module.'">';
6045
6046 $posCursor = (empty($find)) ? array() : array('find' => $find);
6047 $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%', 0, $posCursor);
6048 print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'html'));
6049 print '<br>';
6050 print '<center>';
6051 print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
6052 print ' &nbsp; ';
6053 print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
6054 print '</center>';
6055
6056 print '</form>';
6057 }
6058 }
6059
6060 if ($tab == 'permissions') {
6061 print '<!-- tab=permissions -->'."\n";
6062 $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
6063
6064 $perms = $moduleobj->rights;
6065
6066 // Get list of existing objects
6067 $dir = $dirread.'/'.$modulelowercase.'/class';
6068 $listofobject = dol_dir_list($dir, 'files', 0, '\.class\.php$');
6069 $objects = array('myobject');
6070 $reg = array();
6071 foreach ($listofobject as $fileobj) {
6072 $tmpcontent = file_get_contents($fileobj['fullname']);
6073 if (preg_match('/class\s+([^\s]*)\s+extends\s+CommonObject/ims', $tmpcontent, $reg)) {
6074 $objects[$fileobj['fullname']] = $reg[1];
6075 }
6076 }
6077
6078 // declared select list for actions and labels permissions
6079 $crud = array('read' => 'CRUDRead', 'write' => 'CRUDCreateWrite', 'delete' => 'Delete');
6080 $labels = array("Read objects of ".$module, "Create/Update objects of ".$module, "Delete objects of ".$module);
6081
6082 $action = GETPOST('action', 'alpha');
6083
6084 if ($action == 'deleteright') {
6085 $formconfirm = $form->formconfirm(
6086 $_SERVER["PHP_SELF"].'?permskey='.urlencode((string) (GETPOSTINT('permskey'))).'&tab='.urlencode((string) ($tab)).'&module='.urlencode((string) ($module)).'&tabobj='.urlencode((string) ($tabobj)),
6087 $langs->trans('Delete'),
6088 $langs->trans('Confirm Delete Right', GETPOST('permskey', 'alpha')),
6089 'confirm_deleteright',
6090 '',
6091 0,
6092 1
6093 );
6094 print $formconfirm;
6095 }
6096
6097 if ($action != 'editfile' || empty($file)) {
6098 print '<!-- Tab to manage permissions -->'."\n";
6099 print '<span class="opacitymedium">';
6100 $htmlhelp = $langs->trans("PermissionsDefDescTooltip");
6101 //$htmlhelp = $langs->trans("PermissionsDefDescTooltip", '{s1}');
6102 //$htmlhelp = str_replace('{s1}', '<a target="adminbis" class="nofocusvisible" href="'.DOL_URL_ROOT.'/admin/perms.php">'.$langs->trans('DefaultRights').'</a>', $htmlhelp);
6103 print $form->textwithpicto($langs->trans("PermissionsDefDesc"), $htmlhelp, 1, 'help', '', 0, 2, 'helpondesc').'<br>';
6104 print '</span>';
6105 print '<br>';
6106
6107 print '<span class="fa fa-file"></span> '.$langs->trans("DescriptorFile").' : <strong class="wordbreak">'.$pathtofile.'</strong>';
6108 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>';
6109 print '<br>';
6110
6111 print '<br>';
6112 print load_fiche_titre($langs->trans("ListOfPermissionsDefined"), '', '');
6113
6114 print '<!-- form to add permissions -->'."\n";
6115 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
6116 print '<input type="hidden" name="token" value="'.newToken().'">';
6117 print '<input type="hidden" name="action" value="addright">';
6118 print '<input type="hidden" name="tab" value="permissions">';
6119 print '<input type="hidden" name="module" value="'.dol_escape_htmltag($module).'">';
6120 print '<input type="hidden" name="tabobj" value="'.dol_escape_htmltag($tabobj).'">';
6121
6122 print '<div class="div-table-responsive">';
6123 print '<table class="noborder">';
6124
6125 print '<tr class="liste_titre">';
6126 print_liste_field_titre("ID", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, "center");
6127 print_liste_field_titre("Object", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, "center");
6128 print_liste_field_titre("CRUD", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, "center");
6129 print_liste_field_titre("Label", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, "center");
6130 print_liste_field_titre("", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, "center");
6131 print "</tr>\n";
6132
6133 //form for add new right
6134 print '<tr class="small">';
6135 print '<td><input type="hidden" readonly name="id" class="width75" value="0"></td>';
6136
6137 print '<td><select class="minwidth100" name="permissionObj" id="permissionObj">';
6138 print '<option value=""></option>';
6139 foreach ($objects as $obj) {
6140 if ($obj != 'myobject') {
6141 print '<option value="'.$obj.'">'.$obj.'</option>';
6142 }
6143 }
6144 print '</select></td>';
6145
6146 print '<td><select class="maxwidth75" name="crud" id="crud">';
6147 print '<option value=""></option>';
6148 foreach ($crud as $key => $val) {
6149 print '<option value="'.$key.'">'.$langs->trans($val).'</option>';
6150 }
6151 print '</td>';
6152
6153 print '<td >';
6154 print '<input type="text" name="label" id="label" class="minwidth200">';
6155 print '</td>';
6156
6157 print '<td class="center minwidth75 tdstickyright tdstickyghostwhite">';
6158 print '<input type="submit" class="button" name="add" value="'.$langs->trans("Add").'">';
6159 print '</td>';
6160 print '</tr>';
6161
6162 if (count($perms)) {
6163 $i = 0;
6164 foreach ($perms as $perm) {
6165 $i++;
6166
6167 // section for editing right
6168 if ($action == 'edit_right' && $perm[0] == GETPOSTINT('permskey')) {
6169 print '<tr class="oddeven">';
6170 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST" name="modifPerms">';
6171 print '<input type="hidden" name="token" value="'.newToken().'">';
6172 print '<input type="hidden" name="tab" value="permissions">';
6173 print '<input type="hidden" name="module" value="'.dol_escape_htmltag($module).'">';
6174 print '<input type="hidden" name="tabobj" value="'.dol_escape_htmltag($tabobj).'">';
6175 print '<input type="hidden" name="action" value="update_right">';
6176 print '<input type="hidden" name="counter" value="'.$i.'">';
6177
6178 print '<input type="hidden" name="permskey" value="'.$perm[0].'">';
6179
6180 print '<td class="tdsticky tdstickygray">';
6181 print '<input class="width75" type="text" readonly value="'.dol_escape_htmltag($perm[0]).'"/>';
6182 print '</td>';
6183
6184 print '<td>';
6185 print '<select name="crud">';
6186 print '<option value="'.dol_escape_htmltag($perm[5]).'">'.$langs->trans($perm[5]).'</option>';
6187 foreach ($crud as $i => $x) {
6188 if ($perm[5] != $i) {
6189 print '<option value="'.$i.'">'.$langs->trans(ucfirst($x)).'</option>';
6190 }
6191 }
6192 print '</select>';
6193 print '</td>';
6194
6195 print '<td><select name="permissionObj" >';
6196 print '<option value="'.dol_escape_htmltag($perm[4]).'">'.ucfirst($perm[4]).'</option>';
6197 print '</select></td>';
6198
6199 print '<td>';
6200 print '<input type="text" name="label" value="'.dol_escape_htmltag($perm[1]).'">';
6201 print '</td>';
6202
6203 print '<td class="center minwidth75 tdstickyright tdstickyghostwhite">';
6204 print '<input id ="modifyPerm" class="reposition button smallpaddingimp" type="submit" name="modifyright" value="'.$langs->trans("Modify").'"/>';
6205 print '<br>';
6206 print '<input class="reposition button button-cancel smallpaddingimp" type="submit" name="cancel" value="'.$langs->trans("Cancel").'"/>';
6207 print '</td>';
6208
6209 print '</form>';
6210 print '</tr>';
6211 } else {
6212 // $perm can be module->object->crud or module->crud
6213 print '<tr class="oddeven">';
6214
6215 print '<td>';
6216 print dol_escape_htmltag($perm[0]);
6217 print '</td>';
6218
6219 print '<td>';
6220 if (in_array($perm[5], array('lire', 'read', 'creer', 'write', 'effacer', 'delete'))) {
6221 print dol_escape_htmltag(ucfirst($perm[4]));
6222 } else {
6223 print ''; // No particular object
6224 }
6225 print '</td>';
6226
6227 print '<td>';
6228 if (in_array($perm[5], array('lire', 'read', 'creer', 'write', 'effacer', 'delete'))) {
6229 print ucfirst($langs->trans($perm[5]));
6230 } else {
6231 print ucfirst($langs->trans($perm[4]));
6232 }
6233 print '</td>';
6234
6235 print '<td>';
6236 print $langs->trans($perm[1]);
6237 print '</td>';
6238
6239 print '<td class="center minwidth75 tdstickyright tdstickyghostwhite">';
6240 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>';
6241 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>';
6242
6243 print '</td>';
6244
6245 print '</tr>';
6246 }
6247 }
6248 } else {
6249 print '<tr><td colspan="5"><span class="opacitymedium">'.$langs->trans("None").'</span></td></tr>';
6250 }
6251
6252 print '</table>';
6253 print '</div>';
6254
6255 print '</form>';
6256 print '<script>
6257 function updateInputField() {
6258 value1 = $("#crud").val();
6259 value2 = $("#permissionObj").val();
6260
6261 // Check if both selections are made
6262 if (value1 && value2) {
6263 switch(value1.toLowerCase()){
6264 case "read":
6265 $("#label").val("Read "+value2+" object of '.ucfirst($module).'")
6266 break;
6267 case "write":
6268 $("#label").val("Create/Update "+value2+" object of '.ucfirst($module).'")
6269 break;
6270 case "delete":
6271 $("#label").val("Delete "+value2+" object of '.ucfirst($module).'")
6272 break;
6273 default:
6274 $("#label").val("")
6275 }
6276 }
6277 }
6278
6279 $("#crud, #permissionObj").change(function(){
6280 console.log("We change selection");
6281 updateInputField();
6282 });
6283
6284 </script>';
6285 } else {
6286 $fullpathoffile = dol_buildpath($file, 0);
6287
6288 $content = file_get_contents($fullpathoffile);
6289
6290 // New module
6291 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
6292 print '<input type="hidden" name="token" value="'.newToken().'">';
6293 print '<input type="hidden" name="action" value="savefile">';
6294 print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
6295 print '<input type="hidden" name="tab" value="'.$tab.'">';
6296 print '<input type="hidden" name="module" value="'.$module.'">';
6297
6298 $posCursor = (empty($find)) ? array() : array('find' => $find);
6299 $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%', 0, $posCursor);
6300 print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'html'));
6301 print '<br>';
6302 print '<center>';
6303 print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
6304 print ' &nbsp; ';
6305 print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
6306 print '</center>';
6307
6308 print '</form>';
6309 }
6310 }
6311
6312 if ($tab == 'hooks') {
6313 print '<!-- tab=hooks -->'."\n";
6314 if ($action != 'editfile' || empty($file)) {
6315 print '<span class="opacitymedium">'.$langs->trans("HooksDefDesc").'</span><br>';
6316 print '<br>';
6317
6318 print '<table>';
6319
6320 $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
6321 print '<tr><td>';
6322 print '<span class="fa fa-file"></span> '.$langs->trans("DescriptorFile").' : <strong class="wordbreak">'.$pathtofile.'</strong>';
6323 print '</td><td>';
6324 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>';
6325 print '</td></tr>';
6326
6327 print '<tr><td>';
6328 $pathtohook = strtolower($module).'/class/actions_'.strtolower($module).'.class.php';
6329 print '<span class="fa fa-file"></span> '.$langs->trans("HooksFile").' : ';
6330 if (dol_is_file($dirins.'/'.$pathtohook)) {
6331 print '<strong class="wordbreak">'.$pathtohook.'</strong>';
6332 print '</td>';
6333 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> ';
6334 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>';
6335 } else {
6336 print '<span class="opacitymedium">'.$langs->trans("FileNotYetGenerated").'</span>';
6337 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>';
6338 print '<td></td>';
6339 }
6340 print '</tr>';
6341 } else {
6342 $fullpathoffile = dol_buildpath($file, 0);
6343
6344 $content = file_get_contents($fullpathoffile);
6345
6346 // New module
6347 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
6348 print '<input type="hidden" name="token" value="'.newToken().'">';
6349 print '<input type="hidden" name="action" value="savefile">';
6350 print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
6351 print '<input type="hidden" name="tab" value="'.$tab.'">';
6352 print '<input type="hidden" name="module" value="'.$module.'">';
6353
6354 $posCursor = (empty($find)) ? array() : array('find' => $find);
6355 $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%', 0, $posCursor);
6356 print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'html'));
6357 print '<br>';
6358 print '<center>';
6359 print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
6360 print ' &nbsp; ';
6361 print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
6362 print '</center>';
6363
6364 print '</form>';
6365 }
6366 }
6367
6368 if ($tab == 'triggers') {
6369 print '<!-- tab=triggers -->'."\n";
6370 require_once DOL_DOCUMENT_ROOT.'/core/class/interfaces.class.php';
6371
6372 $interfaces = new Interfaces($db);
6373 $triggers = $interfaces->getTriggersList(array('/'.strtolower($module).'/core/triggers'));
6374
6375 if ($action != 'editfile' || empty($file)) {
6376 print '<span class="opacitymedium">'.$langs->trans("TriggerDefDesc").'</span><br>';
6377 print '<br>';
6378
6379 print '<table>';
6380
6381 $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
6382 print '<tr><td>';
6383 print '<span class="fa fa-file"></span> '.$langs->trans("DescriptorFile").' : <strong class="wordbreak">'.$pathtofile.'</strong>';
6384 print '</td><td>';
6385 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>';
6386 print '</td></tr>';
6387
6388 if (!empty($triggers)) {
6389 foreach ($triggers as $trigger) {
6390 $pathtofile = $trigger['relpath'];
6391
6392 print '<tr><td>';
6393 print '<span class="fa fa-file"></span> '.$langs->trans("TriggersFile").' : <strong class="wordbreak">'.$pathtofile.'</strong>';
6394 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>';
6395 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>';
6396 print '</tr>';
6397 }
6398 } else {
6399 print '<tr><td>';
6400 print '<span class="fa fa-file"></span> '.$langs->trans("TriggersFile");
6401 print ' : <span class="opacitymedium">'.$langs->trans("FileNotYetGenerated").'</span>';
6402 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>';
6403 print '<td></td>';
6404 print '</tr>';
6405 }
6406
6407 print '</table>';
6408 } else {
6409 $fullpathoffile = dol_buildpath($file, 0);
6410
6411 $content = file_get_contents($fullpathoffile);
6412
6413 // New module
6414 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
6415 print '<input type="hidden" name="token" value="'.newToken().'">';
6416 print '<input type="hidden" name="action" value="savefile">';
6417 print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
6418 print '<input type="hidden" name="tab" value="'.$tab.'">';
6419 print '<input type="hidden" name="module" value="'.$module.'">';
6420
6421 $posCursor = (empty($find)) ? array() : array('find' => $find);
6422 $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%', 0, $posCursor);
6423 print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'html'));
6424 print '<br>';
6425 print '<center>';
6426 print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
6427 print ' &nbsp; ';
6428 print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
6429 print '</center>';
6430
6431 print '</form>';
6432 }
6433 }
6434
6435 if ($tab == 'css') {
6436 print '<!-- tab=css -->'."\n";
6437 if ($action != 'editfile' || empty($file)) {
6438 print '<span class="opacitymedium">'.$langs->trans("CSSDesc").'</span><br>';
6439 print '<br>';
6440
6441 print '<table>';
6442
6443 print '<tr><td>';
6444 $pathtohook = strtolower($module).'/css/'.strtolower($module).'.css.php';
6445 print '<span class="fa fa-file"></span> '.$langs->trans("CSSFile").' : ';
6446 if (dol_is_file($dirins.'/'.$pathtohook)) {
6447 print '<strong class="wordbreak">'.$pathtohook.'</strong>';
6448 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>';
6449 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>';
6450 } else {
6451 print '<span class="opacitymedium">'.$langs->trans("FileNotYetGenerated").'</span>';
6452 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>';
6453 }
6454 print '</tr>';
6455 } else {
6456 $fullpathoffile = dol_buildpath($file, 0);
6457
6458 $content = file_get_contents($fullpathoffile);
6459
6460 // New module
6461 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
6462 print '<input type="hidden" name="token" value="'.newToken().'">';
6463 print '<input type="hidden" name="action" value="savefile">';
6464 print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
6465 print '<input type="hidden" name="tab" value="'.$tab.'">';
6466 print '<input type="hidden" name="module" value="'.$module.'">';
6467
6468 $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%');
6469 print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'html'));
6470 print '<br>';
6471 print '<center>';
6472 print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
6473 print ' &nbsp; ';
6474 print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
6475 print '</center>';
6476
6477 print '</form>';
6478 }
6479 }
6480
6481 if ($tab == 'js') {
6482 print '<!-- tab=js -->'."\n";
6483 if ($action != 'editfile' || empty($file)) {
6484 print '<span class="opacitymedium">'.$langs->trans("JSDesc").'</span><br>';
6485 print '<br>';
6486
6487 print '<table>';
6488
6489 print '<tr><td>';
6490 $pathtohook = strtolower($module).'/js/'.strtolower($module).'.js.php';
6491 print '<span class="fa fa-file"></span> '.$langs->trans("JSFile").' : ';
6492 if (dol_is_file($dirins.'/'.$pathtohook)) {
6493 print '<strong class="wordbreak">'.$pathtohook.'</strong>';
6494 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>';
6495 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>';
6496 } else {
6497 print '<span class="opacitymedium">'.$langs->trans("FileNotYetGenerated").'</span>';
6498 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>';
6499 }
6500 print '</tr>';
6501 } else {
6502 $fullpathoffile = dol_buildpath($file, 0);
6503
6504 $content = file_get_contents($fullpathoffile);
6505
6506 // New module
6507 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
6508 print '<input type="hidden" name="token" value="'.newToken().'">';
6509 print '<input type="hidden" name="action" value="savefile">';
6510 print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
6511 print '<input type="hidden" name="tab" value="'.$tab.'">';
6512 print '<input type="hidden" name="module" value="'.$module.'">';
6513
6514 $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%');
6515 print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'html'));
6516 print '<br>';
6517 print '<center>';
6518 print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
6519 print ' &nbsp; ';
6520 print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
6521 print '</center>';
6522
6523 print '</form>';
6524 }
6525 }
6526
6527 if ($tab == 'widgets') {
6528 print '<!-- tab=widgets -->'."\n";
6529 require_once DOL_DOCUMENT_ROOT.'/core/boxes/modules_boxes.php';
6530
6531 $widgets = ModeleBoxes::getWidgetsList(array('/'.strtolower($module).'/core/boxes'));
6532
6533 if ($action != 'editfile' || empty($file)) {
6534 print '<span class="opacitymedium">'.$langs->trans("WidgetDesc").'</span><br>';
6535 print '<br>';
6536
6537 print '<table>';
6538 if (!empty($widgets)) {
6539 foreach ($widgets as $widget) {
6540 $pathtofile = $widget['relpath'];
6541
6542 print '<tr><td><span class="fa fa-file"></span> '.$langs->trans("WidgetFile").' : <strong class="wordbreak">'.$pathtofile.'</strong>';
6543 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>';
6544 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>';
6545 print '</tr>';
6546 }
6547 } else {
6548 print '<tr><td><span class="fa fa-file"></span> '.$langs->trans("WidgetFile").' : <span class="opacitymedium">'.$langs->trans("NoWidget").'</span>';
6549 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>';
6550 print '</td></tr>';
6551 }
6552 print '</table>';
6553 } else {
6554 $fullpathoffile = dol_buildpath($file, 0);
6555
6556 $content = file_get_contents($fullpathoffile);
6557
6558 // New module
6559 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
6560 print '<input type="hidden" name="token" value="'.newToken().'">';
6561 print '<input type="hidden" name="action" value="savefile">';
6562 print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
6563 print '<input type="hidden" name="tab" value="'.$tab.'">';
6564 print '<input type="hidden" name="module" value="'.$module.'">';
6565
6566 $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%');
6567 print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'html'));
6568 print '<br>';
6569 print '<center>';
6570 print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
6571 print ' &nbsp; ';
6572 print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
6573 print '</center>';
6574
6575 print '</form>';
6576 }
6577 }
6578
6579 if ($tab == 'emailings') {
6580 print '<!-- tab=emailings -->'."\n";
6581 require_once DOL_DOCUMENT_ROOT.'/core/modules/mailings/modules_mailings.php';
6582
6583 $emailingselectors = MailingTargets::getEmailingSelectorsList(array('/'.strtolower($module).'/core/modules/mailings'));
6584
6585 if ($action != 'editfile' || empty($file)) {
6586 print '<span class="opacitymedium">'.$langs->trans("EmailingSelectorDesc").'</span><br>';
6587 print '<br>';
6588
6589 print '<table>';
6590 if (!empty($emailingselectors)) {
6591 foreach ($emailingselectors as $emailingselector) {
6592 $pathtofile = $emailingselector['relpath'];
6593
6594 print '<tr><td><span class="fa fa-file"></span> '.$langs->trans("EmailingSelectorFile").' : <strong class="wordbreak">'.$pathtofile.'</strong>';
6595 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>';
6596 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>';
6597 print '</tr>';
6598 }
6599 } else {
6600 print '<tr><td><span class="fa fa-file"></span> '.$langs->trans("EmailingSelectorFile").' : <span class="opacitymedium">'.$langs->trans("NoEmailingSelector").'</span>';
6601 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>';
6602 print '</td></tr>';
6603 }
6604 print '</table>';
6605 } else {
6606 $fullpathoffile = dol_buildpath($file, 0);
6607
6608 $content = file_get_contents($fullpathoffile);
6609
6610 // New module
6611 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
6612 print '<input type="hidden" name="token" value="'.newToken().'">';
6613 print '<input type="hidden" name="action" value="savefile">';
6614 print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
6615 print '<input type="hidden" name="tab" value="'.$tab.'">';
6616 print '<input type="hidden" name="module" value="'.$module.'">';
6617
6618 $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%');
6619 print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'html'));
6620 print '<br>';
6621 print '<center>';
6622 print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
6623 print ' &nbsp; ';
6624 print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
6625 print '</center>';
6626
6627 print '</form>';
6628 }
6629 }
6630
6631 if ($tab == 'exportimport') {
6632 print '<!-- tab=exportimport -->'."\n";
6633 $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
6634
6635 $exportlist = $moduleobj->export_label;
6636 $importlist = $moduleobj->import_label;
6637
6638 if ($action != 'editfile' || empty($file)) {
6639 print '<span class="opacitymedium">'.$langs->transnoentities('ImportExportProfiles').'</span><br>';
6640 print '<br>';
6641
6642 print '<span class="fa fa-file"></span> '.$langs->trans("DescriptorFile").' ('.$langs->trans("ExportsArea").') : <strong class="wordbreak">'.$pathtofile.'</strong>';
6643 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>';
6644 print '<br>';
6645 print '<span class="fa fa-file"></span> '.$langs->trans("DescriptorFile").' ('.$langs->trans("ImportArea").') : <strong class="wordbreak">'.$pathtofile.'</strong>';
6646 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>';
6647 print '<br>';
6648 } else {
6649 $fullpathoffile = dol_buildpath($file, 0);
6650
6651 $content = file_get_contents($fullpathoffile);
6652
6653 // New module
6654 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
6655 print '<input type="hidden" name="token" value="'.newToken().'">';
6656 print '<input type="hidden" name="action" value="savefile">';
6657 print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
6658 print '<input type="hidden" name="tab" value="'.$tab.'">';
6659 print '<input type="hidden" name="module" value="'.$module.'">';
6660
6661 $posCursor = (empty($find)) ? array() : array('find' => $find);
6662 $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%', 0, $posCursor);
6663 print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'html'));
6664 print '<br>';
6665 print '<center>';
6666 print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
6667 print ' &nbsp; ';
6668 print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
6669 print '</center>';
6670
6671 print '</form>';
6672 }
6673 }
6674
6675 if ($tab == 'cli') {
6676 print '<!-- tab=cli -->'."\n";
6677 $clifiles = array();
6678 $i = 0;
6679
6680 $dircli = array('/'.strtolower($module).'/scripts');
6681
6682 foreach ($dircli as $reldir) {
6683 $dir = dol_buildpath($reldir, 0);
6684 $newdir = dol_osencode($dir);
6685
6686 // Check if directory exists (we do not use dol_is_dir to avoid loading files.lib.php at each call)
6687 if (!is_dir($newdir)) {
6688 continue;
6689 }
6690
6691 $handle = opendir($newdir);
6692
6693 if (is_resource($handle)) {
6694 while (($tmpfile = readdir($handle)) !== false) {
6695 if (is_readable($newdir.'/'.$tmpfile) && preg_match('/^(.+)\.php/', $tmpfile, $reg)) {
6696 if (preg_match('/\.back$/', $tmpfile)) {
6697 continue;
6698 }
6699
6700 $clifiles[$i]['relpath'] = preg_replace('/^\//', '', $reldir).'/'.$tmpfile;
6701
6702 $i++;
6703 }
6704 }
6705 closedir($handle);
6706 }
6707 }
6708
6709 if ($action != 'editfile' || empty($file)) {
6710 print '<span class="opacitymedium">'.$langs->trans("CLIDesc").'</span><br>';
6711 print '<br>';
6712
6713 print '<table>';
6714 if (!empty($clifiles)) {
6715 foreach ($clifiles as $clifile) {
6716 $pathtofile = $clifile['relpath'];
6717
6718 print '<tr><td><span class="fa fa-file"></span> '.$langs->trans("CLIFile").' : <strong class="wordbreak">'.$pathtofile.'</strong>';
6719 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>';
6720 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>';
6721 print '</tr>';
6722 }
6723 } else {
6724 print '<tr><td><span class="fa fa-file"></span> '.$langs->trans("CLIFile").' : <span class="opacitymedium">'.$langs->trans("FileNotYetGenerated").'</span>';
6725 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>';
6726 print '</td></tr>';
6727 }
6728 print '</table>';
6729 } else {
6730 $fullpathoffile = dol_buildpath($file, 0);
6731
6732 $content = file_get_contents($fullpathoffile);
6733
6734 // New module
6735 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
6736 print '<input type="hidden" name="token" value="'.newToken().'">';
6737 print '<input type="hidden" name="action" value="savefile">';
6738 print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
6739 print '<input type="hidden" name="tab" value="'.$tab.'">';
6740 print '<input type="hidden" name="module" value="'.$module.'">';
6741
6742 $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%');
6743 print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'html'));
6744 print '<br>';
6745 print '<center>';
6746 print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
6747 print ' &nbsp; ';
6748 print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
6749 print '</center>';
6750
6751 print '</form>';
6752 }
6753 }
6754
6755 if ($tab == 'cron') {
6756 print '<!-- tab=cron -->'."\n";
6757 $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
6758
6759 $cronjobs = $moduleobj->cronjobs;
6760
6761 if ($action != 'editfile' || empty($file)) {
6762 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>';
6763 print '<br>';
6764
6765 print '<span class="fa fa-file"></span> '.$langs->trans("DescriptorFile").' : <strong class="wordbreak">'.$pathtofile.'</strong>';
6766 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>';
6767 print '<br>';
6768
6769 print '<br>';
6770 print load_fiche_titre($langs->trans("CronJobProfiles"), '', '');
6771
6772 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
6773 print '<input type="hidden" name="token" value="'.newToken().'">';
6774 print '<input type="hidden" name="action" value="addproperty">';
6775 print '<input type="hidden" name="tab" value="objects">';
6776 print '<input type="hidden" name="module" value="'.dol_escape_htmltag($module).'">';
6777 print '<input type="hidden" name="tabobj" value="'.dol_escape_htmltag($tabobj).'">';
6778
6779 print '<div class="div-table-responsive">';
6780 print '<table class="noborder">';
6781
6782 print '<tr class="liste_titre">';
6783 print_liste_field_titre("CronLabel", $_SERVER["PHP_SELF"], "", "", $param, '', $sortfield, $sortorder);
6784 print_liste_field_titre("CronTask", '', '', "", $param, '', $sortfield, $sortorder);
6785 print_liste_field_titre("CronFrequency", '', "", "", $param, '', $sortfield, $sortorder);
6786 print_liste_field_titre("StatusAtInstall", $_SERVER["PHP_SELF"], "", "", $param, '', $sortfield, $sortorder);
6787 print_liste_field_titre("Comment", $_SERVER["PHP_SELF"], "", "", $param, '', $sortfield, $sortorder);
6788 print "</tr>\n";
6789
6790 if (count($cronjobs)) {
6791 foreach ($cronjobs as $cron) {
6792 print '<tr class="oddeven">';
6793
6794 print '<td>';
6795 print $cron['label'];
6796 print '</td>';
6797
6798 print '<td>';
6799 $texttoshow = '';
6800 if ($cron['jobtype'] == 'method') {
6801 $text = $langs->trans("CronClass");
6802 $texttoshow = $langs->trans('CronModule').': '.$module.'<br>';
6803 $texttoshow .= $langs->trans('CronClass').': '.$cron['class'].'<br>';
6804 $texttoshow .= $langs->trans('CronObject').': '.$cron['objectname'].'<br>';
6805 $texttoshow .= $langs->trans('CronMethod').': '.$cron['method'];
6806 $texttoshow .= '<br>'.$langs->trans('CronArgs').': '.$cron['parameters'];
6807 $texttoshow .= '<br>'.$langs->trans('Comment').': '.$langs->trans($cron['comment']);
6808 } elseif ($cron['jobtype'] == 'command') {
6809 $text = $langs->trans('CronCommand');
6810 $texttoshow = $langs->trans('CronCommand').': '.dol_trunc($cron['command']);
6811 $texttoshow .= '<br>'.$langs->trans('CronArgs').': '.$cron['parameters'];
6812 $texttoshow .= '<br>'.$langs->trans('Comment').': '.$langs->trans($cron['comment']);
6813 }
6814 print $form->textwithpicto($text, $texttoshow, 1);
6815 print '</td>';
6816
6817 print '<td>';
6818 if ($cron['unitfrequency'] == "60") {
6819 print $langs->trans('CronEach')." ".($cron['frequency'])." ".$langs->trans('Minutes');
6820 }
6821 if ($cron['unitfrequency'] == "3600") {
6822 print $langs->trans('CronEach')." ".($cron['frequency'])." ".$langs->trans('Hours');
6823 }
6824 if ($cron['unitfrequency'] == "86400") {
6825 print $langs->trans('CronEach')." ".($cron['frequency'])." ".$langs->trans('Days');
6826 }
6827 if ($cron['unitfrequency'] == "604800") {
6828 print $langs->trans('CronEach')." ".($cron['frequency'])." ".$langs->trans('Weeks');
6829 }
6830 print '</td>';
6831
6832 print '<td>';
6833 print $cron['status'];
6834 print '</td>';
6835
6836 print '<td>';
6837 if (!empty($cron['comment'])) {
6838 print $cron['comment'];
6839 }
6840 print '</td>';
6841
6842 print '</tr>';
6843 }
6844 } else {
6845 print '<tr><td colspan="5"><span class="opacitymedium">'.$langs->trans("None").'</span></td></tr>';
6846 }
6847
6848 print '</table>';
6849 print '</div>';
6850
6851 print '</form>';
6852 } else {
6853 $fullpathoffile = dol_buildpath($file, 0);
6854
6855 $content = file_get_contents($fullpathoffile);
6856
6857 // New module
6858 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
6859 print '<input type="hidden" name="token" value="'.newToken().'">';
6860 print '<input type="hidden" name="action" value="savefile">';
6861 print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
6862 print '<input type="hidden" name="tab" value="'.$tab.'">';
6863 print '<input type="hidden" name="module" value="'.$module.'">';
6864
6865 $posCursor = (empty($find)) ? array() : array('find' => $find);
6866 $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%', 0, $posCursor);
6867 print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'html'));
6868 print '<br>';
6869 print '<center>';
6870 print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
6871 print ' &nbsp; ';
6872 print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
6873 print '</center>';
6874
6875 print '</form>';
6876 }
6877 }
6878
6879 if ($tab == 'specifications') {
6880 print '<!-- tab=specifications -->'."\n";
6881 $specs = dol_dir_list(dol_buildpath($modulelowercase.'/doc', 0), 'files', 1, '(\.md|\.asciidoc)$', array('\/temp\/'));
6882
6883 if ($action != 'editfile' || empty($file)) {
6884 print '<span class="opacitymedium">'.$langs->trans("SpecDefDesc").'</span><br>';
6885 print '<br>';
6886
6887 print '<table>';
6888 if (is_array($specs) && !empty($specs)) {
6889 foreach ($specs as $spec) {
6890 $pathtofile = $modulelowercase.'/doc/'.$spec['relativename'];
6891 $format = 'asciidoc';
6892 if (preg_match('/\.md$/i', $spec['name'])) {
6893 $format = 'markdown';
6894 }
6895 print '<tr><td>';
6896 print '<span class="fa fa-file"></span> '.$langs->trans("SpecificationFile").' : <strong class="wordbreak">'.$pathtofile.'</strong>';
6897 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>';
6898 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>';
6899 print '</tr>';
6900 }
6901 } else {
6902 print '<tr><td>';
6903 print '<span class="fa fa-file"></span> '.$langs->trans("SpecificationFile").' : <span class="opacitymedium">'.$langs->trans("FileNotYetGenerated").'</span>';
6904 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>';
6905 print '</tr>';
6906 }
6907 print '</table>';
6908 } else {
6909 // Use MD or asciidoc
6910
6911 //print $langs->trans("UseAsciiDocFormat").'<br>';
6912
6913 $fullpathoffile = dol_buildpath($file, 0);
6914
6915 $content = file_get_contents($fullpathoffile);
6916
6917 // New module
6918 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
6919 print '<input type="hidden" name="token" value="'.newToken().'">';
6920 print '<input type="hidden" name="action" value="savefile">';
6921 print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
6922 print '<input type="hidden" name="tab" value="'.$tab.'">';
6923 print '<input type="hidden" name="module" value="'.$module.'">';
6924
6925 $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%');
6926 print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'html'));
6927 print '<br>';
6928 print '<center>';
6929 print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
6930 print ' &nbsp; ';
6931 print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
6932 print '</center>';
6933
6934 print '</form>';
6935 }
6936
6937 print '<br><br><br>';
6938
6939 $FILENAMEDOC = $modulelowercase.'.html';
6940 $FILENAMEDOCPDF = $modulelowercase.'.pdf';
6941 $outputfiledoc = dol_buildpath($modulelowercase, 0).'/doc/'.$FILENAMEDOC;
6942 $outputfiledocurl = dol_buildpath($modulelowercase, 1).'/doc/'.$FILENAMEDOC;
6943 $outputfiledocrel = $modulelowercase.'/doc/'.$FILENAMEDOC;
6944 $outputfiledocpdf = dol_buildpath($modulelowercase, 0).'/doc/'.$FILENAMEDOCPDF;
6945 $outputfiledocurlpdf = dol_buildpath($modulelowercase, 1).'/doc/'.$FILENAMEDOCPDF;
6946 $outputfiledocrelpdf = $modulelowercase.'/doc/'.$FILENAMEDOCPDF;
6947
6948 // HTML
6949 print '<span class="fa fa-file"></span> '.$langs->trans("PathToModuleDocumentation", "HTML").' : ';
6950 if (!dol_is_file($outputfiledoc)) {
6951 print '<span class="opacitymedium">'.$langs->trans("FileNotYetGenerated").'</span>';
6952 } else {
6953 print '<strong>';
6954 print '<a href="'.$outputfiledocurl.'" target="_blank" rel="noopener noreferrer">';
6955 print $outputfiledoc;
6956 print '</a>';
6957 print '</strong>';
6958 print ' <span class="opacitymedium">('.$langs->trans("GeneratedOn").' '.dol_print_date(dol_filemtime($outputfiledoc), 'dayhour').')</span>';
6959 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>';
6960 }
6961 print '</strong><br>';
6962
6963 // PDF
6964 print '<span class="fa fa-file"></span> '.$langs->trans("PathToModuleDocumentation", "PDF").' : ';
6965 if (!dol_is_file($outputfiledocpdf)) {
6966 print '<span class="opacitymedium">'.$langs->trans("FileNotYetGenerated").'</span>';
6967 } else {
6968 print '<strong>';
6969 print '<a href="'.$outputfiledocurlpdf.'" target="_blank" rel="noopener noreferrer">';
6970 print $outputfiledocpdf;
6971 print '</a>';
6972 print '</strong>';
6973 print ' <span class="opacitymedium">('.$langs->trans("GeneratedOn").' '.dol_print_date(dol_filemtime($outputfiledocpdf), 'dayhour').')</span>';
6974 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>';
6975 }
6976 print '</strong><br>';
6977
6978 print '<br>';
6979
6980 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST" name="generatedoc">';
6981 print '<input type="hidden" name="token" value="'.newToken().'">';
6982 print '<input type="hidden" name="action" value="generatedoc">';
6983 print '<input type="hidden" name="tab" value="'.dol_escape_htmltag($tab).'">';
6984 print '<input type="hidden" name="module" value="'.dol_escape_htmltag($module).'">';
6985 print '<input type="submit" class="button" name="generatedoc" value="'.$langs->trans("BuildDocumentation").'"';
6986 if (!is_array($specs) || empty($specs)) {
6987 print ' disabled="disabled"';
6988 }
6989 print '>';
6990 print '</form>';
6991 }
6992
6993 if ($tab == 'buildpackage') {
6994 print '<!-- tab=buildpackage -->'."\n";
6995 print '<span class="opacitymedium">'.$langs->trans("BuildPackageDesc").'</span>';
6996 print '<br>';
6997
6998 if (!class_exists('ZipArchive') && !defined('ODTPHP_PATHTOPCLZIP')) {
6999 print img_warning().' '.$langs->trans("ErrNoZipEngine");
7000 print '<br>';
7001 }
7002
7003 $modulelowercase = strtolower($module);
7004
7005 // Zip file to build
7006 $FILENAMEZIP = '';
7007
7008 // Load module
7009 $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
7010 dol_include_once($pathtofile);
7011 $class = 'mod'.$module;
7012 $moduleobj = null;
7013 if (class_exists($class)) {
7014 try {
7015 $moduleobj = new $class($db);
7016 '@phan-var-force DolibarrModules $moduleobj';
7018 } catch (Exception $e) {
7019 $error++;
7020 dol_print_error($db, $e->getMessage());
7021 }
7022 }
7023 if ($moduleobj === null) {
7024 $error++;
7025 $langs->load("errors");
7026 dol_print_error($db, $langs->trans("ErrorFailedToLoadModuleDescriptorForXXX", $module));
7027 exit;
7028 }
7029
7030 $outputfilezip = null;
7031 $arrayversion = explode('.', $moduleobj->version, 3);
7032 if (count($arrayversion)) {
7033 $FILENAMEZIP = "module_".$modulelowercase.'-'.$arrayversion[0].(empty($arrayversion[1]) ? '.0' : '.'.$arrayversion[1]).(empty($arrayversion[2]) ? '' : ".".$arrayversion[2]).".zip";
7034 $outputfilezip = dol_buildpath($modulelowercase, 0).'/bin/'.$FILENAMEZIP;
7035 }
7036
7037 print '<br>';
7038
7039 print '<span class="fa fa-file"></span> '.$langs->trans("PathToModulePackage").' : ';
7040 if ($outputfilezip === null || !dol_is_file($outputfilezip)) {
7041 print '<span class="opacitymedium">'.$langs->trans("FileNotYetGenerated").'</span>';
7042 } else {
7043 $relativepath = $modulelowercase.'/bin/'.$FILENAMEZIP;
7044 print '<strong><a href="'.DOL_URL_ROOT.'/document.php?modulepart=packages&file='.urlencode($relativepath).'">'.$outputfilezip.'</a></strong>';
7045 print ' <span class="opacitymedium">('.$langs->trans("GeneratedOn").' '.dol_print_date(dol_filemtime($outputfilezip), 'dayhour').')</span>';
7046 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>';
7047 }
7048 print '</strong>';
7049
7050 print '<br>';
7051
7052 print '<br>';
7053
7054 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST" name="generatepackage">';
7055 print '<input type="hidden" name="token" value="'.newToken().'">';
7056 print '<input type="hidden" name="action" value="generatepackage">';
7057 print '<input type="hidden" name="tab" value="'.dol_escape_htmltag($tab).'">';
7058 print '<input type="hidden" name="module" value="'.dol_escape_htmltag($module).'">';
7059 print '<input type="submit" class="button" name="generatepackage" value="'.$langs->trans("BuildPackage").'">';
7060 print '</form>';
7061 }
7062
7063 if ($tab == 'tabs') {
7064 $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
7065
7066 $tabs = $moduleobj->tabs;
7067
7068 if ($action != 'editfile' || empty($file)) {
7069 print '<span class="opacitymedium">';
7070 $htmlhelp = $langs->trans("TabsDefDescTooltip", '{s1}');
7071 $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);
7072 print $form->textwithpicto($langs->trans("TabsDefDesc"), $htmlhelp, 1, 'help', '', 0, 2, 'helpondesc').'<br>';
7073 print '</span>';
7074 print '<br>';
7075
7076 print '<span class="fa fa-file"></span> '.$langs->trans("DescriptorFile").' : <strong>'.$pathtofile.'</strong>';
7077 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>';
7078 print '<br>';
7079
7080 print '<br>';
7081 print load_fiche_titre($langs->trans("ListOfTabsEntries"), '', '');
7082
7083 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
7084 print '<input type="hidden" name="token" value="'.newToken().'">';
7085 print '<input type="hidden" name="action" value="addproperty">';
7086 print '<input type="hidden" name="tab" value="objects">';
7087 print '<input type="hidden" name="module" value="'.dol_escape_htmltag($module).'">';
7088 print '<input type="hidden" name="tabobj" value="'.dol_escape_htmltag($tabobj).'">';
7089
7090 print '<div class="div-table-responsive">';
7091 print '<table class="noborder small">';
7092
7093 print '<tr class="liste_titre">';
7094 print_liste_field_titre("ObjectType", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
7095 print_liste_field_titre("Tab", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
7096 print_liste_field_titre("Title", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
7097 print_liste_field_titre("LangFile", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
7098 print_liste_field_titre("Condition", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
7099 print_liste_field_titre("Path", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
7100 print "</tr>\n";
7101
7102 if (count($tabs)) {
7103 foreach ($tabs as $tab) {
7104 $parts = explode(':', $tab['data']);
7105
7106 $objectType = $parts[0];
7107 $tabName = $parts[1];
7108 $tabTitle = isset($parts[2]) ? $parts[2] : '';
7109 $langFile = isset($parts[3]) ? $parts[3] : '';
7110 $condition = isset($parts[4]) ? $parts[4] : '';
7111 $path = isset($parts[5]) ? $parts[5] : '';
7112
7113 // If we want to remove the tab, then the format is 'objecttype:tabname:optionalcondition'
7114 // See: https://wiki.dolibarr.org/index.php?title=Tabs_system#To_remove_an_existing_tab
7115 if ($tabName[0] === '-') {
7116 $tabTitle = '';
7117 $condition = isset($parts[2]) ? $parts[2] : '';
7118 }
7119
7120 print '<tr class="oddeven">';
7121
7122 print '<td>';
7123 print dol_escape_htmltag($parts[0]);
7124 print '</td>';
7125
7126 print '<td>';
7127 if ($tabName[0] === "+") {
7128 print '<span class="badge badge-status4 badge-status">' . dol_escape_htmltag($tabName) . '</span>';
7129 } else {
7130 print '<span class="badge badge-status8 badge-status">' . dol_escape_htmltag($tabName) . '</span>';
7131 }
7132 print '</td>';
7133
7134 print '<td>';
7135 print dol_escape_htmltag($tabTitle);
7136 print '</td>';
7137
7138 print '<td>';
7139 print dol_escape_htmltag($langFile);
7140 print '</td>';
7141
7142 print '<td>';
7143 print dol_escape_htmltag($condition);
7144 print '</td>';
7145
7146 print '<td>';
7147 print dol_escape_htmltag($path);
7148 print '</td>';
7149
7150 print '</tr>';
7151 }
7152 } else {
7153 print '<tr><td colspan="5"><span class="opacitymedium">'.$langs->trans("None").'</span></td></tr>';
7154 }
7155
7156 print '</table>';
7157 print '</div>';
7158
7159 print '</form>';
7160 } else {
7161 $fullpathoffile = dol_buildpath($file, 0);
7162
7163 $content = file_get_contents($fullpathoffile);
7164
7165 // New module
7166 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
7167 print '<input type="hidden" name="token" value="'.newToken().'">';
7168 print '<input type="hidden" name="action" value="savefile">';
7169 print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
7170 print '<input type="hidden" name="tab" value="'.$tab.'">';
7171 print '<input type="hidden" name="module" value="'.$module.'">';
7172
7173 $posCursor = (empty($find)) ? array() : array('find' => $find);
7174 $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%', 0, $posCursor);
7175 print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'html'));
7176 print '<br>';
7177 print '<center>';
7178 print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
7179 print ' &nbsp; ';
7180 print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
7181 print '</center>';
7182
7183 print '</form>';
7184 }
7185 }
7186
7187 if ($tab != 'description') {
7188 print dol_get_fiche_end();
7189 }
7190 }
7191}
7192
7193print dol_get_fiche_end(); // End modules
7194
7195
7196// End of page
7197llxFooter();
7198$db->close();
if(! $sortfield) if(! $sortorder) $object
Definition account.php:100
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='')
Convert a html select field into an ajax combobox.
Definition ajax.lib.php:476
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.
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:
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $db
API class for accounts.
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_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_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.
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.
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.
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
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0, $attop=0)
Set event messages in dol_events session object.
print_liste_field_titre($name, $file="", $field="", $begin="", $param="", $moreattrib="", $sortfield="", $sortorder="", $prefix="", $tooltip="", $forcenowrapcolumntitle=0)
Show title line of an array.
print_barre_liste($title, $page, $file, $options='', $sortfield='', $sortorder='', $morehtmlcenter='', $num=-1, $totalnboflines='', $picto='generic', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limit=-1, $selectlimitsuffix=0, $hidenavigation=0, $pagenavastextinput=0, $morehtmlrightbeforearrow='')
Print a title with navigation controls for pagination.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2, $allowothertags=array())
Show picto whatever it's its name (generic function)
img_warning($titlealt='default', $moreatt='', $morecss='pictowarning')
Show warning logo.
img_delete($titlealt='default', $other='class="pictodelete"', $morecss='')
Show delete logo.
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:519
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:415
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:717
getPictoForType($key, $morecss='')
Return the picto for a data type.
yn($yesno, $format=1, $color=0)
Return yes or no in current language.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
load_fiche_titre($title, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='', $morecssonpicto='widthpictotitle')
Load a title with picto.
img_edit($titlealt='default', $float=0, $other='')
Show logo edit/modify fiche.
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)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...
Definition html.lib.php:172
print $langs trans("Show") . '< td style="' . $timeColor . '" align="center"> s</td > badge status0 badge status4 badge status3 Error badge status8< td align="center">< span class="badge ' . $badge . '"></span ></td >< td align="center">< a href="#" class="button button-small" onclick="openLogModal(this)" data-req="' . dol_escape_htmltag($reqSafe) . '" data-res="' . dol_escape_htmltag($resSafe) . '" data-err="' . dol_escape_htmltag($errSafe) . '">< span class="fa fa-search-plus"></span ></a ></td ></tr >< tr >< td colspan="' . $colspan . '" class="opacitymedium"></td ></tr ></table ></div ></form > logModal none logModal none s a JSON string
$moduleobj
Definition index.php:3514
getLicenceHeader($user, $langs, $now)
Produce copyright replacement string for user.
Definition index.php:268
modulebuilderValidateGeneratedFile(string $destfile, NamingContract $nc)
Post-generation validation – logs and displays a warning if residual myobject/mymodule tokens remain.
Definition index.php:289
foreach( $dirsrootforscan as $tmpdirread) moduleBuilderShutdownFunction()
Add management to catch fatal errors - shutdown handler.
Definition index.php:244
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.
filterEnabledTabs($requested, $map)
Filter a list of requested tab keys against the known optional tabs map.
createNewDictionnary($modulename, $file, $namedic, $dictionnaires=null)
Create a new dictionary table.
countItemsInDirectory($path, $type=1)
count directories or files in modulebuilder folder
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.
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.
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:134
if(preg_match('/(crypted|dolcrypt):/i', $dolibarr_main_db_pass)||!empty($dolibarr_main_db_encrypted_pass)) $conf db type
'integer', 'integer:ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter[:Sortfield]]]',...
Definition repair.php:130
$conf db name
Only used if Module[ID]Name translation string is not found.
Definition repair.php:133
restrictedArea(User $user, $features, $object=0, $tableandshare='', $feature2='', $dbt_keyfield='fk_soc', $dbt_select='rowid', $isdraft=0, $mode=0)
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.