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