dolibarr 23.0.3
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-2025 MDW <mdeweerd@users.noreply.github.com>
6 * Copyright (C) 2024-2025 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';
50require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
51require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
52require_once DOL_DOCUMENT_ROOT.'/core/class/html.formadmin.class.php';
53require_once DOL_DOCUMENT_ROOT.'/core/lib/modulebuilder.lib.php';
54require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
55require_once DOL_DOCUMENT_ROOT.'/core/class/utils.class.php';
56
57// Load translation files required by the page
58$langs->loadLangs(array("admin", "modulebuilder", "exports", "other", "cron", "errors", "uxdocumentation"));
59
60// GET Parameters
61$action = GETPOST('action', 'aZ09');
62$confirm = GETPOST('confirm', 'alpha');
63$cancel = GETPOST('cancel', 'alpha');
64
65$sortfield = GETPOST('sortfield', 'aZ09comma');
66$sortorder = GETPOST('sortorder', 'aZ09');
67
68$module = (string) GETPOST('module', 'alpha');
69$tab = (string) GETPOST('tab', 'aZ09');
70$tabobj = GETPOST('tabobj', 'alpha');
71$tabdic = GETPOST('tabdic', 'alpha');
72$propertykey = GETPOST('propertykey', 'alpha');
73if (empty($module)) {
74 $module = 'initmodule';
75}
76if (empty($tab)) {
77 $tab = 'description';
78}
79'@phan-var-force string $tab'; // Workaround 'empty()' bug of phan
80if (empty($tabobj)) {
81 $tabobj = 'newobjectifnoobj';
82}
83if (empty($tabdic)) {
84 $tabdic = 'newdicifnodic';
85}
86$file = GETPOST('file', 'alpha');
87$find = GETPOST('find', 'alpha');
88
89$modulename = dol_sanitizeFileName(GETPOST('modulename', 'alpha'));
90$objectname = dol_sanitizeFileName(GETPOST('objectname', 'alpha'));
91$dicname = dol_sanitizeFileName(GETPOST('dicname', 'alpha'));
92$editorname = (string) GETPOST('editorname', 'alpha');
93$editorurl = (string) GETPOST('editorurl', 'alpha');
94$version = (string) GETPOST('version', 'alpha');
95$family = (string) GETPOST('family', 'alpha');
96$picto = (string) GETPOST('idpicto', 'alpha');
97$idmodule = (string) GETPOST('idmodule', 'alpha');
98$format = ''; // Prevent undefined in css tab
99
100// Security check
101if (!isModEnabled('modulebuilder')) {
102 accessforbidden('Module ModuleBuilder not enabled');
103}
104if (!$user->hasRight("modulebuilder", "run")) { // after this test $user->hasRight("modulebuilder", "run") is always true, no need to check it more
105 accessforbidden('ModuleBuilderNotAllowed');
106}
107
108// Dir for custom dirs
109$tmp = explode(',', $dolibarr_main_document_root_alt);
110$dirins = $tmp[0];
111$dirread = $dirins;
112$forceddirread = 0;
113
114$tmpdir = explode('@', $module);
115if (!empty($tmpdir[1])) {
116 $module = $tmpdir[0];
117 $dirread = $tmpdir[1];
118 $forceddirread = 1;
119}
120if (GETPOST('dirins', 'alpha')) {
121 $dirread = $dirins = GETPOST('dirins', 'alpha');
122 $forceddirread = 1;
123}
124
125$FILEFLAG = 'modulebuilder.txt';
126
127$now = dol_now();
128$newmask = 0;
129if (empty($newmask) && getDolGlobalString('MAIN_UMASK')) {
130 $newmask = getDolGlobalString('MAIN_UMASK');
131}
132if (empty($newmask)) { // This should no happen
133 $newmask = '0664';
134}
135
136$result = restrictedArea($user, 'modulebuilder', 0);
137
138$error = 0;
139$param = '';
140
141$form = new Form($db);
142
143// Define $listofmodules
144$dirsrootforscan = array($dirread);
145
146// Add also the core modules into the list of modules to show/edit
147if ($dirread != DOL_DOCUMENT_ROOT && (getDolGlobalInt('MAIN_FEATURES_LEVEL') >= 2 || getDolGlobalString('MODULEBUILDER_ADD_DOCUMENT_ROOT'))) {
148 $dirsrootforscan[] = DOL_DOCUMENT_ROOT;
149}
150
151// Search modules to edit
152$textforlistofdirs = '<!-- Directory scanned -->'."\n";
153$listofmodules = array();
154'@phan-var-force array<string,array{modulenamewithcase:string,moduledescriptorrelpath:string,moduledescriptorfullpath:string,moduledescriptorrootpath,moduletype?:string}> $listofmodules';
155$i = 0;
156foreach ($dirsrootforscan as $tmpdirread) {
157 $moduletype = 'external';
158 if ($tmpdirread == DOL_DOCUMENT_ROOT) {
159 $moduletype = 'internal';
160 }
161
162 $dirsincustom = dol_dir_list($tmpdirread, 'directories');
163 if (is_array($dirsincustom) && count($dirsincustom) > 0) {
164 foreach ($dirsincustom as $dircustomcursor) {
165 $fullname = $dircustomcursor['fullname'];
166 if (dol_is_file($fullname.'/'.$FILEFLAG)) {
167 // Get real name of module (MyModule instead of mymodule)
168 $dirtoscanrel = basename($fullname).'/core/modules/';
169
170 $descriptorfiles = dol_dir_list(dirname($fullname).'/'.$dirtoscanrel, 'files', 0, 'mod.*\.class\.php$');
171 if (empty($descriptorfiles)) { // If descriptor not found into module dir, we look into main module dir.
172 $dirtoscanrel = 'core/modules/';
173 $descriptorfiles = dol_dir_list($fullname.'/../'.$dirtoscanrel, 'files', 0, 'mod'.strtoupper(basename($fullname)).'\.class\.php$');
174 }
175 $modulenamewithcase = '';
176 $moduledescriptorrelpath = '';
177 $moduledescriptorfullpath = '';
178
179 foreach ($descriptorfiles as $descriptorcursor) {
180 $modulenamewithcase = preg_replace('/^mod/', '', $descriptorcursor['name']);
181 $modulenamewithcase = preg_replace('/\.class\.php$/', '', $modulenamewithcase);
182 $moduledescriptorrelpath = $dirtoscanrel.$descriptorcursor['name'];
183 $moduledescriptorfullpath = $descriptorcursor['fullname'];
184 //var_dump($descriptorcursor);
185 }
186 if ($modulenamewithcase) {
187 $listofmodules[$dircustomcursor['name']] = array(
188 'modulenamewithcase' => $modulenamewithcase,
189 'moduledescriptorrelpath' => $moduledescriptorrelpath,
190 'moduledescriptorfullpath' => $moduledescriptorfullpath,
191 'moduledescriptorrootpath' => $tmpdirread,
192 'moduletype' => $moduletype
193 );
194 }
195 //var_dump($listofmodules);
196 }
197 }
198 }
199
200 if ($forceddirread && empty($listofmodules)) { // $forceddirread is 1 if we forced dir to read with dirins=... or with module=...@mydir
201 $listofmodules[strtolower($module)] = array(
202 'modulenamewithcase' => $module,
203 'moduledescriptorrelpath' => 'notyetimplemented',
204 'moduledescriptorfullpath' => 'notyetimplemented',
205 'moduledescriptorrootpath' => 'notyetimplemented',
206 );
207 }
208
209 // Show description of content
210 $newdircustom = $dirins;
211 if (empty($newdircustom)) {
212 $newdircustom = img_warning();
213 }
214 // If dirread was forced to somewhere else, by using URL
215 // htdocs/modulebuilder/index.php?module=Inventory@/home/ldestailleur/git/dolibarr/htdocs/product
216 if (empty($i)) {
217 $textforlistofdirs .= $langs->trans("DirScanned").' : ';
218 } else {
219 $textforlistofdirs .= ', ';
220 }
221 $textforlistofdirs .= '<strong class="wordbreakimp">'.$tmpdirread.'</strong>';
222 if ($tmpdirread == DOL_DOCUMENT_ROOT) {
223 if (getDolGlobalInt('MAIN_FEATURES_LEVEL') >= 2) {
224 $textforlistofdirs .= $form->textwithpicto('', $langs->trans("ConstantIsOn", "MAIN_FEATURES_LEVEL"));
225 }
226 if (getDolGlobalString('MODULEBUILDER_ADD_DOCUMENT_ROOT')) {
227 $textforlistofdirs .= $form->textwithpicto('', $langs->trans("ConstantIsOn", "MODULEBUILDER_ADD_DOCUMENT_ROOT"));
228 }
229 }
230 $i++;
231}
232
239{
240 $error = error_get_last();
241 if ($error && ($error['type'] & (E_ERROR | E_PARSE | E_CORE_ERROR | E_COMPILE_ERROR | E_USER_ERROR))) {
242 // Handle the fatal error
243 echo "Fatal error occurred: {$error['message']} in {$error['file']} on line {$error['line']}";
244 // If a header was already send, we suppose it is the llx_Header() so we call the llxFooter()
245 if (headers_sent()) {
246 llxFooter();
247 }
248 }
249}
250register_shutdown_function("moduleBuilderShutdownFunction");
251
252
262function getLicenceHeader($user, $langs, $now)
263{
264 $licInfo = $user->getFullName($langs);
265 $emailTabs = str_repeat("\t", (int) (max(0, (31 - mb_strlen($licInfo)) / 4)));
266 $licInfo .= ($user->email ? $emailTabs.'<'.$user->email.'>' : '');
267 $licInfo = dol_print_date($now, '%Y')."\t\t".$licInfo;
268 return $licInfo;
269}
270
271
272/*
273 * Actions
274 */
275
276if ($dirins && $action == 'initmodule' && $modulename /* && $user->hasRight("modulebuilder", "run") // already checked */) {
277 $modulename = ucfirst($modulename); // Force first letter in uppercase
278 $destdir = '/not_set/';
279
280 if (preg_match('/[^a-z0-9_]/i', $modulename)) {
281 $error++;
282 setEventMessages($langs->trans("SpaceOrSpecialCharAreNotAllowed"), null, 'errors');
283 }
284
285 if (!$error) {
286 $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template';
287 $destdir = $dirins.'/'.strtolower($modulename);
288
289 $arrayreplacement = array(
290 'mymodule' => strtolower($modulename),
291 'MyModule' => $modulename
292 );
293 $result = dolCopyDir($srcdir, $destdir, '0', 0, $arrayreplacement);
294 //dol_mkdir($destfile);
295 if ($result <= 0) {
296 if ($result < 0) {
297 $error++;
298 $langs->load("errors");
299 setEventMessages($langs->trans("ErrorFailToCopyDir", $srcdir, $destdir), null, 'errors');
300 } else {
301 // $result == 0
302 setEventMessages($langs->trans("AllFilesDidAlreadyExist", $srcdir, $destdir), null, 'warnings');
303 }
304 }
305
306 // Copy last 'html.formsetup.class.php' to backport folder
307 if (getDolGlobalInt('MODULEBUILDER_SUPPORT_COMPATIBILITY_V16')) {
308 $tryToCopyFromSetupClass = true;
309 $backportDest = $destdir .'/backport/v16/core/class';
310 $backportFileSrc = DOL_DOCUMENT_ROOT.'/core/class/html.formsetup.class.php';
311 $backportFileDest = $backportDest.'/html.formsetup.class.php';
312 $result = dol_mkdir($backportDest);
313
314 if ($result < 0) {
315 $error++;
316 $langs->load("errors");
317 setEventMessages($langs->trans("ErrorFailToCreateDir", $backportDest), null, 'errors');
318 $tryToCopyFromSetupClass = false;
319 }
320
321 if ($tryToCopyFromSetupClass) {
322 $result = dol_copy($backportFileSrc, $backportFileDest);
323 if ($result <= 0) {
324 if ($result < 0) {
325 $error++;
326 $langs->load("errors");
327 setEventMessages($langs->trans("ErrorFailToCopyFile", $backportFileSrc, $backportFileDest), null, 'errors');
328 } else {
329 setEventMessages($langs->trans("FileDidAlreadyExist", $backportFileDest), null, 'warnings');
330 }
331 }
332 }
333 }
334
335 if (getDolGlobalString('MODULEBUILDER_USE_ABOUT')) {
336 dol_delete_file($destdir.'/admin/about.php');
337 }
338
339 // Delete dir and files that can be generated in sub tabs later if we need them (we want a minimal module first)
340 dol_delete_dir_recursive($destdir.'/ajax');
341 dol_delete_dir_recursive($destdir.'/build/doxygen');
342 dol_delete_dir_recursive($destdir.'/core/modules/mailings');
343 dol_delete_dir_recursive($destdir.'/core/modules/'.strtolower($modulename));
344 dol_delete_dir_recursive($destdir.'/core/tpl');
345 dol_delete_dir_recursive($destdir.'/core/triggers');
346 dol_delete_dir_recursive($destdir.'/doc');
347 //dol_delete_dir_recursive($destdir.'/.tx');
348 dol_delete_dir_recursive($destdir.'/core/boxes');
349
350 dol_delete_file($destdir.'/admin/myobject_extrafields.php');
351
352 dol_delete_file($destdir.'/class/actions_'.strtolower($modulename).'.class.php');
353 dol_delete_file($destdir.'/class/api_'.strtolower($modulename).'.class.php');
354
355 dol_delete_file($destdir.'/css/'.strtolower($modulename).'.css.php');
356
357 dol_delete_file($destdir.'/js/'.strtolower($modulename).'.js.php');
358
359 dol_delete_file($destdir.'/scripts/'.strtolower($modulename).'.php');
360
361 dol_delete_file($destdir.'/sql/data.sql');
362 dol_delete_file($destdir.'/sql/update_x.x.x-y.y.y.sql');
363
364 // Delete some files related to Object (because the previous dolCopyDir has copied everything)
365 dol_delete_file($destdir.'/myobject_card.php');
366 dol_delete_file($destdir.'/myobject_contact.php');
367 dol_delete_file($destdir.'/myobject_note.php');
368 dol_delete_file($destdir.'/myobject_document.php');
369 dol_delete_file($destdir.'/myobject_agenda.php');
370 dol_delete_file($destdir.'/myobject_list.php');
371 dol_delete_file($destdir.'/lib/'.strtolower($modulename).'_myobject.lib.php');
372 dol_delete_file($destdir.'/test/phpunit/functional/'.$modulename.'FunctionalTest.php');
373 dol_delete_file($destdir.'/test/phpunit/MyObjectTest.php');
374 dol_delete_file($destdir.'/sql/llx_'.strtolower($modulename).'_myobject.sql');
375 dol_delete_file($destdir.'/sql/llx_'.strtolower($modulename).'_myobject_extrafields.sql');
376 dol_delete_file($destdir.'/sql/llx_'.strtolower($modulename).'_myobject.key.sql');
377 dol_delete_file($destdir.'/sql/llx_'.strtolower($modulename).'_myobject_extrafields.key.sql');
378 dol_delete_file($destdir.'/class/myobject.class.php');
379
380 dol_delete_dir($destdir.'/class', 1);
381 dol_delete_dir($destdir.'/css', 1);
382 dol_delete_dir($destdir.'/js', 1);
383 dol_delete_dir($destdir.'/scripts', 1);
384 dol_delete_dir($destdir.'/sql', 1);
385 dol_delete_dir($destdir.'/test/phpunit/functionnal', 1);
386 dol_delete_dir($destdir.'/test/phpunit', 1);
387 dol_delete_dir($destdir.'/test', 1);
388 }
389
390 // Edit PHP files
391 if (!$error) {
392 $listofphpfilestoedit = dol_dir_list($destdir, 'files', 1, '\.(php|MD|js|sql|txt|xml|lang)$', '', 'fullname', SORT_ASC, 0, 1);
393
394 $licInfo = getLicenceHeader($user, $langs, $now);
395 foreach ($listofphpfilestoedit as $phpfileval) {
396 //var_dump($phpfileval['fullname']);
397 $arrayreplacement = array(
398 'mymodule' => strtolower($modulename),
399 'MyModule' => $modulename,
400 'MYMODULE' => strtoupper($modulename),
401 'My module' => $modulename,
402 'my module' => $modulename,
403 'Mon module' => $modulename,
404 'mon module' => $modulename,
405 'htdocs/modulebuilder/template' => strtolower($modulename),
406 '---Put here your own copyright and developer email---' => $licInfo,
407 '---Replace with your own copyright and developer email---' => $licInfo,
408 'Editor name' => $editorname,
409 'https://www.example.com' => $editorurl,
410 '$this->version = \'1.0\'' => '$this->version = \''.$version.'\'',
411 '$this->picto = \'generic\';' => (empty($picto)) ? '$this->picto = \'generic\'' : '$this->picto = \''.$picto.'\';',
412 "modulefamily" => $family,
413 '500000' => $idmodule
414 );
415
416 if (getDolGlobalString('MODULEBUILDER_SPECIFIC_AUTHOR')) {
417 $arrayreplacement['---Replace with your own copyright and developer email---'] = dol_print_date($now, '%Y')."\t\t" . getDolGlobalString('MODULEBUILDER_SPECIFIC_AUTHOR');
418 }
419
420 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
421 $result = dolReplaceInFile($phpfileval['fullname'], $arrayreplacement); // @phpstan-ignore-line
422 //var_dump($result);
423 if ($result < 0) {
424 setEventMessages($langs->trans("ErrorFailToMakeReplacementInto", $phpfileval['fullname']), null, 'errors');
425 }
426 }
427
428 if (getDolGlobalString('MODULEBUILDER_SPECIFIC_README')) {
429 setEventMessages($langs->trans("ContentOfREADMECustomized"), null, 'warnings');
430 dol_delete_file($destdir.'/README.md');
431 file_put_contents($destdir.'/README.md', getDolGlobalString("MODULEBUILDER_SPECIFIC_README"));
432 dolChmod($destdir.'/README.md');
433 }
434 // for create file to add properties
435 // file_put_contents($destdir.'/'.strtolower($modulename).'propertycard.php','');
436 // $srcFileCard = DOL_DOCUMENT_ROOT.'/modulebuilder/card.php';
437 // $destFileCard = $dirins.'/'.strtolower($modulename).'/template/card.php';
438 // dol_copy($srcFileCard, $destdir.'/'.strtolower($modulename).'propertycard.php', '0',1, $arrayreplacement);
439 }
440
441 if (!$error) {
442 setEventMessages($langs->trans('ModuleInitialized', $destdir), null);
443 $module = $modulename;
444
445 clearstatcache(true);
446 if (function_exists('opcache_invalidate')) {
447 opcache_reset(); // remove the include cache hell !
448 }
449
450 header("Location: ".$_SERVER["PHP_SELF"].'?module='.$modulename);
451 exit;
452 }
453}
454
455$destdir = '/not_set/'; // Initialize (for static analysis)
456$destfile = '/not_set/'; // Initialize (for static analysis)
457$srcfile = '/not_set/'; // Initialize (for static analysis)
458
459// init API, PHPUnit
460if ($dirins && in_array($action, array('initapi', 'initphpunit', 'initpagecontact', 'initpagedocument', 'initpagenote', 'initpageagenda')) && !empty($module) /* && $user->hasRight("modulebuilder", "run") // already checked */) {
461 $modulename = ucfirst($module); // Force first letter in uppercase
462 $objectname = $tabobj;
463 $varnametoupdate = '';
464 $dirins = $listofmodules[strtolower($module)]['moduledescriptorrootpath'];
465 $destdir = $dirins.'/'.strtolower($module);
466
467 // Get list of existing objects
468 $objects = dolGetListOfObjectClasses($destdir);
469
470
471 if ($action == 'initapi') { // Test on permission already done
472 if (file_exists($dirins.'/'.strtolower($module).'/class/api_'.strtolower($module).'.class.php')) {
473 $result = dol_copy(DOL_DOCUMENT_ROOT.'/modulebuilder/template/class/api_mymodule.class.php', $dirins.'/'.strtolower($module).'/class/api_'.strtolower($module).'.class.php', '0', 1);
474 }
475 dol_mkdir($dirins.'/'.strtolower($module).'/class');
476 $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template';
477 $srcfile = $srcdir.'/class/api_mymodule.class.php';
478 $destfile = $dirins.'/'.strtolower($module).'/class/api_'.strtolower($module).'.class.php';
479 } elseif ($action == 'initphpunit') { // Test on permission already done
480 dol_mkdir($dirins.'/'.strtolower($module).'/test/phpunit');
481 $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template';
482 $srcfile = $srcdir.'/test/phpunit/MyObjectTest.php';
483 $destfile = $dirins.'/'.strtolower($module).'/test/phpunit/'.strtolower($objectname).'Test.php';
484 } elseif ($action == 'initpagecontact') { // Test on permission already done
485 dol_mkdir($dirins.'/'.strtolower($module));
486 $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template';
487 $srcfile = $srcdir.'/myobject_contact.php';
488 $destfile = $dirins.'/'.strtolower($module).'/'.strtolower($objectname).'_contact.php';
489 $varnametoupdate = 'showtabofpagecontact';
490 } elseif ($action == 'initpagedocument') { // Test on permission already done
491 dol_mkdir($dirins.'/'.strtolower($module));
492 $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template';
493 $srcfile = $srcdir.'/myobject_document.php';
494 $destfile = $dirins.'/'.strtolower($module).'/'.strtolower($objectname).'_document.php';
495 $varnametoupdate = 'showtabofpagedocument';
496 } elseif ($action == 'initpagenote') { // Test on permission already done
497 dol_mkdir($dirins.'/'.strtolower($module));
498 $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template';
499 $srcfile = $srcdir.'/myobject_note.php';
500 $destfile = $dirins.'/'.strtolower($module).'/'.strtolower($objectname).'_note.php';
501 $varnametoupdate = 'showtabofpagenote';
502 } elseif ($action == 'initpageagenda') { // Test on permission already done
503 dol_mkdir($dirins.'/'.strtolower($module));
504 $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template';
505 $srcfile = $srcdir.'/myobject_agenda.php';
506 $destfile = $dirins.'/'.strtolower($module).'/'.strtolower($objectname).'_agenda.php';
507 $varnametoupdate = 'showtabofpageagenda';
508 }
509
510 if (!file_exists($destfile)) {
511 $result = dol_copy($srcfile, $destfile, '0', 0);
512 }
513
514 if ($result > 0) {
515 //var_dump($phpfileval['fullname']);
516 $arrayreplacement = array(
517 'mymodule' => strtolower($modulename),
518 'MyModule' => $modulename,
519 'MYMODULE' => strtoupper($modulename),
520 'My module' => $modulename,
521 'my module' => $modulename,
522 'Mon module' => $modulename,
523 'mon module' => $modulename,
524 'htdocs/modulebuilder/template' => strtolower($modulename),
525 'myobject' => strtolower($objectname),
526 'MyObject' => $objectname,
527 'MYOBJECT' => strtoupper($objectname),
528
529 '---Replace with your own copyright and developer email---' => getLicenceHeader($user, $langs, $now)
530 );
531
532 if ($action == 'initapi') { // Test on permission already done
533 if (count($objects) >= 1) {
534 addObjectsToApiFile($srcfile, $destfile, $objects, $modulename);
535 }
536 } else {
537 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
538 dolReplaceInFile($destfile, $arrayreplacement);
539 }
540
541 if ($varnametoupdate) {
542 // Now we update the object file to set $$varnametoupdate to 1
543 $srcfile = $dirins.'/'.strtolower($module).'/lib/'.strtolower($module).'_'.strtolower($objectname).'.lib.php';
544 $arrayreplacement = array('/\$'.preg_quote($varnametoupdate, '/').' = 0;/' => '$'.$varnametoupdate.' = 1;');
545 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
546 dolReplaceInFile($srcfile, $arrayreplacement, '', '0', 0, 1);
547 }
548 } else {
549 $langs->load("errors");
550 setEventMessages($langs->trans('ErrorFailToCreateFile', $destfile), null, 'errors');
551 }
552}
553
554
555// init ExtraFields
556if ($dirins && $action == 'initsqlextrafields' && !empty($module) /* && $user->hasRight("modulebuilder", "run") // already checked */) {
557 $modulename = ucfirst($module); // Force first letter in uppercase
558 $objectname = $tabobj;
559
560 dol_mkdir($dirins.'/'.strtolower($module).'/sql');
561 $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template';
562 $srcfile1 = $srcdir.'/sql/llx_mymodule_myobject_extrafields.sql';
563 $destfile1 = $dirins.'/'.strtolower($module).'/sql/llx_'.strtolower($module).'_'.strtolower($objectname).'_extrafields.sql';
564 $result1 = dol_copy($srcfile1, $destfile1, '0', 0);
565 $srcfile2 = $srcdir.'/sql/llx_mymodule_myobject_extrafields.key.sql';
566 $destfile2 = $dirins.'/'.strtolower($module).'/sql/llx_'.strtolower($module).'_'.strtolower($objectname).'_extrafields.key.sql';
567 $result2 = dol_copy($srcfile2, $destfile2, '0', 0);
568
569 if ($result1 > 0 && $result2 > 0) {
570 $modulename = ucfirst($module); // Force first letter in uppercase
571
572 //var_dump($phpfileval['fullname']);
573 $arrayreplacement = array(
574 'mymodule' => strtolower($modulename),
575 'MyModule' => $modulename,
576 'MYMODULE' => strtoupper($modulename),
577 'My module' => $modulename,
578 'my module' => $modulename,
579 'Mon module' => $modulename,
580 'mon module' => $modulename,
581 'htdocs/modulebuilder/template' => strtolower($modulename),
582 'My Object' => $objectname,
583 'MyObject' => $objectname,
584 'my object' => strtolower($objectname),
585 'myobject' => strtolower($objectname),
586 '---Replace with your own copyright and developer email---' => getLicenceHeader($user, $langs, $now)
587 );
588
589 dolReplaceInFile($destfile1, $arrayreplacement);
590 dolReplaceInFile($destfile2, $arrayreplacement);
591 } else {
592 $langs->load("errors");
593 if ($result1 <= 0) {
594 setEventMessages($langs->trans('ErrorFailToCreateFile', $destfile1), null, 'errors');
595 }
596 if ($result2 <= 0) {
597 setEventMessages($langs->trans('ErrorFailToCreateFile', $destfile2), null, 'errors');
598 }
599 }
600
601 // Now we update the object file to set $this->isextrafieldmanaged to 1
602 $srcfile = $dirins.'/'.strtolower($module).'/class/'.strtolower($objectname).'.class.php';
603 $arrayreplacement = array('/\$this->isextrafieldmanaged = 0;/' => '$this->isextrafieldmanaged = 1;');
604 $arrayreplacement = array('/\$isextrafieldmanaged = 0;/' => '$isextrafieldmanaged = 1;');
605 dolReplaceInFile($srcfile, $arrayreplacement, '', '0', 0, 1);
606}
607
608
609// init Hook
610if ($dirins && $action == 'inithook' && !empty($module) /* && $user->hasRight("modulebuilder", "run") // already checked */) {
611 dol_mkdir($dirins.'/'.strtolower($module).'/class');
612 $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template';
613 $srcfile = $srcdir.'/class/actions_mymodule.class.php';
614 $destfile = $dirins.'/'.strtolower($module).'/class/actions_'.strtolower($module).'.class.php';
615 $result = dol_copy($srcfile, $destfile, '0', 0);
616
617 if ($result > 0) {
618 $modulename = ucfirst($module); // Force first letter in uppercase
619
620 //var_dump($phpfileval['fullname']);
621 $arrayreplacement = array(
622 'mymodule' => strtolower($modulename),
623 'MyModule' => $modulename,
624 'MYMODULE' => strtoupper($modulename),
625 'My module' => $modulename,
626 'my module' => $modulename,
627 'Mon module' => $modulename,
628 'mon module' => $modulename,
629 'htdocs/modulebuilder/template' => strtolower($modulename),
630 '---Replace with your own copyright and developer email---' => getLicenceHeader($user, $langs, $now)
631 );
632
633 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
634 dolReplaceInFile($destfile, $arrayreplacement);
635 } else {
636 $langs->load("errors");
637 setEventMessages($langs->trans('ErrorFailToCreateFile', $destfile), null, 'errors');
638 }
639}
640
641
642// init Trigger
643if ($dirins && $action == 'inittrigger' && !empty($module) /* && $user->hasRight("modulebuilder", "run") // already checked */) {
644 dol_mkdir($dirins.'/'.strtolower($module).'/core/triggers');
645 $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template';
646 $srcfile = $srcdir.'/core/triggers/interface_99_modMyModule_MyModuleTriggers.class.php';
647 $destfile = $dirins.'/'.strtolower($module).'/core/triggers/interface_99_mod'.$module.'_'.$module.'Triggers.class.php';
648 $result = dol_copy($srcfile, $destfile, '0', 0);
649
650 if ($result > 0) {
651 $modulename = ucfirst($module); // Force first letter in uppercase
652
653 //var_dump($phpfileval['fullname']);
654 $arrayreplacement = array(
655 'mymodule' => strtolower($modulename),
656 'MyModule' => $modulename,
657 'MYMODULE' => strtoupper($modulename),
658 'My module' => $modulename,
659 'my module' => $modulename,
660 'Mon module' => $modulename,
661 'mon module' => $modulename,
662 'htdocs/modulebuilder/template' => strtolower($modulename),
663 '---Replace with your own copyright and developer email---' => getLicenceHeader($user, $langs, $now)
664 );
665
666 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
667 dolReplaceInFile($destfile, $arrayreplacement);
668 } else {
669 $langs->load("errors");
670 setEventMessages($langs->trans('ErrorFailToCreateFile', $destfile), null, 'errors');
671 }
672}
673
674
675// init Widget
676if ($dirins && $action == 'initwidget' && !empty($module) /* && $user->hasRight("modulebuilder", "run") // already checked */) {
677 dol_mkdir($dirins.'/'.strtolower($module).'/core/boxes');
678 $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template';
679 $srcfile = $srcdir.'/core/boxes/mymodulewidget1.php';
680 $destfile = $dirins.'/'.strtolower($module).'/core/boxes/'.strtolower($module).'widget1.php';
681 $result = dol_copy($srcfile, $destfile, '0', 0);
682
683 if ($result > 0) {
684 $modulename = ucfirst($module); // Force first letter in uppercase
685
686 //var_dump($phpfileval['fullname']);
687 $arrayreplacement = array(
688 'mymodule' => strtolower($modulename),
689 'MyModule' => $modulename,
690 'MYMODULE' => strtoupper($modulename),
691 'My module' => $modulename,
692 'my module' => $modulename,
693 'Mon module' => $modulename,
694 'mon module' => $modulename,
695 'htdocs/modulebuilder/template' => strtolower($modulename),
696 '---Replace with your own copyright and developer email---' => getLicenceHeader($user, $langs, $now)
697 );
698
699 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
700 dolReplaceInFile($destfile, $arrayreplacement);
701 } else {
702 $langs->load("errors");
703 setEventMessages($langs->trans('ErrorFailToCreateFile', $destfile), null, 'errors');
704 }
705}
706
707
708// init EmailSelector
709if ($dirins && $action == 'initemailing' && !empty($module) /* && $user->hasRight("modulebuilder", "run") // already checked */) {
710 dol_mkdir($dirins.'/'.strtolower($module).'/core/modules/mailings');
711 $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template';
712 $srcfile = $srcdir.'/core/modules/mailings/mailing_mymodule_selector1.modules.php';
713 $destfile = $dirins.'/'.strtolower($module).'/core/modules/mailings/mailing_'.strtolower($module).'_selector1.modules.php';
714 $result = dol_copy($srcfile, $destfile, '0', 0);
715
716 if ($result > 0) {
717 $modulename = ucfirst($module); // Force first letter in uppercase
718
719 //var_dump($phpfileval['fullname']);
720 $arrayreplacement = array(
721 'mymodule' => strtolower($modulename),
722 'MyModule' => $modulename,
723 'MYMODULE' => strtoupper($modulename),
724 'My module' => $modulename,
725 'my module' => $modulename,
726 'Mon module' => $modulename,
727 'mon module' => $modulename,
728 'htdocs/modulebuilder/template' => strtolower($modulename),
729 '---Replace with your own copyright and developer email---' => getLicenceHeader($user, $langs, $now)
730 );
731
732 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
733 dolReplaceInFile($destfile, $arrayreplacement);
734 } else {
735 $langs->load("errors");
736 setEventMessages($langs->trans('ErrorFailToCreateFile', $destfile), null, 'errors');
737 }
738}
739
740
741// init CSS
742if ($dirins && $action == 'initcss' && !empty($module) /* && $user->hasRight("modulebuilder", "run") // already checked */) {
743 dol_mkdir($dirins.'/'.strtolower($module).'/css');
744 $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template';
745 $srcfile = $srcdir.'/css/mymodule.css.php';
746 $destfile = $dirins.'/'.strtolower($module).'/css/'.strtolower($module).'.css.php';
747 $result = dol_copy($srcfile, $destfile, '0', 0);
748
749 if ($result > 0) {
750 $modulename = ucfirst($module); // Force first letter in uppercase
751
752 //var_dump($phpfileval['fullname']);
753 $arrayreplacement = array(
754 'mymodule' => strtolower($modulename),
755 'MyModule' => $modulename,
756 'MYMODULE' => strtoupper($modulename),
757 'My module' => $modulename,
758 'my module' => $modulename,
759 'Mon module' => $modulename,
760 'mon module' => $modulename,
761 'htdocs/modulebuilder/template' => strtolower($modulename),
762 '---Replace with your own copyright and developer email---' => getLicenceHeader($user, $langs, $now)
763 );
764
765 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
766 dolReplaceInFile($destfile, $arrayreplacement);
767
768 // Update descriptor file to uncomment file
769 $srcfile = $dirins.'/'.strtolower($module).'/core/modules/mod'.$module.'.class.php';
770 $arrayreplacement = array('/\/\/\s*\''.preg_quote('/'.strtolower($module).'/css/'.strtolower($module).'.css.php', '/').'\'/' => '\'/'.strtolower($module).'/css/'.strtolower($module).'.css.php\'');
771 dolReplaceInFile($srcfile, $arrayreplacement, '', '0', 0, 1);
772 } else {
773 $langs->load("errors");
774 setEventMessages($langs->trans('ErrorFailToCreateFile', $destfile), null, 'errors');
775 }
776}
777
778
779// init JS
780if ($dirins && $action == 'initjs' && !empty($module) /* && $user->hasRight("modulebuilder", "run") // already checked */) {
781 dol_mkdir($dirins.'/'.strtolower($module).'/js');
782 $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template';
783 $srcfile = $srcdir.'/js/mymodule.js.php';
784 $destfile = $dirins.'/'.strtolower($module).'/js/'.strtolower($module).'.js.php';
785 $result = dol_copy($srcfile, $destfile, '0', 0);
786
787 if ($result > 0) {
788 $modulename = ucfirst($module); // Force first letter in uppercase
789
790 //var_dump($phpfileval['fullname']);
791 $arrayreplacement = array(
792 'mymodule' => strtolower($modulename),
793 'MyModule' => $modulename,
794 'MYMODULE' => strtoupper($modulename),
795 'My module' => $modulename,
796 'my module' => $modulename,
797 'Mon module' => $modulename,
798 'mon module' => $modulename,
799 'htdocs/modulebuilder/template' => strtolower($modulename),
800 '---Replace with your own copyright and developer email---' => getLicenceHeader($user, $langs, $now)
801 );
802
803 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
804 dolReplaceInFile($destfile, $arrayreplacement);
805
806 // Update descriptor file to uncomment file
807 $srcfile = $dirins.'/'.strtolower($module).'/core/modules/mod'.$module.'.class.php';
808 $arrayreplacement = array('/\/\/\s*\''.preg_quote('/'.strtolower($module).'/js/'.strtolower($module).'.js.php', '/').'\'/' => '\'/'.strtolower($module).'/js/'.strtolower($module).'.js.php\'');
809 dolReplaceInFile($srcfile, $arrayreplacement, '', '0', 0, 1);
810 } else {
811 $langs->load("errors");
812 setEventMessages($langs->trans('ErrorFailToCreateFile', $destfile), null, 'errors');
813 }
814}
815
816
817// init CLI
818if ($dirins && $action == 'initcli' && !empty($module) /* && $user->hasRight("modulebuilder", "run") // already checked */) {
819 dol_mkdir($dirins.'/'.strtolower($module).'/scripts');
820 $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template';
821 $srcfile = $srcdir.'/scripts/mymodule.php';
822 $destfile = $dirins.'/'.strtolower($module).'/scripts/'.strtolower($module).'.php';
823 $result = dol_copy($srcfile, $destfile, '0', 0);
824
825 if ($result > 0) {
826 $modulename = ucfirst($module); // Force first letter in uppercase
827
828 //var_dump($phpfileval['fullname']);
829 $arrayreplacement = array(
830 'mymodule' => strtolower($modulename),
831 'MyModule' => $modulename,
832 'MYMODULE' => strtoupper($modulename),
833 'My module' => $modulename,
834 'my module' => $modulename,
835 'Mon module' => $modulename,
836 'mon module' => $modulename,
837 'htdocs/modulebuilder/template' => strtolower($modulename),
838 '__MYCOMPANY_NAME__' => $mysoc->name,
839 '__KEYWORDS__' => $modulename,
840 '__USER_FULLNAME__' => $user->getFullName($langs),
841 '__USER_EMAIL__' => $user->email,
842 '__YYYY-MM-DD__' => dol_print_date($now, 'dayrfc'),
843 '---Replace with your own copyright and developer email---' => getLicenceHeader($user, $langs, $now)
844 );
845
846 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
847 dolReplaceInFile($destfile, $arrayreplacement);
848 } else {
849 $langs->load("errors");
850 setEventMessages($langs->trans('ErrorFailToCreateFile', $destfile), null, 'errors');
851 }
852}
853
854
855$moduledescriptorfile = '/not_set/';
856$modulelowercase = null;
857
858// init Doc
859if ($dirins && $action == 'initdoc' && !empty($module) /* && $user->hasRight("modulebuilder", "run") // already checked */) {
860 dol_mkdir($dirins.'/'.strtolower($module).'/doc');
861 $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template';
862 $srcfile = $srcdir.'/doc/Documentation.asciidoc';
863 $destfile = $dirins.'/'.strtolower($module).'/doc/Documentation.asciidoc';
864 $result = dol_copy($srcfile, $destfile, '0', 0);
865
866 if ($result > 0) {
867 $modulename = ucfirst($module); // Force first letter in uppercase
868 $modulelowercase = strtolower($module);
869
870 //var_dump($phpfileval['fullname']);
871 $arrayreplacement = array(
872 'mymodule' => strtolower($modulename),
873 'MyModule' => $modulename,
874 'MYMODULE' => strtoupper($modulename),
875 'My module' => $modulename,
876 'my module' => $modulename,
877 'Mon module' => $modulename,
878 'mon module' => $modulename,
879 'htdocs/modulebuilder/template' => strtolower($modulename),
880 '__MYCOMPANY_NAME__' => $mysoc->name,
881 '__KEYWORDS__' => $modulename,
882 '__USER_FULLNAME__' => $user->getFullName($langs),
883 '__USER_EMAIL__' => $user->email,
884 '__YYYY-MM-DD__' => dol_print_date($now, 'dayrfc'),
885 '---Replace with your own copyright and developer email---' => getLicenceHeader($user, $langs, $now)
886 );
887
888 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
889 dolReplaceInFile($destfile, $arrayreplacement);
890
891 // add table of properties
892 $dirins = $listofmodules[strtolower($module)]['moduledescriptorrootpath'];
893 $destdir = $dirins.'/'.strtolower($module);
894 $objects = dolGetListOfObjectClasses($destdir);
895 foreach ($objects as $path => $obj) {
896 writePropsInAsciiDoc($path, $obj, $destfile);
897 }
898
899 // add table of permissions
900 $moduledescriptorfile = $dirins.'/'.strtolower($module).'/core/modules/mod'.$module.'.class.php';
901 writePermsInAsciiDoc($moduledescriptorfile, $destfile);
902
903 // add api urls if file exist
904 if (file_exists($dirins.'/'.strtolower($module).'/class/api_'.strtolower($module).'.class.php')) {
905 $apiFile = $dirins.'/'.strtolower($module).'/class/api_'.strtolower($module).'.class.php';
906 writeApiUrlsInDoc($apiFile, $destfile);
907 }
908
909 // add ChangeLog in Doc
910 if (file_exists($dirins.'/'.strtolower($module).'/ChangeLog.md')) {
911 $changeLog = $dirins.'/'.strtolower($module).'/ChangeLog.md';
912 $string = file_get_contents($changeLog);
913
914 $replace = explode("\n", $string);
915 $strreplace = array();
916 foreach ($replace as $line) {
917 if ($line === '') {
918 continue;
919 }
920 if (strpos($line, '##') !== false) {
921 $strreplace[$line] = str_replace('##', '', $line);
922 } else {
923 $strreplace[$line] = $line;
924 }
925 }
926 $stringLog = implode("\n", $strreplace);
927 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
928 dolReplaceInFile($destfile, array('//include::ChangeLog.md[]' => '','__CHANGELOG__' => $stringLog));
929 }
930
931 // Delete old documentation files
932 $FILENAMEDOC = $modulelowercase.'.html';
933 $FILENAMEDOCPDF = $modulelowercase.'.pdf';
934 $outputfiledoc = dol_buildpath($modulelowercase, 0).'/doc/'.$FILENAMEDOC;
935 $outputfiledocurl = dol_buildpath($modulelowercase, 1).'/doc/'.$FILENAMEDOC;
936 $outputfiledocpdf = dol_buildpath($modulelowercase, 0).'/doc/'.$FILENAMEDOCPDF;
937 $outputfiledocurlpdf = dol_buildpath($modulelowercase, 1).'/doc/'.$FILENAMEDOCPDF;
938
939 dol_delete_file($outputfiledoc, 0, 0, 0, null, false, 0);
940 dol_delete_file($outputfiledocpdf, 0, 0, 0, null, false, 0);
941 } else {
942 $langs->load("errors");
943 setEventMessages($langs->trans('ErrorFailToCreateFile', $destfile), null, 'errors');
944 }
945}
946
947
948// add Language
949if ($dirins && $action == 'addlanguage' && !empty($module) /* && $user->hasRight("modulebuilder", "run") // already checked */) {
950 $newlangcode = GETPOST('newlangcode', 'aZ09');
951
952 if ($newlangcode) {
953 $modulelowercase = strtolower($module);
954
955 // Dir for module
956 $diroflang = dol_buildpath($modulelowercase, 0);
957
958 if ($diroflang == $dolibarr_main_document_root.'/'.$modulelowercase) {
959 // This is not a custom module, we force diroflang to htdocs root
960 $diroflang = $dolibarr_main_document_root;
961
962 $srcfile = $diroflang.'/langs/en_US/'.$modulelowercase.'.lang';
963 $destfile = $diroflang.'/langs/'.$newlangcode.'/'.$modulelowercase.'.lang';
964
965 $result = dol_copy($srcfile, $destfile, '0', 0);
966 if ($result < 0) {
967 setEventMessages($langs->trans("ErrorFailToCopyFile", $srcfile, $destfile), null, 'errors');
968 }
969 } else {
970 $srcdir = $diroflang.'/langs/en_US';
971 $srcfile = $diroflang.'/langs/en_US/'.$modulelowercase.'.lang';
972 $destdir = $diroflang.'/langs/'.$newlangcode;
973
974 $arrayofreplacement = array();
975 if (!dol_is_dir($srcdir) || !dol_is_file($srcfile)) {
976 $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template/langs/en_US';
977 $arrayofreplacement = array('mymodule' => $modulelowercase);
978 }
979 $result = dolCopyDir($srcdir, $destdir, '0', 0, $arrayofreplacement);
980 }
981 } else {
982 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Language")), null, 'errors');
983 }
984}
985
986
987// Remove/delete File
988if ($dirins && $action == 'confirm_removefile' && !empty($module) /* && $user->hasRight("modulebuilder", "run") // already checked */) {
989 $objectname = $tabobj;
990 $dirins = $listofmodules[strtolower($module)]['moduledescriptorrootpath'];
991 $destdir = $dirins.'/'.strtolower($module);
992
993 $relativefilename = dol_sanitizePathName(GETPOST('file', 'restricthtml'));
994
995 // Now we delete the file
996 if ($relativefilename) {
997 $dirnametodelete = dirname($relativefilename);
998 $filetodelete = $dirins.'/'.$relativefilename;
999 $dirtodelete = $dirins.'/'.$dirnametodelete;
1000
1001 // Get list of existing objects
1002 $objects = dolGetListOfObjectClasses($destdir);
1003
1004 $keyofobjecttodelete = array_search($objectname, $objects);
1005 if ($keyofobjecttodelete !== false) {
1006 unset($objects[$keyofobjecttodelete]);
1007 }
1008
1009 // Delete or modify the file
1010 if (strpos($relativefilename, 'api') !== false) {
1011 $file_api = $destdir.'/class/api_'.strtolower($module).'.class.php';
1012
1013 $removeFile = removeObjectFromApiFile($file_api, $objects, $objectname);
1014
1015 if (count($objects) == 0) {
1016 $result = dol_delete_file($filetodelete);
1017 }
1018
1019 if ($removeFile) {
1020 setEventMessages($langs->trans("ApiObjectDeleted"), null);
1021 }
1022 } else {
1023 $result = dol_delete_file($filetodelete);
1024 }
1025
1026 if (!$result) {
1027 setEventMessages($langs->trans("ErrorFailToDeleteFile", basename($filetodelete)), null, 'errors');
1028 } else {
1029 // If we delete a .sql file, we delete also the other .sql file
1030 if (preg_match('/\.sql$/', $relativefilename)) {
1031 if (preg_match('/\.key\.sql$/', $relativefilename)) {
1032 $relativefilename = preg_replace('/\.key\.sql$/', '.sql', $relativefilename);
1033 $filetodelete = $dirins.'/'.$relativefilename;
1034 $result = dol_delete_file($filetodelete);
1035 } elseif (preg_match('/\.sql$/', $relativefilename)) {
1036 $relativefilename = preg_replace('/\.sql$/', '.key.sql', $relativefilename);
1037 $filetodelete = $dirins.'/'.$relativefilename;
1038 $result = dol_delete_file($filetodelete);
1039 }
1040 }
1041
1042 if (dol_is_dir_empty($dirtodelete)) {
1043 dol_delete_dir($dirtodelete);
1044 }
1045
1046 // Update descriptor file to comment file
1047 if (in_array($tab, array('css', 'js'))) {
1048 $srcfile = $dirins.'/'.strtolower($module).'/core/modules/mod'.$module.'.class.php';
1049 $arrayreplacement = array('/^\s*\''.preg_quote('/'.$relativefilename, '/').'\',*/m' => ' // \'/'.$relativefilename.'\',');
1050 dolReplaceInFile($srcfile, $arrayreplacement, '', '0', 0, 1);
1051 }
1052
1053 if (preg_match('/_extrafields/', $relativefilename)) {
1054 // Now we update the object file to set $isextrafieldmanaged to 0
1055 $srcfile = $dirins.'/'.strtolower($module).'/class/'.strtolower($objectname).'.class.php';
1056 $arrayreplacement = array('/\$isextrafieldmanaged = 1;/' => '$isextrafieldmanaged = 0;');
1057 dolReplaceInFile($srcfile, $arrayreplacement, '', '0', 0, 1);
1058 }
1059
1060 // Now we update the lib file to set $showtabofpagexxx to 0
1061 $varnametoupdate = '';
1062 $reg = array();
1063 if (preg_match('/_([a-z]+)\.php$/', $relativefilename, $reg)) {
1064 $varnametoupdate = 'showtabofpage'.$reg[1];
1065 }
1066 if ($varnametoupdate) {
1067 $srcfile = $dirins.'/'.strtolower($module).'/lib/'.strtolower($module).'_'.strtolower($objectname).'.lib.php';
1068 $arrayreplacement = array('/\$'.preg_quote($varnametoupdate, '/').' = 1;/' => '$'.preg_quote($varnametoupdate, '/').' = 0;');
1069 dolReplaceInFile($srcfile, $arrayreplacement, '', '0', 0, 1);
1070 }
1071 }
1072 }
1073}
1074
1075// Init an object
1076if ($dirins && $action == 'initobject' && $module && $objectname /* && $user->hasRight("modulebuilder", "run") // already checked */) {
1077 $warning = 0;
1078
1079 $objectname = ucfirst($objectname);
1080
1081 $dirins = $dirread = $listofmodules[strtolower($module)]['moduledescriptorrootpath'];
1082 $moduletype = $listofmodules[strtolower($module)]['moduletype'];
1083
1084 if (preg_match('/[^a-z0-9_]/i', $objectname)) {
1085 $error++;
1086 setEventMessages($langs->trans("SpaceOrSpecialCharAreNotAllowed"), null, 'errors');
1087 $tabobj = 'newobject';
1088 }
1089 if (class_exists($objectname)) {
1090 // TODO Add a more efficient detection. Scan disk ?
1091 $error++;
1092 setEventMessages($langs->trans("AnObjectWithThisClassNameAlreadyExists"), null, 'errors');
1093 $tabobj = 'newobject';
1094 }
1095
1096 $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template';
1097 $destdir = $dirins.'/'.strtolower($module);
1098
1099 // The dir was not created by init
1100 dol_mkdir($destdir.'/class');
1101 dol_mkdir($destdir.'/img');
1102 dol_mkdir($destdir.'/lib');
1103 dol_mkdir($destdir.'/scripts');
1104 dol_mkdir($destdir.'/sql');
1105 dol_mkdir($destdir.'/ajax');
1106
1107 // Scan dir class to find if an object with the same name already exists.
1108 if (!$error) {
1109 $dirlist = dol_dir_list($destdir.'/class', 'files', 0, '\.txt$');
1110 $alreadyfound = false;
1111 foreach ($dirlist as $key => $val) {
1112 $filefound = preg_replace('/\.txt$/', '', $val['name']);
1113 if (strtolower($objectname) == strtolower($filefound) && $objectname != $filefound) {
1114 $alreadyfound = true;
1115 $error++;
1116 setEventMessages($langs->trans("AnObjectAlreadyExistWithThisNameAndDiffCase"), null, 'errors');
1117 break;
1118 }
1119 }
1120 }
1121
1122 // If we must reuse an existing table for properties, define $stringforproperties
1123 // Generate class file from the table
1124 $stringforproperties = '';
1125 $tablename = GETPOST('initfromtablename', 'alpha');
1126 if ($tablename) {
1127 $_results = $db->DDLDescTable($tablename);
1128 if (empty($_results)) {
1129 $error++;
1130 $langs->load("errors");
1131 setEventMessages($langs->trans("ErrorTableNotFound", $tablename), null, 'errors');
1132 } else {
1160 /*public $fields=array(
1161 'rowid' => array('type' => 'integer', 'label' => 'TechnicalID', 'enabled' => 1, 'visible' => -2, 'notnull' => 1, 'index' => 1, 'position' => 1, 'comment' => 'Id'),
1162 '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'),
1163 'entity' => array('type' => 'integer', 'label' => 'Entity', 'enabled' => 1, 'visible' => 0, 'default' => 1, 'notnull' => 1, 'index' => 1, 'position' => 20),
1164 'label' => array('type' => 'varchar(255)', 'label' => 'Label', 'enabled' => 1, 'visible' => 1, 'position' => 30, 'searchall' => 1, 'css' => 'minwidth200', 'help' => 'Help text', 'alwayseditable' => '1'),
1165 'amount' => array('type' => 'double(24,8)', 'label' => 'Amount', 'enabled' => 1, 'visible' => 1, 'default' => 'null', 'position' => 40, 'searchall' => 0, 'isameasure' => 1, 'help' => 'Help text'),
1166 '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'),
1167 'description' => array('type' => 'text', 'label' => 'Descrption', 'enabled' => 1, 'visible' => 0, 'position' => 60),
1168 'note_public' => array('type' => 'html', 'label' => 'NotePublic', 'enabled' => 1, 'visible' => 0, 'position' => 61),
1169 'note_private' => array('type' => 'html', 'label' => 'NotePrivate', 'enabled' => 1, 'visible' => 0, 'position' => 62),
1170 'date_creation' => array('type' => 'datetime', 'label' => 'DateCreation', 'enabled' => 1, 'visible' => -2, 'notnull' => 1, 'position' => 500),
1171 'tms' => array('type' => 'timestamp', 'label' => 'DateModification', 'enabled' => 1, 'visible' => -2, 'notnull' => 1, 'position' => 501),
1172 //'date_valid' => array('type' => 'datetime', 'label' => 'DateCreation', 'enabled' => 1, 'visible' => -2, 'position' => 502),
1173 'fk_user_creat' => array('type' => 'integer', 'label' => 'UserAuthor', 'enabled' => 1, 'visible' => -2, 'notnull' => 1, 'position' => 510),
1174 'fk_user_modif' => array('type' => 'integer', 'label' => 'UserModif', 'enabled' => 1, 'visible' => -2, 'notnull' => -1, 'position' => 511),
1175 //'fk_user_valid' => array('type' => 'integer', 'label' => 'UserValidation', 'enabled' => 1, 'visible' => -1, 'position' => 512),
1176 'import_key' => array('type' => 'varchar(14)', 'label' => 'ImportId', 'enabled' => 1, 'visible' => -2, 'notnull' => -1, 'index' => 0, 'position' => 1000),
1177 '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')),
1178 );*/
1179
1180 $stringforproperties = '// BEGIN MODULEBUILDER PROPERTIES'."\n";
1181 $stringforproperties .= 'public $fields = array('."\n";
1182 $i = 10;
1183 while ($obj = $db->fetch_object($_results)) {
1184 // fieldname
1185 $fieldname = $obj->Field;
1186 // type
1187 $type = $obj->Type;
1188 if ($type == 'int(11)') {
1189 $type = 'integer';
1190 } elseif ($type == 'float') {
1191 $type = 'real';
1192 } elseif (strstr($type, 'tinyint')) {
1193 $type = 'integer';
1194 } elseif (strstr($type, 'url')) {
1195 $type = 'varchar(255)';
1196 } elseif ($obj->Field == 'fk_soc') {
1197 $type = 'integer:Societe:societe/class/societe.class.php';
1198 } elseif (preg_match('/^fk_proj/', $obj->Field)) {
1199 $type = 'integer:Project:projet/class/project.class.php:1:fk_statut=1';
1200 } elseif (preg_match('/^fk_prod/', $obj->Field)) {
1201 $type = 'integer:Product:product/class/product.class.php:1';
1202 } elseif ($obj->Field == 'fk_warehouse') {
1203 $type = 'integer:Entrepot:product/stock/class/entrepot.class.php';
1204 } elseif (preg_match('/^(fk_user|fk_commercial)/', $obj->Field)) {
1205 $type = 'integer:User:user/class/user.class.php';
1206 }
1207
1208 // notnull
1209 $notnull = ($obj->Null == 'YES' ? 0 : 1);
1210 if ($fieldname == 'fk_user_modif') {
1211 $notnull = -1;
1212 }
1213 // label
1214 $label = preg_replace('/_/', '', ucfirst($fieldname));
1215 if ($fieldname == 'rowid') {
1216 $label = 'TechnicalID';
1217 }
1218 if ($fieldname == 'import_key') {
1219 $label = 'ImportId';
1220 }
1221 if ($fieldname == 'fk_soc') {
1222 $label = 'ThirdParty';
1223 }
1224 if (in_array($fieldname, array('tms', 'date_modification'))) {
1225 $label = 'DateModification';
1226 }
1227 if (in_array($fieldname, array('datec', 'date_creation'))) {
1228 $label = 'DateCreation';
1229 }
1230 if ($fieldname == 'date_valid') {
1231 $label = 'DateValidation';
1232 }
1233 if ($fieldname == 'datev') {
1234 $label = 'DateValidation';
1235 }
1236 if ($fieldname == 'note_private') {
1237 $label = 'NotePublic';
1238 }
1239 if ($fieldname == 'note_public') {
1240 $label = 'NotePrivate';
1241 }
1242 if ($fieldname == 'fk_user_creat') {
1243 $label = 'UserAuthor';
1244 }
1245 if ($fieldname == 'fk_user_modif') {
1246 $label = 'UserModif';
1247 }
1248 if ($fieldname == 'fk_user_valid') {
1249 $label = 'UserValidation';
1250 }
1251 // visible
1252 $visible = -1;
1253 if (in_array($fieldname, array('ref', 'label'))) {
1254 $visible = 1;
1255 }
1256 if ($fieldname == 'entity') {
1257 $visible = -2;
1258 }
1259 if ($fieldname == 'entity') {
1260 $visible = -2;
1261 }
1262 if ($fieldname == 'import_key') {
1263 $visible = -2;
1264 }
1265 if ($fieldname == 'fk_user_creat') {
1266 $visible = -2;
1267 }
1268 if ($fieldname == 'fk_user_modif') {
1269 $visible = -2;
1270 }
1271 if (in_array($fieldname, array('ref_ext', 'model_pdf', 'note_public', 'note_private'))) {
1272 $visible = 0;
1273 }
1274 // enabled
1275 $enabled = 1;
1276 // default
1277 $default = '';
1278 if ($fieldname == 'entity') {
1279 $default = 1;
1280 }
1281 // position
1282 $position = $i;
1283 if (in_array($fieldname, array('status', 'statut', 'fk_status', 'fk_statut'))) {
1284 $position = 500;
1285 }
1286 if ($fieldname == 'import_key') {
1287 $position = 900;
1288 }
1289 // $alwayseditable
1290 $alwayseditable = 0;
1291 if ($fieldname == 'label') {
1292 $alwayseditable = 1;
1293 } else {
1294 $alwayseditable = 0;
1295 }
1296 // index
1297 $index = 0;
1298 if ($fieldname == 'entity') {
1299 $index = 1;
1300 }
1301 // css, cssview, csslist
1302 $css = '';
1303 $cssview = '';
1304 $csslist = '';
1305 if (preg_match('/^fk_/', $fieldname)) {
1306 $css = 'maxwidth500 widthcentpercentminusxx';
1307 }
1308 if ($fieldname == 'label') {
1309 $css = 'minwidth300';
1310 $cssview = 'wordbreak';
1311 }
1312 if (in_array($fieldname, array('note_public', 'note_private'))) {
1313 $cssview = 'wordbreak';
1314 }
1315 if (in_array($fieldname, array('ref', 'label')) || preg_match('/integer:/', $type)) {
1316 $csslist = 'tdoverflowmax150';
1317 }
1318
1319 // type
1320 $picto = '';
1321 if (isset($obj->Picto)) { // This should never exists
1322 $picto = $obj->Picto;
1323 }
1324 if (preg_match('/^fk_soc/', $obj->Field)) {
1325 $picto = 'company';
1326 } elseif (preg_match('/^fk_contact/', $obj->Field)) {
1327 $picto = 'contact';
1328 } elseif (preg_match('/^fk_bank/', $obj->Field)) {
1329 $picto = 'bank';
1330 } elseif (preg_match('/^fk_user/', $obj->Field)) {
1331 $picto = 'user';
1332 } elseif (preg_match('/^fk_warehouse/', $obj->Field)) {
1333 $picto = 'warehouse';
1334 } elseif (preg_match('/^fk_prod/', $obj->Field)) {
1335 $picto = 'product';
1336 } elseif (preg_match('/^fk_proj/', $obj->Field)) {
1337 $picto = 'project';
1338 } elseif (preg_match('/^fk_task/', $obj->Field)) {
1339 $picto = 'task';
1340 }
1341
1342 // lang
1343 $lang = $module.'@'.$module;
1344
1345 // Build the property string
1346 $stringforproperties .= "'".$obj->Field."' => array('type' => '".$type."', 'label' => '".$label."',";
1347 if ($default != '') {
1348 $stringforproperties .= " 'default' => ".$default.",";
1349 }
1350 $stringforproperties .= " 'enabled' => ".$enabled.",";
1351 $stringforproperties .= " 'visible' => ".$visible;
1352 if ($notnull) {
1353 $stringforproperties .= ", 'notnull' => ".$notnull;
1354 }
1355 if ($alwayseditable) {
1356 $stringforproperties .= ", 'alwayseditable' => 1";
1357 }
1358 if ($fieldname == 'ref' || $fieldname == 'code') {
1359 $stringforproperties .= ", 'showoncombobox' => 1";
1360 }
1361 $stringforproperties .= ", 'position' => ".$position;
1362 if ($index) {
1363 $stringforproperties .= ", 'index' => ".$index;
1364 }
1365 if ($picto) {
1366 $stringforproperties .= ", 'picto' => '".$picto."'";
1367 }
1368 if ($css) {
1369 $stringforproperties .= ", 'css' => '".$css."'";
1370 }
1371 if ($cssview) {
1372 $stringforproperties .= ", 'cssview' => '".$cssview."'";
1373 }
1374 if ($csslist) {
1375 $stringforproperties .= ", 'csslist' => '".$csslist."'";
1376 }
1377
1378 $stringforproperties .= ", 'lang' => '".$lang."'";
1379
1380 $stringforproperties .= "),\n";
1381 $i += 5;
1382 }
1383 $stringforproperties .= ');'."\n";
1384 $stringforproperties .= '// END MODULEBUILDER PROPERTIES'."\n";
1385 }
1386 }
1387
1388 $filetogenerate = array(); // For static analysis
1389 if (!$error) {
1390 // Copy some files
1391 $filetogenerate = array(
1392 'myobject_card.php' => strtolower($objectname).'_card.php',
1393 'myobject_note.php' => strtolower($objectname).'_note.php',
1394 'myobject_contact.php' => strtolower($objectname).'_contact.php',
1395 'myobject_document.php' => strtolower($objectname).'_document.php',
1396 'myobject_agenda.php' => strtolower($objectname).'_agenda.php',
1397 'myobject_list.php' => strtolower($objectname).'_list.php',
1398 'admin/myobject_extrafields.php' => 'admin/'.strtolower($objectname).'_extrafields.php',
1399 'lib/mymodule_myobject.lib.php' => 'lib/'.strtolower($module).'_'.strtolower($objectname).'.lib.php',
1400 //'test/phpunit/MyObjectTest.php' => 'test/phpunit/'.strtolower($objectname).'Test.php',
1401 'sql/llx_mymodule_myobject.sql' => 'sql/llx_'.strtolower($module).'_'.strtolower($objectname).'.sql',
1402 'sql/llx_mymodule_myobject.key.sql' => 'sql/llx_'.strtolower($module).'_'.strtolower($objectname).'.key.sql',
1403 'sql/llx_mymodule_myobject_extrafields.sql' => 'sql/llx_'.strtolower($module).'_'.strtolower($objectname).'_extrafields.sql',
1404 'sql/llx_mymodule_myobject_extrafields.key.sql' => 'sql/llx_'.strtolower($module).'_'.strtolower($objectname).'_extrafields.key.sql',
1405 //'scripts/mymodule.php' => 'scripts/'.strtolower($objectname).'.php',
1406 'class/myobject.class.php' => 'class/'.strtolower($objectname).'.class.php',
1407 //'class/api_mymodule.class.php' => 'class/api_'.strtolower($module).'.class.php',
1408 'ajax/myobject.php' => 'ajax/'.strtolower($objectname).'.php',
1409 );
1410
1411 if (GETPOST('includerefgeneration', 'aZ09')) {
1412 dol_mkdir($destdir.'/core/modules/'.strtolower($module));
1413
1414 $filetogenerate += array(
1415 'core/modules/mymodule/mod_myobject_advanced.php' => 'core/modules/'.strtolower($module).'/mod_'.strtolower($objectname).'_advanced.php',
1416 'core/modules/mymodule/mod_myobject_standard.php' => 'core/modules/'.strtolower($module).'/mod_'.strtolower($objectname).'_standard.php',
1417 'core/modules/mymodule/modules_myobject.php' => 'core/modules/'.strtolower($module).'/modules_'.strtolower($objectname).'.php',
1418 );
1419 }
1420 if (GETPOST('includedocgeneration', 'aZ09')) {
1421 dol_mkdir($destdir.'/core/modules/'.strtolower($module));
1422 dol_mkdir($destdir.'/core/modules/'.strtolower($module).'/doc');
1423
1424 $filetogenerate += array(
1425 'core/modules/mymodule/doc/doc_generic_myobject_odt.modules.php' => 'core/modules/'.strtolower($module).'/doc/doc_generic_'.strtolower($objectname).'_odt.modules.php',
1426 'core/modules/mymodule/doc/pdf_standard_myobject.modules.php' => 'core/modules/'.strtolower($module).'/doc/pdf_standard_'.strtolower($objectname).'.modules.php'
1427 );
1428 }
1429 if (GETPOST('generatepermissions', 'aZ09')) {
1430 $firstobjectname = 'myobject';
1431 $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
1432 dol_include_once($pathtofile);
1433 $class = 'mod'.$module;
1434 $moduleobj = null;
1435 if (class_exists($class)) {
1436 try {
1437 $moduleobj = new $class($db);
1438 '@phan-var-force DolibarrModules $moduleobj';
1440 } catch (Exception $e) {
1441 $error++;
1442 dol_print_error($db, $e->getMessage());
1443 }
1444 }
1445 if (is_object($moduleobj)) {
1446 $rights = $moduleobj->rights;
1447 } else {
1448 $rights = [];
1449 }
1450 $moduledescriptorfile = $destdir.'/core/modules/mod'.$module.'.class.php';
1451 $checkComment = checkExistComment($moduledescriptorfile, 1);
1452 if ($checkComment < 0) {
1453 setEventMessages($langs->trans("WarningCommentNotFound", $langs->trans("Permissions"), "mod".$module."class.php"), null, 'warnings');
1454 } else {
1455 $generatePerms = reWriteAllPermissions($moduledescriptorfile, $rights, null, null, $objectname, $module, -2);
1456 if ($generatePerms < 0) {
1457 setEventMessages($langs->trans("WarningPermissionAlreadyExist", $langs->transnoentities($objectname)), null, 'warnings');
1458 }
1459 }
1460 }
1461
1462 if (!$error) {
1463 foreach ($filetogenerate as $srcfile => $destfile) {
1464 $result = dol_copy($srcdir.'/'.$srcfile, $destdir.'/'.$destfile, $newmask, 0);
1465 if ($result <= 0) {
1466 if ($result < 0) {
1467 $warning++;
1468 $langs->load("errors");
1469 setEventMessages($langs->trans("ErrorFailToCopyFile", $srcdir.'/'.$srcfile, $destdir.'/'.$destfile), null, 'errors');
1470 } else {
1471 // $result == 0
1472 setEventMessages($langs->trans("FileAlreadyExists", $destfile), null, 'warnings');
1473 }
1474 }
1475 $arrayreplacement = array(
1476 '/myobject\.class\.php/' => strtolower($objectname).'.class.php',
1477 '/myobject\.lib\.php/' => strtolower($objectname).'.lib.php',
1478 );
1479
1480 dolReplaceInFile($destdir.'/'.$destfile, $arrayreplacement, '', '0', 0, 1);
1481 }
1482 }
1483
1484 // Replace property section with $stringforproperties
1485 if (!$error && $stringforproperties) {
1486 //var_dump($stringforproperties);exit;
1487 $arrayreplacement = array(
1488 '/\/\/ BEGIN MODULEBUILDER PROPERTIES.*\/\/ END MODULEBUILDER PROPERTIES/ims' => $stringforproperties
1489 );
1490
1491 dolReplaceInFile($destdir.'/class/'.strtolower($objectname).'.class.php', $arrayreplacement, '', '0', 0, 1);
1492 }
1493
1494 // Edit the class 'class/'.strtolower($objectname).'.class.php'
1495 if (GETPOST('includerefgeneration', 'aZ09')) {
1496 // Replace 'visible' => 1, 'noteditable' => 0, 'default' => ''
1497 $arrayreplacement = array(
1498 '/\'visible\'s*=>s*1,\s*\'noteditable\'s*=>s*0,\s*\'default\'s*=>s*\'\'/' => "'visible' => 4, 'noteditable' => 1, 'default' => '(PROV)'"
1499 );
1500 //var_dump($arrayreplacement);exit;
1501 //var_dump($destdir.'/class/'.strtolower($objectname).'.class.php');exit;
1502 dolReplaceInFile($destdir.'/class/'.strtolower($objectname).'.class.php', $arrayreplacement, '', '0', 0, 1);
1503
1504 $arrayreplacement = array(
1505 '/\'models\' => 0,/' => '\'models\' => 1,'
1506 );
1507 dolReplaceInFile($destdir.'/core/modules/mod'.$module.'.class.php', $arrayreplacement, '', '0', 0, 1);
1508 }
1509
1510 // Edit the setup file and the card page
1511 if (GETPOST('includedocgeneration', 'aZ09')) {
1512 // Replace some var init into some files
1513 $arrayreplacement = array(
1514 '/\$includedocgeneration = 0;/' => '$includedocgeneration = 1;'
1515 );
1516 dolReplaceInFile($destdir.'/class/'.strtolower($objectname).'.class.php', $arrayreplacement, '', '0', 0, 1);
1517 dolReplaceInFile($destdir.'/'.strtolower($objectname).'_card.php', $arrayreplacement, '', '0', 0, 1);
1518
1519 $arrayreplacement = array(
1520 '/\'models\' => 0,/' => '\'models\' => 1,'
1521 );
1522
1523 dolReplaceInFile($destdir.'/core/modules/mod'.$module.'.class.php', $arrayreplacement, '', '0', 0, 1);
1524 }
1525
1526 // TODO Update entries '$myTmpObjects['MyObject'] = array('includerefgeneration' => 0, 'includedocgeneration' => 0);'
1527
1528
1529 // Scan for object class files
1530 $listofobject = dol_dir_list($destdir.'/class', 'files', 0, '\.class\.php$');
1531
1532 $firstobjectname = '';
1533 $stringtoadd = '';
1534 foreach ($listofobject as $fileobj) {
1535 if (preg_match('/^api_/', $fileobj['name'])) {
1536 continue;
1537 }
1538 if (preg_match('/^actions_/', $fileobj['name'])) {
1539 continue;
1540 }
1541
1542 $tmpcontent = file_get_contents($fileobj['fullname']);
1543 $reg = array();
1544 if (preg_match('/class\s+([^\s]*)\s+extends\s+CommonObject/ims', $tmpcontent, $reg)) {
1545 $objectnameloop = $reg[1];
1546 if (empty($firstobjectname)) {
1547 $firstobjectname = $objectnameloop;
1548 }
1549 }
1550
1551 // Regenerate left menu entry in descriptor for $objectname
1552 $stringtoadd = "
1553 \$this->menu[\$r++] = array(
1554 'fk_menu' => 'fk_mainmenu=mymodule',
1555 'type' => 'left',
1556 'titre' => 'MyObject',
1557 'prefix' => img_picto('', \$this->picto, 'class=\"paddingright pictofixedwidth valignmiddle\"'),
1558 'mainmenu' => 'mymodule',
1559 'leftmenu' => 'myobject',
1560 'url' => '/mymodule/myobject_list.php',
1561 'langs' => 'mymodule@mymodule',
1562 'position' => 1000 + \$r,
1563 'enabled' => 'isModEnabled(\"mymodule\")',
1564 'perms' => '".(GETPOST('generatepermissions') ? '$user->hasRight("mymodule", "myobject", "read")' : '1')."',
1565 'target' => '',
1566 'user' => 2,
1567 'object' => 'MyObject'
1568 );
1569 \$this->menu[\$r++] = array(
1570 'fk_menu' => 'fk_mainmenu=mymodule,fk_leftmenu=myobject',
1571 'type' => 'left',
1572 'titre' => 'List MyObject',
1573 'mainmenu' => 'mymodule',
1574 'leftmenu' => 'mymodule_myobject_list',
1575 'url' => '/mymodule/myobject_list.php',
1576 'langs' => 'mymodule@mymodule',
1577 'position' => 1000 + \$r,
1578 'enabled' => 'isModEnabled(\"mymodule\")',
1579 'perms' => '".(GETPOST('generatepermissions') ? '$user->hasRight("mymodule", "myobject", "read")' : '1')."',
1580 'target' => '',
1581 'user' => 2,
1582 'object' => 'MyObject'
1583 );
1584 \$this->menu[\$r++] = array(
1585 'fk_menu' => 'fk_mainmenu=mymodule,fk_leftmenu=myobject',
1586 'type' => 'left',
1587 'titre' => 'New MyObject',
1588 'mainmenu' => 'mymodule',
1589 'leftmenu' => 'mymodule_myobject_new',
1590 'url' => '/mymodule/myobject_card.php?action=create',
1591 'langs' => 'mymodule@mymodule',
1592 'position' => 1000 + \$r,
1593 'enabled' => 'isModEnabled(\"mymodule\")',
1594 'perms' => '".(GETPOST('generatepermissions') ? '$user->hasRight("mymodule", "myobject", "write")' : '1')."',
1595 'target' => '',
1596 'user' => 2,
1597 'object' => 'MyObject'
1598 );";
1599 $stringtoadd = preg_replace('/MyObject/', $objectname, $stringtoadd);
1600 $stringtoadd = preg_replace('/mymodule/', strtolower($module), $stringtoadd);
1601 $stringtoadd = preg_replace('/myobject/', strtolower($objectname), $stringtoadd);
1602
1603 $moduledescriptorfile = $destdir.'/core/modules/mod'.$module.'.class.php';
1604 }
1605 // TODO Allow a replace with regex using dolReplaceInFile with param arryreplacementisregex to 1
1606 // TODO Avoid duplicate addition
1607
1608 // load class and check if menu exist with same object name
1609 $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
1610 dol_include_once($pathtofile);
1611 $class = 'mod'.$module;
1612 $moduleobj = null;
1613 if (class_exists($class)) {
1614 try {
1615 $moduleobj = new $class($db);
1616 '@phan-var-force DolibarrModules $moduleobj';
1618 } catch (Exception $e) {
1619 $error++;
1620 dol_print_error($db, $e->getMessage());
1621 }
1622 }
1623 if (is_object($moduleobj)) {
1624 $menus = $moduleobj->menu;
1625 } else {
1626 $menus = array();
1627 }
1628 $counter = 0 ;
1629 foreach ($menus as $menu) {
1630 if ($menu['leftmenu'] == strtolower($objectname)) {
1631 $counter++;
1632 }
1633 }
1634 if (!$counter) {
1635 $checkComment = checkExistComment($moduledescriptorfile, 0);
1636 if ($checkComment < 0) {
1637 $warning++;
1638 setEventMessages($langs->trans("WarningCommentNotFound", $langs->trans("Menus"), basename($moduledescriptorfile)), null, 'warnings');
1639 } else {
1640 $arrayofreplacement = array('/* BEGIN MODULEBUILDER LEFTMENU MYOBJECT */' => '/* BEGIN MODULEBUILDER LEFTMENU '.strtoupper($objectname).' */'.$stringtoadd."\n\t\t".'/* END MODULEBUILDER LEFTMENU '.strtoupper($objectname).' */'."\n\t\t".'/* BEGIN MODULEBUILDER LEFTMENU MYOBJECT */');
1641 dolReplaceInFile($moduledescriptorfile, $arrayofreplacement);
1642 }
1643 }
1644 // Add module descriptor to list of files to replace "MyObject' string with real name of object.
1645 $filetogenerate[] = 'core/modules/mod'.$module.'.class.php';
1646 }
1647
1648 if (!$error) {
1649 // Edit PHP files to make replacement
1650 foreach ($filetogenerate as $destfile) {
1651 $phpfileval['fullname'] = $destdir.'/'.$destfile;
1652
1653 //var_dump($phpfileval['fullname']);
1654 $arrayreplacement = array(
1655 'mymodule' => strtolower($module),
1656 'MyModule' => $module,
1657 'MYMODULE' => strtoupper($module),
1658 'My module' => $module,
1659 'my module' => $module,
1660 'mon module' => $module,
1661 'Mon module' => $module,
1662 'htdocs/modulebuilder/template/' => strtolower($modulename),
1663 'myobject' => strtolower($objectname),
1664 'MyObject' => $objectname,
1665 //'MYOBJECT' => strtoupper($objectname),
1666 '---Replace with your own copyright and developer email---' => getLicenceHeader($user, $langs, $now)
1667 );
1668
1669 if (getDolGlobalString('MODULEBUILDER_SPECIFIC_AUTHOR')) {
1670 $arrayreplacement['---Replace with your own copyright and developer email---'] = dol_print_date($now, '%Y').' ' . getDolGlobalString('MODULEBUILDER_SPECIFIC_AUTHOR');
1671 }
1672
1673 $result = dolReplaceInFile($phpfileval['fullname'], $arrayreplacement); // @phpstan-ignore-line
1674 //var_dump($result);
1675 if ($result < 0) {
1676 setEventMessages($langs->trans("ErrorFailToMakeReplacementInto", $phpfileval['fullname']), null, 'errors');
1677 }
1678 }
1679 }
1680
1681 if (!$error) {
1682 // Edit the class file to write properties
1683 $object = rebuildObjectClass($destdir, $module, $objectname, $newmask);
1684
1685 if (is_numeric($object) && $object <= 0) {
1686 $pathoffiletoeditsrc = $destdir.'/class/'.strtolower($objectname).'.class.php';
1687 setEventMessages($langs->trans('ErrorFailToCreateFile', $pathoffiletoeditsrc), null, 'errors');
1688 $warning++;
1689 }
1690 // check if documentation was generate and add table of properties object
1691 $file = $destdir.'/class/'.strtolower($objectname).'.class.php';
1692 $destfile = $destdir.'/doc/Documentation.asciidoc';
1693
1694 if (file_exists($destfile)) {
1695 writePropsInAsciiDoc($file, $objectname, $destfile);
1696 }
1697 }
1698 if (!$error) {
1699 // Edit sql with new properties
1700 $result = rebuildObjectSql($destdir, $module, $objectname, $newmask, '', $object);
1701
1702 if ($result <= 0) {
1703 setEventMessages($langs->trans('ErrorFailToCreateFile', '.sql'), null);
1704 $error++;
1705 }
1706 }
1707
1708 if (!$error) {
1709 setEventMessages($langs->trans('FilesForObjectInitialized', $objectname), null);
1710 $tabobj = $objectname;
1711 } else {
1712 $tabobj = 'newobject';
1713 }
1714
1715 // check if module is enabled
1716 if (isModEnabled(strtolower($module))) {
1717 $result = unActivateModule(strtolower($module));
1718 dolibarr_set_const($db, "MAIN_IHM_PARAMS_REV", getDolGlobalInt('MAIN_IHM_PARAMS_REV') + 1, 'chaine', 0, '', $conf->entity);
1719 if ($result) {
1720 setEventMessages($result, null, 'errors');
1721 }
1722 setEventMessages($langs->trans('WarningModuleNeedRefresh', $langs->transnoentities($module)), null, 'warnings');
1723 header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=objects&module='.$module);
1724 exit;
1725 }
1726}
1727
1728// Add a dictionary
1729if ($dirins && $action == 'initdic' && $module && empty($cancel) /* && $user->hasRight("modulebuilder", "run") // already checked */) {
1730 $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
1731 $destdir = $dirins.'/'.strtolower($module);
1732 $moduledescriptorfile = $dirins.'/'.strtolower($module).'/core/modules/mod'.$module.'.class.php';
1733
1734 if (!GETPOST('dicname')) {
1735 $error++;
1736 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Table")), null, 'errors');
1737 }
1738 if (!GETPOST('label')) {
1739 $error++;
1740 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Label")), null, 'errors');
1741 }
1742 if (!$error) {
1743 $newdicname = $dicname;
1744 if (!preg_match('/^c_/', $newdicname)) {
1745 $newdicname = 'c_'.$dicname;
1746 }
1747 dol_include_once($pathtofile);
1748 $class = 'mod'.$module;
1749
1750 if (class_exists($class)) {
1751 try {
1752 $moduleobj = new $class($db);
1753 '@phan-var-force DolibarrModules $moduleobj';
1755 } catch (Exception $e) {
1756 $error++;
1757 dol_print_error($db, $e->getMessage());
1758 }
1759 } else {
1760 $error++;
1761 $langs->load("errors");
1762 dol_print_error($db, $langs->trans("ErrorFailedToLoadModuleDescriptorForXXX", $module));
1763 exit;
1764 }
1765 $dictionaries = $moduleobj->dictionaries;
1766 $checkComment = checkExistComment($moduledescriptorfile, 2);
1767 if ($checkComment < 0) {
1768 setEventMessages($langs->trans("WarningCommentNotFound", $langs->trans("Dictionaries"), "mod".$module."class.php"), null, 'warnings');
1769 } else {
1770 createNewDictionnary($module, $moduledescriptorfile, $newdicname, $dictionaries);
1771 if (function_exists('opcache_invalidate')) {
1772 opcache_reset(); // remove the include cache hell !
1773 }
1774 clearstatcache(true);
1775 header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=dictionaries&module='.$module.($forceddirread ? '@'.$dirread : ''));
1776 exit;
1777 }
1778 }
1779}
1780
1781// Delete a SQL table
1782if ($dirins && ($action == 'droptable' || $action == 'droptableextrafields') && !empty($module) && !empty($tabobj) /* && $user->hasRight("modulebuilder", "run") // already checked */) {
1783 $objectname = $tabobj;
1784
1785 $arrayoftables = array();
1786 if ($action == 'droptable') { // Test on permission already done
1787 $arrayoftables[] = MAIN_DB_PREFIX.strtolower($module).'_'.strtolower($tabobj);
1788 }
1789 if ($action == 'droptableextrafields') { // Test on permission already done
1790 $arrayoftables[] = MAIN_DB_PREFIX.strtolower($module).'_'.strtolower($tabobj).'_extrafields';
1791 }
1792
1793 foreach ($arrayoftables as $tabletodrop) {
1794 $nb = -1;
1795 $sql = "SELECT COUNT(*) as nb FROM ".$tabletodrop;
1796 $resql = $db->query($sql);
1797 if ($resql) {
1798 $obj = $db->fetch_object($resql);
1799 if ($obj) {
1800 $nb = (int) $obj->nb;
1801 }
1802 } else {
1803 if ($db->lasterrno() == 'DB_ERROR_NOSUCHTABLE') {
1804 setEventMessages($langs->trans("TableDoesNotExists", $tabletodrop), null, 'warnings');
1805 } else {
1806 dol_print_error($db);
1807 }
1808 }
1809 if ($nb == 0) {
1810 $resql = $db->DDLDropTable($tabletodrop);
1811 //var_dump($resql);
1812 setEventMessages($langs->trans("TableDropped", $tabletodrop), null, 'mesgs');
1813 } elseif ($nb > 0) {
1814 setEventMessages($langs->trans("TableNotEmptyDropCanceled", $tabletodrop), null, 'warnings');
1815 }
1816 }
1817}
1818
1819if ($dirins && $action == 'addproperty' && empty($cancel) && !empty($module) && (!empty($tabobj) || !empty(GETPOST('obj'))) /* && $user->hasRight("modulebuilder", "run") // already checked */) {
1820 $error = 0;
1821
1822 $objectname = (GETPOST('obj') ? GETPOST('obj') : $tabobj);
1823
1824 $dirins = $dirread = $listofmodules[strtolower($module)]['moduledescriptorrootpath'];
1825 $moduletype = $listofmodules[strtolower($module)]['moduletype'];
1826
1827 $srcdir = $dirread.'/'.strtolower($module);
1828 $destdir = $dirins.'/'.strtolower($module);
1829 dol_mkdir($destdir);
1830
1831 $objects = dolGetListOfObjectClasses($destdir);
1832 if (!in_array($objectname, array_values($objects))) {
1833 $error++;
1834 setEventMessages($langs->trans("ErrorObjectNotFound", $langs->transnoentities($objectname)), null, 'errors');
1835 }
1836
1837 $addfieldentry = array();
1838
1839 // We click on add property
1840 if (!GETPOST('regenerateclasssql') && !GETPOST('regeneratemissing')) {
1841 if (!GETPOST('propname', 'aZ09')) {
1842 $error++;
1843 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Name")), null, 'errors');
1844 }
1845 if (!GETPOST('proplabel', 'alpha')) {
1846 $error++;
1847 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Label")), null, 'errors');
1848 }
1849 if (!GETPOST('proptype', 'alpha')) {
1850 $error++;
1851 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Type")), null, 'errors');
1852 }
1853
1854
1855 if (!$error && !GETPOST('regenerateclasssql') && !GETPOST('regeneratemissing')) {
1856 // Preserve case for composite types such as 'integer:Societe:societe/class/societe.class.php:1:(...__SHARED_ENTITIES__...)'
1857 // because the colon-separated parts include PHP class names (case-sensitive) and __XXX__ substitution
1858 // tokens that are uppercase by convention. Only lowercase simple atomic types (#34602).
1859 $proptype = GETPOST('proptype', 'alpha');
1860 if (strpos($proptype, ':') === false && strpos($proptype, '_') === false) {
1861 $proptype = strtolower($proptype);
1862 }
1863 $addfieldentry = array(
1864 'name' => GETPOST('propname', 'aZ09'),
1865 'label' => GETPOST('proplabel', 'alpha'),
1866 'type' => $proptype,
1867 'arrayofkeyval' => GETPOST('proparrayofkeyval', 'nohtml'), // Example json string '{"0":"Draft","1":"Active","-1":"Cancel"}'
1868 'visible' => GETPOST('propvisible', 'alphanohtml'),
1869 'enabled' => GETPOST('propenabled', 'alphanohtml'),
1870 'position' => GETPOSTINT('propposition'),
1871 'notnull' => GETPOSTINT('propnotnull'),
1872 'index' => GETPOSTINT('propindex'),
1873 'foreignkey' => GETPOST('propforeignkey', 'alpha'),
1874 'searchall' => GETPOSTINT('propsearchall'),
1875 'isameasure' => GETPOSTINT('propisameasure'),
1876 'comment' => GETPOST('propcomment', 'alpha'),
1877 'help' => GETPOST('prophelp', 'alpha'),
1878 'css' => GETPOST('propcss', 'alpha'), // Can be 'maxwidth500 widthcentpercentminusxx' for example
1879 'cssview' => GETPOST('propcssview', 'alpha'),
1880 'csslist' => GETPOST('propcsslist', 'alpha'),
1881 'default' => GETPOST('propdefault', 'restricthtml'),
1882 'noteditable' => GETPOSTINT('propnoteditable'),
1883 //'alwayseditable' => GETPOSTINT('propalwayseditable'),
1884 'validate' => GETPOSTINT('propvalidate')
1885 );
1886
1887 if (!empty($addfieldentry['arrayofkeyval']) && !is_array($addfieldentry['arrayofkeyval'])) {
1888 $tmpdecode = json_decode($addfieldentry['arrayofkeyval'], true);
1889 if ($tmpdecode) { // If string is already a json
1890 $addfieldentry['arrayofkeyval'] = $tmpdecode;
1891 } else { // If string is a list of lines with "key,value"
1892 $tmparray = dolExplodeIntoArray($addfieldentry['arrayofkeyval'], "\n", ",");
1893 $addfieldentry['arrayofkeyval'] = $tmparray;
1894 }
1895 }
1896 }
1897 }
1898
1899 /*if (GETPOST('regeneratemissing'))
1900 {
1901 setEventMessages($langs->trans("FeatureNotYetAvailable"), null, 'warnings');
1902 $error++;
1903 }*/
1904
1905 $moduletype = $listofmodules[strtolower($module)]['moduletype'];
1906
1907 // Edit the class file to write properties
1908 if (!$error) {
1909 $object = rebuildObjectClass($destdir, $module, $objectname, $newmask, $srcdir, $addfieldentry, $moduletype);
1910
1911 if (is_numeric($object) && $object <= 0) {
1912 $pathoffiletoeditsrc = $destdir.'/class/'.strtolower($objectname).'.class.php';
1913 setEventMessages($langs->trans('ErrorFailToCreateFile', $pathoffiletoeditsrc), null, 'errors');
1914 $error++;
1915 }
1916 }
1917
1918 // Edit sql with new properties
1919 if (!$error) {
1920 $result = rebuildObjectSql($destdir, $module, $objectname, $newmask, $srcdir, $object, $moduletype);
1921
1922 if ($result <= 0) {
1923 setEventMessages($langs->trans('ErrorFailToCreateFile', '.sql'), null, 'errors');
1924 $error++;
1925 }
1926 }
1927
1928 if (!$error) {
1929 clearstatcache(true);
1930
1931 setEventMessages($langs->trans('FilesForObjectUpdated', $objectname), null);
1932
1933 setEventMessages($langs->trans('WarningDatabaseIsNotUpdated'), null);
1934
1935 // Make a redirect to reload all data
1936 header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=objects&module='.$module.($forceddirread ? '@'.$dirread : '').'&tabobj='.$objectname.'&nocache='.time());
1937 exit;
1938 }
1939}
1940
1941if ($dirins && $action == 'confirm_deleteproperty' && $propertykey /* && $user->hasRight("modulebuilder", "run") // already checked */) {
1942 $objectname = $tabobj;
1943
1944 $dirins = $dirread = $listofmodules[strtolower($module)]['moduledescriptorrootpath'];
1945 $moduletype = $listofmodules[strtolower($module)]['moduletype'];
1946
1947 $srcdir = $dirread.'/'.strtolower($module);
1948 $destdir = $dirins.'/'.strtolower($module);
1949 dol_mkdir($destdir);
1950
1951 // Edit the class file to write properties
1952 if (!$error) {
1953 $object = rebuildObjectClass($destdir, $module, $objectname, $newmask, $srcdir, array(), $propertykey);
1954
1955 if (is_numeric($object) && $object <= 0) {
1956 $pathoffiletoeditsrc = $destdir.'/class/'.strtolower($objectname).'.class.php';
1957 setEventMessages($langs->trans('ErrorFailToCreateFile', $pathoffiletoeditsrc), null, 'errors');
1958 $error++;
1959 }
1960 }
1961
1962 // Edit sql with new properties
1963 if (!$error) {
1964 $result = rebuildObjectSql($destdir, $module, $objectname, $newmask, $srcdir, $object);
1965
1966 if ($result <= 0) {
1967 setEventMessages($langs->trans('ErrorFailToCreateFile', '.sql'), null, 'errors');
1968 $error++;
1969 }
1970 }
1971
1972 if (!$error) {
1973 setEventMessages($langs->trans('FilesForObjectUpdated', $objectname), null);
1974
1975 clearstatcache(true);
1976
1977 // Make a redirect to reload all data
1978 header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=objects&module='.$module.($forceddirread ? '@'.$dirread : '').'&tabobj='.$objectname);
1979 exit;
1980 }
1981}
1982
1983if ($dirins && $action == 'confirm_deletemodule' /* && $user->hasRight("modulebuilder", "run") // already checked */) {
1984 if (preg_match('/[^a-z0-9_]/i', $module)) {
1985 $error++;
1986 setEventMessages($langs->trans("SpaceOrSpecialCharAreNotAllowed"), null, 'errors');
1987 }
1988
1989 if (!$error) {
1990 $modulelowercase = strtolower($module);
1991
1992 // Dir for module
1993 $dir = $dirins.'/'.$modulelowercase;
1994
1995 $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
1996
1997 // Dir for module
1998 $dir = dol_buildpath($modulelowercase, 0);
1999
2000 // Zip file to build
2001 $FILENAMEZIP = '';
2002
2003 // Load module
2004 dol_include_once($pathtofile);
2005 $class = 'mod'.$module;
2006
2007 $moduleobj = null;
2008
2009 if (class_exists($class)) {
2010 try {
2011 $moduleobj = new $class($db);
2012 '@phan-var-force DolibarrModules $moduleobj';
2014 } catch (Exception $e) {
2015 $error++;
2016 dol_print_error($db, $e->getMessage());
2017 }
2018 } else {
2019 $error++;
2020 $langs->load("errors");
2021 setEventMessages($langs->trans("ErrorFailedToLoadModuleDescriptorForXXX", $module), null, 'warnings');
2022 }
2023
2024 if ($moduleobj) {
2025 $moduleobj->remove();
2026 }
2027
2028 $result = dol_delete_dir_recursive($dir);
2029
2030 if ($result > 0) {
2031 setEventMessages($langs->trans("DirWasRemoved", $modulelowercase), null);
2032
2033 clearstatcache(true);
2034 if (function_exists('opcache_invalidate')) {
2035 opcache_reset(); // remove the include cache hell !
2036 }
2037
2038 header("Location: ".$_SERVER["PHP_SELF"].'?module=deletemodule');
2039 exit;
2040 } else {
2041 setEventMessages($langs->trans("PurgeNothingToDelete"), null, 'warnings');
2042 }
2043 }
2044
2045 $action = '';
2046 $module = 'deletemodule';
2047}
2048
2049if ($dirins && $action == 'confirm_deleteobject' && $objectname /* && $user->hasRight("modulebuilder", "run") // already checked */) {
2050 if (preg_match('/[^a-z0-9_]/i', $objectname)) {
2051 $error++;
2052 setEventMessages($langs->trans("SpaceOrSpecialCharAreNotAllowed"), null, 'errors');
2053 }
2054
2055 if (!$error) {
2056 $modulelowercase = strtolower($module);
2057 $objectlowercase = strtolower($objectname);
2058
2059 // Dir for module
2060 $dir = $dirins.'/'.$modulelowercase;
2061
2062 // Delete some files
2063 $filetodelete = array(
2064 'myobject_card.php' => strtolower($objectname).'_card.php',
2065 'myobject_note.php' => strtolower($objectname).'_note.php',
2066 'myobject_contact.php' => strtolower($objectname).'_contact.php',
2067 'myobject_document.php' => strtolower($objectname).'_document.php',
2068 'myobject_agenda.php' => strtolower($objectname).'_agenda.php',
2069 'myobject_list.php' => strtolower($objectname).'_list.php',
2070 'admin/myobject_extrafields.php' => 'admin/'.strtolower($objectname).'_extrafields.php',
2071 'ajax/myobject.lib.php' => 'ajax/'.strtolower($objectname).'.php',
2072 'lib/mymodule_myobject.lib.php' => 'lib/'.strtolower($module).'_'.strtolower($objectname).'.lib.php',
2073 'test/phpunit/MyObjectTest.php' => 'test/phpunit/'.strtolower($objectname).'Test.php',
2074 'sql/llx_mymodule_myobject.sql' => 'sql/llx_'.strtolower($module).'_'.strtolower($objectname).'.sql',
2075 'sql/llx_mymodule_myobject_extrafields.sql' => 'sql/llx_'.strtolower($module).'_'.strtolower($objectname).'_extrafields.sql',
2076 'sql/llx_mymodule_myobject.key.sql' => 'sql/llx_'.strtolower($module).'_'.strtolower($objectname).'.key.sql',
2077 'sql/llx_mymodule_myobject_extrafields.key.sql' => 'sql/llx_'.strtolower($module).'_'.strtolower($objectname).'_extrafields.key.sql',
2078 'scripts/myobject.php' => 'scripts/'.strtolower($objectname).'.php',
2079 'class/myobject.class.php' => 'class/'.strtolower($objectname).'.class.php',
2080 'class/api_myobject.class.php' => 'class/api_'.strtolower($module).'.class.php',
2081 'core/modules/mymodule/mod_myobject_advanced.php' => 'core/modules/'.strtolower($module).'/mod_'.strtolower($objectname).'_advanced.php',
2082 'core/modules/mymodule/mod_myobject_standard.php' => 'core/modules/'.strtolower($module).'/mod_'.strtolower($objectname).'_standard.php',
2083 'core/modules/mymodule/modules_myobject.php' => 'core/modules/'.strtolower($module).'/modules_'.strtolower($objectname).'.php',
2084 'core/modules/mymodule/doc/doc_generic_myobject_odt.modules.php' => 'core/modules/'.strtolower($module).'/doc/doc_generic_'.strtolower($objectname).'_odt.modules.php',
2085 'core/modules/mymodule/doc/pdf_standard_myobject.modules.php' => 'core/modules/'.strtolower($module).'/doc/pdf_standard_'.strtolower($objectname).'.modules.php'
2086 );
2087
2088 //menu for the object selected
2089 // load class and check if menu,permission,documentation exist for this object
2090 $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
2091 dol_include_once($pathtofile);
2092 $class = 'mod'.$module;
2093 $moduleobj = null;
2094 if (class_exists($class)) {
2095 try {
2096 $moduleobj = new $class($db);
2097 '@phan-var-force DolibarrModules $moduleobj';
2099 } catch (Exception $e) {
2100 $error++;
2101 dol_print_error($db, $e->getMessage());
2102 }
2103 } else {
2104 $error++;
2105 $langs->load("errors");
2106 dol_print_error($db, $langs->trans("ErrorFailedToLoadModuleDescriptorForXXX", $module));
2107 exit;
2108 }
2109 $moduledescriptorfile = $dirins.'/'.strtolower($module).'/core/modules/mod'.$module.'.class.php';
2110
2111 // delete menus linked to the object
2112 $menus = $moduleobj->menu;
2113 $rewriteMenu = checkExistComment($moduledescriptorfile, 0);
2114
2115 if ($rewriteMenu < 0) {
2116 setEventMessages($langs->trans("WarningCommentNotFound", $langs->trans("Menus"), "mod".$module."class.php"), null, 'warnings');
2117 } else {
2118 reWriteAllMenus($moduledescriptorfile, $menus, $objectname, null, -1);
2119 }
2120
2121 // regenerate permissions and delete them
2122 $permissions = $moduleobj->rights;
2123 $rewritePerms = checkExistComment($moduledescriptorfile, 1);
2124 if ($rewritePerms < 0) {
2125 setEventMessages($langs->trans("WarningCommentNotFound", $langs->trans("Permissions"), "mod".$module."class.php"), null, 'warnings');
2126 } else {
2127 reWriteAllPermissions($moduledescriptorfile, $permissions, null, null, $objectname, '', -1);
2128 }
2129 if ($rewritePerms && $rewriteMenu) {
2130 // check if documentation has been generated
2131 $file_doc = $dirins.'/'.strtolower($module).'/doc/Documentation.asciidoc';
2132 deletePropsAndPermsFromDoc($file_doc, $objectname);
2133
2134 clearstatcache(true);
2135 if (function_exists('opcache_invalidate')) {
2136 opcache_reset(); // remove the include cache hell !
2137 }
2138 $resultko = 0;
2139 foreach ($filetodelete as $tmpfiletodelete) {
2140 $resulttmp = dol_delete_file($dir.'/'.$tmpfiletodelete, 0, 0, 1);
2141 $resulttmp = dol_delete_file($dir.'/'.$tmpfiletodelete.'.back', 0, 0, 1);
2142 if (!$resulttmp) {
2143 $resultko++;
2144 }
2145 }
2146
2147 if ($resultko == 0) {
2148 setEventMessages($langs->trans("FilesDeleted"), null);
2149 } else {
2150 setEventMessages($langs->trans("ErrorSomeFilesCouldNotBeDeleted"), null, 'warnings');
2151 }
2152 }
2153 }
2154
2155 $action = '';
2156 if (! $error) {
2157 $tabobj = 'newobject';
2158 } else {
2159 $tabobj = 'deleteobject';
2160 }
2161
2162 // check if module is enabled
2163 if (isModEnabled(strtolower($module))) {
2164 $result = unActivateModule(strtolower($module));
2165 dolibarr_set_const($db, "MAIN_IHM_PARAMS_REV", getDolGlobalInt('MAIN_IHM_PARAMS_REV') + 1, 'chaine', 0, '', $conf->entity);
2166 if ($result) {
2167 setEventMessages($result, null, 'errors');
2168 }
2169 setEventMessages($langs->trans('WarningModuleNeedRefresh', $langs->transnoentities($module)), null, 'warnings');
2170 header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=objects&tabobj=deleteobject&module='.urlencode($module));
2171 exit;
2172 }
2173}
2174
2175if (($dirins && $action == 'confirm_deletedictionary' && $dicname) || ($dirins && $action == 'confirm_deletedictionary' && GETPOST('dictionnarykey')) /* && $user->hasRight("modulebuilder", "run") // already checked */) {
2176 $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
2177 $destdir = $dirins.'/'.strtolower($module);
2178 $moduledescriptorfile = $dirins.'/'.strtolower($module).'/core/modules/mod'.$module.'.class.php';
2179
2180 if (preg_match('/[^a-z0-9_]/i', $dicname)) {
2181 $error++;
2182 setEventMessages($langs->trans("SpaceOrSpecialCharAreNotAllowed"), null, 'errors');
2183 }
2184
2185 if (!empty($dicname)) {
2186 $newdicname = $dicname;
2187 if (!preg_match('/^c_/', $newdicname)) {
2188 $newdicname = 'c_'.strtolower($dicname);
2189 }
2190 } else {
2191 $newdicname = null;
2192 }
2193
2194 dol_include_once($pathtofile);
2195 $class = 'mod'.$module;
2196
2197 if (class_exists($class)) {
2198 try {
2199 $moduleobj = new $class($db);
2200 '@phan-var-force DolibarrModules $moduleobj';
2202 } catch (Exception $e) {
2203 $error++;
2204 dol_print_error($db, $e->getMessage());
2205 }
2206 } else {
2207 $error++;
2208 $langs->load("errors");
2209 dol_print_error($db, $langs->trans("ErrorFailedToLoadModuleDescriptorForXXX", $module));
2210 exit;
2211 }
2212
2213 $dicts = $moduleobj->dictionaries;
2214 $checkComment = checkExistComment($moduledescriptorfile, 2);
2215 if ($checkComment < 0) {
2216 $error++;
2217 setEventMessages($langs->trans("WarningCommentNotFound", $langs->trans("Dictionaries"), "mod".$module."class.php"), null, 'warnings');
2218 }
2219
2220 if (!empty(GETPOST('dictionnarykey'))) {
2221 $newdicname = $dicts['tabname'][GETPOSTINT('dictionnarykey') - 1];
2222 }
2223
2224 // Lookup the table dicname
2225 $checkTable = false;
2226 if ($newdicname !== null) {
2227 $checkTable = $db->DDLDescTable(MAIN_DB_PREFIX.strtolower($newdicname));
2228 }
2229
2230 if (is_bool($checkTable) || $db->num_rows($checkTable) <= 0) { // @phpstan-ignore-line
2231 $error++;
2232 }
2233
2234 // search the key by name
2235 $keyToDelete = null;
2236 foreach ($dicts['tabname'] as $key => $table) {
2237 //var_dump($table." /////// ".$newdicname);exit;
2238 if (strtolower($table) === $newdicname) {
2239 $keyToDelete = $key;
2240 break;
2241 }
2242 }
2243 // delete all dicname's key values from the dictionary
2244 if ($keyToDelete !== null) {
2245 $keysToDelete = ['tabname', 'tablib', 'tabsql', 'tabsqlsort', 'tabfield', 'tabfieldvalue', 'tabfieldinsert', 'tabrowid', 'tabcond', 'tabhelp'];
2246 foreach ($keysToDelete as $key) {
2247 unset($dicts[$key][$keyToDelete]);
2248 }
2249 } else {
2250 $error++;
2251 setEventMessages($langs->trans("ErrorDictionaryNotFound", ucfirst($dicname)), null, 'errors');
2252 }
2253 if (!$error && $newdicname !== null) {
2254 // delete table
2255 $_results = $db->DDLDropTable(MAIN_DB_PREFIX.strtolower($newdicname));
2256 if ($_results < 0) {
2257 dol_print_error($db);
2258 $langs->load("errors");
2259 setEventMessages($langs->trans("ErrorTableNotFound", $newdicname), null, 'errors');
2260 }
2261 // rebuild file after update dictionaries
2262 $result = updateDictionaryInFile($module, $moduledescriptorfile, $dicts);
2263 if ($result > 0) {
2264 setEventMessages($langs->trans("DictionaryDeleted", ucfirst(substr($newdicname, 2))), null);
2265 }
2266 if (function_exists('opcache_invalidate')) {
2267 opcache_reset(); // remove the include cache hell !
2268 }
2269 clearstatcache(true);
2270 header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=dictionaries&module='.$module.($forceddirread ? '@'.$dirread : ''));
2271 exit;
2272 }
2273}
2274if ($dirins && $action == 'updatedictionary' && GETPOST('dictionnarykey') /* && $user->hasRight("modulebuilder", "run") // already checked */) {
2275 $keydict = GETPOSTINT('dictionnarykey') - 1 ;
2276
2277 $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
2278 $destdir = $dirins.'/'.strtolower($module);
2279 $moduledescriptorfile = $dirins.'/'.strtolower($module).'/core/modules/mod'.$module.'.class.php';
2280 dol_include_once($pathtofile);
2281 $class = 'mod'.$module;
2282
2283 if (class_exists($class)) {
2284 try {
2285 $moduleobj = new $class($db);
2286 '@phan-var-force DolibarrModules $moduleobj';
2288 } catch (Exception $e) {
2289 $error++;
2290 dol_print_error($db, $e->getMessage());
2291 }
2292 } else {
2293 $error++;
2294 $langs->load("errors");
2295 dol_print_error($db, $langs->trans("ErrorFailedToLoadModuleDescriptorForXXX", $module));
2296 exit;
2297 }
2298
2299 $dicts = $moduleobj->dictionaries;
2300 if (!empty(GETPOST('tablib')) && GETPOST('tablib') !== $dicts['tablib'][$keydict]) {
2301 $dicts['tablib'][$keydict] = ucfirst(strtolower(GETPOST('tablib')));
2302 $checkComment = checkExistComment($moduledescriptorfile, 2);
2303 if ($checkComment < 0) {
2304 setEventMessages($langs->trans("WarningCommentNotFound", $langs->trans("Dictionaries"), "mod".$module."class.php"), null, 'warnings');
2305 } else {
2306 $updateDict = updateDictionaryInFile($module, $moduledescriptorfile, $dicts);
2307 if ($updateDict > 0) {
2308 setEventMessages($langs->trans("DictionaryNameUpdated", ucfirst(GETPOST('tablib'))), null);
2309 }
2310 if (function_exists('opcache_invalidate')) {
2311 opcache_reset(); // remove the include cache hell !
2312 }
2313 clearstatcache(true);
2314 header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=dictionaries&module='.$module.($forceddirread ? '@'.$dirread : ''));
2315 exit;
2316 }
2317 }
2318 //var_dump(GETPOST('tablib'));exit;
2319}
2320if ($dirins && $action == 'generatedoc' /* && $user->hasRight("modulebuilder", "run") // already checked */) {
2321 $modulelowercase = strtolower($module);
2322
2323 // Dir for module
2324 $dirofmodule = dol_buildpath($modulelowercase, 0).'/doc';
2325
2326 $FILENAMEDOC = strtolower($module).'.html';
2327
2328 $util = new Utils($db);
2329 $result = $util->generateDoc($module);
2330
2331 if ($result > 0) {
2332 setEventMessages($langs->trans("DocFileGeneratedInto", $dirofmodule), null);
2333 } else {
2334 setEventMessages($util->error, $util->errors, 'errors');
2335 }
2336}
2337
2338if ($dirins && $action == 'generatepackage' /* && $user->hasRight("modulebuilder", "run") // already checked */) {
2339 $modulelowercase = strtolower($module);
2340
2341 $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
2342
2343 // Dir for module
2344 $dir = dol_buildpath($modulelowercase, 0);
2345
2346 // Zip file to build
2347 $FILENAMEZIP = '';
2348
2349 // Load module
2350 dol_include_once($pathtofile);
2351 $class = 'mod'.$module;
2352
2353 if (class_exists($class)) {
2354 try {
2355 $moduleobj = new $class($db);
2356 '@phan-var-force DolibarrModules $moduleobj';
2358 } catch (Exception $e) {
2359 $error++;
2360 dol_print_error($db, $e->getMessage());
2361 }
2362 } else {
2363 $error++;
2364 $langs->load("errors");
2365 dol_print_error($db, $langs->trans("ErrorFailedToLoadModuleDescriptorForXXX", $module));
2366 exit;
2367 }
2368
2369 $arrayversion = explode('.', $moduleobj->version, 3);
2370 if (count($arrayversion)) {
2371 $FILENAMEZIP = "module_".$modulelowercase.'-'.$arrayversion[0].(empty($arrayversion[1]) ? '.0' : '.'.$arrayversion[1]).(empty($arrayversion[2]) ? '' : '.'.$arrayversion[2]).'.zip';
2372
2373 $dirofmodule = dol_buildpath($modulelowercase, 0).'/bin';
2374 $outputfilezip = $dirofmodule.'/'.$FILENAMEZIP;
2375
2376 if (!dol_is_dir($dirofmodule)) {
2377 dol_mkdir($dirofmodule);
2378 }
2379 // Note: We exclude /bin/ to not include the already generated zip
2380 $result = dol_compress_dir($dir, $outputfilezip, 'zip', '/\/bin\/|\.git|\.old|\.back|\.ssh/', $modulelowercase);
2381
2382 if ($result > 0) {
2383 setEventMessages($langs->trans("ZipFileGeneratedInto", $outputfilezip), null);
2384 } else {
2385 $error++;
2386 $langs->load("errors");
2387 setEventMessages($langs->trans("ErrorFailToGenerateFile", $outputfilezip), null, 'errors');
2388 }
2389 } else {
2390 $error++;
2391 $langs->load("errors");
2392 setEventMessages($langs->trans("ErrorCheckVersionIsDefined"), null, 'errors');
2393 }
2394}
2395
2396// Add permission
2397if ($dirins && $action == 'addright' && !empty($module) && empty($cancel) /* && $user->hasRight("modulebuilder", "run") // already checked */) {
2398 $error = 0;
2399
2400 // load class and check if right exist
2401 $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
2402 dol_include_once($pathtofile);
2403 $class = 'mod'.$module;
2404 $moduleobj = null;
2405 if (class_exists($class)) {
2406 try {
2407 $moduleobj = new $class($db);
2408 '@phan-var-force DolibarrModules $moduleobj';
2410 } catch (Exception $e) {
2411 $error++;
2412 dol_print_error($db, $e->getMessage());
2413 }
2414 }
2415
2416 // verify information entered
2417 if (!GETPOST('label', 'alpha')) {
2418 $error++;
2419 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Label")), null, 'errors');
2420 }
2421 if (!GETPOST('permissionObj', 'alpha')) {
2422 $error++;
2423 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Rights")), null, 'errors');
2424 }
2425
2426 $id = GETPOST('id', 'alpha');
2427 $label = GETPOST('label', 'alpha');
2428 $objectForPerms = strtolower(GETPOST('permissionObj', 'alpha'));
2429 $crud = GETPOST('crud', 'alpha');
2430
2431 //check existing object permission
2432 $counter = 0;
2433 $permsForObject = array();
2434 if (is_object($moduleobj)) {
2435 $permissions = $moduleobj->rights;
2436 } else {
2437 $permissions = array();
2438 }
2439 $allObject = array();
2440
2441 $countPerms = count($permissions);
2442
2443 for ($i = 0; $i < $countPerms; $i++) {
2444 if ($permissions[$i][4] == $objectForPerms) {
2445 $counter++;
2446 if (count($permsForObject) < 3) {
2447 $permsForObject[] = $permissions[$i];
2448 }
2449 }
2450 $allObject[] = $permissions[$i][4];
2451 }
2452
2453 // check if label of object already exists
2454 $countPermsObj = count($permsForObject);
2455 for ($j = 0; $j < $countPermsObj; $j++) {
2456 if (in_array($crud, $permsForObject[$j])) {
2457 $error++;
2458 setEventMessages($langs->trans("ErrorExistingPermission", $langs->transnoentities($crud), $langs->transnoentities($objectForPerms)), null, 'errors');
2459 }
2460 }
2461
2462 $rightToAdd = array();
2463 if (!$error) {
2464 $key = $countPerms + 1;
2465 //prepare right to add
2466 $rightToAdd = array(
2467 0 => $id,
2468 1 => $label,
2469 4 => $objectForPerms,
2470 5 => $crud
2471 );
2472
2473 if (isModEnabled(strtolower($module))) {
2474 $result = unActivateModule(strtolower($module));
2475 dolibarr_set_const($db, "MAIN_IHM_PARAMS_REV", getDolGlobalInt('MAIN_IHM_PARAMS_REV') + 1, 'chaine', 0, '', $conf->entity);
2476 if ($result) {
2477 setEventMessages($result, null, 'errors');
2478 }
2479 setEventMessages($langs->trans('WarningModuleNeedRefresh', $langs->transnoentities($module)), null, 'warnings');
2480 }
2481
2482 $moduledescriptorfile = $dirins.'/'.strtolower($module).'/core/modules/mod'.$module.'.class.php';
2483 // Rewriting all permissions section in the descriptor file
2484 $rewrite = checkExistComment($moduledescriptorfile, 1);
2485 if ($rewrite < 0) {
2486 setEventMessages($langs->trans("WarningCommentNotFound", $langs->trans("Permissions"), "mod".$module."class.php"), null, 'warnings');
2487 } else {
2488 reWriteAllPermissions($moduledescriptorfile, $permissions, $key, $rightToAdd, '', '', 1);
2489 setEventMessages($langs->trans('PermissionAddedSuccesfuly'), null);
2490
2491 clearstatcache(true);
2492 if (function_exists('opcache_invalidate')) {
2493 opcache_reset(); // remove the include cache hell !
2494 }
2495 header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=permissions&module='.$module);
2496 exit;
2497 }
2498 }
2499}
2500
2501
2502// Update permission
2503if ($dirins && GETPOST('action') == 'update_right' && GETPOST('modifyright') && empty($cancel) /* && $user->hasRight("modulebuilder", "run") // already checked */) {
2504 $error = 0;
2505 // load class and check if right exist
2506 $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
2507 dol_include_once($pathtofile);
2508 $class = 'mod'.$module;
2509 $moduleobj = null;
2510 if (class_exists($class)) {
2511 try {
2512 $moduleobj = new $class($db);
2513 '@phan-var-force DolibarrModules $moduleobj';
2515 } catch (Exception $e) {
2516 $error++;
2517 dol_print_error($db, $e->getMessage());
2518 }
2519 }
2520 // verify information entered
2521 if (!GETPOST('label', 'alpha')) {
2522 $error++;
2523 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Label")), null, 'errors');
2524 }
2525 if (!GETPOST('permissionObj', 'alpha')) {
2526 $error++;
2527 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Rights")), null, 'errors');
2528 }
2529
2530 $label = GETPOST('label', 'alpha');
2531 $objectForPerms = strtolower(GETPOST('permissionObj', 'alpha'));
2532 $crud = GETPOST('crud', 'alpha');
2533
2534
2535 if ($label == "Read objects of $module" && $crud != "read") {
2536 $crud = "read";
2537 // $label = "Read objects of $module";
2538 }
2539 if ($label == "Create/Update objects of $module" && $crud != "write") {
2540 $crud = "write";
2541 // $label = "Create/Update objects of $module";
2542 }
2543 if ($label == "Delete objects of $module" && $crud != "delete") {
2544 $crud = "delete";
2545 // $label = "Delete objects of $module";
2546 }
2547
2548 if (is_object($moduleobj)) {
2549 $permissions = $moduleobj->rights;
2550 } else {
2551 $permissions = [];
2552 }
2553 $key = GETPOSTINT('counter') - 1;
2554 //get permission want to delete from permissions array
2555 if (array_key_exists($key, $permissions)) {
2556 $x1 = $permissions[$key][1];
2557 $x2 = $permissions[$key][4];
2558 $x3 = $permissions[$key][5];
2559 } else {
2560 $x1 = null;
2561 $x2 = null;
2562 $x3 = null;
2563 }
2564 //check existing object permission
2565 $counter = 0;
2566 $permsForObject = array();
2567 // $permissions = $moduleobj->rights; // Already fetched above
2568 $firstRight = 0;
2569 $existRight = 0;
2570 $allObject = array();
2571
2572 $countPerms = count($permissions);
2573 for ($i = 0; $i < $countPerms; $i++) {
2574 if ($permissions[$i][4] == $objectForPerms) {
2575 $counter++;
2576 if (count($permsForObject) < 3) {
2577 $permsForObject[] = $permissions[$i];
2578 }
2579 }
2580 $allObject[] = $permissions[$i][4];
2581 }
2582
2583 if ($label != $x1 && $crud != $x3) {
2584 $countPermsObj = count($permsForObject);
2585 for ($j = 0; $j < $countPermsObj; $j++) {
2586 if (in_array($label, $permsForObject[$j])) {
2587 $error++;
2588 setEventMessages($langs->trans("ErrorExistingPermission", $langs->transnoentities($label), $langs->transnoentities($objectForPerms)), null, 'errors');
2589 }
2590 }
2591 }
2592
2593 if (!$error) {
2594 if (isModEnabled(strtolower($module))) {
2595 $result = unActivateModule(strtolower($module));
2596 dolibarr_set_const($db, "MAIN_IHM_PARAMS_REV", getDolGlobalInt('MAIN_IHM_PARAMS_REV') + 1, 'chaine', 0, '', $conf->entity);
2597 if ($result) {
2598 setEventMessages($result, null, 'errors');
2599 }
2600 setEventMessages($langs->trans('WarningModuleNeedRefresh', $langs->transnoentities($module)), null, 'warnings');
2601 }
2602
2603 $moduledescriptorfile = $dirins.'/'.strtolower($module).'/core/modules/mod'.$module.'.class.php';
2604 // rewriting all permissions after update permission needed
2605 $rewrite = checkExistComment($moduledescriptorfile, 1);
2606 if ($rewrite < 0) {
2607 setEventMessages($langs->trans("WarningCommentNotFound", $langs->trans("Permissions"), "mod".$module."class.php"), null, 'warnings');
2608 } else {
2609 $rightUpdated = null; // I not set at this point
2610 reWriteAllPermissions($moduledescriptorfile, $permissions, $key, $rightUpdated, '', '', 2);
2611 setEventMessages($langs->trans('PermissionUpdatedSuccesfuly'), null);
2612 clearstatcache(true);
2613 if (function_exists('opcache_invalidate')) {
2614 opcache_reset(); // remove the include cache hell !
2615 }
2616 header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=permissions&module='.$module);
2617 exit;
2618 }
2619 }
2620}
2621// Delete permission
2622if ($dirins && $action == 'confirm_deleteright' && !empty($module) && GETPOSTINT('permskey') /* && $user->hasRight("modulebuilder", "run") // already checked */) {
2623 $error = 0;
2624 // load class and check if right exist
2625 $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
2626 dol_include_once($pathtofile);
2627 $class = 'mod'.$module;
2628 $moduleobj = null;
2629 if (class_exists($class)) {
2630 try {
2631 $moduleobj = new $class($db);
2632 '@phan-var-force DolibarrModules $moduleobj';
2634 } catch (Exception $e) {
2635 $error++;
2636 dol_print_error($db, $e->getMessage());
2637 }
2638 }
2639
2640 $permissions = $moduleobj->rights;
2641 $key = GETPOSTINT('permskey') - 1;
2642
2643 if (!$error) {
2644 // check if module is enabled
2645 if (isModEnabled(strtolower($module))) {
2646 $result = unActivateModule(strtolower($module));
2647 dolibarr_set_const($db, "MAIN_IHM_PARAMS_REV", getDolGlobalInt('MAIN_IHM_PARAMS_REV') + 1, 'chaine', 0, '', $conf->entity);
2648 if ($result) {
2649 setEventMessages($result, null, 'errors');
2650 }
2651 setEventMessages($langs->trans('WarningModuleNeedRefresh', $langs->transnoentities($module)), null, 'warnings');
2652 header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=permissions&module='.$module);
2653 exit;
2654 }
2655
2656 // rewriting all permissions
2657 $moduledescriptorfile = $dirins.'/'.strtolower($module).'/core/modules/mod'.$module.'.class.php';
2658 $rewrite = checkExistComment($moduledescriptorfile, 1);
2659 if ($rewrite < 0) {
2660 setEventMessages($langs->trans("WarningCommentNotFound", $langs->trans("Permissions"), "mod".$module."class.php"), null, 'warnings');
2661 } else {
2662 reWriteAllPermissions($moduledescriptorfile, $permissions, $key, null, '', '', 0);
2663 setEventMessages($langs->trans('PermissionDeletedSuccesfuly'), null);
2664
2665 clearstatcache(true);
2666 if (function_exists('opcache_invalidate')) {
2667 opcache_reset(); // remove the include cache hell !
2668 }
2669
2670 header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=permissions&module='.$module);
2671 exit;
2672 }
2673 }
2674}
2675// Save file
2676if ($action == 'savefile' && empty($cancel) /* && $user->hasRight("modulebuilder", "run") // already checked */) {
2677 $relofcustom = basename($dirins);
2678
2679 if ($relofcustom) {
2680 // Check that relative path ($file) start with name 'custom'
2681 if (!preg_match('/^'.$relofcustom.'/', $file)) {
2682 $file = $relofcustom.'/'.$file;
2683 }
2684
2685 $pathoffile = dol_buildpath($file, 0);
2686 $pathoffilebackup = dol_buildpath($file.'.back', 0);
2687
2688 // Save old version
2689 if (dol_is_file($pathoffile)) {
2690 dol_copy($pathoffile, $pathoffilebackup, '0', 1);
2691 }
2692
2693 $check = 'restricthtml';
2694 $srclang = dol_mimetype($pathoffile, '', 3);
2695 if ($srclang == 'md') {
2696 $check = 'restricthtml';
2697 }
2698 if ($srclang == 'lang') {
2699 $check = 'restricthtml';
2700 }
2701 if ($srclang == 'php') {
2702 $check = 'none';
2703 }
2704
2705 $content = GETPOST('editfilecontent', $check);
2706
2707 // Save file on disk
2708 if ($content) {
2709 dol_delete_file($pathoffile);
2710 $result = file_put_contents($pathoffile, $content);
2711 if ($result) {
2712 dolChmod($pathoffile, $newmask);
2713
2714 setEventMessages($langs->trans("FileSaved"), null);
2715 } else {
2716 setEventMessages($langs->trans("ErrorFailedToSaveFile"), null, 'errors');
2717 }
2718 } else {
2719 setEventMessages($langs->trans("ContentCantBeEmpty"), null, 'errors');
2720 //$action='editfile';
2721 $error++;
2722 }
2723 }
2724}
2725
2726// Enable module
2727if ($action == 'set' && $user->admin /* && $user->hasRight("modulebuilder", "run") // already checked */) {
2728 $param = '';
2729 if ($module) {
2730 $param .= '&module='.urlencode($module);
2731 }
2732
2733 $param .= '&tab='.urlencode($tab);
2734 $param .= '&tabobj='.urlencode($tabobj);
2735
2736 $value = GETPOST('value', 'alpha');
2737 $resarray = activateModule($value);
2738 if (!empty($resarray['errors'])) {
2739 setEventMessages('', $resarray['errors'], 'errors');
2740 } else {
2741 //var_dump($resarray);exit;
2742 if ($resarray['nbperms'] > 0) {
2743 $tmpsql = "SELECT COUNT(rowid) as nb FROM ".MAIN_DB_PREFIX."user WHERE admin <> 1";
2744 $resqltmp = $db->query($tmpsql);
2745 if ($resqltmp) {
2746 $obj = $db->fetch_object($resqltmp);
2747 //var_dump($obj->nb);exit;
2748 if ($obj && $obj->nb > 1) {
2749 $msg = $langs->trans('ModuleEnabledAdminMustCheckRights');
2750 setEventMessages($msg, null, 'warnings');
2751 }
2752 } else {
2753 dol_print_error($db);
2754 }
2755 }
2756 }
2757 header("Location: ".$_SERVER["PHP_SELF"]."?".$param);
2758 exit;
2759}
2760
2761// Disable module
2762if ($action == 'reset' && $user->admin /* && $user->hasRight("modulebuilder", "run") // already checked */) {
2763 $param = '';
2764 if ($module) {
2765 $param .= '&module='.urlencode($module);
2766 }
2767 $param .= '&tab='.urlencode($tab);
2768 $param .= '&tabobj='.urlencode($tabobj);
2769
2770 $value = GETPOST('value', 'alpha');
2771 $result = unActivateModule(strtolower($value));
2772 if ($result) {
2773 setEventMessages($result, null, 'errors');
2774 }
2775 header("Location: ".$_SERVER["PHP_SELF"]."?".$param);
2776 exit;
2777}
2778
2779// Delete menu
2780if ($dirins && $action == 'confirm_deletemenu' && GETPOSTINT('menukey') /* && $user->hasRight("modulebuilder", "run") // already checked */) {
2781 // check if module is enabled
2782 if (isModEnabled(strtolower($module))) {
2783 $result = unActivateModule(strtolower($module));
2784 dolibarr_set_const($db, "MAIN_IHM_PARAMS_REV", getDolGlobalInt('MAIN_IHM_PARAMS_REV') + 1, 'chaine', 0, '', $conf->entity);
2785 if ($result) {
2786 setEventMessages($result, null, 'errors');
2787 }
2788 setEventMessages($langs->trans('WarningModuleNeedRefresh', $langs->transnoentities($module)), null, 'warnings');
2789 header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=menus&module='.$module);
2790 exit;
2791 }
2792 // load class and check if menu exist
2793 $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
2794 dol_include_once($pathtofile);
2795 $class = 'mod'.$module;
2796 $moduleobj = null;
2797 if (class_exists($class)) {
2798 try {
2799 $moduleobj = new $class($db);
2800 '@phan-var-force DolibarrModules $moduleobj';
2802 } catch (Exception $e) {
2803 $error++;
2804 dol_print_error($db, $e->getMessage());
2805 }
2806 }
2807 // get all objects and convert value to lower case for compare
2808 $dir = $listofmodules[strtolower($module)]['moduledescriptorrootpath'];
2809 $destdir = $dir.'/'.strtolower($module);
2810 $objects = dolGetListOfObjectClasses($destdir);
2811 $result = array_map('strtolower', $objects);
2812
2813 $menus = $moduleobj->menu;
2814 $key = GETPOSTINT('menukey');
2815 $moduledescriptorfile = $dirins.'/'.strtolower($module).'/core/modules/mod'.$module.'.class.php';
2816
2817 $checkcomment = checkExistComment($moduledescriptorfile, 0);
2818 if ($checkcomment < 0) {
2819 setEventMessages($langs->trans("WarningCommentNotFound", $langs->trans("Menus"), "mod".$module."class.php"), null, 'warnings');
2820 } else {
2821 if ($menus[$key]['fk_menu'] === 'fk_mainmenu='.strtolower($module)) {
2822 if (in_array(strtolower($menus[$key]['leftmenu']), $result)) {
2823 reWriteAllMenus($moduledescriptorfile, $menus, $menus[$key]['leftmenu'], $key, -1);
2824 } else {
2825 reWriteAllMenus($moduledescriptorfile, $menus, null, $key, 0);
2826 }
2827 } else {
2828 reWriteAllMenus($moduledescriptorfile, $menus, null, $key, 0);
2829 }
2830
2831 clearstatcache(true);
2832 if (function_exists('opcache_invalidate')) {
2833 opcache_reset(); // remove the include cache hell !
2834 }
2835
2836 setEventMessages($langs->trans('MenuDeletedSuccessfuly'), null);
2837 header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=menus&module='.$module);
2838 exit;
2839 }
2840}
2841
2842// Add menu in module without initial object
2843if ($dirins && $action == 'addmenu' && empty($cancel) /* && $user->hasRight("modulebuilder", "run") // already checked */) {
2844 // check if module is enabled
2845 if (isModEnabled(strtolower($module))) {
2846 $result = unActivateModule(strtolower($module));
2847 dolibarr_set_const($db, "MAIN_IHM_PARAMS_REV", getDolGlobalInt('MAIN_IHM_PARAMS_REV') + 1, 'chaine', 0, '', $conf->entity);
2848 if ($result) {
2849 setEventMessages($result, null, 'errors');
2850 }
2851 setEventMessages($langs->trans('WarningModuleNeedRefresh', $langs->transnoentities($module)), null, 'warnings');
2852 header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=menus&module='.$module);
2853 exit;
2854 }
2855 $error = 0;
2856
2857 // load class and check if right exist
2858 $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
2859 dol_include_once($pathtofile);
2860 $class = 'mod'.$module;
2861 $moduleobj = null;
2862 if (class_exists($class)) {
2863 try {
2864 $moduleobj = new $class($db);
2865 '@phan-var-force DolibarrModules $moduleobj';
2867 } catch (Exception $e) {
2868 $error++;
2869 dol_print_error($db, $e->getMessage());
2870 }
2871 }
2872 // get all menus
2873 $menus = $moduleobj->menu;
2874
2875 //verify fields required
2876 if (!GETPOST('type', 'alpha')) {
2877 $error++;
2878 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Type")), null, 'errors');
2879 }
2880 if (!GETPOST('titre', 'alpha')) {
2881 $error++;
2882 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Title")), null, 'errors');
2883 }
2884 if (!GETPOST('user', 'alpha')) {
2885 $error++;
2886 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("DetailUser")), null, 'errors');
2887 }
2888 if (!GETPOST('url', 'alpha')) {
2889 $error++;
2890 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Url")), null, 'errors');
2891 }
2892 if (!empty(GETPOST('target'))) {
2893 $targets = array('_blank','_self','_parent','_top','');
2894 if (!in_array(GETPOST('target'), $targets)) {
2895 $error++;
2896 setEventMessages($langs->trans("ErrorFieldValue", $langs->transnoentities("target")), null, 'errors');
2897 }
2898 }
2899
2900
2901 // check if title or url already exist in menus
2902
2903 foreach ($menus as $menu) {
2904 if (!empty(GETPOST('url')) && GETPOST('url') == $menu['url']) {
2905 $error++;
2906 setEventMessages($langs->trans("ErrorFieldExist", $langs->transnoentities("url")), null, 'errors');
2907 break;
2908 }
2909 if (strtolower(GETPOST('titre')) == strtolower($menu['titre'])) {
2910 $error++;
2911 setEventMessages($langs->trans("ErrorFieldExist", $langs->transnoentities("titre")), null, 'errors');
2912 break;
2913 }
2914 }
2915
2916 if (GETPOST('type', 'alpha') == 'left' && !empty(GETPOST('lefmenu', 'alpha'))) {
2917 if (!str_contains(GETPOST('leftmenu'), strtolower($module))) {
2918 $error++;
2919 setEventMessages($langs->trans("WarningFieldsMustContains", $langs->transnoentities("LeftmenuId")), null, 'errors');
2920 }
2921 }
2922 $dirins = $listofmodules[strtolower($module)]['moduledescriptorrootpath'];
2923 $destdir = $dirins.'/'.strtolower($module);
2924 $objects = dolGetListOfObjectClasses($destdir);
2925
2926 if (GETPOST('type', 'alpha') == 'left') {
2927 if (empty(GETPOST('leftmenu')) && count($objects) > 0) {
2928 $error++;
2929 setEventMessages($langs->trans("ErrorCoherenceMenu", $langs->transnoentities("LeftmenuId"), $langs->transnoentities("type")), null, 'errors');
2930 }
2931 }
2932 if (GETPOST('type', 'alpha') == 'top') {
2933 $error++;
2934 setEventMessages($langs->trans("ErrorTypeMenu", $langs->transnoentities("type")), null, 'errors');
2935 }
2936
2937 $moduledescriptorfile = $dirins.'/'.strtolower($module).'/core/modules/mod'.$module.'.class.php';
2938 if (!$error) {
2939 //stock forms in array
2940 $menuToAdd = array(
2941 'fk_menu' => GETPOST('fk_menu', 'alpha'),
2942 'type' => GETPOST('type', 'alpha'),
2943 'titre' => ucfirst(GETPOST('titre', 'alpha')),
2944 'prefix' => '',
2945 'mainmenu' => GETPOST('mainmenu', 'alpha'),
2946 'leftmenu' => GETPOST('leftmenu', 'alpha'),
2947 'url' => GETPOST('url', 'alpha'),
2948 'langs' => strtolower($module)."@".strtolower($module),
2949 'position' => '',
2950 'enabled' => GETPOST('enabled', 'alpha'),
2951 'perms' => '$user->hasRight("'.strtolower($module).'", "'.GETPOST('objects', 'alpha').'", "'.GETPOST('perms', 'alpha').'")',
2952 'target' => GETPOST('target', 'alpha'),
2953 'user' => GETPOSTINT('user'),
2954 );
2955
2956 if (GETPOST('type') == 'left') {
2957 unset($menuToAdd['prefix']);
2958 if (empty(GETPOST('fk_menu'))) {
2959 $menuToAdd['fk_menu'] = 'fk_mainmenu='.GETPOST('mainmenu', 'alpha');
2960 } else {
2961 $menuToAdd['fk_menu'] = 'fk_mainmenu='.GETPOST('mainmenu', 'alpha').',fk_leftmenu='.GETPOST('fk_menu');
2962 }
2963 }
2964 if (GETPOST('enabled') == '1') {
2965 $menuToAdd['enabled'] = 'isModEnabled("'.strtolower($module).'")';
2966 } else {
2967 $menuToAdd['enabled'] = "0";
2968 }
2969 if (empty(GETPOST('objects'))) {
2970 $menuToAdd['perms'] = '1';
2971 }
2972
2973 $checkcomment = checkExistComment($moduledescriptorfile, 0);
2974 if ($checkcomment < 0) {
2975 setEventMessages($langs->trans("WarningCommentNotFound", $langs->trans("Menus"), "mod".$module."class.php"), null, 'warnings');
2976 } else {
2977 // Write all menus
2978 $result = reWriteAllMenus($moduledescriptorfile, $menus, $menuToAdd, null, 1);
2979
2980 clearstatcache(true);
2981 if (function_exists('opcache_invalidate')) {
2982 opcache_reset();
2983 }
2984 /*if ($result < 0) {
2985 setEventMessages($langs->trans('ErrorMenuExistValue'), null, 'errors');
2986 header("Location: ".$_SERVER["PHP_SELF"].'?action=editmenu&token='.newToken().'&menukey='.urlencode($key+1).'&tab='.urlencode($tab).'&module='.urlencode($module).'&tabobj='.($key+1));
2987 exit;
2988 }*/
2989
2990 header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=menus&module='.$module);
2991 setEventMessages($langs->trans('MenuAddedSuccesfuly'), null);
2992 exit;
2993 }
2994 }
2995}
2996
2997// Modify a menu entry
2998if ($dirins && $action == "update_menu" && GETPOSTINT('menukey') && GETPOST('tabobj') /* && $user->hasRight("modulebuilder", "run") // already checked */) {
2999 $objectname = GETPOST('tabobj');
3000 $dirins = $listofmodules[strtolower($module)]['moduledescriptorrootpath'];
3001 $destdir = $dirins.'/'.strtolower($module);
3002 $objects = dolGetListOfObjectClasses($destdir);
3003
3004 if (empty($cancel)) {
3005 if (isModEnabled(strtolower($module))) {
3006 $result = unActivateModule(strtolower($module));
3007 dolibarr_set_const($db, "MAIN_IHM_PARAMS_REV", getDolGlobalInt('MAIN_IHM_PARAMS_REV') + 1, 'chaine', 0, '', $conf->entity);
3008 if ($result) {
3009 setEventMessages($result, null, 'errors');
3010 }
3011 setEventMessages($langs->trans('WarningModuleNeedRefresh', $langs->transnoentities($module)), null, 'warnings');
3012 header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=menus&module='.$module);
3013 exit;
3014 }
3015 $error = 0;
3016 // for loading class and the menu wants to modify
3017 $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
3018 dol_include_once($pathtofile);
3019 $class = 'mod'.$module;
3020 $moduleobj = null;
3021 if (class_exists($class)) {
3022 try {
3023 $moduleobj = new $class($db);
3024 '@phan-var-force DolibarrModules $moduleobj';
3026 } catch (Exception $e) {
3027 $error++;
3028 dol_print_error($db, $e->getMessage());
3029 }
3030 }
3031 $menus = $moduleobj->menu;
3032 $key = GETPOSTINT('menukey') - 1;
3033
3034 $moduledescriptorfile = $dirins.'/'.strtolower($module).'/core/modules/mod'.$module.'.class.php';
3035 //stock forms in array
3036 $menuModify = array(
3037 'fk_menu' => GETPOST('fk_menu', 'alpha'),
3038 'type' => GETPOST('type', 'alpha'),
3039 'titre' => ucfirst(GETPOST('titre', 'alpha')),
3040 'prefix' => '',
3041 'mainmenu' => GETPOST('mainmenu', 'alpha'),
3042 'leftmenu' => $menus[$key]['leftmenu'],
3043 'url' => GETPOST('url', 'alpha'),
3044 'langs' => strtolower($module)."@".strtolower($module),
3045 'position' => '',
3046 'enabled' => GETPOST('enabled', 'alpha'),
3047 'perms' => GETPOST('perms', 'alpha'),
3048 'target' => GETPOST('target', 'alpha'),
3049 'user' => GETPOSTINT('user'),
3050 );
3051 if (!empty(GETPOST('fk_menu')) && GETPOST('fk_menu') != $menus[$key]['fk_menu']) {
3052 $menuModify['fk_menu'] = 'fk_mainmenu='.GETPOST('mainmenu').',fk_leftmenu='.GETPOST('fk_menu');
3053 } elseif (GETPOST('fk_menu') == $menus[$key]['fk_menu']) {
3054 $menuModify['fk_menu'] = $menus[$key]['fk_menu'];
3055 } else {
3056 $menuModify['fk_menu'] = 'fk_mainmenu='.GETPOST('mainmenu');
3057 }
3058 if ($menuModify['enabled'] === '') {
3059 $menuModify['enabled'] = '1';
3060 }
3061 if ($menuModify['perms'] === '') {
3062 $menuModify['perms'] = '1';
3063 }
3064
3065 if (GETPOST('type', 'alpha') == 'top') {
3066 $error++;
3067 setEventMessages($langs->trans("ErrorTypeMenu", $langs->transnoentities("type")), null, 'errors');
3068 }
3069
3070 if (!$error) {
3071 //update menu
3072 $checkComment = checkExistComment($moduledescriptorfile, 0);
3073
3074 if ($checkComment < 0) {
3075 setEventMessages($langs->trans("WarningCommentNotFound", $langs->trans("Menus"), "mod".$module."class.php"), null, 'warnings');
3076 } else {
3077 // Write all menus
3078 $result = reWriteAllMenus($moduledescriptorfile, $menus, $menuModify, $key, 2);
3079
3080 clearstatcache(true);
3081 if (function_exists('opcache_invalidate')) {
3082 opcache_reset();
3083 }
3084
3085 if ($result < 0) {
3086 setEventMessages($langs->trans('ErrorMenuExistValue'), null, 'errors');
3087 //var_dump($_SESSION);exit;
3088 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));
3089 exit;
3090 }
3091
3092 setEventMessages($langs->trans('MenuUpdatedSuccessfuly'), null);
3093 header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=menus&module='.$module);
3094 exit;
3095 }
3096 }
3097 } else {
3098 $_POST['type'] = ''; // TODO Use a var here and later
3099 $_POST['titre'] = '';
3100 $_POST['fk_menu'] = '';
3101 $_POST['leftmenu'] = '';
3102 $_POST['url'] = '';
3103 }
3104}
3105
3106// update properties description of module
3107if ($dirins && $action == "update_props_module" && !empty(GETPOST('keydescription', 'alpha')) && empty($cancel) /* && $user->hasRight("modulebuilder", "run") // already checked */) {
3108 if (isModEnabled(strtolower($module))) {
3109 $result = unActivateModule(strtolower($module));
3110 dolibarr_set_const($db, "MAIN_IHM_PARAMS_REV", getDolGlobalInt('MAIN_IHM_PARAMS_REV') + 1, 'chaine', 0, '', $conf->entity);
3111 if ($result) {
3112 setEventMessages($result, null, 'errors');
3113 }
3114 setEventMessages($langs->trans('WarningModuleNeedRefresh', $langs->transnoentities($module)), null, 'warnings');
3115 header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=menus&module='.$module);
3116 exit;
3117 }
3118 $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
3119 $moduledescriptorfile = $dirins.'/'.strtolower($module).'/core/modules/mod'.$module.'.class.php';
3120 $modulelogfile = $dirins.'/'.strtolower($module).'/ChangeLog.md';
3121
3122 dol_include_once($pathtofile);
3123
3124 $class = 'mod'.$module;
3125 $moduleobj = null;
3126 if (class_exists($class)) {
3127 try {
3128 $moduleobj = new $class($db);
3129 '@phan-var-force DolibarrModules $moduleobj';
3131 } catch (Exception $e) {
3132 $error++;
3133 dol_print_error($db, $e->getMessage());
3134 }
3135 }
3136
3137 $keydescription = GETPOST('keydescription', 'alpha');
3138 switch ($keydescription) {
3139 case 'desc':
3140 $propertyToUpdate = 'description';
3141 break;
3142 case 'version':
3143 case 'family':
3144 case 'picto':
3145 case 'editor_name':
3146 case 'editor_url':
3147 $propertyToUpdate = $keydescription;
3148 break;
3149 default:
3150 $error = GETPOST('keydescription');
3151 break;
3152 }
3153
3154 if (isset($propertyToUpdate) && !empty(GETPOST('propsmodule'))) {
3155 $newValue = GETPOST('propsmodule');
3156 $patternToFindLine = '^\s*\$this->'.$propertyToUpdate.'\s*='; // Must be a regex string
3157 $newLine = "\t\t\$this->$propertyToUpdate = '$newValue';\n"; // Must a real string
3158
3159 $fileLines = file($moduledescriptorfile); // Get each line of file into an array
3160 $error = 0;
3161 $changedone = 0;
3162 foreach ($fileLines as &$line) {
3163 if (preg_match('/'.$patternToFindLine.'/', $line)) {
3164 $result = dolReplaceInFile($moduledescriptorfile, array($line => $newLine));
3165 if ($result > 0) {
3166 $changedone++;
3167 } elseif ($result <= -1) {
3168 $langs->load("errors");
3169 setEventMessages($langs->trans('ErrorFailToEditFile', $moduledescriptorfile), null, 'warnings');
3170 break;
3171 }
3172 break;
3173 }
3174 }
3175
3176 // To complete also the ChangeLogif we update the version
3177 if ($changedone && $propertyToUpdate === 'version') {
3178 dolReplaceInFile($modulelogfile, array("## ".$moduleobj->$propertyToUpdate => $newValue));
3179 }
3180
3181 clearstatcache(true);
3182 if (function_exists('opcache_invalidate')) {
3183 opcache_reset();
3184 }
3185 if ($changedone) {
3186 setEventMessages($langs->trans('PropertyModuleUpdated', $propertyToUpdate), null);
3187 } else {
3188 setEventMessages($langs->trans('NothingProcessed'), null, 'warnings');
3189 }
3190
3191 header("Location: ".DOL_URL_ROOT.'/modulebuilder/index.php?tab=description&module='.$module);
3192 exit;
3193 }
3194}
3195
3196
3197/*
3198 * View
3199 */
3200
3201$form = new Form($db);
3202$formadmin = new FormAdmin($db);
3203
3204// Set dir where external modules are installed
3205if (!dol_is_dir($dirins)) {
3206 dol_mkdir($dirins);
3207}
3208$dirins_ok = (dol_is_dir($dirins));
3209
3210$help_url = '';
3211$morejs = array(
3212 '/includes/ace/src/ace.js',
3213 '/includes/ace/src/ext-statusbar.js',
3214 '/includes/ace/src/ext-language_tools.js',
3215 //'/includes/ace/src/ext-chromevox.js'
3216);
3217$morecss = array();
3218
3219llxHeader('', $langs->trans("ModuleBuilder"), $help_url, '', 0, 0, $morejs, $morecss, '', 'classforhorizontalscrolloftabs');
3220
3221
3222$text = $langs->trans("ModuleBuilder");
3223
3224$morehtmlright = '<a href="'.DOL_URL_ROOT.'/admin/tools/ui/index.php" target="_blank" rel="noopener">'.img_picto('', 'book', 'class="pictofixedwidth"').$langs->trans("UxComponentsDoc").'</a>';
3225
3226print load_fiche_titre($text, $morehtmlright, 'title_setup');
3227
3228print '<span class="opacitymedium hideonsmartphone">'.$langs->trans("ModuleBuilderDesc", 'https://wiki.dolibarr.org/index.php/Module_development').'</span>';
3229print '<br class="hideonsmartphone">';
3230
3231//print $textforlistofdirs;
3232//print '<br>';
3233
3234
3235
3236$message = '';
3237if (!$dirins) {
3238 $message = info_admin($langs->trans("ConfFileMustContainCustom", DOL_DOCUMENT_ROOT.'/custom', DOL_DOCUMENT_ROOT));
3239 $allowfromweb = -1;
3240} else {
3241 if ($dirins_ok) {
3242 if (!is_writable(dol_osencode($dirins))) {
3243 $langs->load("errors");
3244 $message = info_admin($langs->trans("ErrorFailedToWriteInDir", $dirins));
3245 $allowfromweb = 0;
3246 }
3247 } else {
3248 $message = info_admin($langs->trans("NotExistsDirect", $dirins).$langs->trans("InfDirAlt").$langs->trans("InfDirExample"));
3249 $allowfromweb = 0;
3250 }
3251}
3252if ($message) {
3253 print $message;
3254}
3255
3256//print $langs->trans("ModuleBuilderDesc3", count($listofmodules), $FILEFLAG).'<br>';
3257$infomodulesfound = '<div style="padding: 12px 9px 12px">'.$form->textwithpicto('', $langs->trans("ModuleBuilderDesc3", count($listofmodules)).'<br><br>'.$langs->trans("ModuleBuilderDesc4", $FILEFLAG).'<br>'.$textforlistofdirs).'</div>';
3258
3259
3260
3261$dolibarrdataroot = preg_replace('/([\\/]+)$/i', '', DOL_DATA_ROOT);
3262$allowonlineinstall = true;
3263if (dol_is_file($dolibarrdataroot.'/installmodules.lock')) {
3264 $allowonlineinstall = false;
3265}
3266if (empty($allowonlineinstall)) {
3267 if (getDolGlobalString('MAIN_MESSAGE_INSTALL_MODULES_DISABLED_CONTACT_US')) {
3268 // Show clean message
3269 $message = info_admin($langs->trans('InstallModuleFromWebHasBeenDisabledContactUs'));
3270 } else {
3271 // Show technical message
3272 $message = info_admin($langs->trans("InstallModuleFromWebHasBeenDisabledByFile", $dolibarrdataroot.'/installmodules.lock'), 0, 0, '1', 'warning');
3273 }
3274
3275 print $message;
3276
3277 llxFooter();
3278 exit(0);
3279}
3280
3281
3282// Load module descriptor
3283$error = 0;
3285
3286
3287if (!empty($module) && $module != 'initmodule' && $module != 'deletemodule') {
3288 $modulelowercase = strtolower($module);
3289 $loadclasserrormessage = '';
3290
3291 // Load module
3292 try {
3293 $fullpathdirtodescriptor = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
3294
3295 //throw(new Exception());
3296 dol_include_once($fullpathdirtodescriptor);
3297
3298 $class = 'mod'.$module;
3299 } catch (Throwable $e) { // This is called in PHP 7 only (includes Error and Exception)
3300 $loadclasserrormessage = $e->getMessage()."<br>\n";
3301 $loadclasserrormessage .= 'File: '.$e->getFile()."<br>\n";
3302 $loadclasserrormessage .= 'Line: '.$e->getLine()."<br>\n";
3303 }
3304
3305 $moduleobj = null;
3306 if (class_exists($class)) {
3307 try {
3308 $moduleobj = new $class($db);
3309 '@phan-var-force DolibarrModules $moduleobj';
3311 } catch (Exception $e) {
3312 $error++;
3313 print $e->getMessage();
3314 }
3315 } else {
3316 if (empty($forceddirread)) {
3317 $error++;
3318 }
3319 $langs->load("errors");
3320 print '<!-- ErrorFailedToLoadModuleDescriptorForXXX -->';
3321 print img_warning('').' '.$langs->trans("ErrorFailedToLoadModuleDescriptorForXXX", $module).'<br>';
3322 print $loadclasserrormessage;
3323 }
3324}
3325
3326print '<br>';
3327
3328
3329// Tabs for all modules
3330$head = array();
3331$h = 0;
3332
3333$head[$h][0] = $_SERVER["PHP_SELF"].'?module=initmodule';
3334$head[$h][1] = '<span class="valignmiddle text-plus-circle">'.$langs->trans("NewModule").'</span><span class="fa fa-plus-circle valignmiddle paddingleft"></span>';
3335$head[$h][2] = 'initmodule';
3336$h++;
3337
3338$linktoenabledisable = '';
3339
3340if (/* is_array($listofmodules) && */ count($listofmodules) > 0) {
3341 // Define $linktoenabledisable
3342 $modulelowercase = strtolower($module);
3343
3344 $param = '';
3345 if ($module) {
3346 $param .= '&module='.urlencode($module);
3347 }
3348
3349 $param .= '&tab='.urlencode($tab);
3350 $param .= '&tabobj='.urlencode($tabobj);
3351
3352 $urltomodulesetup = '<a href="'.DOL_URL_ROOT.'/admin/modules.php?search_keyword='.urlencode($module).'">'.$langs->trans('Home').'-'.$langs->trans("Setup").'-'.$langs->trans("Modules").'</a>';
3353
3354 // Define $linktoenabledisable to show after module title
3355 if (isModEnabled($modulelowercase)) { // If module is already activated
3356 $linktoenabledisable .= '<a class="reposition asetresetmodule valignmiddle" href="'.$_SERVER["PHP_SELF"].'?id='.$moduleobj->numero.'&action=reset&token='.newToken().'&value=mod'.$module.$param.'">';
3357 $linktoenabledisable .= img_picto($langs->trans("Activated"), 'switch_on', '', 0, 0, 0, '', '', 1);
3358 $linktoenabledisable .= '</a>';
3359
3360 $linktoenabledisable .= $form->textwithpicto('', $langs->trans("Warning").' : '.$langs->trans("ModuleIsLive"), -1, 'warning');
3361
3362 $objMod = $moduleobj;
3363 $backtourlparam = '';
3364 $backtourlparam .= ($backtourlparam ? '&' : '?').'module='.$module; // No urlencode here, done later
3365 $backtourlparam .= ($backtourlparam ? '&' : '?').'tab='.$tab; // No urlencode here, done later
3366 $backtourl = $_SERVER["PHP_SELF"].$backtourlparam;
3367
3368 $regs = array();
3369 if (is_array($objMod->config_page_url)) {
3370 $i = 0;
3371 foreach ($objMod->config_page_url as $page) {
3372 $urlpage = $page;
3373 if ($i++) {
3374 $linktoenabledisable .= ' <a href="'.$urlpage.'" title="'.$langs->trans($page).'">'.img_picto(ucfirst($page), "setup").'</a>';
3375 // print '<a href="'.$page.'">'.ucfirst($page).'</a>&nbsp;';
3376 } else {
3377 if (preg_match('/^([^@]+)@([^@]+)$/i', $urlpage, $regs)) {
3378 $urltouse = dol_buildpath('/'.$regs[2].'/admin/'.$regs[1], 1);
3379 $linktoenabledisable .= ' <a 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"').'</a>';
3380 } else {
3381 // Case standard admin page (not a page provided by the
3382 // module but a page provided by dolibarr)
3383 $urltouse = DOL_URL_ROOT.'/admin/'.$urlpage;
3384 $linktoenabledisable .= ' <a 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"').'</a>';
3385 }
3386 }
3387 }
3388 } elseif (preg_match('/^([^@]+)@([^@]+)$/i', $objMod->config_page_url, $regs)) {
3389 $linktoenabledisable .= ' &nbsp; <a 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"').'</a>';
3390 }
3391 } else {
3392 if (is_object($moduleobj)) {
3393 $linktoenabledisable .= '<a class="reposition asetresetmodule valignmiddle" href="'.$_SERVER["PHP_SELF"].'?id='.$moduleobj->numero.'&action=set&token='.newToken().'&value=mod'.$module.$param.'">';
3394 $linktoenabledisable .= img_picto($langs->trans("ModuleIsNotActive", $urltomodulesetup), 'switch_off', 'style="padding-right: 8px"', 0, 0, 0, '', 'classfortooltip', 1);
3395 $linktoenabledisable .= "</a>\n";
3396 }
3397 }
3398
3399 // Loop to show tab of each module
3400 foreach ($listofmodules as $tmpmodule => $tmpmodulearray) {
3401 $head[$h][0] = $_SERVER["PHP_SELF"].'?module='.$tmpmodulearray['modulenamewithcase'].($forceddirread ? '@'.$dirread : '');
3402 $head[$h][1] = $tmpmodulearray['modulenamewithcase'];
3403 $head[$h][2] = $tmpmodulearray['modulenamewithcase'];
3404
3405 if ($tmpmodulearray['modulenamewithcase'] == $module) {
3406 $head[$h][4] = '<span class="inline-block">'.$linktoenabledisable.'</span>';
3407 }
3408
3409 $h++;
3410 }
3411}
3412
3413$head[$h][0] = $_SERVER["PHP_SELF"].'?module=deletemodule';
3414$head[$h][1] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("DangerZone");
3415$head[$h][2] = 'deletemodule';
3416$h++;
3417
3418
3419print dol_get_fiche_head($head, $module, '', -1, '', 0, $infomodulesfound, '', 8); // Modules
3420
3421if ($module == 'initmodule') {
3422 // New module
3423 print '<!-- section init module -->'."\n";
3424 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
3425 print '<input type="hidden" name="token" value="'.newToken().'">';
3426 print '<input type="hidden" name="action" value="initmodule">';
3427 print '<input type="hidden" name="module" value="initmodule">';
3428
3429 //print '<span class="opacitymedium">'.$langs->trans("ModuleBuilderDesc2", 'conf/conf.php', $newdircustom).'</span><br>';
3430 print '<br>';
3431
3432 print '<div class="tagtable table-border">';
3433
3434 print '<div class="tagtr"><div class="tagtd paddingright">';
3435 print '<span class="opacitymedium">'.$langs->trans("IdModule").'</span>';
3436 print '</div><div class="tagtd">';
3437 print '<input type="number" min="100000" name="idmodule" class="width100" value="500000">';
3438 print '<span class="opacitymedium small">';
3439 print ' &nbsp; &nbsp; ';
3440 print dolButtonToOpenUrlInDialogPopup('popup_modules_id', $langs->transnoentitiesnoconv("SeeIDsInUse"), $langs->transnoentitiesnoconv("SeeIDsInUse"), '/admin/system/modules.php?mainmenu=home&leftmenu=admintools_info&hidetitle=1', '', '');
3441 print ' - ';
3442 print '<a href="https://wiki.dolibarr.org/index.php/List_of_modules_id" target="_blank" rel="noopener noreferrer external">'.$langs->trans("SeeReservedIDsRangeHere").'</a>';
3443 print '</span>';
3444 print '</div></div>';
3445
3446 print '<div class="tagtr"><div class="tagtd paddingright">';
3447 print '<span class="opacitymedium fieldrequired">'.$langs->trans("ModuleName").'</span>';
3448 print '</div><div class="tagtd">';
3449 print '<input type="text" name="modulename" value="'.dol_escape_htmltag($modulename).'" autofocus>';
3450 print ' '.$form->textwithpicto('', $langs->trans("EnterNameOfModuleDesc"));
3451 print '</div></div>';
3452
3453 print '<div class="tagtr"><div class="tagtd paddingright">';
3454 print '<span class="opacitymedium">'.$langs->trans("Description").'</span>';
3455 print '</div><div class="tagtd">';
3456 print '<input type="text" name="description" value="" class="minwidth500"><br>';
3457 print '</div></div>';
3458
3459 print '<div class="tagtr"><div class="tagtd paddingright">';
3460 print '<span class="opacitymedium">'.$langs->trans("Version").'</span>';
3461 print '</div><div class="tagtd">';
3462 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")).'">';
3463 print '</div></div>';
3464
3465 print '<div class="tagtr"><div class="tagtd paddingright">';
3466 print '<span class="opacitymedium">'.$langs->trans("Family").'</span>';
3467 print '</div><div class="tagtd">';
3468 print '<select name="family" id="family" class="minwidth400">';
3469 $arrayoffamilies = array(
3470 'hr' => "ModuleFamilyHr",
3471 'crm' => "ModuleFamilyCrm",
3472 'srm' => "ModuleFamilySrm",
3473 'financial' => 'ModuleFamilyFinancial',
3474 'products' => 'ModuleFamilyProducts',
3475 'projects' => 'ModuleFamilyProjects',
3476 'ecm' => 'ModuleFamilyECM',
3477 'technic' => 'ModuleFamilyTechnic',
3478 'portal' => 'ModuleFamilyPortal',
3479 'interface' => 'ModuleFamilyInterface',
3480 'base' => 'ModuleFamilyBase',
3481 'other' => 'ModuleFamilyOther'
3482 );
3483 foreach ($arrayoffamilies as $key => $value) {
3484 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>';
3485 }
3486 print '</select>';
3487 print ajax_combobox("family");
3488 print '</div></div>';
3489
3490 print '<div class="tagtr"><div class="tagtd paddingright">';
3491 print '<span class="opacitymedium">'.$langs->trans("Picto").'</span>';
3492 print '</div><div class="tagtd">';
3493 print '<input type="text" name="idpicto" value="'.(GETPOSTISSET('idpicto') ? GETPOST('idpicto') : getDolGlobalString('MODULEBUILDER_DEFAULTPICTO', 'fa-file')).'" placeholder="'.dol_escape_htmltag($langs->trans("Picto")).'">';
3494 print $form->textwithpicto('', $langs->trans("Example").': fa-file, fa-globe, ... any font awesome code.<br>Advanced syntax is fa-fakey[_faprefix[_facolor[_fasize]]]');
3495
3496 print ' &nbsp; &nbsp; ';
3497
3498 print '<span class="opacitymedium small">';
3499 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', '', '');
3500 print '</span>';
3501
3502 print '</div></div>';
3503
3504 print '<div class="tagtr"><div class="tagtd paddingright">';
3505 print '<span class="opacitymedium">'.$langs->trans("EditorName").'</span>';
3506 print '</div><div class="tagtd">';
3507 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")).'"><br>';
3508 print '</div></div>';
3509
3510 print '<div class="tagtr"><div class="tagtd paddingright">';
3511 print '<span class="opacitymedium">'.$langs->trans("EditorUrl").'</span>';
3512 print '</div><div class="tagtd">';
3513 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")).'"><br>';
3514 print '</div></div>';
3515
3516 print '</div>'; // End div tagtable
3517
3518 print '<br><center>';
3519 print '<input type="submit" class="button" name="create" value="'.dol_escape_htmltag($langs->trans("Create")).'"'.($dirins ? '' : ' disabled="disabled"').'>';
3520 print '</center>';
3521 print '</form>';
3522} elseif ($module == 'deletemodule') {
3523 print '<!-- Form to init a module -->'."\n";
3524 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST" name="delete">';
3525 print '<input type="hidden" name="token" value="'.newToken().'">';
3526 print '<input type="hidden" name="action" value="confirm_deletemodule">';
3527 print '<input type="hidden" name="module" value="deletemodule">';
3528
3529 print $langs->trans("EnterNameOfModuleToDeleteDesc").'<br><br>';
3530
3531 print '<input type="text" name="module" placeholder="'.dol_escape_htmltag($langs->trans("ModuleKey")).'" value="" autofocus>';
3532 print '<input type="submit" class="button smallpaddingimp" value="'.$langs->trans("Delete").'"'.($dirins ? '' : ' disabled="disabled"').'>';
3533 print '</form>';
3534} elseif (!empty($module) && $modulelowercase !== null) {
3535 // Tabs for module
3536 if (!$error) {
3537 $dirread = $listofmodules[strtolower($module)]['moduledescriptorrootpath'];
3538 $destdir = $dirread.'/'.strtolower($module);
3539 $objects = dolGetListOfObjectClasses($destdir);
3540 $diroflang = dol_buildpath($modulelowercase, 0)."/langs";
3541 $countLangs = countItemsInDirectory($diroflang, 2);
3542 $countDictionaries = (!empty($moduleobj->dictionaries) ? count($moduleobj->dictionaries['tabname']) : 0);
3543 $countRights = count($moduleobj->rights);
3544 $countMenus = count($moduleobj->menu);
3545 $countTriggers = countItemsInDirectory(dol_buildpath($modulelowercase, 0)."/core/triggers");
3546 $countWidgets = countItemsInDirectory(dol_buildpath($modulelowercase, 0)."/core/boxes");
3547 $countEmailingSelectors = countItemsInDirectory(dol_buildpath($modulelowercase, 0)."/core/modules/mailings");
3548 $countCss = countItemsInDirectory(dol_buildpath($modulelowercase, 0)."/css");
3549 $countJs = countItemsInDirectory(dol_buildpath($modulelowercase, 0)."/js");
3550 $countCLI = countItemsInDirectory(dol_buildpath($modulelowercase, 0)."/scripts");
3551 $hasDoc = countItemsInDirectory(dol_buildpath($modulelowercase, 0)."/doc");
3552 //var_dump($moduleobj->dictionaries);exit;
3553 $head2 = array();
3554 $h = 0;
3555
3556 $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=description&module='.$module.($forceddirread ? '@'.$dirread : '');
3557 $head2[$h][1] = $langs->trans("Description");
3558 $head2[$h][2] = 'description';
3559 $h++;
3560
3561 $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=objects&module='.$module.($forceddirread ? '@'.$dirread : '');
3562 $head2[$h][1] = ((!is_array($objects) || count($objects) <= 0) ? $langs->trans("Objects") : $langs->trans("Objects").'<span class="marginleftonlyshort badge">'.count($objects)."</span>");
3563 $head2[$h][2] = 'objects';
3564 $h++;
3565
3566 $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=languages&module='.$module.($forceddirread ? '@'.$dirread : '');
3567 $head2[$h][1] = ($countLangs <= 0 ? $langs->trans("Languages") : $langs->trans("Languages").'<span class="marginleftonlyshort badge">'.$countLangs."</span>");
3568 $head2[$h][2] = 'languages';
3569 $h++;
3570
3571 $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=permissions&module='.$module.($forceddirread ? '@'.$dirread : '');
3572 $head2[$h][1] = ($countRights <= 0 ? $langs->trans("Permissions") : $langs->trans("Permissions").'<span class="marginleftonlyshort badge">'.$countRights."</span>");
3573 $head2[$h][2] = 'permissions';
3574 $h++;
3575
3576 $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=dictionaries&module='.$module.($forceddirread ? '@'.$dirread : '');
3577 $head2[$h][1] = ($countDictionaries == 0 ? $langs->trans("Dictionaries") : $langs->trans('Dictionaries').'<span class="marginleftonlyshort badge">'.$countDictionaries."</span>");
3578 $head2[$h][2] = 'dictionaries';
3579 $h++;
3580
3581 $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=tabs&module='.$module.($forceddirread ? '@'.$dirread : '');
3582 $head2[$h][1] = $langs->trans("Tabs");
3583 $head2[$h][2] = 'tabs';
3584 $h++;
3585
3586 $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=menus&module='.$module.($forceddirread ? '@'.$dirread : '');
3587 $head2[$h][1] = ($countMenus <= 0 ? $langs->trans("Menus") : $langs->trans("Menus").'<span class="marginleftonlyshort badge">'.$countMenus."</span>");
3588 $head2[$h][2] = 'menus';
3589 $h++;
3590
3591 $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=hooks&module='.$module.($forceddirread ? '@'.$dirread : '');
3592 $head2[$h][1] = $langs->trans("Hooks");
3593 $head2[$h][2] = 'hooks';
3594 $h++;
3595
3596 $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=triggers&module='.$module.($forceddirread ? '@'.$dirread : '');
3597 $head2[$h][1] = ($countTriggers <= 0 ? $langs->trans("Triggers") : $langs->trans("Triggers").'<span class="marginleftonlyshort badge">'.$countTriggers."</span>");
3598 $head2[$h][2] = 'triggers';
3599 $h++;
3600
3601 $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=widgets&module='.$module.($forceddirread ? '@'.$dirread : '');
3602 $head2[$h][1] = ($countWidgets <= 0 ? $langs->trans("Widgets") : $langs->trans("Widgets").'<span class="marginleftonlyshort badge">'.$countWidgets."</span>");
3603 $head2[$h][2] = 'widgets';
3604 $h++;
3605
3606 $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=emailings&module='.$module.($forceddirread ? '@'.$dirread : '');
3607 $head2[$h][1] = ($countEmailingSelectors <= 0 ? $langs->trans("EmailingSelectors") : $langs->trans("EmailingSelectors").'<span class="marginleftonlyshort badge">'.$countEmailingSelectors."</span>");
3608 $head2[$h][2] = 'emailings';
3609 $h++;
3610
3611 $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=exportimport&module='.$module.($forceddirread ? '@'.$dirread : '');
3612 $head2[$h][1] = $langs->trans("Export").'-'.$langs->trans("Import");
3613 $head2[$h][2] = 'exportimport';
3614 $h++;
3615
3616 $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=css&module='.$module.($forceddirread ? '@'.$dirread : '');
3617 $head2[$h][1] = ($countCss <= 0 ? $langs->trans("CSS") : $langs->trans("CSS")." (".$countCss.")");
3618 $head2[$h][2] = 'css';
3619 $h++;
3620
3621 $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=js&module='.$module.($forceddirread ? '@'.$dirread : '');
3622 $head2[$h][1] = ($countJs <= 0 ? $langs->trans("JS") : $langs->trans("JS").'<span class="marginleftonlyshort badge">'.$countJs."</span>");
3623 $head2[$h][2] = 'js';
3624 $h++;
3625
3626 $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=cli&module='.$module.($forceddirread ? '@'.$dirread : '');
3627 $head2[$h][1] = ($countCLI <= 0 ? $langs->trans("CLI") : $langs->trans("CLI").'<span class="marginleftonlyshort badge">'.$countCLI."</span>");
3628 $head2[$h][2] = 'cli';
3629 $h++;
3630
3631 $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=cron&module='.$module.($forceddirread ? '@'.$dirread : '');
3632 $head2[$h][1] = $langs->trans("CronList");
3633 $head2[$h][2] = 'cron';
3634 $h++;
3635
3636 $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=specifications&module='.$module.($forceddirread ? '@'.$dirread : '');
3637 $head2[$h][1] = ($hasDoc <= 0 ? $langs->trans("Documentation") : $langs->trans("Documentation").'<span class="marginleftonlyshort badge">'.$hasDoc."</span>");
3638 $head2[$h][2] = 'specifications';
3639 $h++;
3640
3641 $head2[$h][0] = $_SERVER["PHP_SELF"].'?tab=buildpackage&module='.$module.($forceddirread ? '@'.$dirread : '');
3642 $head2[$h][1] = $langs->trans("BuildPackage");
3643 $head2[$h][2] = 'buildpackage';
3644 $h++;
3645
3646 $MAXTABFOROBJECT = 12;
3647
3648 print '<!-- Section for a given module -->';
3649
3650 // Note module is inside $dirread
3651
3652 if ($tab == 'description') {
3653 print '<!-- tab=description -->'."\n";
3654 $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
3655 $pathtofilereadme = $modulelowercase.'/README.md';
3656 $pathtochangelog = $modulelowercase.'/ChangeLog.md';
3657
3658 $realpathofmodule = realpath($dirread.'/'.$modulelowercase);
3659
3660 if ($action != 'editfile' || empty($file)) {
3661 $morehtmlright = '';
3662 if ($realpathofmodule != $dirread.'/'.$modulelowercase) {
3663 $morehtmlright = '<div style="padding: 12px 9px 12px">'.$form->textwithpicto('', '<span class="opacitymedium">'.$langs->trans("RealPathOfModule").' :</span> <strong class="wordbreak">'.$realpathofmodule.'</strong>').'</div>';
3664 }
3665
3666 print dol_get_fiche_head($head2, $tab, '', -1, '', 0, $morehtmlright, '', $MAXTABFOROBJECT, 'formodulesuffix'); // Description - level 2
3667
3668 print '<span class="opacitymedium">'.$langs->trans("ModuleBuilderDesc".$tab).'</span>';
3669 print '<br><br>';
3670
3671 print '<table>';
3672
3673 print '<tr><td>';
3674 print '<span class="fa fa-file"></span> '.$langs->trans("DescriptorFile").' : <strong class="wordbreak">'.$pathtofile.'</strong>';
3675 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>';
3676 print '</td></tr>';
3677
3678 // List of setup pages
3679 $listofsetuppages = dol_dir_list($realpathofmodule.'/admin', 'files', 0, '\.php$');
3680 foreach ($listofsetuppages as $setuppage) {
3681 //var_dump($setuppage);
3682 print '<tr><td>';
3683 print '<span class="fa fa-file"></span> ';
3684 if ($setuppage['relativename'] == 'about.php') {
3685 print $langs->trans("AboutFile");
3686 } else {
3687 print $langs->trans("SetupFile");
3688 }
3689 print ' : ';
3690 print '<strong class="wordbreak bold"><a href="'.dol_buildpath($modulelowercase.'/admin/'.$setuppage['relativename'], 1).'" target="_test">'.$modulelowercase.'/admin/'.$setuppage['relativename'].'</a></strong>';
3691 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>';
3692 print '</td></tr>';
3693 }
3694
3695 print '<tr><td><span class="fa fa-file"></span> '.$langs->trans("ReadmeFile").' : <strong class="wordbreak">'.$pathtofilereadme.'</strong>';
3696 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>';
3697 print '</td></tr>';
3698
3699 print '<tr><td><span class="fa fa-file"></span> '.$langs->trans("ChangeLog").' : <strong class="wordbreak">'.$pathtochangelog.'</strong>';
3700 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>';
3701 print '</td></tr>';
3702
3703 print '</table>';
3704 print '<br>';
3705
3706 print load_fiche_titre($form->textwithpicto($langs->trans("DescriptorFile"), $langs->transnoentitiesnoconv("File").' '.$pathtofile), '', '');
3707
3708 if (is_object($moduleobj)) {
3709 print '<div class="underbanner clearboth"></div>';
3710 print '<div class="fichecenter">';
3711 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
3712 print '<input type="hidden" name="token" value="'.newToken().'">';
3713 print '<input type="hidden" name="action" value="update_props_module">';
3714 print '<input type="hidden" name="module" value="'.dol_escape_htmltag($module).'">';
3715 print '<input type="hidden" name="tab" value="'.dol_escape_htmltag($tab).'">';
3716 print '<input type="hidden" name="keydescription" value="'.dol_escape_htmltag(GETPOST('keydescription', 'alpha')).'">';
3717
3718 print '<div class="div-table-responsive-no-min">';
3719 print '<table class="border centpercent">';
3720 print '<tr class="liste_titre"><td class="titlefield">';
3721 print $langs->trans("Parameter");
3722 print '</td><td>';
3723 print $langs->trans("Value");
3724 print '</td></tr>';
3725
3726 print '<tr><td>';
3727 print $langs->trans("IdModule");
3728 print '</td><td>';
3729 print $moduleobj->numero;
3730 print '<span class="opacitymedium">';
3731 print ' &nbsp; (';
3732 print dolButtonToOpenUrlInDialogPopup('popup_modules_id', $langs->transnoentitiesnoconv("SeeIDsInUse"), $langs->transnoentitiesnoconv("SeeIDsInUse"), '/admin/system/modules.php?mainmenu=home&leftmenu=admintools_info', '', '');
3733 print ' - <a href="https://wiki.dolibarr.org/index.php/List_of_modules_id" target="_blank" rel="noopener noreferrer external">'.$langs->trans("SeeReservedIDsRangeHere").'</a>)';
3734 print '</span>';
3735 print '</td></tr>';
3736
3737 print '<tr><td>';
3738 print $langs->trans("ModuleName");
3739 print '</td><td>';
3740 print $moduleobj->getName();
3741 print '</td></tr>';
3742
3743 print '<tr><td>';
3744 print $langs->trans("Description");
3745 print '</td><td>';
3746 if ($action == 'edit_moduledescription' && GETPOST('keydescription', 'alpha') === 'desc') {
3747 print '<input class="minwidth500" name="propsmodule" value="'.dol_escape_htmltag($moduleobj->description).'">';
3748 print '<input class="reposition button smallpaddingimp" type="submit" name="modifydesc" value="'.$langs->trans("Modify").'"/>';
3749 print '<input class="reposition button button-cancel smallpaddingimp" type="submit" name="cancel" value="'.$langs->trans("Cancel").'"/>';
3750 } else {
3751 print $moduleobj->description;
3752 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>';
3753
3754 $moduledescritpionautotrans = $moduleobj->getDesc();
3755 if ($moduledescritpionautotrans != "Module".$moduleobj->name."Desc") {
3756 // $moduledescritpionautotrans has been found into a translation file
3757 print ' '.$form->textwithpicto('', $langs->trans("ModuleTranslatedIntoLangForKeyInto", "Module".$moduleobj->name."Desc", $moduledescritpionautotrans));
3758 } elseif ($moduledescritpionautotrans != "Module".$moduleobj->numero."Desc") {
3759 // $moduledescritpionautotrans has been found into a translation file
3760 print ' '.$form->textwithpicto('', $langs->trans("ModuleTranslatedIntoLangForKeyInto", "Module".$moduleobj->numero."Desc", $moduledescritpionautotrans));
3761 }
3762 }
3763 print '</td></tr>';
3764
3765 print '<tr><td>';
3766 print $langs->trans("Version");
3767 print '</td><td>';
3768 if ($action == 'edit_moduledescription' && GETPOST('keydescription', 'alpha') === 'version') {
3769 print '<input name="propsmodule" value="'.dol_escape_htmltag($moduleobj->getVersion()).'">';
3770 print '<input class="reposition button smallpaddingimp" type="submit" name="modifyversion" value="'.$langs->trans("Modify").'"/>';
3771 print '<input class="reposition button button-cancel smallpaddingimp" type="submit" name="cancel" value="'.$langs->trans("Cancel").'"/>';
3772 } else {
3773 print $moduleobj->getVersion();
3774 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>';
3775 }
3776 print '</td></tr>';
3777
3778 print '<tr><td>';
3779 print $langs->trans("Family");
3780 //print "<br>'crm','financial','hr','projects','products','ecm','technic','interface','other'";
3781 print '</td><td>';
3782 if ($action == 'edit_moduledescription' && GETPOST('keydescription', 'alpha') === 'family') {
3783 print '<select name="propsmodule" id="family" class="minwidth400">';
3784 $arrayoffamilies = array(
3785 'hr' => "ModuleFamilyHr",
3786 'crm' => "ModuleFamilyCrm",
3787 'srm' => "ModuleFamilySrm",
3788 'financial' => 'ModuleFamilyFinancial',
3789 'products' => 'ModuleFamilyProducts',
3790 'projects' => 'ModuleFamilyProjects',
3791 'ecm' => 'ModuleFamilyECM',
3792 'technic' => 'ModuleFamilyTechnic',
3793 'portal' => 'ModuleFamilyPortal',
3794 'interface' => 'ModuleFamilyInterface',
3795 'base' => 'ModuleFamilyBase',
3796 'other' => 'ModuleFamilyOther'
3797 );
3798 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>';
3799 foreach ($arrayoffamilies as $key => $value) {
3800 if ($key != $moduleobj->family) {
3801 print '<option value="'.$key.'" data-html="'.dol_escape_htmltag($langs->trans($value).' <span class="opacitymedium">- '.$key.'</span>').'">'.$langs->trans($value).'</option>';
3802 }
3803 }
3804 print '</select>';
3805 print '<input class="reposition button smallpaddingimp" type="submit" name="modifyfamily" value="'.$langs->trans("Modify").'"/>';
3806 print '<input class="reposition button button-cancel smallpaddingimp" type="submit" name="cancel" value="'.$langs->trans("Cancel").'"/>';
3807 } else {
3808 print $moduleobj->family;
3809 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>';
3810 }
3811 print '</td></tr>';
3812
3813 print '<!-- picto of module -->'."\n";
3814 print '<tr><td>';
3815 print $langs->trans("Picto");
3816 print '</td><td>';
3817 if ($action == 'edit_modulepicto' && GETPOST('keydescription', 'alpha') === 'picto') {
3818 print '<input class="minwidth200 maxwidth500" name="propsmodule" value="'.dol_escape_htmltag($moduleobj->picto).'">';
3819
3820 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\'');
3821
3822 print '<input class="reposition button smallpaddingimp" type="submit" name="modifypicto" value="'.$langs->trans("Modify").'"/>';
3823 print '<input class="reposition button button-cancel smallpaddingimp" type="submit" name="cancel" value="'.$langs->trans("Cancel").'"/>';
3824
3825 print ' &nbsp; &nbsp; ';
3826
3827 print '<span class="opacitymedium small">';
3828 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', '', '');
3829 print '</span>';
3830 } else {
3831 print $moduleobj->picto;
3832 print ' &nbsp; '.img_picto('', $moduleobj->picto, 'class="valignmiddle pictomodule paddingrightonly"');
3833 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>';
3834 }
3835 print '</td></tr>';
3836
3837 print '<tr><td>';
3838 print $langs->trans("EditorName");
3839 print '</td><td>';
3840 if ($action == 'edit_moduledescription' && GETPOST('keydescription', 'alpha') === 'editor_name') {
3841 print '<input name="propsmodule" value="'.dol_escape_htmltag($moduleobj->editor_name).'">';
3842 print '<input class="reposition button smallpaddingimp" type="submit" name="modifyname" value="'.$langs->trans("Modify").'"/>';
3843 print '<input class="reposition button button-cancel smallpaddingimp" type="submit" name="cancel" value="'.$langs->trans("Cancel").'"/>';
3844 } else {
3845 print $moduleobj->editor_name;
3846 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>';
3847 }
3848 print '</td></tr>';
3849
3850 print '<tr><td>';
3851 print $langs->trans("EditorUrl");
3852 print '</td><td>';
3853 if ($action == 'edit_moduledescription' && GETPOST('keydescription', 'alpha') === 'editor_url') {
3854 print '<input name="propsmodule" value="'.dol_escape_htmltag($moduleobj->editor_url).'">';
3855 print '<input class="reposition button smallpaddingimp" type="submit" name="modifyeditorurl" value="'.$langs->trans("Modify").'"/>';
3856 print '<input class="reposition button button-cancel smallpaddingimp" type="submit" name="cancel" value="'.$langs->trans("Cancel").'"/>';
3857 } else {
3858 if (!empty($moduleobj->editor_url)) {
3859 print '<a href="'.$moduleobj->editor_url.'" target="_blank" rel="noopener">'.$moduleobj->editor_url.' '.img_picto('', 'globe').'</a>';
3860 }
3861 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>';
3862 }
3863 print '</td></tr>';
3864
3865 print '</table>';
3866 print '</div>';
3867 print '</form>';
3868 } else {
3869 print $langs->trans("ErrorFailedToLoadModuleDescriptorForXXX", $module).'<br>';
3870 }
3871
3872 if (!empty($moduleobj)) {
3873 print '<br><br>';
3874
3875 // Readme file
3876 print load_fiche_titre($form->textwithpicto($langs->trans("ReadmeFile"), $langs->transnoentitiesnoconv("File").' '.$pathtofilereadme), '', '');
3877
3878 print '<!-- readme file -->';
3879 if (dol_is_file($dirread.'/'.$pathtofilereadme)) {
3880 print '<div class="underbanner clearboth"></div><div class="fichecenter">'.$moduleobj->getDescLong().'</div>';
3881 } else {
3882 print '<span class="opacitymedium">'.$langs->trans("ErrorFileNotFound", $pathtofilereadme).'</span>';
3883 }
3884
3885 print '<br><br>';
3886
3887 // ChangeLog
3888 print load_fiche_titre($form->textwithpicto($langs->trans("ChangeLog"), $langs->transnoentitiesnoconv("File").' '.$pathtochangelog), '', '');
3889
3890 print '<!-- changelog file -->';
3891 if (dol_is_file($dirread.'/'.$pathtochangelog)) {
3892 print '<div class="underbanner clearboth"></div><div class="fichecenter">'.$moduleobj->getChangeLog().'</div>';
3893 } else {
3894 print '<span class="opacitymedium">'.$langs->trans("ErrorFileNotFound", $pathtochangelog).'</span>';
3895 }
3896 }
3897
3898 print dol_get_fiche_end();
3899 } else { // Edit text file
3900 $fullpathoffile = dol_buildpath($file, 0, 1); // Description - level 2
3901
3902 $content = '';
3903 if ($fullpathoffile) {
3904 $content = file_get_contents($fullpathoffile);
3905 }
3906
3907 // New module
3908 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
3909 print '<input type="hidden" name="token" value="'.newToken().'">';
3910 print '<input type="hidden" name="action" value="savefile">';
3911 print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
3912 print '<input type="hidden" name="tab" value="'.$tab.'">';
3913 print '<input type="hidden" name="module" value="'.$module.'">';
3914
3915 print dol_get_fiche_head($head2, $tab, '', -1, '', 0, '', '', 0, 'formodulesuffix');
3916
3917 $posCursor = (empty($find)) ? array() : array('find' => $find);
3918 $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%', 0, $posCursor);
3919 print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'html'));
3920
3921 print dol_get_fiche_end();
3922
3923 print '<center>';
3924 print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
3925 print ' &nbsp; ';
3926 print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
3927 print '</center>';
3928
3929 print '</form>';
3930 }
3931 } else {
3932 print dol_get_fiche_head($head2, $tab, '', -1, '', 0, '', '', $MAXTABFOROBJECT, 'formodulesuffix'); // Level 2
3933 }
3934
3935 if ($tab == 'languages') {
3936 print '<!-- tab=languages -->'."\n";
3937 if ($action != 'editfile' || empty($file)) {
3938 print '<span class="opacitymedium">'.$langs->trans("LanguageDefDesc").'</span><br>';
3939 print '<br>';
3940
3941
3942 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
3943 print '<input type="hidden" name="token" value="'.newToken().'">';
3944 print '<input type="hidden" name="action" value="addlanguage">';
3945 print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
3946 print '<input type="hidden" name="tab" value="'.$tab.'">';
3947 print '<input type="hidden" name="module" value="'.$module.'">';
3948 print $formadmin->select_language(getDolGlobalString('MAIN_LANG_DEFAULT'), 'newlangcode', 0, array(), 1, 0, 0, 'minwidth300', 1);
3949 print '<input type="submit" name="addlanguage" class="button smallpaddingimp" value="'.dol_escape_htmltag($langs->trans("AddLanguageFile")).'"><br>';
3950 print '</form>';
3951
3952 print '<br>';
3953 print '<br>';
3954
3955 $modulelowercase = strtolower($module);
3956
3957 // Dir for module
3958 $diroflang = dol_buildpath($modulelowercase, 0);
3959 $diroflang .= '/langs';
3960 $langfiles = dol_dir_list($diroflang, 'files', 1, '\.lang$');
3961
3962 if (!preg_match('/custom/', $dirread)) {
3963 // If this is not a module into custom
3964 $diroflang = $dirread;
3965 $diroflang .= '/langs';
3966 $langfiles = dol_dir_list($diroflang, 'files', 1, $modulelowercase.'\.lang$');
3967 }
3968
3969 print '<table class="none">';
3970 foreach ($langfiles as $langfile) {
3971 $pathtofile = $modulelowercase.'/langs/'.$langfile['relativename'];
3972 if (!preg_match('/custom/', $dirread)) { // If this is not a module into custom
3973 $pathtofile = 'langs/'.$langfile['relativename'];
3974 }
3975 print '<tr><td><span class="fa fa-file"></span> '.$langs->trans("LanguageFile").' '.basename(dirname($pathtofile)).' : <strong class="wordbreak">'.$pathtofile.'</strong>';
3976 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>';
3977 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>';
3978 print '</td>';
3979 }
3980 print '</table>';
3981 } else {
3982 // Edit text language file
3983
3984 //print $langs->trans("UseAsciiDocFormat").'<br>';
3985
3986 $fullpathoffile = dol_buildpath($file, 0);
3987
3988 $content = file_get_contents($fullpathoffile);
3989
3990 // New module
3991 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
3992 print '<input type="hidden" name="token" value="'.newToken().'">';
3993 print '<input type="hidden" name="action" value="savefile">';
3994 print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
3995 print '<input type="hidden" name="tab" value="'.$tab.'">';
3996 print '<input type="hidden" name="module" value="'.$module.'">';
3997
3998 $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%');
3999 print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'text'));
4000 print '<br>';
4001 print '<center>';
4002 print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
4003 print ' &nbsp; ';
4004 print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
4005 print '</center>';
4006
4007 print '</form>';
4008 }
4009 }
4010
4011 if ($tab == 'objects') {
4012 print '<!-- tab=objects -->'."\n";
4013 $head3 = array();
4014 $h = 0;
4015
4016 // Dir for module
4017 $dir = $dirread.'/'.$modulelowercase.'/class';
4018
4019 $head3[$h][0] = $_SERVER["PHP_SELF"].'?tab=objects&module='.$module.($forceddirread ? '@'.$dirread : '').'&tabobj=newobject';
4020 $head3[$h][1] = '<span class="valignmiddle text-plus-circle">'.$langs->trans("NewObjectInModulebuilder").'</span><span class="fa fa-plus-circle valignmiddle paddingleft"></span>';
4021 $head3[$h][2] = 'newobject';
4022 $h++;
4023
4024 // Scan for object class files
4025 $listofobject = dol_dir_list($dir, 'files', 0, '\.class\.php$');
4026
4027 $firstobjectname = '';
4028 foreach ($listofobject as $fileobj) {
4029 if (preg_match('/^api_/', $fileobj['name'])) {
4030 continue;
4031 }
4032 if (preg_match('/^actions_/', $fileobj['name'])) {
4033 continue;
4034 }
4035
4036 $tmpcontent = file_get_contents($fileobj['fullname']);
4037 if (preg_match('/class\s+([^\s]*)\s+extends\s+CommonObject/ims', $tmpcontent, $reg)) {
4038 //$objectname = preg_replace('/\.txt$/', '', $fileobj['name']);
4039 $objectname = $reg[1];
4040 if (empty($firstobjectname)) {
4041 $firstobjectname = $objectname;
4042 }
4043 $pictoname = 'generic';
4044 if (preg_match('/\$picto\s*=\s*["\']([^"\']+)["\']/', $tmpcontent, $reg)) {
4045 $pictoname = $reg[1];
4046 }
4047
4048 $head3[$h][0] = $_SERVER["PHP_SELF"].'?tab=objects&module='.$module.($forceddirread ? '@'.$dirread : '').'&tabobj='.$objectname;
4049 $head3[$h][1] = img_picto('', $pictoname, 'class="pictofixedwidth valignmiddle"').$objectname;
4050 $head3[$h][2] = $objectname;
4051 $h++;
4052 }
4053 }
4054
4055 if ($h > 1) {
4056 $head3[$h][0] = $_SERVER["PHP_SELF"].'?tab=objects&module='.$module.($forceddirread ? '@'.$dirread : '').'&tabobj=deleteobject';
4057 $head3[$h][1] = img_picto('', 'delete', 'class="pictofixedwidth"').$langs->trans("DangerZone");
4058 $head3[$h][2] = 'deleteobject';
4059 $h++;
4060 }
4061
4062 // 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.
4063 if ($tabobj == 'newobjectifnoobj') {
4064 if ($firstobjectname) {
4065 $tabobj = $firstobjectname;
4066 } else {
4067 $tabobj = 'newobject';
4068 }
4069 }
4070
4071 print dol_get_fiche_head($head3, $tabobj, '', -1, '', 0, '', '', 0, 'forobjectsuffix'); // Level 3
4072
4073
4074 if ($tabobj == 'newobject') {
4075 // New object tab
4076 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
4077 print '<input type="hidden" name="token" value="'.newToken().'">';
4078 print '<input type="hidden" name="action" value="initobject">';
4079 print '<input type="hidden" name="tab" value="objects">';
4080 print '<input type="hidden" name="module" value="'.dol_escape_htmltag($module).'">';
4081
4082 print '<span class="opacitymedium">'.$langs->trans("EnterNameOfObjectDesc").'</span><br><br>';
4083
4084 print '<div class="tagtable">';
4085
4086 print '<div class="tagtr"><div class="tagtd">';
4087 print '<span class="opacitymedium">'.$langs->trans("ObjectKey").'</span> &nbsp; ';
4088 print '</div><div class="tagtd">';
4089 print '<input type="text" name="objectname" maxlength="64" value="'.dol_escape_htmltag(GETPOSTISSET('objectname') ? GETPOST('objectname', 'alpha') : $modulename).'" autofocus>';
4090 print $form->textwithpicto('', $langs->trans("Example").': MyObject, ACamelCaseName, ...');
4091 print '</div></div>';
4092
4093 print '<div class="tagtr"><div class="tagtd">';
4094 print '<span class="opacitymedium">'.$langs->trans("Picto").'</span> &nbsp; ';
4095 print '</div><div class="tagtd">';
4096 print '<input type="text" name="idpicto" value="fa-file" placeholder="'.dol_escape_htmltag($langs->trans("Picto")).'">';
4097
4098 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\'');
4099
4100 print '<span class="opacitymedium small">';
4101 print ' &nbsp; &nbsp; ';
4102 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', '', '');
4103 print '</span>';
4104
4105 print '</div></div>';
4106
4107 print '<div class="tagtr"><div class="tagtd">';
4108 print '<span class="opacitymedium">'.$langs->trans("DefinePropertiesFromExistingTable").'</span> &nbsp; ';
4109 print '</div><div class="tagtd">';
4110 print '<input type="text" name="initfromtablename" value="'.GETPOST('initfromtablename').'" placeholder="'.$langs->trans("TableName").'">';
4111 print $form->textwithpicto('', $langs->trans("DefinePropertiesFromExistingTableDesc").'<br>'.$langs->trans("DefinePropertiesFromExistingTableDesc2"));
4112 print '</div></div>';
4113
4114 print '</div>';
4115
4116 print '<br>';
4117 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>';
4118 print '<input type="checkbox" name="includedocgeneration" id="includedocgeneration" value="includedocgeneration"> <label for="includedocgeneration">'.$form->textwithpicto($langs->trans("IncludeDocGeneration"), $langs->trans("IncludeDocGenerationHelp")).'</label><br>';
4119 print '<input type="checkbox" name="generatepermissions" id="generatepermissions" value="generatepermissions"> <label for="generatepermissions">'.$form->textwithpicto($langs->trans("GeneratePermissions"), $langs->trans("GeneratePermissionsHelp")).'</label><br>';
4120 print '<br>';
4121 print '<input type="submit" class="button small" name="create" value="'.dol_escape_htmltag($langs->trans("GenerateCode")).'"'.($dirins ? '' : ' disabled="disabled"').'>';
4122 print '<br>';
4123 print '<br>';
4124 /*
4125 print '<br>';
4126 print '<span class="opacitymedium">'.$langs->trans("or").'</span>';
4127 print '<br>';
4128 print '<br>';
4129 //print '<input type="checkbox" name="initfromtablecheck"> ';
4130 print $langs->trans("InitStructureFromExistingTable");
4131 print '<input type="text" name="initfromtablename" value="" placeholder="'.$langs->trans("TableName").'">';
4132 print '<input type="submit" class="button smallpaddingimp" name="createtablearray" value="'.dol_escape_htmltag($langs->trans("GenerateCode")).'"'.($dirins ? '' : ' disabled="disabled"').'>';
4133 print '<br>';
4134 */
4135
4136 print '</form>';
4137 } elseif ($tabobj == 'createproperty') {
4138 $attributesUnique = array(
4139 'proplabel' => $form->textwithpicto($langs->trans("Label"), $langs->trans("YouCanUseTranslationKey")),
4140 'propname' => $form->textwithpicto($langs->trans("Code"), $langs->trans("PropertyDesc"), 1, 'help', 'extracss', 0, 3, 'propertyhelp'),
4141 'proptype' => $form->textwithpicto($langs->trans("Type"), $langs->trans("TypeOfFieldsHelpIntro").'<br><br>'.$langs->trans("TypeOfFieldsHelp"), 1, 'help', 'extracss', 0, 3, 'typehelp'),
4142 'proparrayofkeyval' => $form->textwithpicto($langs->trans("ArrayOfKeyValues"), $langs->trans("ArrayOfKeyValuesDesc")),
4143 'propnotnull' => $form->textwithpicto($langs->trans("NotNull"), $langs->trans("NotNullDesc")),
4144 'propdefault' => $langs->trans("DefaultValue"),
4145 'propindex' => $langs->trans("DatabaseIndex"),
4146 'propforeignkey' => $form->textwithpicto($langs->trans("ForeignKey"), $langs->trans("ForeignKeyDesc"), 1, 'help', 'extracss', 0, 3, 'foreignkeyhelp'),
4147 'propposition' => $langs->trans("Position"),
4148 'propenabled' => $form->textwithpicto($langs->trans("Enabled"), $langs->trans("EnabledDesc"), 1, 'help', 'extracss', 0, 3, 'enabledhelp'),
4149 'propvisible' => $form->textwithpicto($langs->trans("Visibility"), $langs->trans("VisibleDesc").'<br><br>'.$langs->trans("ItCanBeAnExpression"), 1, 'help', 'extracss', 0, 3, 'visiblehelp'),
4150 'propnoteditable' => $langs->trans("NotEditable"),
4151 //'propalwayseditable' => $langs->trans("AlwaysEditable"),
4152 'propsearchall' => $form->textwithpicto($langs->trans("SearchAll"), $langs->trans("SearchAllDesc")),
4153 'propisameasure' => $form->textwithpicto($langs->trans("IsAMeasure"), $langs->trans("IsAMeasureDesc")),
4154 'propcss' => $langs->trans("CSSClass"),
4155 'propcssview' => $langs->trans("CSSViewClass"),
4156 'propcsslist' => $langs->trans("CSSListClass"),
4157 'prophelp' => $langs->trans("KeyForTooltip"),
4158 'propshowoncombobox' => $langs->trans("ShowOnCombobox"),
4159 //'propvalidate' => $form->textwithpicto($langs->trans("Validate"), $langs->trans("ValidateModBuilderDesc")),
4160 'propcomment' => $langs->trans("Comment"),
4161 );
4162 print '<form action="'.$_SERVER["PHP_SELF"].'?tab=objects&module='.urlencode($module).'&tabobj=createproperty&obj='.urlencode(GETPOST('obj')).'" method="POST">';
4163 print '<input type="hidden" name="token" value="'.newToken().'">';
4164 print '<input type="hidden" name="action" value="addproperty">';
4165 print '<input type="hidden" name="tab" value="objects">';
4166 print '<input type="hidden" name="module" value="'.dol_escape_htmltag($module).'">';
4167 print '<input type="hidden" name="obj" value="'.dol_escape_htmltag(GETPOST('obj')).'">';
4168
4169 print '<table class="border centpercent tableforfieldcreate">'."\n";
4170 $counter = 0;
4171 foreach ($attributesUnique as $key => $attribute) {
4172 if ($counter % 2 === 0) {
4173 print '<tr>';
4174 }
4175 if ($key == 'propname' || $key == 'proplabel') {
4176 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>';
4177 } elseif ($key == 'proptype') {
4178 print '<td class="titlefieldcreate fieldrequired">'.$attribute.'</td><td class="valuefieldcreate maxwidth50">';
4179 print '<input class="maxwidth200" name="'.$key.'" id="'.$key.'" list="datalist'.$key.'" type="text" value="'.dol_escape_htmltag(GETPOST($key, 'alpha')).'">';
4180 //print '<div id="suggestions"></div>';
4181 print '<datalist id="datalist'.$key.'">';
4182 print '<option>varchar(128)</option>';
4183 print '<option>email</option>';
4184 print '<option>phone</option>';
4185 print '<option>ip</option>';
4186 print '<option>url</option>';
4187 print '<option>password</option>';
4188 print '<option>text</option>';
4189 print '<option>html</option>';
4190 print '<option>date</option>';
4191 print '<option>datetime</option>';
4192 print '<option>integer</option>';
4193 print '<option>stars(5)</option>';
4194 print '<option>double(28,4)</option>';
4195 print '<option>real</option>';
4196 print '<option>integer:ClassName:RelativePath/To/ClassFile.class.php[:1[:FILTER]]</option>';
4197 // Combo with list of fields
4198 /*
4199 if (empty($formadmin)) {
4200 include_once DOL_DOCUMENT_ROOT.'/core/class/html.formadmin.class.php';
4201 $formadmin = new FormAdmin($db);
4202 }
4203 print $formadmin->selectTypeOfFields($key, GETPOST($key, 'alpha'));
4204 */
4205 print '</datalist>';
4206 print '</td>';
4207 //} elseif ($key == 'propvalidate') {
4208 // 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>';
4209 } elseif ($key == 'propvisible') {
4210 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>';
4211 } elseif ($key == 'propenabled') {
4212 //$default = "isModEnabled('".strtolower($module)."')";
4213 $default = 1;
4214 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>';
4215 } elseif ($key == 'proparrayofkeyval') {
4216 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>';
4217 } else {
4218 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>';
4219 }
4220 $counter++;
4221 if ($counter % 2 === 0) {
4222 print '</tr>';
4223 }
4224 }
4225 if ($counter % 2 !== 0) {
4226 while ($counter % 2 !== 0) {
4227 print '<td></td>';
4228 $counter++;
4229 }
4230 print '</tr>';
4231 }
4232 print '</table><br>'."\n";
4233 print '<div class="center">';
4234 print '<input type="submit" class="button button-save" name="add" value="' . dol_escape_htmltag($langs->trans('Create')) . '">';
4235 print '<input type="button" class="button button-cancel" name="cancel" value="' . dol_escape_htmltag($langs->trans('Cancel')) . '" onclick="goBack()">';
4236 print '</div>';
4237 print '</form>';
4238 // javascript
4239 print '<script>
4240 function goBack() {
4241 var url = "'.$_SERVER["PHP_SELF"].'?tab=objects&module='.urlencode($module).'";
4242 window.location.href = url;
4243 }
4244 $(document).ready(function() {
4245 $("#proplabel").on("keyup", function() {
4246 console.log("key up on label");
4247 s = cleanString($("#proplabel").val());
4248 $("#propname").val(s);
4249 });
4250
4251 function cleanString( stringtoclean )
4252 {
4253 // allow "a-z", "A-Z", "0-9" and "_"
4254 stringtoclean = stringtoclean.replace(/[^a-z0-9_]+/ig, "");
4255 stringtoclean = stringtoclean.toLowerCase();
4256 if (!isNaN(stringtoclean)) {
4257 return ""
4258 }
4259 while ( stringtoclean.length > 1 && !isNaN( stringtoclean.charAt(0)) ){
4260 stringtoclean = stringtoclean.substr(1)
4261 }
4262 if (stringtoclean.length > 28) {
4263 stringtoclean = stringtoclean.substring(0, 27);
4264 }
4265 return stringtoclean;
4266 }
4267
4268 });';
4269 print '</script>';
4270 } elseif ($tabobj == 'deleteobject') {
4271 // Delete object tab
4272 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
4273 print '<input type="hidden" name="token" value="'.newToken().'">';
4274 print '<input type="hidden" name="action" value="confirm_deleteobject">';
4275 print '<input type="hidden" name="tab" value="objects">';
4276 print '<input type="hidden" name="tabobj" value="deleteobject">';
4277 print '<input type="hidden" name="module" value="'.dol_escape_htmltag($module).'">';
4278
4279 print $langs->trans("EnterNameOfObjectToDeleteDesc").'<br><br>';
4280
4281 print '<input type="text" name="objectname" value="" placeholder="'.dol_escape_htmltag($langs->trans("ObjectKey")).'" autofocus>';
4282 print '<input type="submit" class="button smallpaddingimp" name="delete" value="'.dol_escape_htmltag($langs->trans("Delete")).'"'.($dirins ? '' : ' disabled="disabled"').'>';
4283 print '</form>';
4284 } else {
4285 // tabobj = module
4286 if ($action == 'deleteproperty') {
4287 $formconfirm = $form->formconfirm(
4288 $_SERVER["PHP_SELF"].'?propertykey='.urlencode(GETPOST('propertykey', 'alpha')).'&objectname='.urlencode($objectname).'&tab='.urlencode($tab).'&module='.urlencode($module).'&tabobj='.urlencode($tabobj),
4289 $langs->trans('Delete'),
4290 $langs->trans('ConfirmDeleteProperty', GETPOST('propertykey', 'alpha')),
4291 'confirm_deleteproperty',
4292 '',
4293 0,
4294 1
4295 );
4296
4297 // Print form confirm
4298 print $formconfirm;
4299 }
4300 if ($action != 'editfile' || empty($file)) {
4301 try {
4302 //$pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
4303
4304 $pathtoclass = strtolower($module).'/class/'.strtolower($tabobj).'.class.php';
4305 $pathtoapi = strtolower($module).'/class/api_'.strtolower($module).'.class.php';
4306 $pathtoagenda = strtolower($module).'/'.strtolower($tabobj).'_agenda.php';
4307 $pathtocard = strtolower($module).'/'.strtolower($tabobj).'_card.php';
4308 $pathtodocument = strtolower($module).'/'.strtolower($tabobj).'_document.php';
4309 $pathtolist = strtolower($module).'/'.strtolower($tabobj).'_list.php';
4310 $pathtonote = strtolower($module).'/'.strtolower($tabobj).'_note.php';
4311 $pathtocontact = strtolower($module).'/'.strtolower($tabobj).'_contact.php';
4312 $pathtophpunit = strtolower($module).'/test/phpunit/'.strtolower($tabobj).'Test.php';
4313
4314 // Try to load object class file
4315 clearstatcache(true);
4316 if (function_exists('opcache_invalidate')) {
4317 opcache_invalidate($dirread.'/'.$pathtoclass, true); // remove the include cache hell !
4318 }
4319
4320 if (empty($forceddirread) && empty($dirread)) {
4321 $result = dol_include_once($pathtoclass);
4322 $stringofinclude = "dol_include_once(".$pathtoclass.")";
4323 } else {
4324 $result = include_once $dirread.'/'.$pathtoclass;
4325 $stringofinclude = "@include_once ".$dirread.'/'.$pathtoclass;
4326 }
4327
4328 if (class_exists($tabobj)) {
4329 try {
4330 $tmpobject = @new $tabobj($db);
4331 } catch (Exception $e) {
4332 dol_syslog('Failed to load Constructor of class: '.$e->getMessage(), LOG_WARNING);
4333 }
4334 } else {
4335 print '<span class="warning">'.$langs->trans('Failed to find the class '.$tabobj.' despite the '.$stringofinclude).'</span><br><br>';
4336 }
4337
4338 // Define path for sql file
4339 $pathtosql = strtolower($module).'/sql/llx_'.strtolower($module).'_'.strtolower($tabobj).'-'.strtolower($module).'.sql';
4340 $result = dol_buildpath($pathtosql);
4341 if (! dol_is_file($result)) {
4342 $pathtosql = strtolower($module).'/sql/llx_'.strtolower($module).'_'.strtolower($tabobj).'.sql';
4343 $result = dol_buildpath($pathtosql);
4344 if (! dol_is_file($result)) {
4345 $pathtosql = 'install/mysql/tables/llx_'.strtolower($module).'_'.strtolower($tabobj).'-'.strtolower($module).'.sql';
4346 $result = dol_buildpath($pathtosql);
4347 if (! dol_is_file($result)) {
4348 $pathtosql = 'install/mysql/tables/llx_'.strtolower($module).'-'.strtolower($module).'.sql';
4349 $result = dol_buildpath($pathtosql);
4350 if (! dol_is_file($result)) {
4351 $pathtosql = 'install/mysql/tables/llx_'.strtolower($module).'.sql';
4352 $pathtosqlextra = 'install/mysql/tables/llx_'.strtolower($module).'_extrafields.sql';
4353 $result = dol_buildpath($pathtosql);
4354 } else {
4355 $pathtosqlextra = 'install/mysql/tables/llx_'.strtolower($module).'_extrafields-'.strtolower($module).'.sql';
4356 }
4357 } else {
4358 $pathtosqlextra = 'install/mysql/tables/llx_'.strtolower($module).'_'.strtolower($tabobj).'_extrafields-'.strtolower($module).'.sql';
4359 }
4360 } else {
4361 $pathtosqlextra = strtolower($module).'/sql/llx_'.strtolower($module).'_'.strtolower($tabobj).'_extrafields.sql';
4362 }
4363 } else {
4364 $pathtosqlextra = strtolower($module).'/sql/llx_'.strtolower($module).'_'.strtolower($tabobj).'_extrafields-'.strtolower($module).'.sql';
4365 }
4366 $pathtosqlroot = preg_replace('/\/llx_.*$/', '', $pathtosql);
4367
4368 $pathtosqlkey = preg_replace('/\.sql$/', '.key.sql', $pathtosql);
4369 $pathtosqlextrakey = preg_replace('/\.sql$/', '.key.sql', $pathtosqlextra);
4370
4371 $pathtolib = strtolower($module).'/lib/'.strtolower($module).'.lib.php';
4372 $pathtoobjlib = strtolower($module).'/lib/'.strtolower($module).'_'.strtolower($tabobj).'.lib.php';
4373
4374 $tmpobject = $tmpobject ?? null; // @phan-suppress-current-line PhanPluginDuplicateExpressionAssignmentOperation
4375 if (is_object($tmpobject) && property_exists($tmpobject, 'picto')) {
4376 $pathtopicto = $tmpobject->picto;
4377 $realpathtopicto = '';
4378 } else {
4379 $pathtopicto = strtolower($module).'/img/object_'.strtolower($tabobj).'.png';
4380 $realpathtopicto = $dirread.'/'.$pathtopicto;
4381 }
4382
4383 //var_dump($pathtoclass);
4384 //var_dump($dirread);
4385 $realpathtoclass = $dirread.'/'.$pathtoclass;
4386 $realpathtoapi = $dirread.'/'.$pathtoapi;
4387 $realpathtoagenda = $dirread.'/'.$pathtoagenda;
4388 $realpathtocard = $dirread.'/'.$pathtocard;
4389 $realpathtodocument = $dirread.'/'.$pathtodocument;
4390 $realpathtolist = $dirread.'/'.$pathtolist;
4391 $realpathtonote = $dirread.'/'.$pathtonote;
4392 $realpathtocontact = $dirread.'/'.$pathtocontact;
4393 $realpathtophpunit = $dirread.'/'.$pathtophpunit;
4394 $realpathtosql = $dirread.'/'.$pathtosql;
4395 $realpathtosqlextra = $dirread.'/'.$pathtosqlextra;
4396 $realpathtosqlkey = $dirread.'/'.$pathtosqlkey;
4397 $realpathtosqlextrakey = $dirread.'/'.$pathtosqlextrakey;
4398 $realpathtolib = $dirread.'/'.$pathtolib;
4399 $realpathtoobjlib = $dirread.'/'.$pathtoobjlib;
4400
4401 if (empty($realpathtoapi)) { // For compatibility with some old modules
4402 $pathtoapi = strtolower($module).'/class/api_'.strtolower($module).'s.class.php';
4403 $realpathtoapi = $dirread.'/'.$pathtoapi;
4404 }
4405
4406 $urloflist = dol_buildpath('/'.$pathtolist, 1);
4407 $urlofcard = dol_buildpath('/'.$pathtocard, 1);
4408
4409 $objs = array();
4410
4411 // Image
4412 $htmltooltip = '';
4413 if ($realpathtopicto && dol_is_file($realpathtopicto)) {
4414 $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>';
4415 $htmltooltip .= '<br>';
4416 } elseif (!empty($tmpobject)) {
4417 $htmltooltip .= '<span class="fa fa-file-image-o"></span> '.$langs->trans("Image").' : '.img_picto('', $tmpobject->picto, 'class="pictofixedwidth valignmiddle"').$tmpobject->picto;
4418 $htmltooltip .= '<br>';
4419 }
4420 $htmltooltip .= '<span class="fa fa-file-image-o"></span> '.$langs->trans("IsExtraFieldManaged").' : '.yn(empty($tmpobject->isextrafieldmanaged) ? 0 : 1, 1, 2);
4421 $htmltooltip .= '<br>';
4422 $htmltooltip .= '<span class="fa fa-file-image-o"></span> '.$langs->trans("IsMultiEntityManaged").' : '.yn(empty($tmpobject->ismultientitymanaged) ? 0 : 1, 1, 2);
4423 $htmltooltip .= '<br>';
4424
4425 print '<!-- section for object -->';
4426 print '<div class="fichehalfleft smallxxx">';
4427 // Main DAO class file
4428 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>';
4429 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>';
4430 print $form->textwithpicto('', $htmltooltip, 1, 'help', 'valignmiddle', 1);
4431 print '<br>';
4432
4433 // API file
4434 print '<br>';
4435 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>';
4436 if (dol_is_file($realpathtoapi)) {
4437 $file = file_get_contents($realpathtoapi);
4438 if (preg_match('/var '.$tabobj.'\s+([^\s]*)\s/ims', $file, $objs)) {
4439 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>';
4440 print ' ';
4441 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>';
4442 print $form->textwithpicto('', $langs->trans("InfoForApiFile"), 1, 'warning');
4443 print ' &nbsp; ';
4444 // Comparing to null (phan considers $modulelowercase can be null here)
4445 if (!isModEnabled($modulelowercase)) { // If module is not activated
4446 print '<a href="#" class="classfortooltip" target="apiexplorer" title="'.$langs->trans("ModuleMustBeEnabled", $module).'"><strike>'.$langs->trans("ApiExplorer").'</strike></a>';
4447 } else {
4448 print '<a href="'.DOL_URL_ROOT.'/api/index.php/explorer/" target="apiexplorer">'.$langs->trans("ApiExplorer").'</a>';
4449 }
4450 } else {
4451 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>';
4452 }
4453 } else {
4454 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>';
4455 }
4456 // PHPUnit
4457 print '<br>';
4458 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>';
4459 if (dol_is_file($realpathtophpunit)) {
4460 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>';
4461 print ' ';
4462 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>';
4463 } else {
4464 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>';
4465 }
4466 print '<br>';
4467
4468 print '<br>';
4469
4470 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>';
4471 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>';
4472 print '<br>';
4473 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>';
4474 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>';
4475 print '<br>';
4476
4477 print '<br>';
4478 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>';
4479 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>';
4480 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>';
4481 //print ' &nbsp; <a href="'.$_SERVER["PHP_SELF"].'">'.$langs->trans("RunSql").'</a>';
4482 print '<br>';
4483 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>';
4484 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>';
4485 //print ' &nbsp; <a href="'.$_SERVER["PHP_SELF"].'">'.$langs->trans("RunSql").'</a>';
4486 print '<br>';
4487 if (!empty($tmpobject->isextrafieldmanaged)) {
4488 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>';
4489 if (dol_is_file($realpathtosqlextra) && dol_is_file($realpathtosqlextrakey)) {
4490 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>';
4491 print ' ';
4492 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>';
4493 print ' &nbsp; ';
4494 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>';
4495 } else {
4496 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>';
4497 }
4498
4499 //print ' &nbsp; <a href="'.$_SERVER["PHP_SELF"].'">'.$langs->trans("RunSql").'</a>';
4500 print '<br>';
4501 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>';
4502 if (dol_is_file($realpathtosqlextra) && dol_is_file($realpathtosqlextrakey)) {
4503 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>';
4504 print ' ';
4505 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>';
4506 } else {
4507 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>';
4508 }
4509 print '<br>';
4510 }
4511 print '</div>';
4512
4513 print '<div class="fichehalfleft smallxxxx">';
4514 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>';
4515 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>';
4516 print '<br>';
4517 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>';
4518 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>';
4519 print '<br>';
4520 // Page contact
4521 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>';
4522 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>';
4523 if (dol_is_file($realpathtocontact)) {
4524 print ' ';
4525 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>';
4526 } else {
4527 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>';
4528 }
4529 print '<br>';
4530 // Page document
4531 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>';
4532 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>';
4533 if (dol_is_file($realpathtodocument)) {
4534 print ' ';
4535 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>';
4536 } else {
4537 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>';
4538 }
4539 print '<br>';
4540 // Page notes
4541 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>';
4542 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>';
4543 if (dol_is_file($realpathtonote)) {
4544 print ' ';
4545 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>';
4546 } else {
4547 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>';
4548 }
4549 print '<br>';
4550 // Page agenda
4551 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>';
4552 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>';
4553 if (dol_is_file($realpathtoagenda)) {
4554 print ' ';
4555 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>';
4556 } else {
4557 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>';
4558 }
4559 print '<br>';
4560 print '<br>';
4561
4562 print '</div>';
4563
4564 print '<br><br><br>';
4565
4566 if (!empty($tmpobject)) {
4567 $reflector = new ReflectionClass($tabobj);
4568 $reflectorproperties = $reflector->getProperties(); // Can also use get_object_vars
4569 $reflectorpropdefault = $reflector->getDefaultProperties(); // Can also use get_object_vars
4570 //$propstat = $reflector->getStaticProperties();
4571 //var_dump($reflectorpropdefault);
4572
4573 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
4574 print '<input type="hidden" name="token" value="'.newToken().'">';
4575 print '<input type="hidden" name="action" value="addproperty">';
4576 print '<input type="hidden" name="tab" value="objects">';
4577 print '<input type="hidden" name="page_y" value="">';
4578 print '<input type="hidden" name="module" value="'.dol_escape_htmltag($module.($forceddirread ? '@'.$dirread : '')).'">';
4579 print '<input type="hidden" name="tabobj" value="'.dol_escape_htmltag($tabobj).'">';
4580
4581 print '<input class="button smallpaddingimp" type="submit" name="regenerateclasssql" value="'.$langs->trans("RegenerateClassAndSql").'">';
4582 print '<br><br class="clearboth">';
4583 print '<br class="clearboth">';
4584
4585 $mod = strtolower($module);
4586 $obj = strtolower($tabobj);
4587 $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));
4588 $nbOfProperties = count($reflectorpropdefault['fields']);
4589
4590 print_barre_liste($langs->trans("ObjectProperties"), 0, $_SERVER["PHP_SELF"], '', '', '', '', 0, $nbOfProperties, '', 0, $newproperty, 'margintoponly', 0, 0, 0, 1);
4591
4592 //var_dump($reflectorpropdefault);exit;
4593 print '<!-- Table with properties of object -->'."\n";
4594 print '<div class="div-table-responsive">';
4595 print '<table class="noborder small">';
4596 print '<tr class="liste_titre">';
4597 if (!empty($conf->main_checkbox_left_column)) {
4598 print '<th class="tdstickyright tdstickyghostwhite"></th>';
4599 }
4600 print '<th class="tdsticky tdstickygray">';
4601 $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>';
4602 print $form->textwithpicto($langs->trans("Code"), $htmltext, 1, 'help', 'extracss', 0, 3, 'propertyhelp');
4603 print '</th>';
4604 print '<th>';
4605 print $form->textwithpicto($langs->trans("Label"), $langs->trans("YouCanUseTranslationKey"));
4606 print '</th>';
4607 print '<th>'.$form->textwithpicto($langs->trans("Type"), $langs->trans("TypeOfFieldsHelpIntro").'<br><br>'.$langs->trans("TypeOfFieldsHelp"), 1, 'help', 'extracss', 0, 3, 'typehelp').'</th>';
4608 print '<th>'.$form->textwithpicto($langs->trans("ArrayOfKeyValues"), $langs->trans("ArrayOfKeyValuesDesc")).'</th>';
4609 print '<th class="center">'.$form->textwithpicto($langs->trans("NotNull"), $langs->trans("NotNullDesc")).'</th>';
4610 print '<th class="center">'.$langs->trans("DefaultValue").'</th>';
4611 print '<th class="center">'.$langs->trans("DatabaseIndex").'</th>';
4612 print '<th class="center">'.$form->textwithpicto($langs->trans("ForeignKey"), $langs->trans("ForeignKeyDesc"), 1, 'help', 'extracss', 0, 3, 'foreignkeyhelp').'</th>';
4613 print '<th class="right">'.$langs->trans("Position").'</th>';
4614 print '<th class="center">'.$form->textwithpicto($langs->trans("Enabled"), $langs->trans("EnabledDesc"), 1, 'help', 'extracss', 0, 3, 'enabledhelp').'</th>';
4615 print '<th class="center">'.$form->textwithpicto($langs->trans("Visibility"), $langs->trans("VisibleDesc").'<br><br>'.$langs->trans("ItCanBeAnExpression"), 1, 'help', 'extracss', 0, 3, 'visiblehelp').'</th>';
4616 print '<th class="center">'.$langs->trans("NotEditable").'</th>';
4617 //print '<th class="center">'.$langs->trans("AlwaysEditable").'</th>';
4618 print '<th class="center">'.$form->textwithpicto($langs->trans("SearchAll"), $langs->trans("SearchAllDesc")).'</th>';
4619 print '<th class="center">'.$form->textwithpicto($langs->trans("IsAMeasure"), $langs->trans("IsAMeasureDesc")).'</th>';
4620 print '<th class="center">'.$langs->trans("CSSClass").'</th>';
4621 print '<th class="center">'.$langs->trans("CSSViewClass").'</th>';
4622 print '<th class="center">'.$langs->trans("CSSListClass").'</th>';
4623 print '<th>'.$langs->trans("KeyForTooltip").'</th>';
4624 print '<th class="center">'.$langs->trans("ShowOnCombobox").'</th>';
4625 //print '<th class="center">'.$langs->trans("Disabled").'</th>';
4626 print '<th>'.$form->textwithpicto($langs->trans("Validate"), $langs->trans("ValidateModBuilderDesc")).'</th>';
4627 print '<th>'.$langs->trans("Comment").'</th>';
4628 if (empty($conf->main_checkbox_left_column)) {
4629 print '<th class="tdstickyright tdstickyghostwhite"></th>';
4630 }
4631 print '</tr>';
4632
4633 // We must use $reflectorpropdefault['fields'] to get list of fields because $tmpobject->fields may have been
4634 // modified during the constructor and we want value into head of class before constructor is called.
4635 //$properties = dol_sort_array($tmpobject->fields, 'position');
4636 $properties = dol_sort_array($reflectorpropdefault['fields'], 'position');
4637 if (!empty($properties)) {
4638 // List of existing properties
4639 foreach ($properties as $propkey => $propval) {
4640 /* If from Reflection
4641 if ($propval->class == $tabobj)
4642 {
4643 $propname=$propval->getName();
4644 $comment=$propval->getDocComment();
4645 $type=gettype($tmpobject->$propname);
4646 $default=$propdefault[$propname];
4647 // Discard generic properties
4648 if (in_array($propname, array('element', 'childtables', 'table_element', 'table_element_line', 'class_element_line', 'ismultientitymanaged'))) continue;
4649
4650 // Keep or not lines
4651 if (in_array($propname, array('fk_element', 'lines'))) continue;
4652 }*/
4653
4654 $propname = $propkey;
4655 $proplabel = $propval['label'];
4656 $proptype = $propval['type'];
4657 $proparrayofkeyval = !empty($propval['arrayofkeyval']) ? $propval['arrayofkeyval'] : '';
4658 $propnotnull = !empty($propval['notnull']) ? $propval['notnull'] : '0';
4659 $propdefault = !empty($propval['default']) ? $propval['default'] : '';
4660 $propindex = !empty($propval['index']) ? $propval['index'] : '';
4661 $propforeignkey = !empty($propval['foreignkey']) ? $propval['foreignkey'] : '';
4662 $propposition = $propval['position'];
4663 $propenabled = $propval['enabled'];
4664 $propvisible = $propval['visible'];
4665 $propnoteditable = !empty($propval['noteditable']) ? $propval['noteditable'] : 0;
4666 //$propalwayseditable = !empty($propval['alwayseditable'])?$propval['alwayseditable']:0;
4667 $propsearchall = !empty($propval['searchall']) ? $propval['searchall'] : 0;
4668 $propisameasure = !empty($propval['isameasure']) ? $propval['isameasure'] : 0;
4669 $propcss = !empty($propval['css']) ? $propval['css'] : '';
4670 $propcssview = !empty($propval['cssview']) ? $propval['cssview'] : '';
4671 $propcsslist = !empty($propval['csslist']) ? $propval['csslist'] : '';
4672 $prophelp = !empty($propval['help']) ? $propval['help'] : '';
4673 $propshowoncombobox = !empty($propval['showoncombobox']) ? $propval['showoncombobox'] : 0;
4674 //$propdisabled=$propval['disabled'];
4675 $propvalidate = !empty($propval['validate']) ? $propval['validate'] : 0;
4676 $propcomment = !empty($propval['comment']) ? $propval['comment'] : '';
4677
4678 print '<!-- line for object property -->'."\n";
4679 print '<tr class="oddeven">';
4680
4681 if (!empty($conf->main_checkbox_left_column)) {
4682 if ($action == 'editproperty' && $propname == $propertykey) {
4683 print '<td class="center minwidth75 tdstickyright tdstickyghostwhite">';
4684 print '<input class="reposition button smallpaddingimp" type="submit" name="edit" value="'.$langs->trans("Save").'">';
4685 print '<input class="reposition button button-cancel smallpaddingimp" type="submit" name="cancel" value="'.$langs->trans("Cancel").'">';
4686 print '</td>';
4687 } else {
4688 print '<td class="center minwidth75 tdstickyright tdstickyghostwhite">';
4689 if ($propname != 'rowid') {
4690 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>';
4691 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>';
4692 }
4693 print '</td>';
4694 }
4695 }
4696 print '<td class="tdsticky tdstickygray">';
4697 print dol_escape_htmltag($propname);
4698 print '</td>';
4699 if ($action == 'editproperty' && $propname == $propertykey) {
4700 print '<td>';
4701 print '<input type="hidden" name="propname" value="'.dol_escape_htmltag($propname).'">';
4702 print '<input name="proplabel" class="maxwidth125" value="'.dol_escape_htmltag($proplabel).'">';
4703 print '</td>';
4704 print '<td class="tdoverflowmax150">';
4705 print '<input name="proptype" id="proptype" class="maxwidth125" value="'.dol_escape_htmltag($proptype).'" list="datalistproptype"></input>';
4706 // Use the samedatalist than for create
4707 print '<datalist id="datalistproptype">';
4708 print '<option>varchar(128)</option>';
4709 print '<option>email</option>';
4710 print '<option>phone</option>';
4711 print '<option>ip</option>';
4712 print '<option>url</option>';
4713 print '<option>password</option>';
4714 print '<option>text</option>';
4715 print '<option>html</option>';
4716 print '<option>date</option>';
4717 print '<option>datetime</option>';
4718 print '<option>integer</option>';
4719 print '<option>stars(5)</option>';
4720 print '<option>double(28,4)</option>';
4721 print '<option>real</option>';
4722 print '<option>integer:ClassName:RelativePath/To/ClassFile.class.php[:1[:FILTER]]</option>';
4723 // Combo with list of fields
4724 /*
4725 if (empty($formadmin)) {
4726 include_once DOL_DOCUMENT_ROOT.'/core/class/html.formadmin.class.php';
4727 $formadmin = new FormAdmin($db);
4728 }
4729 print $formadmin->selectTypeOfFields($key, GETPOST($key, 'alpha'));
4730 */
4731 print '</datalist>';
4732
4733 print '</td>';
4734 print '<td class="tdoverflowmax200">';
4735 print '<textarea name="proparrayofkeyval">';
4736 if (isset($proparrayofkeyval)) {
4737 if (is_array($proparrayofkeyval) || $proparrayofkeyval != '') {
4738 print dol_escape_htmltag(json_encode($proparrayofkeyval, JSON_UNESCAPED_UNICODE));
4739 }
4740 }
4741 print '</textarea>';
4742 print '</td>';
4743 print '<td>';
4744 print '<input class="center width50" name="propnotnull" value="'.dol_escape_htmltag($propnotnull).'">';
4745 print '</td>';
4746 print '<td>';
4747 print '<input class="maxwidth50" name="propdefault" value="'.dol_escape_htmltag($propdefault).'">';
4748 print '</td>';
4749 print '<td class="center">';
4750 print '<input class="center maxwidth50" name="propindex" value="'.dol_escape_htmltag($propindex).'">';
4751 print '</td>';
4752 print '<td>';
4753 print '<input class="center maxwidth100" name="propforeignkey" value="'.dol_escape_htmltag($propforeignkey).'">';
4754 print '</td>';
4755 print '<td>';
4756 print '<input class="right width50" name="propposition" value="'.dol_escape_htmltag($propposition).'">';
4757 print '</td>';
4758 print '<td>';
4759 print '<input class="center width75" name="propenabled" value="'.dol_escape_htmltag($propenabled).'">';
4760 print '</td>';
4761 print '<td>';
4762 print '<input class="center width75" name="propvisible" value="'.dol_escape_htmltag($propvisible).'">';
4763 print '</td>';
4764 print '<td>';
4765 print '<input class="center width50" name="propnoteditable" size="2" value="'.dol_escape_htmltag($propnoteditable).'">';
4766 print '</td>';
4767 /*print '<td>';
4768 print '<input class="center" name="propalwayseditable" size="2" value="'.dol_escape_htmltag($propalwayseditable).'">';
4769 print '</td>';*/
4770 print '<td>';
4771 print '<input class="center width50" name="propsearchall" value="'.dol_escape_htmltag($propsearchall).'">';
4772 print '</td>';
4773 print '<td>';
4774 print '<input class="center width50" name="propisameasure" value="'.dol_escape_htmltag($propisameasure).'">';
4775 print '</td>';
4776 print '<td>';
4777 print '<input class="center maxwidth50" name="propcss" value="'.dol_escape_htmltag($propcss).'">';
4778 print '</td>';
4779 print '<td>';
4780 print '<input class="center maxwidth50" name="propcssview" value="'.dol_escape_htmltag($propcssview).'">';
4781 print '</td>';
4782 print '<td>';
4783 print '<input class="center maxwidth50" name="propcsslist" value="'.dol_escape_htmltag($propcsslist).'">';
4784 print '</td>';
4785 print '<td>';
4786 print '<input class="maxwidth100" name="prophelp" value="'.dol_escape_htmltag($prophelp).'">';
4787 print '</td>';
4788 print '<td>';
4789 print '<input class="center maxwidth50" name="propshowoncombobox" value="'.dol_escape_htmltag($propshowoncombobox).'">';
4790 print '</td>';
4791 print '<td>';
4792 print '<input type="number" step="1" min="0" max="1" class="text maxwidth100" name="propvalidate" value="'.dol_escape_htmltag($propvalidate).'">';
4793 print '</td>';
4794 print '<td>';
4795 print '<input class="maxwidth100" name="propcomment" value="'.dol_escape_htmltag($propcomment).'">';
4796 print '</td>';
4797 if (empty($conf->main_checkbox_left_column)) {
4798 print '<td class="center minwidth75 tdstickyright tdstickyghostwhite">';
4799 print '<input class="reposition button smallpaddingimp" type="submit" name="edit" value="'.$langs->trans("Save").'">';
4800 print '<input class="reposition button button-cancel smallpaddingimp" type="submit" name="cancel" value="'.$langs->trans("Cancel").'">';
4801 print '</td>';
4802 }
4803 } else {
4804 print '<td class="tdoverflowmax200" title="'.dol_escape_htmltag($proplabel).'">';
4805 print dol_escape_htmltag($proplabel);
4806 print '</td>';
4807 print '<td class="tdoverflowmax200">';
4808 $pictoType = '';
4809 $matches = array();
4810 if (preg_match('/^varchar/', $proptype, $matches)) {
4811 $pictoType = 'varchar';
4812 } elseif (preg_match('/^integer:/', $proptype, $matches)) {
4813 $pictoType = 'link';
4814 } elseif (strpos($proptype, 'integer') === 0) {
4815 $pictoType = substr($proptype, 0, 3);
4816 } elseif (strpos($proptype, 'timestamp') === 0) {
4817 $pictoType = 'datetime';
4818 } elseif (strpos($proptype, 'real') === 0) {
4819 $pictoType = 'double';
4820 } elseif (strpos($proptype, 'stars') === 0) {
4821 $pictoType = 'stars';
4822 }
4823 print(!empty($pictoType) ? getPictoForType($pictoType) : getPictoForType($proptype)).'<span title="'.dol_escape_htmltag($proptype).'">'.dol_escape_htmltag($proptype).'</span>';
4824 print '</td>';
4825 print '<td class="tdoverflowmax200">';
4826 if ($proparrayofkeyval) {
4827 print '<span title="'.dol_escape_htmltag(json_encode($proparrayofkeyval, JSON_UNESCAPED_UNICODE)).'">';
4828 print dol_escape_htmltag(json_encode($proparrayofkeyval, JSON_UNESCAPED_UNICODE));
4829 print '</span>';
4830 }
4831 print '</td>';
4832 print '<td class="center">';
4833 print dol_escape_htmltag($propnotnull);
4834 print '</td>';
4835 print '<td>';
4836 print dol_escape_htmltag($propdefault);
4837 print '</td>';
4838 print '<td class="center">';
4839 print $propindex ? '1' : '';
4840 print '</td>';
4841 print '<td class="center">';
4842 print $propforeignkey ? dol_escape_htmltag($propforeignkey) : '';
4843 print '</td>';
4844 print '<td class="right">';
4845 print dol_escape_htmltag($propposition);
4846 print '</td>';
4847 print '<td class="center tdoverflowmax100" title="'.($propnoteditable ? dol_escape_htmltag($propnoteditable) : '').'">';
4848 print $propenabled ? dol_escape_htmltag($propenabled) : '';
4849 print '</td>';
4850 // Visibility
4851 print '<td class="center tdoverflowmax100" title="'.($propvisible ? dol_escape_htmltag($propvisible) : '0').'">';
4852 print $propvisible ? dol_escape_htmltag($propvisible) : '0';
4853 print '</td>';
4854 // Readonly
4855 print '<td class="center tdoverflowmax100" title="'.($propnoteditable ? dol_escape_htmltag($propnoteditable) : '').'">';
4856 print $propnoteditable ? dol_escape_htmltag($propnoteditable) : '';
4857 print '</td>';
4858 /*print '<td class="center">';
4859 print $propalwayseditable ? dol_escape_htmltag($propalwayseditable) : '';
4860 print '</td>';*/
4861 print '<td class="center">';
4862 print $propsearchall ? '1' : '';
4863 print '</td>';
4864 print '<td class="center">';
4865 print $propisameasure ? dol_escape_htmltag($propisameasure) : '';
4866 print '</td>';
4867 print '<td class="center tdoverflowmax100" title="'.($propcss ? dol_escape_htmltag($propcss) : '').'">';
4868 print $propcss ? dol_escape_htmltag($propcss) : '';
4869 print '</td>';
4870 print '<td class="center tdoverflowmax100" title="'.($propcssview ? dol_escape_htmltag($propcssview) : '').'">';
4871 print $propcssview ? dol_escape_htmltag($propcssview) : '';
4872 print '</td>';
4873 print '<td class="center tdoverflowmax100" title="'.($propcsslist ? dol_escape_htmltag($propcsslist) : '').'">';
4874 print $propcsslist ? dol_escape_htmltag($propcsslist) : '';
4875 print '</td>';
4876 // Key for tooltop
4877 print '<td class="tdoverflowmax150" title="'.($prophelp ? dol_escape_htmltag($prophelp) : '').'">';
4878 print $prophelp ? dol_escape_htmltag($prophelp) : '';
4879 print '</td>';
4880 print '<td class="center">';
4881 print $propshowoncombobox ? dol_escape_htmltag($propshowoncombobox) : '';
4882 print '</td>';
4883 /*print '<td class="center">';
4884 print $propdisabled?$propdisabled:'';
4885 print '</td>';*/
4886 print '<td class="center">';
4887 print $propvalidate ? dol_escape_htmltag($propvalidate) : '';
4888 print '</td>';
4889 print '<td class="tdoverflowmax200">';
4890 print '<span title="'.dol_escape_htmltag($propcomment).'">';
4891 print dol_escape_htmltag($propcomment);
4892 print '</span>';
4893 print '</td>';
4894 if (empty($conf->main_checkbox_left_column)) {
4895 print '<td class="center minwidth75 tdstickyright tdstickyghostwhite">';
4896 if ($propname != 'rowid') {
4897 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>';
4898 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>';
4899 }
4900 print '</td>';
4901 }
4902 }
4903 print '</tr>';
4904 }
4905 } else {
4906 if ($tab == 'specifications') {
4907 if ($action != 'editfile' || empty($file)) {
4908 print '<span class="opacitymedium">'.$langs->trans("SpecDefDesc").'</span><br>';
4909 print '<br>';
4910
4911 $specs = dol_dir_list(dol_buildpath($modulelowercase.'/doc', 0), 'files', 1, '(\.md|\.asciidoc)$', array('\/temp\/'));
4912
4913 foreach ($specs as $spec) {
4914 $pathtofile = $modulelowercase.'/doc/'.$spec['relativename'];
4915 $format = 'asciidoc';
4916 if (preg_match('/\.md$/i', $spec['name'])) {
4917 $format = 'markdown';
4918 }
4919 print '<span class="fa fa-file"></span> '.$langs->trans("SpecificationFile").' : <strong class="wordbreak">'.$pathtofile.'</strong>';
4920 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>';
4921 print '<br>';
4922 }
4923 } else {
4924 // Use MD or asciidoc
4925
4926 //print $langs->trans("UseAsciiDocFormat").'<br>';
4927
4928 $fullpathoffile = dol_buildpath($file, 0);
4929
4930 $content = file_get_contents($fullpathoffile);
4931
4932 // New module
4933 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
4934 print '<input type="hidden" name="token" value="'.newToken().'">';
4935 print '<input type="hidden" name="action" value="savefile">';
4936 print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
4937 print '<input type="hidden" name="tab" value="'.$tab.'">';
4938 print '<input type="hidden" name="module" value="'.$module.'">';
4939
4940 $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%');
4941 print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'html'));
4942 print '<br>';
4943 print '<center>';
4944 print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
4945 print ' &nbsp; ';
4946 print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
4947 print '</center>';
4948
4949 print '</form>';
4950 }
4951 }
4952 print '<tr><td><span class="warning">'.$langs->trans('Property %s not found in the class. The class was probably not generated by modulebuilder.', $field).'</warning></td></tr>';
4953 }
4954 print '</table>';
4955 print '</div>';
4956
4957 print '</form>';
4958 } else {
4959 print '<span class="warning">'.$langs->trans('Failed to init the object with the new %s (%s)', $tabobj, (string) $db).'</warning>';
4960 }
4961 } catch (Exception $e) {
4962 print 'ee';
4963 print $e->getMessage();
4964 print 'ff';
4965 }
4966 } else {
4967 if (empty($forceddirread)) {
4968 $fullpathoffile = dol_buildpath($file, 0);
4969 } else {
4970 $fullpathoffile = $dirread.'/'.$file;
4971 }
4972
4973 $content = file_get_contents($fullpathoffile);
4974
4975 // New module
4976 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
4977 print '<input type="hidden" name="token" value="'.newToken().'">';
4978 print '<input type="hidden" name="action" value="savefile">';
4979 print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
4980 print '<input type="hidden" name="tab" value="'.$tab.'">';
4981 print '<input type="hidden" name="tabobj" value="'.dol_escape_htmltag($tabobj).'">';
4982 print '<input type="hidden" name="module" value="'.$module.($forceddirread ? '@'.$dirread : '').'">';
4983
4984 $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%');
4985 print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'html'));
4986 print '<br>';
4987 print '<center>';
4988 print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
4989 print ' &nbsp; ';
4990 print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
4991 print '</center>';
4992
4993 print '</form>';
4994 }
4995 }
4996
4997 print dol_get_fiche_end(); // Level 3
4998 }
4999
5000 if ($tab == 'dictionaries') {
5001 print '<!-- tab=dictionaries -->'."\n";
5002 $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
5003
5004 $dicts = $moduleobj->dictionaries;
5005
5006 if ($action == 'deletedict') {
5007 $formconfirm = $form->formconfirm(
5008 $_SERVER["PHP_SELF"].'?dictionnarykey='.urlencode((string) (GETPOSTINT('dictionnarykey'))).'&tab='.urlencode((string) ($tab)).'&module='.urlencode((string) ($module)),
5009 $langs->trans('Delete'),
5010 $langs->trans('Confirm Delete Dictionnary', GETPOST('dictionnarykey', 'alpha')),
5011 'confirm_deletedictionary',
5012 '',
5013 0,
5014 1
5015 );
5016 print $formconfirm;
5017 }
5018
5019 if ($action != 'editfile' || empty($file)) {
5020 print '<span class="opacitymedium">';
5021 $htmlhelp = $langs->trans("DictionariesDefDescTooltip", '{s1}');
5022 $htmlhelp = str_replace('{s1}', '<a target="adminbis" class="nofocusvisible" href="'.DOL_URL_ROOT.'/admin/dict.php">'.$langs->trans('Setup').' - '.$langs->trans('Dictionaries').'</a>', $htmlhelp);
5023 print $form->textwithpicto($langs->trans("DictionariesDefDesc"), $htmlhelp, 1, 'help', '', 0, 2, 'helpondesc').'<br>';
5024 print '</span>';
5025 print '<br>';
5026
5027 print '<span class="fa fa-file"></span> '.$langs->trans("DescriptorFile").' : <strong class="wordbreak">'.$pathtofile.'</strong>';
5028 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>';
5029 print '<br>';
5030 if (is_array($dicts) && !empty($dicts)) {
5031 print '<span class="fa fa-file"></span> '.$langs->trans("LanguageFile").' :</span> ';
5032 print '<strong class="wordbreak">'.$dicts['langs'].'</strong>';
5033 print '<br>';
5034 }
5035 print '<br>';
5036
5037 $head3 = array();
5038 $h = 0;
5039
5040 // Dir for module
5041 //$dir = $dirread.'/'.$modulelowercase.'/class';
5042
5043 $head3[$h][0] = $_SERVER["PHP_SELF"].'?tab=dictionaries&module='.$module.($forceddirread ? '@'.$dirread : '').'&tabdic=newdictionary';
5044 $head3[$h][1] = '<span class="valignmiddle text-plus-circle">'.$langs->trans("NewDictionary").'</span><span class="fa fa-plus-circle valignmiddle paddingleft"></span>';
5045 $head3[$h][2] = 'newdictionary';
5046 $h++;
5047
5048 // Scan for object class files
5049 //$listofobject = dol_dir_list($dir, 'files', 0, '\.class\.php$');
5050
5051 $firstdicname = '';
5052 // if (!empty($dicts['tabname'])) {
5053 // foreach ($dicts['tabname'] as $key => $dic) {
5054 // $dicname = $dic;
5055 // $diclabel = $dicts['tablib'][$key];
5056
5057 // if (empty($firstdicname)) {
5058 // $firstdicname = $dicname;
5059 // }
5060
5061 // $head3[$h][0] = $_SERVER["PHP_SELF"].'?tab=dictionaries&module='.$module.($forceddirread ? '@'.$dirread : '').'&tabdic='.$dicname;
5062 // $head3[$h][1] = $diclabel;
5063 // $head3[$h][2] = $dicname;
5064 // $h++;
5065 // }
5066 // }
5067
5068 // if ($h > 1) {
5069 // $head3[$h][0] = $_SERVER["PHP_SELF"].'?tab=dictionaries&module='.$module.($forceddirread ? '@'.$dirread : '').'&tabdic=deletedictionary';
5070 // $head3[$h][1] = $langs->trans("DangerZone");
5071 // $head3[$h][2] = 'deletedictionary';
5072 // $h++;
5073 // }
5074
5075 // 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.
5076 // if ($tabdic == 'newdicifnodic') {
5077 // if ($firstdicname) {
5078 // $tabdic = $firstdicname;
5079 // } else {
5080 // $tabdic = 'newdictionary';
5081 // }
5082 // }
5083 //print dol_get_fiche_head($head3, $tabdic, '', -1, ''); // Level 3
5084
5085
5086 $newdict = dolGetButtonTitle($langs->trans('NewDictionary'), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/modulebuilder/index.php?tab=dictionaries&module='.urlencode($module).'&tabdic=newdictionary');
5087 print_barre_liste($langs->trans("ListOfDictionariesEntries"), 0, $_SERVER["PHP_SELF"], '', '', '', '', 0, '', '', 0, $newdict, '', 0, 0, 0, 1);
5088
5089 if ($tabdic != 'newdictionary') {
5090 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
5091 print '<input type="hidden" name="token" value="'.newToken().'">';
5092 print '<input type="hidden" name="action" value="addDictionary">';
5093 print '<input type="hidden" name="tab" value="dictionaries">';
5094 print '<input type="hidden" name="module" value="'.dol_escape_htmltag($module).'">';
5095 print '<input type="hidden" name="tabdic" value="'.dol_escape_htmltag($tabdic).'">';
5096
5097 print '<div class="div-table-responsive">';
5098 print '<table class="noborder">';
5099
5100 print '<tr class="liste_titre">';
5101 print_liste_field_titre("#", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, 'thsticky thstickygrey ');
5102 print_liste_field_titre("Table", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
5103 print_liste_field_titre("Label", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
5104 print_liste_field_titre("SQL", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
5105 print_liste_field_titre("SQLSort", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
5106 print_liste_field_titre("FieldsView", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
5107 print_liste_field_titre("FieldsEdit", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
5108 print_liste_field_titre("FieldsInsert", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
5109 print_liste_field_titre("Rowid", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
5110 print_liste_field_titre("Condition", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
5111 print_liste_field_titre("", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
5112 print "</tr>\n";
5113
5114 if (!empty($dicts) && is_array($dicts) && !empty($dicts['tabname']) && is_array($dicts['tabname'])) {
5115 $i = 0;
5116 $maxi = count($dicts['tabname']);
5117 while ($i < $maxi) {
5118 if ($action == 'editdict' && $i == GETPOSTINT('dictionnarykey') - 1) {
5119 print '<tr class="oddeven">';
5120 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
5121 print '<input type="hidden" name="token" value="'.newToken().'">';
5122 print '<input type="hidden" name="tab" value="dictionaries">';
5123 print '<input type="hidden" name="module" value="'.dol_escape_htmltag($module).'">';
5124 print '<input type="hidden" name="action" value="updatedictionary">';
5125 print '<input type="hidden" name="dictionnarykey" value="'.($i + 1).'">';
5126
5127 print '<td class="tdsticky tdstickygray">';
5128 print($i + 1);
5129 print '</td>';
5130
5131 print '<td>';
5132 print '<input type="text" name="tabname" value="'.$dicts['tabname'][$i].'" readonly class="tdstickygray">';
5133 print '</td>';
5134
5135 print '<td>';
5136 print '<input type="text" name="tablib" value="'.$dicts['tablib'][$i].'">';
5137 print '</td>';
5138
5139 print '<td>';
5140 print '<input type="text" name="tabsql" value="'.$dicts['tabsql'][$i].'" readonly class="tdstickygray">';
5141 print '</td>';
5142
5143 print '<td>';
5144 print '<select name="tabsqlsort">';
5145 print '<option value="'.dol_escape_htmltag($dicts['tabsqlsort'][$i]).'">'.$dicts['tabsqlsort'][$i].'</option>';
5146 print '</select>';
5147 print '</td>';
5148
5149 print '<td><select name="tabfield" >';
5150 print '<option value="'.dol_escape_htmltag($dicts['tabfield'][$i]).'">'.$dicts['tabfield'][$i].'</option>';
5151 print '</select></td>';
5152
5153 print '<td><select name="tabfieldvalue" >';
5154 print '<option value="'.dol_escape_htmltag($dicts['tabfieldvalue'][$i]).'">'.$dicts['tabfieldvalue'][$i].'</option>';
5155 print '</select></td>';
5156
5157 print '<td><select name="tabfieldinsert" >';
5158 print '<option value="'.dol_escape_htmltag($dicts['tabfieldinsert'][$i]).'">'.$dicts['tabfieldinsert'][$i].'</option>';
5159 print '</select></td>';
5160
5161 print '<td>';
5162 print '<input type="text" name="tabrowid" value="'.dol_escape_htmltag($dicts['tabrowid'][$i]).'" readonly class="tdstickygray">';
5163 print '</td>';
5164
5165 print '<td>';
5166 print '<input type="text" name="tabcond" value="'.dol_escape_htmltag((empty($dicts['tabcond'][$i]) ? 'disabled' : 'enabled')).'" readonly class="tdstickygray">';
5167 print '</td>';
5168
5169 print '<td class="center minwidth75 tdstickyright tdstickyghostwhite">';
5170 print '<input id ="updatedict" class="reposition button smallpaddingimp" type="submit" name="updatedict" value="'.$langs->trans("Modify").'"/>';
5171 print '<br>';
5172 print '<input class="reposition button button-cancel smallpaddingimp" type="submit" name="cancel" value="'.$langs->trans("Cancel").'"/>';
5173 print '</td>';
5174
5175 print '</form>';
5176 print '</tr>';
5177 } else {
5178 print '<tr class="oddeven">';
5179
5180 print '<td class="tdsticky tdstickygray">';
5181 print($i + 1);
5182 print '</td>';
5183
5184 print '<td>';
5185 print $dicts['tabname'][$i];
5186 print '</td>';
5187
5188 print '<td>';
5189 print $dicts['tablib'][$i];
5190 print '</td>';
5191
5192 print '<td>';
5193 print $dicts['tabsql'][$i];
5194 print '</td>';
5195
5196 print '<td>';
5197 print $dicts['tabsqlsort'][$i];
5198 print '</td>';
5199
5200 print '<td>';
5201 print $dicts['tabfield'][$i];
5202 print '</td>';
5203
5204 print '<td>';
5205 print $dicts['tabfieldvalue'][$i];
5206 print '</td>';
5207
5208 print '<td>';
5209 print $dicts['tabfieldinsert'][$i];
5210 print '</td>';
5211
5212 print '<td >';
5213 print $dicts['tabrowid'][$i];
5214 print '</td>';
5215
5216 print '<td >';
5217 print $dicts['tabcond'][$i];
5218 print '</td>';
5219
5220 print '<td class="center minwidth75 tdstickyright tdstickyghostwhite">';
5221 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>';
5222 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>';
5223 print '</td>';
5224
5225 print '</tr>';
5226 }
5227 $i++;
5228 }
5229 } else {
5230 print '<tr><td colspan="11"><span class="opacitymedium">'.$langs->trans("None").'</span></td></tr>';
5231 }
5232
5233 print '</table>';
5234 print '</div>';
5235
5236 print '</form>';
5237 }
5238
5239 if ($tabdic == 'newdictionary') {
5240 // New dic tab
5241 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
5242 print '<input type="hidden" name="token" value="'.newToken().'">';
5243 print '<input type="hidden" name="action" value="initdic">';
5244 print '<input type="hidden" name="tab" value="dictionaries">';
5245 print '<input type="hidden" name="tabdic" value="'.$tabdic.'">';
5246
5247 print '<input type="hidden" name="module" value="'.dol_escape_htmltag($module).'">';
5248
5249 print '<span class="opacitymedium">'.$langs->trans("EnterNameOfDictionaryDesc").'</span><br><br>';
5250
5251 print dol_get_fiche_head();
5252 print '<table class="border centpercent">';
5253 print '<tbody>';
5254 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>';
5255 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>';
5256 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>';
5257 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>';
5258 print '<tr><td class="titlefieldcreate">'.$langs->trans("FieldsView").'</td><td><input type="text" name="field" value="'.dol_escape_htmltag(GETPOST('field', 'alpha')).'"></td></tr>';
5259 print '<tr><td class="titlefieldcreate">'.$langs->trans("FieldsEdit").'</td><td><input type="text" name="fieldvalue" value="'.dol_escape_htmltag(GETPOST('fieldvalue', 'alpha')).'"></td></tr>';
5260 print '<tr><td class="titlefieldcreate">'.$langs->trans("FieldsInsert").'</td><td><input type="text" name="fieldinsert" value="'.dol_escape_htmltag(GETPOST('fieldinsert', 'alpha')).'"></td></tr>';
5261 print '<tr><td class="titlefieldcreate">'.$langs->trans("Rowid").'</td><td><input type="text" name="rowid" value="'.dol_escape_htmltag(GETPOST('rowid', 'alpha')).'"></td></tr>';
5262 print '<tr></tr>';
5263 print '</tbody></table>';
5264 print '<input type="submit" class="button" name="create" value="'.dol_escape_htmltag($langs->trans("GenerateCode")).'"'.($dirins ? '' : ' disabled="disabled"').'>';
5265 print '<input id="cancel" type="submit" class="button" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
5266 print dol_get_fiche_end();
5267 print '</form>';
5268 print '<script>
5269 $(document).ready(function() {
5270 $("input[name=\'dicname\']").on("blur", function() {
5271 if ($(this).val().length > 0) {
5272 $("input[name=\'label\']").val($(this).val());
5273 $("input[name=\'sql\']").val("SELECT f.rowid as rowid, f.code, f.label, f.active FROM llx_c_" + $(this).val() + " as f");
5274 $("input[name=\'sqlsort\']").val("label ASC");
5275 $("input[name=\'field\']").val("code,label");
5276 $("input[name=\'fieldvalue\']").val("code,label");
5277 $("input[name=\'fieldinsert\']").val("code,label");
5278 $("input[name=\'rowid\']").val("rowid");
5279 } else {
5280 $("input[name=\'label\']").val("");
5281 $("input[name=\'sql\']").val("");
5282 $("input[name=\'sqlsort\']").val("");
5283 $("input[name=\'field\']").val("");
5284 $("input[name=\'fieldvalue\']").val("");
5285 $("input[name=\'fieldinsert\']").val("");
5286 $("input[name=\'rowid\']").val("");
5287 }
5288 });
5289 $("input[id=\'cancel\']").click(function() {
5290 window.history.back();
5291 });
5292 });
5293 </script>';
5294
5295 /*print '<br>';
5296 print '<br>';
5297 print '<br>';
5298 print '<span class="opacitymedium">'.$langs->trans("or").'</span>';
5299 print '<br>';
5300 print '<br>';
5301 //print '<input type="checkbox" name="initfromtablecheck"> ';
5302 print $langs->trans("InitStructureFromExistingTable");
5303 print '<input type="text" name="initfromtablename" value="" placeholder="'.$langs->trans("TableName").'">';
5304 print '<input type="submit" class="button smallpaddingimp" name="createtablearray" value="'.dol_escape_htmltag($langs->trans("GenerateCode")).'"'.($dirins ? '' : ' disabled="disabled"').'>';
5305 print '<br>';
5306 */
5307 } elseif ($tabdic == 'deletedictionary') {
5308 // Delete dic tab
5309 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
5310 print '<input type="hidden" name="token" value="'.newToken().'">';
5311 print '<input type="hidden" name="action" value="confirm_deletedictionary">';
5312 print '<input type="hidden" name="tab" value="dictionaries">';
5313 print '<input type="hidden" name="module" value="'.dol_escape_htmltag($module).'">';
5314
5315 print $langs->trans("EnterNameOfDictionnaryToDeleteDesc").'<br><br>';
5316
5317 print '<input type="text" name="dicname" value="'.dol_escape_htmltag($modulename).'" placeholder="'.dol_escape_htmltag($langs->trans("DicKey")).'">';
5318 print '<input type="submit" class="button smallpaddingimp" name="delete" value="'.dol_escape_htmltag($langs->trans("Delete")).'"'.($dirins ? '' : ' disabled="disabled"').'>';
5319 print '</form>';
5320 }
5321
5322 print dol_get_fiche_end();
5323 } else {
5324 $fullpathoffile = dol_buildpath($file, 0);
5325
5326 $content = file_get_contents($fullpathoffile);
5327
5328 // New module
5329 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
5330 print '<input type="hidden" name="token" value="'.newToken().'">';
5331 print '<input type="hidden" name="action" value="savefile">';
5332 print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
5333 print '<input type="hidden" name="tab" value="'.$tab.'">';
5334 print '<input type="hidden" name="module" value="'.$module.'">';
5335
5336 $posCursor = (empty($find)) ? array() : array('find' => $find);
5337 $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%', 0, $posCursor);
5338 print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'html'));
5339 print '<br>';
5340 print '<center>';
5341 print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
5342 print ' &nbsp; ';
5343 print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
5344 print '</center>';
5345
5346 print '</form>';
5347 }
5348 }
5349
5350 if ($tab == 'menus') {
5351 print '<!-- tab=menus -->'."\n";
5352 $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
5353 $dirins = $listofmodules[strtolower($module)]['moduledescriptorrootpath'];
5354 $destdir = $dirins.'/'.strtolower($module);
5355 $listofobject = dol_dir_list($destdir.'/class', 'files', 0, '\.class\.php$');
5356 $objects = dolGetListOfObjectClasses($destdir);
5357
5358 $leftmenus = array();
5359
5360 $menus = $moduleobj->menu;
5361
5362 $permissions = $moduleobj->rights;
5363 $crud = array('read' => 'CRUDRead', 'write' => 'CRUDCreateWrite', 'delete' => 'Delete');
5364
5365 //grouped permissions
5366 $groupedRights = array();
5367 foreach ($permissions as $right) {
5368 $key = $right[4];
5369 if (!isset($groupedRights[$key])) {
5370 $groupedRights[$key] = array();
5371 }
5372 $groupedRights[$key][] = $right;
5373 }
5374 $groupedRights_json = json_encode($groupedRights);
5375
5376 if ($action == 'deletemenu') {
5377 $formconfirms = $form->formconfirm(
5378 $_SERVER["PHP_SELF"].'?menukey='.urlencode((string) (GETPOSTINT('menukey'))).'&tab='.urlencode((string) ($tab)).'&module='.urlencode((string) ($module)),
5379 $langs->trans('Delete'),
5380 ($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'))),
5381 'confirm_deletemenu',
5382 '',
5383 0,
5384 1
5385 );
5386 print $formconfirms;
5387 }
5388 if ($action != 'editfile' || empty($file)) {
5389 print '<span class="opacitymedium">';
5390 $htmlhelp = $langs->trans("MenusDefDescTooltip", '{s1}');
5391 $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);
5392 print $form->textwithpicto($langs->trans("MenusDefDesc"), $htmlhelp, 1, 'help', '', 0, 2, 'helpondesc').'<br>';
5393 print '</span>';
5394 print '<br>';
5395
5396 // Links to editable files
5397 print '<span class="fa fa-file"></span> '.$langs->trans("DescriptorFile").' : <strong class="wordbreak">'.$pathtofile.'</strong>';
5398 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>';
5399 print '<br>';
5400
5401 // Search all files of modules mentioned by menu
5402 $listODifferentUrlsInMenu = array();
5403 foreach ($menus as $obj) {
5404 if (preg_match('/^\/'.preg_quote(strtolower($module), '/').'\//', $obj['url']) && !empty($pathoffile)) {
5405 if (!empty($listODifferentUrlsInMenu[$pathoffile])) { // Test to avoid to show same file twice.
5406 continue;
5407 }
5408 $pathtofile = $obj['url'];
5409 $listODifferentUrlsInMenu[$pathoffile] = $pathtofile;
5410 print '<span class="fa fa-file"></span> '.$langs->trans("PageLinkedByAMenuEntry").' : <strong class="wordbreak">'.$pathtofile.'</strong>';
5411 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>';
5412 print '<br>';
5413 }
5414 }
5415
5416
5417 print '<br>';
5418 print load_fiche_titre($langs->trans("ListOfMenusEntries"), '', '');
5419
5420 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
5421 print '<input type="hidden" name="token" value="'.newToken().'">';
5422 print '<input type="hidden" name="action" value="addmenu">';
5423 print '<input type="hidden" name="tab" value="menus">';
5424 print '<input type="hidden" name="module" value="'.dol_escape_htmltag($module).'">';
5425 print '<input type="hidden" name="tabobj" value="'.dol_escape_htmltag($tabobj).'">';
5426
5427 print '<div class="div-table-responsive">';
5428 print '<table class="noborder small">';
5429
5430 $htmltextenabled = '<u>'.$langs->trans("Examples").':</u><br>';
5431 $htmltextenabled .= '1 <span class="opacitymedium">(module always enabled)</span><br>';
5432 $htmltextenabled .= '0 <span class="opacitymedium">(module always disabled)</span><br>';
5433 $htmltextenabled .= 'isModEnabled(\''.dol_escape_htmltag(strtolower($module)).'\') <span class="opacitymedium">(enabled when module is enabled)</span>';
5434 $htmltextperms = '<u>'.$langs->trans("Examples").':</u><br>';
5435 $htmltextperms .= '1 <span class="opacitymedium">(access always allowed)</span><br>';
5436 $htmltextperms .= '$user->hasright(\''.dol_escape_htmltag(strtolower($module)).'\', \'myobject\', \'read\') <span class="opacitymedium">(access allowed if user has permission module->object->read)</span>';
5437
5438 print '<tr class="liste_titre">';
5439 print_liste_field_titre("#", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, 'center tdsticky tdstickygray ');
5440 print_liste_field_titre("Position", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
5441 print_liste_field_titre("Title", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, 'center');
5442 print_liste_field_titre("LinkToParentMenu", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, 'minwidth100 ');
5443 print_liste_field_titre("mainmenu", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
5444 print_liste_field_titre("leftmenu", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
5445 print_liste_field_titre("URL", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, '', $langs->transnoentitiesnoconv('DetailUrl'));
5446 print_liste_field_titre("LanguageFile", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
5447 print_liste_field_titre("Position", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, 'right ');
5448 print_liste_field_titre("Enabled", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, 'center ', $langs->trans('DetailEnabled').'<br><br>'.$htmltextenabled);
5449 print_liste_field_titre("Rights", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, '', $langs->trans('DetailRight').'<br><br>'.$htmltextperms);
5450 print_liste_field_titre("Target", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, '', $langs->trans('DetailTarget'));
5451 print_liste_field_titre("MenuForUsers", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, 'center minwidth100 ', $langs->trans('DetailUser'));
5452 print_liste_field_titre("", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, 'center ', $langs->trans(''));
5453 print "</tr>\n";
5454
5455 $r = count($menus) + 1;
5456 // for adding menu on module
5457 print '<tr>';
5458 print '<td class="center tdsticky tdstickygray"><input type="hidden" readonly class="center maxwidth50" name="propenabled" value="#"></td>';
5459 print '<td class="center">';
5460 print '<select class="maxwidth50" name="type">';
5461 print '<option value="">'.$langs->trans("........").'</option><option value="'.dol_escape_htmltag("left").'">left</option><option value="'.dol_escape_htmltag("top").'">top</option>';
5462 print '</select></td>';
5463 print '<td class="left"><input type="text" class="left maxwidth100" name="titre" value="'.dol_escape_htmltag(GETPOST('titre', 'alpha')).'"></td>';
5464 print '<td class="left">';
5465 print '<select name="fk_menu">';
5466 print '<option value="">'.$langs->trans("........").'</option>';
5467 foreach ($menus as $obj) {
5468 if ($obj['type'] == 'left' && !empty($obj['leftmenu'])) {
5469 print "<option value=".strtolower($obj['leftmenu']).">".$obj['leftmenu']."</option>";
5470 }
5471 }
5472 print '</select>';
5473 print '</td>';
5474 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>';
5475 print '<td class="center"><input id="leftmenu" type="text" class="left maxwidth50" name="leftmenu" value="'.dol_escape_htmltag(GETPOST('leftmenu', 'alpha')).'"></td>';
5476 // URL
5477 print '<td class="left"><input id="url" type="text" class="left maxwidth100" name="url" value="'.dol_escape_htmltag(GETPOST('url', 'alpha')).'"></td>';
5478 print '<td class="left"><input type="text" class="left maxwidth75" name="langs" value="'.strtolower($module).'@'.strtolower($module).'" readonly></td>';
5479 // Position
5480 print '<td class="center"><input type="text" class="center maxwidth50 tdstickygray" name="position" value="'.(1000 + $r).'" readonly></td>';
5481 // Enabled
5482 print '<td class="center">';
5483 print '<input type="enabled" class="maxwidth125" value="'.dol_escape_htmltag(GETPOSTISSET('enabled') ? GETPOST('enabled') : 'isModEnabled(\''.$module.'\')').'">';
5484 /*
5485 print '<select class="maxwidth" name="enabled">';
5486 print '<option value="1" selected>'.$langs->trans("Show").'</option>';
5487 print '<option value="0">'.$langs->trans("Hide").'</option>';
5488 print '</select>';
5489 */
5490 print '</td>';
5491 // Perms
5492 print '<td class="left">';
5493 print '<select class="maxwidth" name="objects" id="objects">';
5494 print '<option value=""></option>';
5495 if (is_array($objects)) {
5496 foreach ($objects as $value) {
5497 print '<option value="'.strtolower($value).'">'.dol_escape_htmltag(strtolower($value)).'</option>';
5498 }
5499 }
5500 print '</select>';
5501 print '<select class="maxwidth hideobject" name="perms" id="perms">';
5502 print '</select>';
5503 print '</td>';
5504 print '<td class="center"><input type="text" class="center maxwidth50" name="target" value="'.dol_escape_htmltag(GETPOST('target', 'alpha')).'"></td>';
5505 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>';
5506
5507 print '<td class="center minwidth75 tdstickyright tdstickyghostwhite">';
5508 print '<input type="submit" class="button" name="add" value="'.$langs->trans("Add").'">';
5509 print '</td>';
5510 print '</tr>';
5511 // end form for add menu
5512
5513 //var_dump($menus);
5514
5515 // Loop on each menu entry
5516 if (count($menus)) {
5517 $i = 0;
5518 foreach ($menus as $menu) {
5519 $i++;
5520 //for get parent in menu
5521 $string = dol_escape_htmltag($menu['fk_menu']);
5522 $value = substr($string, strpos($string, 'fk_leftmenu=') + strlen('fk_leftmenu='));
5523
5524 $propFk_menu = !empty($menu['fk_menu']) ? $menu['fk_menu'] : GETPOST('fk_menu');
5525 $propTitre = !empty($menu['titre']) ? $menu['titre'] : GETPOST('titre');
5526 $propMainmenu = !empty($menu['mainmenu']) ? $menu['mainmenu'] : GETPOST('mainmenu');
5527 $propLeftmenu = !empty($menu['leftmenu']) ? $menu['leftmenu'] : GETPOST('leftmenu');
5528 $propUrl = !empty($menu['url']) ? $menu['url'] : GETPOST('url', 'alpha');
5529 $propPerms = !empty($menu['perms']) ? $menu['perms'] : GETPOST('perms');
5530 $propUser = !empty($menu['user']) ? $menu['user'] : GETPOST('user');
5531 $propTarget = !empty($menu['target']) ? $menu['target'] : GETPOST('target');
5532 $propEnabled = !empty($menu['enabled']) ? $menu['enabled'] : GETPOST('enabled');
5533
5534 $objPerms = (empty($arguments[1]) ? '' : trim($arguments[1]));
5535 $valPerms = (empty($arguments[2]) ? '' : trim($arguments[2]));
5536
5537 //$tabobject = ''; // We can't know what is $tabobject in most cases
5538
5539 if ($action == 'editmenu' && GETPOSTINT('menukey') == $i) {
5540 //var_dump($propPerms);exit;
5541 print '<tr class="oddeven">';
5542 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
5543 print '<input type="hidden" name="token" value="'.newToken().'">';
5544 print '<input type="hidden" name="action" value="update_menu">';
5545 print '<input type="hidden" name="tab" value="menus">';
5546 print '<input type="hidden" name="module" value="'.dol_escape_htmltag($module).'">';
5547 print '<input type="hidden" name="menukey" value="'.$i.'"/>';
5548 //print '<input type="hidden" name="tabobject" value="'.dol_escape_htmltag($tabobject).'">';
5549 print '<td class="tdsticky tdstickygray">';
5550 print $i;
5551 print '</td>';
5552 // Position (top, left)
5553 print '<td class="center">
5554 <select class="center maxwidth50" name="type">
5555 <option value="'.dol_escape_htmltag($menu['type']).'">
5556 '.dol_escape_htmltag($menu['type']).'
5557 </option>';
5558 print '<option value="'.($menu['type'] == 'left' ? 'top' : 'left').'">';
5559 if ($menu['type'] == 'left') {
5560 print 'top';
5561 } else {
5562 print 'left';
5563 }
5564 print '</option></select></td>';
5565 // Title
5566 print '<td><input type="text" class="left maxwidth100" name="titre" value="'.dol_escape_htmltag($propTitre).'"></td>';
5567 // Parent menu
5568 print '<td>';
5569 /*print '<select name="fk_menu" class="left maxwidth">';
5570 print '<option value="'.dol_escape_htmltag($propFk_menu).'">'.dol_escape_htmltag($value).'</option>';
5571 foreach ($menus as $obj) {
5572 if ($obj['type'] == 'left' && $obj['leftmenu'] != $value && $obj['leftmenu'] != $menu['leftmenu']) {
5573 print "<option value=".strtolower($obj['leftmenu']).">".$obj['leftmenu']."</option>";
5574 }
5575 }
5576 print '</select>';*/
5577 print '<input type="text" name="fk_menu" class="maxwidth150" value="'.dol_escape_htmltag($propFk_menu).'">';
5578 print '</td>';
5579 print '<td><input type="text" class="left maxwidth50" name="mainmenu" value="'.dol_escape_htmltag($propMainmenu).'" readonly></td>';
5580 print '<td><input type="text" class="left maxwidth50" name="leftmenu" value="'.dol_escape_htmltag($propLeftmenu).'" readonly></td>';
5581 // URL
5582 print '<td><input type="text" class="left maxwidth250" name="url" value="'.dol_escape_htmltag($propUrl).'"></td>';
5583 print '<td><input type="text" class="left maxwidth50" name="langs" value="'.strtolower($module).'@'.strtolower($module).'" readonly></td>';
5584 // Position
5585 print '<td class="center"><input type="text" class="center maxwidth50 tdstickygray" name="position" value="'.($menu['position']).'" readonly></td>';
5586 // Enabled
5587 print '<td class="nowraponall">';
5588 print '<input type="text" class="maxwidth125" name="enabled" value="'.dol_escape_htmltag($propEnabled != '' ? $propEnabled : "isModEnabled('".dol_escape_htmltag($module)."')").'">';
5589 $htmltext = '<u>'.$langs->trans("Examples").':</u><br>';
5590 $htmltext .= '1 <span class="opacitymedium">(always enabled)</span><br>';
5591 $htmltext .= '0 <span class="opacitymedium">(always disabled)</span><br>';
5592 $htmltext .= 'isModEnabled(\''.dol_escape_htmltag($module).'\') <span class="opacitymedium">(enabled when module is enabled)</span><br>';
5593 print $form->textwithpicto('', $htmltext);
5594 /*
5595 print '<select class="maxwidth50" name="enabledselect">';
5596 print '<option value="1">1 (always enabled)</option>';
5597 print '<option value="0">0 (always disabled)</option>';
5598 print '<option value="isModEnabled(\''.dol_escape_htmltag($module).'\')" >isModEnabled(\''.dol_escape_htmltag($module).'\')</option>';
5599 print '</select>';
5600 */
5601 print '</td>';
5602 // Permissions
5603 print '<td class="nowraponall">';
5604 print '<input type="text" name="perms" value="'.dol_escape_htmltag($propPerms).'">';
5605 /*
5606 if (!empty($objPerms)) {
5607 print '<input type="hidden" name="objects" value="'.$objPerms.'" />';
5608 print '<select class="center maxwidth50" name="perms">';
5609 if (!empty($valPerms)) {
5610 print '<option selected value="'.dol_escape_htmltag($valPerms).'">'.dol_escape_htmltag($langs->trans($crud[$valPerms])).'</option>';
5611 foreach ($crud as $key => $val) {
5612 if ($valPerms != $key) {
5613 print '<option value="'.dol_escape_htmltag($key).'">'.dol_escape_htmltag($langs->trans($val)).'</option>';
5614 }
5615 }
5616 }
5617 print '</select>';
5618 } else {
5619 print '<select class="center maxwidth50" name="objects">';
5620 print '<option></option>';
5621 foreach ($objects as $obj) {
5622 print '<option value="'.dol_escape_htmltag(strtolower($obj)).'">'.dol_escape_htmltag($obj).'</option>';
5623 }
5624 print '</select>';
5625 print '<select class="center maxwidth50" name="perms">';
5626 foreach ($crud as $key => $val) {
5627 print '<option value="'.dol_escape_htmltag($key).'">'.dol_escape_htmltag($key).'</option>';
5628 }
5629 print '</select>';
5630 }*/
5631 print '</td>';
5632 // Target
5633 print '<td class="center"><input type="text" class="center maxwidth50" name="target" value="'.dol_escape_htmltag($propTarget).'"></td>';
5634 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>';
5635 print '<td class="center minwidth75 tdstickyright tdstickyghostwhite maxwidth75">';
5636 print '<input class="reposition button smallpaddingimp" type="submit" name="edit" value="'.$langs->trans("Modify").'">';
5637 print '<input class="reposition button button-cancel smallpaddingimp" type="submit" name="cancel" value="'.$langs->trans("Cancel").'">';
5638 print '</td>';
5639 print '</form>';
5640 print '</tr>';
5641 } else {
5642 print '<tr class="oddeven">';
5643
5644 print '<td class="tdsticky tdstickygray">';
5645 print $i;
5646 print '</td>';
5647
5648 print '<td class="center">';
5649 print dol_escape_htmltag($menu['type']);
5650 print '</td>';
5651
5652 // Title
5653 print '<td>';
5654 print dol_escape_htmltag($menu['titre']);
5655 print '</td>';
5656
5657 // Parent menu
5658 print '<td class="tdoverflowmax100" title="'.dol_escape_htmltag($menu['fk_menu']).'">';
5659 print dol_escape_htmltag($menu['fk_menu']);
5660 print '</td>';
5661
5662 print '<td>';
5663 print dol_escape_htmltag($menu['mainmenu']);
5664 print '</td>';
5665
5666 print '<td>';
5667 print dol_escape_htmltag($menu['leftmenu']);
5668 print '</td>';
5669
5670 print '<td class="tdoverflowmax250" title="'.dol_escape_htmltag($menu['url']).'">';
5671 print dol_escape_htmltag($menu['url']);
5672 print '</td>';
5673
5674 print '<td>';
5675 print dol_escape_htmltag($menu['langs']);
5676 print '</td>';
5677
5678 // Position
5679 print '<td class="center">';
5680 print dol_escape_htmltag((string) $menu['position']);
5681 print '</td>';
5682
5683 // Enabled
5684 print '<td class="tdoverflowmax200" title="'.dol_escape_htmltag($menu['enabled']).'">';
5685 print dol_escape_htmltag($menu['enabled']);
5686 print '</td>';
5687
5688 // Perms
5689 print '<td class="tdoverflowmax200" title="'.dol_escape_htmltag($menu['perms']).'">';
5690 print dol_escape_htmltag($langs->trans($menu['perms']));
5691 print '</td>';
5692
5693 // Target
5694 print '<td class="center tdoverflowmax200" title="'.dol_escape_htmltag($menu['target']).'">';
5695 print dol_escape_htmltag($menu['target']);
5696 print '</td>';
5697
5698 print '<td class="center">';
5699 if ($menu['user'] == 2) {
5700 print $langs->trans("AllMenus");
5701 } elseif ($menu['user'] == 0) {
5702 print $langs->trans('Internal');
5703 } elseif ($menu['user'] == 1) {
5704 print $langs->trans('External');
5705 } else {
5706 print $menu['user']; // should not happen
5707 }
5708 print '</td>';
5709 print '<td class="center minwidth75 tdstickyright tdstickyghostwhite">';
5710 if ($menu['titre'] != 'Module'.$module.'Name') {
5711 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>';
5712 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>';
5713 }
5714 print '</td>';
5715 }
5716 print '</tr>';
5717 }
5718 } else {
5719 print '<tr><td colspan="14"><span class="opacitymedium">'.$langs->trans("None").'</span></td></tr>';
5720 }
5721
5722 print '</table>';
5723 print '</div>';
5724 print '</form>';
5725
5726
5727 print '<script>
5728 $(document).ready(function() {
5729 //for fill in auto url
5730 $("#leftmenu").on("input", function() {
5731 var inputLeftMenu = $("#leftmenu").val();
5732 if (inputLeftMenu !== \'\') {
5733 var url = \''.dol_escape_js(strtolower($module)).'\' + inputLeftMenu + \'.php\';
5734 $("#url").val(url);
5735 }else {
5736 $("#url").val("");
5737 }
5738 });
5739
5740 var groupedRights = ' . $groupedRights_json . ';
5741 var objectsSelect = $("select[id=\'objects\']");
5742 var permsSelect = $("select[id=\'perms\']");
5743
5744 objectsSelect.change(function() {
5745 var selectedObject = $(this).val();
5746
5747 permsSelect.empty();
5748
5749 var rights = groupedRights[selectedObject];
5750
5751 if (rights) {
5752 for (var i = 0; i < rights.length; i++) {
5753 var right = rights[i];
5754 var option = $("<option></option>").attr("value", right[5]).text(right[5]);
5755 permsSelect.append(option);
5756 }
5757 } else {
5758 var option = $("<option></option>").attr("value", "read").text("read");
5759 permsSelect.append(option);
5760 }
5761
5762 if (selectedObject !== "" && selectedObject !== null && rights) {
5763 permsSelect.show();
5764 } else {
5765 permsSelect.hide();
5766 }
5767 if (objectsSelect.val() === "" || objectsSelect.val() === null) {
5768 permsSelect.hide();
5769 }
5770 });
5771 });
5772 </script>';
5773
5774 // display permissions for each object
5775 } else {
5776 $fullpathoffile = dol_buildpath($file, 0);
5777
5778 $content = file_get_contents($fullpathoffile);
5779
5780 // New module
5781 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
5782 print '<input type="hidden" name="token" value="'.newToken().'">';
5783 print '<input type="hidden" name="action" value="savefile">';
5784 print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
5785 print '<input type="hidden" name="tab" value="'.$tab.'">';
5786 print '<input type="hidden" name="module" value="'.$module.'">';
5787
5788 $posCursor = (empty($find)) ? array() : array('find' => $find);
5789 $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%', 0, $posCursor);
5790 print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'html'));
5791 print '<br>';
5792 print '<center>';
5793 print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
5794 print ' &nbsp; ';
5795 print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
5796 print '</center>';
5797
5798 print '</form>';
5799 }
5800 }
5801
5802 if ($tab == 'permissions') {
5803 print '<!-- tab=permissions -->'."\n";
5804 $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
5805
5806 $perms = $moduleobj->rights;
5807
5808 // Get list of existing objects
5809 $dir = $dirread.'/'.$modulelowercase.'/class';
5810 $listofobject = dol_dir_list($dir, 'files', 0, '\.class\.php$');
5811 $objects = array('myobject');
5812 $reg = array();
5813 foreach ($listofobject as $fileobj) {
5814 $tmpcontent = file_get_contents($fileobj['fullname']);
5815 if (preg_match('/class\s+([^\s]*)\s+extends\s+CommonObject/ims', $tmpcontent, $reg)) {
5816 $objects[$fileobj['fullname']] = $reg[1];
5817 }
5818 }
5819
5820 // declared select list for actions and labels permissions
5821 $crud = array('read' => 'CRUDRead', 'write' => 'CRUDCreateWrite', 'delete' => 'Delete');
5822 $labels = array("Read objects of ".$module, "Create/Update objects of ".$module, "Delete objects of ".$module);
5823
5824 $action = GETPOST('action', 'alpha');
5825
5826 if ($action == 'deleteright') {
5827 $formconfirm = $form->formconfirm(
5828 $_SERVER["PHP_SELF"].'?permskey='.urlencode((string) (GETPOSTINT('permskey'))).'&tab='.urlencode((string) ($tab)).'&module='.urlencode((string) ($module)).'&tabobj='.urlencode((string) ($tabobj)),
5829 $langs->trans('Delete'),
5830 $langs->trans('Confirm Delete Right', GETPOST('permskey', 'alpha')),
5831 'confirm_deleteright',
5832 '',
5833 0,
5834 1
5835 );
5836 print $formconfirm;
5837 }
5838
5839 if ($action != 'editfile' || empty($file)) {
5840 print '<!-- Tab to manage permissions -->'."\n";
5841 print '<span class="opacitymedium">';
5842 $htmlhelp = $langs->trans("PermissionsDefDescTooltip", '{s1}');
5843 $htmlhelp = str_replace('{s1}', '<a target="adminbis" class="nofocusvisible" href="'.DOL_URL_ROOT.'/admin/perms.php">'.$langs->trans('DefaultRights').'</a>', $htmlhelp);
5844 print $form->textwithpicto($langs->trans("PermissionsDefDesc"), $htmlhelp, 1, 'help', '', 0, 2, 'helpondesc').'<br>';
5845 print '</span>';
5846 print '<br>';
5847
5848 print '<span class="fa fa-file"></span> '.$langs->trans("DescriptorFile").' : <strong class="wordbreak">'.$pathtofile.'</strong>';
5849 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>';
5850 print '<br>';
5851
5852 print '<br>';
5853 print load_fiche_titre($langs->trans("ListOfPermissionsDefined"), '', '');
5854
5855 print '<!-- form to add permissions -->'."\n";
5856 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
5857 print '<input type="hidden" name="token" value="'.newToken().'">';
5858 print '<input type="hidden" name="action" value="addright">';
5859 print '<input type="hidden" name="tab" value="permissions">';
5860 print '<input type="hidden" name="module" value="'.dol_escape_htmltag($module).'">';
5861 print '<input type="hidden" name="tabobj" value="'.dol_escape_htmltag($tabobj).'">';
5862
5863 print '<div class="div-table-responsive">';
5864 print '<table class="noborder">';
5865
5866 print '<tr class="liste_titre">';
5867 print_liste_field_titre("ID", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, "center");
5868 print_liste_field_titre("Object", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, "center");
5869 print_liste_field_titre("CRUD", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, "center");
5870 print_liste_field_titre("Label", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, "center");
5871 print_liste_field_titre("", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder, "center");
5872 print "</tr>\n";
5873
5874 //form for add new right
5875 print '<tr class="small">';
5876 print '<td><input type="hidden" readonly name="id" class="width75" value="0"></td>';
5877
5878 print '<td><select class="minwidth100" name="permissionObj" id="permissionObj">';
5879 print '<option value=""></option>';
5880 foreach ($objects as $obj) {
5881 if ($obj != 'myobject') {
5882 print '<option value="'.$obj.'">'.$obj.'</option>';
5883 }
5884 }
5885 print '</select></td>';
5886
5887 print '<td><select class="maxwidth75" name="crud" id="crud">';
5888 print '<option value=""></option>';
5889 foreach ($crud as $key => $val) {
5890 print '<option value="'.$key.'">'.$langs->trans($val).'</option>';
5891 }
5892 print '</td>';
5893
5894 print '<td >';
5895 print '<input type="text" name="label" id="label" class="minwidth200">';
5896 print '</td>';
5897
5898 print '<td class="center minwidth75 tdstickyright tdstickyghostwhite">';
5899 print '<input type="submit" class="button" name="add" value="'.$langs->trans("Add").'">';
5900 print '</td>';
5901 print '</tr>';
5902
5903 if (count($perms)) {
5904 $i = 0;
5905 foreach ($perms as $perm) {
5906 $i++;
5907
5908 // section for editing right
5909 if ($action == 'edit_right' && $perm[0] == GETPOSTINT('permskey')) {
5910 print '<tr class="oddeven">';
5911 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST" name="modifPerms">';
5912 print '<input type="hidden" name="token" value="'.newToken().'">';
5913 print '<input type="hidden" name="tab" value="permissions">';
5914 print '<input type="hidden" name="module" value="'.dol_escape_htmltag($module).'">';
5915 print '<input type="hidden" name="tabobj" value="'.dol_escape_htmltag($tabobj).'">';
5916 print '<input type="hidden" name="action" value="update_right">';
5917 print '<input type="hidden" name="counter" value="'.$i.'">';
5918
5919 print '<input type="hidden" name="permskey" value="'.$perm[0].'">';
5920
5921 print '<td class="tdsticky tdstickygray">';
5922 print '<input class="width75" type="text" readonly value="'.dol_escape_htmltag($perm[0]).'"/>';
5923 print '</td>';
5924
5925 print '<td>';
5926 print '<select name="crud">';
5927 print '<option value="'.dol_escape_htmltag($perm[5]).'">'.$langs->trans($perm[5]).'</option>';
5928 foreach ($crud as $i => $x) {
5929 if ($perm[5] != $i) {
5930 print '<option value="'.$i.'">'.$langs->trans(ucfirst($x)).'</option>';
5931 }
5932 }
5933 print '</select>';
5934 print '</td>';
5935
5936 print '<td><select name="permissionObj" >';
5937 print '<option value="'.dol_escape_htmltag($perm[4]).'">'.ucfirst($perm[4]).'</option>';
5938 print '</select></td>';
5939
5940 print '<td>';
5941 print '<input type="text" name="label" value="'.dol_escape_htmltag($perm[1]).'">';
5942 print '</td>';
5943
5944 print '<td class="center minwidth75 tdstickyright tdstickyghostwhite">';
5945 print '<input id ="modifyPerm" class="reposition button smallpaddingimp" type="submit" name="modifyright" value="'.$langs->trans("Modify").'"/>';
5946 print '<br>';
5947 print '<input class="reposition button button-cancel smallpaddingimp" type="submit" name="cancel" value="'.$langs->trans("Cancel").'"/>';
5948 print '</td>';
5949
5950 print '</form>';
5951 print '</tr>';
5952 } else {
5953 // $perm can be module->object->crud or module->crud
5954 print '<tr class="oddeven">';
5955
5956 print '<td>';
5957 print dol_escape_htmltag($perm[0]);
5958 print '</td>';
5959
5960 print '<td>';
5961 if (in_array($perm[5], array('lire', 'read', 'creer', 'write', 'effacer', 'delete'))) {
5962 print dol_escape_htmltag(ucfirst($perm[4]));
5963 } else {
5964 print ''; // No particular object
5965 }
5966 print '</td>';
5967
5968 print '<td>';
5969 if (in_array($perm[5], array('lire', 'read', 'creer', 'write', 'effacer', 'delete'))) {
5970 print ucfirst($langs->trans($perm[5]));
5971 } else {
5972 print ucfirst($langs->trans($perm[4]));
5973 }
5974 print '</td>';
5975
5976 print '<td>';
5977 print $langs->trans($perm[1]);
5978 print '</td>';
5979
5980 print '<td class="center minwidth75 tdstickyright tdstickyghostwhite">';
5981 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>';
5982 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>';
5983
5984 print '</td>';
5985
5986 print '</tr>';
5987 }
5988 }
5989 } else {
5990 print '<tr><td colspan="5"><span class="opacitymedium">'.$langs->trans("None").'</span></td></tr>';
5991 }
5992
5993 print '</table>';
5994 print '</div>';
5995
5996 print '</form>';
5997 print '<script>
5998 function updateInputField() {
5999 value1 = $("#crud").val();
6000 value2 = $("#permissionObj").val();
6001
6002 // Vérifie si les deux sélections sont faites
6003 if (value1 && value2) {
6004 switch(value1.toLowerCase()){
6005 case "read":
6006 $("#label").val("Read "+value2+" object of '.ucfirst($module).'")
6007 break;
6008 case "write":
6009 $("#label").val("Create/Update "+value2+" object of '.ucfirst($module).'")
6010 break;
6011 case "delete":
6012 $("#label").val("Delete "+value2+" object of '.ucfirst($module).'")
6013 break;
6014 default:
6015 $("#label").val("")
6016 }
6017 }
6018 }
6019
6020 $("#crud, #permissionObj").change(function(){
6021 console.log("We change selection");
6022 updateInputField();
6023 });
6024
6025 </script>';
6026 } else {
6027 $fullpathoffile = dol_buildpath($file, 0);
6028
6029 $content = file_get_contents($fullpathoffile);
6030
6031 // New module
6032 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
6033 print '<input type="hidden" name="token" value="'.newToken().'">';
6034 print '<input type="hidden" name="action" value="savefile">';
6035 print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
6036 print '<input type="hidden" name="tab" value="'.$tab.'">';
6037 print '<input type="hidden" name="module" value="'.$module.'">';
6038
6039 $posCursor = (empty($find)) ? array() : array('find' => $find);
6040 $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%', 0, $posCursor);
6041 print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'html'));
6042 print '<br>';
6043 print '<center>';
6044 print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
6045 print ' &nbsp; ';
6046 print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
6047 print '</center>';
6048
6049 print '</form>';
6050 }
6051 }
6052
6053 if ($tab == 'hooks') {
6054 print '<!-- tab=hooks -->'."\n";
6055 if ($action != 'editfile' || empty($file)) {
6056 print '<span class="opacitymedium">'.$langs->trans("HooksDefDesc").'</span><br>';
6057 print '<br>';
6058
6059 print '<table>';
6060
6061 $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
6062 print '<tr><td>';
6063 print '<span class="fa fa-file"></span> '.$langs->trans("DescriptorFile").' : <strong class="wordbreak">'.$pathtofile.'</strong>';
6064 print '</td><td>';
6065 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>';
6066 print '</td></tr>';
6067
6068 print '<tr><td>';
6069 $pathtohook = strtolower($module).'/class/actions_'.strtolower($module).'.class.php';
6070 print '<span class="fa fa-file"></span> '.$langs->trans("HooksFile").' : ';
6071 if (dol_is_file($dirins.'/'.$pathtohook)) {
6072 print '<strong class="wordbreak">'.$pathtohook.'</strong>';
6073 print '</td>';
6074 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> ';
6075 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>';
6076 } else {
6077 print '<span class="opacitymedium">'.$langs->trans("FileNotYetGenerated").'</span>';
6078 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>';
6079 print '<td></td>';
6080 }
6081 print '</tr>';
6082 } else {
6083 $fullpathoffile = dol_buildpath($file, 0);
6084
6085 $content = file_get_contents($fullpathoffile);
6086
6087 // New module
6088 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
6089 print '<input type="hidden" name="token" value="'.newToken().'">';
6090 print '<input type="hidden" name="action" value="savefile">';
6091 print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
6092 print '<input type="hidden" name="tab" value="'.$tab.'">';
6093 print '<input type="hidden" name="module" value="'.$module.'">';
6094
6095 $posCursor = (empty($find)) ? array() : array('find' => $find);
6096 $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%', 0, $posCursor);
6097 print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'html'));
6098 print '<br>';
6099 print '<center>';
6100 print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
6101 print ' &nbsp; ';
6102 print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
6103 print '</center>';
6104
6105 print '</form>';
6106 }
6107 }
6108
6109 if ($tab == 'triggers') {
6110 print '<!-- tab=triggers -->'."\n";
6111 require_once DOL_DOCUMENT_ROOT.'/core/class/interfaces.class.php';
6112
6113 $interfaces = new Interfaces($db);
6114 $triggers = $interfaces->getTriggersList(array('/'.strtolower($module).'/core/triggers'));
6115
6116 if ($action != 'editfile' || empty($file)) {
6117 print '<span class="opacitymedium">'.$langs->trans("TriggerDefDesc").'</span><br>';
6118 print '<br>';
6119
6120 print '<table>';
6121
6122 $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
6123 print '<tr><td>';
6124 print '<span class="fa fa-file"></span> '.$langs->trans("DescriptorFile").' : <strong class="wordbreak">'.$pathtofile.'</strong>';
6125 print '</td><td>';
6126 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>';
6127 print '</td></tr>';
6128
6129 if (!empty($triggers)) {
6130 foreach ($triggers as $trigger) {
6131 $pathtofile = $trigger['relpath'];
6132
6133 print '<tr><td>';
6134 print '<span class="fa fa-file"></span> '.$langs->trans("TriggersFile").' : <strong class="wordbreak">'.$pathtofile.'</strong>';
6135 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>';
6136 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>';
6137 print '</tr>';
6138 }
6139 } else {
6140 print '<tr><td>';
6141 print '<span class="fa fa-file"></span> '.$langs->trans("TriggersFile");
6142 print ' : <span class="opacitymedium">'.$langs->trans("FileNotYetGenerated").'</span>';
6143 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>';
6144 print '<td></td>';
6145 print '</tr>';
6146 }
6147
6148 print '</table>';
6149 } else {
6150 $fullpathoffile = dol_buildpath($file, 0);
6151
6152 $content = file_get_contents($fullpathoffile);
6153
6154 // New module
6155 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
6156 print '<input type="hidden" name="token" value="'.newToken().'">';
6157 print '<input type="hidden" name="action" value="savefile">';
6158 print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
6159 print '<input type="hidden" name="tab" value="'.$tab.'">';
6160 print '<input type="hidden" name="module" value="'.$module.'">';
6161
6162 $posCursor = (empty($find)) ? array() : array('find' => $find);
6163 $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%', 0, $posCursor);
6164 print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'html'));
6165 print '<br>';
6166 print '<center>';
6167 print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
6168 print ' &nbsp; ';
6169 print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
6170 print '</center>';
6171
6172 print '</form>';
6173 }
6174 }
6175
6176 if ($tab == 'css') {
6177 print '<!-- tab=css -->'."\n";
6178 if ($action != 'editfile' || empty($file)) {
6179 print '<span class="opacitymedium">'.$langs->trans("CSSDesc").'</span><br>';
6180 print '<br>';
6181
6182 print '<table>';
6183
6184 print '<tr><td>';
6185 $pathtohook = strtolower($module).'/css/'.strtolower($module).'.css.php';
6186 print '<span class="fa fa-file"></span> '.$langs->trans("CSSFile").' : ';
6187 if (dol_is_file($dirins.'/'.$pathtohook)) {
6188 print '<strong class="wordbreak">'.$pathtohook.'</strong>';
6189 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>';
6190 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>';
6191 } else {
6192 print '<span class="opacitymedium">'.$langs->trans("FileNotYetGenerated").'</span>';
6193 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>';
6194 }
6195 print '</tr>';
6196 } else {
6197 $fullpathoffile = dol_buildpath($file, 0);
6198
6199 $content = file_get_contents($fullpathoffile);
6200
6201 // New module
6202 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
6203 print '<input type="hidden" name="token" value="'.newToken().'">';
6204 print '<input type="hidden" name="action" value="savefile">';
6205 print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
6206 print '<input type="hidden" name="tab" value="'.$tab.'">';
6207 print '<input type="hidden" name="module" value="'.$module.'">';
6208
6209 $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%');
6210 print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'html'));
6211 print '<br>';
6212 print '<center>';
6213 print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
6214 print ' &nbsp; ';
6215 print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
6216 print '</center>';
6217
6218 print '</form>';
6219 }
6220 }
6221
6222 if ($tab == 'js') {
6223 print '<!-- tab=js -->'."\n";
6224 if ($action != 'editfile' || empty($file)) {
6225 print '<span class="opacitymedium">'.$langs->trans("JSDesc").'</span><br>';
6226 print '<br>';
6227
6228 print '<table>';
6229
6230 print '<tr><td>';
6231 $pathtohook = strtolower($module).'/js/'.strtolower($module).'.js.php';
6232 print '<span class="fa fa-file"></span> '.$langs->trans("JSFile").' : ';
6233 if (dol_is_file($dirins.'/'.$pathtohook)) {
6234 print '<strong class="wordbreak">'.$pathtohook.'</strong>';
6235 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>';
6236 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>';
6237 } else {
6238 print '<span class="opacitymedium">'.$langs->trans("FileNotYetGenerated").'</span>';
6239 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>';
6240 }
6241 print '</tr>';
6242 } else {
6243 $fullpathoffile = dol_buildpath($file, 0);
6244
6245 $content = file_get_contents($fullpathoffile);
6246
6247 // New module
6248 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
6249 print '<input type="hidden" name="token" value="'.newToken().'">';
6250 print '<input type="hidden" name="action" value="savefile">';
6251 print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
6252 print '<input type="hidden" name="tab" value="'.$tab.'">';
6253 print '<input type="hidden" name="module" value="'.$module.'">';
6254
6255 $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%');
6256 print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'html'));
6257 print '<br>';
6258 print '<center>';
6259 print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
6260 print ' &nbsp; ';
6261 print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
6262 print '</center>';
6263
6264 print '</form>';
6265 }
6266 }
6267
6268 if ($tab == 'widgets') {
6269 print '<!-- tab=widgets -->'."\n";
6270 require_once DOL_DOCUMENT_ROOT.'/core/boxes/modules_boxes.php';
6271
6272 $widgets = ModeleBoxes::getWidgetsList(array('/'.strtolower($module).'/core/boxes'));
6273
6274 if ($action != 'editfile' || empty($file)) {
6275 print '<span class="opacitymedium">'.$langs->trans("WidgetDesc").'</span><br>';
6276 print '<br>';
6277
6278 print '<table>';
6279 if (!empty($widgets)) {
6280 foreach ($widgets as $widget) {
6281 $pathtofile = $widget['relpath'];
6282
6283 print '<tr><td><span class="fa fa-file"></span> '.$langs->trans("WidgetFile").' : <strong class="wordbreak">'.$pathtofile.'</strong>';
6284 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>';
6285 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>';
6286 print '</tr>';
6287 }
6288 } else {
6289 print '<tr><td><span class="fa fa-file"></span> '.$langs->trans("WidgetFile").' : <span class="opacitymedium">'.$langs->trans("NoWidget").'</span>';
6290 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>';
6291 print '</td></tr>';
6292 }
6293 print '</table>';
6294 } else {
6295 $fullpathoffile = dol_buildpath($file, 0);
6296
6297 $content = file_get_contents($fullpathoffile);
6298
6299 // New module
6300 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
6301 print '<input type="hidden" name="token" value="'.newToken().'">';
6302 print '<input type="hidden" name="action" value="savefile">';
6303 print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
6304 print '<input type="hidden" name="tab" value="'.$tab.'">';
6305 print '<input type="hidden" name="module" value="'.$module.'">';
6306
6307 $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%');
6308 print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'html'));
6309 print '<br>';
6310 print '<center>';
6311 print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
6312 print ' &nbsp; ';
6313 print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
6314 print '</center>';
6315
6316 print '</form>';
6317 }
6318 }
6319
6320 if ($tab == 'emailings') {
6321 print '<!-- tab=emailings -->'."\n";
6322 require_once DOL_DOCUMENT_ROOT.'/core/modules/mailings/modules_mailings.php';
6323
6324 $emailingselectors = MailingTargets::getEmailingSelectorsList(array('/'.strtolower($module).'/core/modules/mailings'));
6325
6326 if ($action != 'editfile' || empty($file)) {
6327 print '<span class="opacitymedium">'.$langs->trans("EmailingSelectorDesc").'</span><br>';
6328 print '<br>';
6329
6330 print '<table>';
6331 if (!empty($emailingselectors)) {
6332 foreach ($emailingselectors as $emailingselector) {
6333 $pathtofile = $emailingselector['relpath'];
6334
6335 print '<tr><td><span class="fa fa-file"></span> '.$langs->trans("EmailingSelectorFile").' : <strong class="wordbreak">'.$pathtofile.'</strong>';
6336 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>';
6337 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>';
6338 print '</tr>';
6339 }
6340 } else {
6341 print '<tr><td><span class="fa fa-file"></span> '.$langs->trans("EmailingSelectorFile").' : <span class="opacitymedium">'.$langs->trans("NoEmailingSelector").'</span>';
6342 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>';
6343 print '</td></tr>';
6344 }
6345 print '</table>';
6346 } else {
6347 $fullpathoffile = dol_buildpath($file, 0);
6348
6349 $content = file_get_contents($fullpathoffile);
6350
6351 // New module
6352 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
6353 print '<input type="hidden" name="token" value="'.newToken().'">';
6354 print '<input type="hidden" name="action" value="savefile">';
6355 print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
6356 print '<input type="hidden" name="tab" value="'.$tab.'">';
6357 print '<input type="hidden" name="module" value="'.$module.'">';
6358
6359 $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%');
6360 print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'html'));
6361 print '<br>';
6362 print '<center>';
6363 print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
6364 print ' &nbsp; ';
6365 print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
6366 print '</center>';
6367
6368 print '</form>';
6369 }
6370 }
6371
6372 if ($tab == 'exportimport') {
6373 print '<!-- tab=exportimport -->'."\n";
6374 $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
6375
6376 $exportlist = $moduleobj->export_label;
6377 $importlist = $moduleobj->import_label;
6378
6379 if ($action != 'editfile' || empty($file)) {
6380 print '<span class="opacitymedium">'.$langs->transnoentities('ImportExportProfiles').'</span><br>';
6381 print '<br>';
6382
6383 print '<span class="fa fa-file"></span> '.$langs->trans("DescriptorFile").' ('.$langs->trans("ExportsArea").') : <strong class="wordbreak">'.$pathtofile.'</strong>';
6384 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>';
6385 print '<br>';
6386 print '<span class="fa fa-file"></span> '.$langs->trans("DescriptorFile").' ('.$langs->trans("ImportArea").') : <strong class="wordbreak">'.$pathtofile.'</strong>';
6387 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>';
6388 print '<br>';
6389 } else {
6390 $fullpathoffile = dol_buildpath($file, 0);
6391
6392 $content = file_get_contents($fullpathoffile);
6393
6394 // New module
6395 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
6396 print '<input type="hidden" name="token" value="'.newToken().'">';
6397 print '<input type="hidden" name="action" value="savefile">';
6398 print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
6399 print '<input type="hidden" name="tab" value="'.$tab.'">';
6400 print '<input type="hidden" name="module" value="'.$module.'">';
6401
6402 $posCursor = (empty($find)) ? array() : array('find' => $find);
6403 $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%', 0, $posCursor);
6404 print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'html'));
6405 print '<br>';
6406 print '<center>';
6407 print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
6408 print ' &nbsp; ';
6409 print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
6410 print '</center>';
6411
6412 print '</form>';
6413 }
6414 }
6415
6416 if ($tab == 'cli') {
6417 print '<!-- tab=cli -->'."\n";
6418 $clifiles = array();
6419 $i = 0;
6420
6421 $dircli = array('/'.strtolower($module).'/scripts');
6422
6423 foreach ($dircli as $reldir) {
6424 $dir = dol_buildpath($reldir, 0);
6425 $newdir = dol_osencode($dir);
6426
6427 // Check if directory exists (we do not use dol_is_dir to avoid loading files.lib.php at each call)
6428 if (!is_dir($newdir)) {
6429 continue;
6430 }
6431
6432 $handle = opendir($newdir);
6433
6434 if (is_resource($handle)) {
6435 while (($tmpfile = readdir($handle)) !== false) {
6436 if (is_readable($newdir.'/'.$tmpfile) && preg_match('/^(.+)\.php/', $tmpfile, $reg)) {
6437 if (preg_match('/\.back$/', $tmpfile)) {
6438 continue;
6439 }
6440
6441 $clifiles[$i]['relpath'] = preg_replace('/^\//', '', $reldir).'/'.$tmpfile;
6442
6443 $i++;
6444 }
6445 }
6446 closedir($handle);
6447 }
6448 }
6449
6450 if ($action != 'editfile' || empty($file)) {
6451 print '<span class="opacitymedium">'.$langs->trans("CLIDesc").'</span><br>';
6452 print '<br>';
6453
6454 print '<table>';
6455 if (!empty($clifiles)) {
6456 foreach ($clifiles as $clifile) {
6457 $pathtofile = $clifile['relpath'];
6458
6459 print '<tr><td><span class="fa fa-file"></span> '.$langs->trans("CLIFile").' : <strong class="wordbreak">'.$pathtofile.'</strong>';
6460 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>';
6461 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>';
6462 print '</tr>';
6463 }
6464 } else {
6465 print '<tr><td><span class="fa fa-file"></span> '.$langs->trans("CLIFile").' : <span class="opacitymedium">'.$langs->trans("FileNotYetGenerated").'</span>';
6466 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>';
6467 print '</td></tr>';
6468 }
6469 print '</table>';
6470 } else {
6471 $fullpathoffile = dol_buildpath($file, 0);
6472
6473 $content = file_get_contents($fullpathoffile);
6474
6475 // New module
6476 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
6477 print '<input type="hidden" name="token" value="'.newToken().'">';
6478 print '<input type="hidden" name="action" value="savefile">';
6479 print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
6480 print '<input type="hidden" name="tab" value="'.$tab.'">';
6481 print '<input type="hidden" name="module" value="'.$module.'">';
6482
6483 $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%');
6484 print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'html'));
6485 print '<br>';
6486 print '<center>';
6487 print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
6488 print ' &nbsp; ';
6489 print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
6490 print '</center>';
6491
6492 print '</form>';
6493 }
6494 }
6495
6496 if ($tab == 'cron') {
6497 print '<!-- tab=cron -->'."\n";
6498 $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
6499
6500 $cronjobs = $moduleobj->cronjobs;
6501
6502 if ($action != 'editfile' || empty($file)) {
6503 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>';
6504 print '<br>';
6505
6506 print '<span class="fa fa-file"></span> '.$langs->trans("DescriptorFile").' : <strong class="wordbreak">'.$pathtofile.'</strong>';
6507 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>';
6508 print '<br>';
6509
6510 print '<br>';
6511 print load_fiche_titre($langs->trans("CronJobProfiles"), '', '');
6512
6513 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
6514 print '<input type="hidden" name="token" value="'.newToken().'">';
6515 print '<input type="hidden" name="action" value="addproperty">';
6516 print '<input type="hidden" name="tab" value="objects">';
6517 print '<input type="hidden" name="module" value="'.dol_escape_htmltag($module).'">';
6518 print '<input type="hidden" name="tabobj" value="'.dol_escape_htmltag($tabobj).'">';
6519
6520 print '<div class="div-table-responsive">';
6521 print '<table class="noborder">';
6522
6523 print '<tr class="liste_titre">';
6524 print_liste_field_titre("CronLabel", $_SERVER["PHP_SELF"], "", "", $param, '', $sortfield, $sortorder);
6525 print_liste_field_titre("CronTask", '', '', "", $param, '', $sortfield, $sortorder);
6526 print_liste_field_titre("CronFrequency", '', "", "", $param, '', $sortfield, $sortorder);
6527 print_liste_field_titre("StatusAtInstall", $_SERVER["PHP_SELF"], "", "", $param, '', $sortfield, $sortorder);
6528 print_liste_field_titre("Comment", $_SERVER["PHP_SELF"], "", "", $param, '', $sortfield, $sortorder);
6529 print "</tr>\n";
6530
6531 if (count($cronjobs)) {
6532 foreach ($cronjobs as $cron) {
6533 print '<tr class="oddeven">';
6534
6535 print '<td>';
6536 print $cron['label'];
6537 print '</td>';
6538
6539 print '<td>';
6540 $texttoshow = '';
6541 if ($cron['jobtype'] == 'method') {
6542 $text = $langs->trans("CronClass");
6543 $texttoshow = $langs->trans('CronModule').': '.$module.'<br>';
6544 $texttoshow .= $langs->trans('CronClass').': '.$cron['class'].'<br>';
6545 $texttoshow .= $langs->trans('CronObject').': '.$cron['objectname'].'<br>';
6546 $texttoshow .= $langs->trans('CronMethod').': '.$cron['method'];
6547 $texttoshow .= '<br>'.$langs->trans('CronArgs').': '.$cron['parameters'];
6548 $texttoshow .= '<br>'.$langs->trans('Comment').': '.$langs->trans($cron['comment']);
6549 } elseif ($cron['jobtype'] == 'command') {
6550 $text = $langs->trans('CronCommand');
6551 $texttoshow = $langs->trans('CronCommand').': '.dol_trunc($cron['command']);
6552 $texttoshow .= '<br>'.$langs->trans('CronArgs').': '.$cron['parameters'];
6553 $texttoshow .= '<br>'.$langs->trans('Comment').': '.$langs->trans($cron['comment']);
6554 }
6555 print $form->textwithpicto($text, $texttoshow, 1);
6556 print '</td>';
6557
6558 print '<td>';
6559 if ($cron['unitfrequency'] == "60") {
6560 print $langs->trans('CronEach')." ".($cron['frequency'])." ".$langs->trans('Minutes');
6561 }
6562 if ($cron['unitfrequency'] == "3600") {
6563 print $langs->trans('CronEach')." ".($cron['frequency'])." ".$langs->trans('Hours');
6564 }
6565 if ($cron['unitfrequency'] == "86400") {
6566 print $langs->trans('CronEach')." ".($cron['frequency'])." ".$langs->trans('Days');
6567 }
6568 if ($cron['unitfrequency'] == "604800") {
6569 print $langs->trans('CronEach')." ".($cron['frequency'])." ".$langs->trans('Weeks');
6570 }
6571 print '</td>';
6572
6573 print '<td>';
6574 print $cron['status'];
6575 print '</td>';
6576
6577 print '<td>';
6578 if (!empty($cron['comment'])) {
6579 print $cron['comment'];
6580 }
6581 print '</td>';
6582
6583 print '</tr>';
6584 }
6585 } else {
6586 print '<tr><td colspan="5"><span class="opacitymedium">'.$langs->trans("None").'</span></td></tr>';
6587 }
6588
6589 print '</table>';
6590 print '</div>';
6591
6592 print '</form>';
6593 } else {
6594 $fullpathoffile = dol_buildpath($file, 0);
6595
6596 $content = file_get_contents($fullpathoffile);
6597
6598 // New module
6599 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
6600 print '<input type="hidden" name="token" value="'.newToken().'">';
6601 print '<input type="hidden" name="action" value="savefile">';
6602 print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
6603 print '<input type="hidden" name="tab" value="'.$tab.'">';
6604 print '<input type="hidden" name="module" value="'.$module.'">';
6605
6606 $posCursor = (empty($find)) ? array() : array('find' => $find);
6607 $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%', 0, $posCursor);
6608 print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'html'));
6609 print '<br>';
6610 print '<center>';
6611 print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
6612 print ' &nbsp; ';
6613 print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
6614 print '</center>';
6615
6616 print '</form>';
6617 }
6618 }
6619
6620 if ($tab == 'specifications') {
6621 print '<!-- tab=specifications -->'."\n";
6622 $specs = dol_dir_list(dol_buildpath($modulelowercase.'/doc', 0), 'files', 1, '(\.md|\.asciidoc)$', array('\/temp\/'));
6623
6624 if ($action != 'editfile' || empty($file)) {
6625 print '<span class="opacitymedium">'.$langs->trans("SpecDefDesc").'</span><br>';
6626 print '<br>';
6627
6628 print '<table>';
6629 if (is_array($specs) && !empty($specs)) {
6630 foreach ($specs as $spec) {
6631 $pathtofile = $modulelowercase.'/doc/'.$spec['relativename'];
6632 $format = 'asciidoc';
6633 if (preg_match('/\.md$/i', $spec['name'])) {
6634 $format = 'markdown';
6635 }
6636 print '<tr><td>';
6637 print '<span class="fa fa-file"></span> '.$langs->trans("SpecificationFile").' : <strong class="wordbreak">'.$pathtofile.'</strong>';
6638 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>';
6639 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>';
6640 print '</tr>';
6641 }
6642 } else {
6643 print '<tr><td>';
6644 print '<span class="fa fa-file"></span> '.$langs->trans("SpecificationFile").' : <span class="opacitymedium">'.$langs->trans("FileNotYetGenerated").'</span>';
6645 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>';
6646 print '</tr>';
6647 }
6648 print '</table>';
6649 } else {
6650 // Use MD or asciidoc
6651
6652 //print $langs->trans("UseAsciiDocFormat").'<br>';
6653
6654 $fullpathoffile = dol_buildpath($file, 0);
6655
6656 $content = file_get_contents($fullpathoffile);
6657
6658 // New module
6659 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
6660 print '<input type="hidden" name="token" value="'.newToken().'">';
6661 print '<input type="hidden" name="action" value="savefile">';
6662 print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
6663 print '<input type="hidden" name="tab" value="'.$tab.'">';
6664 print '<input type="hidden" name="module" value="'.$module.'">';
6665
6666 $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%');
6667 print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'html'));
6668 print '<br>';
6669 print '<center>';
6670 print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
6671 print ' &nbsp; ';
6672 print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
6673 print '</center>';
6674
6675 print '</form>';
6676 }
6677
6678 print '<br><br><br>';
6679
6680 $FILENAMEDOC = $modulelowercase.'.html';
6681 $FILENAMEDOCPDF = $modulelowercase.'.pdf';
6682 $outputfiledoc = dol_buildpath($modulelowercase, 0).'/doc/'.$FILENAMEDOC;
6683 $outputfiledocurl = dol_buildpath($modulelowercase, 1).'/doc/'.$FILENAMEDOC;
6684 $outputfiledocrel = $modulelowercase.'/doc/'.$FILENAMEDOC;
6685 $outputfiledocpdf = dol_buildpath($modulelowercase, 0).'/doc/'.$FILENAMEDOCPDF;
6686 $outputfiledocurlpdf = dol_buildpath($modulelowercase, 1).'/doc/'.$FILENAMEDOCPDF;
6687 $outputfiledocrelpdf = $modulelowercase.'/doc/'.$FILENAMEDOCPDF;
6688
6689 // HTML
6690 print '<span class="fa fa-file"></span> '.$langs->trans("PathToModuleDocumentation", "HTML").' : ';
6691 if (!dol_is_file($outputfiledoc)) {
6692 print '<span class="opacitymedium">'.$langs->trans("FileNotYetGenerated").'</span>';
6693 } else {
6694 print '<strong>';
6695 print '<a href="'.$outputfiledocurl.'" target="_blank" rel="noopener noreferrer">';
6696 print $outputfiledoc;
6697 print '</a>';
6698 print '</strong>';
6699 print ' <span class="opacitymedium">('.$langs->trans("GeneratedOn").' '.dol_print_date(dol_filemtime($outputfiledoc), 'dayhour').')</span>';
6700 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>';
6701 }
6702 print '</strong><br>';
6703
6704 // PDF
6705 print '<span class="fa fa-file"></span> '.$langs->trans("PathToModuleDocumentation", "PDF").' : ';
6706 if (!dol_is_file($outputfiledocpdf)) {
6707 print '<span class="opacitymedium">'.$langs->trans("FileNotYetGenerated").'</span>';
6708 } else {
6709 print '<strong>';
6710 print '<a href="'.$outputfiledocurlpdf.'" target="_blank" rel="noopener noreferrer">';
6711 print $outputfiledocpdf;
6712 print '</a>';
6713 print '</strong>';
6714 print ' <span class="opacitymedium">('.$langs->trans("GeneratedOn").' '.dol_print_date(dol_filemtime($outputfiledocpdf), 'dayhour').')</span>';
6715 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>';
6716 }
6717 print '</strong><br>';
6718
6719 print '<br>';
6720
6721 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST" name="generatedoc">';
6722 print '<input type="hidden" name="token" value="'.newToken().'">';
6723 print '<input type="hidden" name="action" value="generatedoc">';
6724 print '<input type="hidden" name="tab" value="'.dol_escape_htmltag($tab).'">';
6725 print '<input type="hidden" name="module" value="'.dol_escape_htmltag($module).'">';
6726 print '<input type="submit" class="button" name="generatedoc" value="'.$langs->trans("BuildDocumentation").'"';
6727 if (!is_array($specs) || empty($specs)) {
6728 print ' disabled="disabled"';
6729 }
6730 print '>';
6731 print '</form>';
6732 }
6733
6734 if ($tab == 'buildpackage') {
6735 print '<!-- tab=buildpackage -->'."\n";
6736 print '<span class="opacitymedium">'.$langs->trans("BuildPackageDesc").'</span>';
6737 print '<br>';
6738
6739 if (!class_exists('ZipArchive') && !defined('ODTPHP_PATHTOPCLZIP')) {
6740 print img_warning().' '.$langs->trans("ErrNoZipEngine");
6741 print '<br>';
6742 }
6743
6744 $modulelowercase = strtolower($module);
6745
6746 // Zip file to build
6747 $FILENAMEZIP = '';
6748
6749 // Load module
6750 $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
6751 dol_include_once($pathtofile);
6752 $class = 'mod'.$module;
6753 $moduleobj = null;
6754 if (class_exists($class)) {
6755 try {
6756 $moduleobj = new $class($db);
6757 '@phan-var-force DolibarrModules $moduleobj';
6759 } catch (Exception $e) {
6760 $error++;
6761 dol_print_error($db, $e->getMessage());
6762 }
6763 }
6764 if ($moduleobj === null) {
6765 $error++;
6766 $langs->load("errors");
6767 dol_print_error($db, $langs->trans("ErrorFailedToLoadModuleDescriptorForXXX", $module));
6768 exit;
6769 }
6770
6771 $arrayversion = explode('.', $moduleobj->version, 3);
6772 if (count($arrayversion)) {
6773 $FILENAMEZIP = "module_".$modulelowercase.'-'.$arrayversion[0].(empty($arrayversion[1]) ? '.0' : '.'.$arrayversion[1]).(empty($arrayversion[2]) ? '' : ".".$arrayversion[2]).".zip";
6774 $outputfilezip = dol_buildpath($modulelowercase, 0).'/bin/'.$FILENAMEZIP;
6775 }
6776
6777 print '<br>';
6778
6779 print '<span class="fa fa-file"></span> '.$langs->trans("PathToModulePackage").' : ';
6780 if ($outputfilezip === null || !dol_is_file($outputfilezip)) {
6781 print '<span class="opacitymedium">'.$langs->trans("FileNotYetGenerated").'</span>';
6782 } else {
6783 $relativepath = $modulelowercase.'/bin/'.$FILENAMEZIP;
6784 print '<strong><a href="'.DOL_URL_ROOT.'/document.php?modulepart=packages&file='.urlencode($relativepath).'">'.$outputfilezip.'</a></strong>';
6785 print ' <span class="opacitymedium">('.$langs->trans("GeneratedOn").' '.dol_print_date(dol_filemtime($outputfilezip), 'dayhour').')</span>';
6786 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>';
6787 }
6788 print '</strong>';
6789
6790 print '<br>';
6791
6792 print '<br>';
6793
6794 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST" name="generatepackage">';
6795 print '<input type="hidden" name="token" value="'.newToken().'">';
6796 print '<input type="hidden" name="action" value="generatepackage">';
6797 print '<input type="hidden" name="tab" value="'.dol_escape_htmltag($tab).'">';
6798 print '<input type="hidden" name="module" value="'.dol_escape_htmltag($module).'">';
6799 print '<input type="submit" class="button" name="generatepackage" value="'.$langs->trans("BuildPackage").'">';
6800 print '</form>';
6801 }
6802
6803 if ($tab == 'tabs') {
6804 $pathtofile = $listofmodules[strtolower($module)]['moduledescriptorrelpath'];
6805
6806 $tabs = $moduleobj->tabs;
6807
6808 if ($action != 'editfile' || empty($file)) {
6809 print '<span class="opacitymedium">';
6810 $htmlhelp = $langs->trans("TabsDefDescTooltip", '{s1}');
6811 $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);
6812 print $form->textwithpicto($langs->trans("TabsDefDesc"), $htmlhelp, 1, 'help', '', 0, 2, 'helpondesc').'<br>';
6813 print '</span>';
6814 print '<br>';
6815
6816 print '<span class="fa fa-file"></span> '.$langs->trans("DescriptorFile").' : <strong>'.$pathtofile.'</strong>';
6817 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>';
6818 print '<br>';
6819
6820 print '<br>';
6821 print load_fiche_titre($langs->trans("ListOfTabsEntries"), '', '');
6822
6823 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
6824 print '<input type="hidden" name="token" value="'.newToken().'">';
6825 print '<input type="hidden" name="action" value="addproperty">';
6826 print '<input type="hidden" name="tab" value="objects">';
6827 print '<input type="hidden" name="module" value="'.dol_escape_htmltag($module).'">';
6828 print '<input type="hidden" name="tabobj" value="'.dol_escape_htmltag($tabobj).'">';
6829
6830 print '<div class="div-table-responsive">';
6831 print '<table class="noborder small">';
6832
6833 print '<tr class="liste_titre">';
6834 print_liste_field_titre("ObjectType", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
6835 print_liste_field_titre("Tab", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
6836 print_liste_field_titre("Title", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
6837 print_liste_field_titre("LangFile", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
6838 print_liste_field_titre("Condition", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
6839 print_liste_field_titre("Path", $_SERVER["PHP_SELF"], '', "", $param, '', $sortfield, $sortorder);
6840 print "</tr>\n";
6841
6842 if (count($tabs)) {
6843 foreach ($tabs as $tab) {
6844 $parts = explode(':', $tab['data']);
6845
6846 $objectType = $parts[0];
6847 $tabName = $parts[1];
6848 $tabTitle = isset($parts[2]) ? $parts[2] : '';
6849 $langFile = isset($parts[3]) ? $parts[3] : '';
6850 $condition = isset($parts[4]) ? $parts[4] : '';
6851 $path = isset($parts[5]) ? $parts[5] : '';
6852
6853 // If we want to remove the tab, then the format is 'objecttype:tabname:optionalcondition'
6854 // See: https://wiki.dolibarr.org/index.php?title=Tabs_system#To_remove_an_existing_tab
6855 if ($tabName[0] === '-') {
6856 $tabTitle = '';
6857 $condition = isset($parts[2]) ? $parts[2] : '';
6858 }
6859
6860 print '<tr class="oddeven">';
6861
6862 print '<td>';
6863 print dol_escape_htmltag($parts[0]);
6864 print '</td>';
6865
6866 print '<td>';
6867 if ($tabName[0] === "+") {
6868 print '<span class="badge badge-status4 badge-status">' . dol_escape_htmltag($tabName) . '</span>';
6869 } else {
6870 print '<span class="badge badge-status8 badge-status">' . dol_escape_htmltag($tabName) . '</span>';
6871 }
6872 print '</td>';
6873
6874 print '<td>';
6875 print dol_escape_htmltag($tabTitle);
6876 print '</td>';
6877
6878 print '<td>';
6879 print dol_escape_htmltag($langFile);
6880 print '</td>';
6881
6882 print '<td>';
6883 print dol_escape_htmltag($condition);
6884 print '</td>';
6885
6886 print '<td>';
6887 print dol_escape_htmltag($path);
6888 print '</td>';
6889
6890 print '</tr>';
6891 }
6892 } else {
6893 print '<tr><td colspan="5"><span class="opacitymedium">'.$langs->trans("None").'</span></td></tr>';
6894 }
6895
6896 print '</table>';
6897 print '</div>';
6898
6899 print '</form>';
6900 } else {
6901 $fullpathoffile = dol_buildpath($file, 0);
6902
6903 $content = file_get_contents($fullpathoffile);
6904
6905 // New module
6906 print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
6907 print '<input type="hidden" name="token" value="'.newToken().'">';
6908 print '<input type="hidden" name="action" value="savefile">';
6909 print '<input type="hidden" name="file" value="'.dol_escape_htmltag($file).'">';
6910 print '<input type="hidden" name="tab" value="'.$tab.'">';
6911 print '<input type="hidden" name="module" value="'.$module.'">';
6912
6913 $posCursor = (empty($find)) ? array() : array('find' => $find);
6914 $doleditor = new DolEditor('editfilecontent', $content, '', 300, 'Full', 'In', true, false, 'ace', 0, '99%', 0, $posCursor);
6915 print $doleditor->Create(1, '', false, $langs->trans("File").' : '.$file, (GETPOST('format', 'aZ09') ? GETPOST('format', 'aZ09') : 'html'));
6916 print '<br>';
6917 print '<center>';
6918 print '<input type="submit" class="button buttonforacesave button-save" id="savefile" name="savefile" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
6919 print ' &nbsp; ';
6920 print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
6921 print '</center>';
6922
6923 print '</form>';
6924 }
6925 }
6926
6927 if ($tab != 'description') {
6928 print dol_get_fiche_end();
6929 }
6930 }
6931}
6932
6933print dol_get_fiche_end(); // End modules
6934
6935
6936// End of page
6937llxFooter();
6938$db->close();
$id
Support class for third parties, contacts, members, users or resources.
Definition account.php:47
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:475
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:207
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.
Class to manage utility methods.
global $mysoc
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:64
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.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0, $attop=0)
Set event messages in dol_events session object.
dolExplodeIntoArray($string, $delimiter=';', $kv='=')
Split a string with 2 keys into key array.
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_mimetype($file, $default='application/octet-stream', $mode=0)
Return MIME type of a file from its name with extension.
GETPOSTINT($paramname, $method=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
dol_osencode($str)
Return a string encoded into OS filesystem encoding.
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.
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.
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.
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.
getPictoForType($key, $morecss='')
Return the picto for a data type.
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'.
yn($yesno, $format=1, $color=0)
Return yes or no in current language.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
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_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.
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.
info_admin($text, $infoonimgalt=0, $nodiv=0, $admin='1', $morecss='hideonsmartphone', $textfordropdown='', $picto='')
Show information in HTML for admin users or standard users.
img_edit($titlealt='default', $float=0, $other='')
Show logo edit/modify fiche.
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)
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...
treeview li table
No Email.
a disabled
$moduleobj
Definition index.php:3284
foreach( $dirsrootforscan as $tmpdirread) moduleBuilderShutdownFunction()
Add management to catch fatal errors - shutdown handler.
Definition index.php:238
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.
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.
rebuildObjectClass($destdir, $module, $objectname, $newmask, $readdir='', $addfieldentry=array(), $delfieldentry='')
Regenerate files .class.php.
reWriteAllPermissions($file, $permissions, $key, $right, $objectname, $module, $action)
Rewriting all permissions after any actions.
checkExistComment($file, $number)
Function to check if comment BEGIN and END exists in modMyModule class.
addObjectsToApiFile($srcfile, $file, $objects, $modulename)
Add Object in ModuleApi File.
$conf db user
Active Directory does not allow anonymous connections.
Definition repair.php:129
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:125
$conf db name
Only used if Module[ID]Name translation string is not found.
Definition repair.php:128
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.