1<?php 2/* Copyright (C) 2003-2007 Rodolphe Quiedeville <rodolphe@quiedeville.org> 3 * Copyright (C) 2003 Jean-Louis Bergamo <jlb@j1b.org> 4 * Copyright (C) 2004-2017 Laurent Destailleur <eldy@users.sourceforge.net> 5 * Copyright (C) 2004 Eric Seigne <eric.seigne@ryxeo.com> 6 * Copyright (C) 2005-2017 Regis Houssin <regis.houssin@inodbox.com> 7 * Copyright (C) 2011 Juanjo Menent <jmenent@2byte.es> 8 * Copyright (C) 2015 Jean-François Ferry <jfefe@aternatik.fr> 9 * Copyright (C) 2015 Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr> 10 * Copyright (C) 2018 Nicolas ZABOURI <info@inovea-conseil.com> 11 * 12 * This program is free software; you can redistribute it and/or modify 13 * it under the terms of the GNU General Public License as published by 14 * the Free Software Foundation; either version 3 of the License, or 15 * (at your option) any later version. 16 * 17 * This program is distributed in the hope that it will be useful, 18 * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 * GNU General Public License for more details. 21 * 22 * You should have received a copy of the GNU General Public License 23 * along with this program. If not, see <https://www.gnu.org/licenses/>. 24 */ 25 26/** 27 * \file htdocs/admin/modules.php 28 * \brief Page to activate/disable all modules 29 */ 30 31if (!defined('CSRFCHECK_WITH_TOKEN') && (empty($_GET['action']) || $_GET['action'] != 'reset')) { // We do not force security to disable modules so we can do it if problem 32 define('CSRFCHECK_WITH_TOKEN', '1'); // Force use of CSRF protection with tokens even for GET 33} 34 35require '../main.inc.php'; 36require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; 37require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; 38require_once DOL_DOCUMENT_ROOT.'/core/lib/geturl.lib.php'; 39require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; 40require_once DOL_DOCUMENT_ROOT.'/admin/dolistore/class/dolistore.class.php'; 41 42// Load translation files required by the page 43$langs->loadLangs(array("errors", "admin", "modulebuilder")); 44 45$mode = GETPOSTISSET('mode') ? GETPOST('mode', 'alpha') : (empty($conf->global->MAIN_MODULE_SETUP_ON_LIST_BY_DEFAULT) ? 'commonkanban' : 'common'); 46if (empty($mode)) { 47 $mode = 'common'; 48} 49$action = GETPOST('action', 'aZ09'); 50//var_dump($_POST);exit; 51$value = GETPOST('value', 'alpha'); 52$page_y = GETPOST('page_y', 'int'); 53$search_keyword = GETPOST('search_keyword', 'alpha'); 54$search_status = GETPOST('search_status', 'alpha'); 55$search_nature = GETPOST('search_nature', 'alpha'); 56$search_version = GETPOST('search_version', 'alpha'); 57 58 59// For dolistore search 60$options = array(); 61$options['per_page'] = 20; 62$options['categorie'] = ((GETPOST('categorie', 'int') ?GETPOST('categorie', 'int') : 0) + 0); 63$options['start'] = ((GETPOST('start', 'int') ?GETPOST('start', 'int') : 0) + 0); 64$options['end'] = ((GETPOST('end', 'int') ?GETPOST('end', 'int') : 0) + 0); 65$options['search'] = GETPOST('search_keyword', 'alpha'); 66$dolistore = new Dolistore(false); 67 68 69if (!$user->admin) { 70 accessforbidden(); 71} 72 73$familyinfo = array( 74 'hr'=>array('position'=>'001', 'label'=>$langs->trans("ModuleFamilyHr")), 75 'crm'=>array('position'=>'006', 'label'=>$langs->trans("ModuleFamilyCrm")), 76 'srm'=>array('position'=>'007', 'label'=>$langs->trans("ModuleFamilySrm")), 77 'financial'=>array('position'=>'009', 'label'=>$langs->trans("ModuleFamilyFinancial")), 78 'products'=>array('position'=>'012', 'label'=>$langs->trans("ModuleFamilyProducts")), 79 'projects'=>array('position'=>'015', 'label'=>$langs->trans("ModuleFamilyProjects")), 80 'ecm'=>array('position'=>'018', 'label'=>$langs->trans("ModuleFamilyECM")), 81 'technic'=>array('position'=>'021', 'label'=>$langs->trans("ModuleFamilyTechnic")), 82 'portal'=>array('position'=>'040', 'label'=>$langs->trans("ModuleFamilyPortal")), 83 'interface'=>array('position'=>'050', 'label'=>$langs->trans("ModuleFamilyInterface")), 84 'base'=>array('position'=>'060', 'label'=>$langs->trans("ModuleFamilyBase")), 85 'other'=>array('position'=>'100', 'label'=>$langs->trans("ModuleFamilyOther")), 86); 87 88$param = ''; 89if (!GETPOST('buttonreset', 'alpha')) { 90 if ($search_keyword) { 91 $param .= '&search_keyword='.urlencode($search_keyword); 92 } 93 if ($search_status && $search_status != '-1') { 94 $param .= '&search_status='.urlencode($search_status); 95 } 96 if ($search_nature && $search_nature != '-1') { 97 $param .= '&search_nature='.urlencode($search_nature); 98 } 99 if ($search_version && $search_version != '-1') { 100 $param .= '&search_version='.urlencode($search_version); 101 } 102} 103 104$dirins = DOL_DOCUMENT_ROOT.'/custom'; 105$urldolibarrmodules = 'https://www.dolistore.com/'; 106 107// Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context 108$hookmanager->initHooks(array('adminmodules', 'globaladmin')); 109 110 111/* 112 * Actions 113 */ 114 115$formconfirm = ''; 116 117$parameters = array(); 118$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks 119if ($reshook < 0) { 120 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); 121} 122 123if (GETPOST('buttonreset', 'alpha')) { 124 $search_keyword = ''; 125 $search_status = ''; 126 $search_nature = ''; 127 $search_version = ''; 128} 129 130if ($action == 'install') { 131 $error = 0; 132 133 // $original_file should match format module_modulename-x.y[.z].zip 134 $original_file = basename($_FILES["fileinstall"]["name"]); 135 $original_file = preg_replace('/\(\d+\)\.zip$/i', '.zip', $original_file); 136 $newfile = $conf->admin->dir_temp.'/'.$original_file.'/'.$original_file; 137 138 if (!$original_file) { 139 $langs->load("Error"); 140 setEventMessages($langs->trans("ErrorModuleFileRequired"), null, 'warnings'); 141 $error++; 142 } else { 143 if (!$error && !preg_match('/\.zip$/i', $original_file)) { 144 $langs->load("errors"); 145 setEventMessages($langs->trans("ErrorFileMustBeADolibarrPackage", $original_file), null, 'errors'); 146 $error++; 147 } 148 if (!$error && !preg_match('/^(module[a-zA-Z0-9]*|theme)_.*\-([0-9][0-9\.]*)\.zip$/i', $original_file)) { 149 $langs->load("errors"); 150 setEventMessages($langs->trans("ErrorFilenameDosNotMatchDolibarrPackageRules", $original_file, 'module_*-x.y*.zip'), null, 'errors'); 151 $error++; 152 } 153 if (empty($_FILES['fileinstall']['tmp_name'])) { 154 $langs->load("errors"); 155 setEventMessages($langs->trans("ErrorFileNotUploaded"), null, 'errors'); 156 $error++; 157 } 158 } 159 160 if (!$error) { 161 if ($original_file) { 162 @dol_delete_dir_recursive($conf->admin->dir_temp.'/'.$original_file); 163 dol_mkdir($conf->admin->dir_temp.'/'.$original_file); 164 } 165 166 $tmpdir = preg_replace('/\.zip$/i', '', $original_file).'.dir'; 167 if ($tmpdir) { 168 @dol_delete_dir_recursive($conf->admin->dir_temp.'/'.$tmpdir); 169 dol_mkdir($conf->admin->dir_temp.'/'.$tmpdir); 170 } 171 172 $result = dol_move_uploaded_file($_FILES['fileinstall']['tmp_name'], $newfile, 1, 0, $_FILES['fileinstall']['error']); 173 if ($result > 0) { 174 $result = dol_uncompress($newfile, $conf->admin->dir_temp.'/'.$tmpdir); 175 176 if (!empty($result['error'])) { 177 $langs->load("errors"); 178 setEventMessages($langs->trans($result['error'], $original_file), null, 'errors'); 179 $error++; 180 } else { 181 // Now we move the dir of the module 182 $modulename = preg_replace('/module_/', '', $original_file); 183 $modulename = preg_replace('/\-([0-9][0-9\.]*)\.zip$/i', '', $modulename); 184 // Search dir $modulename 185 $modulenamedir = $conf->admin->dir_temp.'/'.$tmpdir.'/'.$modulename; // Example ./mymodule 186 187 if (!dol_is_dir($modulenamedir)) { 188 $modulenamedir = $conf->admin->dir_temp.'/'.$tmpdir.'/htdocs/'.$modulename; // Example ./htdocs/mymodule 189 //var_dump($modulenamedir); 190 if (!dol_is_dir($modulenamedir)) { 191 setEventMessages($langs->trans("ErrorModuleFileSeemsToHaveAWrongFormat").'<br>'.$langs->trans("ErrorModuleFileSeemsToHaveAWrongFormat2", $modulename, 'htdocs/'.$modulename), null, 'errors'); 192 $error++; 193 } 194 } 195 196 if (!$error) { 197 // TODO Make more test 198 } 199 200 dol_syslog("Uncompress of module file is a success."); 201 202 $modulenamearrays = array(); 203 if (dol_is_file($modulenamedir.'/metapackage.conf')) { 204 // This is a meta package 205 $metafile = file_get_contents($modulenamedir.'/metapackage.conf'); 206 $modulenamearrays = explode("\n", $metafile); 207 } 208 $modulenamearrays[$modulename] = $modulename; 209 //var_dump($modulenamearrays);exit; 210 211 foreach ($modulenamearrays as $modulenameval) { 212 if (strpos($modulenameval, '#') === 0) { 213 continue; // Discard comments 214 } 215 if (strpos($modulenameval, '//') === 0) { 216 continue; // Discard comments 217 } 218 if (!trim($modulenameval)) { 219 continue; 220 } 221 222 // Now we install the module 223 if (!$error) { 224 @dol_delete_dir_recursive($dirins.'/'.$modulenameval); // delete the zip file 225 dol_syslog("We copy now directory ".$conf->admin->dir_temp.'/'.$tmpdir.'/htdocs/'.$modulenameval." into target dir ".$dirins.'/'.$modulenameval); 226 $result = dolCopyDir($modulenamedir, $dirins.'/'.$modulenameval, '0444', 1); 227 if ($result <= 0) { 228 dol_syslog('Failed to call dolCopyDir result='.$result." with param ".$modulenamedir." and ".$dirins.'/'.$modulenameval, LOG_WARNING); 229 $langs->load("errors"); 230 setEventMessages($langs->trans("ErrorFailToCopyDir", $modulenamedir, $dirins.'/'.$modulenameval), null, 'errors'); 231 $error++; 232 } 233 } 234 } 235 } 236 } else { 237 setEventMessages($langs->trans("ErrorFailToRenameFile", $_FILES['fileinstall']['tmp_name'], $newfile), null, 'errors'); 238 $error++; 239 } 240 } 241 242 if (!$error) { 243 setEventMessages($langs->trans("SetupIsReadyForUse", DOL_URL_ROOT.'/admin/modules.php?mainmenu=home', $langs->transnoentitiesnoconv("Home").' - '.$langs->transnoentitiesnoconv("Setup").' - '.$langs->transnoentitiesnoconv("Modules")), null, 'warnings'); 244 } 245} 246 247if ($action == 'set' && $user->admin) { 248 $resarray = activateModule($value); 249 if (!empty($resarray['errors'])) { 250 setEventMessages('', $resarray['errors'], 'errors'); 251 } else { 252 //var_dump($resarray);exit; 253 if ($resarray['nbperms'] > 0) { 254 $tmpsql = "SELECT COUNT(rowid) as nb FROM ".MAIN_DB_PREFIX."user WHERE admin <> 1"; 255 $resqltmp = $db->query($tmpsql); 256 if ($resqltmp) { 257 $obj = $db->fetch_object($resqltmp); 258 //var_dump($obj->nb);exit; 259 if ($obj && $obj->nb > 1) { 260 $msg = $langs->trans('ModuleEnabledAdminMustCheckRights'); 261 setEventMessages($msg, null, 'warnings'); 262 } 263 } else { 264 dol_print_error($db); 265 } 266 } 267 } 268 header("Location: ".$_SERVER["PHP_SELF"]."?mode=".$mode.$param.($page_y ? '&page_y='.$page_y : '')); 269 exit; 270} elseif ($action == 'reset' && $user->admin && GETPOST('confirm') == 'yes') { 271 $result = unActivateModule($value); 272 if ($result) { 273 setEventMessages($result, null, 'errors'); 274 } 275 header("Location: ".$_SERVER["PHP_SELF"]."?mode=".$mode.$param.($page_y ? '&page_y='.$page_y : '')); 276 exit; 277} 278 279 280 281/* 282 * View 283 */ 284 285$form = new Form($db); 286 287$morejs = array(); 288$morecss = array("/admin/dolistore/css/dolistore.css"); 289 290// Set dir where external modules are installed 291if (!dol_is_dir($dirins)) { 292 dol_mkdir($dirins); 293} 294$dirins_ok = (dol_is_dir($dirins)); 295 296$help_url = 'EN:First_setup|FR:Premiers_paramétrages|ES:Primeras_configuraciones'; 297llxHeader('', $langs->trans("Setup"), $help_url, '', '', '', $morejs, $morecss, 0, 0); 298 299 300// Search modules dirs 301$modulesdir = dolGetModulesDirs(); 302 303$arrayofnatures = array('core'=>$langs->transnoentitiesnoconv("Core"), 'external'=>$langs->transnoentitiesnoconv("External").' - ['.$langs->trans("AllPublishers").']'); 304$arrayofwarnings = array(); // Array of warning each module want to show when activated 305$arrayofwarningsext = array(); // Array of warning each module want to show when we activate an external module 306$filename = array(); 307$modules = array(); 308$orders = array(); 309$categ = array(); 310 311$i = 0; // is a sequencer of modules found 312$j = 0; // j is module number. Automatically affected if module number not defined. 313$modNameLoaded = array(); 314 315foreach ($modulesdir as $dir) { 316 // Load modules attributes in arrays (name, numero, orders) from dir directory 317 //print $dir."\n<br>"; 318 dol_syslog("Scan directory ".$dir." for module descriptor files (modXXX.class.php)"); 319 $handle = @opendir($dir); 320 if (is_resource($handle)) { 321 while (($file = readdir($handle)) !== false) { 322 //print "$i ".$file."\n<br>"; 323 if (is_readable($dir.$file) && substr($file, 0, 3) == 'mod' && substr($file, dol_strlen($file) - 10) == '.class.php') { 324 $modName = substr($file, 0, dol_strlen($file) - 10); 325 326 if ($modName) { 327 if (!empty($modNameLoaded[$modName])) { // In cache of already loaded modules ? 328 $mesg = "Error: Module ".$modName." was found twice: Into ".$modNameLoaded[$modName]." and ".$dir.". You probably have an old file on your disk.<br>"; 329 setEventMessages($mesg, null, 'warnings'); 330 dol_syslog($mesg, LOG_ERR); 331 continue; 332 } 333 334 try { 335 $res = include_once $dir.$file; // A class already exists in a different file will send a non catchable fatal error. 336 if (class_exists($modName)) { 337 try { 338 $objMod = new $modName($db); 339 $modNameLoaded[$modName] = $dir; 340 if (!$objMod->numero > 0 && $modName != 'modUser') { 341 dol_syslog('The module descriptor '.$modName.' must have a numero property', LOG_ERR); 342 } 343 $j = $objMod->numero; 344 345 $modulequalified = 1; 346 347 // We discard modules according to features level (PS: if module is activated we always show it) 348 $const_name = 'MAIN_MODULE_'.strtoupper(preg_replace('/^mod/i', '', get_class($objMod))); 349 if ($objMod->version == 'development' && (empty($conf->global->$const_name) && ($conf->global->MAIN_FEATURES_LEVEL < 2))) { 350 $modulequalified = 0; 351 } 352 if ($objMod->version == 'experimental' && (empty($conf->global->$const_name) && ($conf->global->MAIN_FEATURES_LEVEL < 1))) { 353 $modulequalified = 0; 354 } 355 if (preg_match('/deprecated/', $objMod->version) && (empty($conf->global->$const_name) && ($conf->global->MAIN_FEATURES_LEVEL >= 0))) { 356 $modulequalified = 0; 357 } 358 359 // We discard modules according to property ->hidden 360 if (!empty($objMod->hidden)) { 361 $modulequalified = 0; 362 } 363 364 if ($modulequalified > 0) { 365 $publisher = dol_escape_htmltag($objMod->getPublisher()); 366 $external = ($objMod->isCoreOrExternalModule() == 'external'); 367 if ($external) { 368 if ($publisher) { 369 $arrayofnatures['external_'.$publisher] = $langs->trans("External").' - '.$publisher; 370 } else { 371 $arrayofnatures['external_'] = $langs->trans("External").' - '.$langs->trans("UnknownPublishers"); 372 } 373 } 374 ksort($arrayofnatures); 375 376 // Define array $categ with categ with at least one qualified module 377 $filename[$i] = $modName; 378 $modules[$modName] = $objMod; 379 380 // Gives the possibility to the module, to provide his own family info and position of this family 381 if (is_array($objMod->familyinfo) && !empty($objMod->familyinfo)) { 382 $familyinfo = array_merge($familyinfo, $objMod->familyinfo); 383 $familykey = key($objMod->familyinfo); 384 } else { 385 $familykey = $objMod->family; 386 } 387 388 $moduleposition = ($objMod->module_position ? $objMod->module_position : '50'); 389 if ($moduleposition == '50' && ($objMod->isCoreOrExternalModule() == 'external')) { 390 $moduleposition = '80'; // External modules at end by default 391 } 392 393 // Add list of warnings to show into arrayofwarnings and arrayofwarningsext 394 if (!empty($objMod->warnings_activation)) { 395 $arrayofwarnings[$modName] = $objMod->warnings_activation; 396 } 397 if (!empty($objMod->warnings_activation_ext)) { 398 $arrayofwarningsext[$modName] = $objMod->warnings_activation_ext; 399 } 400 401 $familyposition = (empty($familyinfo[$familykey]['position']) ? 0 : $familyinfo[$familykey]['position']); 402 $listOfOfficialModuleGroups = array('hr', 'technic', 'interface', 'technic', 'portal', 'financial', 'crm', 'base', 'products', 'srm', 'ecm', 'projects', 'other'); 403 if ($external && !in_array($familykey, $listOfOfficialModuleGroups)) { 404 // If module is extern and into a custom group (not into an official predefined one), it must appear at end (custom groups should not be before official groups). 405 if (is_numeric($familyposition)) { 406 $familyposition = sprintf("%03d", (int) $familyposition + 100); 407 } 408 } 409 410 $orders[$i] = $familyposition."_".$familykey."_".$moduleposition."_".$j; // Sort by family, then by module position then number 411 412 // Set categ[$i] 413 $specialstring = 'unknown'; 414 if ($objMod->version == 'development' || $objMod->version == 'experimental') { 415 $specialstring = 'expdev'; 416 } 417 if (isset($categ[$specialstring])) { 418 $categ[$specialstring]++; // Array of all different modules categories 419 } else { 420 $categ[$specialstring] = 1; 421 } 422 $j++; 423 $i++; 424 } else { 425 dol_syslog("Module ".get_class($objMod)." not qualified"); 426 } 427 } catch (Exception $e) { 428 dol_syslog("Failed to load ".$dir.$file." ".$e->getMessage(), LOG_ERR); 429 } 430 } else { 431 print "Warning bad descriptor file : ".$dir.$file." (Class ".$modName." not found into file)<br>"; 432 } 433 } catch (Exception $e) { 434 dol_syslog("Failed to load ".$dir.$file." ".$e->getMessage(), LOG_ERR); 435 } 436 } 437 } 438 } 439 closedir($handle); 440 } else { 441 dol_syslog("htdocs/admin/modules.php: Failed to open directory ".$dir.". See permission and open_basedir option.", LOG_WARNING); 442 } 443} 444 445if ($action == 'reset_confirm' && $user->admin) { 446 if (!empty($modules[$value])) { 447 $objMod = $modules[$value]; 448 449 if (!empty($objMod->langfiles)) { 450 $langs->loadLangs($objMod->langfiles); 451 } 452 453 $form = new Form($db); 454 $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?value='.$value.'&mode='.$mode.$param, $langs->trans('ConfirmUnactivation'), $langs->trans(GETPOST('confirm_message_code')), 'reset', '', 'no', 1); 455 } 456} 457 458print $formconfirm; 459 460asort($orders); 461//var_dump($orders); 462//var_dump($categ); 463//var_dump($modules); 464 465$nbofactivatedmodules = count($conf->modules); 466$moreinfo = $langs->trans("TitleNumberOfActivatedModules"); 467$moreinfo2 = ($nbofactivatedmodules - 1)." / ".count($modules); 468if ($nbofactivatedmodules <= 1) { 469 $moreinfo2 .= ' '.img_warning($langs->trans("YouMustEnableOneModule")); 470} 471 472print load_fiche_titre($langs->trans("ModulesSetup"), '', 'title_setup'); 473 474// Start to show page 475if ($mode == 'common' || $mode == 'commonkanban') { 476 $desc = $langs->trans("ModulesDesc", '{picto}'); 477 $desc = str_replace('{picto}', img_picto('', 'switch_off'), $desc); 478 print '<span class="opacitymedium hideonsmartphone">'.$desc."<br><br></span>\n"; 479} 480if ($mode == 'marketplace') { 481 print '<span class="opacitymedium hideonsmartphone">'.$langs->trans("ModulesMarketPlaceDesc")."<br><br></span>\n"; 482} 483if ($mode == 'deploy') { 484 print '<span class="opacitymedium hideonsmartphone">'.$langs->trans("ModulesDeployDesc", $langs->transnoentitiesnoconv("AvailableModules"))."<br><br></span>\n"; 485} 486if ($mode == 'develop') { 487 print '<span class="opacitymedium hideonsmartphone">'.$langs->trans("ModulesDevelopDesc")."<br><br></span>\n"; 488} 489 490 491$head = modules_prepare_head(); 492 493 494if ($mode == 'common' || $mode == 'commonkanban') { 495 dol_set_focus('#search_keyword'); 496 497 print '<form method="POST" id="searchFormList" action="'.$_SERVER["PHP_SELF"].'">'; 498 if ($optioncss != '') { 499 print '<input type="hidden" name="optioncss" value="'.$optioncss.'">'; 500 } 501 print '<input type="hidden" name="token" value="'.newToken().'">'; 502 print '<input type="hidden" name="sortfield" value="'.$sortfield.'">'; 503 print '<input type="hidden" name="sortorder" value="'.$sortorder.'">'; 504 print '<input type="hidden" name="page" value="'.$page.'">'; 505 print '<input type="hidden" name="mode" value="'.$mode.'">'; 506 507 print dol_get_fiche_head($head, 'modules', '', -1); 508 509 $moreforfilter = '<div class="valignmiddle">'; 510 511 $moreforfilter .= '<div class="floatright right pagination"><ul><li>'; 512 $moreforfilter .= dolGetButtonTitle($langs->trans('ViewKanban'), '', 'fa fa-th-list imgforviewmode', $_SERVER["PHP_SELF"].'?mode=commonkanban'.$param, '', 1, array('morecss'=>'reposition'.($mode == 'common' ? '' : ' btnTitleSelected'))); 513 $moreforfilter .= dolGetButtonTitle($langs->trans('ViewList'), '', 'fa fa-list-alt imgforviewmode', $_SERVER["PHP_SELF"].'?mode=common'.$param, '', 1, array('morecss'=>'reposition'.($mode == 'commonkanban' ? '' : ' btnTitleSelected'))); 514 $moreforfilter .= '</li></ul></div>'; 515 516 $moreforfilter .= '<div class="floatright center marginrightonly hideonsmartphone" style="padding-top: 3px"><span class="">'.$moreinfo.'</span><br><b class="largenumber">'.$moreinfo2.'</b></div>'; 517 518 $moreforfilter .= '<div class="colorbacktimesheet float valignmiddle">'; 519 $moreforfilter .= '<div class="divsearchfield paddingtop">'; 520 $moreforfilter .= $langs->trans('Keyword').': <input type="text" id="search_keyword" name="search_keyword" class="maxwidth100" value="'.dol_escape_htmltag($search_keyword).'">'; 521 $moreforfilter .= '</div>'; 522 $moreforfilter .= '<div class="divsearchfield paddingtop">'; 523 $moreforfilter .= $langs->trans('Origin').': '.$form->selectarray('search_nature', $arrayofnatures, dol_escape_htmltag($search_nature), 1, 0, 0, '', 0, 0, 0, '', 'maxwidth200', 1); 524 $moreforfilter .= '</div>'; 525 if (!empty($conf->global->MAIN_FEATURES_LEVEL)) { 526 $array_version = array('stable'=>$langs->transnoentitiesnoconv("Stable")); 527 if ($conf->global->MAIN_FEATURES_LEVEL < 0) { 528 $array_version['deprecated'] = $langs->trans("Deprecated"); 529 } 530 if ($conf->global->MAIN_FEATURES_LEVEL > 0) { 531 $array_version['experimental'] = $langs->trans("Experimental"); 532 } 533 if ($conf->global->MAIN_FEATURES_LEVEL > 1) { 534 $array_version['development'] = $langs->trans("Development"); 535 } 536 $moreforfilter .= '<div class="divsearchfield paddingtop">'; 537 $moreforfilter .= $langs->trans('Version').': '.$form->selectarray('search_version', $array_version, $search_version, 1, 0, 0, '', 0, 0, 0, '', 'maxwidth150', 1); 538 $moreforfilter .= '</div>'; 539 } 540 $moreforfilter .= '<div class="divsearchfield paddingtop">'; 541 $moreforfilter .= $langs->trans('Status').': '.$form->selectarray('search_status', array('active'=>$langs->transnoentitiesnoconv("Enabled"), 'disabled'=>$langs->transnoentitiesnoconv("Disabled")), $search_status, 1, 0, 0, '', 0, 0, 0, '', 'maxwidth150', 1); 542 $moreforfilter .= '</div>'; 543 $moreforfilter .= ' '; 544 $moreforfilter .= '<div class="divsearchfield">'; 545 $moreforfilter .= '<input type="submit" name="buttonsubmit" class="button" value="'.dol_escape_htmltag($langs->trans("Refresh")).'">'; 546 $moreforfilter .= ' '; 547 $moreforfilter .= '<input type="submit" name="buttonreset" class="butActionDelete noborderbottom" value="'.dol_escape_htmltag($langs->trans("Reset")).'">'; 548 $moreforfilter .= '</div>'; 549 $moreforfilter .= '</div>'; 550 551 $moreforfilter .= '</div>'; 552 553 if (!empty($moreforfilter)) { 554 print $moreforfilter; 555 $parameters = array(); 556 $reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters); // Note that $action and $object may have been modified by hook 557 print $hookmanager->resPrint; 558 } 559 560 $moreforfilter = ''; 561 562 print '<div class="clearboth"></div><br>'; 563 564 $object = new stdClass(); 565 $parameters = array(); 566 $reshook = $hookmanager->executeHooks('insertExtraHeader', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks 567 if ($reshook < 0) { 568 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); 569 } 570 571 // Show list of modules 572 $oldfamily = ''; 573 $linenum = 0; 574 575 foreach ($orders as $key => $value) { 576 $linenum++; 577 $tab = explode('_', $value); 578 $familykey = $tab[1]; 579 $module_position = $tab[2]; 580 581 $modName = $filename[$key]; 582 $objMod = $modules[$modName]; 583 584 //print $objMod->name." - ".$key." - ".$objMod->version."<br>"; 585 if ($mode == 'expdev' && $objMod->version != 'development' && $objMod->version != 'experimental') { 586 continue; // Discard if not for current tab 587 } 588 589 if (!$objMod->getName()) { 590 dol_syslog("Error for module ".$key." - Property name of module looks empty", LOG_WARNING); 591 continue; 592 } 593 594 $const_name = 'MAIN_MODULE_'.strtoupper(preg_replace('/^mod/i', '', get_class($objMod))); 595 596 // Check filters 597 $modulename = $objMod->getName(); 598 $moduletechnicalname = $objMod->name; 599 $moduledesc = $objMod->getDesc(); 600 $moduledesclong = $objMod->getDescLong(); 601 $moduleauthor = $objMod->getPublisher(); 602 603 // We discard showing according to filters 604 if ($search_keyword) { 605 $qualified = 0; 606 if (preg_match('/'.preg_quote($search_keyword).'/i', $modulename) 607 || preg_match('/'.preg_quote($search_keyword).'/i', $moduletechnicalname) 608 || preg_match('/'.preg_quote($search_keyword).'/i', $moduledesc) 609 || preg_match('/'.preg_quote($search_keyword).'/i', $moduledesclong) 610 || preg_match('/'.preg_quote($search_keyword).'/i', $moduleauthor) 611 ) { 612 $qualified = 1; 613 } 614 if (!$qualified) { 615 continue; 616 } 617 } 618 if ($search_status) { 619 if ($search_status == 'active' && empty($conf->global->$const_name)) { 620 continue; 621 } 622 if ($search_status == 'disabled' && !empty($conf->global->$const_name)) { 623 continue; 624 } 625 } 626 if ($search_nature) { 627 if (preg_match('/^external/', $search_nature) && $objMod->isCoreOrExternalModule() != 'external') { 628 continue; 629 } 630 $reg = array(); 631 if (preg_match('/^external_(.*)$/', $search_nature, $reg)) { 632 //print $reg[1].'-'.dol_escape_htmltag($objMod->getPublisher()); 633 $publisher = dol_escape_htmltag($objMod->getPublisher()); 634 if ($reg[1] && dol_escape_htmltag($reg[1]) != $publisher) { 635 continue; 636 } 637 if (!$reg[1] && !empty($publisher)) { 638 continue; 639 } 640 } 641 if ($search_nature == 'core' && $objMod->isCoreOrExternalModule() == 'external') { 642 continue; 643 } 644 } 645 if ($search_version) { 646 if (($objMod->version == 'development' || $objMod->version == 'experimental' || preg_match('/deprecated/', $objMod->version)) && $search_version == 'stable') { 647 continue; 648 } 649 if ($objMod->version != 'development' && ($search_version == 'development')) { 650 continue; 651 } 652 if ($objMod->version != 'experimental' && ($search_version == 'experimental')) { 653 continue; 654 } 655 if (!preg_match('/deprecated/', $objMod->version) && ($search_version == 'deprecated')) { 656 continue; 657 } 658 } 659 660 // Load all lang files of module 661 if (isset($objMod->langfiles) && is_array($objMod->langfiles)) { 662 foreach ($objMod->langfiles as $domain) { 663 $langs->load($domain); 664 } 665 } 666 667 // Print a separator if we change family 668 if ($familykey != $oldfamily) { 669 if ($oldfamily) { 670 print '</table></div><br>'; 671 } 672 673 $familytext = empty($familyinfo[$familykey]['label']) ? $familykey : $familyinfo[$familykey]['label']; 674 675 print load_fiche_titre($familytext, '', '', 0, '', 'modulefamilygroup'); 676 677 if ($mode == 'commonkanban') { 678 print '<div class="box-flex-container">'; 679 } else { 680 print '<div class="div-table-responsive">'; 681 print '<table class="tagtable liste" summary="list_of_modules">'."\n"; 682 } 683 684 $atleastoneforfamily = 0; 685 } 686 687 $atleastoneforfamily++; 688 689 if ($familykey != $oldfamily) { 690 $familytext = empty($familyinfo[$familykey]['label']) ? $familykey : $familyinfo[$familykey]['label']; 691 $oldfamily = $familykey; 692 } 693 694 // Version (with picto warning or not) 695 $version = $objMod->getVersion(0); 696 $versiontrans = ''; 697 if (preg_match('/development/i', $version)) { 698 $versiontrans .= img_warning($langs->trans("Development"), '', 'floatleft paddingright'); 699 } 700 if (preg_match('/experimental/i', $version)) { 701 $versiontrans .= img_warning($langs->trans("Experimental"), '', 'floatleft paddingright'); 702 } 703 if (preg_match('/deprecated/i', $version)) { 704 $versiontrans .= img_warning($langs->trans("Deprecated"), '', 'floatleft paddingright'); 705 } 706 if ($objMod->isCoreOrExternalModule() == 'external' || preg_match('/development|experimental|deprecated/i', $version)) { 707 $versiontrans .= $objMod->getVersion(1); 708 } 709 710 // Define imginfo 711 $imginfo = "info"; 712 if ($objMod->isCoreOrExternalModule() == 'external') { 713 $imginfo = "info_black"; 714 } 715 716 $codeenabledisable = ''; 717 $codetoconfig = ''; 718 719 // Activate/Disable and Setup (2 columns) 720 if (!empty($conf->global->$const_name)) { // If module is already activated 721 // Set $codeenabledisable 722 $disableSetup = 0; 723 if (!empty($arrayofwarnings[$modName])) { 724 $codeenabledisable .= '<!-- This module has a warning to show when we activate it (note: your country is '.$mysoc->country_code.') -->'."\n"; 725 } 726 if (!empty($objMod->disabled)) { 727 $codeenabledisable .= $langs->trans("Disabled"); 728 } elseif (!empty($objMod->always_enabled) || ((!empty($conf->multicompany->enabled) && $objMod->core_enabled) && ($user->entity || $conf->entity != 1))) { 729 if (method_exists($objMod, 'alreadyUsed') && $objMod->alreadyUsed()) { 730 $codeenabledisable .= $langs->trans("Used"); 731 } else { 732 $codeenabledisable .= img_picto($langs->trans("Required"), 'switch_on', '', false, 0, 0, '', 'opacitymedium valignmiddle'); 733 //print $langs->trans("Required"); 734 } 735 if (!empty($conf->multicompany->enabled) && $user->entity) { 736 $disableSetup++; 737 } 738 } else { 739 if (!empty($objMod->warnings_unactivation[$mysoc->country_code]) && method_exists($objMod, 'alreadyUsed') && $objMod->alreadyUsed()) { 740 $codeenabledisable .= '<a class="reposition valignmiddle" href="'.$_SERVER["PHP_SELF"].'?id='.$objMod->numero.'&token='.newToken().'&module_position='.$module_position.'&action=reset_confirm&confirm_message_code='.$objMod->warnings_unactivation[$mysoc->country_code].'&value='.$modName.'&mode='.$mode.$param.'">'; 741 $codeenabledisable .= img_picto($langs->trans("Activated"), 'switch_on'); 742 $codeenabledisable .= '</a>'; 743 } else { 744 $codeenabledisable .= '<a class="reposition valignmiddle" href="'.$_SERVER["PHP_SELF"].'?id='.$objMod->numero.'&token='.newToken().'&module_position='.$module_position.'&action=reset&value='.$modName.'&mode='.$mode.'&confirm=yes'.$param.'">'; 745 $codeenabledisable .= img_picto($langs->trans("Activated"), 'switch_on'); 746 $codeenabledisable .= '</a>'; 747 } 748 } 749 750 // Set $codetoconfig 751 if (!empty($objMod->config_page_url) && !$disableSetup) { 752 $backtourlparam = ''; 753 if ($search_keyword != '') { 754 $backtourlparam .= ($backtourlparam ? '&' : '?').'search_keyword='.$search_keyword; // No urlencode here, done later 755 } 756 if ($search_nature > -1) { 757 $backtourlparam .= ($backtourlparam ? '&' : '?').'search_nature='.$search_nature; 758 } 759 if ($search_version > -1) { 760 $backtourlparam .= ($backtourlparam ? '&' : '?').'search_version='.$search_version; 761 } 762 if ($search_status > -1) { 763 $backtourlparam .= ($backtourlparam ? '&' : '?').'search_status='.$search_status; 764 } 765 $backtourl = $_SERVER["PHP_SELF"].$backtourlparam; 766 767 $regs = array(); 768 if (is_array($objMod->config_page_url)) { 769 $i = 0; 770 foreach ($objMod->config_page_url as $page) { 771 $urlpage = $page; 772 if ($i++) { 773 $codetoconfig .= '<a href="'.$urlpage.'" title="'.$langs->trans($page).'">'.img_picto(ucfirst($page), "setup").'</a>'; 774 // print '<a href="'.$page.'">'.ucfirst($page).'</a> '; 775 } else { 776 if (preg_match('/^([^@]+)@([^@]+)$/i', $urlpage, $regs)) { 777 $urltouse = dol_buildpath('/'.$regs[2].'/admin/'.$regs[1], 1); 778 $codetoconfig .= '<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: 6px"', false, 0, 0, '', 'fa-15').'</a>'; 779 } else { 780 $urltouse = $urlpage; 781 $codetoconfig .= '<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: 6px"', false, 0, 0, '', 'fa-15').'</a>'; 782 } 783 } 784 } 785 } elseif (preg_match('/^([^@]+)@([^@]+)$/i', $objMod->config_page_url, $regs)) { 786 $codetoconfig .= '<a class="valignmiddle" 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: 6px"', false, 0, 0, '', 'fa-15').'</a>'; 787 } else { 788 $codetoconfig .= '<a class="valignmiddle" href="'.$objMod->config_page_url.'?save_lastsearch_values=1&backtopage='.urlencode($backtourl).'" title="'.$langs->trans("Setup").'">'.img_picto($langs->trans("Setup"), "setup", 'style="padding-right: 6px"', false, 0, 0, '', 'fa-15').'</a>'; 789 } 790 } else { 791 $codetoconfig .= img_picto($langs->trans("NothingToSetup"), "setup", 'class="opacitytransp" style="padding-right: 6px"', false, 0, 0, '', 'fa-15'); 792 } 793 } else // Module not yet activated 794 { 795 // Set $codeenabledisable 796 if (!empty($objMod->always_enabled)) { 797 // Should never happened 798 } elseif (!empty($objMod->disabled)) { 799 $codeenabledisable .= $langs->trans("Disabled"); 800 } else { 801 // Module qualified for activation 802 $warningmessage = ''; 803 if (!empty($arrayofwarnings[$modName])) { 804 $codeenabledisable .= '<!-- This module is a core module and it may have a warning to show when we activate it (note: your country is '.$mysoc->country_code.') -->'."\n"; 805 foreach ($arrayofwarnings[$modName] as $keycountry => $cursorwarningmessage) { 806 if (preg_match('/^always/', $keycountry) || ($mysoc->country_code && preg_match('/^'.$mysoc->country_code.'/', $keycountry))) { 807 $warningmessage .= ($warningmessage ? "\n" : "").$langs->trans($cursorwarningmessage, $objMod->getName(), $mysoc->country_code); 808 } 809 } 810 } 811 if ($objMod->isCoreOrExternalModule() == 'external' && !empty($arrayofwarningsext)) { 812 $codeenabledisable .= '<!-- This module is an external module and it may have a warning to show (note: your country is '.$mysoc->country_code.') -->'."\n"; 813 foreach ($arrayofwarningsext as $keymodule => $arrayofwarningsextbycountry) { 814 $keymodulelowercase = strtolower(preg_replace('/^mod/', '', $keymodule)); 815 if (in_array($keymodulelowercase, $conf->modules)) { // If module that request warning is on 816 foreach ($arrayofwarningsextbycountry as $keycountry => $cursorwarningmessage) { 817 if (preg_match('/^always/', $keycountry) || ($mysoc->country_code && preg_match('/^'.$mysoc->country_code.'/', $keycountry))) { 818 $warningmessage .= ($warningmessage ? "\n" : "").$langs->trans($cursorwarningmessage, $objMod->getName(), $mysoc->country_code, $modules[$keymodule]->getName()); 819 $warningmessage .= ($warningmessage ? "\n" : "").($warningmessage ? "\n" : "").$langs->trans("Module").' : '.$objMod->getName(); 820 if (!empty($objMod->editor_name)) { 821 $warningmessage .= ($warningmessage ? "\n" : "").$langs->trans("Publisher").' : '.$objMod->editor_name; 822 } 823 if (!empty($objMod->editor_name)) { 824 $warningmessage .= ($warningmessage ? "\n" : "").$langs->trans("ModuleTriggeringThisWarning").' : '.$modules[$keymodule]->getName(); 825 } 826 } 827 } 828 } 829 } 830 } 831 $codeenabledisable .= '<!-- Message to show: '.$warningmessage.' -->'."\n"; 832 $codeenabledisable .= '<a class="reposition" href="'.$_SERVER["PHP_SELF"].'?id='.$objMod->numero.'&token='.newToken().'&module_position='.$module_position.'&action=set&value='.$modName.'&mode='.$mode.$param.'"'; 833 if ($warningmessage) { 834 $codeenabledisable .= ' onclick="return confirm(\''.dol_escape_js($warningmessage).'\');"'; 835 } 836 $codeenabledisable .= '>'; 837 $codeenabledisable .= img_picto($langs->trans("Disabled"), 'switch_off'); 838 $codeenabledisable .= "</a>\n"; 839 } 840 841 // Set $codetoconfig 842 $codetoconfig .= img_picto($langs->trans("NothingToSetup"), "setup", 'class="opacitytransp" style="padding-right: 6px"'); 843 } 844 845 if ($mode == 'commonkanban') { 846 // Output Kanban 847 print $objMod->getKanbanView($codeenabledisable, $codetoconfig); 848 } else { 849 print '<tr class="oddeven">'."\n"; 850 if (!empty($conf->global->MAIN_MODULES_SHOW_LINENUMBERS)) { 851 print '<td width="20px">'.$linenum.'</td>'; 852 } 853 854 // Picto + Name of module 855 print ' <td width="200px">'; 856 $alttext = ''; 857 //if (is_array($objMod->need_dolibarr_version)) $alttext.=($alttext?' - ':'').'Dolibarr >= '.join('.',$objMod->need_dolibarr_version); 858 //if (is_array($objMod->phpmin)) $alttext.=($alttext?' - ':'').'PHP >= '.join('.',$objMod->phpmin); 859 if (!empty($objMod->picto)) { 860 if (preg_match('/^\//i', $objMod->picto)) { 861 print img_picto($alttext, $objMod->picto, 'class="valignmiddle pictomodule paddingrightonly"', 1); 862 } else { 863 print img_object($alttext, $objMod->picto, 'class="valignmiddle pictomodule paddingrightonly"'); 864 } 865 } else { 866 print img_object($alttext, 'generic', 'class="valignmiddle paddingrightonly"'); 867 } 868 print ' <span class="valignmiddle">'.$objMod->getName().'</span>'; 869 print "</td>\n"; 870 871 // Desc 872 print '<td class="valignmiddle tdoverflowmax300">'; 873 print nl2br($objMod->getDesc()); 874 print "</td>\n"; 875 876 // Help 877 print '<td class="center nowrap" style="width: 82px;">'; 878 //print $form->textwithpicto('', $text, 1, $imginfo, 'minheight20', 0, 2, 1); 879 print '<a href="javascript:document_preview(\''.DOL_URL_ROOT.'/admin/modulehelp.php?id='.$objMod->numero.'\',\'text/html\',\''.dol_escape_js($langs->trans("Module")).'\')">'.img_picto(($objMod->isCoreOrExternalModule() == 'external' ? $langs->trans("ExternalModule").' - ' : '').$langs->trans("ClickToShowDescription"), $imginfo).'</a>'; 880 print '</td>'; 881 882 // Version 883 print '<td class="center nowrap" width="120px">'; 884 print $versiontrans; 885 if (!empty($conf->global->CHECKLASTVERSION_EXTERNALMODULE)) { // This is a bad practice to activate a synch external access during building of a page. 1 external module can hang the application. 886 require_once DOL_DOCUMENT_ROOT.'/core/lib/geturl.lib.php'; 887 if (!empty($objMod->url_last_version)) { 888 $newversion = getURLContent($objMod->url_last_version); 889 if (isset($newversion['content'])) { 890 if (version_compare($newversion['content'], $versiontrans) > 0) { 891 print " <span class='butAction' title='".$langs->trans('LastStableVersion')."'>".$newversion['content']."</span>"; 892 } 893 } 894 } 895 } 896 print "</td>\n"; 897 898 // Link enable/disable 899 print '<td class="center valignmiddle" width="60px">'; 900 print $codeenabledisable; 901 print "</td>\n"; 902 903 // Link config 904 print '<td class="tdsetuppicto right valignmiddle" width="60px">'; 905 print $codetoconfig; 906 print '</td>'; 907 908 print "</tr>\n"; 909 } 910 } 911 912 if ($oldfamily) { 913 if ($mode == 'commonkanban') { 914 print '</div>'; 915 } else { 916 print "</table>\n"; 917 print '</div>'; 918 } 919 } 920 921 print dol_get_fiche_end(); 922 923 print '<br>'; 924 925 // Show warning about external users 926 print info_admin(showModulesExludedForExternal($modules))."\n"; 927 928 print '</form>'; 929} 930 931if ($mode == 'marketplace') { 932 print dol_get_fiche_head($head, $mode, '', -1); 933 934 // Marketplace 935 print '<div class="div-table-responsive-no-min">'; 936 print '<table summary="list_of_modules" class="noborder centpercent">'."\n"; 937 print '<tr class="liste_titre">'."\n"; 938 print '<td class="hideonsmartphone">'.$form->textwithpicto($langs->trans("Provider"), $langs->trans("WebSiteDesc")).'</td>'; 939 print '<td></td>'; 940 print '<td>'.$langs->trans("URL").'</td>'; 941 print '</tr>'; 942 943 print '<tr class="oddeven">'."\n"; 944 $url = 'https://www.dolistore.com'; 945 print '<td class="hideonsmartphone"><a href="'.$url.'" target="_blank" rel="external"><img border="0" class="imgautosize imgmaxwidth180" src="'.DOL_URL_ROOT.'/theme/dolistore_logo.png"></a></td>'; 946 print '<td>'.$langs->trans("DoliStoreDesc").'</td>'; 947 print '<td><a href="'.$url.'" target="_blank" rel="external">'.$url.'</a></td>'; 948 print '</tr>'; 949 950 print "</table>\n"; 951 print '</div>'; 952 953 print dol_get_fiche_end(); 954 955 print '<br>'; 956 957 if (empty($conf->global->MAIN_DISABLE_DOLISTORE_SEARCH) && $conf->global->MAIN_FEATURES_LEVEL >= 1) { 958 // $options is array with filter criterias 959 //var_dump($options); 960 $dolistore->getRemoteCategories(); 961 $dolistore->getRemoteProducts($options); 962 963 print '<span class="opacitymedium">'.$langs->trans('DOLISTOREdescriptionLong').'</span><br><br>'; 964 965 $previouslink = $dolistore->get_previous_link(); 966 $nextlink = $dolistore->get_next_link(); 967 968 print '<div class="liste_titre liste_titre_bydiv centpercent"><div class="divsearchfield">'; 969 970 print '<form method="POST" class="centpercent" id="searchFormList" action="'.$dolistore->url.'">'; 971 ?> 972 <input type="hidden" name="token" value="<?php echo newToken(); ?>"> 973 <input type="hidden" name="mode" value="marketplace"> 974 <div class="divsearchfield"><?php echo $langs->trans('Keyword') ?>: 975 <input name="search_keyword" placeholder="<?php echo $langs->trans('Chercher un module') ?>" id="search_keyword" type="text" size="50" value="<?php echo $options['search'] ?>"><br> 976 </div> 977 <div class="divsearchfield"> 978 <input class="button buttongen" value="<?php echo $langs->trans('Rechercher') ?>" type="submit"> 979 <a class="buttonreset" href="<?php echo $dolistore->url ?>"><?php echo $langs->trans('Reset') ?></a> 980 981 982 </div> 983 <?php 984 print $previouslink; 985 print $nextlink; 986 print '</form>'; 987 988 989 print '</div></div>'; 990 print '<div class="clearboth"></div>'; 991 992 ?> 993 994 <div id="category-tree-left"> 995 <ul class="tree"> 996 <?php echo $dolistore->get_categories(); ?> 997 </ul> 998 </div> 999 <div id="listing-content"> 1000 <table summary="list_of_modules" id="list_of_modules" class="productlist centpercent"> 1001 <tbody id="listOfModules"> 1002 <?php echo $dolistore->get_products($categorie); ?> 1003 </tbody> 1004 </table> 1005 </div> 1006 1007 <?php 1008 } 1009} 1010 1011 1012// Install external module 1013 1014if ($mode == 'deploy') { 1015 print dol_get_fiche_head($head, $mode, '', -1); 1016 1017 $dolibarrdataroot = preg_replace('/([\\/]+)$/i', '', DOL_DATA_ROOT); 1018 $allowonlineinstall = true; 1019 $allowfromweb = 1; 1020 if (dol_is_file($dolibarrdataroot.'/installmodules.lock')) { 1021 $allowonlineinstall = false; 1022 } 1023 1024 $fullurl = '<a href="'.$urldolibarrmodules.'" target="_blank">'.$urldolibarrmodules.'</a>'; 1025 $message = ''; 1026 if (!empty($allowonlineinstall)) { 1027 if (!in_array('/custom', explode(',', $dolibarr_main_url_root_alt))) { 1028 $message = info_admin($langs->trans("ConfFileMustContainCustom", DOL_DOCUMENT_ROOT.'/custom', DOL_DOCUMENT_ROOT)); 1029 $allowfromweb = -1; 1030 } else { 1031 if ($dirins_ok) { 1032 if (!is_writable(dol_osencode($dirins))) { 1033 $langs->load("errors"); 1034 $message = info_admin($langs->trans("ErrorFailedToWriteInDir", $dirins), 0, 0, '1', 'warning'); 1035 $allowfromweb = 0; 1036 } 1037 } else { 1038 $message = info_admin($langs->trans("NotExistsDirect", $dirins).$langs->trans("InfDirAlt").$langs->trans("InfDirExample")); 1039 $allowfromweb = 0; 1040 } 1041 } 1042 } else { 1043 $message = info_admin($langs->trans("InstallModuleFromWebHasBeenDisabledByFile", $dolibarrdataroot.'/installmodules.lock')); 1044 $allowfromweb = 0; 1045 } 1046 1047 if ($allowfromweb < 1) { 1048 print $langs->trans("SomethingMakeInstallFromWebNotPossible"); 1049 print $message; 1050 //print $langs->trans("SomethingMakeInstallFromWebNotPossible2"); 1051 print '<br>'; 1052 } 1053 1054 print '<br>'; 1055 1056 if ($allowfromweb >= 0) { 1057 if ($allowfromweb == 1) { 1058 //print $langs->trans("ThisIsProcessToFollow").'<br>'; 1059 } else { 1060 print $langs->trans("ThisIsAlternativeProcessToFollow").'<br>'; 1061 print '<b>'.$langs->trans("StepNb", 1).'</b>: '; 1062 print str_replace('{s1}', $fullurl, $langs->trans("FindPackageFromWebSite", '{s1}')).'<br>'; 1063 print '<b>'.$langs->trans("StepNb", 2).'</b>: '; 1064 print str_replace('{s1}', $fullurl, $langs->trans("DownloadPackageFromWebSite", '{s1}')).'<br>'; 1065 print '<b>'.$langs->trans("StepNb", 3).'</b>: '; 1066 } 1067 1068 if ($allowfromweb == 1) { 1069 print $langs->trans("UnpackPackageInModulesRoot", $dirins).'<br>'; 1070 1071 print '<br>'; 1072 1073 print '<form enctype="multipart/form-data" method="POST" class="noborder" action="'.$_SERVER["PHP_SELF"].'" name="forminstall">'; 1074 print '<input type="hidden" name="token" value="'.newToken().'">'; 1075 print '<input type="hidden" name="action" value="install">'; 1076 print '<input type="hidden" name="mode" value="deploy">'; 1077 1078 print $langs->trans("YouCanSubmitFile"); 1079 1080 $max = $conf->global->MAIN_UPLOAD_DOC; // In Kb 1081 $maxphp = @ini_get('upload_max_filesize'); // In unknown 1082 if (preg_match('/k$/i', $maxphp)) { 1083 $maxphp = $maxphp * 1; 1084 } 1085 if (preg_match('/m$/i', $maxphp)) { 1086 $maxphp = $maxphp * 1024; 1087 } 1088 if (preg_match('/g$/i', $maxphp)) { 1089 $maxphp = $maxphp * 1024 * 1024; 1090 } 1091 if (preg_match('/t$/i', $maxphp)) { 1092 $maxphp = $maxphp * 1024 * 1024 * 1024; 1093 } 1094 $maxphp2 = @ini_get('post_max_size'); // In unknown 1095 if (preg_match('/k$/i', $maxphp2)) { 1096 $maxphp2 = $maxphp2 * 1; 1097 } 1098 if (preg_match('/m$/i', $maxphp2)) { 1099 $maxphp2 = $maxphp2 * 1024; 1100 } 1101 if (preg_match('/g$/i', $maxphp2)) { 1102 $maxphp2 = $maxphp2 * 1024 * 1024; 1103 } 1104 if (preg_match('/t$/i', $maxphp2)) { 1105 $maxphp2 = $maxphp2 * 1024 * 1024 * 1024; 1106 } 1107 // Now $max and $maxphp and $maxphp2 are in Kb 1108 $maxmin = $max; 1109 $maxphptoshow = $maxphptoshowparam = ''; 1110 if ($maxphp > 0) { 1111 $maxmin = min($max, $maxphp); 1112 $maxphptoshow = $maxphp; 1113 $maxphptoshowparam = 'upload_max_filesize'; 1114 } 1115 if ($maxphp2 > 0) { 1116 $maxmin = min($max, $maxphp2); 1117 if ($maxphp2 < $maxphp) { 1118 $maxphptoshow = $maxphp2; 1119 $maxphptoshowparam = 'post_max_size'; 1120 } 1121 } 1122 1123 if ($maxmin > 0) { 1124 print '<script type="text/javascript"> 1125 $(document).ready(function() { 1126 jQuery("#fileinstall").on("change", function() { 1127 if(this.files[0].size > '.($maxmin * 1024).'){ 1128 alert("'.dol_escape_js($langs->trans("ErrorFileSizeTooLarge")).'"); 1129 this.value = ""; 1130 }; 1131 }); 1132 }); 1133 </script>'."\n"; 1134 // MAX_FILE_SIZE doit précéder le champ input de type file 1135 print '<input type="hidden" name="max_file_size" value="'.($maxmin * 1024).'">'; 1136 } 1137 1138 print '<input class="flat minwidth400" type="file" name="fileinstall" id="fileinstall"> '; 1139 1140 print '<input type="submit" name="send" value="'.dol_escape_htmltag($langs->trans("Upload")).'" class="button">'; 1141 1142 if (!empty($conf->global->MAIN_UPLOAD_DOC)) { 1143 if ($user->admin) { 1144 $langs->load('other'); 1145 print ' '; 1146 print info_admin($langs->trans("ThisLimitIsDefinedInSetup", $max, $maxphptoshow, $maxphptoshowparam), 1); 1147 } 1148 } else { 1149 print ' ('.$langs->trans("UploadDisabled").')'; 1150 } 1151 1152 print '</form>'; 1153 1154 print '<br>'; 1155 print '<br>'; 1156 1157 print '<div class="center"><div class="logo_setup"></div></div>'; 1158 } else { 1159 print $langs->trans("UnpackPackageInModulesRoot", $dirins).'<br>'; 1160 print '<b>'.$langs->trans("StepNb", 4).'</b>: '; 1161 print $langs->trans("SetupIsReadyForUse").'<br>'; 1162 } 1163 } 1164 1165 if (!empty($result['return'])) { 1166 print '<br>'; 1167 1168 foreach ($result['return'] as $value) { 1169 echo $value.'<br>'; 1170 } 1171 } 1172 1173 print dol_get_fiche_end(); 1174} 1175 1176if ($mode == 'develop') { 1177 print dol_get_fiche_head($head, $mode, '', -1); 1178 1179 // Marketplace 1180 print "<table summary=\"list_of_modules\" class=\"noborder\" width=\"100%\">\n"; 1181 print "<tr class=\"liste_titre\">\n"; 1182 //print '<td>'.$langs->trans("Logo").'</td>'; 1183 print '<td colspan="2">'.$langs->trans("DevelopYourModuleDesc").'</td>'; 1184 print '<td>'.$langs->trans("URL").'</td>'; 1185 print '</tr>'; 1186 1187 print '<tr class="oddeven" height="80">'."\n"; 1188 print '<td class="left">'; 1189 print '<div class="imgmaxheight50 logo_setup"></div>'; 1190 print '</td>'; 1191 print '<td>'.$langs->trans("TryToUseTheModuleBuilder", $langs->transnoentitiesnoconv("ModuleBuilder")).'</td>'; 1192 print '<td>'.$langs->trans("SeeTopRightMenu").'</td>'; 1193 print '</tr>'; 1194 1195 print '<tr class="oddeven" height="80">'."\n"; 1196 $url = 'https://partners.dolibarr.org'; 1197 print '<td class="left">'; 1198 print'<a href="'.$url.'" target="_blank" rel="external"><img border="0" class="imgautosize imgmaxwidth180" src="'.DOL_URL_ROOT.'/theme/dolibarr_preferred_partner.png"></a>'; 1199 print '</td>'; 1200 print '<td>'.$langs->trans("DoliPartnersDesc").'</td>'; 1201 print '<td><a href="'.$url.'" target="_blank" rel="external">'.$url.'</a></td>'; 1202 print '</tr>'; 1203 1204 print "</table>\n"; 1205 1206 print dol_get_fiche_end(); 1207} 1208 1209// End of page 1210llxFooter(); 1211$db->close(); 1212