Issues (2811)

public/htdocs/admin/modulehelp.php (1 issue)

1
<?php
2
3
/* Copyright (C) 2017       Laurent Destailleur         <[email protected]>
4
 * Copyright (C) 2017	    Regis Houssin			    <[email protected]>
5
 * Copyright (C) 2022	    Charlene Benke			    <[email protected]>
6
 * Copyright (C) 2024		MDW							<[email protected]>
7
 * Copyright (C) 2024       Rafael San José             <[email protected]>
8
 *
9
 * This program is free software; you can redistribute it and/or modify
10
 * it under the terms of the GNU General Public License as published by
11
 * the Free Software Foundation; either version 3 of the License, or
12
 * (at your option) any later version.
13
 *
14
 * This program is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 * GNU General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU General Public License
20
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
21
 */
22
23
use Dolibarr\Code\Core\Classes\Form;
24
use Dolibarr\Code\User\Classes\User;
25
use Dolibarr\Core\Base\DolibarrModules;
26
use Dolibarr\Lib\ViewMain;
27
28
/**
29
 *  \file       htdocs/admin/modulehelp.php
30
 *  \brief      Page to activate/disable all modules
31
 */
32
33
if (!defined('NOREQUIREMENU')) {
34
    define('NOREQUIREMENU', '1'); // If there is no need to load and show top and left menu
35
}
36
if (!defined('NOTOKENRENEWAL')) {
37
    define('NOTOKENRENEWAL', '1'); // Disabled because this page is into a popup on module search page and we want to avoid to have an Anti CSRF token error (done if MAIN_SECURITY_CSRF_WITH_TOKEN is on) when we make a second search after closing popup.
38
}
39
40
// Load Dolibarr environment
41
require constant('DOL_DOCUMENT_ROOT') . '/main.inc.php';
42
require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/admin.lib.php';
43
require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/files.lib.php';
44
require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/functions2.lib.php';
45
46
// Load translation files required by the page
47
$langs->loadLangs(array('errors', 'admin', 'modulebuilder', 'exports'));
48
49
$mode = GETPOST('mode', 'alpha');
50
$action = GETPOST('action', 'aZ09');
51
$id = GETPOSTINT('id');
52
if (empty($mode)) {
53
    $mode = 'desc';
54
}
55
56
if (empty($user->admin)) {
57
    accessforbidden();
58
}
59
60
61
/*
62
 * Actions
63
 */
64
65
// Nothing
66
67
68
/*
69
 * View
70
 */
71
72
$form = new Form($db);
73
74
$help_url = 'EN:First_setup|FR:Premiers_paramétrages|ES:Primeras_configuraciones';
75
ViewMain::llxHeader('', $langs->trans("Setup"), $help_url, '', 0, 0, '', '', '', 'mod-admin page-modulehelp');
76
77
print '<!-- Force style container -->' . "\n" . '<style>
78
.id-container {
79
    width: 100%;
80
}
81
#id-right {
82
	padding-left: unset;
83
}
84
</style>';
85
86
$arrayofnatures = array('core' => $langs->transnoentitiesnoconv("Core"), 'external' => $langs->transnoentitiesnoconv("External") . ' - ' . $langs->trans("AllPublishers"));
87
88
// Search modules dirs
89
$modulesdir = dolGetModulesDirs();
90
91
$filename = array();
92
$modules = array();
93
$orders = array();
94
$categ = array();
95
$dirmod = array();
96
$i = 0; // is a sequencer of modules found
97
$j = 0; // j is module number. Automatically affected if module number not defined.
98
$modNameLoaded = array();
99
100
$allModules = DolibarrModules::getModules($modulesdir);
101
foreach ($allModules as $modName => $filename) {
102
    if (str_starts_with($modName, 'mod')) {
103
        include_once $filename;
104
        $objMod = new $modName($db);
105
    } else {
106
        $className = "\\Dolibarr\\Modules\\" . $modName;
107
        $objMod = new $className($db);
108
    }
109
110
    if (isset($modNameLoaded[$modName])) {
111
        $mesg = "Error: Module " . $modName . " was found twice: Into " . $modNameLoaded[$modName] . " and " . $dir . ". You probably have an old file on your disk.<br>";
112
        setEventMessages($mesg, null, 'warnings');
113
        dol_syslog($mesg, LOG_ERR);
114
        continue;
115
    }
116
117
    try {
118
        $modNameLoaded[$modName] = $filename;
119
120
        if (!$objMod->numero > 0 && $modName != 'modUser') {
121
            dol_syslog('The module descriptor ' . $modName . ' must have a numero property', LOG_ERR);
122
        }
123
        $j = $objMod->numero;
124
125
        /**
126
         * TODO: See modules use of $objMod->isDevelopment(), etc
127
         */
128
129
        $modulequalified = 1;
130
131
        // We discard modules according to features level (PS: if module is activated we always show it)
132
        $const_name = 'MAIN_MODULE_' . strtoupper(preg_replace('/^mod/i', '', get_only_class($objMod)));
133
        if ($objMod->version == 'development' && (!getDolGlobalString($const_name) && (getDolGlobalInt('MAIN_FEATURES_LEVEL') < 2))) {
134
            $modulequalified = 0;
135
        }
136
        if ($objMod->version == 'experimental' && (!getDolGlobalString($const_name) && (getDolGlobalInt('MAIN_FEATURES_LEVEL') < 1))) {
137
            $modulequalified = 0;
138
        }
139
        if (preg_match('/deprecated/', $objMod->version) && (!getDolGlobalString($const_name) && (getDolGlobalInt('MAIN_FEATURES_LEVEL') >= 0))) {
140
            $modulequalified = 0;
141
        }
142
143
        // We discard modules according to property disabled
144
        //if (!empty($objMod->hidden)) $modulequalified=0;
145
146
        if ($modulequalified > 0) {
147
            $publisher = dol_escape_htmltag($objMod->getPublisher());
148
            $external = ($objMod->isCoreOrExternalModule() == 'external');
149
            if ($external) {
150
                if ($publisher) {
151
                    $arrayofnatures['external_' . $publisher] = $langs->trans("External") . ' - ' . $publisher;
152
                } else {
153
                    $arrayofnatures['external_'] = $langs->trans("External") . ' - ' . $langs->trans("UnknownPublishers");
154
                }
155
            }
156
            ksort($arrayofnatures);
157
        }
158
159
        // Define array $categ with categ with at least one qualified module
160
        if ($modulequalified > 0) {
161
            $modules[$i] = $objMod;
162
            $filename[$i] = $modName;
163
164
            // Gives the possibility to the module, to provide his own family info and position of this family
165
            if (is_array($objMod->familyinfo) && !empty($objMod->familyinfo)) {
166
                if (!is_array($familyinfo)) {
167
                    $familyinfo = array();
168
                }
169
                $familyinfo = array_merge($familyinfo, $objMod->familyinfo);
170
                $familykey = key($objMod->familyinfo);
171
            } else {
172
                $familykey = $objMod->family;
173
            }
174
            if (empty($familykey) || $familykey === null) {
175
                $familykey = 'other';
176
            }
177
178
            $moduleposition = ($objMod->module_position ? $objMod->module_position : '50');
179
            if ($moduleposition == '50' && ($objMod->isCoreOrExternalModule() == 'external')) {
180
                $moduleposition = '80'; // External modules at end by default
181
            }
182
183
            if (empty($familyinfo[$familykey]['position'])) {
184
                $familyinfo[$familykey]['position'] = '0';
185
            }
186
187
            $orders[$i] = $familyinfo[$familykey]['position'] . "_" . $familykey . "_" . $moduleposition . "_" . $j; // Sort by family, then by module position then number
188
            $dirmod[$i] = $dir;
189
            //print $i.'-'.$dirmod[$i].'<br>';
190
            // Set categ[$i]
191
            $specialstring = 'unknown';
192
            if ($objMod->version == 'development' || $objMod->version == 'experimental') {
193
                $specialstring = 'expdev';
194
            }
195
            if (isset($categ[$specialstring])) {
196
                $categ[$specialstring]++; // Array of all different modules categories
197
            } else {
198
                $categ[$specialstring] = 1;
199
            }
200
            $j++;
201
            $i++;
202
        } else {
203
            dol_syslog("Module " . get_only_class($objMod) . " not qualified");
204
        }
205
    } catch (Exception $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
206
    }
207
}
208
209
asort($orders);
210
//var_dump($orders);
211
//var_dump($categ);
212
//var_dump($modules);
213
214
215
unset($objMod);
216
$i = 0;
217
foreach ($orders as $tmpkey => $tmpvalue) {
218
    $tmpMod = $modules[$tmpkey];
219
    if ($tmpMod->numero == $id) {
220
        $key = $i;
221
        $modName = $filename[$tmpkey];
222
        $dirofmodule = $dirmod[$tmpkey];
223
        $objMod = $tmpMod;
224
        break;
225
    }
226
    $i++;
227
}
228
$value = $orders[$key];
229
$tab = explode('_', $value);
230
$familyposition = $tab[0];
231
$familykey = $tab[1];
232
$module_position = $tab[2];
233
$numero = $tab[3];
234
235
236
$head = modulehelp_prepare_head($objMod);
237
238
// Check filters
239
$modulename = $objMod->getName();
240
$moduledesc = $objMod->getDesc();
241
$moduleauthor = $objMod->getPublisher();
242
$moduledir = strtolower(preg_replace('/^mod/i', '', get_only_class($objMod)));
243
244
$const_name = 'MAIN_MODULE_' . strtoupper(preg_replace('/^mod/i', '', get_only_class($objMod)));
245
246
$text = '<span class="opacitymedium">' . $langs->trans("LastActivationDate") . ':</span> ';
247
if (getDolGlobalString($const_name)) {
248
    $text .= dol_print_date($objMod->getLastActivationDate(), 'dayhour');
249
} else {
250
    $text .= $langs->trans("Disabled");
251
}
252
$tmp = $objMod->getLastActivationInfo();
253
$authorid = (empty($tmp['authorid']) ? '' : $tmp['authorid']);
254
if ($authorid > 0) {
255
    $tmpuser = new User($db);
256
    $tmpuser->fetch($authorid);
257
    $text .= '<br><span class="opacitymedium">' . $langs->trans("LastActivationAuthor") . ':</span> ';
258
    $text .= $tmpuser->getNomUrl(-1);
259
}
260
$ip = (empty($tmp['ip']) ? '' : $tmp['ip']);
261
if ($ip) {
262
    $text .= '<br><span class="opacitymedium">' . $langs->trans("LastActivationIP") . ':</span> ';
263
    $text .= $ip;
264
}
265
$lastactivationversion = (empty($tmp['lastactivationversion']) ? '' : $tmp['lastactivationversion']);
266
if ($lastactivationversion) {
267
    $text .= '<br><span class="opacitymedium">' . $langs->trans("LastActivationVersion") . ':</span> ';
268
    $text .= $lastactivationversion;
269
}
270
271
$moreinfo = $text;
272
273
$title = ($modulename ? $modulename : $moduledesc);
274
275
print '<div class="centpercent">';
276
277
$picto = 'object_' . $objMod->picto;
278
279
print load_fiche_titre(($modulename ? $modulename : $moduledesc), $moreinfo, $picto, 0, '', 'titlemodulehelp');
280
print '<br>';
281
282
print dol_get_fiche_head($head, $mode, '', -1);
283
284
if (!$modulename) {
285
    dol_syslog("Error for module " . $key . " - Property name of module looks empty", LOG_WARNING);
286
}
287
288
// Load all lang files of module
289
if (isset($objMod->langfiles) && is_array($objMod->langfiles)) {
290
    foreach ($objMod->langfiles as $domain) {
291
        $langs->load($domain);
292
    }
293
}
294
295
296
// Version (with picto warning or not)
297
$version = $objMod->getVersion(0);
298
$versiontrans = '';
299
if (preg_match('/development/i', $version)) {
300
    $versiontrans .= img_warning($langs->trans("Development"), 'style="float: left"');
301
}
302
if (preg_match('/experimental/i', $version)) {
303
    $versiontrans .= img_warning($langs->trans("Experimental"), 'style="float: left"');
304
}
305
if (preg_match('/deprecated/i', $version)) {
306
    $versiontrans .= img_warning($langs->trans("Deprecated"), 'style="float: left"');
307
}
308
$versiontrans .= $objMod->getVersion(1);
309
310
// Define imginfo
311
$imginfo = "info";
312
if ($objMod->isCoreOrExternalModule() == 'external') {
313
    $imginfo = "info_black";
314
}
315
316
// Define text of description of module
317
$text = '';
318
319
if ($mode == 'desc') {
320
    if ($moduledesc) {
321
        $text .= '<br>' . $moduledesc . '<br><br><br>';
322
    }
323
324
    $moduledescriptorfile = get_only_class($objMod) . '.class.php';
325
    $text .= '<span class="opacitymedium">' . $langs->trans("DescriptorFile") . ':</span> ' . $moduledescriptorfile;
326
327
    $text .= '<br><span class="opacitymedium">' . $langs->trans("IdModule") . ':</span> ' . $objMod->numero;
328
329
    $text .= '<br><span class="opacitymedium">' . $langs->trans("Version") . ':</span> ' . $version;
330
331
    $textexternal = '';
332
    if ($objMod->isCoreOrExternalModule() == 'external') {
333
        $tmpdirofmoduletoshow = preg_replace('/^' . preg_quote(DOL_DOCUMENT_ROOT, '/') . '/', '', $dirofmodule);
334
        $textexternal .= '<br><span class="opacitymedium">' . $langs->trans("Origin") . ':</span> ' . $langs->trans("ExternalModule") . ' - ' . $langs->trans("InstalledInto", $tmpdirofmoduletoshow);
335
336
        global $dolibarr_allow_download_external_modules;
337
        if (!empty($dolibarr_allow_download_external_modules) && preg_match('/\/custom\//', $dirofmodule)) {
338
            // Add a link to download a zip of the module
339
            $textexternal .= ' <a href="' . constant('BASE_URL') . '/admin/tools/export_files.php?export_type=externalmodule&what=' . urlencode($moduledir) . '&compression=zip&zipfilename_template=module_' . $moduledir . '-' . $version . '.notorig" target="_blank" rel="noopener">' . img_picto('', 'download') . '</a>';
340
        }
341
342
        if ($objMod->editor_name != 'dolibarr') {
343
            $textexternal .= '<br><span class="opacitymedium">' . $langs->trans("Publisher") . ':</span> ' . (empty($objMod->editor_name) ? $langs->trans("Unknown") : $objMod->editor_name);
344
        }
345
        $editor_url = $objMod->editor_url;
346
        if (!preg_match('/^http/', $editor_url)) {
347
            $editor_url = 'http://' . $editor_url;
348
        }
349
        if (!empty($objMod->editor_url) && !preg_match('/dolibarr\.org/i', $objMod->editor_url)) {
350
            $textexternal .= ($objMod->editor_name != 'dolibarr' ? ' - ' : '') . img_picto('', 'globe') . ' <a href="' . $editor_url . '" target="_blank" rel="noopener noreferrer external">' . $objMod->editor_url . '</a>';
351
        }
352
        $text .= $textexternal;
353
    } else {
354
        $text .= '<br><span class="opacitymedium">' . $langs->trans("Origin") . ':</span> ' . $langs->trans("Core");
355
        if (empty($objMod->numero)) {
356
            $text .= ' &nbsp; <span class="italic opacitymedium">(' . $langs->trans("AlwaysEnabled") . ')</span>';
357
        } elseif (!empty($objMod->enabled_bydefault)) {
358
            $text .= ' &nbsp; <span class="italic opacitymedium">(' . $langs->trans("EnabledByDefaultAtInstall") . ')</span>';
359
        }
360
        $text .= '<br>';
361
    }
362
    $text .= '<br>';
363
364
    $moduledesclong = $objMod->getDescLong();
365
    if ($moduledesclong) {
366
        $text .= '<br><hr><div class="moduledesclong">' . $moduledesclong . '<div>';
367
    }
368
}
369
370
if ($mode == 'feature') {
371
    $text .= '<br><strong>' . $langs->trans("DependsOn") . ':</strong> ';
372
    if (is_array($objMod->depends) && count($objMod->depends)) {
373
        $i = 0;
374
        foreach ($objMod->depends as $modulestringorarray) {
375
            if (is_array($modulestringorarray)) {
376
                $text .= ($i ? ', ' : '') . implode(', ', $modulestringorarray);
377
            } else {
378
                $text .= ($i ? ', ' : '') . $modulestringorarray;
379
            }
380
            $i++;
381
        }
382
    } else {
383
        $text .= '<span class="opacitymedium">' . $langs->trans("None") . '</span>';
384
    }
385
    $text .= '<br>';
386
387
    $text .= '<br><strong>' . $langs->trans("RequiredBy") . ':</strong> ';
388
    if (is_array($objMod->requiredby) && count($objMod->requiredby)) {
389
        $i = 0;
390
        foreach ($objMod->requiredby as $modulestringorarray) {
391
            if (is_array($modulestringorarray)) {
392
                $text .= ($i ? ', ' : '') . implode(', ', $modulestringorarray);
393
            } else {
394
                $text .= ($i ? ', ' : '') . $modulestringorarray;
395
            }
396
            $i++;
397
        }
398
    } else {
399
        $text .= '<span class="opacitymedium">' . $langs->trans("None") . '</span>';
400
    }
401
402
    $text .= '<br><br>';
403
404
    $text .= '<br><strong>' . $langs->trans("AddDataTables") . ':</strong> ';
405
    $listofsqlfiles1 = dol_dir_list(DOL_DOCUMENT_ROOT . '/install/mysql/tables/', 'files', 0, 'llx.*-' . $moduledir . '\.sql', array('\.key\.sql', '\.sql\.back'));
406
    $listofsqlfiles2 = dol_dir_list(dol_buildpath($moduledir . '/sql/'), 'files', 0, 'llx.*\.sql', array('\.key\.sql', '\.sql\.back'));
407
    $sqlfiles = array_merge($listofsqlfiles1, $listofsqlfiles2);
408
409
    if (count($sqlfiles) > 0) {
410
        $i = 0;
411
        foreach ($sqlfiles as $val) {
412
            $text .= ($i ? ', ' : '') . preg_replace('/\-' . $moduledir . '$/', '', preg_replace('/\.sql$/', '', preg_replace('/llx_/', '', $val['name'])));
413
            $i++;
414
        }
415
    } else {
416
        $text .= '<span class="opacitymedium">' . $langs->trans("No") . '</span>';
417
    }
418
419
    $text .= '<br>';
420
421
    $text .= '<br><strong>' . $langs->trans("AddDictionaries") . ':</strong> ';
422
    if (isset($objMod->dictionaries) && isset($objMod->dictionaries['tablib']) && is_array($objMod->dictionaries['tablib']) && count($objMod->dictionaries['tablib'])) {
423
        $i = 0;
424
        foreach ($objMod->dictionaries['tablib'] as $val) {
425
            $text .= ($i ? ', ' : '') . $val;
426
            $i++;
427
        }
428
    } else {
429
        $text .= '<span class="opacitymedium">' . $langs->trans("No") . '</span>';
430
    }
431
432
    $text .= '<br>';
433
434
    $text .= '<br><strong>' . $langs->trans("AddData") . ':</strong> ';
435
    $filedata = dol_buildpath($moduledir . '/sql/data.sql');
436
    if (dol_is_file($filedata)) {
437
        $text .= $langs->trans("Yes") . ' <span class="opacitymedium">(' . $moduledir . '/sql/data.sql)</span>';
438
    } else {
439
        $text .= '<span class="opacitymedium">' . $langs->trans("No") . '</span>';
440
    }
441
442
    $text .= '<br>';
443
444
    $text .= '<br><strong>' . $langs->trans("AddRemoveTabs") . ':</strong> ';
445
    if (isset($objMod->tabs) && is_array($objMod->tabs) && count($objMod->tabs)) {
446
        $i = 0;
447
        foreach ($objMod->tabs as $val) {
448
            if (is_array($val)) {
449
                $val = $val['data'];
450
            }
451
            if (is_string($val)) {
452
                $tmp = explode(':', $val, 3);
453
                $text .= ($i ? ', ' : '') . $tmp[0] . ':' . $tmp[1];
454
                $i++;
455
            }
456
        }
457
    } else {
458
        $text .= '<span class="opacitymedium">' . $langs->trans("No") . '</span>';
459
    }
460
461
    $text .= '<br>';
462
463
    $text .= '<br><strong>' . $langs->trans("AddModels") . ':</strong> ';
464
    if (isset($objMod->module_parts) && isset($objMod->module_parts['models']) && $objMod->module_parts['models']) {
465
        $text .= $langs->trans("Yes");
466
    } else {
467
        $text .= '<span class="opacitymedium">' . $langs->trans("No") . '</span>';
468
    }
469
470
    $text .= '<br>';
471
472
    $text .= '<br><strong>' . $langs->trans("AddSubstitutions") . ':</strong> ';
473
    if (isset($objMod->module_parts) && isset($objMod->module_parts['substitutions']) && $objMod->module_parts['substitutions']) {
474
        $text .= $langs->trans("Yes");
475
    } else {
476
        $text .= '<span class="opacitymedium">' . $langs->trans("No") . '</span>';
477
    }
478
479
    $text .= '<br>';
480
481
    $text .= '<br><strong>' . $langs->trans("AddSheduledJobs") . ':</strong> ';
482
    if (isset($objMod->cronjobs) && is_array($objMod->cronjobs) && count($objMod->cronjobs)) {
483
        $i = 0;
484
        foreach ($objMod->cronjobs as $val) {
485
            $text .= ($i ? ', ' : '') . ($val['label']);
486
            $i++;
487
        }
488
    } else {
489
        $text .= '<span class="opacitymedium">' . $langs->trans("No") . '</span>';
490
    }
491
492
    $text .= '<br>';
493
494
    $text .= '<br><strong>' . $langs->trans("AddTriggers") . ':</strong> ';
495
    $moreinfoontriggerfile = '';
496
    if (isset($objMod->module_parts) && isset($objMod->module_parts['triggers']) && $objMod->module_parts['triggers']) {
497
        $yesno = 'Yes';
498
    } else {
499
        $yesno = '<span class="opacitymedium">No</span>';
500
    }
501
    $interfaces = new Interfaces($db);
502
    $triggers = $interfaces->getTriggersList(array((($objMod->isCoreOrExternalModule() == 'external') ? '/' . $moduledir : '') . '/core/triggers'));
503
    foreach ($triggers as $triggercursor) {
504
        if ($triggercursor['module'] == $moduledir) {
505
            $yesno = 'Yes';
506
            $moreinfoontriggerfile = ' (' . $triggercursor['relpath'] . ')';
507
        }
508
    }
509
510
    $text .= $langs->trans($yesno) . $moreinfoontriggerfile;
511
512
    $text .= '<br>';
513
514
    $text .= '<br><strong>' . $langs->trans("AddBoxes") . ':</strong> ';
515
    if (isset($objMod->boxes) && is_array($objMod->boxes) && count($objMod->boxes)) {
516
        $i = 0;
517
        foreach ($objMod->boxes as $val) {
518
            $boxstring = (empty($val['file']) ? (empty($val[0]) ? '' : $val[0]) : $val['file']);
519
            if ($boxstring) {
520
                $text .= ($i ? ', ' : '') . $boxstring;
521
            }
522
            $i++;
523
        }
524
    } else {
525
        $text .= '<span class="opacitymedium">' . $langs->trans("No") . '</span>';
526
    }
527
528
    $text .= '<br>';
529
530
    $text .= '<br><strong>' . $langs->trans("AddHooks") . ':</strong> ';
531
    if (isset($objMod->module_parts) && isset($objMod->module_parts['hooks']) && is_array($objMod->module_parts['hooks']) && count($objMod->module_parts['hooks'])) {
532
        $i = 0;
533
        foreach ($objMod->module_parts['hooks'] as $key => $val) {
534
            if ($key === 'entity') {
535
                continue;
536
            }
537
538
            // For special values
539
            if ($key === 'data') {
540
                if (is_array($val)) {
541
                    foreach ($val as $value) {
542
                        $text .= ($i ? ', ' : '') . ($value);
543
                        $i++;
544
                    }
545
546
                    continue;
547
                }
548
            }
549
550
            $text .= ($i ? ', ' : '') . ($val);
551
            $i++;
552
        }
553
    } else {
554
        $text .= '<span class="opacitymedium">' . $langs->trans("No") . '</span>';
555
    }
556
557
    $text .= '<br>';
558
559
    $text .= '<br><strong>' . $langs->trans("AddPermissions") . ':</strong> ';
560
    if (isset($objMod->rights) && is_array($objMod->rights) && count($objMod->rights)) {
561
        $i = 0;
562
        foreach ($objMod->rights as $val) {
563
            $text .= ($i ? ', ' : '') . ($val[1]);
564
            $i++;
565
        }
566
    } else {
567
        $text .= '<span class="opacitymedium">' . $langs->trans("No") . '</span>';
568
    }
569
570
    $text .= '<br>';
571
572
    $text .= '<br><strong>' . $langs->trans("AddMenus") . ':</strong> ';
573
    if (isset($objMod->menu) && !empty($objMod->menu)) { // objMod can be an array or just an int 1
574
        $text .= $langs->trans("Yes");
575
    } else {
576
        $text .= '<span class="opacitymedium">' . $langs->trans("No") . '</span>';
577
    }
578
579
    $text .= '<br>';
580
581
    $text .= '<br><strong>' . $langs->trans("AddExportProfiles") . ':</strong> ';
582
    if (isset($objMod->export_label) && is_array($objMod->export_label) && count($objMod->export_label)) {
583
        $i = 0;
584
        foreach ($objMod->export_label as $val) {
585
            $text .= ($i ? ', ' : '') . ($val);
586
            $i++;
587
        }
588
    } else {
589
        $text .= '<span class="opacitymedium">' . $langs->trans("No") . '</span>';
590
    }
591
592
    $text .= '<br>';
593
594
    $text .= '<br><strong>' . $langs->trans("AddImportProfiles") . ':</strong> ';
595
    if (isset($objMod->import_label) && is_array($objMod->import_label) && count($objMod->import_label)) {
596
        $i = 0;
597
        foreach ($objMod->import_label as $val) {
598
            $text .= ($i ? ', ' : '') . ($val);
599
            $i++;
600
        }
601
    } else {
602
        $text .= '<span class="opacitymedium">' . $langs->trans("No") . '</span>';
603
    }
604
605
    $text .= '<br>';
606
607
    $text .= '<br><strong>' . $langs->trans("AddWebsiteTemplates") . ':</strong> ';
608
    if (isset($objMod->module_parts) && isset($objMod->module_parts['websitetemplates']) && $objMod->module_parts['websitetemplates']) {
609
        $text .= $langs->trans("Yes");
610
    } else {
611
        $text .= '<span class="opacitymedium">' . $langs->trans("No") . '</span>';
612
    }
613
614
    $text .= '<br>';
615
616
    $text .= '<br><strong>' . $langs->trans("AddOtherPagesOrServices") . ':</strong> ';
617
    $text .= '<span class="opacitymedium">' . $langs->trans("DetectionNotPossible") . '</span>';
618
}
619
620
621
if ($mode == 'changelog') {
622
    $changelog = $objMod->getChangeLog();
623
    if ($changelog) {
624
        $text .= '<div class="moduledesclong">' . $changelog . '<div>';
625
    } else {
626
        $text .= '<div class="moduledesclong"><span class="opacitymedium">' . $langs->trans("NotAvailable") . '</span></div>';
627
    }
628
}
629
630
print $text;
631
632
633
print dol_get_fiche_end();
634
635
print '</div>';
636
637
// End of page
638
ViewMain::llxFooter();
639
$db->close();
640