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