33if (!defined(
'CSRFCHECK_WITH_TOKEN') && (empty($_GET[
'action']) || $_GET[
'action'] !=
'reset')) {
34 define(
'CSRFCHECK_WITH_TOKEN',
'1');
38require
'../main.inc.php';
50@phan-var-force string $dolibarr_main_url_root_alt
52require_once DOL_DOCUMENT_ROOT.
'/core/lib/admin.lib.php';
53require_once DOL_DOCUMENT_ROOT.
'/core/lib/files.lib.php';
54require_once DOL_DOCUMENT_ROOT.
'/core/lib/geturl.lib.php';
55require_once DOL_DOCUMENT_ROOT.
'/core/lib/functions2.lib.php';
56require_once DOL_DOCUMENT_ROOT.
'/core/class/events.class.php';
57require_once DOL_DOCUMENT_ROOT.
'/core/modules/DolibarrModules.class.php';
58require_once DOL_DOCUMENT_ROOT.
'/admin/remotestore/class/externalModules.class.php';
62$langs->loadLangs(array(
"errors",
"admin",
"modulebuilder"));
64$action =
GETPOST(
'action',
'aZ09');
67$optioncss =
GETPOST(
'optioncss',
'aZ09');
68$sortfield =
GETPOST(
'sortfield',
'aZ09');
69$sortorder =
GETPOST(
'sortorder',
'aZ09');
71$mode =
GETPOST(
'mode',
'alpha');
72$value =
GETPOST(
'value',
'alpha');
73$search_keyword =
GETPOST(
'search_keyword',
'alpha');
74$search_status =
GETPOST(
'search_status',
'alpha');
75$search_nature =
GETPOST(
'search_nature',
'alpha');
76$search_version =
GETPOST(
'search_version',
'alpha');
81$options[
'per_page'] = 11;
84$options[
'search'] =
GETPOST(
'search_keyword',
'alpha');
87if (
GETPOST(
'buttonsubmit',
'alphanohtml', 2)) {
88 $options[
'no_page'] = 1;
92$options[
'search_source_dolistore'] =
getDolGlobalInt(
'MAIN_ENABLE_EXTERNALMODULES_DOLISTORE');
94$options[
'search_source_github'] =
getDolGlobalInt(
'MAIN_ENABLE_EXTERNALMODULES_COMMUNITY');
101 'hr' => array(
'position' =>
'001',
'label' => $langs->trans(
"ModuleFamilyHr")),
102 'crm' => array(
'position' =>
'006',
'label' => $langs->trans(
"ModuleFamilyCrm")),
103 'srm' => array(
'position' =>
'007',
'label' => $langs->trans(
"ModuleFamilySrm")),
104 'financial' => array(
'position' =>
'009',
'label' => $langs->trans(
"ModuleFamilyFinancial")),
105 'products' => array(
'position' =>
'012',
'label' => $langs->trans(
"ModuleFamilyProducts")),
106 'projects' => array(
'position' =>
'015',
'label' => $langs->trans(
"ModuleFamilyProjects")),
107 'ecm' => array(
'position' =>
'018',
'label' => $langs->trans(
"ModuleFamilyECM")),
108 'technic' => array(
'position' =>
'021',
'label' => $langs->trans(
"ModuleFamilyTechnic")),
109 'portal' => array(
'position' =>
'040',
'label' => $langs->trans(
"ModuleFamilyPortal")),
110 'interface' => array(
'position' =>
'050',
'label' => $langs->trans(
"ModuleFamilyInterface")),
111 'base' => array(
'position' =>
'060',
'label' => $langs->trans(
"ModuleFamilyBase")),
112 'other' => array(
'position' =>
'100',
'label' => $langs->trans(
"ModuleFamilyOther")),
116if (!
GETPOST(
'buttonreset',
'alpha')) {
117 if ($search_keyword) {
118 $param .=
'&search_keyword='.urlencode($search_keyword);
120 if ($search_status && $search_status !=
'-1') {
121 $param .=
'&search_status='.urlencode($search_status);
123 if ($search_nature && $search_nature !=
'-1') {
124 $param .=
'&search_nature='.urlencode($search_nature);
126 if ($search_version && $search_version !=
'-1') {
127 $param .=
'&search_version='.urlencode($search_version);
131$dirins = DOL_DOCUMENT_ROOT.
'/custom';
132$urldolibarrmodules =
'https://www.dolistore.com/';
135$hookmanager->initHooks(array(
'adminmodules',
'globaladmin'));
138$max_execution_time_for_deploy =
getDolGlobalInt(
'MODULE_UPLOAD_MAX_EXECUTION_TIME', 300);
139if (!empty($max_execution_time_for_deploy)) {
140 $err = error_reporting();
143 @set_time_limit($max_execution_time_for_deploy);
144 error_reporting($err);
147$max_time = @ini_get(
"max_execution_time");
148if ($max_time && $max_time < $max_execution_time_for_deploy) {
149 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.");
150 @ini_set(
"max_execution_time", $max_execution_time_for_deploy);
154$dolibarrdataroot = preg_replace(
'/([\\/]+)$/i',
'', DOL_DATA_ROOT);
155$allowonlineinstall =
true;
157if (
dol_is_file($dolibarrdataroot.
'/installmodules.lock')) {
158 $allowonlineinstall =
false;
164if ($mode ==
'marketplace') {
169 $remotestore->loadRemoteSources(
false);
183$parameters = array();
184$reshook = $hookmanager->executeHooks(
'doActions', $parameters, $object, $action);
190if (GETPOSTISSET(
'mode')) {
191 $mode =
GETPOST(
'mode',
'alpha');
192 if ($mode ==
'common' && !
getDolGlobalString(
'MAIN_MODULE_SETUP_ON_LIST_BY_DEFAULT')) {
193 dolibarr_set_const($db,
"MAIN_MODULE_SETUP_ON_LIST_BY_DEFAULT", $mode,
'chaine', 0,
'', $conf->entity);
199if (
GETPOST(
'buttonreset',
'alpha')) {
200 $search_keyword =
'';
203 $search_version =
'';
206if ($action ==
'install' && $allowonlineinstall) {
210 $tmpfile = $_FILES[
'fileinstall'][
'tmp_name'];
211 $original_file = basename($_FILES[
"fileinstall"][
"name"]);
212 $original_file = preg_replace(
'/\s*\(\d+\)\.zip$/i',
'.zip', $original_file);
215 if (!$original_file) {
216 $langs->load(
"Error");
217 setEventMessages($langs->trans(
"ErrorModuleFileRequired"),
null,
'warnings');
220 if (!$error && !preg_match(
'/\.zip$/i', $original_file)) {
221 $langs->load(
"errors");
222 setEventMessages($langs->trans(
"ErrorFileMustBeADolibarrPackage", $original_file),
null,
'errors');
225 if (!$error && !preg_match(
'/^(module[a-zA-Z0-9]*_|theme_|).*\-([0-9][0-9\.]*)(\s\(\d+\)\s)?\.zip$/i', $original_file)) {
226 $langs->load(
"errors");
227 setEventMessages($langs->trans(
"ErrorFilenameDosNotMatchDolibarrPackageRules", $original_file,
'modulename-x[.y.z].zip'),
null,
'errors');
230 if (empty($tmpfile)) {
231 $langs->load(
"errors");
238 if ($original_file) {
240 dol_mkdir($conf->admin->dir_temp.
'/'.$original_file);
243 $tmpdir = preg_replace(
'/\.zip$/i',
'', $original_file).
'.dir';
246 dol_mkdir($conf->admin->dir_temp.
'/'.$tmpdir);
250 if ((
int) $result > 0) {
251 $resultuncompress =
dol_uncompress($newfile, $conf->admin->dir_temp.
'/'.$tmpdir);
253 if (!empty($resultuncompress[
'error'])) {
254 $langs->load(
"errors");
255 setEventMessages($langs->trans($resultuncompress[
'error'], $original_file),
null,
'errors');
259 $modulename = preg_replace(
'/module_/',
'', $original_file);
260 $modulename = preg_replace(
'/\-([0-9][0-9\.]*)\.zip$/i',
'', $modulename);
262 $modulenamedir = $conf->admin->dir_temp.
'/'.$tmpdir.
'/'.$modulename;
265 $modulenamedir = $conf->admin->dir_temp.
'/'.$tmpdir.
'/htdocs/'.$modulename;
268 setEventMessages($langs->trans(
"ErrorModuleFileSeemsToHaveAWrongFormat").
'<br>'.$langs->trans(
"ErrorModuleFileSeemsToHaveAWrongFormat2", $modulename,
'htdocs/'.$modulename),
null,
'errors');
273 dol_syslog(
"Uncompress of module file is a success.");
312 if (
GETPOST(
'checkforcompliance') ==
'on') {
314 $res = include_once DOL_DOCUMENT_ROOT.
'/core/modules/DolibarrModules.class.php';
316 $checkRes = $dolibarrmodule->checkForcompliance($modulename);
318 if (!is_numeric($checkRes) && $checkRes !=
'') {
319 $langs->load(
"errors");
320 setEventMessages($modulename.
' : '.$langs->trans($checkRes),
null,
'errors');
334 $modulenamearrays = array();
335 if (
dol_is_file($modulenamedir.
'/metapackage.conf')) {
337 $metafile = file_get_contents($modulenamedir.
'/metapackage.conf');
338 $modulenamearrays = explode(
"\n", $metafile);
340 $modulenamearrays[$modulename] = $modulename;
345 foreach ($modulenamearrays as $modulenameval) {
346 if (strpos($modulenameval,
'#') === 0) {
349 if (strpos($modulenameval,
'//') === 0) {
352 if (!trim($modulenameval)) {
359 $submodulenamedir = $conf->admin->dir_temp.
'/'.$tmpdir.
'/'.$modulenameval;
361 $submodulenamedir = $conf->admin->dir_temp.
'/'.$tmpdir.
'/htdocs/'.$modulenameval;
363 dol_syslog(
"We copy now directory ".$submodulenamedir.
" into target dir ".$dirins.
'/'.$modulenameval);
364 $resultcopy =
dolCopyDir($submodulenamedir, $dirins.
'/'.$modulenameval,
'0444', 1);
365 if ($resultcopy <= 0) {
366 dol_syslog(
'Failed to call dolCopyDir result='.$resultcopy.
" with param ".$submodulenamedir.
" and ".$dirins.
'/'.$modulenameval, LOG_WARNING);
367 $langs->load(
"errors");
368 setEventMessages($langs->trans(
"ErrorFailToCopyDir", $submodulenamedir, $dirins.
'/'.$modulenameval),
null,
'errors');
376 setEventMessages($langs->trans(
"ErrorFailToRenameFile", $tmpfile, $newfile).
' - code = '.$result,
null,
'errors');
382 $securityevent =
new Events($db);
384 $text = $langs->trans(
"SecurityModuleDeploymentError",
dol_sanitizePathName($_FILES[
"fileinstall"][
"name"]));
385 $securityevent->type =
'MODULE_DEPLOYMENT_ERROR';
387 $text = $langs->trans(
"SecurityModuleDeploymentSuccess",
dol_sanitizePathName($_FILES[
"fileinstall"][
"name"]));
388 $securityevent->type =
'MODULE_DEPLOYMENT_SUCCESS';
390 $securityevent->dateevent = $now;
391 $securityevent->description = $text;
393 $resultcreateevent = $securityevent->create($user);
396 $searchParams = array(
397 'search_keyword' => $modulenameval,
398 'search_status' =>
'-1',
399 'search_nature' =>
'-1',
400 'search_version' =>
'-1'
402 $queryString = http_build_query($searchParams);
403 $redirectUrl = DOL_URL_ROOT .
'/admin/modules.php?' . $queryString;
405 $message = $langs->trans(
"SetupIsReadyForUse", $redirectUrl, $langs->transnoentitiesnoconv(
"Home").
' - '.$langs->transnoentitiesnoconv(
"Setup").
' - '.$langs->transnoentitiesnoconv(
"Modules"));
409} elseif ($action ==
'install' && !$allowonlineinstall) {
410 httponly_accessforbidden(
"You try to bypass the protection to disallow deployment of an external module. Hack attempt ?");
413if ($action ==
'set' && $user->admin) {
417 $resarray = activateModule($value);
418 if ($checkOldValue !=
getDolGlobalInt(
'CHECKLASTVERSION_EXTERNALMODULE')) {
419 setEventMessage($langs->trans(
'WarningModuleHasChangedLastVersionCheckParameter', $value),
'warnings');
421 if ($csrfCheckOldValue !=
getDolGlobalInt(
'MAIN_SECURITY_CSRF_WITH_TOKEN')) {
422 setEventMessage($langs->trans(
'WarningModuleHasChangedSecurityCsrfParameter', $value),
'warnings');
426 if (!empty($resarray[
'errors'])) {
430 if ($resarray[
'nbperms'] > 0) {
431 $tmpsql =
"SELECT COUNT(rowid) as nb FROM ".MAIN_DB_PREFIX.
"user WHERE admin <> 1";
432 $resqltmp = $db->query($tmpsql);
434 $obj = $db->fetch_object($resqltmp);
436 if ($obj && $obj->nb > 1) {
437 $msg = $langs->trans(
'ModuleEnabledAdminMustCheckRights');
445 header(
"Location: ".$_SERVER[
"PHP_SELF"].
"?mode=".$mode.$param.($page_y ?
'&page_y='.$page_y :
''));
447} elseif ($action ==
'reset' && $user->admin &&
GETPOST(
'confirm') ==
'yes') {
448 $result = unActivateModule($value);
453 header(
"Location: ".$_SERVER[
"PHP_SELF"].
"?mode=".$mode.$param.($page_y ?
'&page_y='.$page_y :
''));
455} elseif (
getDolGlobalInt(
"MAIN_FEATURES_LEVEL") > 1 && $action ==
'reload' && $user->admin &&
GETPOST(
'confirm') ==
'yes') {
456 $result = unActivateModule($value, 0,
'newboxdefonly');
460 header(
"Location: ".$_SERVER[
"PHP_SELF"].
"?mode=".$mode.$param.($page_y ?
'&page_y='.$page_y :
''));
462 $resarray = activateModule($value, 0, 1);
464 if (!empty($resarray[
'errors'])) {
467 if ($resarray[
'nbperms'] > 0) {
468 $tmpsql =
"SELECT COUNT(rowid) as nb FROM ".MAIN_DB_PREFIX.
"user WHERE admin <> 1";
469 $resqltmp = $db->query($tmpsql);
471 $obj = $db->fetch_object($resqltmp);
472 if ($obj && $obj->nb > 1) {
473 $msg = $langs->trans(
'ModuleEnabledAdminMustCheckRights');
481 header(
"Location: ".$_SERVER[
"PHP_SELF"].
"?mode=".$mode.$param.($page_y ?
'&page_y='.$page_y :
''));
490$form =
new Form($db);
493$morecss = array(
"/admin/remotestore/css/store.css");
501$help_url =
'EN:First_setup|FR:Premiers_paramétrages|ES:Primeras_configuraciones';
502llxHeader(
'', $langs->trans(
"Setup"), $help_url,
'', 0, 0, $morejs, $morecss,
'',
'mod-admin page-modules');
508$arrayofnatures = array(
509 'core' => array(
'label' => $langs->transnoentitiesnoconv(
"NativeModules")),
510 'external' => array(
'label' => $langs->transnoentitiesnoconv(
"External").
' - ['.$langs->trans(
"AllPublishers").
']')
512$arrayofwarnings = array();
513$arrayofwarningsext = array();
522$modNameLoaded = array();
526foreach ($modulesdir as $dir) {
529 dol_syslog(
"Scan directory ".$dir.
" for module descriptor files (modXXX.class.php)");
530 $handle = @opendir($dir);
531 if (is_resource($handle)) {
532 while (($file = readdir($handle)) !==
false) {
534 if (is_readable($dir.$file) && substr($file, 0, 3) ==
'mod' && substr($file,
dol_strlen($file) - 10) ==
'.class.php') {
535 $modName = substr($file, 0,
dol_strlen($file) - 10);
538 if (!empty($modNameLoaded[$modName])) {
539 $mesg =
"Error: Module ".$modName.
" was found twice: Into ".$modNameLoaded[$modName].
" and ".$dir.
". You probably have an old file on your disk.<br>";
546 $res = include_once $dir.$file;
547 if (class_exists($modName)) {
548 $objMod =
new $modName($db);
549 '@phan-var-force DolibarrModules $objMod';
551 $modNameLoaded[$modName] = $dir;
552 if (!$objMod->numero > 0 && $modName !=
'modUser') {
553 dol_syslog(
'The module descriptor '.$modName.
' must have a numero property', LOG_ERR);
555 $j = $objMod->numero;
557 $modulequalified = 1;
560 $const_name =
'MAIN_MODULE_'.strtoupper(preg_replace(
'/^mod/i',
'', get_class($objMod)));
562 $modulequalified = 0;
565 $modulequalified = 0;
568 $modulequalified = 0;
572 if (!empty($objMod->hidden)) {
573 $modulequalified = 0;
576 if ($modulequalified > 0) {
578 $external = ($objMod->isCoreOrExternalModule() ==
'external');
588 $arrayofnatures[
'external_'.$publisher] = array(
'label' => $langs->trans(
"External").
' - '.$publisher,
'data-html' => $langs->trans(
"External").
' - <span class="opacitymedium inine-block valignmiddle">'.$publisher.
'</span>');
590 $arrayofnatures[
'external_'] = array(
'label' => $langs->trans(
"External").
' - ['.$langs->trans(
"UnknownPublishers").
']');
593 ksort($arrayofnatures);
596 $filename[$i] = $modName;
597 $modules[$modName] = $objMod;
600 if (is_array($objMod->familyinfo) && !empty($objMod->familyinfo)) {
601 $familyinfo = array_merge($familyinfo, $objMod->familyinfo);
602 $familykey = key($objMod->familyinfo);
604 $familykey = $objMod->family;
606 '@phan-var-force string $familykey';
608 $moduleposition = ($objMod->module_position ? $objMod->module_position :
'50');
609 if ($objMod->isCoreOrExternalModule() ==
'external' && $moduleposition < 100000) {
611 $moduleposition =
'80';
615 if (!empty($objMod->warnings_activation)) {
616 $arrayofwarnings[$modName] = $objMod->warnings_activation;
618 if (!empty($objMod->warnings_activation_ext)) {
619 $arrayofwarningsext[$modName] = $objMod->warnings_activation_ext;
622 $familyposition = (empty($familyinfo[$familykey][
'position']) ?
'0' : $familyinfo[$familykey][
'position']);
623 if ($external && !in_array($familykey, array_keys($familyinfo))) {
625 if (is_numeric($familyposition)) {
626 $familyposition = sprintf(
"%03d", (
int) $familyposition + 100);
630 $orders[$i] = $familyposition.
"_".$familykey.
"_".$moduleposition.
"_".$j;
633 $specialstring =
'unknown';
634 if ($objMod->version ==
'development' || $objMod->version ==
'experimental') {
635 $specialstring =
'expdev';
637 if (isset($categ[$specialstring])) {
638 $categ[$specialstring]++;
640 $categ[$specialstring] = 1;
645 dol_syslog(
"Module ".get_class($objMod).
" not qualified");
648 print
info_admin(
"admin/modules.php Warning bad descriptor file : ".$dir.$file.
" (Class ".$modName.
" not found into file)", 0, 0,
'1',
'warning');
651 dol_syslog(
"Failed to load ".$dir.$file.
" ".$e->getMessage(), LOG_ERR);
658 dol_syslog(
"htdocs/admin/modules.php: Failed to open directory ".$dir.
". See permission and open_basedir option.", LOG_WARNING);
662'@phan-var-force array<string,DolibarrModules> $modules';
665if ($action ==
'reset_confirm' && $user->admin) {
666 if (!empty($modules[$value])) {
667 $objMod = $modules[$value];
669 if (!empty($objMod->langfiles)) {
670 $langs->loadLangs($objMod->langfiles);
673 $form =
new Form($db);
674 $formconfirm = $form->formconfirm($_SERVER[
"PHP_SELF"].
'?value='.$value.
'&mode='.$mode.$param, $langs->trans(
'ConfirmUnactivation'), $langs->trans(
GETPOST(
'confirm_message_code')),
'reset',
'',
'no', 1);
678if ($action ==
'reload_confirm' && $user->admin) {
679 if (!empty($modules[$value])) {
680 $objMod = $modules[$value];
682 if (!empty($objMod->langfiles)) {
683 $langs->loadLangs($objMod->langfiles);
686 $form =
new Form($db);
687 $formconfirm = $form->formconfirm($_SERVER[
"PHP_SELF"].
'?value='.$value.
'&mode='.$mode.$param, $langs->trans(
'ConfirmReload'), $langs->trans(
GETPOST(
'confirm_message_code')),
'reload',
'',
'no', 1);
698$nbofactivatedmodules = count($conf->modules);
701$nbmodulesnotautoenabled = count($conf->modules);
702$listofmodulesautoenabled = array(
'user',
'agenda',
'fckeditor',
'export',
'import');
703foreach ($listofmodulesautoenabled as $moduleautoenable) {
704 if (in_array($moduleautoenable, $conf->modules)) {
705 $nbmodulesnotautoenabled--;
713if ($mode ==
'common' || $mode ==
'commonkanban') {
714 $desc = $langs->trans(
"ModulesDesc",
'{picto}');
715 $desc .=
' '.$langs->trans(
"ModulesDesc2",
'{picto2}');
716 $desc = str_replace(
'{picto}',
img_picto(
'',
'switch_off',
'class="size15x"'), $desc);
717 $desc = str_replace(
'{picto2}',
img_picto(
'',
'setup',
'class="size15x"'), $desc);
719 $deschelp .=
'<div class="info hideonsmartphone">'.$desc.
"<br></div>\n";
722 $deschelp .=
'<div class="info">'.$langs->trans(
getDolGlobalString(
'MAIN_SETUP_MODULES_INFO')).
"<br></div>\n";
728if ($mode ==
'deploy') {
729 $deschelp =
'<div class="info hideonsmartphone">'.$langs->trans(
"ModulesDeployDesc", $langs->transnoentitiesnoconv(
"AvailableModules")).
"<br></div><br>\n";
731if ($mode ==
'develop') {
732 $deschelp =
'<div class="info hideonsmartphone">'.$langs->trans(
"ModulesDevelopDesc").
"<br></div><br>\n";
738if ($mode ==
'common' || $mode ==
'commonkanban') {
741 print
'<form method="POST" id="searchFormList" action="'.dolBuildUrl($_SERVER[
"PHP_SELF"]).
'">';
742 print
'<input type="hidden" name="token" value="'.newToken().
'">';
743 if (isset($optioncss) && $optioncss !=
'') {
744 print
'<input type="hidden" name="optioncss" value="'.$optioncss.
'">';
746 if (isset($sortfield) && $sortfield !=
'') {
747 print
'<input type="hidden" name="sortfield" value="'.$sortfield.
'">';
749 if (isset($sortorder) && $sortorder !=
'') {
750 print
'<input type="hidden" name="sortorder" value="'.$sortorder.
'">';
752 if (isset($page) && $page !=
'') {
753 print
'<input type="hidden" name="page" value="'.$page.
'">';
755 print
'<input type="hidden" name="mode" value="'.$mode.
'">';
761 $moreforfilter =
'<div class="valignmiddle">';
763 $moreforfilter .=
'<div class="floatright right pagination paddingtop --module-list"><ul><li>';
764 $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'));
766 $moreforfilter .=
dolGetButtonTitle($langs->trans(
'ViewList'),
'',
'fa fa-bars imgforviewmode', $_SERVER[
"PHP_SELF"].
'?mode=common'.$param,
'', ($mode ==
'common' ? 2 : 1), array(
'morecss' =>
'reposition'));
767 $moreforfilter .=
dolGetButtonTitle($langs->trans(
'ViewKanban'),
'',
'fa fa-th-list imgforviewmode', $_SERVER[
"PHP_SELF"].
'?mode=commonkanban'.$param,
'', ($mode ==
'commonkanban' ? 2 : 1), array(
'morecss' =>
'reposition'));
768 $moreforfilter .=
'</li></ul></div>';
770 $moreforfilter .=
'<div class="divfilteralone colorbacktimesheet float valignmiddle">';
771 $moreforfilter .=
'<div class="divsearchfield paddingtop paddingbottom valignmiddle inline-block">';
772 $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')).
'">';
773 $moreforfilter .=
'</div>';
774 $moreforfilter .=
'<div class="divsearchfield paddingtop paddingbottom valignmiddle inline-block">';
775 $moreforfilter .= $form->selectarray(
'search_nature', $arrayofnatures,
dol_escape_htmltag($search_nature), $langs->trans(
'Origin'), 0, 0,
'', 0, 0, 0,
'',
'maxwidth250', 1);
776 $moreforfilter .=
'</div>';
779 $array_version = array(
'stable' => $langs->transnoentitiesnoconv(
"Stable"));
781 $array_version[
'deprecated'] = $langs->trans(
"Deprecated");
784 $array_version[
'experimental'] = $langs->trans(
"Experimental");
787 $array_version[
'development'] = $langs->trans(
"Development");
789 $moreforfilter .=
'<div class="divsearchfield paddingtop paddingbottom valignmiddle inline-block">';
790 $moreforfilter .= $form->selectarray(
'search_version', $array_version, $search_version, $langs->transnoentitiesnoconv(
'Version'), 0, 0,
'', 0, 0, 0,
'',
'maxwidth150', 1);
791 $moreforfilter .=
'</div>';
793 $array_status = array(
'active' => $langs->transnoentitiesnoconv(
"Enabled"),
'disabled' => $langs->transnoentitiesnoconv(
"Disabled"));
794 $moreforfilter .=
'<div class="divsearchfield paddingtop paddingbottom valignmiddle inline-block">';
795 $moreforfilter .= $form->selectarray(
'search_status', $array_status, $search_status, $langs->transnoentitiesnoconv(
'Status'), 0, 0,
'', 0, 0, 0,
'',
'maxwidth150', 1);
796 $moreforfilter .=
'</div>';
797 $moreforfilter .=
' ';
798 $moreforfilter .=
'<div class="divsearchfield valignmiddle inline-block">';
799 $moreforfilter .=
'<input type="submit" name="buttonsubmit" class="button small nomarginleft" value="'.dolPrintHTMLForAttribute($langs->trans(
"Refresh")).
'">';
800 if ($search_keyword || ($search_nature && $search_nature !=
'-1') || ($search_version && $search_version !=
'-1') || ($search_status && $search_status !=
'-1')) {
801 $moreforfilter .=
' ';
802 $moreforfilter .=
'<input type="submit" name="buttonreset" class="buttonreset noborderall nomargintop nomarginbottom" value="'.dolPrintHTMLForAttribute($langs->trans(
"Reset")).
'">';
804 $moreforfilter .=
'</div>';
805 $moreforfilter .=
'</div>';
807 $moreforfilter .=
'</div>';
809 print $moreforfilter;
810 $parameters = array();
811 $reshook = $hookmanager->executeHooks(
'printFieldPreListTitle', $parameters, $object, $action);
812 print $hookmanager->resPrint;
816 print
'<div class="clearboth"></div><br><br>';
819 $parameters = array();
820 $reshook = $hookmanager->executeHooks(
'insertExtraHeader', $parameters, $object, $action);
825 $disabled_modules = array();
826 if (!empty($_SESSION[
"disablemodules"])) {
827 $disabled_modules = explode(
',', $_SESSION[
"disablemodules"]);
832 $foundoneexternalmodulewithupdate = 0;
834 $atleastonequalified = 0;
835 $atleastoneforfamily = 0;
837 foreach ($orders as $key => $value) {
839 $tab = explode(
'_', $value);
840 $familykey = $tab[1];
841 $module_position = $tab[2];
843 $modName = $filename[$key];
846 $objMod = $modules[$modName];
848 if (!is_object($objMod)) {
853 if ($mode ==
'expdev' && $objMod->version !=
'development' && $objMod->version !=
'experimental') {
857 if (!$objMod->getName()) {
858 dol_syslog(
"Error for module ".$key.
" - Property name of module looks empty", LOG_WARNING);
862 $modulenameshort = strtolower(preg_replace(
'/^mod/i',
'', get_class($objMod)));
863 $const_name =
'MAIN_MODULE_'.strtoupper(preg_replace(
'/^mod/i',
'', get_class($objMod)));
866 $modulename = $objMod->getName();
867 $moduletechnicalname = $objMod->name;
868 $moduledesc = $objMod->getDesc();
869 $moduledesclong = $objMod->getDescLong();
870 $moduleauthor = $objMod->getPublisher();
873 if ($search_keyword) {
875 if (preg_match(
'/'.preg_quote($search_keyword,
'/').
'/i', $modulename)
876 || preg_match(
'/'.preg_quote($search_keyword,
'/').
'/i', $moduletechnicalname)
877 || ($moduledesc && preg_match(
'/'.preg_quote($search_keyword,
'/').
'/i', $moduledesc))
878 || ($moduledesclong && preg_match(
'/'.preg_quote($search_keyword,
'/').
'/i', $moduledesclong))
879 || ($moduleauthor && preg_match(
'/'.preg_quote($search_keyword,
'/').
'/i', $moduleauthor))
887 if ($search_status) {
895 if ($search_nature) {
896 if (preg_match(
'/^external/', $search_nature) && $objMod->isCoreOrExternalModule() !=
'external') {
900 if (preg_match(
'/^external_(.*)$/', $search_nature, $reg)) {
906 if (!$reg[1] && !empty($publisher)) {
910 if ($search_nature ==
'core' && $objMod->isCoreOrExternalModule() ==
'external') {
914 if ($search_version) {
915 if (($objMod->version ==
'development' || $objMod->version ==
'experimental' || preg_match(
'/deprecated/', $objMod->version)) && $search_version ==
'stable') {
918 if ($objMod->version !=
'development' && ($search_version ==
'development')) {
921 if ($objMod->version !=
'experimental' && ($search_version ==
'experimental')) {
924 if (!preg_match(
'/deprecated/', $objMod->version) && ($search_version ==
'deprecated')) {
929 $atleastonequalified++;
932 if (isset($objMod->langfiles) && is_array($objMod->langfiles)) {
933 foreach ($objMod->langfiles as $domain) {
934 $langs->load($domain);
939 if ($familykey != $oldfamily) {
941 print
'</table></div><br>';
944 $familytext = empty($familyinfo[$familykey][
'label']) ? $familykey : $familyinfo[$familykey][
'label'];
948 if ($mode ==
'commonkanban') {
949 print
'<div class="box-flex-container kanban">';
951 print
'<div class="div-table-responsive">';
952 print
'<table class="tagtable liste" summary="list_of_modules">'.
"\n";
955 $atleastoneforfamily = 0;
958 $atleastoneforfamily++;
960 if ($familykey != $oldfamily) {
961 $familytext = empty($familyinfo[$familykey][
'label']) ? $familykey : $familyinfo[$familykey][
'label'];
962 $oldfamily = $familykey;
966 $version = $objMod->getVersion(0);
969 if (preg_match(
'/development/i', $version)) {
970 $warningstring = $langs->trans(
"Development");
972 if (preg_match(
'/experimental/i', $version)) {
973 $warningstring = $langs->trans(
"Experimental");
975 if (preg_match(
'/deprecated/i', $version)) {
976 $warningstring = $langs->trans(
"Deprecated");
979 if ($objMod->isCoreOrExternalModule() ==
'external' || preg_match(
'/development|experimental|deprecated/i', $version)) {
980 $versiontrans .= $objMod->getVersion(1);
983 if ($objMod->isCoreOrExternalModule() ==
'external' && ($action ==
'checklastversion' ||
getDolGlobalString(
'CHECKLASTVERSION_EXTERNALMODULE'))) {
987 $checkRes = $objMod->checkForUpdate();
989 setEventMessages($objMod->getName().
' : '.preg_replace(
'/[^a-z0-9_\.\-\s]/i',
'', $versiontrans).
' -> '.preg_replace(
'/[^a-z0-9_\.\-\s]/i',
'', $objMod->lastVersion),
null,
'warnings');
990 } elseif ($checkRes < 0) {
991 setEventMessages($objMod->getName().
' '.$langs->trans(
'CheckVersionFail'),
null,
'errors');
995 if ($objMod->isCoreOrExternalModule() ==
'external' && $action ==
'checklastversion' && !
getDolGlobalString(
'DISABLE_CHECK_ON_MALWARE_MODULES')) {
996 $checkRes = $objMod->checkForCompliance();
997 if (!is_numeric($checkRes) && $checkRes !=
'') {
998 $langs->load(
"errors");
999 setEventMessages($objMod->getName().
' : '.$langs->trans($checkRes),
null,
'errors');
1005 if ($objMod->isCoreOrExternalModule() ==
'external') {
1006 $imginfo =
"info_black";
1009 $codeenabledisable =
'';
1013 if (in_array($modulenameshort, $disabled_modules)) {
1014 $objMod->disabled =
true;
1021 if (!empty($arrayofwarnings[$modName])) {
1022 $codeenabledisable .=
'<!-- This module has a warning to show when we activate it (note: your country is '.$mysoc->country_code.
') -->'.
"\n";
1025 if (!empty($objMod->disabled)) {
1026 $codeenabledisable .= $langs->trans(
"Disabled");
1027 } elseif (is_object($objMod)
1028 && (!empty($objMod->always_enabled) || ((
isModEnabled(
'multicompany') && $objMod->core_enabled) && ($user->entity || $conf->entity != 1)))) {
1030 if (method_exists($objMod,
'alreadyUsed') && $objMod->alreadyUsed()) {
1031 $codeenabledisable .= $langs->trans(
"Used");
1033 $codeenabledisable .=
img_picto($langs->trans(
"Required"),
'switch_on',
'', 0, 0, 0,
'',
'opacitymedium valignmiddle');
1041 if (is_object($objMod) && !empty($objMod->warnings_unactivation[
$mysoc->country_code]) && method_exists($objMod,
'alreadyUsed') && $objMod->alreadyUsed()) {
1042 $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.
'">';
1043 $codeenabledisable .=
img_picto($langs->trans(
"Activated").($warningstring ?
' '.$warningstring :
''),
'switch_on');
1044 $codeenabledisable .=
'</a>';
1046 $codeenabledisable .=
' ';
1047 $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.
'">';
1048 $codeenabledisable .=
img_picto($langs->trans(
"Reload"),
'refresh',
'class="opacitymedium"');
1049 $codeenabledisable .=
'</a>';
1052 $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.
'">';
1053 $codeenabledisable .=
img_picto($langs->trans(
"Activated").($warningstring ?
' '.$warningstring :
''),
'switch_on');
1054 $codeenabledisable .=
'</a>';
1056 $codeenabledisable .=
' ';
1057 $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.
'">';
1058 $codeenabledisable .=
img_picto($langs->trans(
"Reload"),
'refresh',
'class="opacitymedium"');
1059 $codeenabledisable .=
'</a>';
1065 if (!empty($objMod->config_page_url) && !$disableSetup) {
1066 $backtourlquery = [];
1067 if ($search_keyword !=
'') {
1068 $backtourlquery += [
'search_keyword' => $search_keyword];
1070 if ($search_nature > -1) {
1071 $backtourlquery += [
'search_nature' => $search_nature];
1073 if ($search_version > -1) {
1074 $backtourlquery += [
'search_version' => $search_version];
1076 if ($search_status > -1) {
1077 $backtourlquery += [
'search_status' => $search_status];
1079 $backtourl =
dolBuildUrl($_SERVER[
"PHP_SELF"], $backtourlquery);
1083 'save_lastsearch_values' => 1,
1084 'backtopage' => $backtourl,
1086 if (is_array($objMod->config_page_url)) {
1088 foreach ($objMod->config_page_url as $page) {
1091 $codetoconfig .=
'<a href="'.$urlpage.
'" title="'.$langs->trans($page).
'">'.
img_picto(ucfirst($page),
"setup").
'</a>';
1094 if (preg_match(
'/^([^@]+)@([^@]+)$/i', $urlpage, $regs)) {
1095 $urltouse =
dol_buildpath(
'/'.$regs[2].
'/admin/'.$regs[1], 1);
1096 $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>';
1098 $urltouse = $urlpage;
1099 $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>';
1103 } elseif (preg_match(
'/^([^@]+)@([^@]+)$/i', (
string) $objMod->config_page_url, $regs)) {
1104 $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>';
1106 $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>';
1109 $codetoconfig .=
img_picto($langs->trans(
"NothingToSetup"),
"setup",
'class="opacitytransp" style="padding-right: 6px"', 0, 0, 0,
'',
'fa-15');
1113 if (!empty($objMod->always_enabled)) {
1115 $codeenabledisable .=
'<!-- Message to show: an always_enabled module has been disabled -->'.
"\n";
1116 $codeenabledisable .=
'<a class="reposition" id="idalways'.$objMod->numero.
'" data-alreadyclicked="0" href="'.$_SERVER[
"PHP_SELF"].
'?id='.$objMod->numero.
'&token='.
newToken().
'&module_position='.$module_position.
'&action=set&token='.
newToken().
'&value='.$modName.
'&mode='.$mode.$param.
'"';
1117 $codeenabledisable .=
'>';
1118 $codeenabledisable .=
img_picto($langs->trans(
"Disabled"),
'switch_off');
1119 $codeenabledisable .=
"</a>\n";
1120 } elseif (!empty($objMod->disabled)) {
1121 $codeenabledisable .= $langs->trans(
"Disabled");
1124 $warningmessage =
'';
1127 if (!empty($arrayofwarnings[$modName])) {
1128 $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";
1129 foreach ($arrayofwarnings[$modName] as $keycountry => $cursorwarningmessage) {
1130 if (preg_match(
'/^always/', $keycountry) || (
$mysoc->country_code && preg_match(
'/^'.
$mysoc->country_code.
'/', $keycountry))) {
1131 if (!is_array($cursorwarningmessage)) {
1132 $cursorwarningmessage = array($cursorwarningmessage);
1134 foreach ($cursorwarningmessage as $messagetoshow) {
1135 if (preg_match(
'/:1$/', $messagetoshow)) {
1138 $messagetoshow = preg_replace(
'/:1$/',
'', $messagetoshow);
1141 $warningmessage .= ($warningmessage ?
"\n" :
"").$langs->trans($messagetoshow, $objMod->getName(),
$mysoc->country_code);
1146 if ($objMod->isCoreOrExternalModule() ==
'external' && !empty($arrayofwarningsext)) {
1147 $codeenabledisable .=
'<!-- This module is an external module and it may have a warning to show (note: your country is '.$mysoc->country_code.
') -->'.
"\n";
1148 foreach ($arrayofwarningsext as $keymodule => $arrayofwarningsextbycountry) {
1149 $keymodulelowercase = strtolower(preg_replace(
'/^mod/',
'', $keymodule));
1150 if (preg_match(
'/^always/', $keymodulelowercase) || in_array($keymodulelowercase, $conf->modules)) {
1151 foreach ($arrayofwarningsextbycountry as $keycountry => $cursorwarningmessage) {
1152 if (preg_match(
'/^always/', $keycountry) || (
$mysoc->country_code && preg_match(
'/^'.
$mysoc->country_code.
'/', $keycountry))) {
1153 if (!is_array($cursorwarningmessage)) {
1154 $cursorwarningmessage = array($cursorwarningmessage);
1156 foreach ($cursorwarningmessage as $messagetoshow) {
1158 $warningmessage .= ($warningmessage ?
"\n" :
"").$langs->trans($messagetoshow, $objMod->getName(),
$mysoc->country_code, $modules[$keymodule]->getName());
1160 $warningmessage .= ($warningmessage ?
"\n" :
"").($warningmessage ?
"\n" :
"").$langs->trans(
"Module").
' : '.$objMod->getName();
1161 if (!empty($objMod->editor_name)) {
1162 $warningmessage .= ($warningmessage ?
"\n" :
"").$langs->trans(
"Publisher").
' : '.$objMod->editor_name;
1164 if ($keymodulelowercase !=
'always') {
1165 $warningmessage .= ($warningmessage ?
"\n" :
"").$langs->trans(
"ModuleTriggeringThisWarning").
' : '.$modules[$keymodule]->getName();
1173 $urltogo = $_SERVER[
"PHP_SELF"].
'?id='.$objMod->numero.
'&token='.
newToken().
'&module_position='.$module_position.
'&action=set&token='.
newToken().
'&value='.$modName.
'&mode='.$mode.$param;
1176 $codeenabledisable .=
'<!-- Message to show: '.$warningmessage.
' -->'.
"\n";
1177 $codeenabledisable .=
'<a class="reposition" id="idqualified'.$objMod->numero.
'" data-alreadyclicked="0" href="'.$urltogo.
'"';
1178 if ($warningmessage) {
1179 $codeenabledisable .=
' onclick="return confirmDolibarr(\''.dol_escape_js($warningmessage).
'\', \
'idqualified'.$objMod->numero.
'\',
'.$popupWidth.',
'.$popupHeight.',
'.$disableCancel.');
"';
1181 $codeenabledisable .= '>';
1182 $codeenabledisable .= img_picto($langs->trans("Disabled
"), 'switch_off');
1183 $codeenabledisable .= "</a>\n
";
1186 // Set $codetoconfig
1187 $codetoconfig .= img_picto($langs->trans("NothingToSetup
"), "setup
", 'class="opacitytransp
" style="padding-right: 6px
"');
1190 if ($mode == 'commonkanban') {
1192 print $objMod->getKanbanView($codeenabledisable, $codetoconfig);
1194 print '<tr class="oddeven
'.($warningstring ? ' info-box-content-warning
' : '').'">'."\n
";
1195 if (getDolGlobalString('MAIN_MODULES_SHOW_LINENUMBERS')) {
1196 print '<td class="width50
">'.$linenum.'</td>';
1199 // Picto + Name of module
1200 print ' <td class="tdoverflowmax200 minwidth200imp
" title="'.dol_escape_htmltag($objMod->getName()).'">';
1202 //if (is_array($objMod->need_dolibarr_version)) $alttext.=($alttext?' - ':'').'Dolibarr >= '.join('.',$objMod->need_dolibarr_version);
1203 //if (is_array($objMod->phpmin)) $alttext.=($alttext?' - ':'').'PHP >= '.join('.',$objMod->phpmin);
1204 if (!empty($objMod->picto)) {
1205 if (preg_match('/^\//i', $objMod->picto)) {
1206 print img_picto($alttext, $objMod->picto, 'class="valignmiddle pictomodule paddingrightonly
"', 1);
1208 print img_object($alttext, $objMod->picto, 'class="valignmiddle pictomodule paddingrightonly
"');
1211 print img_object($alttext, 'generic', 'class="valignmiddle paddingrightonly
"');
1213 print ' <span class="valignmiddle
">'.$objMod->getName().'</span>';
1217 print '<td class="valignmiddle tdoverflowmax300 minwidth200imp opacitylow
">';
1218 print nl2br($objMod->getDesc());
1222 print '<td class="center nowrap
" style="width: 82px;
">';
1223 print '<a href="javascript:
document_preview(\
''.DOL_URL_ROOT.
'/admin/modulehelp.php?id='.((
int) $objMod->numero).
'\',\
'text/html\',\''.dol_escape_js($langs->trans(
"Module")).
'\')
">';
1224 print img_picto(($objMod->isCoreOrExternalModule() == 'external' ? $langs->trans("ExternalModule
").' - ' : '').$langs->trans("ClickToShowDescription
"), $imginfo, '', 0, 0, 0, '', 'purple');
1229 print '<td class="center nowrap width150
" title="'.dol_escape_htmltag(dol_string_nohtmltag($versiontrans)).'">';
1230 if ($objMod->needUpdate) {
1231 $versionTitle = $langs->trans('ModuleUpdateAvailable').' : '.$objMod->lastVersion;
1232 print '<span class="badge badge-warning classfortooltip
" title="'.dol_escape_htmltag($versionTitle).'">'.$versiontrans.'</span>';
1234 print $versiontrans;
1238 // Link enable/disable
1239 print '<td class="center valignmiddle left nowraponall
" width="60px
">';
1240 print $codeenabledisable;
1244 print '<td class="tdsetuppicto right valignmiddle
" width="60px
">';
1245 print $codetoconfig;
1250 if ($objMod->needUpdate) {
1251 $foundoneexternalmodulewithupdate++;
1255 if ($action == 'checklastversion') {
1256 if ($foundoneexternalmodulewithupdate) {
1257 setEventMessages($langs->trans("ModuleUpdateAvailable
"), null, 'warnings', '', 0, 1);
1259 setEventMessages($langs->trans("NoExternalModuleWithUpdate
"), null, 'mesgs');
1264 if ($mode == 'commonkanban') {
1272 if (!$atleastonequalified) {
1273 print '<br><span class="opacitymedium
">'.$langs->trans("NoDeployedModulesFoundWithThisSearchCriteria
").'</span><br><br>';
1276 print dol_get_fiche_end();
1280 // Show warning about external users
1281 print info_admin(showModulesExludedForExternal($modules))."\n
";
1286if ($mode == 'marketplace') {
1287 print dol_get_fiche_head($head, $mode, '', -1);
1293 print '<!-- summary of sources -->';
1295 // Marketplace and community modules
1296 print '<div class="div-
table-responsive-no-min
">';
1297 print '<table summary="list_of_modules
" class="noborder centpercent
">'."\n
";
1298 print '<tr class="liste_titre
">'."\n
";
1299 print '<td colspan="2
">'.$form->textwithpicto($langs->trans("ModuleProviderSites
"), $langs->trans("WebSiteDesc
")).'</td>';
1300 print '<td class="hideonsmartphone
">';
1305 $url = 'https://www.dolistore.com';
1307 // Source Marketplace DoliStore
1308 print '<tr class="oddeven nohover
" height="100
">'."\n
";
1309 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>';
1310 print '<td class="minwidth500imp smallonsmartphone
"><span class="opacitymedium
">'.$langs->trans("DoliStoreDesc
").'</span><br>';
1311 print img_picto('', 'url', 'class="pictofixedwidth
"').'<a href="'.$url.'" target="_blank
" rel="noopener noreferrer external
">'.$url.'</a></td>';
1313 print ajax_constantonoff('MAIN_ENABLE_EXTERNALMODULES_DOLISTORE', array(), null, 0, 0, 1);
1315 print '<td class="center
">';
1316 if (!getDolGlobalString('MAIN_DISABLE_EXTERNALMODULES_DOLISTORE') && getDolGlobalInt('MAIN_ENABLE_EXTERNALMODULES_DOLISTORE')) {
1317 $messagetoadd = '<br><span class="small
">';
1318 if ($remotestore->dolistoreApiStatus <= 0) {
1319 $messagetoadd = '<br>'.$remotestore->dolistoreApiError.'<br>Failed to get answer of remote API server<br>';
1322 $messagetoadd .= '<br>Using Shop address MAIN_MODULE_DOLISTORE_SHOP_URL = '.$remotestore->shop_url;
1323 $messagetoadd .= '<br>Using Remote API address MAIN_MODULE_DOLISTORE_API_URL = '.$remotestore->dolistore_api_url;
1324 $messagetoadd .= '<br>Using API public key MAIN_MODULE_DOLISTORE_API_KEY = '.$remotestore->dolistore_api_key;
1325 // Add basic auth if needed
1326 $basicAuthLogin = getDolGlobalString('MAIN_MODULE_DOLISTORE_BASIC_LOGIN');
1327 $basicAuthPassword = getDolGlobalString('MAIN_MODULE_DOLISTORE_BASIC_PASSWORD');
1328 if ($basicAuthLogin) {
1329 $messagetoadd .= '<br>Using basic auth login: base64('.$basicAuthLogin.':'.$basicAuthPassword.')';
1331 $messagetoadd .= '</span>';
1333 print $remotestore->libStatus($remotestore->dolistoreApiStatus, 2, $messagetoadd);
1338 $url = 'https://github.com/Dolibarr/dolibarr-community-modules';
1340 // Source Community github
1341 print '<tr class="oddeven nohover
" height="100
">'."\n
";
1342 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>';
1343 print '<td class="minwidth500imp smallonsmartphone
"><span class="opacitymedium
">'.$langs->trans("CommunityModulesDesc
").'</span><br>';
1344 print img_picto('', 'url', 'class="pictofixedwidth
"').'<a href="'.$url.'" target="_blank
" rel="noopener noreferrer external
">'.$url.'</a></td>';
1346 print ajax_constantonoff('MAIN_ENABLE_EXTERNALMODULES_COMMUNITY', array(), null, 0, 0, 1);
1348 print '<td class="center
">';
1349 if (!getDolGlobalString('MAIN_DISABLE_EXTERNALMODULES_COMMUNITY') && getDolGlobalInt('MAIN_ENABLE_EXTERNALMODULES_COMMUNITY')) {
1350 $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;
1351 $messagetoadd .= ' (Date: '.dol_print_date(dol_filemtime($remotestore->cache_file), 'dayhour', 'tzuserrel').')</span>';
1352 if ($remotestore->githubFileError) {
1353 $messagetoadd .= '<br><span class="error small
">'.$remotestore->githubFileError.'</span>';
1355 print $remotestore->libStatus($remotestore->githubFileStatus, 2, $messagetoadd);
1363 print dol_get_fiche_end();
1367 if ($remotestore->numberOfProviders > 0) {
1368 // $options is array with filter criteria
1369 $nbmaxtoshow = $options['per_page'];
1370 $options['per_page']++;
1372 //$remotestore->getRemoteCategories();
1373 //$remotestore->getRemoteProducts($options);
1375 //print '<span class="opacitymedium hideonsmartphone
">'.$langs->trans('DOLISTOREdescriptionLong').'</span><br><br>';
1377 $categories_tree = $remotestore->getCategories($options['categorie']); // Call API to get the categories
1379 $products_list = $remotestore->getProducts($options); // Get list of product from all sources
1381 $previouslink = $remotestore->get_previous_link();
1383 $nextlink = $remotestore->get_next_link();
1386 print '<div class="liste_titre liste_titre_bydiv centpercent
"><div class="">';
1388 print '<form method="POST
" class="centpercent
" id="searchFormList
" action="'.$remotestore->url.'">'; ?>
1389 <input type="hidden
" name="token
" value="<?php echo
newToken(); ?>
">
1390 <input type="hidden
" name="mode
" value="marketplace
">
1391 <input type="hidden
" name="page_y
" value="">
1392 <div class="divsearchfield
">
1393 <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">
1395 <div class="divsearchfield
">
1396 <input name="buttonsubmit
" class="button buttongen reposition
" value="<?php echo $langs->trans(
'Search') ?>
" type="submit
">
1398 print $form->textwithpicto('', $langs->trans('DOLISTOREdescriptionLong'));
1400 if ($search_keyword !== '') {
1401 print '<a class="buttonreset reposition
" href="'.$_SERVER["PHP_SELF"].'?mode=marketplace
">'.$langs->trans('Reset').'</a>';
1407 $totalnboflines = '<span class="product-count opacitymedium paddingleft
">';
1408 $totalnboflines .= $langs->trans("itemFound
", $remotestore->numberTotalOfProducts);
1409 $totalnboflines .= '</span>';
1411 print $totalnboflines;
1412 print $remotestore->getPagination();
1416 print '<div class="clearboth
"></div>';
1419 <?php if (!empty($categories_tree)) { ?>
1420 <div id="category-tree-left
" class="paddingtop
">
1423 print $categories_tree; ?>
1428 <div id="listing-content
" class="div-
table-responsive
" <?php if (empty($categories_tree)) { ?>style="width:100%;
"<?php } ?>>
1429 <table summary="list_of_modules
" id="list_of_modules
" class="productlist centpercent
">
1430 <tbody id="listOfModules
">
1431 <!-- $product_list is $remotestore->getProducts($options) done previously -->
1432 <?php print $products_list; ?>
1436 <div style="clear: both;
"></div>
1437 <div><?php print $remotestore->getPagination(); ?></div>
1443// Form to install an external module
1445if ($mode == 'deploy') {
1446 print dol_get_fiche_head($head, $mode, '', -1);
1448 $fullurl = '<a href="'.$urldolibarrmodules.'" target="_blank
" rel="noopener noreferrer
">'.$urldolibarrmodules.'</a>';
1450 if ($allowonlineinstall) {
1451 if (!in_array('/custom', explode(',', $dolibarr_main_url_root_alt))) {
1452 $message = info_admin($langs->trans("ConfFileMustContainCustom
", DOL_DOCUMENT_ROOT.'/custom', DOL_DOCUMENT_ROOT));
1456 if (!is_writable(dol_osencode($dirins))) {
1457 $langs->load("errors
");
1458 $message = info_admin($langs->trans("ErrorFailedToWriteInDir
", $dirins), 0, 0, '1', 'warning');
1462 $message = info_admin($langs->trans("NotExistsDirect
", $dirins).$langs->trans("InfDirAlt
").$langs->trans("InfDirExample
"));
1467 if (getDolGlobalString('MAIN_MESSAGE_INSTALL_MODULES_DISABLED_CONTACT_US')) {
1468 // Show clean message
1469 if (!is_numeric(getDolGlobalString('MAIN_MESSAGE_INSTALL_MODULES_DISABLED_CONTACT_US'))) {
1470 $message = info_admin($langs->trans(getDolGlobalString('MAIN_MESSAGE_INSTALL_MODULES_DISABLED_CONTACT_US')), 0, 0, 'warning');
1472 $message = info_admin($langs->trans('InstallModuleFromWebHasBeenDisabledContactUs'), 0, 0, 'warning');
1475 // Show technical message
1476 $message = info_admin($langs->trans("InstallModuleFromWebHasBeenDisabledByFile
", $dolibarrdataroot.'/installmodules.lock'), 0, 0, 'warning');
1483 if ($allowfromweb < 1) {
1484 print $langs->trans("SomethingMakeInstallFromWebNotPossible
");
1486 //print $langs->trans("SomethingMakeInstallFromWebNotPossible2
");
1490 // $allowfromweb = -1 if installation or setup not correct, 0 if not allowed, 1 if allowed
1491 if ($allowfromweb >= 0) {
1492 if ($allowfromweb == 1) {
1493 //print $langs->trans("ThisIsProcessToFollow
").'<br>';
1497 print $langs->trans("ThisIsAlternativeProcessToFollow
").'<br>';
1498 print '<b>'.$langs->trans("StepNb
", 1).'</b>: ';
1499 print str_replace('{s1}', $fullurl, $langs->trans("FindPackageFromWebSite
", '{s1}')).'<br>';
1500 print '<b>'.$langs->trans("StepNb
", 2).'</b>: ';
1501 print str_replace('{s1}', $fullurl, $langs->trans("DownloadPackageFromWebSite
", '{s1}')).'<br>';
1502 print '<b>'.$langs->trans("StepNb
", 3).'</b>: ';
1505 if ($allowfromweb == 1) {
1506 print '<form enctype="multipart/form-data
" method="POST
" class="noborder
" action="'.$_SERVER["PHP_SELF"].'" name="forminstall
">';
1507 print '<input type="hidden
" name="token
" value="'.newToken().'">';
1508 print '<input type="hidden
" name="action
" value="install
">';
1509 print '<input type="hidden
" name="mode
" value="deploy
">';
1511 print $langs->trans("YouCanSubmitFile
").'<br><br><br>';
1513 print '<span class="opacitymedium
"><input class="paddingright
" type="checkbox
" name="checkforcompliance
" id="checkforcompliance
"'.(getDolGlobalString('DISABLE_CHECK_ON_MALWARE_MODULES') ? ' disabled="disabled"' : 'checked="checked
"').'>';
1514 print '<label for="checkforcompliance
">'.$form->textwithpicto($langs->trans("CheckIfModuleIsNotBlackListed
"), $langs->trans("CheckIfModuleIsNotBlackListedHelp
")).'</label>';
1515 print '</span><br><br>';
1517 $max = getDolGlobalString('MAIN_UPLOAD_DOC'); // In Kb
1518 $maxphp = @ini_get('upload_max_filesize'); // In unknown
1519 if (preg_match('/k$/i', $maxphp)) {
1520 $maxphp = preg_replace('/k$/i', '', $maxphp);
1523 if (preg_match('/m$/i', $maxphp)) {
1524 $maxphp = preg_replace('/m$/i', '', $maxphp);
1527 if (preg_match('/g$/i', $maxphp)) {
1528 $maxphp = preg_replace('/g$/i', '', $maxphp);
1529 $maxphp *= 1024 * 1024;
1531 if (preg_match('/t$/i', $maxphp)) {
1532 $maxphp = preg_replace('/t$/i', '', $maxphp);
1533 $maxphp *= 1024 * 1024 * 1024;
1535 $maxphp2 = @ini_get('post_max_size'); // In unknown
1536 if (preg_match('/k$/i', $maxphp2)) {
1537 $maxphp2 = preg_replace('/k$/i', '', $maxphp2);
1540 if (preg_match('/m$/i', $maxphp2)) {
1541 $maxphp2 = preg_replace('/m$/i', '', $maxphp2);
1544 if (preg_match('/g$/i', $maxphp2)) {
1545 $maxphp2 = preg_replace('/g$/i', '', $maxphp2);
1546 $maxphp2 *= 1024 * 1024;
1548 if (preg_match('/t$/i', $maxphp2)) {
1549 $maxphp2 = preg_replace('/t$/i', '', $maxphp2);
1550 $maxphp2 *= 1024 * 1024 * 1024;
1552 // Now $max and $maxphp and $maxphp2 are in Kb
1554 $maxphptoshow = $maxphptoshowparam = '';
1556 $maxmin = min($max, $maxphp);
1557 $maxphptoshow = $maxphp;
1558 $maxphptoshowparam = 'upload_max_filesize';
1561 $maxmin = min($max, $maxphp2);
1562 if ($maxphp2 < $maxphp) {
1563 $maxphptoshow = $maxphp2;
1564 $maxphptoshowparam = 'post_max_size';
1569 print '<script type="text/javascript
">
1570 $(document).ready(function() {
1571 jQuery("#fileinstall
").on("change
", function() {
1572 if(this.files[0].size > '.($maxmin * 1024).') {
1573 alert("'.dol_escape_js($langs->transnoentitiesnoconv("ErrorFileSizeTooLarge")).'");
1579 // MAX_FILE_SIZE doit précéder le champ input de type file
1580 print '<input type="hidden
" name="MAX_FILE_SIZE
" value="'.($maxmin * 1024).'">';
1583 print '<input class="flat minwidth400
" type="file
" name="fileinstall
" id="fileinstall
">';
1585 print '<input type="submit
" name="send
" value="'.dol_escape_htmltag($langs->trans("Upload")).'" class="button small
">';
1587 if (getDolGlobalString('MAIN_UPLOAD_DOC')) {
1589 $langs->load('other');
1591 print info_admin($langs->trans("ThisLimitIsDefinedInSetup
", $max, $maxphptoshow, $maxphptoshowparam), 1);
1594 print ' ('.$langs->trans("UploadDisabled
").')';
1602 print '<div class="center
"><div class="logo_setup
"></div></div>';
1604 print $langs->trans("UnpackPackageInModulesRoot
", $dirins).'<br>';
1605 print '<b>'.$langs->trans("StepNb
", 4).'</b>: ';
1606 print $langs->trans("SetupIsReadyForUse
", DOL_URL_ROOT.'/admin/modules.php?mainmenu=home', $langs->transnoentitiesnoconv("Home
").' - '.$langs->transnoentitiesnoconv("Setup").' - '.$langs->transnoentitiesnoconv("Modules
")).'<br>';
1610 print dol_get_fiche_end();
1613if ($mode == 'develop') {
1614 print dol_get_fiche_head($head, $mode, '', -1);
1621 print '<div class="div-
table-responsive-no-min
">';
1622 print '<table summary="list_of_modules
" class="noborder centpercent
">'."\n
";
1623 print '<tr class="liste_titre
">'."\n
";
1624 print '<td colspan="3
">'.$langs->trans("DevelopYourModuleDesc
").'</td>';
1627 print '<tr class="oddeven nohover
" height="100
">'."\n
";
1628 print '<td class="center hideonsmartphone
">';
1629 print '<div class="imgmaxheight50 logo_setup
"></div>';
1631 print '<td class="minwidth500imp smallonsmartphone
">'.$langs->trans("TryToUseTheModuleBuilder
", $langs->transnoentitiesnoconv("ModuleBuilder
")).'</td>';
1632 print '<td class="maxwidth300
">';
1633 if (isModEnabled('modulebuilder')) {
1634 print $langs->trans("SeeTopRightMenu
");
1636 print '<span class="opacitymedium
">'.$langs->trans("ModuleMustBeEnabledFirst
", $langs->transnoentitiesnoconv("ModuleBuilder
")).'</span>';
1641 print '<tr class="oddeven nohover
" height="100
">'."\n
";
1642 $url = 'https://partners.dolibarr.org';
1643 print '<td class="center hideonsmartphone
">';
1644 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>';
1646 print '<td class="minwidth500imp smallonsmartphone
">'.$langs->trans("DoliPartnersDesc
").'</td>';
1647 print '<td><a href="'.$url.'" target="_blank
" rel="noopener noreferrer external
">';
1648 print img_picto('', 'url', 'class="pictofixedwidth
"');
1649 print $url.'</a></td>';
1655 print dol_get_fiche_end();
if(! $sortfield) if(! $sortorder) $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).
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.
document_preview(file, type, title)
Function to show a document preview popup.
dol_delete_file($file, $disableglob=0, $nophperrors=0, $nohook=0, $object=null, $allowdotdot=false, $indexdatabase=1, $nolog=0)
Remove a file or several files with a mask.
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.
dol_now($mode='gmt')
Return date for now.
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.
dolBuildUrl($url, $params=[], $addtoken=false)
Return path of url.
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_sanitizePathName($str, $newstr='_', $unaccent=0, $allowdash=0)
Clean a string to use it as a path name.
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...
load_fiche_titre($title, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='', $morecssonpicto='widthpictotitle')
Load a title with picto.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
isModEnabled($module)
Is Dolibarr module enabled.
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...
multi select button
0 = Do not include form tag and submit button -1 = Do not include form tag but include submit button
treeview li table
No Email.
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.