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