dolibarr 24.0.0-beta
modulehelp.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2017 Laurent Destailleur <eldy@users.sourceforge.net>
3 * Copyright (C) 2017 Regis Houssin <regis.houssin@inodbox.com>
4 * Copyright (C) 2022 Charlene Benke <charlene@patas-monkey.com>
5 * Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
6 * Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 */
21
27if (!defined('NOREQUIREMENU')) {
28 define('NOREQUIREMENU', '1'); // If there is no need to load and show top and left menu
29}
30if (!defined('NOTOKENRENEWAL')) {
31 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.
32}
33
34
35// Load Dolibarr environment
36require '../main.inc.php';
44require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
45require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
46require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
47
48// Load translation files required by the page
49$langs->loadLangs(array('errors', 'admin', 'modulebuilder', 'exports'));
50
51$mode = GETPOST('mode', 'alpha');
52$action = GETPOST('action', 'aZ09');
53$id = GETPOSTINT('id');
54if (empty($mode)) {
55 $mode = 'desc';
56}
57
58if (empty($user->admin)) {
60}
61
62
63
64/*
65 * Actions
66 */
67
68// Nothing
69
70
71/*
72 * View
73 */
74
75$form = new Form($db);
76
77$help_url = 'EN:First_setup|FR:Premiers_paramétrages|ES:Primeras_configuraciones';
78llxHeader('', $langs->trans("Setup"), $help_url, '', 0, 0, '', '', '', 'mod-admin page-modulehelp');
79
80print '<!-- Force style container -->'."\n".'<style>
81.id-container {
82 width: 100%;
83}
84#id-right {
85 padding-left: unset;
86}
87</style>';
88
89$arrayofnatures = array('core' => $langs->transnoentitiesnoconv("Core"), 'external' => $langs->transnoentitiesnoconv("External").' - '.$langs->trans("AllPublishers"));
90
91// Search modules dirs
92$modulesdir = dolGetModulesDirs();
93
94
95$filename = array();
96'@phan-var-force DolibarrModules[] $modules';
97$modules = array();
98$orders = array();
99$categ = array();
100$dirmod = array();
101$i = 0; // is a sequencer of modules found
102$j = 0; // j is module number. Automatically affected if module number not defined.
103$modNameLoaded = array();
104$familyinfo = array();
105
106foreach ($modulesdir as $dir) {
107 // Load modules attributes in arrays (name, numero, orders) from dir directory
108 //print $dir."\n<br>";
109 dol_syslog("Scan directory ".$dir." for module descriptor files (modXXX.class.php)");
110 $handle = @opendir($dir);
111 if (is_resource($handle)) {
112 while (($file = readdir($handle)) !== false) {
113 //print "$i ".$file."\n<br>";
114 if (is_readable($dir.$file) && substr($file, 0, 3) == 'mod' && substr($file, dol_strlen($file) - 10) == '.class.php') {
115 $modName = substr($file, 0, dol_strlen($file) - 10);
116
117 if ($modName) {
118 if (!empty($modNameLoaded[$modName])) {
119 $mesg = "Error: Module ".$modName." was found twice: Into ".$modNameLoaded[$modName]." and ".$dir.". You probably have an old file on your disk.<br>";
120 setEventMessages($mesg, null, 'warnings');
121 dol_syslog($mesg, LOG_ERR);
122 continue;
123 }
124
125 try {
126 $res = include_once $dir.$file;
127 if (class_exists($modName)) {
128 try {
129 $objMod = new $modName($db);
130 '@phan-var-force DolibarrModules $objMod';
131 $modNameLoaded[$modName] = $dir;
132
133 if (!$objMod->numero > 0 && $modName != 'modUser') {
134 dol_syslog('The module descriptor '.$modName.' must have a numero property', LOG_ERR);
135 }
136 $j = $objMod->numero;
137
138 $modulequalified = 1;
139
140 // We discard modules according to features level (PS: if module is activated we always show it)
141 $const_name = 'MAIN_MODULE_'.strtoupper(preg_replace('/^mod/i', '', get_class($objMod)));
142 if ($objMod->version == 'development' && (!getDolGlobalString($const_name) && (getDolGlobalInt('MAIN_FEATURES_LEVEL') < 2))) {
143 $modulequalified = 0;
144 }
145 if ($objMod->version == 'experimental' && (!getDolGlobalString($const_name) && (getDolGlobalInt('MAIN_FEATURES_LEVEL') < 1))) {
146 $modulequalified = 0;
147 }
148 if (preg_match('/deprecated/', $objMod->version) && (!getDolGlobalString($const_name) && (getDolGlobalInt('MAIN_FEATURES_LEVEL') >= 0))) {
149 $modulequalified = 0;
150 }
151
152 // We discard modules according to property disabled
153 //if (!empty($objMod->hidden)) $modulequalified=0;
154
155 if ($modulequalified > 0) {
156 $publisher = dol_escape_htmltag($objMod->getPublisher());
157 $external = ($objMod->isCoreOrExternalModule() == 'external');
158 if ($external) {
159 if ($publisher) {
160 $arrayofnatures['external_'.$publisher] = $langs->trans("External").' - '.$publisher;
161 } else {
162 $arrayofnatures['external_'] = $langs->trans("External").' - '.$langs->trans("UnknownPublishers");
163 }
164 }
165 ksort($arrayofnatures);
166 }
167
168 // Define an array $categ with categ with at least one qualified module
169 if ($modulequalified > 0) {
170 $modules[$i] = $objMod;
171 $filename[$i] = $modName;
172
173 // Gives the possibility to the module, to provide his own family info and position of this family
174 if (is_array($objMod->familyinfo) && !empty($objMod->familyinfo)) {
175 $familyinfo = array_merge($familyinfo, $objMod->familyinfo);
176 $familykey = key($objMod->familyinfo);
177 } else {
178 $familykey = $objMod->family;
179 }
180 if (empty($familykey) || $familykey === null) {
181 $familykey = 'other';
182 }
183
184 $moduleposition = ($objMod->module_position ? $objMod->module_position : '50');
185 if ($moduleposition == '50' && ($objMod->isCoreOrExternalModule() == 'external')) {
186 $moduleposition = '80'; // External modules at end by default
187 }
188
189 if (empty($familyinfo[$familykey]['position'])) {
190 $familyinfo[$familykey]['position'] = '0';
191 }
192
193 $orders[$i] = $familyinfo[$familykey]['position']."_".$familykey."_".$moduleposition."_".$j; // Sort by family, then by module position then number
194 $dirmod[$i] = $dir;
195 //print $i.'-'.$dirmod[$i].'<br>';
196 // Set categ[$i]
197 $specialstring = 'unknown';
198 if ($objMod->version == 'development' || $objMod->version == 'experimental') {
199 $specialstring = 'expdev';
200 }
201 if (isset($categ[$specialstring])) {
202 $categ[$specialstring]++; // Array of all different modules categories
203 } else {
204 $categ[$specialstring] = 1;
205 }
206 $j++;
207 $i++;
208 } else {
209 dol_syslog("Module ".get_class($objMod)." not qualified");
210 }
211 } catch (Exception $e) {
212 dol_syslog("Failed to load ".$dir.$file." ".$e->getMessage(), LOG_ERR);
213 }
214 } else {
215 // Skip warning for modules being refactored (class split in progress)
216 $silentModules = array('modSupplierOrder', 'modSupplierInvoice', 'modFournisseur');
217 if (!in_array($modName, $silentModules)) {
218 print info_admin("admin/modules.php Warning bad descriptor file : ".$dir.$file." (Class ".$modName." not found into file)", 0, 0, '1', 'warning');
219 }
220 }
221 } catch (Exception $e) {
222 dol_syslog("Failed to load ".$dir.$file." ".$e->getMessage(), LOG_ERR);
223 }
224 }
225 }
226 }
227 closedir($handle);
228 } else {
229 dol_syslog("htdocs/admin/modulehelp.php: Failed to open directory ".$dir.". See permission and open_basedir option.", LOG_WARNING);
230 }
231}
232
233asort($orders);
234//var_dump($orders);
235//var_dump($categ);
236//var_dump($modules);
237
238
239$objMod = null;
240$dirofmodule = null;
241$key = -1;
242$i = 0;
243foreach ($orders as $tmpkey => $tmpvalue) {
244 $tmpMod = $modules[$tmpkey];
245 '@phan-var-force DolibarrModules $tmpMod';
246 if ($tmpMod->numero == $id) {
247 $key = $i;
248 $modName = $filename[$tmpkey];
249 $dirofmodule = $dirmod[$tmpkey];
250 $objMod = $tmpMod;
251 break;
252 }
253 $i++;
254}
255if (!is_object($objMod)) {
256 $msg = __FILE__." Module with no found for id:".$id;
257 dol_syslog($msg, LOG_ERR);
258 return;
259}
260
261$value = $orders[$key];
262$tab = explode('_', $value);
263$familyposition = $tab[0];
264$familykey = $tab[1];
265$module_position = $tab[2];
266$numero = $tab[3];
267
268
269
270$head = modulehelp_prepare_head($objMod);
271
272// Check filters
273$modulename = $objMod->getName();
274$moduledesc = $objMod->getDesc(1);
275$moduleauthor = $objMod->getPublisher();
276$moduledir = strtolower(preg_replace('/^mod/i', '', get_class($objMod)));
277
278$const_name = 'MAIN_MODULE_'.strtoupper(preg_replace('/^mod/i', '', get_class($objMod)));
279
280$text = '<span class="opacitymedium">'.$langs->trans("LastActivationDate").':</span> ';
281if (getDolGlobalString($const_name)) {
282 $text .= dol_print_date($objMod->getLastActivationDate(), 'dayhour');
283} else {
284 $text .= $langs->trans("Disabled");
285}
286$tmp = $objMod->getLastActivationInfo();
287$authorid = (empty($tmp['authorid']) ? '' : $tmp['authorid']);
288if ($authorid > 0) {
289 $tmpuser = new User($db);
290 $tmpuser->fetch($authorid);
291 $text .= '<br><span class="opacitymedium">'.$langs->trans("LastActivationAuthor").':</span> ';
292 $text .= $tmpuser->getNomUrl(-1);
293}
294$ip = (empty($tmp['ip']) ? '' : $tmp['ip']);
295if ($ip) {
296 $text .= '<br><span class="opacitymedium">'.$langs->trans("LastActivationIP").':</span> ';
297 $text .= $ip;
298}
299$lastactivationversion = (empty($tmp['lastactivationversion']) ? '' : $tmp['lastactivationversion']);
300if ($lastactivationversion && $lastactivationversion != 'dolibarr') {
301 $text .= '<br><span class="opacitymedium">'.$langs->trans("LastActivationVersion").':</span> ';
302 $text .= $lastactivationversion;
303}
304
305$moreinfo = $text;
306
307$title = ($modulename ? $modulename : $moduledesc);
308
309print '<div class="centpercent">';
310
311$picto = 'object_'.$objMod->picto;
312
313print load_fiche_titre($title, $moreinfo, $picto, 0, '', 'titlemodulehelp');
314print '<br>';
315
316print dol_get_fiche_head($head, $mode, '', -1);
317
318if (!$modulename) {
319 dol_syslog("Error for module ".$key." - Property name of module looks empty", LOG_WARNING);
320}
321
322// Load all lang files of module
323if (isset($objMod->langfiles) && is_array($objMod->langfiles)) {
324 foreach ($objMod->langfiles as $domain) {
325 $langs->load($domain);
326 }
327}
328
329
330
331
332// Version (with picto warning or not)
333$version = $objMod->getVersion(0);
334$versiontrans = '';
335if (preg_match('/development/i', $version)) {
336 $versiontrans .= img_warning($langs->trans("Development"), 'style="float: left"');
337}
338if (preg_match('/experimental/i', $version)) {
339 $versiontrans .= img_warning($langs->trans("Experimental"), 'style="float: left"');
340}
341if (preg_match('/deprecated/i', $version)) {
342 $versiontrans .= img_warning($langs->trans("Deprecated"), 'style="float: left"');
343}
344$versiontrans .= $objMod->getVersion(1);
345
346// Define imginfo
347$imginfo = "info";
348if ($objMod->isCoreOrExternalModule() == 'external') {
349 $imginfo = "info_black";
350}
351
352// Define text of description of module
353$text = '';
354
355if ($mode == 'desc') {
356 if ($moduledesc) {
357 $text .= '<br>'.$moduledesc.'<br><br><br>';
358 }
359
360 $moduledescriptorfile = get_class($objMod).'.class.php';
361 $text .= '<span class="opacitymedium">'.$langs->trans("DescriptorFile").':</span> '.$moduledescriptorfile;
362
363 $text .= '<br><span class="opacitymedium">'.$langs->trans("IdModule").':</span> '.$objMod->numero;
364
365 $textexternal = '';
366 if ($objMod->isCoreOrExternalModule() == 'external') {
367 $tmpdirofmoduletoshow = preg_replace('/^'.preg_quote(DOL_DOCUMENT_ROOT, '/').'/', '', (string) $dirofmodule);
368 $textexternal .= '<br><span class="opacitymedium">'.$langs->trans("Origin").':</span> '.$langs->trans("ExternalModule").' - '.$langs->trans("InstalledInto", $tmpdirofmoduletoshow);
369
370 $installmoduleslock = DOL_DATA_ROOT.'/installmodules.lock';
371 global $dolibarr_allow_download_external_modules;
372 if ((!file_exists($installmoduleslock) || !empty($dolibarr_allow_download_external_modules)) && preg_match('/\/custom\//', (string) $dirofmodule)) {
373 // Add a link to download a zip of the module
374 $textexternal .= ' <a href="'.DOL_URL_ROOT.'/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>';
375 } else {
376 // Add a link to download a zip of the module
377 $textexternal .= img_picto($langs->trans("DownloadOfModuleFileDisallowed"), 'download', 'class="opacitymedium paddingleft"');
378 }
379
380 if ($objMod->editor_name != 'dolibarr') {
381 $textexternal .= '<br><span class="opacitymedium">'.$langs->trans("Publisher").':</span> '.(empty($objMod->editor_name) ? $langs->trans("Unknown") : $objMod->editor_name);
382 }
383 $editor_url = $objMod->editor_url;
384 if (!preg_match('/^http/', $editor_url)) {
385 $editor_url = 'https://'.$editor_url;
386 }
387 $editor_url_to_show = preg_replace('/(utm_[a-z_]+|origin)=[a-z0-9_]+/i', '', $editor_url);
388 $editor_url_to_show = preg_replace('/[\/\?]+$/', '', $editor_url_to_show);
389 if (!empty($objMod->editor_url) && !preg_match('/dolibarr\.org/i', $objMod->editor_url)) {
390 $textexternal .= ($objMod->editor_name != 'dolibarr' ? ' - ' : '').img_picto('', 'globe').' <a href="'.$editor_url.'" target="_blank" rel="noopener noreferrer external">'.$editor_url_to_show.'</a>';
391 }
392 $text .= $textexternal;
393 } else {
394 $text .= '<br><span class="opacitymedium">'.$langs->trans("Origin").':</span> '.$langs->trans("Core");
395 if (empty($objMod->numero)) {
396 $text .= ' &nbsp; <span class="italic opacitymedium">('.$langs->trans("AlwaysEnabled").')</span>';
397 } elseif (!empty($objMod->enabled_bydefault)) {
398 $text .= ' &nbsp; <span class="italic opacitymedium">('.$langs->trans("EnabledByDefaultAtInstall").')</span>';
399 }
400 }
401
402 $text .= '<br><span class="opacitymedium">'.$langs->trans("Version").':</span> '.$version;
403
404 $text .= '<br>';
405
406 $moduledesclong = $objMod->getDescLong();
407 if ($moduledesclong) {
408 $text .= '<br><hr><div class="moduledesclong">'.$moduledesclong.'<div>';
409 }
410}
411
412if ($mode == 'feature') {
413 $text .= '<br><strong>'.$langs->trans("DependsOn").':</strong> ';
414 if (is_array($objMod->depends) && count($objMod->depends)) {
415 $i = 0;
416 foreach ($objMod->depends as $modulestringorarray) {
417 if (is_array($modulestringorarray)) {
418 $text .= ($i ? ', ' : img_picto('', 'tick', 'class="pictofixedwidth"')).implode(', ', $modulestringorarray);
419 } else {
420 $text .= ($i ? ', ' : img_picto('', 'tick', 'class="pictofixedwidth"')).$modulestringorarray;
421 }
422 $i++;
423 }
424 } else {
425 $text .= '<span class="opacitymedium">'.$langs->trans("None").'</span>';
426 }
427 $text .= '<br>';
428
429 $text .= '<br><strong>'.$langs->trans("RequiredBy").':</strong> ';
430 if (is_array($objMod->requiredby) && count($objMod->requiredby)) {
431 $i = 0;
432 foreach ($objMod->requiredby as $modulestringorarray) {
433 if (is_array($modulestringorarray)) {
434 $text .= ($i ? ', ' : img_picto('', 'tick', 'class="pictofixedwidth"')).implode(', ', $modulestringorarray);
435 } else {
436 $text .= ($i ? ', ' : img_picto('', 'tick', 'class="pictofixedwidth"')).$modulestringorarray;
437 }
438 $i++;
439 }
440 } else {
441 $text .= '<span class="opacitymedium">'.$langs->trans("None").'</span>';
442 }
443
444 $text .= '<br><br>';
445
446 $text .= '<br><strong>'.$langs->trans("AddDataTables").':</strong> ';
447 $listofsqlfiles1 = dol_dir_list(DOL_DOCUMENT_ROOT.'/install/mysql/tables/', 'files', 0, 'llx.*-'.$moduledir.'\.sql', array('\.key\.sql', '\.sql\.back'));
448 $listofsqlfiles2 = dol_dir_list(dol_buildpath($moduledir.'/sql/'), 'files', 0, 'llx.*\.sql', array('\.key\.sql', '\.sql\.back'));
449 $sqlfiles = array_merge($listofsqlfiles1, $listofsqlfiles2);
450
451 if (count($sqlfiles) > 0) {
452 $i = 0;
453 foreach ($sqlfiles as $val) {
454 $text .= ($i ? ', ' : img_picto('', 'tick', 'class="pictofixedwidth"')).preg_replace('/\-'.$moduledir.'$/', '', preg_replace('/\.sql$/', '', preg_replace('/llx_/', '', $val['name'])));
455 $i++;
456 }
457 } else {
458 $text .= '<span class="opacitymedium">'.$langs->trans("No").'</span>';
459 }
460
461 $text .= '<br>';
462
463 $text .= '<br><strong>'.$langs->trans("AddDictionaries").':</strong> ';
464 if (isset($objMod->dictionaries) && isset($objMod->dictionaries['tablib']) && is_array($objMod->dictionaries['tablib']) && count($objMod->dictionaries['tablib'])) {
465 $i = 0;
466 foreach ($objMod->dictionaries['tablib'] as $val) {
467 $text .= ($i ? ', ' : img_picto('', 'tick', 'class="pictofixedwidth"')).$val;
468 $i++;
469 }
470 } else {
471 $text .= '<span class="opacitymedium">'.$langs->trans("No").'</span>';
472 }
473
474 $text .= '<br>';
475
476 $text .= '<br><strong>'.$langs->trans("AddData").':</strong> ';
477 $filedata = dol_buildpath($moduledir.'/sql/data.sql');
478 if (dol_is_file($filedata)) {
479 $text .= img_picto('', 'tick', 'class="pictofixedwidth"').$langs->trans("Yes").' <span class="opacitymedium">('.$moduledir.'/sql/data.sql)</span>';
480 } else {
481 $text .= '<span class="opacitymedium">'.$langs->trans("No").'</span>';
482 }
483
484 $text .= '<br>';
485
486 $text .= '<br><strong>'.$langs->trans("AddRemoveTabs").':</strong> ';
487 if (isset($objMod->tabs) && is_array($objMod->tabs) && count($objMod->tabs)) {
488 $i = 0;
489 foreach ($objMod->tabs as $val) {
490 if (is_array($val)) {
491 $val = $val['data'];
492 }
493 if (is_string($val)) {
494 $tmp = explode(':', $val, 3);
495 $text .= ($i ? ', ' : '').$tmp[0].':'.$tmp[1];
496 $i++;
497 }
498 }
499 } else {
500 $text .= '<span class="opacitymedium">'.$langs->trans("No").'</span>';
501 }
502
503 $text .= '<br>';
504
505 $text .= '<br><strong>'.$langs->trans("AddModels").':</strong> ';
506 if (isset($objMod->module_parts) && isset($objMod->module_parts['models']) && $objMod->module_parts['models']) {
507 $text .= img_picto('', 'tick', 'class="pictofixedwidth"').$langs->trans("Yes");
508 } else {
509 $text .= '<span class="opacitymedium">'.$langs->trans("No").'</span>';
510 }
511
512 $text .= '<br>';
513
514 $text .= '<br><strong>'.$langs->trans("AddSubstitutions").':</strong> ';
515 if (isset($objMod->module_parts) && isset($objMod->module_parts['substitutions']) && $objMod->module_parts['substitutions']) {
516 $text .= img_picto('', 'tick', 'class="pictofixedwidth"').$langs->trans("Yes");
517 } else {
518 $text .= '<span class="opacitymedium">'.$langs->trans("No").'</span>';
519 }
520
521 $text .= '<br>';
522
523 $text .= '<br><strong>'.$langs->trans("AddSheduledJobs").':</strong> ';
524 if (isset($objMod->cronjobs) && is_array($objMod->cronjobs) && count($objMod->cronjobs)) {
525 $i = 0;
526 foreach ($objMod->cronjobs as $val) {
527 $text .= ($i ? ', ' : img_picto('', 'tick', 'class="pictofixedwidth"')).$langs->trans($val['label']);
528 $i++;
529 }
530 } else {
531 $text .= '<span class="opacitymedium">'.$langs->trans("No").'</span>';
532 }
533
534 $text .= '<br>';
535
536 $text .= '<br><strong>'.$langs->trans("AddTriggers").':</strong> ';
537 $moreinfoontriggerfile = '';
538 if (isset($objMod->module_parts) && isset($objMod->module_parts['triggers']) && $objMod->module_parts['triggers']) {
539 $yesno = 'Yes';
540 } else {
541 $yesno = '<span class="opacitymedium">'.$langs->trans("No").'</span>';
542 }
543 require_once DOL_DOCUMENT_ROOT.'/core/class/interfaces.class.php';
544 $interfaces = new Interfaces($db);
545 $triggers = $interfaces->getTriggersList(array((($objMod->isCoreOrExternalModule() == 'external') ? '/'.$moduledir : '').'/core/triggers'));
546 foreach ($triggers as $triggercursor) {
547 if ($triggercursor['module'] == $moduledir) {
548 $yesno = 'Yes';
549 $moreinfoontriggerfile = ' ('.$triggercursor['relpath'].')';
550 }
551 }
552
553 $text .= ($yesno == 'Yes' ? img_picto('', 'tick', 'class="pictofixedwidth"') : '').$langs->trans($yesno).$moreinfoontriggerfile;
554
555 $text .= '<br>';
556
557 $text .= '<br><strong>'.$langs->trans("AddBoxes").':</strong> ';
558 if (isset($objMod->boxes) && is_array($objMod->boxes) && count($objMod->boxes)) {
559 $i = 0;
560 foreach ($objMod->boxes as $val) {
561 $boxstring = (empty($val['file']) ? (empty($val[0]) ? '' : $val[0]) : $val['file']);
562 if ($boxstring) {
563 $text .= ($i ? ', ' : img_picto('', 'tick', 'class="pictofixedwidth"')).$boxstring;
564 }
565 $i++;
566 }
567 } else {
568 $text .= '<span class="opacitymedium">'.$langs->trans("No").'</span>';
569 }
570
571 $text .= '<br>';
572
573 $text .= '<br><strong>'.$langs->trans("AddHooks").':</strong> ';
574 if (isset($objMod->module_parts) && isset($objMod->module_parts['hooks']) && is_array($objMod->module_parts['hooks']) && count($objMod->module_parts['hooks'])) {
575 $i = 0;
576 foreach ($objMod->module_parts['hooks'] as $key => $val) {
577 if ($key === 'entity') {
578 continue;
579 }
580
581 // For special values
582 if ($key === 'data') {
583 if (is_array($val)) {
584 foreach ($val as $value) {
585 $text .= ($i ? ', ' : img_picto('', 'tick', 'class="pictofixedwidth"')).($value);
586 $i++;
587 }
588
589 continue;
590 }
591 }
592
593 $text .= ($i ? ', ' : img_picto('', 'tick', 'class="pictofixedwidth"')).($val);
594 $i++;
595 }
596 } else {
597 $text .= '<span class="opacitymedium">'.$langs->trans("No").'</span>';
598 }
599
600 $text .= '<br>';
601
602 $text .= '<br><strong>'.$langs->trans("AddPermissions").':</strong> ';
603 if (isset($objMod->rights) && is_array($objMod->rights) && count($objMod->rights)) {
604 $i = 0;
605 foreach ($objMod->rights as $val) {
606 $text .= ($i ? ', ' : img_picto('', 'tick', 'class="pictofixedwidth"')).($val[1]);
607 $i++;
608 }
609 } else {
610 $text .= '<span class="opacitymedium">'.$langs->trans("No").'</span>';
611 }
612
613 $text .= '<br>';
614
615 $text .= '<br><strong>'.$langs->trans("AddMenus").':</strong> ';
616 if (isset($objMod->menu) && !empty($objMod->menu)) { // objMod can be an array or just an int 1
617 $text .= img_picto('', 'tick', 'class="pictofixedwidth"').$langs->trans("Yes");
618 } else {
619 $text .= '<span class="opacitymedium">'.$langs->trans("No").'</span>';
620 }
621
622 $text .= '<br>';
623
624 $text .= '<br><strong>'.$langs->trans("AddExportProfiles").':</strong> ';
625 if (isset($objMod->export_label) && is_array($objMod->export_label) && count($objMod->export_label)) {
626 $i = 0;
627 foreach ($objMod->export_label as $val) {
628 $text .= ($i ? ', ' : img_picto('', 'tick', 'class="pictofixedwidth"')).$langs->trans($val);
629 $i++;
630 }
631 } else {
632 $text .= '<span class="opacitymedium">'.$langs->trans("No").'</span>';
633 }
634
635 $text .= '<br>';
636
637 $text .= '<br><strong>'.$langs->trans("AddImportProfiles").':</strong> ';
638 if (isset($objMod->import_label) && is_array($objMod->import_label) && count($objMod->import_label)) {
639 $i = 0;
640 foreach ($objMod->import_label as $val) {
641 $text .= ($i ? ', ' : img_picto('', 'tick', 'class="pictofixedwidth"')).$langs->trans($val);
642 $i++;
643 }
644 } else {
645 $text .= '<span class="opacitymedium">'.$langs->trans("No").'</span>';
646 }
647
648 $text .= '<br>';
649
650 $text .= '<br><strong>'.$langs->trans("AddWebsiteTemplates").':</strong> ';
651 if (isset($objMod->module_parts) && isset($objMod->module_parts['websitetemplates']) && $objMod->module_parts['websitetemplates']) {
652 $text .= img_picto('', 'tick', 'class="pictofixedwidth"').$langs->trans("Yes");
653 } else {
654 $text .= '<span class="opacitymedium">'.$langs->trans("No").'</span>';
655 }
656
657 $text .= '<br>';
658
659 $text .= '<br><strong>'.$langs->trans("AddOtherPagesOrServices").':</strong> ';
660 $text .= '<span class="opacitymedium">'.$langs->trans("DetectionNotPossible").'</span>';
661}
662
663
664if ($mode == 'changelog') {
665 $changelog = $objMod->getChangeLog();
666 if ($changelog) {
667 $text .= '<div class="moduledesclong">'.$changelog.'<div>';
668 } else {
669 $text .= '<div class="moduledesclong"><span class="opacitymedium">'.$langs->trans("NotAvailable").'</span></div>';
670 }
671}
672
673print $text;
674
675
676print dol_get_fiche_end();
677
678print '</div>';
679
680// End of page
681llxFooter();
682$db->close();
$id
Support class for third parties, contacts, members, users or resources.
Definition account.php:47
modulehelp_prepare_head($object)
Prepare array with list of tabs.
llxFooter($comment='', $zone='private', $disabledoutputofmessages=0)
Empty footer.
Definition wrapper.php:91
if(!defined('NOREQUIRESOC')) if(!defined( 'NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined( 'NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined( 'NOREQUIREAJAX')) llxHeader($head='', $title='', $help_url='', $target='', $disablejs=0, $disablehead=0, $arrayofjs='', $arrayofcss='', $morequerystring='', $morecssonbody='', $replacemainareaby='', $disablenofollow=0, $disablenoindex=0)
Empty header.
Definition wrapper.php:73
Class to manage generation of HTML components Only common components must be here.
Class to manage triggers.
Class to manage Dolibarr users.
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $db
API class for accounts.
dol_is_file($pathoffile)
Return if path is a file.
dol_dir_list($utf8_path, $types="all", $recursive=0, $filter="", $excludefilter=null, $sortcriteria="name", $sortorder=SORT_ASC, $mode=0, $nohook=0, $relativename="", $donotfollowsymlinks=0, $nbsecondsold=0)
Scan a directory and return a list of files/directories.
Definition files.lib.php:64
dolGetModulesDirs($subdir='')
Return list of directories that contain modules.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0, $attop=0)
Set event messages in dol_events session object.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2, $allowothertags=array())
Show picto whatever it's its name (generic function)
img_warning($titlealt='default', $moreatt='', $morecss='pictowarning')
Show warning logo.
info_admin($text, $infoonimgalt=0, $nodiv=0, $admin='1', $morecss='hideonsmartphone', $textfordropdown='', $picto='', $textonpictotooltip='')
Show information in HTML for admin users or standard users.
GETPOSTINT($paramname, $method=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
dol_get_fiche_head($links=array(), $active='', $title='', $notab=0, $picto='', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limittoshow=0, $moretabssuffix='', $dragdropfile=0, $morecssdiv='')
Show tabs of a record.
dol_get_fiche_end($notab=0)
Return tab footer of a card.
dol_strlen($string, $stringencoding='UTF-8')
Make a strlen call.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false, $decorate=0)
Output date in a string format according to outputlangs (or langs if not defined).
load_fiche_titre($title, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='', $morecssonpicto='widthpictotitle')
Load a title with picto.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
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...
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program.