modules.php 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921
  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-2012 Regis Houssin <regis.houssin@capnetworks.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. *
  11. * This program is free software; you can redistribute it and/or modify
  12. * it under the terms of the GNU General Public License as published by
  13. * the Free Software Foundation; either version 3 of the License, or
  14. * (at your option) any later version.
  15. *
  16. * This program is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. * GNU General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU General Public License
  22. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  23. */
  24. /**
  25. * \file htdocs/admin/modules.php
  26. * \brief Page to activate/disable all modules
  27. */
  28. require '../main.inc.php';
  29. require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
  30. require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
  31. require_once DOL_DOCUMENT_ROOT.'/core/lib/geturl.lib.php';
  32. require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
  33. $langs->load("errors");
  34. $langs->load("admin");
  35. $mode=GETPOST('mode', 'alpha');
  36. if (empty($mode)) $mode='common';
  37. $action=GETPOST('action','alpha');
  38. $value=GETPOST('value', 'alpha');
  39. $page_y=GETPOST('page_y','int');
  40. $search_keyword=GETPOST('search_keyword','alpha');
  41. $search_status=GETPOST('search_status','alpha');
  42. $search_nature=GETPOST('search_nature','alpha');
  43. $search_version=GETPOST('search_version','alpha');
  44. if (! $user->admin)
  45. accessforbidden();
  46. $specialtostring=array(0=>'common', 1=>'interfaces', 2=>'other', 3=>'functional', 4=>'marketplace');
  47. $familyinfo=array(
  48. 'hr'=>array('position'=>'001', 'label'=>$langs->trans("ModuleFamilyHr")),
  49. 'crm'=>array('position'=>'006', 'label'=>$langs->trans("ModuleFamilyCrm")),
  50. 'srm'=>array('position'=>'007', 'label'=>$langs->trans("ModuleFamilySrm")),
  51. 'financial'=>array('position'=>'009', 'label'=>$langs->trans("ModuleFamilyFinancial")),
  52. 'products'=>array('position'=>'012', 'label'=>$langs->trans("ModuleFamilyProducts")),
  53. 'projects'=>array('position'=>'015', 'label'=>$langs->trans("ModuleFamilyProjects")),
  54. 'ecm'=>array('position'=>'018', 'label'=>$langs->trans("ModuleFamilyECM")),
  55. 'technic'=>array('position'=>'021', 'label'=>$langs->trans("ModuleFamilyTechnic")),
  56. 'portal'=>array('position'=>'040', 'label'=>$langs->trans("ModuleFamilyPortal")),
  57. 'interface'=>array('position'=>'050', 'label'=>$langs->trans("ModuleFamilyInterface")),
  58. 'base'=>array('position'=>'060', 'label'=>$langs->trans("ModuleFamilyBase")),
  59. 'other'=>array('position'=>'100', 'label'=>$langs->trans("ModuleFamilyOther")),
  60. );
  61. $param='';
  62. if ($search_keyword) $param.='&search_keyword='.urlencode($search_keyword);
  63. if ($search_status) $param.='&search_status='.urlencode($search_status);
  64. if ($search_nature) $param.='&search_nature='.urlencode($search_nature);
  65. if ($search_version) $param.='&search_version='.urlencode($search_version);
  66. $dirins=DOL_DOCUMENT_ROOT.'/custom';
  67. $urldolibarrmodules='https://www.dolistore.com/';
  68. /*
  69. * Actions
  70. */
  71. if (GETPOST('buttonreset'))
  72. {
  73. $search_keyword='';
  74. $search_status='';
  75. $search_nature='';
  76. $search_version='';
  77. }
  78. if ($action=='install')
  79. {
  80. $error=0;
  81. // $original_file should match format module_modulename-x.y[.z].zip
  82. $original_file=basename($_FILES["fileinstall"]["name"]);
  83. $newfile=$conf->admin->dir_temp.'/'.$original_file.'/'.$original_file;
  84. if (! $original_file)
  85. {
  86. $langs->load("Error");
  87. setEventMessages($langs->trans("ErrorModuleFileRequired"), null, 'warnings');
  88. $error++;
  89. }
  90. else
  91. {
  92. if (! preg_match('/\.zip$/i',$original_file))
  93. {
  94. $langs->load("errors");
  95. setEventMessages($langs->trans("ErrorFileMustBeADolibarrPackage",$original_file), null, 'errors');
  96. $error++;
  97. }
  98. if (! preg_match('/module_.*\-[\d]+\.[\d]+.*$/i',$original_file))
  99. {
  100. $langs->load("errors");
  101. setEventMessages($langs->trans("ErrorFilenameDosNotMatchDolibarrPackageRules",$original_file, 'module_*-x.y*.zip'), null, 'errors');
  102. $error++;
  103. }
  104. }
  105. if (! $error)
  106. {
  107. if ($original_file)
  108. {
  109. @dol_delete_dir_recursive($conf->admin->dir_temp.'/'.$original_file);
  110. dol_mkdir($conf->admin->dir_temp.'/'.$original_file);
  111. }
  112. $tmpdir=preg_replace('/\.zip$/','',$original_file).'.dir';
  113. if ($tmpdir)
  114. {
  115. @dol_delete_dir_recursive($conf->admin->dir_temp.'/'.$tmpdir);
  116. dol_mkdir($conf->admin->dir_temp.'/'.$tmpdir);
  117. }
  118. $result=dol_move_uploaded_file($_FILES['fileinstall']['tmp_name'],$newfile,1,0,$_FILES['fileinstall']['error']);
  119. if ($result > 0)
  120. {
  121. $result=dol_uncompress($newfile,$conf->admin->dir_temp.'/'.$tmpdir);
  122. if (! empty($result['error']))
  123. {
  124. $langs->load("errors");
  125. setEventMessages($langs->trans($result['error'],$original_file), null, 'errors');
  126. $error++;
  127. }
  128. else
  129. {
  130. // Now we move the dir of the module
  131. $modulename=preg_replace('/module_/', '', $original_file);
  132. $modulename=preg_replace('/\-[\d]+\.[\d]+.*$/', '', $modulename);
  133. // Search dir $modulename
  134. $modulenamedir=$conf->admin->dir_temp.'/'.$tmpdir.'/'.$modulename;
  135. //var_dump($modulenamedir);
  136. if (! dol_is_dir($modulenamedir))
  137. {
  138. $modulenamedir=$conf->admin->dir_temp.'/'.$tmpdir.'/htdocs/'.$modulename;
  139. //var_dump($modulenamedir);
  140. if (! dol_is_dir($modulenamedir))
  141. {
  142. setEventMessages($langs->trans("ErrorModuleFileSeemsToHaveAWrongFormat").'<br>Dir not found: '.$conf->admin->dir_temp.'/'.$tmpdir.'/'.$modulename.'<br>'.$conf->admin->dir_temp.'/'.$tmpdir.'/htdocs/'.$modulename, null, 'errors');
  143. $error++;
  144. }
  145. }
  146. if (! $error)
  147. {
  148. //var_dump($dirins);
  149. @dol_delete_dir_recursive($dirins.'/'.$modulename);
  150. dol_syslog("Uncompress of module file is a success. We copy it from ".$modulenamedir." into target dir ".$dirins.'/'.$modulename);
  151. $result=dolCopyDir($modulenamedir, $dirins.'/'.$modulename, '0444', 1);
  152. if ($result <= 0)
  153. {
  154. dol_syslog('Failed to call dolCopyDir result='.$result." with param ".$modulenamedir." and ".$dirins.'/'.$modulename, LOG_WARNING);
  155. $langs->load("errors");
  156. setEventMessages($langs->trans("ErrorFailToCopyDir", $modulenamedir, $dirins.'/'.$modulename), null, 'errors');
  157. $error++;
  158. }
  159. }
  160. }
  161. }
  162. else
  163. {
  164. $error++;
  165. }
  166. }
  167. if (! $error)
  168. {
  169. setEventMessages($langs->trans("SetupIsReadyForUse", DOL_URL_ROOT.'/admin/modules.php?mainmenu=home', $langs->transnoentitiesnoconv("Home").' - '.$langs->transnoentitiesnoconv("Setup").' - '.$langs->transnoentitiesnoconv("Modules")), null, 'warnings');
  170. }
  171. }
  172. if ($action == 'set' && $user->admin)
  173. {
  174. $resarray = activateModule($value);
  175. if (! empty($resarray['errors'])) setEventMessages('', $resarray['errors'], 'errors');
  176. else
  177. {
  178. //var_dump($resarray);exit;
  179. if ($resarray['nbperms'] > 0)
  180. {
  181. $msg = $langs->trans('ModuleEnabledAdminMustCheckRights');
  182. setEventMessages($msg, null, 'warnings');
  183. }
  184. }
  185. header("Location: modules.php?mode=".$mode.$param.($page_y?'&page_y='.$page_y:''));
  186. exit;
  187. }
  188. if ($action == 'reset' && $user->admin)
  189. {
  190. $result=unActivateModule($value);
  191. if ($result) setEventMessages($result, null, 'errors');
  192. header("Location: modules.php?mode=".$mode.$param.($page_y?'&page_y='.$page_y:''));
  193. exit;
  194. }
  195. /*
  196. * View
  197. */
  198. // Set dir where external modules are installed
  199. if (! dol_is_dir($dirins))
  200. {
  201. dol_mkdir($dirins);
  202. }
  203. $dirins_ok=(dol_is_dir($dirins));
  204. $form = new Form($db);
  205. $help_url='EN:First_setup|FR:Premiers_paramétrages|ES:Primeras_configuraciones';
  206. llxHeader('',$langs->trans("Setup"),$help_url);
  207. $arrayofnatures=array('core'=>$langs->transnoentitiesnoconv("Core"), 'external'=>$langs->transnoentitiesnoconv("External").' - '.$langs->trans("AllPublishers"));
  208. $arrayofwarnings=array(); // Array of warning each module want to show when activated
  209. $arrayofwarningsext=array(); // Array of warning each module want to show when we activate an external module
  210. // Search modules dirs
  211. $modulesdir = dolGetModulesDirs();
  212. $filename = array();
  213. $modules = array();
  214. $orders = array();
  215. $categ = array();
  216. $dirmod = array();
  217. $i = 0; // is a sequencer of modules found
  218. $j = 0; // j is module number. Automatically affected if module number not defined.
  219. $modNameLoaded=array();
  220. foreach ($modulesdir as $dir)
  221. {
  222. // Load modules attributes in arrays (name, numero, orders) from dir directory
  223. //print $dir."\n<br>";
  224. dol_syslog("Scan directory ".$dir." for module descriptor files (modXXX.class.php)");
  225. $handle=@opendir($dir);
  226. if (is_resource($handle))
  227. {
  228. while (($file = readdir($handle))!==false)
  229. {
  230. //print "$i ".$file."\n<br>";
  231. if (is_readable($dir.$file) && substr($file, 0, 3) == 'mod' && substr($file, dol_strlen($file) - 10) == '.class.php')
  232. {
  233. $modName = substr($file, 0, dol_strlen($file) - 10);
  234. if ($modName)
  235. {
  236. if (! empty($modNameLoaded[$modName])) // In cache of already loaded modules ?
  237. {
  238. $mesg="Error: Module ".$modName." was found twice: Into ".$modNameLoaded[$modName]." and ".$dir.". You probably have an old file on your disk.<br>";
  239. setEventMessages($mesg, null, 'warnings');
  240. dol_syslog($mesg, LOG_ERR);
  241. continue;
  242. }
  243. try
  244. {
  245. $res=include_once $dir.$file; // A class already exists in a different file will send a non catchable fatal error.
  246. if (class_exists($modName))
  247. {
  248. try {
  249. $objMod = new $modName($db);
  250. $modNameLoaded[$modName]=$dir;
  251. if (! $objMod->numero > 0 && $modName != 'modUser')
  252. {
  253. dol_syslog('The module descriptor '.$modName.' must have a numero property', LOG_ERR);
  254. }
  255. $j = $objMod->numero;
  256. $modulequalified=1;
  257. // We discard modules according to features level (PS: if module is activated we always show it)
  258. $const_name = 'MAIN_MODULE_'.strtoupper(preg_replace('/^mod/i','',get_class($objMod)));
  259. if ($objMod->version == 'development' && (empty($conf->global->$const_name) && ($conf->global->MAIN_FEATURES_LEVEL < 2))) $modulequalified=0;
  260. if ($objMod->version == 'experimental' && (empty($conf->global->$const_name) && ($conf->global->MAIN_FEATURES_LEVEL < 1))) $modulequalified=0;
  261. if (preg_match('/deprecated/', $objMod->version) && (empty($conf->global->$const_name) && ($conf->global->MAIN_FEATURES_LEVEL >= 0))) $modulequalified=0;
  262. // We discard modules according to property ->hidden
  263. if (! empty($objMod->hidden)) $modulequalified=0;
  264. if ($modulequalified > 0)
  265. {
  266. $publisher=dol_escape_htmltag($objMod->getPublisher());
  267. $external=($objMod->isCoreOrExternalModule() == 'external');
  268. if ($external)
  269. {
  270. if ($publisher)
  271. {
  272. $arrayofnatures['external_'.$publisher]=$langs->trans("External").' - '.$publisher;
  273. }
  274. else
  275. {
  276. $arrayofnatures['external_']=$langs->trans("External").' - '.$langs->trans("UnknownPublishers");
  277. }
  278. }
  279. ksort($arrayofnatures);
  280. }
  281. // Define array $categ with categ with at least one qualified module
  282. if ($modulequalified > 0)
  283. {
  284. $filename[$i]= $modName;
  285. $modules[$modName] = $objMod;
  286. $special = $objMod->special;
  287. // Gives the possibility to the module, to provide his own family info and position of this family
  288. if (is_array($objMod->familyinfo) && !empty($objMod->familyinfo)) {
  289. $familyinfo = array_merge($familyinfo, $objMod->familyinfo);
  290. $familykey = key($objMod->familyinfo);
  291. } else {
  292. $familykey = $objMod->family;
  293. }
  294. $moduleposition = ($objMod->module_position?$objMod->module_position:'500');
  295. if ($moduleposition == 500 && ($objMod->isCoreOrExternalModule() == 'external'))
  296. {
  297. $moduleposition = 800;
  298. }
  299. if ($special == 1) $familykey='interface';
  300. // Add list of warnings to show into arrayofwarnings and arrayofwarningsext
  301. if (! empty($objMod->warnings_activation))
  302. {
  303. $arrayofwarnings[$modName]=$objMod->warnings_activation;
  304. }
  305. if (! empty($objMod->warnings_activation_ext))
  306. {
  307. $arrayofwarningsext[$modName]=$objMod->warnings_activation_ext;
  308. }
  309. $orders[$i] = $familyinfo[$familykey]['position']."_".$familykey."_".$moduleposition."_".$j; // Sort by family, then by module position then number
  310. $dirmod[$i] = $dir;
  311. //print $i.'-'.$dirmod[$i].'<br>';
  312. // Set categ[$i]
  313. $specialstring = isset($specialtostring[$special])?$specialtostring[$special]:'unknown';
  314. if ($objMod->version == 'development' || $objMod->version == 'experimental') $specialstring='expdev';
  315. if (isset($categ[$specialstring])) $categ[$specialstring]++; // Array of all different modules categories
  316. else $categ[$specialstring]=1;
  317. $j++;
  318. $i++;
  319. }
  320. else dol_syslog("Module ".get_class($objMod)." not qualified");
  321. }
  322. catch(Exception $e)
  323. {
  324. dol_syslog("Failed to load ".$dir.$file." ".$e->getMessage(), LOG_ERR);
  325. }
  326. }
  327. else
  328. {
  329. print "Warning bad descriptor file : ".$dir.$file." (Class ".$modName." not found into file)<br>";
  330. }
  331. }
  332. catch(Exception $e)
  333. {
  334. dol_syslog("Failed to load ".$dir.$file." ".$e->getMessage(), LOG_ERR);
  335. }
  336. }
  337. }
  338. }
  339. closedir($handle);
  340. }
  341. else
  342. {
  343. dol_syslog("htdocs/admin/modules.php: Failed to open directory ".$dir.". See permission and open_basedir option.", LOG_WARNING);
  344. }
  345. }
  346. asort($orders);
  347. //var_dump($orders);
  348. //var_dump($categ);
  349. //var_dump($modules);
  350. $nbofactivatedmodules=count($conf->modules);
  351. $moreinfo=$langs->trans("TotalNumberOfActivatedModules",($nbofactivatedmodules-1), count($modules));
  352. if ($nbofactivatedmodules <= 1) $moreinfo .= ' '.img_warning($langs->trans("YouMustEnableOneModule"));
  353. print load_fiche_titre($langs->trans("ModulesSetup"),$moreinfo,'title_setup');
  354. // Start to show page
  355. if ($mode=='common') print '<span class="opacitymedium">'.$langs->trans("ModulesDesc")."</span><br>\n";
  356. if ($mode=='marketplace') print '<span class="opacitymedium">'.$langs->trans("ModulesMarketPlaceDesc")."</span><br>\n";
  357. if ($mode=='deploy') print '<span class="opacitymedium">'.$langs->trans("ModulesDeployDesc", $langs->transnoentitiesnoconv("AvailableModules"))."</span><br>\n";
  358. $h = 0;
  359. $head[$h][0] = DOL_URL_ROOT."/admin/modules.php?mode=common";
  360. $head[$h][1] = $langs->trans("AvailableModules");
  361. $head[$h][2] = 'common';
  362. $h++;
  363. $head[$h][0] = DOL_URL_ROOT."/admin/modules.php?mode=marketplace";
  364. $head[$h][1] = $langs->trans("ModulesMarketPlaces");
  365. $head[$h][2] = 'marketplace';
  366. $h++;
  367. $head[$h][0] = DOL_URL_ROOT."/admin/modules.php?mode=deploy";
  368. $head[$h][1] = $langs->trans("AddExtensionThemeModuleOrOther");
  369. $head[$h][2] = 'deploy';
  370. $h++;
  371. print "<br>\n";
  372. if ($mode == 'common')
  373. {
  374. print '<form method="GET" id="searchFormList" action="'.$_SERVER["PHP_SELF"].'">';
  375. if ($optioncss != '') print '<input type="hidden" name="optioncss" value="'.$optioncss.'">';
  376. print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
  377. print '<input type="hidden" name="sortfield" value="'.$sortfield.'">';
  378. print '<input type="hidden" name="sortorder" value="'.$sortorder.'">';
  379. print '<input type="hidden" name="page" value="'.$page.'">';
  380. dol_fiche_head($head, $mode, '', -1);
  381. $moreforfilter = '';
  382. $moreforfilter.='<div class="divsearchfield">';
  383. $moreforfilter.= $langs->trans('Keyword') . ': <input type="text" name="search_keyword" value="'.dol_escape_htmltag($search_keyword).'">';
  384. $moreforfilter.= '</div>';
  385. $moreforfilter.='<div class="divsearchfield">';
  386. $moreforfilter.= $langs->trans('Origin') . ': '.$form->selectarray('search_nature', $arrayofnatures, dol_escape_htmltag($search_nature), 1);
  387. $moreforfilter.= '</div>';
  388. if (! empty($conf->global->MAIN_FEATURES_LEVEL))
  389. {
  390. $array_version = array('stable'=>$langs->transnoentitiesnoconv("Stable"));
  391. if ($conf->global->MAIN_FEATURES_LEVEL < 0) $array_version['deprecated']=$langs->trans("Deprecated");
  392. if ($conf->global->MAIN_FEATURES_LEVEL > 0) $array_version['experimental']=$langs->trans("Experimental");
  393. if ($conf->global->MAIN_FEATURES_LEVEL > 1) $array_version['development']=$langs->trans("Development");
  394. $moreforfilter.='<div class="divsearchfield">';
  395. $moreforfilter.= $langs->trans('Version') . ': '.$form->selectarray('search_version', $array_version, $search_version, 1);
  396. $moreforfilter.= '</div>';
  397. }
  398. $moreforfilter.='<div class="divsearchfield">';
  399. $moreforfilter.= $langs->trans('Status') . ': '.$form->selectarray('search_status', array('active'=>$langs->transnoentitiesnoconv("Enabled"), 'disabled'=>$langs->transnoentitiesnoconv("Disabled")), $search_status, 1);
  400. $moreforfilter.= '</div>';
  401. $moreforfilter.=' ';
  402. $moreforfilter.='<div class="divsearchfield">';
  403. $moreforfilter.='<input type="submit" name="buttonsubmit" class="button" value="'.dol_escape_htmltag($langs->trans("Refresh")).'">';
  404. $moreforfilter.=' ';
  405. $moreforfilter.='<input type="submit" name="buttonreset" class="button" value="'.dol_escape_htmltag($langs->trans("Reset")).'">';
  406. $moreforfilter.= '</div>';
  407. if (! empty($moreforfilter))
  408. {
  409. print $moreforfilter;
  410. $parameters=array();
  411. $reshook=$hookmanager->executeHooks('printFieldPreListTitle',$parameters); // Note that $action and $object may have been modified by hook
  412. print $hookmanager->resPrint;
  413. }
  414. print '<div class="clearboth"></div><br>';
  415. $moreforfilter='';
  416. // Show list of modules
  417. $oldfamily='';
  418. foreach ($orders as $key => $value)
  419. {
  420. $tab=explode('_',$value);
  421. $familyposition=$tab[0]; $familykey=$tab[1]; $module_position=$tab[2]; $numero=$tab[3];
  422. $modName = $filename[$key];
  423. $objMod = $modules[$modName];
  424. $dirofmodule = $dirmod[$key];
  425. $special = $objMod->special;
  426. //print $objMod->name." - ".$key." - ".$objMod->special.' - '.$objMod->version."<br>";
  427. //if (($mode != (isset($specialtostring[$special])?$specialtostring[$special]:'unknown') && $mode != 'expdev')
  428. if (($special >= 4 && $mode != 'expdev')
  429. || ($mode == 'expdev' && $objMod->version != 'development' && $objMod->version != 'experimental')) continue; // Discard if not for current tab
  430. if (! $objMod->getName())
  431. {
  432. dol_syslog("Error for module ".$key." - Property name of module looks empty", LOG_WARNING);
  433. continue;
  434. }
  435. $const_name = 'MAIN_MODULE_'.strtoupper(preg_replace('/^mod/i','',get_class($objMod)));
  436. // Check filters
  437. $modulename=$objMod->getName();
  438. $moduletechnicalname=$objMod->name;
  439. $moduledesc=$objMod->getDesc();
  440. $moduledesclong=$objMod->getDescLong();
  441. $moduleauthor=$objMod->getPublisher();
  442. // We discard showing according to filters
  443. if ($search_keyword)
  444. {
  445. $qualified=0;
  446. if (preg_match('/'.preg_quote($search_keyword).'/i', $modulename)
  447. || preg_match('/'.preg_quote($search_keyword).'/i', $moduletechnicalname)
  448. || preg_match('/'.preg_quote($search_keyword).'/i', $moduledesc)
  449. || preg_match('/'.preg_quote($search_keyword).'/i', $moduledesclong)
  450. || preg_match('/'.preg_quote($search_keyword).'/i', $moduleauthor)
  451. ) $qualified=1;
  452. if (! $qualified) continue;
  453. }
  454. if ($search_status)
  455. {
  456. if ($search_status == 'active' && empty($conf->global->$const_name)) continue;
  457. if ($search_status == 'disabled' && ! empty($conf->global->$const_name)) continue;
  458. }
  459. if ($search_nature)
  460. {
  461. if (preg_match('/^external/',$search_nature) && $objMod->isCoreOrExternalModule() != 'external') continue;
  462. if (preg_match('/^external_(.*)$/',$search_nature, $reg))
  463. {
  464. //print $reg[1].'-'.dol_escape_htmltag($objMod->getPublisher());
  465. $publisher=dol_escape_htmltag($objMod->getPublisher());
  466. if ($reg[1] && dol_escape_htmltag($reg[1]) != $publisher) continue;
  467. if (! $reg[1] && ! empty($publisher)) continue;
  468. }
  469. if ($search_nature == 'core' && $objMod->isCoreOrExternalModule() == 'external') continue;
  470. }
  471. if ($search_version)
  472. {
  473. if (($objMod->version == 'development' || $objMod->version == 'experimental' || preg_match('/deprecated/', $objMod->version)) && $search_version == 'stable') continue;
  474. if ($objMod->version != 'development' && ($search_version == 'development')) continue;
  475. if ($objMod->version != 'experimental' && ($search_version == 'experimental')) continue;
  476. if (! preg_match('/deprecated/', $objMod->version) && ($search_version == 'deprecated')) continue;
  477. }
  478. // Load all lang files of module
  479. if (isset($objMod->langfiles) && is_array($objMod->langfiles))
  480. {
  481. foreach($objMod->langfiles as $domain)
  482. {
  483. $langs->load($domain);
  484. }
  485. }
  486. // Print a separator if we change family
  487. if ($familykey!=$oldfamily)
  488. {
  489. if ($oldfamily) print '</table></div><br>';
  490. $familytext=empty($familyinfo[$familykey]['label'])?$familykey:$familyinfo[$familykey]['label'];
  491. print_fiche_titre($familytext, '', '');
  492. print '<div class="div-table-responsive">';
  493. print '<table class="tagtable liste" summary="list_of_modules">'."\n";
  494. $atleastoneforfamily=0;
  495. }
  496. $atleastoneforfamily++;
  497. if ($familykey!=$oldfamily)
  498. {
  499. $familytext=empty($familyinfo[$familykey]['label'])?$familykey:$familyinfo[$familykey]['label'];
  500. $oldfamily=$familykey;
  501. }
  502. // Version (with picto warning or not)
  503. $version=$objMod->getVersion(0);
  504. $versiontrans='';
  505. if (preg_match('/development/i', $version)) $versiontrans.=img_warning($langs->trans("Development"), 'style="float: left"');
  506. if (preg_match('/experimental/i', $version)) $versiontrans.=img_warning($langs->trans("Experimental"), 'style="float: left"');
  507. if (preg_match('/deprecated/i', $version)) $versiontrans.=img_warning($langs->trans("Deprecated"), 'style="float: left"');
  508. $versiontrans.=$objMod->getVersion(1);
  509. // Define imginfo
  510. $imginfo="info";
  511. if ($objMod->isCoreOrExternalModule() == 'external')
  512. {
  513. $imginfo="info_black";
  514. }
  515. print '<tr>'."\n";
  516. // Picto + Name of module
  517. print ' <td width="200px">';
  518. $alttext='';
  519. //if (is_array($objMod->need_dolibarr_version)) $alttext.=($alttext?' - ':'').'Dolibarr >= '.join('.',$objMod->need_dolibarr_version);
  520. //if (is_array($objMod->phpmin)) $alttext.=($alttext?' - ':'').'PHP >= '.join('.',$objMod->phpmin);
  521. if (! empty($objMod->picto))
  522. {
  523. if (preg_match('/^\//i',$objMod->picto)) print img_picto($alttext,$objMod->picto,' width="14px"',1);
  524. else print img_object($alttext, $objMod->picto, 'class="valignmiddle" width="14px"');
  525. }
  526. else
  527. {
  528. print img_object($alttext, 'generic', 'class="valignmiddle"');
  529. }
  530. print ' <span class="valignmiddle">'.$objMod->getName().'</span>';
  531. print "</td>\n";
  532. // Desc
  533. print '<td class="valignmiddle tdoverflowmax300">';
  534. print nl2br($objMod->getDesc());
  535. print "</td>\n";
  536. // Help
  537. print '<td class="center nowrap" style="width: 82px;">';
  538. //print $form->textwithpicto('', $text, 1, $imginfo, 'minheight20', 0, 2, 1);
  539. 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($langs->trans("ClickToShowDescription"), $imginfo).'</a>';
  540. print '</td>';
  541. // Version
  542. print '<td class="center nowrap" width="120px">';
  543. print $versiontrans;
  544. print "</td>\n";
  545. // Activate/Disable and Setup (2 columns)
  546. if (! empty($conf->global->$const_name)) // If module is already activated
  547. {
  548. $disableSetup = 0;
  549. // Link enable/disabme
  550. print '<td class="center valignmiddle" width="60px">';
  551. if (! empty($arrayofwarnings[$modName]))
  552. {
  553. print '<!-- This module has a warning to show when we activate it (note: your country is '.$mysoc->country_code.') -->'."\n";
  554. }
  555. if (! empty($objMod->disabled))
  556. {
  557. print $langs->trans("Disabled");
  558. }
  559. else if (! empty($objMod->always_enabled) || ((! empty($conf->multicompany->enabled) && $objMod->core_enabled) && ($user->entity || $conf->entity!=1)))
  560. {
  561. print $langs->trans("Required");
  562. if (! empty($conf->multicompany->enabled) && $user->entity) $disableSetup++;
  563. }
  564. else
  565. {
  566. print '<a class="reposition" href="modules.php?id='.$objMod->numero.'&amp;module_position='.$module_position.'&amp;action=reset&amp;value=' . $modName . '&amp;mode=' . $mode . $param . '">';
  567. print img_picto($langs->trans("Activated"),'switch_on');
  568. print '</a>';
  569. }
  570. print '</td>'."\n";
  571. // Link config
  572. if (! empty($objMod->config_page_url) && !$disableSetup)
  573. {
  574. if (is_array($objMod->config_page_url))
  575. {
  576. print '<td class="tdsetuppicto right" width="60px">';
  577. $i=0;
  578. foreach ($objMod->config_page_url as $page)
  579. {
  580. $urlpage=$page;
  581. if ($i++)
  582. {
  583. print '<a href="'.$urlpage.'" title="'.$langs->trans($page).'">'.img_picto(ucfirst($page),"setup").'</a>';
  584. // print '<a href="'.$page.'">'.ucfirst($page).'</a>&nbsp;';
  585. }
  586. else
  587. {
  588. if (preg_match('/^([^@]+)@([^@]+)$/i',$urlpage,$regs))
  589. {
  590. print '<a href="'.dol_buildpath('/'.$regs[2].'/admin/'.$regs[1],1).'" title="'.$langs->trans("Setup").'">'.img_picto($langs->trans("Setup"),"setup",'style="padding-right: 6px"').'</a>';
  591. }
  592. else
  593. {
  594. print '<a href="'.$urlpage.'" title="'.$langs->trans("Setup").'">'.img_picto($langs->trans("Setup"),"setup",'style="padding-right: 6px"').'</a>';
  595. }
  596. }
  597. }
  598. print "</td>\n";
  599. }
  600. else if (preg_match('/^([^@]+)@([^@]+)$/i',$objMod->config_page_url,$regs))
  601. {
  602. print '<td class="tdsetuppicto right valignmiddle" width="60px"><a href="'.dol_buildpath('/'.$regs[2].'/admin/'.$regs[1],1).'" title="'.$langs->trans("Setup").'">'.img_picto($langs->trans("Setup"),"setup",'style="padding-right: 6px"').'</a></td>';
  603. }
  604. else
  605. {
  606. print '<td class="tdsetuppicto right valignmiddle" width="60px"><a href="'.$objMod->config_page_url.'" title="'.$langs->trans("Setup").'">'.img_picto($langs->trans("Setup"),"setup",'style="padding-right: 6px"').'</a></td>';
  607. }
  608. }
  609. else
  610. {
  611. print '<td class="tdsetuppicto right valignmiddle" width="60px">'.img_picto($langs->trans("NothingToSetup"),"setup",'class="opacitytransp" style="padding-right: 6px"').'</td>';
  612. }
  613. }
  614. else // Module not yet activated
  615. {
  616. // Link enable/disable
  617. print '<td class="center valignmiddle" width="60px">';
  618. if (! empty($objMod->always_enabled))
  619. {
  620. // Should never happened
  621. }
  622. else if (! empty($objMod->disabled))
  623. {
  624. print $langs->trans("Disabled");
  625. }
  626. else
  627. {
  628. // Module qualified for activation
  629. $warningmessage='';
  630. if (! empty($arrayofwarnings[$modName]))
  631. {
  632. print '<!-- This module has a warning to show when we activate it (note: your country is '.$mysoc->country_code.') -->'."\n";
  633. foreach ($arrayofwarnings[$modName] as $keycountry => $cursorwarningmessage)
  634. {
  635. $warningmessage .= ($warningmessage?"\n":"").$langs->trans($cursorwarningmessage, $objMod->getName(), $mysoc->country_code);
  636. }
  637. }
  638. if ($objMod->isCoreOrExternalModule() == 'external' && ! empty($arrayofwarningsext))
  639. {
  640. print '<!-- This module is an external module and it may have a warning to show (note: your country is '.$mysoc->country_code.') -->'."\n";
  641. foreach ($arrayofwarningsext as $keymodule => $arrayofwarningsextbycountry)
  642. {
  643. if (! empty($modules[$keymodule]->const_name)) // If module that request warning is on
  644. {
  645. foreach ($arrayofwarningsextbycountry as $keycountry => $cursorwarningmessage)
  646. {
  647. if ($keycountry == 'always' || $keycountry == $mysoc->country_code)
  648. {
  649. $warningmessage .= ($warningmessage?"\n":"").$langs->trans($cursorwarningmessage, $objMod->getName(), $mysoc->country_code, $modules[$keymodule]->getName());
  650. }
  651. }
  652. }
  653. }
  654. }
  655. print '<!-- Message to show: '.$warningmessage.' -->'."\n";
  656. print '<a class="reposition" href="modules.php?id='.$objMod->numero.'&amp;module_position='.$module_position.'&amp;action=set&amp;value=' . $modName . '&amp;mode=' . $mode . $param . '"';
  657. if ($warningmessage) print ' onclick="return confirm(\''.dol_escape_js($warningmessage).'\');"';
  658. print '>';
  659. print img_picto($langs->trans("Disabled"),'switch_off');
  660. print "</a>\n";
  661. }
  662. print "</td>\n";
  663. // Link config
  664. print '<td class="tdsetuppicto right valignmiddle" width="60px">'.img_picto($langs->trans("NothingToSetup"),"setup",'class="opacitytransp" style="padding-right: 6px"').'</td>';
  665. }
  666. print "</tr>\n";
  667. }
  668. if ($oldfamily)
  669. {
  670. print "</table>\n";
  671. print '</div>';
  672. }
  673. dol_fiche_end();
  674. // Show warning about external users
  675. print info_admin(showModulesExludedForExternal($modules))."\n";
  676. print '</form>';
  677. }
  678. if ($mode == 'marketplace')
  679. {
  680. dol_fiche_head($head, $mode, '', -1);
  681. // Marketplace
  682. print "<table summary=\"list_of_modules\" class=\"noborder\" width=\"100%\">\n";
  683. print "<tr class=\"liste_titre\">\n";
  684. //print '<td>'.$langs->trans("Logo").'</td>';
  685. print '<td colspan="2">'.$langs->trans("WebSiteDesc").'</td>';
  686. print '<td>'.$langs->trans("URL").'</td>';
  687. print '</tr>';
  688. print "<tr class=\"oddeven\">\n";
  689. $url='https://www.dolistore.com';
  690. print '<td align="left"><a href="'.$url.'" target="_blank" rel="external"><img border="0" class="imgautosize imgmaxwidth180" src="'.DOL_URL_ROOT.'/theme/dolistore_logo.png"></a></td>';
  691. print '<td>'.$langs->trans("DoliStoreDesc").'</td>';
  692. print '<td><a href="'.$url.'" target="_blank" rel="external">'.$url.'</a></td>';
  693. print '</tr>';
  694. print "<tr class=\"oddeven\">\n";
  695. $url='https://partners.dolibarr.org';
  696. print '<td align="left"><a href="'.$url.'" target="_blank" rel="external"><img border="0" class="imgautosize imgmaxwidth180" src="'.DOL_URL_ROOT.'/theme/dolibarr_preferred_partner_int.png"></a></td>';
  697. print '<td>'.$langs->trans("DoliPartnersDesc").'</td>';
  698. print '<td><a href="'.$url.'" target="_blank" rel="external">'.$url.'</a></td>';
  699. print '</tr>';
  700. print "</table>\n";
  701. dol_fiche_end();
  702. }
  703. // Install external module
  704. if ($mode == 'deploy')
  705. {
  706. dol_fiche_head($head, $mode, '', -1);
  707. $allowonlineinstall=true;
  708. $allowfromweb=1;
  709. if (dol_is_file($dolibarrdataroot.'/installmodules.lock')) $allowonlineinstall=false;
  710. $fullurl='<a href="'.$urldolibarrmodules.'" target="_blank">'.$urldolibarrmodules.'</a>';
  711. $message='';
  712. if (! empty($allowonlineinstall))
  713. {
  714. if (! in_array('/custom',explode(',',$dolibarr_main_url_root_alt)))
  715. {
  716. $message=info_admin($langs->trans("ConfFileMuseContainCustom", DOL_DOCUMENT_ROOT.'/custom', DOL_DOCUMENT_ROOT));
  717. $allowfromweb=-1;
  718. }
  719. else
  720. {
  721. if ($dirins_ok)
  722. {
  723. if (! is_writable(dol_osencode($dirins)))
  724. {
  725. $langs->load("errors");
  726. $message=info_admin($langs->trans("ErrorFailedToWriteInDir",$dirins));
  727. $allowfromweb=0;
  728. }
  729. }
  730. else
  731. {
  732. $message=info_admin($langs->trans("NotExistsDirect",$dirins).$langs->trans("InfDirAlt").$langs->trans("InfDirExample"));
  733. $allowfromweb=0;
  734. }
  735. }
  736. }
  737. else
  738. {
  739. $message=info_admin($langs->trans("InstallModuleFromWebHasBeenDisabledByFile",$dolibarrdataroot.'/installmodules.lock'));
  740. $allowfromweb=0;
  741. }
  742. if ($allowfromweb < 1)
  743. {
  744. print $langs->trans("SomethingMakeInstallFromWebNotPossible");
  745. print $message;
  746. //print $langs->trans("SomethingMakeInstallFromWebNotPossible2");
  747. print '<br>';
  748. }
  749. if ($allowfromweb >= 0)
  750. {
  751. if ($allowfromweb == 1)
  752. {
  753. //print $langs->trans("ThisIsProcessToFollow").'<br>';
  754. }
  755. else
  756. {
  757. print $langs->trans("ThisIsAlternativeProcessToFollow").'<br>';
  758. print '<b>'.$langs->trans("StepNb",1).'</b>: ';
  759. print $langs->trans("FindPackageFromWebSite",$fullurl).'<br>';
  760. print '<b>'.$langs->trans("StepNb",2).'</b>: ';
  761. print $langs->trans("DownloadPackageFromWebSite",$fullurl).'<br>';
  762. print '<b>'.$langs->trans("StepNb",3).'</b>: ';
  763. }
  764. if ($allowfromweb == 1)
  765. {
  766. print $langs->trans("UnpackPackageInModulesRoot",$dirins).'<br>';
  767. print '<form enctype="multipart/form-data" method="POST" class="noborder" action="'.$_SERVER["PHP_SELF"].'" name="forminstall">';
  768. print '<input type="hidden" name="action" value="install">';
  769. print '<input type="hidden" name="mode" value="deploy">';
  770. print $langs->trans("YouCanSubmitFile").' <input type="file" name="fileinstall"> ';
  771. print '<input type="submit" name="send" value="'.dol_escape_htmltag($langs->trans("Send")).'" class="button">';
  772. print '</form>';
  773. }
  774. else
  775. {
  776. print $langs->trans("UnpackPackageInModulesRoot",$dirins).'<br>';
  777. print '<b>'.$langs->trans("StepNb",4).'</b>: ';
  778. print $langs->trans("SetupIsReadyForUse").'<br>';
  779. }
  780. }
  781. if (! empty($result['return']))
  782. {
  783. print '<br>';
  784. foreach($result['return'] as $value)
  785. {
  786. echo $value.'<br>';
  787. }
  788. }
  789. dol_fiche_end();
  790. }
  791. llxFooter();
  792. $db->close();