33if (!defined(
'CSRFCHECK_WITH_TOKEN') && (empty($_GET[
'action']) || $_GET[
'action'] !=
'reset')) {
34 define(
'CSRFCHECK_WITH_TOKEN',
'1');
38require
'../main.inc.php';
39require_once DOL_DOCUMENT_ROOT.
'/core/lib/admin.lib.php';
40require_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
41require_once DOL_DOCUMENT_ROOT.
'/core/lib/geturl.lib.php';
42require_once DOL_DOCUMENT_ROOT.
'/core/lib/functions2.lib.php';
43require_once DOL_DOCUMENT_ROOT.
'/core/modules/DolibarrModules.class.php';
44require_once DOL_DOCUMENT_ROOT.
'/admin/remotestore/class/externalModules.class.php';
47@phan-var-force string $dolibarr_main_url_root_alt
62$langs->loadLangs(array(
"errors",
"admin",
"modulebuilder"));
65if (GETPOSTISSET(
'mode')) {
66 $mode =
GETPOST(
'mode',
'alpha');
67 if ($mode ==
'common' || $mode ==
'commonkanban') {
74$action =
GETPOST(
'action',
'aZ09');
76$optioncss =
GETPOST(
'optioncss',
'aZ09');
78$value =
GETPOST(
'value',
'alpha');
79$search_keyword =
GETPOST(
'search_keyword',
'alpha');
80$search_status =
GETPOST(
'search_status',
'alpha');
81$search_nature =
GETPOST(
'search_nature',
'alpha');
82$search_version =
GETPOST(
'search_version',
'alpha');
87$options[
'per_page'] = 11;
90$options[
'search'] =
GETPOST(
'search_keyword',
'alpha');
93if (
GETPOST(
'buttonsubmit',
'alphanohtml', 2)) {
94 $options[
'no_page'] = 1;
98$options[
'search_source_dolistore'] =
getDolGlobalInt(
'MAIN_ENABLE_EXTERNALMODULES_DOLISTORE');
100$options[
'search_source_github'] =
getDolGlobalInt(
'MAIN_ENABLE_EXTERNALMODULES_COMMUNITY');
107 'hr' => array(
'position' =>
'001',
'label' => $langs->trans(
"ModuleFamilyHr")),
108 'crm' => array(
'position' =>
'006',
'label' => $langs->trans(
"ModuleFamilyCrm")),
109 'srm' => array(
'position' =>
'007',
'label' => $langs->trans(
"ModuleFamilySrm")),
110 'financial' => array(
'position' =>
'009',
'label' => $langs->trans(
"ModuleFamilyFinancial")),
111 'products' => array(
'position' =>
'012',
'label' => $langs->trans(
"ModuleFamilyProducts")),
112 'projects' => array(
'position' =>
'015',
'label' => $langs->trans(
"ModuleFamilyProjects")),
113 'ecm' => array(
'position' =>
'018',
'label' => $langs->trans(
"ModuleFamilyECM")),
114 'technic' => array(
'position' =>
'021',
'label' => $langs->trans(
"ModuleFamilyTechnic")),
115 'portal' => array(
'position' =>
'040',
'label' => $langs->trans(
"ModuleFamilyPortal")),
116 'interface' => array(
'position' =>
'050',
'label' => $langs->trans(
"ModuleFamilyInterface")),
117 'base' => array(
'position' =>
'060',
'label' => $langs->trans(
"ModuleFamilyBase")),
118 'other' => array(
'position' =>
'100',
'label' => $langs->trans(
"ModuleFamilyOther")),
122if (!
GETPOST(
'buttonreset',
'alpha')) {
123 if ($search_keyword) {
124 $param .=
'&search_keyword='.urlencode($search_keyword);
126 if ($search_status && $search_status !=
'-1') {
127 $param .=
'&search_status='.urlencode($search_status);
129 if ($search_nature && $search_nature !=
'-1') {
130 $param .=
'&search_nature='.urlencode($search_nature);
132 if ($search_version && $search_version !=
'-1') {
133 $param .=
'&search_version='.urlencode($search_version);
137$dirins = DOL_DOCUMENT_ROOT.
'/custom';
138$urldolibarrmodules =
'https://www.dolistore.com/';
141$hookmanager->initHooks(array(
'adminmodules',
'globaladmin'));
144$max_execution_time_for_deploy =
getDolGlobalInt(
'MODULE_UPLOAD_MAX_EXECUTION_TIME', 300);
145if (!empty($max_execution_time_for_deploy)) {
146 $err = error_reporting();
149 @set_time_limit($max_execution_time_for_deploy);
150 error_reporting($err);
153$max_time = @ini_get(
"max_execution_time");
154if ($max_time && $max_time < $max_execution_time_for_deploy) {
155 dol_syslog(
"max_execution_time=".$max_time.
" is lower than max_execution_time_for_deploy=".$max_execution_time_for_deploy.
". We try to increase it dynamically.");
156 @ini_set(
"max_execution_time", $max_execution_time_for_deploy);
160$dolibarrdataroot = preg_replace(
'/([\\/]+)$/i',
'', DOL_DATA_ROOT);
161$allowonlineinstall =
true;
163if (
dol_is_file($dolibarrdataroot.
'/installmodules.lock')) {
164 $allowonlineinstall =
false;
169if ($mode ==
'marketplace') {
171 $remotestore->loadRemoteSources();
183$parameters = array();
184$reshook = $hookmanager->executeHooks(
'doActions', $parameters, $object, $action);
189if (
GETPOST(
'buttonreset',
'alpha')) {
190 $search_keyword =
'';
193 $search_version =
'';
196if ($action ==
'install' && $allowonlineinstall) {
200 $original_file = basename($_FILES[
"fileinstall"][
"name"]);
201 $original_file = preg_replace(
'/\s*\(\d+\)\.zip$/i',
'.zip', $original_file);
202 $newfile =
$conf->admin->dir_temp.
'/'.$original_file.
'/'.$original_file;
204 if (!$original_file) {
205 $langs->load(
"Error");
206 setEventMessages($langs->trans(
"ErrorModuleFileRequired"),
null,
'warnings');
209 if (!$error && !preg_match(
'/\.zip$/i', $original_file)) {
210 $langs->load(
"errors");
211 setEventMessages($langs->trans(
"ErrorFileMustBeADolibarrPackage", $original_file),
null,
'errors');
214 if (!$error && !preg_match(
'/^(module[a-zA-Z0-9]*_|theme_|).*\-([0-9][0-9\.]*)(\s\(\d+\)\s)?\.zip$/i', $original_file)) {
215 $langs->load(
"errors");
216 setEventMessages($langs->trans(
"ErrorFilenameDosNotMatchDolibarrPackageRules", $original_file,
'modulename-x[.y.z].zip'),
null,
'errors');
219 if (empty($_FILES[
'fileinstall'][
'tmp_name'])) {
220 $langs->load(
"errors");
227 if ($original_file) {
232 $tmpdir = preg_replace(
'/\.zip$/i',
'', $original_file).
'.dir';
238 $result =
dol_move_uploaded_file($_FILES[
'fileinstall'][
'tmp_name'], $newfile, 1, 0, $_FILES[
'fileinstall'][
'error']);
242 if (!empty($result[
'error'])) {
243 $langs->load(
"errors");
244 setEventMessages($langs->trans($result[
'error'], $original_file),
null,
'errors');
248 $modulename = preg_replace(
'/module_/',
'', $original_file);
249 $modulename = preg_replace(
'/\-([0-9][0-9\.]*)\.zip$/i',
'', $modulename);
251 $modulenamedir =
$conf->admin->dir_temp.
'/'.$tmpdir.
'/'.$modulename;
254 $modulenamedir =
$conf->admin->dir_temp.
'/'.$tmpdir.
'/htdocs/'.$modulename;
257 setEventMessages($langs->trans(
"ErrorModuleFileSeemsToHaveAWrongFormat").
'<br>'.$langs->trans(
"ErrorModuleFileSeemsToHaveAWrongFormat2", $modulename,
'htdocs/'.$modulename),
null,
'errors');
262 dol_syslog(
"Uncompress of module file is a success.");
301 if (
GETPOST(
'checkforcompliance') ==
'on') {
303 $res = include_once DOL_DOCUMENT_ROOT.
'/core/modules/DolibarrModules.class.php';
305 $checkRes = $dolibarrmodule->checkForcompliance($modulename);
307 if (!is_numeric($checkRes) && $checkRes !=
'') {
308 $langs->load(
"errors");
309 setEventMessages($modulename.
' : '.$langs->trans($checkRes),
null,
'errors');
323 $modulenamearrays = array();
324 if (
dol_is_file($modulenamedir.
'/metapackage.conf')) {
326 $metafile = file_get_contents($modulenamedir.
'/metapackage.conf');
327 $modulenamearrays = explode(
"\n", $metafile);
329 $modulenamearrays[$modulename] = $modulename;
334 foreach ($modulenamearrays as $modulenameval) {
335 if (strpos($modulenameval,
'#') === 0) {
338 if (strpos($modulenameval,
'//') === 0) {
341 if (!trim($modulenameval)) {
348 $submodulenamedir =
$conf->admin->dir_temp.
'/'.$tmpdir.
'/'.$modulenameval;
350 $submodulenamedir =
$conf->admin->dir_temp.
'/'.$tmpdir.
'/htdocs/'.$modulenameval;
352 dol_syslog(
"We copy now directory ".$submodulenamedir.
" into target dir ".$dirins.
'/'.$modulenameval);
353 $result =
dolCopyDir($submodulenamedir, $dirins.
'/'.$modulenameval,
'0444', 1);
355 dol_syslog(
'Failed to call dolCopyDir result='.$result.
" with param ".$submodulenamedir.
" and ".$dirins.
'/'.$modulenameval, LOG_WARNING);
356 $langs->load(
"errors");
357 setEventMessages($langs->trans(
"ErrorFailToCopyDir", $submodulenamedir, $dirins.
'/'.$modulenameval),
null,
'errors');
365 setEventMessages($langs->trans(
"ErrorFailToRenameFile", $_FILES[
'fileinstall'][
'tmp_name'], $newfile),
null,
'errors');
371 $searchParams = array(
372 'search_keyword' => $modulenameval,
373 'search_status' =>
'-1',
374 'search_nature' =>
'-1',
375 'search_version' =>
'-1'
377 $queryString = http_build_query($searchParams);
378 $redirectUrl = DOL_URL_ROOT .
'/admin/modules.php?' . $queryString;
380 $message = $langs->trans(
"SetupIsReadyForUse", $redirectUrl, $langs->transnoentitiesnoconv(
"Home").
' - '.$langs->transnoentitiesnoconv(
"Setup").
' - '.$langs->transnoentitiesnoconv(
"Modules"));
384} elseif ($action ==
'install' && !$allowonlineinstall) {
385 httponly_accessforbidden(
"You try to bypass the protection to disallow deployment of an external module. Hack attempt ?");
388if ($action ==
'set' && $user->admin) {
393 if ($checkOldValue !=
getDolGlobalInt(
'CHECKLASTVERSION_EXTERNALMODULE')) {
394 setEventMessage($langs->trans(
'WarningModuleHasChangedLastVersionCheckParameter', $value),
'warnings');
396 if ($csrfCheckOldValue !=
getDolGlobalInt(
'MAIN_SECURITY_CSRF_WITH_TOKEN')) {
397 setEventMessage($langs->trans(
'WarningModuleHasChangedSecurityCsrfParameter', $value),
'warnings');
401 if (!empty($resarray[
'errors'])) {
405 if ($resarray[
'nbperms'] > 0) {
406 $tmpsql =
"SELECT COUNT(rowid) as nb FROM ".MAIN_DB_PREFIX.
"user WHERE admin <> 1";
407 $resqltmp = $db->query($tmpsql);
409 $obj = $db->fetch_object($resqltmp);
411 if ($obj && $obj->nb > 1) {
412 $msg = $langs->trans(
'ModuleEnabledAdminMustCheckRights');
420 header(
"Location: ".$_SERVER[
"PHP_SELF"].
"?mode=".$mode.$param.($page_y ?
'&page_y='.$page_y :
''));
422} elseif ($action ==
'reset' && $user->admin &&
GETPOST(
'confirm') ==
'yes') {
428 header(
"Location: ".$_SERVER[
"PHP_SELF"].
"?mode=".$mode.$param.($page_y ?
'&page_y='.$page_y :
''));
430} elseif (
getDolGlobalInt(
"MAIN_FEATURES_LEVEL") > 1 && $action ==
'reload' && $user->admin &&
GETPOST(
'confirm') ==
'yes') {
435 header(
"Location: ".$_SERVER[
"PHP_SELF"].
"?mode=".$mode.$param.($page_y ?
'&page_y='.$page_y :
''));
439 if (!empty($resarray[
'errors'])) {
442 if ($resarray[
'nbperms'] > 0) {
443 $tmpsql =
"SELECT COUNT(rowid) as nb FROM ".MAIN_DB_PREFIX.
"user WHERE admin <> 1";
444 $resqltmp = $db->query($tmpsql);
446 $obj = $db->fetch_object($resqltmp);
447 if ($obj && $obj->nb > 1) {
448 $msg = $langs->trans(
'ModuleEnabledAdminMustCheckRights');
456 header(
"Location: ".$_SERVER[
"PHP_SELF"].
"?mode=".$mode.$param.($page_y ?
'&page_y='.$page_y :
''));
465$form =
new Form($db);
468$morecss = array(
"/admin/remotestore/css/store.css");
476$help_url =
'EN:First_setup|FR:Premiers_paramétrages|ES:Primeras_configuraciones';
477llxHeader(
'', $langs->trans(
"Setup"), $help_url,
'', 0, 0, $morejs, $morecss,
'',
'mod-admin page-modules');
483$arrayofnatures = array(
484 'core' => array(
'label' => $langs->transnoentitiesnoconv(
"NativeModules")),
485 'external' => array(
'label' => $langs->transnoentitiesnoconv(
"External").
' - ['.$langs->trans(
"AllPublishers").
']')
487$arrayofwarnings = array();
488$arrayofwarningsext = array();
493$publisherlogoarray = array();
497$modNameLoaded = array();
501foreach ($modulesdir as $dir) {
504 dol_syslog(
"Scan directory ".$dir.
" for module descriptor files (modXXX.class.php)");
505 $handle = @opendir($dir);
506 if (is_resource($handle)) {
507 while (($file = readdir($handle)) !==
false) {
509 if (is_readable($dir.$file) && substr($file, 0, 3) ==
'mod' && substr($file,
dol_strlen($file) - 10) ==
'.class.php') {
510 $modName = substr($file, 0,
dol_strlen($file) - 10);
513 if (!empty($modNameLoaded[$modName])) {
514 $mesg =
"Error: Module ".$modName.
" was found twice: Into ".$modNameLoaded[$modName].
" and ".$dir.
". You probably have an old file on your disk.<br>";
521 $res = include_once $dir.$file;
522 if (class_exists($modName)) {
523 $objMod =
new $modName($db);
524 '@phan-var-force DolibarrModules $objMod';
525 $modNameLoaded[$modName] = $dir;
526 if (!$objMod->numero > 0 && $modName !=
'modUser') {
527 dol_syslog(
'The module descriptor '.$modName.
' must have a numero property', LOG_ERR);
529 $j = $objMod->numero;
531 $modulequalified = 1;
534 $const_name =
'MAIN_MODULE_'.strtoupper(preg_replace(
'/^mod/i',
'', get_class($objMod)));
536 $modulequalified = 0;
539 $modulequalified = 0;
542 $modulequalified = 0;
546 if (!empty($objMod->hidden)) {
547 $modulequalified = 0;
550 if ($modulequalified > 0) {
552 $external = ($objMod->isCoreOrExternalModule() ==
'external');
562 $arrayofnatures[
'external_'.$publisher] = array(
'label' => $langs->trans(
"External").
' - '.$publisher,
'data-html' => $langs->trans(
"External").
' - <span class="opacitymedium inine-block valignmiddle">'.$publisher.
'</span>');
564 $arrayofnatures[
'external_'] = array(
'label' => $langs->trans(
"External").
' - ['.$langs->trans(
"UnknownPublishers").
']');
567 ksort($arrayofnatures);
570 $filename[$i] = $modName;
571 $modules[$modName] = $objMod;
574 if (is_array($objMod->familyinfo) && !empty($objMod->familyinfo)) {
575 $familyinfo = array_merge($familyinfo, $objMod->familyinfo);
576 $familykey = key($objMod->familyinfo);
578 $familykey = $objMod->family;
580 '@phan-var-force string $familykey';
582 $moduleposition = ($objMod->module_position ? $objMod->module_position :
'50');
583 if ($objMod->isCoreOrExternalModule() ==
'external' && $moduleposition < 100000) {
585 $moduleposition =
'80';
589 if (!empty($objMod->warnings_activation)) {
590 $arrayofwarnings[$modName] = $objMod->warnings_activation;
592 if (!empty($objMod->warnings_activation_ext)) {
593 $arrayofwarningsext[$modName] = $objMod->warnings_activation_ext;
596 $familyposition = (empty($familyinfo[$familykey][
'position']) ?
'0' : $familyinfo[$familykey][
'position']);
597 $listOfOfficialModuleGroups = array(
'hr',
'technic',
'interface',
'technic',
'portal',
'financial',
'crm',
'base',
'products',
'srm',
'ecm',
'projects',
'other');
598 if ($external && !in_array($familykey, $listOfOfficialModuleGroups)) {
600 if (is_numeric($familyposition)) {
601 $familyposition = sprintf(
"%03d", (
int) $familyposition + 100);
605 $orders[$i] = $familyposition.
"_".$familykey.
"_".$moduleposition.
"_".$j;
608 $specialstring =
'unknown';
609 if ($objMod->version ==
'development' || $objMod->version ==
'experimental') {
610 $specialstring =
'expdev';
612 if (isset($categ[$specialstring])) {
613 $categ[$specialstring]++;
615 $categ[$specialstring] = 1;
620 dol_syslog(
"Module ".get_class($objMod).
" not qualified");
623 print
info_admin(
"admin/modules.php Warning bad descriptor file : ".$dir.$file.
" (Class ".$modName.
" not found into file)", 0, 0,
'1',
'warning');
626 dol_syslog(
"Failed to load ".$dir.$file.
" ".$e->getMessage(), LOG_ERR);
633 dol_syslog(
"htdocs/admin/modules.php: Failed to open directory ".$dir.
". See permission and open_basedir option.", LOG_WARNING);
637'@phan-var-force array<string,DolibarrModules> $modules';
639if ($action ==
'reset_confirm' && $user->admin) {
640 if (!empty($modules[$value])) {
641 $objMod = $modules[$value];
643 if (!empty($objMod->langfiles)) {
644 $langs->loadLangs($objMod->langfiles);
647 $form =
new Form($db);
648 $formconfirm = $form->formconfirm($_SERVER[
"PHP_SELF"].
'?value='.$value.
'&mode='.$mode.$param, $langs->trans(
'ConfirmUnactivation'), $langs->trans(
GETPOST(
'confirm_message_code')),
'reset',
'',
'no', 1);
652if ($action ==
'reload_confirm' && $user->admin) {
653 if (!empty($modules[$value])) {
654 $objMod = $modules[$value];
656 if (!empty($objMod->langfiles)) {
657 $langs->loadLangs($objMod->langfiles);
660 $form =
new Form($db);
661 $formconfirm = $form->formconfirm($_SERVER[
"PHP_SELF"].
'?value='.$value.
'&mode='.$mode.$param, $langs->trans(
'ConfirmReload'), $langs->trans(
GETPOST(
'confirm_message_code')),
'reload',
'',
'no', 1);
672$nbofactivatedmodules = count(
$conf->modules);
675$nbmodulesnotautoenabled = count(
$conf->modules);
676$listofmodulesautoenabled = array(
'user',
'agenda',
'fckeditor',
'export',
'import');
677foreach ($listofmodulesautoenabled as $moduleautoenable) {
678 if (in_array($moduleautoenable,
$conf->modules)) {
679 $nbmodulesnotautoenabled--;
687if ($mode ==
'common' || $mode ==
'commonkanban') {
688 $desc = $langs->trans(
"ModulesDesc",
'{picto}');
689 $desc .=
' '.$langs->trans(
"ModulesDesc2",
'{picto2}');
690 $desc = str_replace(
'{picto}',
img_picto(
'',
'switch_off',
'class="size15x"'), $desc);
691 $desc = str_replace(
'{picto2}',
img_picto(
'',
'setup',
'class="size15x"'), $desc);
692 if ($nbmodulesnotautoenabled <
getDolGlobalInt(
'MAIN_MIN_NB_ENABLED_MODULE_FOR_WARNING', 1)) {
693 $deschelp .=
'<div class="info hideonsmartphone">'.$desc.
"<br></div>\n";
696 $deschelp .=
'<div class="info">'.$langs->trans(
getDolGlobalString(
'MAIN_SETUP_MODULES_INFO')).
"<br></div>\n";
705if ($mode ==
'deploy') {
706 $deschelp =
'<div class="info hideonsmartphone">'.$langs->trans(
"ModulesDeployDesc", $langs->transnoentitiesnoconv(
"AvailableModules")).
"<br></div><br>\n";
708if ($mode ==
'develop') {
709 $deschelp =
'<div class="info hideonsmartphone">'.$langs->trans(
"ModulesDevelopDesc").
"<br></div><br>\n";
715if ($mode ==
'common' || $mode ==
'commonkanban') {
718 print
'<form method="POST" id="searchFormList" action="'.$_SERVER[
"PHP_SELF"].
'">';
719 print
'<input type="hidden" name="token" value="'.newToken().
'">';
720 if (isset($optioncss) && $optioncss !=
'') {
721 print
'<input type="hidden" name="optioncss" value="'.$optioncss.
'">';
723 if (isset($sortfield) && $sortfield !=
'') {
724 print
'<input type="hidden" name="sortfield" value="'.$sortfield.
'">';
726 if (isset($sortorder) && $sortorder !=
'') {
727 print
'<input type="hidden" name="sortorder" value="'.$sortorder.
'">';
729 if (isset($page) && $page !=
'') {
730 print
'<input type="hidden" name="page" value="'.$page.
'">';
732 print
'<input type="hidden" name="mode" value="'.$mode.
'">';
738 $moreforfilter =
'<div class="valignmiddle">';
740 $moreforfilter .=
'<div class="floatright right pagination paddingtop --module-list"><ul><li>';
741 $moreforfilter .=
dolGetButtonTitle($langs->trans(
'CheckForModuleUpdate'), $langs->trans(
'CheckForModuleUpdate').
'<br><br>'.
img_warning(
'',
'',
'paddingright').$langs->trans(
'CheckForModuleUpdateHelp').
' '.$langs->trans(
'CheckForModuleUpdateHelp2', DolibarrModules::URL_FOR_BLACKLISTED_MODULES).
'<br>'.$langs->trans(
"YourIPWillBeRevealedToThisExternalProviders"),
'fa fa-sync', $_SERVER[
"PHP_SELF"].
'?action=checklastversion&token='.
newToken().
'&mode='.$mode.$param,
'', 1, array(
'morecss' =>
'reposition'));
743 $moreforfilter .=
dolGetButtonTitle($langs->trans(
'ViewList'),
'',
'fa fa-bars imgforviewmode', $_SERVER[
"PHP_SELF"].
'?mode=common'.$param,
'', ($mode ==
'common' ? 2 : 1), array(
'morecss' =>
'reposition'));
744 $moreforfilter .=
dolGetButtonTitle($langs->trans(
'ViewKanban'),
'',
'fa fa-th-list imgforviewmode', $_SERVER[
"PHP_SELF"].
'?mode=commonkanban'.$param,
'', ($mode ==
'commonkanban' ? 2 : 1), array(
'morecss' =>
'reposition'));
745 $moreforfilter .=
'</li></ul></div>';
747 $moreforfilter .=
'<div class="divfilteralone colorbacktimesheet float valignmiddle">';
748 $moreforfilter .=
'<div class="divsearchfield paddingtop paddingbottom valignmiddle inline-block">';
749 $moreforfilter .=
img_picto($langs->trans(
"Filter"),
'filter',
'class="paddingright opacityhigh hideonsmartphone"').
'<input type="text" id="search_keyword" name="search_keyword" class="maxwidth125" value="'.
dol_escape_htmltag($search_keyword).
'" spellcheck="false" placeholder="'.
dol_escape_htmltag($langs->trans(
'Keyword')).
'">';
750 $moreforfilter .=
'</div>';
751 $moreforfilter .=
'<div class="divsearchfield paddingtop paddingbottom valignmiddle inline-block">';
752 $moreforfilter .= $form->selectarray(
'search_nature', $arrayofnatures,
dol_escape_htmltag($search_nature), $langs->trans(
'Origin'), 0, 0,
'', 0, 0, 0,
'',
'maxwidth250', 1);
753 $moreforfilter .=
'</div>';
756 $array_version = array(
'stable' => $langs->transnoentitiesnoconv(
"Stable"));
758 $array_version[
'deprecated'] = $langs->trans(
"Deprecated");
761 $array_version[
'experimental'] = $langs->trans(
"Experimental");
764 $array_version[
'development'] = $langs->trans(
"Development");
766 $moreforfilter .=
'<div class="divsearchfield paddingtop paddingbottom valignmiddle inline-block">';
767 $moreforfilter .= $form->selectarray(
'search_version', $array_version, $search_version, $langs->transnoentitiesnoconv(
'Version'), 0, 0,
'', 0, 0, 0,
'',
'maxwidth150', 1);
768 $moreforfilter .=
'</div>';
770 $array_status = array(
'active' => $langs->transnoentitiesnoconv(
"Enabled"),
'disabled' => $langs->transnoentitiesnoconv(
"Disabled"));
771 $moreforfilter .=
'<div class="divsearchfield paddingtop paddingbottom valignmiddle inline-block">';
772 $moreforfilter .= $form->selectarray(
'search_status', $array_status, $search_status, $langs->transnoentitiesnoconv(
'Status'), 0, 0,
'', 0, 0, 0,
'',
'maxwidth150', 1);
773 $moreforfilter .=
'</div>';
774 $moreforfilter .=
' ';
775 $moreforfilter .=
'<div class="divsearchfield valignmiddle inline-block">';
776 $moreforfilter .=
'<input type="submit" name="buttonsubmit" class="button small nomarginleft" value="'.dolPrintHTMLForAttribute($langs->trans(
"Refresh")).
'">';
777 if ($search_keyword || ($search_nature && $search_nature !=
'-1') || ($search_version && $search_version !=
'-1') || ($search_status && $search_status !=
'-1')) {
778 $moreforfilter .=
' ';
779 $moreforfilter .=
'<input type="submit" name="buttonreset" class="buttonreset noborderbottom nomargintop nomarginbottom" value="'.dolPrintHTMLForAttribute($langs->trans(
"Reset")).
'">';
781 $moreforfilter .=
'</div>';
782 $moreforfilter .=
'</div>';
784 $moreforfilter .=
'</div>';
786 print $moreforfilter;
787 $parameters = array();
788 $reshook = $hookmanager->executeHooks(
'printFieldPreListTitle', $parameters, $object, $action);
789 print $hookmanager->resPrint;
793 print
'<div class="clearboth"></div><br><br>';
796 $parameters = array();
797 $reshook = $hookmanager->executeHooks(
'insertExtraHeader', $parameters, $object, $action);
802 $disabled_modules = array();
803 if (!empty($_SESSION[
"disablemodules"])) {
804 $disabled_modules = explode(
',', $_SESSION[
"disablemodules"]);
809 $foundoneexternalmodulewithupdate = 0;
811 $atleastonequalified = 0;
812 $atleastoneforfamily = 0;
814 foreach ($orders as $key => $value) {
816 $tab = explode(
'_', $value);
817 $familykey = $tab[1];
818 $module_position = $tab[2];
820 $modName = $filename[$key];
823 $objMod = $modules[$modName];
825 if (!is_object($objMod)) {
830 if ($mode ==
'expdev' && $objMod->version !=
'development' && $objMod->version !=
'experimental') {
834 if (!$objMod->getName()) {
835 dol_syslog(
"Error for module ".$key.
" - Property name of module looks empty", LOG_WARNING);
839 $modulenameshort = strtolower(preg_replace(
'/^mod/i',
'', get_class($objMod)));
840 $const_name =
'MAIN_MODULE_'.strtoupper(preg_replace(
'/^mod/i',
'', get_class($objMod)));
843 $modulename = $objMod->getName();
844 $moduletechnicalname = $objMod->name;
845 $moduledesc = $objMod->getDesc();
846 $moduledesclong = $objMod->getDescLong();
847 $moduleauthor = $objMod->getPublisher();
850 if ($search_keyword) {
852 if (preg_match(
'/'.preg_quote($search_keyword,
'/').
'/i', $modulename)
853 || preg_match(
'/'.preg_quote($search_keyword,
'/').
'/i', $moduletechnicalname)
854 || ($moduledesc && preg_match(
'/'.preg_quote($search_keyword,
'/').
'/i', $moduledesc))
855 || ($moduledesclong && preg_match(
'/'.preg_quote($search_keyword,
'/').
'/i', $moduledesclong))
856 || ($moduleauthor && preg_match(
'/'.preg_quote($search_keyword,
'/').
'/i', $moduleauthor))
864 if ($search_status) {
872 if ($search_nature) {
873 if (preg_match(
'/^external/', $search_nature) && $objMod->isCoreOrExternalModule() !=
'external') {
877 if (preg_match(
'/^external_(.*)$/', $search_nature, $reg)) {
883 if (!$reg[1] && !empty($publisher)) {
887 if ($search_nature ==
'core' && $objMod->isCoreOrExternalModule() ==
'external') {
891 if ($search_version) {
892 if (($objMod->version ==
'development' || $objMod->version ==
'experimental' || preg_match(
'/deprecated/', $objMod->version)) && $search_version ==
'stable') {
895 if ($objMod->version !=
'development' && ($search_version ==
'development')) {
898 if ($objMod->version !=
'experimental' && ($search_version ==
'experimental')) {
901 if (!preg_match(
'/deprecated/', $objMod->version) && ($search_version ==
'deprecated')) {
906 $atleastonequalified++;
909 if (isset($objMod->langfiles) && is_array($objMod->langfiles)) {
910 foreach ($objMod->langfiles as $domain) {
911 $langs->load($domain);
916 if ($familykey != $oldfamily) {
918 print
'</table></div><br>';
921 $familytext = empty($familyinfo[$familykey][
'label']) ? $familykey : $familyinfo[$familykey][
'label'];
925 if ($mode ==
'commonkanban') {
926 print
'<div class="box-flex-container kanban">';
928 print
'<div class="div-table-responsive">';
929 print
'<table class="tagtable liste" summary="list_of_modules">'.
"\n";
932 $atleastoneforfamily = 0;
935 $atleastoneforfamily++;
937 if ($familykey != $oldfamily) {
938 $familytext = empty($familyinfo[$familykey][
'label']) ? $familykey : $familyinfo[$familykey][
'label'];
939 $oldfamily = $familykey;
943 $version = $objMod->getVersion(0);
946 if (preg_match(
'/development/i', $version)) {
947 $warningstring = $langs->trans(
"Development");
949 if (preg_match(
'/experimental/i', $version)) {
950 $warningstring = $langs->trans(
"Experimental");
952 if (preg_match(
'/deprecated/i', $version)) {
953 $warningstring = $langs->trans(
"Deprecated");
956 if ($objMod->isCoreOrExternalModule() ==
'external' || preg_match(
'/development|experimental|deprecated/i', $version)) {
957 $versiontrans .= $objMod->getVersion(1);
960 if ($objMod->isCoreOrExternalModule() ==
'external' && ($action ==
'checklastversion' ||
getDolGlobalString(
'CHECKLASTVERSION_EXTERNALMODULE'))) {
964 $checkRes = $objMod->checkForUpdate();
966 setEventMessages($objMod->getName().
' : '.preg_replace(
'/[^a-z0-9_\.\-\s]/i',
'', $versiontrans).
' -> '.preg_replace(
'/[^a-z0-9_\.\-\s]/i',
'', $objMod->lastVersion),
null,
'warnings');
967 } elseif ($checkRes < 0) {
968 setEventMessages($objMod->getName().
' '.$langs->trans(
'CheckVersionFail'),
null,
'errors');
972 if ($objMod->isCoreOrExternalModule() ==
'external' && $action ==
'checklastversion' && !
getDolGlobalString(
'DISABLE_CHECK_ON_MALWARE_MODULES')) {
973 $checkRes = $objMod->checkForCompliance();
974 if (!is_numeric($checkRes) && $checkRes !=
'') {
975 $langs->load(
"errors");
976 setEventMessages($objMod->getName().
' : '.$langs->trans($checkRes),
null,
'errors');
982 if ($objMod->isCoreOrExternalModule() ==
'external') {
983 $imginfo =
"info_black";
986 $codeenabledisable =
'';
990 if (in_array($modulenameshort, $disabled_modules)) {
991 $objMod->disabled =
true;
998 if (!empty($arrayofwarnings[$modName])) {
999 $codeenabledisable .=
'<!-- This module has a warning to show when we activate it (note: your country is '.$mysoc->country_code.
') -->'.
"\n";
1002 if (!empty($objMod->disabled)) {
1003 $codeenabledisable .= $langs->trans(
"Disabled");
1004 } elseif (is_object($objMod)
1005 && (!empty($objMod->always_enabled) || ((isModEnabled(
'multicompany') && $objMod->core_enabled) && ($user->entity ||
$conf->entity != 1)))) {
1007 if (method_exists($objMod,
'alreadyUsed') && $objMod->alreadyUsed()) {
1008 $codeenabledisable .= $langs->trans(
"Used");
1010 $codeenabledisable .=
img_picto($langs->trans(
"Required"),
'switch_on',
'', 0, 0, 0,
'',
'opacitymedium valignmiddle');
1013 if (isModEnabled(
'multicompany') && $user->entity) {
1018 if (is_object($objMod) && !empty($objMod->warnings_unactivation[$mysoc->country_code]) && method_exists($objMod,
'alreadyUsed') && $objMod->alreadyUsed()) {
1019 $codeenabledisable .=
'<a class="reposition valignmiddle" href="'.$_SERVER[
"PHP_SELF"].
'?id='.$objMod->numero.
'&token='.
newToken().
'&module_position='.$module_position.
'&action=reset_confirm&confirm_message_code='.urlencode($objMod->warnings_unactivation[$mysoc->country_code]).
'&value='.$modName.
'&mode='.$mode.$param.
'">';
1020 $codeenabledisable .=
img_picto($langs->trans(
"Activated").($warningstring ?
' '.$warningstring :
''),
'switch_on');
1021 $codeenabledisable .=
'</a>';
1023 $codeenabledisable .=
' ';
1024 $codeenabledisable .=
'<a class="reposition" href="'.$_SERVER[
"PHP_SELF"].
'?id='.$objMod->numero.
'&token='.
newToken().
'&module_position='.$module_position.
'&action=reload_confirm&value='.$modName.
'&mode='.$mode.
'&confirm=yes'.$param.
'">';
1025 $codeenabledisable .=
img_picto($langs->trans(
"Reload"),
'refresh',
'class="opacitymedium"');
1026 $codeenabledisable .=
'</a>';
1029 $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.
'">';
1030 $codeenabledisable .=
img_picto($langs->trans(
"Activated").($warningstring ?
' '.$warningstring :
''),
'switch_on');
1031 $codeenabledisable .=
'</a>';
1033 $codeenabledisable .=
' ';
1034 $codeenabledisable .=
'<a class="reposition" href="'.$_SERVER[
"PHP_SELF"].
'?id='.$objMod->numero.
'&token='.
newToken().
'&module_position='.$module_position.
'&action=reload&value='.$modName.
'&mode='.$mode.
'&confirm=yes'.$param.
'">';
1035 $codeenabledisable .=
img_picto($langs->trans(
"Reload"),
'refresh',
'class="opacitymedium"');
1036 $codeenabledisable .=
'</a>';
1042 if (!empty($objMod->config_page_url) && !$disableSetup) {
1043 $backtourlparam =
'';
1044 if ($search_keyword !=
'') {
1045 $backtourlparam .= ($backtourlparam ?
'&' :
'?').
'search_keyword='.urlencode($search_keyword);
1047 if ($search_nature > -1) {
1048 $backtourlparam .= ($backtourlparam ?
'&' :
'?').
'search_nature='.urlencode($search_nature);
1050 if ($search_version > -1) {
1051 $backtourlparam .= ($backtourlparam ?
'&' :
'?').
'search_version='.urlencode($search_version);
1053 if ($search_status > -1) {
1054 $backtourlparam .= ($backtourlparam ?
'&' :
'?').
'search_status='.urlencode($search_status);
1056 $backtourl = $_SERVER[
"PHP_SELF"].$backtourlparam;
1059 if (is_array($objMod->config_page_url)) {
1061 foreach ($objMod->config_page_url as $page) {
1064 $codetoconfig .=
'<a href="'.$urlpage.
'" title="'.$langs->trans($page).
'">'.
img_picto(ucfirst($page),
"setup").
'</a>';
1067 if (preg_match(
'/^([^@]+)@([^@]+)$/i', $urlpage, $regs)) {
1068 $urltouse =
dol_buildpath(
'/'.$regs[2].
'/admin/'.$regs[1], 1);
1069 $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"', 0, 0, 0,
'',
'fa-15').
'</a>';
1071 $urltouse = $urlpage;
1072 $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"', 0, 0, 0,
'',
'fa-15').
'</a>';
1076 } elseif (preg_match(
'/^([^@]+)@([^@]+)$/i', (
string) $objMod->config_page_url, $regs)) {
1077 $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"', 0, 0, 0,
'',
'fa-15').
'</a>';
1079 $codetoconfig .=
'<a class="valignmiddle" href="'.((string) $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"', 0, 0, 0,
'',
'fa-15').
'</a>';
1082 $codetoconfig .=
img_picto($langs->trans(
"NothingToSetup"),
"setup",
'class="opacitytransp" style="padding-right: 6px"', 0, 0, 0,
'',
'fa-15');
1086 if (!empty($objMod->always_enabled)) {
1088 $codeenabledisable .=
'<!-- Message to show: an always_enabled module has been disabled -->'.
"\n";
1089 $codeenabledisable .=
'<a class="reposition" href="'.$_SERVER[
"PHP_SELF"].
'?id='.$objMod->numero.
'&token='.
newToken().
'&module_position='.$module_position.
'&action=set&token='.
newToken().
'&value='.$modName.
'&mode='.$mode.$param.
'"';
1090 $codeenabledisable .=
'>';
1091 $codeenabledisable .=
img_picto($langs->trans(
"Disabled"),
'switch_off');
1092 $codeenabledisable .=
"</a>\n";
1093 } elseif (!empty($objMod->disabled)) {
1094 $codeenabledisable .= $langs->trans(
"Disabled");
1097 $warningmessage =
'';
1098 if (!empty($arrayofwarnings[$modName])) {
1099 $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";
1100 foreach ($arrayofwarnings[$modName] as $keycountry => $cursorwarningmessage) {
1101 if (preg_match(
'/^always/', $keycountry) || ($mysoc->country_code && preg_match(
'/^'.$mysoc->country_code.
'/', $keycountry))) {
1102 $warningmessage .= ($warningmessage ?
"\n" :
"").$langs->trans($cursorwarningmessage, $objMod->getName(), $mysoc->country_code);
1106 if ($objMod->isCoreOrExternalModule() ==
'external' && !empty($arrayofwarningsext)) {
1107 $codeenabledisable .=
'<!-- This module is an external module and it may have a warning to show (note: your country is '.$mysoc->country_code.
') -->'.
"\n";
1108 foreach ($arrayofwarningsext as $keymodule => $arrayofwarningsextbycountry) {
1109 $keymodulelowercase = strtolower(preg_replace(
'/^mod/',
'', $keymodule));
1110 if (in_array($keymodulelowercase,
$conf->modules)) {
1111 foreach ($arrayofwarningsextbycountry as $keycountry => $cursorwarningmessage) {
1112 if (preg_match(
'/^always/', $keycountry) || ($mysoc->country_code && preg_match(
'/^'.$mysoc->country_code.
'/', $keycountry))) {
1113 $warningmessage .= ($warningmessage ?
"\n" :
"").$langs->trans($cursorwarningmessage, $objMod->getName(), $mysoc->country_code, $modules[$keymodule]->getName());
1114 $warningmessage .= ($warningmessage ?
"\n" :
"").($warningmessage ?
"\n" :
"").$langs->trans(
"Module").
' : '.$objMod->getName();
1115 if (!empty($objMod->editor_name)) {
1116 $warningmessage .= ($warningmessage ?
"\n" :
"").$langs->trans(
"Publisher").
' : '.$objMod->editor_name;
1118 if (!empty($objMod->editor_name)) {
1119 $warningmessage .= ($warningmessage ?
"\n" :
"").$langs->trans(
"ModuleTriggeringThisWarning").
' : '.$modules[$keymodule]->getName();
1126 $codeenabledisable .=
'<!-- Message to show: '.$warningmessage.
' -->'.
"\n";
1127 $codeenabledisable .=
'<a class="reposition" href="'.$_SERVER[
"PHP_SELF"].
'?id='.$objMod->numero.
'&token='.
newToken().
'&module_position='.$module_position.
'&action=set&token='.
newToken().
'&value='.$modName.
'&mode='.$mode.$param.
'"';
1128 if ($warningmessage) {
1130 $codeenabledisable .=
' onclick="return confirm(\''.dol_escape_js($warningmessage).
'\');
"';
1132 $codeenabledisable .= '>';
1133 $codeenabledisable .= img_picto($langs->trans("Disabled
"), 'switch_off');
1134 $codeenabledisable .= "</a>\n
";
1137 // Set $codetoconfig
1138 $codetoconfig .= img_picto($langs->trans("NothingToSetup
"), "setup
", 'class="opacitytransp
" style="padding-right: 6px
"');
1141 if ($mode == 'commonkanban') {
1143 print $objMod->getKanbanView($codeenabledisable, $codetoconfig);
1145 print '<tr class="oddeven
'.($warningstring ? ' info-box-content-warning
' : '').'">'."\n
";
1146 if (getDolGlobalString('MAIN_MODULES_SHOW_LINENUMBERS')) {
1147 print '<td class="width50
">'.$linenum.'</td>';
1150 // Picto + Name of module
1151 print ' <td class="tdoverflowmax200 minwidth200imp
" title="'.dol_escape_htmltag($objMod->getName()).'">';
1153 //if (is_array($objMod->need_dolibarr_version)) $alttext.=($alttext?' - ':'').'Dolibarr >= '.join('.',$objMod->need_dolibarr_version);
1154 //if (is_array($objMod->phpmin)) $alttext.=($alttext?' - ':'').'PHP >= '.join('.',$objMod->phpmin);
1155 if (!empty($objMod->picto)) {
1156 if (preg_match('/^\//i', $objMod->picto)) {
1157 print img_picto($alttext, $objMod->picto, 'class="valignmiddle pictomodule paddingrightonly
"', 1);
1159 print img_object($alttext, $objMod->picto, 'class="valignmiddle pictomodule paddingrightonly
"');
1162 print img_object($alttext, 'generic', 'class="valignmiddle paddingrightonly
"');
1164 print ' <span class="valignmiddle
">'.$objMod->getName().'</span>';
1168 print '<td class="valignmiddle tdoverflowmax300 minwidth200imp
">';
1169 print nl2br($objMod->getDesc());
1173 print '<td class="center nowrap
" style="width: 82px;
">';
1174 //print $form->textwithpicto('', $text, 1, $imginfo, 'minheight20', 0, 2, 1);
1175 print '<a href="javascript:
document_preview(\
''.DOL_URL_ROOT.
'/admin/modulehelp.php?id='.((
int) $objMod->numero).
'\',\
'text/html\',\''.dol_escape_js($langs->trans(
"Module")).
'\')
">'.img_picto(($objMod->isCoreOrExternalModule() == 'external' ? $langs->trans("ExternalModule
").' - ' : '').$langs->trans("ClickToShowDescription
"), $imginfo).'</a>';
1179 print '<td class="center nowrap width150
" title="'.dol_escape_htmltag(dol_string_nohtmltag($versiontrans)).'">';
1180 if ($objMod->needUpdate) {
1181 $versionTitle = $langs->trans('ModuleUpdateAvailable').' : '.$objMod->lastVersion;
1182 print '<span class="badge badge-warning classfortooltip
" title="'.dol_escape_htmltag($versionTitle).'">'.$versiontrans.'</span>';
1184 print $versiontrans;
1188 // Link enable/disable
1189 print '<td class="center valignmiddle left nowraponall
" width="60px
">';
1190 print $codeenabledisable;
1194 print '<td class="tdsetuppicto right valignmiddle
" width="60px
">';
1195 print $codetoconfig;
1200 if ($objMod->needUpdate) {
1201 $foundoneexternalmodulewithupdate++;
1205 if ($action == 'checklastversion') {
1206 if ($foundoneexternalmodulewithupdate) {
1207 setEventMessages($langs->trans("ModuleUpdateAvailable
"), null, 'warnings', '', 0, 1);
1209 setEventMessages($langs->trans("NoExternalModuleWithUpdate
"), null, 'mesgs');
1214 if ($mode == 'commonkanban') {
1222 if (!$atleastonequalified) {
1223 print '<br><span class="opacitymedium
">'.$langs->trans("NoDeployedModulesFoundWithThisSearchCriteria
").'</span><br><br>';
1226 print dol_get_fiche_end();
1230 // Show warning about external users
1231 print info_admin(showModulesExludedForExternal($modules))."\n
";
1236if ($mode == 'marketplace') {
1237 print dol_get_fiche_head($head, $mode, '', -1);
1243 print '<!-- summary of sources -->';
1245 // Marketplace and community modules
1246 print '<div class="div-
table-responsive-no-min
">';
1247 print '<table summary="list_of_modules
" class="noborder centpercent
">'."\n
";
1248 print '<tr class="liste_titre
">'."\n
";
1249 print '<td class="hideonsmartphone
">'.$form->textwithpicto($langs->trans("Provider
"), $langs->trans("WebSiteDesc
")).'</td>';
1256 $url = 'https://www.dolistore.com';
1259 print '<tr class="oddeven
">'."\n
";
1260 print '<td class="hideonsmartphone center width150 nopaddingleftimp nopaddingrightimp
"><a href="'.$url.'" target="_blank
" rel="noopener noreferrer external
"><img border="0
" class="imgautosize imgmaxwidth100
" src="'.DOL_URL_ROOT.'/theme/dolistore_logo.svg
"></a></td>';
1261 print '<td><span class="opacitymedium
">'.$langs->trans("DoliStoreDesc
").'</span><br>';
1262 print img_picto('', 'url', 'class="pictofixedwidth
"').'<a href="'.$url.'" target="_blank
" rel="noopener noreferrer external
">'.$url.'</a></td>';
1264 print ajax_constantonoff('MAIN_ENABLE_EXTERNALMODULES_DOLISTORE', array(), null, 0, 0, 1);
1266 print '<td class="center
">';
1267 if (!getDolGlobalString('MAIN_DISABLE_EXTERNALMODULES_DOLISTORE') && getDolGlobalInt('MAIN_ENABLE_EXTERNALMODULES_DOLISTORE')) {
1268 $messagetoadd = '<br><span class="small
">';
1269 if ($remotestore->dolistoreApiStatus <= 0) {
1270 $messagetoadd = '<br>'.$remotestore->dolistoreApiError.'<br>Failed to get answer of remote API server<br>';
1273 $messagetoadd .= '<br>Using Shop address MAIN_MODULE_DOLISTORE_SHOP_URL = '.$remotestore->shop_url;
1274 $messagetoadd .= '<br>Using Remote API address MAIN_MODULE_DOLISTORE_API_URL = '.$remotestore->dolistore_api_url;
1275 $messagetoadd .= '<br>Using API public key MAIN_MODULE_DOLISTORE_API_KEY = '.$remotestore->dolistore_api_key;
1276 // Add basic auth if needed
1277 $basicAuthLogin = getDolGlobalString('MAIN_MODULE_DOLISTORE_BASIC_LOGIN');
1278 $basicAuthPassword = getDolGlobalString('MAIN_MODULE_DOLISTORE_BASIC_PASSWORD');
1279 if ($basicAuthLogin) {
1280 $messagetoadd .= '<br>Using basic auth login: base64('.$basicAuthLogin.':'.$basicAuthPassword.')';
1282 $messagetoadd .= '</span>';
1284 print $remotestore->libStatus($remotestore->dolistoreApiStatus, 2, $messagetoadd);
1289 $url = 'https://github.com/Dolibarr/dolibarr-community-modules';
1292 print '<tr class="oddeven
">'."\n
";
1293 print '<td class="hideonsmartphone center width150 nopaddingleftimp nopaddingrightimp
"><a href="'.$url.'" target="_blank
" rel="noopener noreferrer external
"><img border="0
" class="imgautosize imgmaxwidth100
" src="'.DOL_URL_ROOT.'/theme/dolibarr_logo.svg
"></a></td>';
1294 print '<td><span class="opacitymedium
">'.$langs->trans("CommunityModulesDesc
").'</span><br>';
1295 print img_picto('', 'url', 'class="pictofixedwidth
"').'<a href="'.$url.'" target="_blank
" rel="noopener noreferrer external
">'.$url.'</a></td>';
1297 print ajax_constantonoff('MAIN_ENABLE_EXTERNALMODULES_COMMUNITY', array(), null, 0, 0, 1);
1299 print '<td class="center
">';
1300 if (!getDolGlobalString('MAIN_DISABLE_EXTERNALMODULES_COMMUNITY') && getDolGlobalInt('MAIN_ENABLE_EXTERNALMODULES_COMMUNITY')) {
1301 $messagetoadd = '<br><br><span class="small
">Content of the repository index file '.$remotestore->file_source_url.' should be in the local cache file '.$remotestore->cache_file;
1302 $messagetoadd .= ' (Date: '.dol_print_date(dol_filemtime($remotestore->cache_file), 'dayhour', 'tzuserrel').')</span>';
1303 if ($remotestore->githubFileError) {
1304 $messagetoadd .= '<br><span class="error small
">'.$remotestore->githubFileError.'</span>';
1306 print $remotestore->libStatus($remotestore->githubFileStatus, 2, $messagetoadd);
1314 print dol_get_fiche_end();
1318 if ($remotestore->numberOfProviders > 0) {
1319 // $options is array with filter criteria
1320 $nbmaxtoshow = $options['per_page'];
1321 $options['per_page']++;
1323 //$remotestore->getRemoteCategories();
1324 //$remotestore->getRemoteProducts($options);
1326 print '<span class="opacitymedium
">'.$langs->trans('DOLISTOREdescriptionLong').'</span><br><br>';
1328 $categories_tree = $remotestore->getCategories($options['categorie']); // Call API to get the categories
1330 $products_list = $remotestore->getProducts($options); // Get list of product from all sources
1332 $previouslink = $remotestore->get_previous_link();
1334 $nextlink = $remotestore->get_next_link();
1337 print '<div class="liste_titre liste_titre_bydiv centpercent
"><div class="">';
1339 print '<form method="POST
" class="centpercent
" id="searchFormList
" action="'.$remotestore->url.'">'; ?>
1340 <input type="hidden
" name="token
" value="<?php echo
newToken(); ?>
">
1341 <input type="hidden
" name="mode
" value="marketplace
">
1342 <input type="hidden
" name="page_y
" value="">
1343 <div class="divsearchfield
">
1344 <input name="search_keyword
" placeholder="<?php echo $langs->trans(
'Keyword') ?>
" id="search_keyword
" type="text
" class="minwidth200
" value="<?php echo
dolPrintHTMLForAttribute($options[
'search']) ?>
" spellcheck="false">
1346 <div class="divsearchfield
">
1347 <input name="buttonsubmit
" class="button buttongen reposition
" value="<?php echo $langs->trans(
'Search') ?>
" type="submit
">
1349 if ($search_keyword !== '') {
1350 print '<a class="buttonreset reposition
" href="'.$_SERVER["PHP_SELF"].'?mode=marketplace
">'.$langs->trans('Reset').'</a>';
1356 $totalnboflines = '<span class="product-count opacitymedium paddingleft
">';
1357 $totalnboflines .= $langs->trans("itemFound
", $remotestore->numberTotalOfProducts);
1358 $totalnboflines .= '</span>';
1360 print $totalnboflines;
1361 print $remotestore->getPagination();
1364 print '</div></div>';
1365 print '<div class="clearboth
"></div>';
1367 <?php if (!empty($categories_tree)) { ?>
1368 <div id="category-tree-left
">
1371 print $categories_tree; ?>
1376 <div id="listing-content
" class="div-
table-responsive
" <?php if (empty($categories_tree)) { ?>style="width:100%;
"<?php } ?>>
1377 <table summary="list_of_modules
" id="list_of_modules
" class="productlist centpercent
">
1378 <tbody id="listOfModules
">
1379 <?php //echo $remotestore->get_products($nbmaxtoshow); ?>
1380 <?php print $products_list; ?>
1384 <div style="clear: both;
"></div>
1385 <div><?php print $remotestore->getPagination(); ?></div>
1391// Form to install an external module
1393if ($mode == 'deploy') {
1394 print dol_get_fiche_head($head, $mode, '', -1);
1396 $fullurl = '<a href="'.$urldolibarrmodules.'" target="_blank
" rel="noopener noreferrer
">'.$urldolibarrmodules.'</a>';
1398 if ($allowonlineinstall) {
1399 if (!in_array('/custom', explode(',', $dolibarr_main_url_root_alt))) {
1400 $message = info_admin($langs->trans("ConfFileMustContainCustom
", DOL_DOCUMENT_ROOT.'/custom', DOL_DOCUMENT_ROOT));
1404 if (!is_writable(dol_osencode($dirins))) {
1405 $langs->load("errors
");
1406 $message = info_admin($langs->trans("ErrorFailedToWriteInDir
", $dirins), 0, 0, '1', 'warning');
1410 $message = info_admin($langs->trans("NotExistsDirect
", $dirins).$langs->trans("InfDirAlt
").$langs->trans("InfDirExample
"));
1415 if (getDolGlobalString('MAIN_MESSAGE_INSTALL_MODULES_DISABLED_CONTACT_US')) {
1416 // Show clean message
1417 if (!is_numeric(getDolGlobalString('MAIN_MESSAGE_INSTALL_MODULES_DISABLED_CONTACT_US'))) {
1418 $message = info_admin($langs->trans(getDolGlobalString('MAIN_MESSAGE_INSTALL_MODULES_DISABLED_CONTACT_US')), 0, 0, 'warning');
1420 $message = info_admin($langs->trans('InstallModuleFromWebHasBeenDisabledContactUs'), 0, 0, 'warning');
1423 // Show technical message
1424 $message = info_admin($langs->trans("InstallModuleFromWebHasBeenDisabledByFile
", $dolibarrdataroot.'/installmodules.lock'), 0, 0, 'warning');
1431 if ($allowfromweb < 1) {
1432 print $langs->trans("SomethingMakeInstallFromWebNotPossible
");
1434 //print $langs->trans("SomethingMakeInstallFromWebNotPossible2
");
1438 // $allowfromweb = -1 if installation or setup not correct, 0 if not allowed, 1 if allowed
1439 if ($allowfromweb >= 0) {
1440 if ($allowfromweb == 1) {
1441 //print $langs->trans("ThisIsProcessToFollow
").'<br>';
1445 print $langs->trans("ThisIsAlternativeProcessToFollow
").'<br>';
1446 print '<b>'.$langs->trans("StepNb
", 1).'</b>: ';
1447 print str_replace('{s1}', $fullurl, $langs->trans("FindPackageFromWebSite
", '{s1}')).'<br>';
1448 print '<b>'.$langs->trans("StepNb
", 2).'</b>: ';
1449 print str_replace('{s1}', $fullurl, $langs->trans("DownloadPackageFromWebSite
", '{s1}')).'<br>';
1450 print '<b>'.$langs->trans("StepNb
", 3).'</b>: ';
1453 if ($allowfromweb == 1) {
1454 print '<form enctype="multipart/form-data
" method="POST
" class="noborder
" action="'.$_SERVER["PHP_SELF"].'" name="forminstall
">';
1455 print '<input type="hidden
" name="token
" value="'.newToken().'">';
1456 print '<input type="hidden
" name="action
" value="install
">';
1457 print '<input type="hidden
" name="mode
" value="deploy
">';
1459 print $langs->trans("YouCanSubmitFile
").'<br><br><br>';
1461 print '<span class="opacitymedium
"><input class="paddingright
" type="checkbox
" name="checkforcompliance
" id="checkforcompliance
"'.(getDolGlobalString('DISABLE_CHECK_ON_MALWARE_MODULES') ? ' disabled="disabled"' : 'checked="checked
"').'>';
1462 print '<label for="checkforcompliance
">'.$form->textwithpicto($langs->trans("CheckIfModuleIsNotBlackListed
"), $langs->trans("CheckIfModuleIsNotBlackListedHelp
")).'</label>';
1463 print '</span><br><br>';
1465 $max = getDolGlobalString('MAIN_UPLOAD_DOC'); // In Kb
1466 $maxphp = @ini_get('upload_max_filesize'); // In unknown
1467 if (preg_match('/k$/i', $maxphp)) {
1468 $maxphp = preg_replace('/k$/i', '', $maxphp);
1471 if (preg_match('/m$/i', $maxphp)) {
1472 $maxphp = preg_replace('/m$/i', '', $maxphp);
1475 if (preg_match('/g$/i', $maxphp)) {
1476 $maxphp = preg_replace('/g$/i', '', $maxphp);
1477 $maxphp *= 1024 * 1024;
1479 if (preg_match('/t$/i', $maxphp)) {
1480 $maxphp = preg_replace('/t$/i', '', $maxphp);
1481 $maxphp *= 1024 * 1024 * 1024;
1483 $maxphp2 = @ini_get('post_max_size'); // In unknown
1484 if (preg_match('/k$/i', $maxphp2)) {
1485 $maxphp2 = preg_replace('/k$/i', '', $maxphp2);
1488 if (preg_match('/m$/i', $maxphp2)) {
1489 $maxphp2 = preg_replace('/m$/i', '', $maxphp2);
1492 if (preg_match('/g$/i', $maxphp2)) {
1493 $maxphp2 = preg_replace('/g$/i', '', $maxphp2);
1494 $maxphp2 *= 1024 * 1024;
1496 if (preg_match('/t$/i', $maxphp2)) {
1497 $maxphp2 = preg_replace('/t$/i', '', $maxphp2);
1498 $maxphp2 *= 1024 * 1024 * 1024;
1500 // Now $max and $maxphp and $maxphp2 are in Kb
1502 $maxphptoshow = $maxphptoshowparam = '';
1504 $maxmin = min($max, $maxphp);
1505 $maxphptoshow = $maxphp;
1506 $maxphptoshowparam = 'upload_max_filesize';
1509 $maxmin = min($max, $maxphp2);
1510 if ($maxphp2 < $maxphp) {
1511 $maxphptoshow = $maxphp2;
1512 $maxphptoshowparam = 'post_max_size';
1517 print '<script type="text/javascript
">
1518 $(document).ready(function() {
1519 jQuery("#fileinstall
").on("change
", function() {
1520 if(this.files[0].size > '.($maxmin * 1024).') {
1521 alert("'.dol_escape_js($langs->transnoentitiesnoconv("ErrorFileSizeTooLarge")).'");
1527 // MAX_FILE_SIZE doit précéder le champ input de type file
1528 print '<input type="hidden
" name="MAX_FILE_SIZE
" value="'.($maxmin * 1024).'">';
1531 print '<input class="flat minwidth400
" type="file
" name="fileinstall
" id="fileinstall
">';
1533 print '<input type="submit
" name="send
" value="'.dol_escape_htmltag($langs->trans("Upload")).'" class="button small
">';
1535 if (getDolGlobalString('MAIN_UPLOAD_DOC')) {
1537 $langs->load('other');
1539 print info_admin($langs->trans("ThisLimitIsDefinedInSetup
", $max, $maxphptoshow, $maxphptoshowparam), 1);
1542 print ' ('.$langs->trans("UploadDisabled
").')';
1550 print '<div class="center
"><div class="logo_setup
"></div></div>';
1552 print $langs->trans("UnpackPackageInModulesRoot
", $dirins).'<br>';
1553 print '<b>'.$langs->trans("StepNb
", 4).'</b>: ';
1554 print $langs->trans("SetupIsReadyForUse
", DOL_URL_ROOT.'/admin/modules.php?mainmenu=home', $langs->transnoentitiesnoconv("Home
").' - '.$langs->transnoentitiesnoconv("Setup").' - '.$langs->transnoentitiesnoconv("Modules
")).'<br>';
1558 if (!empty($result['return'])) {
1561 foreach ($result['return'] as $value) {
1566 print dol_get_fiche_end();
1569if ($mode == 'develop') {
1570 print dol_get_fiche_head($head, $mode, '', -1);
1577 print '<div class="div-
table-responsive-no-min
">';
1578 print '<table summary="list_of_modules
" class="noborder centpercent
">'."\n
";
1579 print '<tr class="liste_titre
">'."\n
";
1580 print '<td colspan="3
">'.$langs->trans("DevelopYourModuleDesc
").'</td>';
1583 print '<tr class="oddeven
" height="80
">'."\n
";
1584 print '<td class="center hideonsmartphone
">';
1585 print '<div class="imgmaxheight50 logo_setup
"></div>';
1587 print '<td class="minwidth500imp smallonsmartphone
">'.$langs->trans("TryToUseTheModuleBuilder
", $langs->transnoentitiesnoconv("ModuleBuilder
")).'</td>';
1588 print '<td class="maxwidth300
">';
1589 if (isModEnabled('modulebuilder')) {
1590 print $langs->trans("SeeTopRightMenu
");
1592 print '<span class="opacitymedium
">'.$langs->trans("ModuleMustBeEnabledFirst
", $langs->transnoentitiesnoconv("ModuleBuilder
")).'</span>';
1597 print '<tr class="oddeven
" height="80
">'."\n
";
1598 $url = 'https://partners.dolibarr.org';
1599 print '<td class="center hideonsmartphone
">';
1600 print'<a href="'.$url.'" target="_blank
" rel="noopener noreferrer external
"><img border="0
" class="imgautosize imgmaxwidth180
" src="'.DOL_URL_ROOT.'/theme/dolibarr_preferred_partner.png
"></a>';
1602 print '<td class="minwidth500imp smallonsmartphone
">'.$langs->trans("DoliPartnersDesc
").'</td>';
1603 print '<td><a href="'.$url.'" target="_blank
" rel="noopener noreferrer external
">';
1604 print img_picto('', 'url', 'class="pictofixedwidth
"');
1605 print $url.'</a></td>';
1611 print dol_get_fiche_end();
if( $user->socid > 0) if(! $user->hasRight('accounting', 'chartofaccount')) $object
dolibarr_set_const($db, $name, $value, $type='chaine', $visible=0, $note='', $entity=1)
Insert a parameter (key,value) into database (delete old key then insert it again).
unActivateModule($value, $requiredby=1)
Disable a module.
activateModule($value, $withdeps=1, $noconfverification=0)
Enable a module.
modules_prepare_head($nbofactivatedmodules, $nboftotalmodules, $nbmodulesnotautoenabled)
Prepare array with list of tabs.
if(!defined('NOREQUIRESOC')) if(!defined( 'NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined( 'NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined( 'NOREQUIREAJAX')) llxHeader($head='', $title='', $help_url='', $target='', $disablejs=0, $disablehead=0, $arrayofjs='', $arrayofcss='', $morequerystring='', $morecssonbody='', $replacemainareaby='', $disablenofollow=0, $disablenoindex=0)
Empty header.
dol_delete_dir_recursive($dir, $count=0, $nophperrors=0, $onlysub=0, &$countdeleted=0, $indexdatabase=1, $nolog=0, $level=0)
Remove a directory $dir and its subdirectories (or only files and subdirectories)
dol_uncompress($inputfile, $outputdir)
Uncompress a file.
dolCopyDir($srcfile, $destfile, $newmask, $overwriteifexists, $arrayreplacement=null, $excludesubdir=0, $excludefileext=null, $excludearchivefiles=0)
Copy a dir to another dir.
dol_is_file($pathoffile)
Return if path is a file.
dol_is_dir($folder)
Test if filename is a directory.
dol_move_uploaded_file($src_file, $dest_file, $allowoverwrite, $disablevirusscan=0, $uploaderrorcode=0, $nohook=0, $keyforsourcefile='addedfile', $upload_dir='', $mode=0)
Check validity of a file upload from an GUI page, and move it to its final destination.
dolGetModulesDirs($subdir='')
Return list of directories that contain modules.
load_fiche_titre($title, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='')
Load a title with picto.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0, $attop=0)
Set event messages in dol_events session object.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2, $allowothertags=array())
Show picto whatever it's its name (generic function)
img_warning($titlealt='default', $moreatt='', $morecss='pictowarning')
Show warning logo.
GETPOSTINT($paramname, $method=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
dol_get_fiche_head($links=array(), $active='', $title='', $notab=0, $picto='', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limittoshow=0, $moretabssuffix='', $dragdropfile=0, $morecssdiv='')
Show tabs of a record.
dolGetButtonTitle($label, $helpText='', $iconClass='fa fa-file', $url='', $id='', $status=1, $params=array())
Function dolGetButtonTitle : this kind of buttons are used in title in list.
setEventMessage($mesgs, $style='mesgs', $noduplicate=0, $attop=0)
Set event message in dol_events session object.
dol_strlen($string, $stringencoding='UTF-8')
Make a strlen call.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
dol_set_focus($selector)
Set focus onto field with selector (similar behaviour of 'autofocus' HTML5 tag)
newToken()
Return the value of token currently saved into session with name 'newtoken'.
dolPrintHTMLForAttribute($s, $escapeonlyhtmltags=0, $allowothertags=array())
Return a string ready to be output into an HTML attribute (alt, title, data-html, ....
dolGetButtonTitleSeparator($moreClass="")
Add space between dolGetButtonTitle.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
info_admin($text, $infoonimgalt=0, $nodiv=0, $admin='1', $morecss='hideonsmartphone', $textfordropdown='', $picto='')
Show information in HTML for admin users or standard users.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
dol_mkdir($dir, $dataroot='', $newmask='')
Creation of a directory (this can create recursive subdir)
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...
treeview li table
No Email.
ui state ui widget content ui state ui widget header ui state a ui button
0 = Do not include form tag and submit button -1 = Do not include form tag but include submit button
document_preview(file, type, title)
Function to show a document preview popup.
global $conf
The following vars must be defined: $type2label $form $conf, $lang, The following vars may also be de...
httponly_accessforbidden($message='1', $http_response_code=403, $stringalreadysanitized=0)
Show a message to say access is forbidden and stop program.
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program.