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 * 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 20/** 21 * \file htdocs/admin/system/modules.php 22 * \brief File to list all Dolibarr modules 23 */ 24 25require '../../main.inc.php'; 26require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; 27 28if (!$user->admin) { 29 accessforbidden(); 30} 31 32// Load translation files required by the page 33$langs->loadLangs(array("install", "other", "admin")); 34 35$optioncss = GETPOST('optioncss', 'alpha'); 36$contextpage = GETPOST('contextpage', 'aZ') ?GETPOST('contextpage', 'aZ') : 'moduleoverview'; 37 38$search_name = GETPOST("search_name", 'alpha'); 39$search_id = GETPOST("search_id", 'alpha'); 40$search_version = GETPOST("search_version", 'alpha'); 41$search_permission = GETPOST("search_permission", 'alpha'); 42 43$sortfield = GETPOST("sortfield", 'alpha'); 44$sortorder = GETPOST("sortorder", 'alpha'); 45 46if (!$sortfield) $sortfield = "id"; 47if (!$sortorder) $sortorder = "asc"; 48 49// Initialize technical object to manage hooks. Note that conf->hooks_modules contains array of hooks 50$hookmanager->initHooks(array('moduleoverview')); 51$form = new Form($db); 52$object = new stdClass(); 53 54// Definition of fields for lists 55$arrayfields = array( 56 'name'=>array('label'=>$langs->trans("Modules"), 'checked'=>1, 'position'=>10), 57 'version'=>array('label'=>$langs->trans("Version"), 'checked'=>1, 'position'=>20), 58 'id'=>array('label'=>$langs->trans("IdModule"), 'checked'=>1, 'position'=>30), 59 'module_position'=>array('label'=>$langs->trans("Position"), 'checked'=>1, 'position'=>35), 60 'permission'=>array('label'=>$langs->trans("IdPermissions"), 'checked'=>1, 'position'=>40) 61); 62 63$arrayfields = dol_sort_array($arrayfields, 'position'); 64 65 66/* 67 * Actions 68 */ 69 70$parameters = array(); 71$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks 72if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); 73 74if (empty($reshook)) { 75 // Selection of new fields 76 include DOL_DOCUMENT_ROOT.'/core/actions_changeselectedfields.inc.php'; 77} 78 79 80// Load list of modules 81$moduleList = array(); 82$modules = array(); 83$modules_files = array(); 84$modules_fullpath = array(); 85$modulesdir = dolGetModulesDirs(); 86$rights_ids = array(); 87 88foreach ($modulesdir as $dir) { 89 $handle = @opendir(dol_osencode($dir)); 90 if (is_resource($handle)) { 91 while (($file = readdir($handle)) !== false) { 92 if (is_readable($dir.$file) && substr($file, 0, 3) == 'mod' && substr($file, dol_strlen($file) - 10) == '.class.php') { 93 $modName = substr($file, 0, dol_strlen($file) - 10); 94 95 if ($modName) { 96 //print 'xx'.$dir.$file.'<br>'; 97 if (in_array($file, $modules_files)) { 98 // File duplicate 99 print "Warning duplicate file found : ".$file." (Found ".$dir.$file.", already found ".$modules_fullpath[$file].")<br>"; 100 } 101 else { 102 // File to load 103 $res = include_once $dir.$file; 104 if (class_exists($modName)) { 105 try { 106 $objMod = new $modName($db); 107 108 $modules[$objMod->numero] = $objMod; 109 $modules_files[$objMod->numero] = $file; 110 $modules_fullpath[$file] = $dir.$file; 111 } 112 catch (Exception $e) { 113 dol_syslog("Failed to load ".$dir.$file." ".$e->getMessage(), LOG_ERR); 114 } 115 } 116 else { 117 print "Warning bad descriptor file : ".$dir.$file." (Class ".$modName." not found into file)<br>"; 118 } 119 } 120 } 121 } 122 } 123 closedir($handle); 124 } 125} 126 127// create pre-filtered list for modules 128foreach ($modules as $key=>$module) { 129 $newModule = new stdClass(); 130 131 $newModule->name = $module->getName(); 132 $newModule->version = $module->getVersion(); 133 $newModule->id = $key; 134 $newModule->module_position = $module->module_position; 135 136 $alt = $module->name.' - '.$modules_files[$key]; 137 138 if (!empty($module->picto)) { 139 if (preg_match('/^\//', $module->picto)) $newModule->picto = img_picto($alt, $module->picto, 'width="14px"', 1); 140 else $newModule->picto = img_object($alt, $module->picto, 'width="14px"'); 141 } 142 else { 143 $newModule->picto = img_object($alt, 'generic', 'width="14px"'); 144 } 145 146 $permission = array(); 147 if ($module->rights) { 148 foreach ($module->rights as $rights) { 149 if (empty($rights[0])) { 150 continue; 151 } 152 153 $permission[] = $rights[0]; 154 155 array_push($rights_ids, $rights[0]); 156 } 157 } 158 159 $newModule->permission = $permission; 160 161 // pre-filter list 162 if ($search_name && !stristr($newModule->name, $search_name)) continue; 163 if ($search_version && !stristr($newModule->version, $search_version)) continue; 164 if ($search_id && !stristr($newModule->id, $search_id)) continue; 165 166 if ($search_permission) { 167 $found = false; 168 169 foreach ($newModule->permission as $permission) { 170 if (stristr($permission, $search_permission)) { 171 $found = true; 172 break; 173 } 174 } 175 176 if (!$found) continue; 177 } 178 179 $moduleList[] = $newModule; 180} 181 182 183 184/* 185 * View 186 */ 187 188llxHeader(); 189 190print '<form action="'.$_SERVER["PHP_SELF"].'" method="post" name="formulaire">'; 191if ($optioncss != '') print '<input type="hidden" name="optioncss" value="'.$optioncss.'">'; 192print '<input type="hidden" name="token" value="'.newToken().'">'; 193print '<input type="hidden" name="formfilteraction" id="formfilteraction" value="list">'; 194print '<input type="hidden" name="action" value="list">'; 195print '<input type="hidden" name="sortfield" value="'.$sortfield.'">'; 196print '<input type="hidden" name="sortorder" value="'.$sortorder.'">'; 197print '<input type="hidden" name="contextpage" value="'.$contextpage.'">'; 198 199print_barre_liste($langs->trans("AvailableModules"), $page, $_SERVER["PHP_SELF"], '', $sortfield, $sortorder, $massactionbutton, -1, '', 'title_setup', 0, '', '', 0, 1, 1); 200 201print '<span class="opacitymedium">'.$langs->trans("ToActivateModule").'</span>'; 202print '<br>'; 203print '<br>'; 204 205$varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage; 206$selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields 207 208print '<div class="div-table-responsive-no-min">'; 209print '<table class="noborder centpercent">'; 210 211// Lines with input filters 212print '<tr class="liste_titre_filter">'; 213 214if ($arrayfields['name']['checked']) { 215 print '<td class="liste_titre left">'; 216 print '<input class="flat" type="text" name="search_name" size="8" value="'.$search_name.'">'; 217 print '</td>'; 218} 219if ($arrayfields['version']['checked']) { 220 print '<td class="liste_titre left">'; 221 print '<input class="flat" type="text" name="search_version" size="8" value="'.$search_version.'">'; 222 print '</td>'; 223} 224if ($arrayfields['id']['checked']) { 225 print '<td class="liste_titre left">'; 226 print '<input class="flat" type="text" name="search_id" size="8" value="'.$search_id.'">'; 227 print '</td>'; 228} 229if ($arrayfields['module_position']['checked']) { 230 print '<td class="liste_titre left">'; 231 print '</td>'; 232} 233if ($arrayfields['permission']['checked']) { 234 print '<td class="liste_titre left">'; 235 print '<input class="flat" type="text" name="search_permission" size="8" value="'.$search_permission.'">'; 236 print '</td>'; 237} 238 239print '<td class="liste_titre center maxwidthsearch">'; 240$searchpicto = $form->showFilterButtons(); 241print $searchpicto; 242print '</td>'; 243 244print '</tr>'; 245 246print '<tr class="liste_titre">'; 247 248if ($arrayfields['name']['checked']) { 249 print_liste_field_titre($arrayfields['name']['label'], $_SERVER["PHP_SELF"], "name", "", "", "", $sortfield, $sortorder); 250} 251if ($arrayfields['version']['checked']) { 252 print_liste_field_titre($arrayfields['version']['label'], $_SERVER["PHP_SELF"], "version", "", "", "", $sortfield, $sortorder); 253} 254if ($arrayfields['id']['checked']) { 255 print_liste_field_titre($arrayfields['id']['label'], $_SERVER["PHP_SELF"], "id", "", "", "", $sortfield, $sortorder); 256} 257if ($arrayfields['module_position']['checked']) { 258 print_liste_field_titre($arrayfields['module_position']['label'], $_SERVER["PHP_SELF"], "module_position", "", "", "", $sortfield, $sortorder); 259} 260if ($arrayfields['permission']['checked']) { 261 print_liste_field_titre($arrayfields['permission']['label'], $_SERVER["PHP_SELF"], "permission", "", "", "", $sortfield, $sortorder); 262} 263 264// Fields from hook 265$parameters = array('arrayfields'=>$arrayfields, 'param'=>$param, 'sortfield'=>$sortfield, 'sortorder'=>$sortorder); 266$reshook = $hookmanager->executeHooks('printFieldListOption', $parameters); // Note that $action and $object may have been modified by hook 267print $hookmanager->resPrint; 268 269print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch '); 270print '</tr>'; 271 272// sort list 273if ($sortfield == "name" && $sortorder == "asc") usort($moduleList, function (stdClass $a, stdClass $b) { 274 return strcasecmp($a->name, $b->name); }); 275if ($sortfield == "name" && $sortorder == "desc") usort($moduleList, function (stdClass $a, stdClass $b) { 276 return strcasecmp($b->name, $a->name); }); 277if ($sortfield == "version" && $sortorder == "asc") usort($moduleList, function (stdClass $a, stdClass $b) { 278 return strcasecmp($a->version, $b->version); }); 279if ($sortfield == "version" && $sortorder == "desc") usort($moduleList, function (stdClass $a, stdClass $b) { 280 return strcasecmp($b->version, $a->version); }); 281if ($sortfield == "id" && $sortorder == "asc") usort($moduleList, "compareIdAsc"); 282if ($sortfield == "id" && $sortorder == "desc") usort($moduleList, "compareIdDesc"); 283if ($sortfield == "permission" && $sortorder == "asc") usort($moduleList, "comparePermissionIdsAsc"); 284if ($sortfield == "permission" && $sortorder == "desc") usort($moduleList, "comparePermissionIdsDesc"); 285 286$moduleList = dol_sort_array($moduleList, 'module_position'); 287 288foreach ($moduleList as $module) { 289 print '<tr class="oddeven">'; 290 291 if ($arrayfields['name']['checked']) { 292 print '<td width="300" class="nowrap">'; 293 print $module->picto; 294 print ' '.$module->name; 295 print "</td>"; 296 } 297 298 if ($arrayfields['version']['checked']) { 299 print '<td>'.$module->version.'</td>'; 300 } 301 302 if ($arrayfields['id']['checked']) { 303 print '<td class="center">'.$module->id.'</td>'; 304 } 305 306 if ($arrayfields['module_position']['checked']) { 307 print '<td class="center">'.$module->module_position.'</td>'; 308 } 309 310 if ($arrayfields['permission']['checked']) { 311 $idperms = ''; 312 313 foreach ($module->permission as $permission) { 314 $idperms .= ($idperms ? ", " : "").$permission; 315 $translationKey = "Permission".$permission; 316 317 if (!empty($conf->global->MAIN_SHOW_PERMISSION)) { 318 if (empty($langs->tab_translate[$translationKey])) { 319 $tooltip = 'Missing translation (key '.$translationkey.' not found in admin.lang)'; 320 $idperms .= ' <img src="../../theme/eldy/img/warning.png" alt="Warning" title="'.$tooltip.'">'; 321 } 322 } 323 } 324 325 print '<td>'.($idperms ? $idperms : " ").'</td>'; 326 } 327 328 print '<td></td>'; 329 print '</tr>'; 330} 331 332print '</table>'; 333print '</div>'; 334print '</form>'; 335print '<br>'; 336 337sort($rights_ids); 338$old = ''; 339 340foreach ($rights_ids as $right_id) { 341 if ($old == $right_id) { 342 print "Warning duplicate id on permission : ".$right_id."<br>"; 343 } 344 345 $old = $right_id; 346} 347 348// End of page 349llxFooter(); 350$db->close(); 351 352 353 /** 354 * Compare two modules by their ID for a ascending order 355 * 356 * @param stdClass $a First module 357 * @param stdClass $b Second module 358 * @return int Compare result (-1, 0, 1) 359 */ 360function compareIdAsc(stdClass $a, stdClass $b) 361{ 362 if ($a->id == $b->id) return 0; 363 364 return $a->id > $b->id ? -1 : 1; 365} 366 367 /** 368 * Compare two modules by their ID for a descending order 369 * 370 * @param stdClass $a First module 371 * @param stdClass $b Second module 372 * @return int Compare result (-1, 0, 1) 373 */ 374function compareIdDesc(stdClass $a, stdClass $b) 375{ 376 if ($a->id == $b->id) return 0; 377 378 return $b->id > $a->id ? -1 : 1; 379} 380 381 /** 382 * Compare two modules by their ID for a ascending order 383 * 384 * @param stdClass $a First module 385 * @param stdClass $b Second module 386 * @return int Compare result (-1, 0, 1) 387 */ 388function comparePermissionIdsAsc(stdClass $a, stdClass $b) 389{ 390 if (empty($a->permission) && empty($b->permission)) return compareIdAsc($a, $b); 391 392 if (empty($a->permission)) return 1; 393 if (empty($b->permission)) return -1; 394 395 if ($a->permission[0] == $b->permission[0]) return 0; 396 397 return $a->permission[0] > $b->permission[0] ? -1 : 1; 398} 399 400 /** 401 * Compare two modules by their permissions for a descending order 402 * 403 * @param stdClass $a First module 404 * @param stdClass $b Second module 405 * @return int Compare result (-1, 0, 1) 406 */ 407function comparePermissionIdsDesc(stdClass $a, stdClass $b) 408{ 409 if (empty($a->permission) && empty($b->permission)) return compareIdDesc($a, $b); 410 411 if (empty($a->permission)) return -1; 412 if (empty($b->permission)) return 1; 413 414 if ($a->permission[0] == $b->permission[0]) return 0; 415 416 return $a->permission[0] > $b->permission[0] ? 1 : -1; 417} 418