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