dolibarr 20.0.0
modules.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2005-2009 Laurent Destailleur <eldy@users.sourceforge.net>
3 * Copyright (C) 2007 Rodolphe Quiedeville <rodolphe@quiedeville.org>
4 * Copyright (C) 2010-2012 Regis Houssin <regis.houssin@inodbox.com>
5 * Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
26// Load Dolibarr environment
27require '../../main.inc.php';
28require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
29
30if (empty($user->admin)) {
32}
33
34// Load translation files required by the page
35$langs->loadLangs(array("install", "other", "admin"));
36
37$optioncss = GETPOST('optioncss', 'alpha');
38$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'moduleoverview';
39
40$search_name = GETPOST("search_name", 'alpha');
41$search_id = GETPOST("search_id", 'alpha');
42$search_version = GETPOST("search_version", 'alpha');
43$search_permission = GETPOST("search_permission", 'alpha');
44
45$sortfield = GETPOST('sortfield', 'aZ09comma');
46$sortorder = GETPOST('sortorder', 'aZ09comma');
47
48if (!$sortfield) {
49 $sortfield = "id";
50}
51if (!$sortorder) {
52 $sortorder = "asc";
53}
54
55// Initialize technical object to manage hooks. Note that conf->hooks_modules contains array of hooks
56$hookmanager->initHooks(array('moduleoverview'));
57$form = new Form($db);
58$object = new stdClass();
59
60// Definition of fields for lists
61$arrayfields = array(
62 'name' => array('label' => $langs->trans("Modules"), 'checked' => 1, 'position' => 10),
63 'version' => array('label' => $langs->trans("Version"), 'checked' => 1, 'position' => 20),
64 'id' => array('label' => $langs->trans("IdModule"), 'checked' => 1, 'position' => 30),
65 'module_position' => array('label' => $langs->trans("Position"), 'checked' => 1, 'position' => 35),
66 'permission' => array('label' => $langs->trans("IdPermissions"), 'checked' => 1, 'position' => 40)
67);
68
69$arrayfields = dol_sort_array($arrayfields, 'position');
70'@phan-var-force array<string,array{label:string,checked:int<0,1>,position:int}> $arrayfields';
71
72$param = '';
73$info_admin = '';
74
75/*
76 * Actions
77 */
78
79$parameters = array();
80$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
81if ($reshook < 0) {
82 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
83}
84
85if (empty($reshook)) {
86 // Selection of new fields
87 include DOL_DOCUMENT_ROOT.'/core/actions_changeselectedfields.inc.php';
88}
89
90
91// Load list of modules
92$moduleList = array();
93$modules = array();
94$modules_files = array();
95$modules_fullpath = array();
96$modulesdir = dolGetModulesDirs();
97$rights_ids = array();
98$arrayofpermissions = array();
99
100foreach ($modulesdir as $dir) {
101 $handle = @opendir(dol_osencode($dir));
102 if (is_resource($handle)) {
103 while (($file = readdir($handle)) !== false) {
104 if (is_readable($dir.$file) && substr($file, 0, 3) == 'mod' && substr($file, dol_strlen($file) - 10) == '.class.php') {
105 $modName = substr($file, 0, dol_strlen($file) - 10);
106
107 if ($modName) {
108 //print 'xx'.$dir.$file.'<br>';
109 if (in_array($file, $modules_files)) {
110 // File duplicate
111 print "Warning duplicate file found : ".$file." (Found ".$dir.$file.", already found ".$modules_fullpath[$file].")<br>";
112 } else {
113 // File to load
114 $res = include_once $dir.$file;
115 if (class_exists($modName)) {
116 try {
117 $objMod = new $modName($db);
118 '@phan-var-force DolibarrModules $objMod';
119
120 $modules[$objMod->numero] = $objMod;
121 $modules_files[$objMod->numero] = $file;
122 $modules_fullpath[$file] = $dir.$file;
123 } catch (Exception $e) {
124 dol_syslog("Failed to load ".$dir.$file." ".$e->getMessage(), LOG_ERR);
125 }
126 } else {
127 $info_admin .= info_admin("Warning bad descriptor file : ".$dir.$file." (Class ".$modName." not found into file)", 0, 0, '1', 'warning');
128 }
129 }
130 }
131 }
132 }
133 closedir($handle);
134 }
135}
136'@phan-var-force array<string,DolibarrModules> $modules';
137
138// create pre-filtered list for modules
139foreach ($modules as $key => $module) {
140 $newModule = new stdClass();
141
142 $newModule->name = $module->getName();
143 $newModule->version = $module->getVersion();
144 $newModule->id = $key;
145 $newModule->module_position = $module->getModulePosition();
146
147 $alt = $module->name.' - '.$modules_files[$key];
148
149 if (!empty($module->picto)) {
150 if (preg_match('/^\//', $module->picto)) {
151 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
152 $newModule->picto = img_picto($alt, $module->picto, 'width="14px"', 1);
153 } else {
154 $newModule->picto = img_object($alt, $module->picto, 'width="14px"');
155 }
156 } else {
157 $newModule->picto = img_object($alt, 'generic', 'width="14px"');
158 }
159
160 $permission = array();
161 if ($module->rights) {
162 foreach ($module->rights as $rights) {
163 if (empty($rights[0])) {
164 continue;
165 }
166 $arrayofpermissions[$rights[0]] = array('label' => 'user->hasRight(\''.$module->rights_class.'\', \''.$rights[4].'\''.(empty($rights[5]) ? '' : ', \''.$rights[5].'\'').')');
167 $permission[] = $rights[0];
168
169 array_push($rights_ids, $rights[0]);
170 }
171 }
172
173 $newModule->permission = $permission;
174
175 // pre-filter list
176 if (!empty($search_name) && !stristr($newModule->name, $search_name)) {
177 continue;
178 }
179 if (!empty($search_version) && !stristr($newModule->version, $search_version)) {
180 continue;
181 }
182 if (!empty($search_id) && !stristr($newModule->id, $search_id)) {
183 continue;
184 }
185
186 if (!empty($search_permission)) {
187 $found = false;
188
189 foreach ($newModule->permission as $permission) {
190 if (stristr($permission, $search_permission)) {
191 $found = true;
192 break;
193 }
194 }
195
196 if (!$found) {
197 continue;
198 }
199 }
200
201 $moduleList[] = $newModule;
202}
203
204
205
206/*
207 * View
208 */
209
210llxHeader('', '', '', '', 0, 0, '', '', '', 'mod-admin page-system_modules');
211print $info_admin;
212print '<form action="'.$_SERVER["PHP_SELF"].'" method="post" name="formulaire">';
213if ($optioncss != '') {
214 print '<input type="hidden" name="optioncss" value="'.$optioncss.'">';
215}
216print '<input type="hidden" name="token" value="'.newToken().'">';
217print '<input type="hidden" name="formfilteraction" id="formfilteraction" value="list">';
218print '<input type="hidden" name="action" value="list">';
219print '<input type="hidden" name="sortfield" value="'.$sortfield.'">';
220print '<input type="hidden" name="sortorder" value="'.$sortorder.'">';
221print '<input type="hidden" name="contextpage" value="'.$contextpage.'">';
222
223print_barre_liste($langs->trans("AvailableModules"), empty($page) ? 0 : $page, $_SERVER["PHP_SELF"], '', $sortfield, $sortorder, '', -1, '', 'title_setup', 0, '', '', 0, 1, 1);
224
225print '<span class="opacitymedium">'.$langs->trans("ToActivateModule").'</span>';
226print '<br>';
227print '<br>';
228
229$mode = '';
230$arrayofmassactions = array();
231
232$varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage;
233$htmlofselectarray = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage, getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')); // This also change content of $arrayfields with user setup
234$selectedfields = ($mode != 'kanban' ? $htmlofselectarray : '');
235$selectedfields .= (count($arrayofmassactions) ? $form->showCheckAddButtons('checkforselect', 1) : '');
236
237$moreforfilter = '';
238
239print '<div class="div-table-responsive-no-min">';
240print '<table class="tagtable nobottomiftotal liste'.($moreforfilter ? " listwithfilterbefore" : "").'">'."\n";
241
242// Lines with input filters
243print '<tr class="liste_titre_filter">';
244// Action column
245if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
246 print '<td class="liste_titre center maxwidthsearch">';
247 $searchpicto = $form->showFilterButtons();
248 print $searchpicto;
249 print '</td>';
250}
251if ($arrayfields['name']['checked']) {
252 print '<td class="liste_titre left">';
253 print '<input class="flat" type="text" name="search_name" size="8" value="'.dol_escape_htmltag($search_name).'">';
254 print '</td>';
255}
256if ($arrayfields['version']['checked']) {
257 print '<td class="liste_titre left">';
258 print '<input class="flat" type="text" name="search_version" size="6" value="'.dol_escape_htmltag($search_version).'">';
259 print '</td>';
260}
261if ($arrayfields['id']['checked']) {
262 print '<td class="liste_titre left">';
263 print '<input class="flat" type="text" name="search_id" size="6" value="'.dol_escape_htmltag($search_id).'">';
264 print '</td>';
265}
266if ($arrayfields['permission']['checked']) {
267 print '<td class="liste_titre left">';
268 print '<input class="flat" type="text" name="search_permission" size="8" value="'.dol_escape_htmltag($search_permission).'">';
269 print '</td>';
270}
271if ($arrayfields['module_position']['checked']) {
272 print '<td class="liste_titre left">';
273 print '</td>';
274}
275// Action column
276if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
277 print '<td class="liste_titre center maxwidthsearch">';
278 $searchpicto = $form->showFilterButtons();
279 print $searchpicto;
280 print '</td>';
281}
282print '</tr>';
283
284print '<tr class="liste_titre">';
285// Action column
286if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
287 print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch actioncolumn');
288}
289if ($arrayfields['name']['checked']) {
290 print_liste_field_titre($arrayfields['name']['label'], $_SERVER["PHP_SELF"], "name", "", "", "", $sortfield, $sortorder);
291}
292if ($arrayfields['version']['checked']) {
293 print_liste_field_titre($arrayfields['version']['label'], $_SERVER["PHP_SELF"], "version", "", "", "", $sortfield, $sortorder);
294}
295if ($arrayfields['id']['checked']) {
296 print_liste_field_titre($arrayfields['id']['label'], $_SERVER["PHP_SELF"], "id", "", "", "", $sortfield, $sortorder, 'nowraponall ');
297}
298if ($arrayfields['permission']['checked']) {
299 print_liste_field_titre($arrayfields['permission']['label'], $_SERVER["PHP_SELF"], "permission", "", "", "", $sortfield, $sortorder);
300}
301if ($arrayfields['module_position']['checked']) {
302 print_liste_field_titre($arrayfields['module_position']['label'], $_SERVER["PHP_SELF"], "module_position", "", "", "", $sortfield, $sortorder);
303}
304
305// Fields from hook
306$parameters = array('arrayfields' => $arrayfields, 'param' => $param, 'sortfield' => $sortfield, 'sortorder' => $sortorder);
307$reshook = $hookmanager->executeHooks('printFieldListOption', $parameters); // Note that $action and $object may have been modified by hook
308print $hookmanager->resPrint;
309// Action column
310if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
311 print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ');
312}
313print '</tr>';
314
315// sort list
316if ($sortfield == "name" && $sortorder == "asc") {
317 usort(
318 $moduleList,
320 function (stdClass $a, stdClass $b) {
321 return strcasecmp($a->name, $b->name);
322 }
323 );
324} elseif ($sortfield == "name" && $sortorder == "desc") {
325 usort(
326 $moduleList,
328 static function (stdClass $a, stdClass $b) {
329 return strcasecmp($b->name, $a->name);
330 }
331 );
332} elseif ($sortfield == "version" && $sortorder == "asc") {
333 usort(
334 $moduleList,
336 static function (stdClass $a, stdClass $b) {
337 return strcasecmp($a->version, $b->version);
338 }
339 );
340} elseif ($sortfield == "version" && $sortorder == "desc") {
341 usort(
342 $moduleList,
344 static function (stdClass $a, stdClass $b) {
345 return strcasecmp($b->version, $a->version);
346 }
347 );
348} elseif ($sortfield == "id" && $sortorder == "asc") {
349 usort($moduleList, "compareIdAsc");
350} elseif ($sortfield == "id" && $sortorder == "desc") {
351 usort($moduleList, "compareIdDesc");
352} elseif ($sortfield == "permission" && $sortorder == "asc") {
353 usort($moduleList, "comparePermissionIdsAsc");
354} elseif ($sortfield == "permission" && $sortorder == "desc") {
355 usort($moduleList, "comparePermissionIdsDesc");
356} else {
357 $moduleList = dol_sort_array($moduleList, 'module_position');
358}
359
360foreach ($moduleList as $module) {
361 print '<tr class="oddeven">';
362 // Action column
363 if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
364 print '<td></td>';
365 }
366
367 if ($arrayfields['name']['checked']) {
368 print '<td width="300" class="nowrap">';
369 print $module->picto;
370 print ' '.$module->name;
371 print "</td>";
372 }
373
374 if ($arrayfields['version']['checked']) {
375 print '<td class="nowraponall">'.$module->version.'</td>';
376 }
377
378 if ($arrayfields['id']['checked']) {
379 print '<td class="center">'.$module->id.'</td>';
380 }
381
382 if ($arrayfields['permission']['checked']) {
383 $idperms = '';
384
385 foreach ($module->permission as $permission) {
386 $translationKey = "Permission".$permission;
387 $labelpermission = $langs->trans($translationKey);
388 $labelpermission .= ' : '.$arrayofpermissions[$permission]['label'];
389 $idperms .= ($idperms ? ", " : "").'<span title="'.$labelpermission.'">'.$permission.'</a>';
390
391 if (getDolGlobalString('MAIN_SHOW_PERMISSION')) {
392 if (empty($langs->tab_translate[$translationKey])) {
393 $tooltip = 'Missing translation (key '.$translationkey.' not found in admin.lang)';
394 $idperms .= ' <img src="../../theme/eldy/img/warning.png" alt="Warning" title="'.$tooltip.'">';
395 }
396 }
397 }
398
399 print '<td><span class="opacitymedium">'.($idperms ? $idperms : "&nbsp;").'</span></td>';
400 }
401
402 if ($arrayfields['module_position']['checked']) {
403 print '<td class="center">'.$module->module_position.'</td>';
404 }
405
406 // Action column
407 if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
408 print '<td></td>';
409 }
410 print '</tr>';
411}
412
413print '</table>';
414print '</div>';
415print '</form>';
416print '<br>';
417
418sort($rights_ids);
419$old = '';
420
421foreach ($rights_ids as $right_id) {
422 if ($old == $right_id) {
423 print "Warning duplicate id on permission : ".$right_id."<br>";
424 }
425
426 $old = $right_id;
427}
428
429// End of page
430llxFooter();
431$db->close();
432
433
442{
443 if ((int) $a->id == (int) $b->id) {
444 return 0;
445 }
446
447 return ((int) $a->id < (int) $b->id) ? -1 : 1;
448}
449
458{
459 if ((int) $a->id == (int) $b->id) {
460 return 0;
461 }
462
463 return ((int) $b->id < (int) $a->id) ? -1 : 1;
464}
465
474{
475 if (empty($a->permission) && empty($b->permission)) {
476 return compareIdAsc($a, $b);
477 }
478
479 if (empty($a->permission)) {
480 return 1;
481 }
482 if (empty($b->permission)) {
483 return -1;
484 }
485
486 if ($a->permission[0] == $b->permission[0]) {
487 return 0;
488 }
489
490 return $a->permission[0] < $b->permission[0] ? -1 : 1;
491}
492
501{
502 if (empty($a->permission) && empty($b->permission)) {
503 return compareIdDesc($a, $b);
504 }
505
506 if (empty($a->permission)) {
507 return -1;
508 }
509 if (empty($b->permission)) {
510 return 1;
511 }
512
513 if ($a->permission[0] == $b->permission[0]) {
514 return 0;
515 }
516
517 return $b->permission[0] < $a->permission[0] ? -1 : 1;
518}
if( $user->socid > 0) if(! $user->hasRight('accounting', 'chartofaccount')) $object
Definition card.php:58
if(!defined('NOREQUIRESOC')) if(!defined( 'NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined( 'NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined( 'NOREQUIREAJAX')) llxHeader()
Empty header.
Definition wrapper.php:55
llxFooter()
Empty footer.
Definition wrapper.php:69
Class to manage generation of HTML components Only common components must be here.
dolGetModulesDirs($subdir='')
Return list of directories that contain modules.
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0)
Show a picto called object_picto (generic function)
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
dol_osencode($str)
Return a string encoded into OS filesystem encoding.
dol_strlen($string, $stringencoding='UTF-8')
Make a strlen call.
dol_sort_array(&$array, $index, $order='asc', $natsort=0, $case_sensitive=0, $keepindex=0)
Advanced sort array by the value of a given key, which produces ascending (default) or descending out...
print_liste_field_titre($name, $file="", $field="", $begin="", $moreparam="", $moreattrib="", $sortfield="", $sortorder="", $prefix="", $tooltip="", $forcenowrapcolumntitle=0)
Show title line of an array.
print_barre_liste($title, $page, $file, $options='', $sortfield='', $sortorder='', $morehtmlcenter='', $num=-1, $totalnboflines='', $picto='generic', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limit=-1, $hideselectlimit=0, $hidenavigation=0, $pagenavastextinput=0, $morehtmlrightbeforearrow='')
Print a title with navigation controls for pagination.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0)
Set event messages in dol_events session object.
getDolGlobalString($key, $default='')
Return dolibarr global constant string value.
info_admin($text, $infoonimgalt=0, $nodiv=0, $admin='1', $morecss='hideonsmartphone', $textfordropdown='', $picto='')
Show information in HTML for admin users or standard users.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program.
compareIdDesc(stdClass $a, stdClass $b)
Compare two modules by their ID for a descending order.
Definition modules.php:457
compareIdAsc(stdClass $a, stdClass $b)
Compare two modules by their ID for a ascending order.
Definition modules.php:441
comparePermissionIdsDesc(stdClass $a, stdClass $b)
Compare two modules by their permissions for a descending order.
Definition modules.php:500
comparePermissionIdsAsc(stdClass $a, stdClass $b)
Compare two modules by their ID for a ascending order.
Definition modules.php:473