1<?php
2/* Copyright (C) 2003-2007 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3 * Copyright (C) 2003      Xavier Dutoit        <doli@sydesy.com>
4 * Copyright (C) 2004-2020 Laurent Destailleur  <eldy@users.sourceforge.net>
5 * Copyright (C) 2005-2017 Regis Houssin      	<regis.houssin@inodbox.com>
6 * Copyright (C) 2006 	   Jean Heimburger    	<jean@tiaris.info>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 */
21
22/**
23 *	\file       	htdocs/core/class/conf.class.php
24 *	\ingroup		core
25 *  \brief      	File of class to manage storage of current setup
26 *  				Config is stored into file conf.php
27 */
28
29
30/**
31 *  Class to stock current configuration
32 */
33class Conf
34{
35	/**
36	 * @var Object 	Associative array with properties found in conf file
37	 */
38	public $file;
39
40	/**
41	 * @var Object 	Associative array with some properties ->type, ->db, ...
42	 */
43	public $db;
44
45	//! To store properties found into database
46	public $global;
47	//! To store browser info
48	public $browser;
49
50	//! To store if javascript/ajax is enabked
51	public $use_javascript_ajax;
52	//! To store if javascript/ajax is enabked
53	public $disable_compute;
54	//! Used to store current currency (ISO code like 'USD', 'EUR', ...)
55	public $currency;
56
57	//! Used to store current css (from theme)
58	public $theme; // Contains current theme ("eldy", "auguria", ...)
59	public $css; // Contains full path of css page ("/theme/eldy/style.css.php", ...)
60
61	//! Used to store current menu handler
62	public $standard_menu;
63	// List of activated modules
64	public $modules;
65	public $modules_parts;
66
67	// An array to store cache results ->cache['nameofcache']=...
68	public $cache;
69
70
71	/**
72	 * @var string[]
73	 */
74	public $logbuffer = array();
75
76	/**
77	 * @var LogHandlerInterface[]
78	 */
79	public $loghandlers = array();
80
81	//! To store properties of multi-company
82	public $multicompany;
83	//! Used to store running instance for multi-company (default 1)
84	public $entity = 1;
85	//! Used to store list of entities to use for each element
86	public $entities = array();
87
88	public $dol_hide_topmenu; // Set if we force param dol_hide_topmenu into login url
89	public $dol_hide_leftmenu; // Set if we force param dol_hide_leftmenu into login url
90	public $dol_optimize_smallscreen; // Set if we force param dol_optimize_smallscreen into login url or if browser is smartphone
91	public $dol_no_mouse_hover; // Set if we force param dol_no_mouse_hover into login url or if browser is smartphone
92	public $dol_use_jmobile; // Set if we force param dol_use_jmobile into login url. 0=default, 1=to say we use app from a webview app, 2=to say we use app from a webview app and keep ajax
93
94	public $liste_limit;
95
96	public $tzuserinputkey = 'tzserver';		// Use 'tzuserrel' to always store date in GMT and show date in time zone of user.
97
98
99	/**
100	 * Constructor
101	 */
102	public function __construct()
103	{
104		// Properly declare multi-modules objects.
105		$this->file = new stdClass();
106		$this->db = new stdClass();
107		//! Charset for HTML output and for storing data in memory
108		$this->file->character_set_client = 'UTF-8'; // UTF-8, ISO-8859-1
109
110		// Common objects that are not modules
111		$this->mycompany = new stdClass();
112		$this->admin = new stdClass();
113		$this->browser = new stdClass();
114		$this->medias = new stdClass();
115		$this->global = new stdClass();
116
117		$this->cache = array();
118		$this->modules = array();
119		$this->modules_parts = array(
120			'css' => array(),
121			'js' => array(),
122			'tabs' => array(),
123			'triggers' => array(),
124			'login' => array(),
125			'substitutions' => array(),
126			'menus' => array(),
127			'theme' => array(),
128			'sms' => array(),
129			'tpl' => array(),
130			'barcode' => array(),
131			'models' => array(),
132			'societe' => array(),
133			'hooks' => array(),
134			'dir' => array(),
135			'syslog' => array()
136		);
137
138		// First level object that are modules.
139		// TODO Remove this part.
140		$this->syslog = new stdClass();
141		$this->multicompany = new stdClass();
142		$this->expedition_bon = new stdClass();
143		$this->delivery_note = new stdClass();
144		$this->fournisseur = new stdClass();
145		$this->product			= new stdClass();
146		$this->service			= new stdClass();
147		$this->contrat			= new stdClass();
148		$this->actions			= new stdClass();
149		$this->agenda			= new stdClass();
150		$this->commande = new stdClass();
151		$this->propal = new stdClass();
152		$this->facture			= new stdClass();
153		$this->contrat			= new stdClass();
154		$this->user	= new stdClass();
155		$this->usergroup		= new stdClass();
156		$this->adherent			= new stdClass();
157		$this->bank = new stdClass();
158		$this->notification		= new stdClass();
159		$this->mailing = new stdClass();
160		$this->expensereport	= new stdClass();
161		$this->productbatch		= new stdClass();
162	}
163
164
165	/**
166	 *  Load setup values into conf object (read llx_const)
167	 *  Note that this->db->xxx, this->file->xxx have been already set when setValues is called.
168	 *
169	 *  @param      DoliDB      $db     Database handler
170	 *  @return     int                 < 0 if KO, >= 0 if OK
171	 */
172	public function setValues($db)
173	{
174		dol_syslog(get_class($this)."::setValues");
175
176		if (!is_null($db) && is_object($db)) {
177			// Define all global constants into $this->global->key=value
178			$sql = "SELECT ".$db->decrypt('name')." as name,";
179			$sql .= " ".$db->decrypt('value')." as value, entity";
180			$sql .= " FROM ".MAIN_DB_PREFIX."const";
181			$sql .= " WHERE entity IN (0,".$this->entity.")";
182			$sql .= " ORDER BY entity"; // This is to have entity 0 first, then entity 1 that overwrite.
183
184			$resql = $db->query($sql);
185			if ($resql) {
186				$i = 0;
187				$numr = $db->num_rows($resql);
188				while ($i < $numr) {
189					$objp = $db->fetch_object($resql);
190					$key = $objp->name;
191					$value = $objp->value;
192					if ($key) {
193						// Allow constants values to be overridden by environment variables
194						if (isset($_SERVER['DOLIBARR_'.$key])) {
195							$value = $_SERVER['DOLIBARR_'.$key];
196						} elseif (isset($_ENV['DOLIBARR_'.$key])) {
197							$value = $_ENV['DOLIBARR_'.$key];
198						}
199
200						//if (! defined("$key")) define("$key", $value);	// In some cases, the constant might be already forced (Example: SYSLOG_HANDLERS during install)
201						$this->global->$key = $value;
202
203						if ($value && strpos($key, 'MAIN_MODULE_') === 0) {
204							$reg = array();
205							// If this is constant for a new tab page activated by a module. It initializes modules_parts['tabs'].
206							if (preg_match('/^MAIN_MODULE_([0-9A-Z_]+)_TABS_/i', $key)) {
207								$partname = 'tabs';
208								$params = explode(':', $value, 2);
209								if (!is_array($this->modules_parts[$partname])) {
210									$this->modules_parts[$partname] = array();
211								}
212								$this->modules_parts[$partname][$params[0]][] = $value; // $value may be a string or an array
213							} elseif (preg_match('/^MAIN_MODULE_([0-9A-Z_]+)_([A-Z]+)$/i', $key, $reg)) {
214								// If this is constant for all generic part activated by a module. It initializes
215								// modules_parts['login'], modules_parts['menus'], modules_parts['substitutions'], modules_parts['triggers'], modules_parts['tpl'],
216								// modules_parts['models'], modules_parts['theme']
217								// modules_parts['sms'],
218								// modules_parts['css'], ...
219
220								$modulename = strtolower($reg[1]);
221								$partname = strtolower($reg[2]);
222								if (!isset($this->modules_parts[$partname]) || !is_array($this->modules_parts[$partname])) {
223									$this->modules_parts[$partname] = array();
224								}
225								$arrValue = json_decode($value, true);
226								if (is_array($arrValue) && !empty($arrValue)) {
227									$value = $arrValue;
228								} elseif (in_array($partname, array('login', 'menus', 'substitutions', 'triggers', 'tpl'))) {
229									$value = '/'.$modulename.'/core/'.$partname.'/';
230								} elseif (in_array($partname, array('models', 'theme'))) {
231									$value = '/'.$modulename.'/';
232								} elseif (in_array($partname, array('sms'))) {
233									$value = '/'.$modulename.'/';
234								} elseif ($value == 1) {
235									$value = '/'.$modulename.'/core/modules/'.$partname.'/'; // ex: partname = societe
236								}
237								$this->modules_parts[$partname] = array_merge($this->modules_parts[$partname], array($modulename => $value)); // $value may be a string or an array
238							} elseif (preg_match('/^MAIN_MODULE_([0-9A-Z_]+)$/i', $key, $reg)) {
239								// If this is a module constant (must be at end)
240								$modulename = strtolower($reg[1]);
241								if ($modulename == 'propale') {
242									$modulename = 'propal';
243								}
244								if ($modulename == 'supplierproposal') {
245									$modulename = 'supplier_proposal';
246								}
247								if (!isset($this->$modulename) || !is_object($this->$modulename)) {
248									$this->$modulename = new stdClass();
249								}
250								$this->$modulename->enabled = true;
251								$this->modules[] = $modulename; // Add this module in list of enabled modules
252							}
253						}
254					}
255					$i++;
256				}
257
258				$db->free($resql);
259			}
260
261			// Include other local consts.php files and fetch their values to the corresponding database constants.
262			if (!empty($this->global->LOCAL_CONSTS_FILES)) {
263				$filesList = explode(":", $this->global->LOCAL_CONSTS_FILES);
264				foreach ($filesList as $file) {
265					$file = dol_sanitizeFileName($file);
266					dol_include_once($file."/".$file."_consts.php"); // This file can run code like setting $this->global->XXX vars.
267				}
268			}
269
270			//var_dump($this->modules);
271			//var_dump($this->modules_parts['theme']);
272
273			// If you can't set timezone of your PHP, set this constant. Better is to set it to UTC.
274			// In future, this constant will be forced to 'UTC' so PHP server timezone will not have effect anymore.
275			//$this->global->MAIN_SERVER_TZ='Europe/Paris';
276			if (!empty($this->global->MAIN_SERVER_TZ) && $this->global->MAIN_SERVER_TZ != 'auto') {
277				try {
278					date_default_timezone_set($this->global->MAIN_SERVER_TZ);
279				} catch (Exception $e) {
280					dol_syslog("Error: Bad value for parameter MAIN_SERVER_TZ=".$this->global->MAIN_SERVER_TZ, LOG_ERR);
281				}
282			}
283
284			// Object $mc
285			if (!defined('NOREQUIREMC') && !empty($this->multicompany->enabled)) {
286				global $mc;
287				$ret = @dol_include_once('/multicompany/class/actions_multicompany.class.php');
288				if ($ret) {
289					$mc = new ActionsMulticompany($db);
290					$this->mc = $mc;
291				}
292			}
293
294			// Clean some variables
295			if (empty($this->global->MAIN_MENU_STANDARD)) {
296				$this->global->MAIN_MENU_STANDARD = "eldy_menu.php";
297			}
298			if (empty($this->global->MAIN_MENUFRONT_STANDARD)) {
299				$this->global->MAIN_MENUFRONT_STANDARD = "eldy_menu.php";
300			}
301			if (empty($this->global->MAIN_MENU_SMARTPHONE)) {
302				$this->global->MAIN_MENU_SMARTPHONE = "eldy_menu.php"; // Use eldy by default because smartphone does not work on all phones
303			}
304			if (empty($this->global->MAIN_MENUFRONT_SMARTPHONE)) {
305				$this->global->MAIN_MENUFRONT_SMARTPHONE = "eldy_menu.php"; // Use eldy by default because smartphone does not work on all phones
306			}
307			if (!isset($this->global->FACTURE_TVAOPTION)) {
308				$this->global->FACTURE_TVAOPTION = 1;
309			}
310
311			// Variable globales LDAP
312			if (empty($this->global->LDAP_FIELD_FULLNAME)) {
313				$this->global->LDAP_FIELD_FULLNAME = '';
314			}
315			if (!isset($this->global->LDAP_KEY_USERS)) {
316				$this->global->LDAP_KEY_USERS = $this->global->LDAP_FIELD_FULLNAME;
317			}
318			if (!isset($this->global->LDAP_KEY_GROUPS)) {
319				$this->global->LDAP_KEY_GROUPS = $this->global->LDAP_FIELD_FULLNAME;
320			}
321			if (!isset($this->global->LDAP_KEY_CONTACTS)) {
322				$this->global->LDAP_KEY_CONTACTS = $this->global->LDAP_FIELD_FULLNAME;
323			}
324			if (!isset($this->global->LDAP_KEY_MEMBERS)) {
325				$this->global->LDAP_KEY_MEMBERS = $this->global->LDAP_FIELD_FULLNAME;
326			}
327			if (!isset($this->global->LDAP_KEY_MEMBERS_TYPES)) {
328				$this->global->LDAP_KEY_MEMBERS_TYPES = $this->global->LDAP_FIELD_FULLNAME;
329			}
330
331			// Load translation object with current language
332			if (empty($this->global->MAIN_LANG_DEFAULT)) {
333				$this->global->MAIN_LANG_DEFAULT = "en_US";
334			}
335
336			$rootfordata = DOL_DATA_ROOT;
337			$rootforuser = DOL_DATA_ROOT;
338			// If multicompany module is enabled, we redefine the root of data
339			if (!empty($this->multicompany->enabled) && !empty($this->entity) && $this->entity > 1) {
340				$rootfordata .= '/'.$this->entity;
341			}
342			// Set standard temporary folder name or global override
343			$rootfortemp = empty($this->global->MAIN_TEMP_DIR) ? $rootfordata : $this->global->MAIN_TEMP_DIR;
344
345			// Define default dir_output and dir_temp for directories of modules
346			foreach ($this->modules as $module) {
347				//var_dump($module);
348				// For multicompany sharings
349				$this->$module->multidir_output = array($this->entity => $rootfordata."/".$module);
350				$this->$module->multidir_temp = array($this->entity => $rootfortemp."/".$module."/temp");
351				// For backward compatibility
352				$this->$module->dir_output = $rootfordata."/".$module;
353				$this->$module->dir_temp = $rootfortemp."/".$module."/temp";
354			}
355
356			// External modules storage
357			if (!empty($this->modules_parts['dir'])) {
358				foreach ($this->modules_parts['dir'] as $module => $dirs) {
359					if (!empty($this->$module->enabled)) {
360						foreach ($dirs as $type => $name) {  // $type is 'output' or 'temp'
361							$multidirname = 'multidir_'.$type;
362							$dirname = 'dir_'.$type;
363
364							if ($type != 'temp') {
365								// For multicompany sharings
366								$this->$module->$multidirname = array($this->entity => $rootfordata."/".$name);
367
368								// For backward compatibility
369								$this->$module->$dirname = $rootfordata."/".$name;
370							} else {
371								// For multicompany sharings
372								$this->$module->$multidirname = array($this->entity => $rootfortemp."/".$name."/temp");
373
374								// For backward compatibility
375								$this->$module->$dirname = $rootfortemp."/".$name."/temp";
376							}
377						}
378					}
379				}
380			}
381
382			// For mycompany storage
383			$this->mycompany->dir_output = $rootfordata."/mycompany";
384			$this->mycompany->dir_temp = $rootfortemp."/mycompany/temp";
385
386			// For admin storage
387			$this->admin->dir_output = $rootfordata.'/admin';
388			$this->admin->dir_temp = $rootfortemp.'/admin/temp';
389
390			// For user storage
391			$this->user->multidir_output = array($this->entity => $rootfordata."/users");
392			$this->user->multidir_temp = array($this->entity => $rootfortemp."/users/temp");
393			// For backward compatibility
394			$this->user->dir_output = $rootforuser."/users";
395			$this->user->dir_temp = $rootfortemp."/users/temp";
396
397			// For usergroup storage
398			$this->usergroup->dir_output = $rootforuser."/usergroups";
399			$this->usergroup->dir_temp = $rootfortemp."/usergroups/temp";
400
401			// For proposal storage
402			$this->propal->multidir_output = array($this->entity => $rootfordata."/propale");
403			$this->propal->multidir_temp = array($this->entity => $rootfortemp."/propale/temp");
404			// For backward compatibility
405			$this->propal->dir_output = $rootfordata."/propale";
406			$this->propal->dir_temp = $rootfortemp."/propale/temp";
407
408			// For medias storage
409			$this->medias->multidir_output = array($this->entity => $rootfordata."/medias");
410			$this->medias->multidir_temp = array($this->entity => $rootfortemp."/medias/temp");
411
412			// Exception: Some dir are not the name of module. So we keep exception here for backward compatibility.
413
414			// Sous module bons d'expedition
415			$this->expedition_bon->enabled = (!empty($this->global->MAIN_SUBMODULE_EXPEDITION) ? $this->global->MAIN_SUBMODULE_EXPEDITION : 0);
416			// Sub module delivery note  Sous module bons de livraison
417			$this->delivery_note->enabled = (!empty($this->global->MAIN_SUBMODULE_DELIVERY) ? $this->global->MAIN_SUBMODULE_DELIVERY : 0);
418
419			// Module fournisseur
420			if (!empty($this->fournisseur)) {
421				$this->fournisseur->commande = new stdClass();
422				$this->fournisseur->commande->multidir_output = array($this->entity => $rootfordata."/fournisseur/commande");
423				$this->fournisseur->commande->multidir_temp = array($this->entity => $rootfortemp."/fournisseur/commande/temp");
424				$this->fournisseur->commande->dir_output = $rootfordata."/fournisseur/commande"; // For backward compatibility
425				$this->fournisseur->commande->dir_temp = $rootfortemp."/fournisseur/commande/temp"; // For backward compatibility
426
427				$this->fournisseur->facture = new stdClass();
428				$this->fournisseur->facture->multidir_output = array($this->entity => $rootfordata."/fournisseur/facture");
429				$this->fournisseur->facture->multidir_temp = array($this->entity => $rootfortemp."/fournisseur/facture/temp");
430				$this->fournisseur->facture->dir_output = $rootfordata."/fournisseur/facture"; // For backward compatibility
431				$this->fournisseur->facture->dir_temp = $rootfortemp."/fournisseur/facture/temp"; // For backward compatibility
432
433				$this->supplierproposal = new stdClass();
434				$this->supplierproposal->multidir_output = array($this->entity => $rootfordata."/supplier_proposal");
435				$this->supplierproposal->multidir_temp = array($this->entity => $rootfortemp."/supplier_proposal/temp");
436				$this->supplierproposal->dir_output = $rootfordata."/supplier_proposal"; // For backward compatibility
437				$this->supplierproposal->dir_temp = $rootfortemp."/supplier_proposal/temp"; // For backward compatibility
438
439				$this->fournisseur->payment = new stdClass();
440				$this->fournisseur->payment->multidir_output = array($this->entity => $rootfordata."/fournisseur/payment");
441				$this->fournisseur->payment->multidir_temp = array($this->entity => $rootfortemp."/fournisseur/payment/temp");
442				$this->fournisseur->payment->dir_output = $rootfordata."/fournisseur/payment"; // For backward compatibility
443				$this->fournisseur->payment->dir_temp = $rootfortemp."/fournisseur/payment/temp"; // For backward compatibility
444
445				// To prepare split of module fournisseur into module 'fournisseur' + supplier_order + supplier_invoice
446				if (!empty($this->fournisseur->enabled) && empty($this->global->MAIN_USE_NEW_SUPPLIERMOD)) {  // By default, if module supplier is on, and we don't use yet the new modules, we set artificially the module properties
447					$this->supplier_order = new stdClass();
448					$this->supplier_order->enabled = 1;
449					$this->supplier_order->multidir_output = array($this->entity => $rootfordata."/fournisseur/commande");
450					$this->supplier_order->multidir_temp = array($this->entity => $rootfortemp."/fournisseur/commande/temp");
451					$this->supplier_order->dir_output = $rootfordata."/fournisseur/commande"; // For backward compatibility
452					$this->supplier_order->dir_temp = $rootfortemp."/fournisseur/commande/temp"; // For backward compatibility
453
454					$this->supplier_invoice = new stdClass();
455					$this->supplier_invoice->enabled = 1;
456					$this->supplier_invoice->multidir_output = array($this->entity => $rootfordata."/fournisseur/facture");
457					$this->supplier_invoice->multidir_temp = array($this->entity => $rootfortemp."/fournisseur/facture/temp");
458					$this->supplier_invoice->dir_output = $rootfordata."/fournisseur/facture"; // For backward compatibility
459					$this->supplier_invoice->dir_temp = $rootfortemp."/fournisseur/facture/temp"; // For backward compatibility
460				}
461			}
462
463			// Module product/service
464			$this->product->multidir_output 		= array($this->entity => $rootfordata."/produit");
465			$this->product->multidir_temp			= array($this->entity => $rootfortemp."/produit/temp");
466			$this->service->multidir_output			= array($this->entity => $rootfordata."/produit");
467			$this->service->multidir_temp			= array($this->entity => $rootfortemp."/produit/temp");
468			// For backward compatibility
469			$this->product->dir_output				= $rootfordata."/produit";
470			$this->product->dir_temp				= $rootfortemp."/produit/temp";
471			$this->service->dir_output				= $rootfordata."/produit";
472			$this->service->dir_temp				= $rootfortemp."/produit/temp";
473
474			// Module productbatch
475			$this->productbatch->multidir_output = array($this->entity => $rootfordata."/productlot");
476			$this->productbatch->multidir_temp = array($this->entity => $rootfortemp."/productlot/temp");
477
478			// Module contrat
479			$this->contrat->multidir_output = array($this->entity => $rootfordata."/contract");
480			$this->contrat->multidir_temp = array($this->entity => $rootfortemp."/contract/temp");
481			// For backward compatibility
482			$this->contrat->dir_output = $rootfordata."/contract";
483			$this->contrat->dir_temp = $rootfortemp."/contract/temp";
484
485			// Module bank
486			$this->bank->multidir_output = array($this->entity => $rootfordata."/bank");
487			$this->bank->multidir_temp = array($this->entity => $rootfortemp."/bank/temp");
488			// For backward compatibility
489			$this->bank->dir_output = $rootfordata."/bank";
490			$this->bank->dir_temp = $rootfortemp."/bank/temp";
491
492			// Set some default values
493			//$this->global->MAIN_LIST_FILTER_ON_DAY=1;		// On filter that show date, we must show input field for day before or after month
494			$this->global->MAIN_MAIL_USE_MULTI_PART = 1;
495
496			// societe
497			if (empty($this->global->SOCIETE_CODECLIENT_ADDON)) {
498				$this->global->SOCIETE_CODECLIENT_ADDON = "mod_codeclient_leopard";
499			}
500			if (empty($this->global->SOCIETE_CODECOMPTA_ADDON)) {
501				$this->global->SOCIETE_CODECOMPTA_ADDON = "mod_codecompta_panicum";
502			}
503
504			if (empty($this->global->CHEQUERECEIPTS_ADDON)) {
505				$this->global->CHEQUERECEIPTS_ADDON = 'mod_chequereceipt_mint';
506			}
507			if (empty($this->global->TICKET_ADDON)) {
508				$this->global->TICKET_ADDON = 'mod_ticket_simple';
509			}
510
511			// Security
512			if (empty($this->global->USER_PASSWORD_GENERATED)) {
513				$this->global->USER_PASSWORD_GENERATED = 'standard'; // Default password generator
514			}
515			if (empty($this->global->MAIN_UMASK)) {
516				$this->global->MAIN_UMASK = '0664'; // Default mask
517			}
518
519			// conf->use_javascript_ajax
520			$this->use_javascript_ajax = 1;
521			if (isset($this->global->MAIN_DISABLE_JAVASCRIPT)) {
522				$this->use_javascript_ajax = !$this->global->MAIN_DISABLE_JAVASCRIPT;
523			}
524			// If no javascript_ajax, Ajax features are disabled.
525			if (empty($this->use_javascript_ajax)) {
526				unset($this->global->PRODUIT_USE_SEARCH_TO_SELECT);
527				unset($this->global->COMPANY_USE_SEARCH_TO_SELECT);
528				unset($this->global->CONTACT_USE_SEARCH_TO_SELECT);
529				unset($this->global->PROJECT_USE_SEARCH_TO_SELECT);
530			}
531
532			if (!empty($this->productbatch->enabled)) {
533				$this->global->STOCK_CALCULATE_ON_BILL = 0;
534				$this->global->STOCK_CALCULATE_ON_VALIDATE_ORDER = 0;
535				$this->global->STOCK_CALCULATE_ON_SHIPMENT = 1;
536				$this->global->STOCK_CALCULATE_ON_SHIPMENT_CLOSE = 0;
537				$this->global->STOCK_CALCULATE_ON_SUPPLIER_BILL = 0;
538				$this->global->STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER = 0;
539				if (empty($this->reception->enabled)) {
540					$this->global->STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER = 1;
541				} else {
542					$this->global->STOCK_CALCULATE_ON_RECEPTION = 1;
543					$this->global->STOCK_CALCULATE_ON_RECEPTION_CLOSE = 0;
544				}
545			}
546
547			if (!isset($this->global->STOCK_SHOW_ALL_BATCH_BY_DEFAULT)) {
548				$this->global->STOCK_SHOW_ALL_BATCH_BY_DEFAULT = 1;
549			}
550
551			// conf->currency
552			if (empty($this->global->MAIN_MONNAIE)) {
553				$this->global->MAIN_MONNAIE = 'EUR';
554			}
555			$this->currency = $this->global->MAIN_MONNAIE;
556
557			if (empty($this->global->MAIN_BROWSER_NOTIFICATION_FREQUENCY)) {
558				$this->global->MAIN_BROWSER_NOTIFICATION_FREQUENCY = 30; // Less than 1 minutes to be sure
559			}
560
561			// conf->global->ACCOUNTING_MODE = Option des modules Comptabilites (simple ou expert). Defini le mode de calcul des etats comptables (CA,...)
562			if (empty($this->global->ACCOUNTING_MODE)) {
563				$this->global->ACCOUNTING_MODE = 'RECETTES-DEPENSES'; // By default. Can be 'RECETTES-DEPENSES' ou 'CREANCES-DETTES'
564			}
565
566			// By default, suppliers objects can be linked to all projects
567			if (!isset($this->global->PROJECT_CAN_ALWAYS_LINK_TO_ALL_SUPPLIERS)) {
568				$this->global->PROJECT_CAN_ALWAYS_LINK_TO_ALL_SUPPLIERS = 1;
569			}
570
571			// By default we enable feature to bill time spent
572			if (!isset($this->global->PROJECT_BILL_TIME_SPENT)) {
573				$this->global->PROJECT_BILL_TIME_SPENT = 1;
574			}
575
576			// MAIN_HTML_TITLE
577			if (!isset($this->global->MAIN_HTML_TITLE)) {
578				$this->global->MAIN_HTML_TITLE = 'noapp,thirdpartynameonly,contactnameonly,projectnameonly';
579			}
580
581			// conf->liste_limit = constante de taille maximale des listes
582			if (empty($this->global->MAIN_SIZE_LISTE_LIMIT)) {
583				$this->global->MAIN_SIZE_LISTE_LIMIT = 25;
584			}
585			$this->liste_limit = $this->global->MAIN_SIZE_LISTE_LIMIT;
586
587			// conf->product->limit_size = constante de taille maximale des select de produit
588			if (!isset($this->global->PRODUIT_LIMIT_SIZE)) {
589				$this->global->PRODUIT_LIMIT_SIZE = 1000;
590			}
591			$this->product->limit_size = $this->global->PRODUIT_LIMIT_SIZE;
592
593			// conf->theme et $this->css
594			if (empty($this->global->MAIN_THEME)) {
595				$this->global->MAIN_THEME = "eldy";
596			}
597			if (!empty($this->global->MAIN_FORCETHEME)) {
598				$this->global->MAIN_THEME = $this->global->MAIN_FORCETHEME;
599			}
600			$this->theme = $this->global->MAIN_THEME;
601			$this->css = "/theme/".$this->theme."/style.css.php";
602
603			// conf->email_from = email pour envoi par dolibarr des mails automatiques
604			$this->email_from = "robot@example.com";
605			if (!empty($this->global->MAIN_MAIL_EMAIL_FROM)) {
606				$this->email_from = $this->global->MAIN_MAIL_EMAIL_FROM;
607			}
608
609			// conf->notification->email_from = email pour envoi par Dolibarr des notifications
610			$this->notification->email_from = $this->email_from;
611			if (!empty($this->global->NOTIFICATION_EMAIL_FROM)) {
612				$this->notification->email_from = $this->global->NOTIFICATION_EMAIL_FROM;
613			}
614
615			// conf->mailing->email_from = email pour envoi par Dolibarr des mailings
616			$this->mailing->email_from = $this->email_from;
617			if (!empty($this->global->MAILING_EMAIL_FROM)) {
618				$this->mailing->email_from = $this->global->MAILING_EMAIL_FROM;
619			}
620			if (!isset($this->global->MAIN_EMAIL_ADD_TRACK_ID)) {
621				$this->global->MAIN_EMAIL_ADD_TRACK_ID = 1;
622			}
623
624			if (!isset($this->global->MAIN_HIDE_WARNING_TO_ENCOURAGE_SMTP_SETUP)) {
625				$this->global->MAIN_HIDE_WARNING_TO_ENCOURAGE_SMTP_SETUP = 1;
626			}
627
628			// Format for date (used by default when not found or not searched in lang)
629			$this->format_date_short = "%d/%m/%Y"; // Format of day with PHP/C tags (strftime functions)
630			$this->format_date_short_java = "dd/MM/yyyy"; // Format of day with Java tags
631			$this->format_hour_short = "%H:%M";
632			$this->format_hour_short_duration = "%H:%M";
633			$this->format_date_text_short = "%d %b %Y";
634			$this->format_date_text = "%d %B %Y";
635			$this->format_date_hour_short = "%d/%m/%Y %H:%M";
636			$this->format_date_hour_sec_short = "%d/%m/%Y %H:%M:%S";
637			$this->format_date_hour_text_short = "%d %b %Y %H:%M";
638			$this->format_date_hour_text = "%d %B %Y %H:%M";
639
640			// Duration of workday
641			if (!isset($this->global->MAIN_DURATION_OF_WORKDAY)) {
642				$this->global->MAIN_DURATION_OF_WORKDAY = 86400;
643			}
644
645			// Limites decimales si non definie (peuvent etre egale a 0)
646			if (!isset($this->global->MAIN_MAX_DECIMALS_UNIT)) {
647				$this->global->MAIN_MAX_DECIMALS_UNIT = 5;
648			}
649			if (!isset($this->global->MAIN_MAX_DECIMALS_TOT)) {
650				$this->global->MAIN_MAX_DECIMALS_TOT = 2;
651			}
652			if (!isset($this->global->MAIN_MAX_DECIMALS_SHOWN)) {
653				$this->global->MAIN_MAX_DECIMALS_SHOWN = 8;
654			}
655
656			// Default pdf option
657			if (!isset($this->global->MAIN_PDF_DASH_BETWEEN_LINES)) {
658				$this->global->MAIN_PDF_DASH_BETWEEN_LINES = 1; // use dash between lines
659			}
660			if (!isset($this->global->PDF_ALLOW_HTML_FOR_FREE_TEXT)) {
661				$this->global->PDF_ALLOW_HTML_FOR_FREE_TEXT = 1; // allow html content into free footer text
662			}
663
664			// Default max file size for upload
665			$this->maxfilesize = (empty($this->global->MAIN_UPLOAD_DOC) ? 0 : (int) $this->global->MAIN_UPLOAD_DOC * 1024);
666
667			// By default, we propagate contacts
668			if (!isset($this->global->MAIN_PROPAGATE_CONTACTS_FROM_ORIGIN)) {
669				$this->global->MAIN_PROPAGATE_CONTACTS_FROM_ORIGIN = '*'; // Can be also '*' or '^(BILLING|SHIPPING|CUSTOMER|.*)$' (regex not yet implemented)
670			}
671
672			// By default, we do not use the zip town table but the table of third parties
673			if (!isset($this->global->MAIN_USE_ZIPTOWN_DICTIONNARY)) {
674				$this->global->MAIN_USE_ZIPTOWN_DICTIONNARY = 0;
675			}
676
677			// By default, we open card if one found
678			if (!isset($this->global->MAIN_SEARCH_DIRECT_OPEN_IF_ONLY_ONE)) {
679				$this->global->MAIN_SEARCH_DIRECT_OPEN_IF_ONLY_ONE = 1;
680			}
681
682			// By default, we show state code in combo list
683			if (!isset($this->global->MAIN_SHOW_STATE_CODE)) {
684				$this->global->MAIN_SHOW_STATE_CODE = 1;
685			}
686
687			// Use a SCA ready workflow with Stripe module (STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION by default if nothing defined)
688			if (!isset($this->global->STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION) && empty($this->global->STRIPE_USE_NEW_CHECKOUT)) {
689				$this->global->STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION = 1;
690			}
691
692			// Define list of limited modules (value must be key found for "name" property of module, so for example 'supplierproposal' for Module "Supplier Proposal"
693			if (!isset($this->global->MAIN_MODULES_FOR_EXTERNAL)) {
694				$this->global->MAIN_MODULES_FOR_EXTERNAL = 'user,societe,propal,commande,facture,categorie,supplierproposal,fournisseur,contact,projet,contrat,ficheinter,expedition,agenda,resource,adherent,blockedlog'; // '' means 'all'. Note that contact is added here as it should be a module later.
695			}
696			if (!empty($this->modules_parts['moduleforexternal'])) {		// Module part to include an external module into the MAIN_MODULES_FOR_EXTERNAL list
697				foreach ($this->modules_parts['moduleforexternal'] as $key => $value) {
698					$this->global->MAIN_MODULES_FOR_EXTERNAL .= ",".$key;
699				}
700			}
701
702			// Enable select2
703			if (empty($this->global->MAIN_USE_JQUERY_MULTISELECT) || $this->global->MAIN_USE_JQUERY_MULTISELECT == '1') {
704				$this->global->MAIN_USE_JQUERY_MULTISELECT = 'select2';
705			}
706
707			// Timeouts
708			if (empty($this->global->MAIN_USE_CONNECT_TIMEOUT)) {
709				$this->global->MAIN_USE_CONNECT_TIMEOUT = 10;
710			}
711			if (empty($this->global->MAIN_USE_RESPONSE_TIMEOUT)) {
712				$this->global->MAIN_USE_RESPONSE_TIMEOUT = 30;
713			}
714
715			// Set default variable to calculate VAT as if option tax_mode was 0 (standard)
716			if (empty($this->global->TAX_MODE_SELL_PRODUCT)) {
717				$this->global->TAX_MODE_SELL_PRODUCT = 'invoice';
718			}
719			if (empty($this->global->TAX_MODE_BUY_PRODUCT)) {
720				$this->global->TAX_MODE_BUY_PRODUCT = 'invoice';
721			}
722			if (empty($this->global->TAX_MODE_SELL_SERVICE)) {
723				$this->global->TAX_MODE_SELL_SERVICE = 'payment';
724			}
725			if (empty($this->global->TAX_MODE_BUY_SERVICE)) {
726				$this->global->TAX_MODE_BUY_SERVICE = 'payment';
727			}
728
729			// Delay before warnings
730			// Avoid strict errors. TODO: Replace xxx->warning_delay with a property ->warning_delay_xxx
731			if (isset($this->agenda)) {
732				$this->adherent->subscription = new stdClass();
733				$this->adherent->subscription->warning_delay = (isset($this->global->MAIN_DELAY_MEMBERS) ? $this->global->MAIN_DELAY_MEMBERS : 0) * 86400;
734			}
735			if (isset($this->agenda)) {
736				$this->agenda->warning_delay = (isset($this->global->MAIN_DELAY_ACTIONS_TODO) ? $this->global->MAIN_DELAY_ACTIONS_TODO : 7) * 86400;
737			}
738			if (isset($this->projet)) {
739				$this->projet->warning_delay = (isset($this->global->MAIN_DELAY_PROJECT_TO_CLOSE) ? $this->global->MAIN_DELAY_PROJECT_TO_CLOSE : 7) * 86400;
740				$this->projet->task = new StdClass();
741				$this->projet->task->warning_delay = (isset($this->global->MAIN_DELAY_TASKS_TODO) ? $this->global->MAIN_DELAY_TASKS_TODO : 7) * 86400;
742			}
743
744			if (isset($this->commande)) {
745				$this->commande->client = new stdClass();
746				$this->commande->fournisseur = new stdClass();
747				$this->commande->client->warning_delay = (isset($this->global->MAIN_DELAY_ORDERS_TO_PROCESS) ? $this->global->MAIN_DELAY_ORDERS_TO_PROCESS : 2) * 86400;
748				$this->commande->fournisseur->warning_delay = (isset($this->global->MAIN_DELAY_SUPPLIER_ORDERS_TO_PROCESS) ? $this->global->MAIN_DELAY_SUPPLIER_ORDERS_TO_PROCESS : 7) * 86400;
749			}
750			if (isset($this->propal)) {
751				$this->propal->cloture = new stdClass();
752				$this->propal->facturation = new stdClass();
753				$this->propal->cloture->warning_delay = (isset($this->global->MAIN_DELAY_PROPALS_TO_CLOSE) ? $this->global->MAIN_DELAY_PROPALS_TO_CLOSE : 0) * 86400;
754				$this->propal->facturation->warning_delay = (isset($this->global->MAIN_DELAY_PROPALS_TO_BILL) ? $this->global->MAIN_DELAY_PROPALS_TO_BILL : 0) * 86400;
755			}
756			if (isset($this->facture)) {
757				$this->facture->client = new stdClass();
758				$this->facture->fournisseur = new stdClass();
759				$this->facture->client->warning_delay = (isset($this->global->MAIN_DELAY_CUSTOMER_BILLS_UNPAYED) ? $this->global->MAIN_DELAY_CUSTOMER_BILLS_UNPAYED : 0) * 86400;
760				$this->facture->fournisseur->warning_delay = (isset($this->global->MAIN_DELAY_SUPPLIER_BILLS_TO_PAY) ? $this->global->MAIN_DELAY_SUPPLIER_BILLS_TO_PAY : 0) * 86400;
761			}
762			if (isset($this->contrat)) {
763				$this->contrat->services = new stdClass();
764				$this->contrat->services->inactifs = new stdClass();
765				$this->contrat->services->expires = new stdClass();
766				$this->contrat->services->inactifs->warning_delay = (isset($this->global->MAIN_DELAY_NOT_ACTIVATED_SERVICES) ? $this->global->MAIN_DELAY_NOT_ACTIVATED_SERVICES : 0) * 86400;
767				$this->contrat->services->expires->warning_delay = (isset($this->global->MAIN_DELAY_RUNNING_SERVICES) ? $this->global->MAIN_DELAY_RUNNING_SERVICES : 0) * 86400;
768			}
769			if (isset($this->commande)) {
770				$this->bank->rappro					= new stdClass();
771				$this->bank->cheque					= new stdClass();
772				$this->bank->rappro->warning_delay = (isset($this->global->MAIN_DELAY_TRANSACTIONS_TO_CONCILIATE) ? $this->global->MAIN_DELAY_TRANSACTIONS_TO_CONCILIATE : 0) * 86400;
773				$this->bank->cheque->warning_delay = (isset($this->global->MAIN_DELAY_CHEQUES_TO_DEPOSIT) ? $this->global->MAIN_DELAY_CHEQUES_TO_DEPOSIT : 0) * 86400;
774			}
775			if (isset($this->expensereport)) {
776				$this->expensereport->approve = new stdClass();
777				$this->expensereport->approve->warning_delay = (isset($this->global->MAIN_DELAY_EXPENSEREPORTS) ? $this->global->MAIN_DELAY_EXPENSEREPORTS : 0) * 86400;
778				$this->expensereport->payment = new stdClass();
779				$this->expensereport->payment->warning_delay = (isset($this->global->MAIN_DELAY_EXPENSEREPORTS_TO_PAY) ? $this->global->MAIN_DELAY_EXPENSEREPORTS_TO_PAY : 0) * 86400;
780			}
781			if (isset($this->holiday)) {
782				$this->holiday->approve = new stdClass();
783				$this->holiday->approve->warning_delay = (isset($this->global->MAIN_DELAY_HOLIDAYS) ? $this->global->MAIN_DELAY_HOLIDAYS : 0) * 86400;
784			}
785
786			if (!empty($this->global->PRODUIT_MULTIPRICES) && empty($this->global->PRODUIT_MULTIPRICES_LIMIT)) {
787				$this->global->PRODUIT_MULTIPRICES_LIMIT = 5;
788			}
789
790			// For modules that want to disable top or left menu
791			if (!empty($this->global->MAIN_HIDE_TOP_MENU)) {
792				$this->dol_hide_topmenu = $this->global->MAIN_HIDE_TOP_MENU;
793			}
794			if (!empty($this->global->MAIN_HIDE_LEFT_MENU)) {
795				$this->dol_hide_leftmenu = $this->global->MAIN_HIDE_LEFT_MENU;
796			}
797
798			if (empty($this->global->MAIN_SIZE_SHORTLIST_LIMIT)) {
799				$this->global->MAIN_SIZE_SHORTLIST_LIMIT = 3;
800			}
801
802			if (!isset($this->global->THEME_HIDE_BORDER_ON_INPUT)) {
803				$this->global->THEME_HIDE_BORDER_ON_INPUT = 0;
804			}
805
806			// Save inconsistent option
807			if (empty($this->global->AGENDA_USE_EVENT_TYPE) && (!isset($this->global->AGENDA_DEFAULT_FILTER_TYPE) || $this->global->AGENDA_DEFAULT_FILTER_TYPE == 'AC_NON_AUTO')) {
808				$this->global->AGENDA_DEFAULT_FILTER_TYPE = '0'; // 'AC_NON_AUTO' does not exists when AGENDA_DEFAULT_FILTER_TYPE is not on.
809			}
810
811			if (!isset($this->global->MAIN_JS_GRAPH)) {
812				$this->global->MAIN_JS_GRAPH = 'chart'; // Use chart.js library
813			}
814
815			if (empty($this->global->MAIN_MODULE_DOLISTORE_API_SRV)) {
816				$this->global->MAIN_MODULE_DOLISTORE_API_SRV = 'https://www.dolistore.com';
817			}
818			if (empty($this->global->MAIN_MODULE_DOLISTORE_API_KEY)) {
819				$this->global->MAIN_MODULE_DOLISTORE_API_KEY = 'dolistorecatalogpublickey1234567';
820			}
821
822			// If we are in develop mode, we activate the option MAIN_SECURITY_CSRF_WITH_TOKEN to 1 if not already defined.
823			if (!isset($this->global->MAIN_SECURITY_CSRF_WITH_TOKEN) && $this->global->MAIN_FEATURES_LEVEL >= 2) {
824				$this->global->MAIN_SECURITY_CSRF_WITH_TOKEN = 1;
825			}
826
827			if (defined('MAIN_ANTIVIRUS_COMMAND')) {
828				$this->global->MAIN_ANTIVIRUS_COMMAND = constant('MAIN_ANTIVIRUS_COMMAND');
829			}
830			if (defined('MAIN_ANTIVIRUS_PARAM')) {
831				$this->global->MAIN_ANTIVIRUS_PARAM = constant('MAIN_ANTIVIRUS_PARAM');
832			}
833
834			if (!empty($this->global->MAIN_TZUSERINPUTKEY)) {
835				$this->tzuserinputkey = $this->global->MAIN_TZUSERINPUTKEY;	// 'tzserver' or 'tzuserrel'
836			}
837
838			if (!empty($this->global->PRODUIT_AUTOFILL_DESC)) {
839				$this->global->MAIN_NO_CONCAT_DESCRIPTION = 1;
840			} else {
841				unset($this->global->MAIN_NO_CONCAT_DESCRIPTION);
842			}
843
844			// product is new use
845			if (isset($this->product)) {
846				// For backward compatibility
847				$this->produit = $this->product;
848			}
849			// invoice is new use, facture is old use still initialised
850			if (isset($this->facture)) {
851				$this->invoice = $this->facture;
852			}
853			// order is new use, commande is old use still initialised
854			if (isset($this->commande)) {
855				$this->order = $this->commande;
856			}
857			// contract is new use, contrat is old use still initialised
858			if (isset($this->contrat)) {
859				$this->contract = $this->contrat;
860			}
861			// category is new use, categorie is old use still initialised
862			if (isset($this->categorie)) {
863				$this->category = $this->categorie;
864			}
865			// project is new use, projet is old use still initialised
866			if (isset($this->projet) && !isset($this->project)) {
867				$this->project = $this->projet;
868			}
869			// member is new use, adherent is old use still initialised
870			if (isset($this->adherent) && !isset($this->member)) {
871				$this->member = $this->adherent;
872			}
873
874			// Object $mc
875			if (!defined('NOREQUIREMC') && !empty($this->multicompany->enabled)) {
876				if (is_object($mc)) {
877					$mc->setValues($this);
878				}
879			}
880
881			if (!empty($this->syslog->enabled)) {
882				// We init log handlers
883				if (!empty($this->global->SYSLOG_HANDLERS)) {
884					$handlers = json_decode($this->global->SYSLOG_HANDLERS);
885				} else {
886					$handlers = array();
887				}
888				foreach ($handlers as $handler) {
889					$handler_file_found = '';
890					$dirsyslogs = array('/core/modules/syslog/');
891					if (!empty($this->modules_parts['syslog']) && is_array($this->modules_parts['syslog'])) {
892						$dirsyslogs = array_merge($dirsyslogs, $this->modules_parts['syslog']);
893					}
894					foreach ($dirsyslogs as $reldir) {
895						$dir = dol_buildpath($reldir, 0);
896						$newdir = dol_osencode($dir);
897						if (is_dir($newdir)) {
898							$file = $newdir.$handler.'.php';
899							if (file_exists($file)) {
900								$handler_file_found = $file;
901								break;
902							}
903						}
904					}
905
906					if (empty($handler_file_found)) {
907						throw new Exception('Missing log handler file '.$handler.'.php');
908					}
909
910					require_once $handler_file_found;
911					$loghandlerinstance = new $handler();
912					if (!$loghandlerinstance instanceof LogHandlerInterface) {
913						throw new Exception('Log handler does not extend LogHandlerInterface');
914					}
915
916					if (empty($this->loghandlers[$handler])) {
917						$this->loghandlers[$handler] = $loghandlerinstance;
918					}
919				}
920			}
921		}
922
923		// Overwrite database values from conf into the conf.php file.
924		if (!empty($this->file->mailing_limit_sendbyweb)) {
925			$this->global->MAILING_LIMIT_SENDBYWEB = $this->file->mailing_limit_sendbyweb;
926		}
927		if (empty($this->global->MAILING_LIMIT_SENDBYWEB)) {
928			$this->global->MAILING_LIMIT_SENDBYWEB = 25;
929		}
930		if (!empty($this->file->mailing_limit_sendbycli)) {
931			$this->global->MAILING_LIMIT_SENDBYCLI = $this->file->mailing_limit_sendbycli;
932		}
933
934		return 0;
935	}
936}
937