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