dolibarr  13.0.2
functions.lib.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2000-2007 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3  * Copyright (C) 2003 Jean-Louis Bergamo <jlb@j1b.org>
4  * Copyright (C) 2004-2018 Laurent Destailleur <eldy@users.sourceforge.net>
5  * Copyright (C) 2004 Sebastien Di Cintio <sdicintio@ressource-toi.org>
6  * Copyright (C) 2004 Benoit Mortier <benoit.mortier@opensides.be>
7  * Copyright (C) 2004 Christophe Combelles <ccomb@free.fr>
8  * Copyright (C) 2005-2019 Regis Houssin <regis.houssin@inodbox.com>
9  * Copyright (C) 2008 Raphael Bertrand (Resultic) <raphael.bertrand@resultic.fr>
10  * Copyright (C) 2010-2018 Juanjo Menent <jmenent@2byte.es>
11  * Copyright (C) 2013 Cédric Salvador <csalvador@gpcsolutions.fr>
12  * Copyright (C) 2013-2017 Alexandre Spangaro <aspangaro@open-dsi.fr>
13  * Copyright (C) 2014 Cédric GROSS <c.gross@kreiz-it.fr>
14  * Copyright (C) 2014-2015 Marcos García <marcosgdf@gmail.com>
15  * Copyright (C) 2015 Jean-François Ferry <jfefe@aternatik.fr>
16  * Copyright (C) 2018-2020 Frédéric France <frederic.france@netlogic.fr>
17  * Copyright (C) 2019 Thibault Foucart <support@ptibogxiv.net>
18  * Copyright (C) 2020 Open-Dsi <support@open-dsi.fr>
19  *
20  * This program is free software; you can redistribute it and/or modify
21  * it under the terms of the GNU General Public License as published by
22  * the Free Software Foundation; either version 3 of the License, or
23  * (at your option) any later version.
24  *
25  * This program is distributed in the hope that it will be useful,
26  * but WITHOUT ANY WARRANTY; without even the implied warranty of
27  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28  * GNU General Public License for more details.
29  *
30  * You should have received a copy of the GNU General Public License
31  * along with this program. If not, see <https://www.gnu.org/licenses/>.
32  * or see https://www.gnu.org/
33  */
34 
41 include_once DOL_DOCUMENT_ROOT.'/core/lib/json.lib.php';
42 
43 
55 function getDoliDBInstance($type, $host, $user, $pass, $name, $port)
56 {
57  require_once DOL_DOCUMENT_ROOT."/core/db/".$type.'.class.php';
58 
59  $class = 'DoliDB'.ucfirst($type);
60  $dolidb = new $class($type, $host, $user, $pass, $name, $port);
61  return $dolidb;
62 }
63 
81 function getEntity($element, $shared = 1, $currentobject = null)
82 {
83  global $conf, $mc;
84 
85  // fix different element names (France to English)
86  switch ($element) {
87  case 'contrat': $element = 'contract'; break; // "/contrat/class/contrat.class.php"
88  case 'order_supplier': $element = 'supplier_order'; break; // "/fourn/class/fournisseur.commande.class.php"
89  }
90 
91  if (is_object($mc))
92  {
93  return $mc->getEntity($element, $shared, $currentobject);
94  } else {
95  $out = '';
96  $addzero = array('user', 'usergroup', 'c_email_templates', 'email_template', 'default_values');
97  if (in_array($element, $addzero)) $out .= '0,';
98  $out .= ((int) $conf->entity);
99  return $out;
100  }
101 }
102 
109 function setEntity($currentobject)
110 {
111  global $conf, $mc;
112 
113  if (is_object($mc) && method_exists($mc, 'setEntity'))
114  {
115  return $mc->setEntity($currentobject);
116  } else {
117  return ((is_object($currentobject) && $currentobject->id > 0 && $currentobject->entity > 0) ? $currentobject->entity : $conf->entity);
118  }
119 }
120 
127 function isASecretKey($keyname)
128 {
129  return preg_match('/(_pass|password|_pw|_key|securekey|serverkey|secret\d?|p12key|exportkey|_PW_[a-z]+|token)$/i', $keyname);
130 }
131 
148 function getBrowserInfo($user_agent)
149 {
150  include_once DOL_DOCUMENT_ROOT.'/includes/mobiledetect/mobiledetectlib/Mobile_Detect.php';
151 
152  $name = 'unknown';
153  $version = '';
154  $os = 'unknown';
155  $phone = '';
156 
157  $user_agent = substr($user_agent, 0, 512); // Avoid to process too large user agent
158 
159  $detectmobile = new Mobile_Detect(null, $user_agent);
160  $tablet = $detectmobile->isTablet();
161 
162  if ($detectmobile->isMobile()) {
163  $phone = 'unknown';
164 
165  // If phone/smartphone, we set phone os name.
166  if ($detectmobile->is('AndroidOS')) {
167  $os = $phone = 'android';
168  } elseif ($detectmobile->is('BlackBerryOS')) {
169  $os = $phone = 'blackberry';
170  } elseif ($detectmobile->is('iOS')) {
171  $os = 'ios';
172  $phone = 'iphone';
173  } elseif ($detectmobile->is('PalmOS')) {
174  $os = $phone = 'palm';
175  } elseif ($detectmobile->is('SymbianOS')) {
176  $os = 'symbian';
177  } elseif ($detectmobile->is('webOS')) {
178  $os = 'webos';
179  } elseif ($detectmobile->is('MaemoOS')) {
180  $os = 'maemo';
181  } elseif ($detectmobile->is('WindowsMobileOS') || $detectmobile->is('WindowsPhoneOS')) {
182  $os = 'windows';
183  }
184  }
185 
186  // OS
187  if (preg_match('/linux/i', $user_agent)) { $os = 'linux'; } elseif (preg_match('/macintosh/i', $user_agent)) { $os = 'macintosh'; } elseif (preg_match('/windows/i', $user_agent)) { $os = 'windows'; }
188 
189  // Name
190  $reg = array();
191  if (preg_match('/firefox(\/|\s)([\d\.]*)/i', $user_agent, $reg)) { $name = 'firefox'; $version = $reg[2]; } elseif (preg_match('/edge(\/|\s)([\d\.]*)/i', $user_agent, $reg)) { $name = 'edge'; $version = $reg[2]; } elseif (preg_match('/chrome(\/|\s)([\d\.]+)/i', $user_agent, $reg)) { $name = 'chrome'; $version = $reg[2]; } // we can have 'chrome (Mozilla...) chrome x.y' in one string
192  elseif (preg_match('/chrome/i', $user_agent, $reg)) { $name = 'chrome'; } elseif (preg_match('/iceweasel/i', $user_agent)) { $name = 'iceweasel'; } elseif (preg_match('/epiphany/i', $user_agent)) { $name = 'epiphany'; } elseif (preg_match('/safari(\/|\s)([\d\.]*)/i', $user_agent, $reg)) { $name = 'safari'; $version = $reg[2]; } // Safari is often present in string for mobile but its not.
193  elseif (preg_match('/opera(\/|\s)([\d\.]*)/i', $user_agent, $reg)) { $name = 'opera'; $version = $reg[2]; } elseif (preg_match('/(MSIE\s([0-9]+\.[0-9]))|.*(Trident\/[0-9]+.[0-9];.*rv:([0-9]+\.[0-9]+))/i', $user_agent, $reg)) { $name = 'ie'; $version = end($reg); } // MS products at end
194  elseif (preg_match('/(Windows NT\s([0-9]+\.[0-9])).*(Trident\/[0-9]+.[0-9];.*rv:([0-9]+\.[0-9]+))/i', $user_agent, $reg)) { $name = 'ie'; $version = end($reg); } // MS products at end
195  elseif (preg_match('/l(i|y)n(x|ks)(\(|\/|\s)*([\d\.]+)/i', $user_agent, $reg)) { $name = 'lynxlinks'; $version = $reg[4]; }
196 
197  if ($tablet) {
198  $layout = 'tablet';
199  } elseif ($phone) {
200  $layout = 'phone';
201  } else {
202  $layout = 'classic';
203  }
204 
205  return array(
206  'browsername' => $name,
207  'browserversion' => $version,
208  'browseros' => $os,
209  'layout' => $layout,
210  'phone' => $phone,
211  'tablet' => $tablet
212  );
213 }
214 
220 function dol_shutdown()
221 {
222  global $conf, $user, $langs, $db;
223  $disconnectdone = false; $depth = 0;
224  if (is_object($db) && !empty($db->connected)) { $depth = $db->transaction_opened; $disconnectdone = $db->close(); }
225  dol_syslog("--- End access to ".$_SERVER["PHP_SELF"].(($disconnectdone && $depth) ? ' (Warn: db disconnection forced, transaction depth was '.$depth.')' : ''), (($disconnectdone && $depth) ?LOG_WARNING:LOG_INFO));
226 }
227 
234 function GETPOSTISSET($paramname)
235 {
236  $isset = false;
237 
238  $relativepathstring = $_SERVER["PHP_SELF"];
239  // Clean $relativepathstring
240  if (constant('DOL_URL_ROOT')) $relativepathstring = preg_replace('/^'.preg_quote(constant('DOL_URL_ROOT'), '/').'/', '', $relativepathstring);
241  $relativepathstring = preg_replace('/^\//', '', $relativepathstring);
242  $relativepathstring = preg_replace('/^custom\//', '', $relativepathstring);
243  //var_dump($relativepathstring);
244  //var_dump($user->default_values);
245 
246  // Code for search criteria persistence.
247  // Retrieve values if restore_lastsearch_values
248  if (!empty($_GET['restore_lastsearch_values'])) // Use $_GET here and not GETPOST
249  {
250  if (!empty($_SESSION['lastsearch_values_'.$relativepathstring])) // If there is saved values
251  {
252  $tmp = json_decode($_SESSION['lastsearch_values_'.$relativepathstring], true);
253  if (is_array($tmp))
254  {
255  foreach ($tmp as $key => $val)
256  {
257  if ($key == $paramname) // We are on the requested parameter
258  {
259  $isset = true;
260  break;
261  }
262  }
263  }
264  }
265  // If there is saved contextpage, page or limit
266  if ($paramname == 'contextpage' && !empty($_SESSION['lastsearch_contextpage_'.$relativepathstring]))
267  {
268  $isset = true;
269  } elseif ($paramname == 'page' && !empty($_SESSION['lastsearch_page_'.$relativepathstring]))
270  {
271  $isset = true;
272  } elseif ($paramname == 'limit' && !empty($_SESSION['lastsearch_limit_'.$relativepathstring]))
273  {
274  $isset = true;
275  }
276  } else {
277  $isset = (isset($_POST[$paramname]) || isset($_GET[$paramname])); // We must keep $_POST and $_GET here
278  }
279 
280  return $isset;
281 }
282 
309 function GETPOST($paramname, $check = 'alphanohtml', $method = 0, $filter = null, $options = null, $noreplace = 0)
310 {
311  global $mysoc, $user, $conf;
312 
313  if (empty($paramname)) return 'BadFirstParameterForGETPOST';
314  if (empty($check))
315  {
316  dol_syslog("Deprecated use of GETPOST, called with 1st param = ".$paramname." and 2nd param is '', when calling page ".$_SERVER["PHP_SELF"], LOG_WARNING);
317  // Enable this line to know who call the GETPOST with '' $check parameter.
318  //var_dump(debug_backtrace()[0]);
319  }
320 
321  if (empty($method)) $out = isset($_GET[$paramname]) ? $_GET[$paramname] : (isset($_POST[$paramname]) ? $_POST[$paramname] : '');
322  elseif ($method == 1) $out = isset($_GET[$paramname]) ? $_GET[$paramname] : '';
323  elseif ($method == 2) $out = isset($_POST[$paramname]) ? $_POST[$paramname] : '';
324  elseif ($method == 3) $out = isset($_POST[$paramname]) ? $_POST[$paramname] : (isset($_GET[$paramname]) ? $_GET[$paramname] : '');
325  else return 'BadThirdParameterForGETPOST';
326 
327  if (empty($method) || $method == 3 || $method == 4)
328  {
329  $relativepathstring = $_SERVER["PHP_SELF"];
330  // Clean $relativepathstring
331  if (constant('DOL_URL_ROOT')) $relativepathstring = preg_replace('/^'.preg_quote(constant('DOL_URL_ROOT'), '/').'/', '', $relativepathstring);
332  $relativepathstring = preg_replace('/^\//', '', $relativepathstring);
333  $relativepathstring = preg_replace('/^custom\//', '', $relativepathstring);
334  //var_dump($relativepathstring);
335  //var_dump($user->default_values);
336 
337  // Code for search criteria persistence.
338  // Retrieve values if restore_lastsearch_values
339  if (!empty($_GET['restore_lastsearch_values'])) // Use $_GET here and not GETPOST
340  {
341  if (!empty($_SESSION['lastsearch_values_'.$relativepathstring])) // If there is saved values
342  {
343  $tmp = json_decode($_SESSION['lastsearch_values_'.$relativepathstring], true);
344  if (is_array($tmp))
345  {
346  foreach ($tmp as $key => $val)
347  {
348  if ($key == $paramname) // We are on the requested parameter
349  {
350  $out = $val;
351  break;
352  }
353  }
354  }
355  }
356  // If there is saved contextpage, page or limit
357  if ($paramname == 'contextpage' && !empty($_SESSION['lastsearch_contextpage_'.$relativepathstring]))
358  {
359  $out = $_SESSION['lastsearch_contextpage_'.$relativepathstring];
360  } elseif ($paramname == 'page' && !empty($_SESSION['lastsearch_page_'.$relativepathstring]))
361  {
362  $out = $_SESSION['lastsearch_page_'.$relativepathstring];
363  } elseif ($paramname == 'limit' && !empty($_SESSION['lastsearch_limit_'.$relativepathstring]))
364  {
365  $out = $_SESSION['lastsearch_limit_'.$relativepathstring];
366  }
367  } // Else, retrieve default values if we are not doing a sort
368  elseif (!isset($_GET['sortfield'])) // If we did a click on a field to sort, we do no apply default values. Same if option MAIN_ENABLE_DEFAULT_VALUES is not set
369  {
370  if (!empty($_GET['action']) && $_GET['action'] == 'create' && !isset($_GET[$paramname]) && !isset($_POST[$paramname]))
371  {
372  // Search default value from $object->field
373  global $object;
374  if (is_object($object) && isset($object->fields[$paramname]['default']))
375  {
376  $out = $object->fields[$paramname]['default'];
377  }
378  }
379  if (!empty($conf->global->MAIN_ENABLE_DEFAULT_VALUES))
380  {
381  if (!empty($_GET['action']) && (preg_match('/^create/', $_GET['action']) || preg_match('/^presend/', $_GET['action'])) && !isset($_GET[$paramname]) && !isset($_POST[$paramname]))
382  {
383  // Now search in setup to overwrite default values
384  if (!empty($user->default_values)) // $user->default_values defined from menu 'Setup - Default values'
385  {
386  if (isset($user->default_values[$relativepathstring]['createform']))
387  {
388  foreach ($user->default_values[$relativepathstring]['createform'] as $defkey => $defval)
389  {
390  $qualified = 0;
391  if ($defkey != '_noquery_')
392  {
393  $tmpqueryarraytohave = explode('&', $defkey);
394  $tmpqueryarraywehave = explode('&', dol_string_nohtmltag($_SERVER['QUERY_STRING']));
395  $foundintru = 0;
396  foreach ($tmpqueryarraytohave as $tmpquerytohave)
397  {
398  if (!in_array($tmpquerytohave, $tmpqueryarraywehave)) $foundintru = 1;
399  }
400  if (!$foundintru) $qualified = 1;
401  //var_dump($defkey.'-'.$qualified);
402  } else $qualified = 1;
403 
404  if ($qualified)
405  {
406  if (isset($user->default_values[$relativepathstring]['createform'][$defkey][$paramname]))
407  {
408  $out = $user->default_values[$relativepathstring]['createform'][$defkey][$paramname];
409  break;
410  }
411  }
412  }
413  }
414  }
415  } // Management of default search_filters and sort order
416  elseif (!empty($paramname) && !isset($_GET[$paramname]) && !isset($_POST[$paramname]))
417  {
418  if (!empty($user->default_values)) // $user->default_values defined from menu 'Setup - Default values'
419  {
420  //var_dump($user->default_values[$relativepathstring]);
421  if ($paramname == 'sortfield' || $paramname == 'sortorder') // Sorted on which fields ? ASC or DESC ?
422  {
423  if (isset($user->default_values[$relativepathstring]['sortorder'])) // Even if paramname is sortfield, data are stored into ['sortorder...']
424  {
425  foreach ($user->default_values[$relativepathstring]['sortorder'] as $defkey => $defval)
426  {
427  $qualified = 0;
428  if ($defkey != '_noquery_')
429  {
430  $tmpqueryarraytohave = explode('&', $defkey);
431  $tmpqueryarraywehave = explode('&', dol_string_nohtmltag($_SERVER['QUERY_STRING']));
432  $foundintru = 0;
433  foreach ($tmpqueryarraytohave as $tmpquerytohave)
434  {
435  if (!in_array($tmpquerytohave, $tmpqueryarraywehave)) $foundintru = 1;
436  }
437  if (!$foundintru) $qualified = 1;
438  //var_dump($defkey.'-'.$qualified);
439  } else $qualified = 1;
440 
441  if ($qualified)
442  {
443  $forbidden_chars_to_replace = array(" ", "'", "/", "\\", ":", "*", "?", "\"", "<", ">", "|", "[", "]", ";", "="); // we accept _, -, . and ,
444  foreach ($user->default_values[$relativepathstring]['sortorder'][$defkey] as $key => $val)
445  {
446  if ($out) $out .= ', ';
447  if ($paramname == 'sortfield')
448  {
449  $out .= dol_string_nospecial($key, '', $forbidden_chars_to_replace);
450  }
451  if ($paramname == 'sortorder')
452  {
453  $out .= dol_string_nospecial($val, '', $forbidden_chars_to_replace);
454  }
455  }
456  //break; // No break for sortfield and sortorder so we can cumulate fields (is it realy usefull ?)
457  }
458  }
459  }
460  } elseif (isset($user->default_values[$relativepathstring]['filters']))
461  {
462  foreach ($user->default_values[$relativepathstring]['filters'] as $defkey => $defval) // $defkey is a querystring like 'a=b&c=d', $defval is key of user
463  {
464  $qualified = 0;
465  if ($defkey != '_noquery_')
466  {
467  $tmpqueryarraytohave = explode('&', $defkey);
468  $tmpqueryarraywehave = explode('&', dol_string_nohtmltag($_SERVER['QUERY_STRING']));
469  $foundintru = 0;
470  foreach ($tmpqueryarraytohave as $tmpquerytohave)
471  {
472  if (!in_array($tmpquerytohave, $tmpqueryarraywehave)) $foundintru = 1;
473  }
474  if (!$foundintru) $qualified = 1;
475  //var_dump($defkey.'-'.$qualified);
476  } else $qualified = 1;
477 
478  if ($qualified)
479  {
480  // We must keep $_POST and $_GET here
481  if (isset($_POST['sall']) || isset($_POST['search_all']) || isset($_GET['sall']) || isset($_GET['search_all']))
482  {
483  // We made a search from quick search menu, do we still use default filter ?
484  if (empty($conf->global->MAIN_DISABLE_DEFAULT_FILTER_FOR_QUICK_SEARCH))
485  {
486  $forbidden_chars_to_replace = array(" ", "'", "/", "\\", ":", "*", "?", "\"", "<", ">", "|", "[", "]", ";", "="); // we accept _, -, . and ,
487  $out = dol_string_nospecial($user->default_values[$relativepathstring]['filters'][$defkey][$paramname], '', $forbidden_chars_to_replace);
488  }
489  } else {
490  $forbidden_chars_to_replace = array(" ", "'", "/", "\\", ":", "*", "?", "\"", "<", ">", "|", "[", "]", ";", "="); // we accept _, -, . and ,
491  $out = dol_string_nospecial($user->default_values[$relativepathstring]['filters'][$defkey][$paramname], '', $forbidden_chars_to_replace);
492  }
493  break;
494  }
495  }
496  }
497  }
498  }
499  }
500  }
501  }
502 
503  // Substitution variables for GETPOST (used to get final url with variable parameters or final default value with variable parameters)
504  // Example of variables: __DAY__, __MONTH__, __YEAR__, __MYCOMPANY_COUNTRY_ID__, __USER_ID__, ...
505  // We do this only if var is a GET. If it is a POST, may be we want to post the text with vars as the setup text.
506  if (!is_array($out) && empty($_POST[$paramname]) && empty($noreplace))
507  {
508  $reg = array();
509  $maxloop = 20; $loopnb = 0; // Protection against infinite loop
510  while (preg_match('/__([A-Z0-9]+_?[A-Z0-9]+)__/i', $out, $reg) && ($loopnb < $maxloop)) // Detect '__ABCDEF__' as key 'ABCDEF' and '__ABC_DEF__' as key 'ABC_DEF'. Detection is also correct when 2 vars are side by side.
511  {
512  $loopnb++; $newout = '';
513 
514  if ($reg[1] == 'DAY') {
515  $tmp = dol_getdate(dol_now(), true);
516  $newout = $tmp['mday'];
517  } elseif ($reg[1] == 'MONTH') {
518  $tmp = dol_getdate(dol_now(), true);
519  $newout = $tmp['mon'];
520  } elseif ($reg[1] == 'YEAR') {
521  $tmp = dol_getdate(dol_now(), true);
522  $newout = $tmp['year'];
523  } elseif ($reg[1] == 'PREVIOUS_DAY') {
524  $tmp = dol_getdate(dol_now(), true);
525  $tmp2 = dol_get_prev_day($tmp['mday'], $tmp['mon'], $tmp['year']);
526  $newout = $tmp2['day'];
527  } elseif ($reg[1] == 'PREVIOUS_MONTH') {
528  $tmp = dol_getdate(dol_now(), true);
529  $tmp2 = dol_get_prev_month($tmp['mon'], $tmp['year']);
530  $newout = $tmp2['month'];
531  } elseif ($reg[1] == 'PREVIOUS_YEAR') {
532  $tmp = dol_getdate(dol_now(), true);
533  $newout = ($tmp['year'] - 1);
534  } elseif ($reg[1] == 'NEXT_DAY') {
535  $tmp = dol_getdate(dol_now(), true);
536  $tmp2 = dol_get_next_day($tmp['mday'], $tmp['mon'], $tmp['year']);
537  $newout = $tmp2['day'];
538  } elseif ($reg[1] == 'NEXT_MONTH') {
539  $tmp = dol_getdate(dol_now(), true);
540  $tmp2 = dol_get_next_month($tmp['mon'], $tmp['year']);
541  $newout = $tmp2['month'];
542  } elseif ($reg[1] == 'NEXT_YEAR') {
543  $tmp = dol_getdate(dol_now(), true);
544  $newout = ($tmp['year'] + 1);
545  } elseif ($reg[1] == 'MYCOMPANY_COUNTRY_ID' || $reg[1] == 'MYCOUNTRY_ID' || $reg[1] == 'MYCOUNTRYID') {
546  $newout = $mysoc->country_id;
547  } elseif ($reg[1] == 'USER_ID' || $reg[1] == 'USERID') {
548  $newout = $user->id;
549  } elseif ($reg[1] == 'USER_SUPERVISOR_ID' || $reg[1] == 'SUPERVISOR_ID' || $reg[1] == 'SUPERVISORID') {
550  $newout = $user->fk_user;
551  } elseif ($reg[1] == 'ENTITY_ID' || $reg[1] == 'ENTITYID') {
552  $newout = $conf->entity;
553  } else {
554  $newout = ''; // Key not found, we replace with empty string
555  }
556  //var_dump('__'.$reg[1].'__ -> '.$newout);
557  $out = preg_replace('/__'.preg_quote($reg[1], '/').'__/', $newout, $out);
558  }
559  }
560 
561  // Check rule
562  if (preg_match('/^array/', $check)) { // If 'array' or 'array:restricthtml' or 'array:aZ09'
563  if (!is_array($out) || empty($out)) {
564  $out = array();
565  } else {
566  $tmparray = explode(':', $check);
567  if (!empty($tmparray[1])) {
568  $tmpcheck = $tmparray[1];
569  } else {
570  $tmpcheck = 'alphanohtml';
571  }
572  foreach ($out as $outkey => $outval) {
573  $out[$outkey] = checkVal($outval, $tmpcheck, $filter, $options);
574  }
575  }
576  }
577  else {
578  $out = checkVal($out, $check, $filter, $options);
579  }
580 
581  // Sanitizing for special parameters. There is no reason to allow the backtopage parameter to contains an external URL.
582  if ($paramname == 'backtopage') {
583  $out = str_replace('\\', '/', $out);
584  $out = preg_replace(array('/^\/\/+/', '/^[a-z]*:/i'), '', $out);
585  }
586 
587  // Code for search criteria persistence.
588  // Save data into session if key start with 'search_' or is 'smonth', 'syear', 'month', 'year'
589  if (empty($method) || $method == 3 || $method == 4)
590  {
591  if (preg_match('/^search_/', $paramname) || in_array($paramname, array('sortorder', 'sortfield')))
592  {
593  //var_dump($paramname.' - '.$out.' '.$user->default_values[$relativepathstring]['filters'][$paramname]);
594 
595  // We save search key only if $out not empty that means:
596  // - posted value not empty, or
597  // - if posted value is empty and a default value exists that is not empty (it means we did a filter to an empty value when default was not).
598 
599  if ($out != '') // $out = '0' or 'abc', it is a search criteria to keep
600  {
601  $user->lastsearch_values_tmp[$relativepathstring][$paramname] = $out;
602  }
603  }
604  }
605 
606  return $out;
607 }
608 
621 function GETPOSTINT($paramname, $method = 0, $filter = null, $options = null, $noreplace = 0)
622 {
623  return (int) GETPOST($paramname, 'int', $method, $filter, $options, $noreplace);
624 }
625 
635 function checkVal($out = '', $check = 'alphanohtml', $filter = null, $options = null)
636 {
637  // Check is done after replacement
638  switch ($check)
639  {
640  case 'none':
641  break;
642  case 'int': // Check param is a numeric value (integer but also float or hexadecimal)
643  if (!is_numeric($out)) { $out = ''; }
644  break;
645  case 'intcomma':
646  if (preg_match('/[^0-9,-]+/i', $out)) $out = '';
647  break;
648  case 'san_alpha':
649  $out = filter_var($out, FILTER_SANITIZE_STRING);
650  break;
651  case 'email':
652  $out = filter_var($out, FILTER_SANITIZE_EMAIL);
653  break;
654  case 'aZ':
655  if (!is_array($out))
656  {
657  $out = trim($out);
658  if (preg_match('/[^a-z]+/i', $out)) $out = '';
659  }
660  break;
661  case 'aZ09':
662  if (!is_array($out))
663  {
664  $out = trim($out);
665  if (preg_match('/[^a-z0-9_\-\.]+/i', $out)) $out = '';
666  }
667  break;
668  case 'aZ09comma': // great to sanitize sortfield or sortorder params that can be t.abc,t.def_gh
669  if (!is_array($out))
670  {
671  $out = trim($out);
672  if (preg_match('/[^a-z0-9_\-\.,]+/i', $out)) $out = '';
673  }
674  break;
675  case 'nohtml': // No html
676  $out = dol_string_nohtmltag($out, 0);
677  break;
678  case 'alpha': // No html and no ../ and "
679  case 'alphanohtml': // Recommended for most scalar parameters and search parameters
680  if (!is_array($out)) {
681  // '"' is dangerous because param in url can close the href= or src= and add javascript functions.
682  // '../' is dangerous because it allows dir transversals
683  $out = str_replace(array('&quot;', '"'), '', trim($out));
684  $out = str_replace(array('../'), '', $out);
685  // keep lines feed
686  $out = dol_string_nohtmltag($out, 0);
687  }
688  break;
689  case 'alphawithlgt': // No " and no ../ but we keep balanced < > tags with no special chars inside. Can be used for email string like "Name <email>"
690  if (!is_array($out)) {
691  // '"' is dangerous because param in url can close the href= or src= and add javascript functions.
692  // '../' is dangerous because it allows dir transversals
693  $out = str_replace(array('&quot;', '"'), '', trim($out));
694  $out = str_replace(array('../'), '', $out);
695  }
696  break;
697  case 'restricthtml': // Recommended for most html textarea
698  $out = dol_string_onlythesehtmltags($out, 0, 1, 1);
699  break;
700  case 'custom':
701  if (empty($filter)) return 'BadFourthParameterForGETPOST';
702  $out = filter_var($out, $filter, $options);
703  break;
704  }
705 
706  return $out;
707 }
708 
709 
710 
711 if (!function_exists('dol_getprefix'))
712 {
721  function dol_getprefix($mode = '')
722  {
723  // If prefix is for email (we need to have $conf alreayd loaded for this case)
724  if ($mode == 'email')
725  {
726  global $conf;
727 
728  if (!empty($conf->global->MAIL_PREFIX_FOR_EMAIL_ID)) // If MAIL_PREFIX_FOR_EMAIL_ID is set (a value initialized with a random value is recommended)
729  {
730  if ($conf->global->MAIL_PREFIX_FOR_EMAIL_ID != 'SERVER_NAME') return $conf->global->MAIL_PREFIX_FOR_EMAIL_ID;
731  elseif (isset($_SERVER["SERVER_NAME"])) return $_SERVER["SERVER_NAME"];
732  }
733 
734  // The recommended value (may be not defined for old versions)
735  if (!empty($conf->file->instance_unique_id)) return $conf->file->instance_unique_id;
736 
737  // For backward compatibility
738  return dol_hash(DOL_DOCUMENT_ROOT.DOL_URL_ROOT, '3');
739  }
740 
741  // If prefix is for session (no need to have $conf loaded)
742  global $dolibarr_main_instance_unique_id, $dolibarr_main_cookie_cryptkey; // This is loaded by filefunc.inc.php
743  $tmp_instance_unique_id = empty($dolibarr_main_instance_unique_id) ? (empty($dolibarr_main_cookie_cryptkey) ? '' : $dolibarr_main_cookie_cryptkey) : $dolibarr_main_instance_unique_id; // Unique id of instance
744 
745  // The recommended value (may be not defined for old versions)
746  if (!empty($tmp_instance_unique_id)) {
747  return $tmp_instance_unique_id;
748  }
749 
750  // For backward compatibility
751  if (isset($_SERVER["SERVER_NAME"]) && isset($_SERVER["DOCUMENT_ROOT"])) {
752  return dol_hash($_SERVER["SERVER_NAME"].$_SERVER["DOCUMENT_ROOT"].DOL_DOCUMENT_ROOT.DOL_URL_ROOT, '3');
753  }
754 
755  return dol_hash(DOL_DOCUMENT_ROOT.DOL_URL_ROOT, '3');
756  }
757 }
758 
769 function dol_include_once($relpath, $classname = '')
770 {
771  global $conf, $langs, $user, $mysoc; // Do not remove this. They must be defined for files we include. Other globals var must be retrieved with $GLOBALS['var']
772 
773  $fullpath = dol_buildpath($relpath);
774 
775  if (!file_exists($fullpath)) {
776  dol_syslog('functions::dol_include_once Tried to load unexisting file: '.$relpath, LOG_WARNING);
777  return false;
778  }
779 
780  if (!empty($classname) && !class_exists($classname)) {
781  return include $fullpath;
782  } else {
783  return include_once $fullpath;
784  }
785 }
786 
787 
798 function dol_buildpath($path, $type = 0, $returnemptyifnotfound = 0)
799 {
800  global $conf;
801 
802  $path = preg_replace('/^\//', '', $path);
803 
804  if (empty($type)) // For a filesystem path
805  {
806  $res = DOL_DOCUMENT_ROOT.'/'.$path; // Standard default path
807  if (is_array($conf->file->dol_document_root))
808  {
809  foreach ($conf->file->dol_document_root as $key => $dirroot) // ex: array("main"=>"/home/main/htdocs", "alt0"=>"/home/dirmod/htdocs", ...)
810  {
811  if ($key == 'main')
812  {
813  continue;
814  }
815  if (file_exists($dirroot.'/'.$path))
816  {
817  $res = $dirroot.'/'.$path;
818  return $res;
819  }
820  }
821  }
822  if ($returnemptyifnotfound) // Not found into alternate dir
823  {
824  if ($returnemptyifnotfound == 1 || !file_exists($res)) return '';
825  }
826  } else // For an url path
827  {
828  // We try to get local path of file on filesystem from url
829  // Note that trying to know if a file on disk exist by forging path on disk from url
830  // works only for some web server and some setup. This is bugged when
831  // using proxy, rewriting, virtual path, etc...
832  $res = '';
833  if ($type == 1) $res = DOL_URL_ROOT.'/'.$path; // Standard value
834  if ($type == 2) $res = DOL_MAIN_URL_ROOT.'/'.$path; // Standard value
835  if ($type == 3) $res = DOL_URL_ROOT.'/'.$path;
836 
837  foreach ($conf->file->dol_document_root as $key => $dirroot) // ex: array(["main"]=>"/home/main/htdocs", ["alt0"]=>"/home/dirmod/htdocs", ...)
838  {
839  if ($key == 'main')
840  {
841  if ($type == 3)
842  {
843  global $dolibarr_main_url_root;
844 
845  // Define $urlwithroot
846  $urlwithouturlroot = preg_replace('/'.preg_quote(DOL_URL_ROOT, '/').'$/i', '', trim($dolibarr_main_url_root));
847  $urlwithroot = $urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain name found into config file
848  //$urlwithroot=DOL_MAIN_URL_ROOT; // This is to use same domain name than current
849 
850  $res = (preg_match('/^http/i', $conf->file->dol_url_root[$key]) ? '' : $urlwithroot).'/'.$path; // Test on start with http is for old conf syntax
851  }
852  continue;
853  }
854  preg_match('/^([^\?]+(\.css\.php|\.css|\.js\.php|\.js|\.png|\.jpg|\.php)?)/i', $path, $regs); // Take part before '?'
855  if (!empty($regs[1]))
856  {
857  //print $key.'-'.$dirroot.'/'.$path.'-'.$conf->file->dol_url_root[$type].'<br>'."\n";
858  if (file_exists($dirroot.'/'.$regs[1]))
859  {
860  if ($type == 1)
861  {
862  $res = (preg_match('/^http/i', $conf->file->dol_url_root[$key]) ? '' : DOL_URL_ROOT).$conf->file->dol_url_root[$key].'/'.$path;
863  }
864  if ($type == 2)
865  {
866  $res = (preg_match('/^http/i', $conf->file->dol_url_root[$key]) ? '' : DOL_MAIN_URL_ROOT).$conf->file->dol_url_root[$key].'/'.$path;
867  }
868  if ($type == 3)
869  {
870  global $dolibarr_main_url_root;
871 
872  // Define $urlwithroot
873  $urlwithouturlroot = preg_replace('/'.preg_quote(DOL_URL_ROOT, '/').'$/i', '', trim($dolibarr_main_url_root));
874  $urlwithroot = $urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain name found into config file
875  //$urlwithroot=DOL_MAIN_URL_ROOT; // This is to use same domain name than current
876 
877  $res = (preg_match('/^http/i', $conf->file->dol_url_root[$key]) ? '' : $urlwithroot).$conf->file->dol_url_root[$key].'/'.$path; // Test on start with http is for old conf syntax
878  }
879  break;
880  }
881  }
882  }
883  }
884 
885  return $res;
886 }
887 
898 function dol_clone($object, $native = 0)
899 {
900  if (empty($native))
901  {
902  $myclone = unserialize(serialize($object));
903  } else {
904  $myclone = clone $object; // PHP clone is a shallow copy only, not a real clone, so properties of references will keep the reference (refering to the same target/variable)
905  }
906 
907  return $myclone;
908 }
909 
919 function dol_size($size, $type = '')
920 {
921  global $conf;
922  if (empty($conf->dol_optimize_smallscreen)) return $size;
923  if ($type == 'width' && $size > 250) return 250;
924  else return 10;
925 }
926 
927 
938 function dol_sanitizeFileName($str, $newstr = '_', $unaccent = 1)
939 {
940  // List of special chars for filenames in windows are defined on page https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file
941  // Char '>' '<' '|' '$' and ';' are special chars for shells.
942  // Char '/' and '\' are file delimiters.
943  // -- car can be used into filename to inject special paramaters like --use-compress-program to make command with file as parameter making remote execution of command
944  $filesystem_forbidden_chars = array('<', '>', '/', '\\', '?', '*', '|', '"', ':', '°', '$', ';', '--');
945  return dol_string_nospecial($unaccent ? dol_string_unaccent($str) : $str, $newstr, $filesystem_forbidden_chars);
946 }
947 
958 function dol_sanitizePathName($str, $newstr = '_', $unaccent = 1)
959 {
960  $filesystem_forbidden_chars = array('<', '>', '?', '*', '|', '"', '°');
961  return dol_string_nospecial($unaccent ? dol_string_unaccent($str) : $str, $newstr, $filesystem_forbidden_chars);
962 }
963 
972 function dol_string_unaccent($str)
973 {
974  if (utf8_check($str))
975  {
976  // See http://www.utf8-chartable.de/
977  $string = rawurlencode($str);
978  $replacements = array(
979  '%C3%80' => 'A', '%C3%81' => 'A', '%C3%82' => 'A', '%C3%83' => 'A', '%C3%84' => 'A', '%C3%85' => 'A',
980  '%C3%88' => 'E', '%C3%89' => 'E', '%C3%8A' => 'E', '%C3%8B' => 'E',
981  '%C3%8C' => 'I', '%C3%8D' => 'I', '%C3%8E' => 'I', '%C3%8F' => 'I',
982  '%C3%92' => 'O', '%C3%93' => 'O', '%C3%94' => 'O', '%C3%95' => 'O', '%C3%96' => 'O',
983  '%C3%99' => 'U', '%C3%9A' => 'U', '%C3%9B' => 'U', '%C3%9C' => 'U',
984  '%C3%A0' => 'a', '%C3%A1' => 'a', '%C3%A2' => 'a', '%C3%A3' => 'a', '%C3%A4' => 'a', '%C3%A5' => 'a',
985  '%C3%A7' => 'c',
986  '%C3%A8' => 'e', '%C3%A9' => 'e', '%C3%AA' => 'e', '%C3%AB' => 'e',
987  '%C3%AC' => 'i', '%C3%AD' => 'i', '%C3%AE' => 'i', '%C3%AF' => 'i',
988  '%C3%B1' => 'n',
989  '%C3%B2' => 'o', '%C3%B3' => 'o', '%C3%B4' => 'o', '%C3%B5' => 'o', '%C3%B6' => 'o',
990  '%C3%B9' => 'u', '%C3%BA' => 'u', '%C3%BB' => 'u', '%C3%BC' => 'u',
991  '%C3%BF' => 'y'
992  );
993  $string = strtr($string, $replacements);
994  return rawurldecode($string);
995  } else {
996  // See http://www.ascii-code.com/
997  $string = strtr(
998  $str,
999  "\xC0\xC1\xC2\xC3\xC4\xC5\xC7
1000  \xC8\xC9\xCA\xCB\xCC\xCD\xCE\xCF\xD0\xD1
1001  \xD2\xD3\xD4\xD5\xD8\xD9\xDA\xDB\xDD
1002  \xE0\xE1\xE2\xE3\xE4\xE5\xE7\xE8\xE9\xEA\xEB
1003  \xEC\xED\xEE\xEF\xF0\xF1\xF2\xF3\xF4\xF5\xF8
1004  \xF9\xFA\xFB\xFC\xFD\xFF",
1005  "AAAAAAC
1006  EEEEIIIIDN
1007  OOOOOUUUY
1008  aaaaaaceeee
1009  iiiidnooooo
1010  uuuuyy"
1011  );
1012  $string = strtr($string, array("\xC4"=>"Ae", "\xC6"=>"AE", "\xD6"=>"Oe", "\xDC"=>"Ue", "\xDE"=>"TH", "\xDF"=>"ss", "\xE4"=>"ae", "\xE6"=>"ae", "\xF6"=>"oe", "\xFC"=>"ue", "\xFE"=>"th"));
1013  return $string;
1014  }
1015 }
1016 
1028 function dol_string_nospecial($str, $newstr = '_', $badcharstoreplace = '')
1029 {
1030  $forbidden_chars_to_replace = array(" ", "'", "/", "\\", ":", "*", "?", "\"", "<", ">", "|", "[", "]", ",", ";", "=", '°'); // more complete than dol_sanitizeFileName
1031  $forbidden_chars_to_remove = array();
1032  if (is_array($badcharstoreplace)) $forbidden_chars_to_replace = $badcharstoreplace;
1033  //$forbidden_chars_to_remove=array("(",")");
1034 
1035  return str_replace($forbidden_chars_to_replace, $newstr, str_replace($forbidden_chars_to_remove, "", $str));
1036 }
1037 
1038 
1052 function dol_string_nounprintableascii($str, $removetabcrlf = 1)
1053 {
1054  if ($removetabcrlf) {
1055  return preg_replace('/[\x00-\x1F\x7F]/u', '', $str); // /u operator makes UTF8 valid characters being ignored so are not included into the replace
1056  } else {
1057  return preg_replace('/[\x00-\x08\x11-\x12\x14-\x1F\x7F]/u', '', $str); // /u operator should make UTF8 valid characters being ignored so are not included into the replace
1058  }
1059 }
1060 
1061 
1070 function dol_escape_js($stringtoescape, $mode = 0, $noescapebackslashn = 0)
1071 {
1072  // escape quotes and backslashes, newlines, etc.
1073  $substitjs = array("&#039;"=>"\\'", "\r"=>'\\r');
1074  //$substitjs['</']='<\/'; // We removed this. Should be useless.
1075  if (empty($noescapebackslashn)) { $substitjs["\n"] = '\\n'; $substitjs['\\'] = '\\\\'; }
1076  if (empty($mode)) { $substitjs["'"] = "\\'"; $substitjs['"'] = "\\'"; } elseif ($mode == 1) $substitjs["'"] = "\\'";
1077  elseif ($mode == 2) { $substitjs['"'] = '\\"'; } elseif ($mode == 3) { $substitjs["'"] = "\\'"; $substitjs['"'] = "\\\""; }
1078  return strtr($stringtoescape, $substitjs);
1079 }
1080 
1087 function dol_escape_json($stringtoescape)
1088 {
1089  return str_replace('"', '\"', $stringtoescape);
1090 }
1091 
1103 function dol_escape_htmltag($stringtoescape, $keepb = 0, $keepn = 0, $keepmoretags = '', $escapeonlyhtmltags = 0)
1104 {
1105  if ($keepmoretags == 'common') $keepmoretags = 'html,body,a,b,em,i,u,ul,li,br,div,img,font,p,span,strong,table,tr,td,th,tbody';
1106  // TODO Implement $keepmoretags
1107 
1108  // escape quotes and backslashes, newlines, etc.
1109  if ($escapeonlyhtmltags) {
1110  $tmp = htmlspecialchars_decode($stringtoescape, ENT_COMPAT);
1111  } else {
1112  $tmp = html_entity_decode($stringtoescape, ENT_COMPAT, 'UTF-8');
1113  }
1114  if (!$keepb) $tmp = strtr($tmp, array("<b>"=>'', '</b>'=>''));
1115  if (!$keepn) $tmp = strtr($tmp, array("\r"=>'\\r', "\n"=>'\\n'));
1116  if ($escapeonlyhtmltags) {
1117  return htmlspecialchars($tmp, ENT_COMPAT, 'UTF-8');
1118  } else {
1119  return htmlentities($tmp, ENT_COMPAT, 'UTF-8');
1120  }
1121 }
1122 
1130 function dol_strtolower($string, $encoding = "UTF-8")
1131 {
1132  if (function_exists('mb_strtolower')) {
1133  return mb_strtolower($string, $encoding);
1134  } else {
1135  return strtolower($string);
1136  }
1137 }
1138 
1146 function dol_strtoupper($string, $encoding = "UTF-8")
1147 {
1148  if (function_exists('mb_strtoupper')) {
1149  return mb_strtoupper($string, $encoding);
1150  } else {
1151  return strtoupper($string);
1152  }
1153 }
1154 
1162 function dol_ucfirst($string, $encoding = "UTF-8")
1163 {
1164  if (function_exists('mb_substr')) {
1165  return mb_strtoupper(mb_substr($string, 0, 1, $encoding), $encoding).mb_substr($string, 1, null, $encoding);
1166  } else {
1167  return ucfirst($string);
1168  }
1169 }
1170 
1178 function dol_ucwords($string, $encoding = "UTF-8")
1179 {
1180  if (function_exists('mb_convert_case')) {
1181  return mb_convert_case($string, MB_CASE_TITLE, $encoding);
1182  } else {
1183  return ucwords($string);
1184  }
1185 }
1186 
1208 function dol_syslog($message, $level = LOG_INFO, $ident = 0, $suffixinfilename = '', $restricttologhandler = '', $logcontext = null)
1209 {
1210  global $conf, $user, $debugbar;
1211 
1212  // If syslog module enabled
1213  if (empty($conf->syslog->enabled)) return;
1214 
1215  // Check if we are into execution of code of a website
1216  if (defined('USEEXTERNALSERVER') && !defined('USEDOLIBARRSERVER') && !defined('USEDOLIBARREDITOR')) {
1217  global $website, $websitekey;
1218  if (is_object($website) && !empty($website->ref)) $suffixinfilename .= '_website_'.$website->ref;
1219  elseif (!empty($websitekey)) $suffixinfilename .= '_website_'.$websitekey;
1220  }
1221 
1222  if ($ident < 0)
1223  {
1224  foreach ($conf->loghandlers as $loghandlerinstance)
1225  {
1226  $loghandlerinstance->setIdent($ident);
1227  }
1228  }
1229 
1230  if (!empty($message))
1231  {
1232  // Test log level
1233  $logLevels = array(LOG_EMERG=>'EMERG', LOG_ALERT=>'ALERT', LOG_CRIT=>'CRITICAL', LOG_ERR=>'ERR', LOG_WARNING=>'WARN', LOG_NOTICE=>'NOTICE', LOG_INFO=>'INFO', LOG_DEBUG=>'DEBUG');
1234  if (!array_key_exists($level, $logLevels))
1235  {
1236  throw new Exception('Incorrect log level');
1237  }
1238  if ($level > $conf->global->SYSLOG_LEVEL) return;
1239 
1240  $message = preg_replace('/password=\'[^\']*\'/', 'password=\'hidden\'', $message); // protection to avoid to have value of password in log
1241 
1242  // If adding log inside HTML page is required
1243  if ((!empty($_REQUEST['logtohtml']) && !empty($conf->global->MAIN_ENABLE_LOG_TO_HTML))
1244  || (!empty($user->rights->debugbar->read) && is_object($debugbar)))
1245  {
1246  $conf->logbuffer[] = dol_print_date(time(), "%Y-%m-%d %H:%M:%S")." ".$logLevels[$level]." ".$message;
1247  }
1248 
1249  //TODO: Remove this. MAIN_ENABLE_LOG_INLINE_HTML should be deprecated and use a log handler dedicated to HTML output
1250  // If html log tag enabled and url parameter log defined, we show output log on HTML comments
1251  if (!empty($conf->global->MAIN_ENABLE_LOG_INLINE_HTML) && !empty($_GET["log"]))
1252  {
1253  print "\n\n<!-- Log start\n";
1254  print $message."\n";
1255  print "Log end -->\n";
1256  }
1257 
1258  $data = array(
1259  'message' => $message,
1260  'script' => (isset($_SERVER['PHP_SELF']) ? basename($_SERVER['PHP_SELF'], '.php') : false),
1261  'level' => $level,
1262  'user' => ((is_object($user) && $user->id) ? $user->login : false),
1263  'ip' => false
1264  );
1265 
1266  $remoteip = getUserRemoteIP(); // Get ip when page run on a web server
1267  if (!empty($remoteip)) {
1268  $data['ip'] = $remoteip;
1269  // This is when server run behind a reverse proxy
1270  if (!empty($_SERVER['HTTP_X_FORWARDED_FOR']) && $_SERVER['HTTP_X_FORWARDED_FOR'] != $remoteip) $data['ip'] = $_SERVER['HTTP_X_FORWARDED_FOR'].' -> '.$data['ip'];
1271  elseif (!empty($_SERVER['HTTP_CLIENT_IP']) && $_SERVER['HTTP_CLIENT_IP'] != $remoteip) $data['ip'] = $_SERVER['HTTP_CLIENT_IP'].' -> '.$data['ip'];
1272  } // This is when PHP session is ran inside a web server but not inside a client request (example: init code of apache)
1273  elseif (!empty($_SERVER['SERVER_ADDR'])) $data['ip'] = $_SERVER['SERVER_ADDR'];
1274  // This is when PHP session is ran outside a web server, like from Windows command line (Not always defined, but useful if OS defined it).
1275  elseif (!empty($_SERVER['COMPUTERNAME'])) $data['ip'] = $_SERVER['COMPUTERNAME'].(empty($_SERVER['USERNAME']) ? '' : '@'.$_SERVER['USERNAME']);
1276  // This is when PHP session is ran outside a web server, like from Linux command line (Not always defined, but usefull if OS defined it).
1277  elseif (!empty($_SERVER['LOGNAME'])) $data['ip'] = '???@'.$_SERVER['LOGNAME'];
1278  // Loop on each log handler and send output
1279  foreach ($conf->loghandlers as $loghandlerinstance)
1280  {
1281  if ($restricttologhandler && $loghandlerinstance->code != $restricttologhandler) continue;
1282  $loghandlerinstance->export($data, $suffixinfilename);
1283  }
1284  unset($data);
1285  }
1286 
1287  if ($ident > 0)
1288  {
1289  foreach ($conf->loghandlers as $loghandlerinstance)
1290  {
1291  $loghandlerinstance->setIdent($ident);
1292  }
1293  }
1294 }
1295 
1307 function dolButtonToOpenUrlInDialogPopup($name, $label, $buttonstring, $url, $disabled = '')
1308 {
1309  if (strpos($url, '?') > 0) {
1310  $url .= '&dol_hide_topmenu=1&dol_hide_leftmenu=1&dol_openinpopup=1';
1311  } else {
1312  $url .= '?dol_hide_menuinpopup=1&dol_hide_leftmenu=1&dol_openinpopup=1';
1313  }
1314 
1315  //print '<input type="submit" class="button bordertransp"'.$disabled.' value="'.dol_escape_htmltag($langs->trans("MediaFiles")).'" name="file_manager">';
1316  $out = '<a class="button bordertransp button_'.$name.'"'.$disabled.' title="'.dol_escape_htmltag($label).'">'.$buttonstring.'</a>';
1317  $out .= '<script language="javascript">
1318  jQuery(document).ready(function () {
1319  jQuery(".button_'.$name.'").click(function () {
1320  var $dialog = $(\'<div></div>\').html(\'<iframe class="iframedialog" style="border: 0px;" src="'.DOL_URL_ROOT.$url.'" width="100%" height="98%"></iframe>\')
1321  .dialog({
1322  autoOpen: false,
1323  modal: true,
1324  height: (window.innerHeight - 150),
1325  width: \'80%\',
1326  title: "'.dol_escape_js($label).'"
1327  });
1328  $dialog.dialog(\'open\');
1329  });
1330  });
1331  </script>';
1332  return $out;
1333 }
1334 
1351 function dol_fiche_head($links = array(), $active = '0', $title = '', $notab = 0, $picto = '', $pictoisfullpath = 0, $morehtmlright = '', $morecss = '', $limittoshow = 0, $moretabssuffix = '')
1352 {
1353  print dol_get_fiche_head($links, $active, $title, $notab, $picto, $pictoisfullpath, $morehtmlright, $morecss, $limittoshow, $moretabssuffix);
1354 }
1355 
1371 function dol_get_fiche_head($links = array(), $active = '', $title = '', $notab = 0, $picto = '', $pictoisfullpath = 0, $morehtmlright = '', $morecss = '', $limittoshow = 0, $moretabssuffix = '')
1372 {
1373  global $conf, $langs, $hookmanager;
1374 
1375  // Show title
1376  $showtitle = 1;
1377  if (!empty($conf->dol_optimize_smallscreen)) $showtitle = 0;
1378 
1379  $out = "\n".'<!-- dol_fiche_head - dol_get_fiche_head -->';
1380 
1381  if ((!empty($title) && $showtitle) || $morehtmlright || !empty($links)) {
1382  $out .= '<div class="tabs'.($picto ? '' : ' nopaddingleft').'" data-role="controlgroup" data-type="horizontal">'."\n";
1383  }
1384 
1385  // Show right part
1386  if ($morehtmlright) $out .= '<div class="inline-block floatright tabsElem">'.$morehtmlright.'</div>'; // Output right area first so when space is missing, text is in front of tabs and not under.
1387 
1388  // Show title
1389  if (!empty($title) && $showtitle && empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER))
1390  {
1391  $limittitle = 30;
1392  $out .= '<a class="tabTitle">';
1393  if ($picto) $out .= img_picto($title, ($pictoisfullpath ? '' : 'object_').$picto, '', $pictoisfullpath, 0, 0, '', 'imgTabTitle').' ';
1394  $out .= '<span class="tabTitleText">'.dol_trunc($title, $limittitle).'</span>';
1395  $out .= '</a>';
1396  }
1397 
1398  // Show tabs
1399 
1400  // Define max of key (max may be higher than sizeof because of hole due to module disabling some tabs).
1401  $maxkey = -1;
1402  if (is_array($links) && !empty($links))
1403  {
1404  $keys = array_keys($links);
1405  if (count($keys)) $maxkey = max($keys);
1406  }
1407 
1408  // Show tabs
1409  // if =0 we don't use the feature
1410  if (empty($limittoshow)) {
1411  $limittoshow = (empty($conf->global->MAIN_MAXTABS_IN_CARD) ? 99 : $conf->global->MAIN_MAXTABS_IN_CARD);
1412  }
1413  if (!empty($conf->dol_optimize_smallscreen)) $limittoshow = 2;
1414 
1415  $displaytab = 0;
1416  $nbintab = 0;
1417  $popuptab = 0;
1418  $outmore = '';
1419  for ($i = 0; $i <= $maxkey; $i++)
1420  {
1421  if ((is_numeric($active) && $i == $active) || (!empty($links[$i][2]) && !is_numeric($active) && $active == $links[$i][2])) {
1422  // If active tab is already present
1423  if ($i >= $limittoshow) $limittoshow--;
1424  }
1425  }
1426 
1427  for ($i = 0; $i <= $maxkey; $i++)
1428  {
1429  if ((is_numeric($active) && $i == $active) || (!empty($links[$i][2]) && !is_numeric($active) && $active == $links[$i][2])) {
1430  $isactive = true;
1431  } else {
1432  $isactive = false;
1433  }
1434 
1435  if ($i < $limittoshow || $isactive)
1436  {
1437  $out .= '<div class="inline-block tabsElem'.($isactive ? ' tabsElemActive' : '').((!$isactive && !empty($conf->global->MAIN_HIDE_INACTIVETAB_ON_PRINT)) ? ' hideonprint' : '').'"><!-- id tab = '.(empty($links[$i][2]) ? '' : $links[$i][2]).' -->';
1438  if (isset($links[$i][2]) && $links[$i][2] == 'image')
1439  {
1440  if (!empty($links[$i][0]))
1441  {
1442  $out .= '<a class="tabimage'.($morecss ? ' '.$morecss : '').'" href="'.$links[$i][0].'">'.$links[$i][1].'</a>'."\n";
1443  } else {
1444  $out .= '<span class="tabspan">'.$links[$i][1].'</span>'."\n";
1445  }
1446  } elseif (!empty($links[$i][1]))
1447  {
1448  //print "x $i $active ".$links[$i][2]." z";
1449  if ($isactive)
1450  {
1451  $out .= '<a'.(!empty($links[$i][2]) ? ' id="'.$links[$i][2].'"' : '').' class="tabactive tab inline-block'.($morecss ? ' '.$morecss : '').'" href="'.$links[$i][0].'">';
1452  $out .= $links[$i][1];
1453  $out .= '</a>'."\n";
1454  } else {
1455  $out .= '<a'.(!empty($links[$i][2]) ? ' id="'.$links[$i][2].'"' : '').' class="tabunactive tab inline-block'.($morecss ? ' '.$morecss : '').'" href="'.$links[$i][0].'">';
1456  $out .= $links[$i][1];
1457  $out .= '</a>'."\n";
1458  }
1459  }
1460  $out .= '</div>';
1461  } else {
1462  // The popup with the other tabs
1463  if (!$popuptab)
1464  {
1465  $popuptab = 1;
1466  $outmore .= '<div class="popuptabset wordwrap">'; // The css used to hide/show popup
1467  }
1468  $outmore .= '<div class="popuptab wordwrap" style="display:inherit;">';
1469  if (isset($links[$i][2]) && $links[$i][2] == 'image')
1470  {
1471  if (!empty($links[$i][0]))
1472  $outmore .= '<a class="tabimage'.($morecss ? ' '.$morecss : '').'" href="'.$links[$i][0].'">'.$links[$i][1].'</a>'."\n";
1473  else $outmore .= '<span class="tabspan">'.$links[$i][1].'</span>'."\n";
1474  } elseif (!empty($links[$i][1]))
1475  {
1476  $outmore .= '<a'.(!empty($links[$i][2]) ? ' id="'.$links[$i][2].'"' : '').' class="wordwrap inline-block'.($morecss ? ' '.$morecss : '').'" href="'.$links[$i][0].'">';
1477  $outmore .= preg_replace('/([a-z])\/([a-z])/i', '\\1 / \\2', $links[$i][1]); // Replace x/y with x / y to allow wrap on long composed texts.
1478  $outmore .= '</a>'."\n";
1479  }
1480  $outmore .= '</div>';
1481 
1482  $nbintab++;
1483  }
1484  $displaytab = $i;
1485  }
1486  if ($popuptab) $outmore .= '</div>';
1487 
1488  if ($popuptab) // If there is some tabs not shown
1489  {
1490  $left = ($langs->trans("DIRECTION") == 'rtl' ? 'right' : 'left');
1491  $right = ($langs->trans("DIRECTION") == 'rtl' ? 'left' : 'right');
1492  $widthofpopup = 200;
1493 
1494  $tabsname = $moretabssuffix;
1495  if (empty($tabsname)) { $tabsname = str_replace("@", "", $picto); }
1496  $out .= '<div id="moretabs'.$tabsname.'" class="inline-block tabsElem">';
1497  $out .= '<a href="#" class="tab moretab inline-block tabunactive">'.$langs->trans("More").'... ('.$nbintab.')</a>'; // Do not use "reposition" class in the "More".
1498  $out .= '<div id="moretabsList'.$tabsname.'" style="width: '.$widthofpopup.'px; position: absolute; '.$left.': -999em; text-align: '.$left.'; margin:0px; padding:2px; z-index:10;">';
1499  $out .= $outmore;
1500  $out .= '</div>';
1501  $out .= '<div></div>';
1502  $out .= "</div>\n";
1503 
1504  $out .= "<script>";
1505  $out .= "$('#moretabs".$tabsname."').mouseenter( function() {
1506  var x = this.offsetLeft, y = this.offsetTop;
1507  console.log('mouseenter ".$left." x='+x+' y='+y+' window.innerWidth='+window.innerWidth);
1508  if ((window.innerWidth - x) < ".($widthofpopup + 10).") {
1509  $('#moretabsList".$tabsname."').css('".$right."','8px');
1510  }
1511  $('#moretabsList".$tabsname."').css('".$left."','auto');
1512  });
1513  ";
1514  $out .= "$('#moretabs".$tabsname."').mouseleave( function() { console.log('mouseleave ".$left."'); $('#moretabsList".$tabsname."').css('".$left."','-999em');});";
1515  $out .= "</script>";
1516  }
1517 
1518  if ((!empty($title) && $showtitle) || $morehtmlright || !empty($links)) {
1519  $out .= "</div>\n";
1520  }
1521 
1522  if (!$notab || $notab == -1 || $notab == -2) $out .= "\n".'<div class="tabBar'.($notab == -1 ? '' : ($notab == -2 ? ' tabBarNoTop' : ' tabBarWithBottom')).'">'."\n";
1523 
1524  $parameters = array('tabname' => $active, 'out' => $out);
1525  $reshook = $hookmanager->executeHooks('printTabsHead', $parameters); // This hook usage is called just before output the head of tabs. Take also a look at "completeTabsHead"
1526  if ($reshook > 0)
1527  {
1528  $out = $hookmanager->resPrint;
1529  }
1530 
1531  return $out;
1532 }
1533 
1541 function dol_fiche_end($notab = 0)
1542 {
1543  print dol_get_fiche_end($notab);
1544 }
1545 
1552 function dol_get_fiche_end($notab = 0)
1553 {
1554  if (!$notab || $notab == -1) return "\n</div>\n";
1555  else return '';
1556 }
1557 
1577 function dol_banner_tab($object, $paramid, $morehtml = '', $shownav = 1, $fieldid = 'rowid', $fieldref = 'ref', $morehtmlref = '', $moreparam = '', $nodbprefix = 0, $morehtmlleft = '', $morehtmlstatus = '', $onlybanner = 0, $morehtmlright = '')
1578 {
1579  global $conf, $form, $user, $langs;
1580 
1581  $error = 0;
1582 
1583  $maxvisiblephotos = 1;
1584  $showimage = 1;
1585  $entity = (empty($object->entity) ? $conf->entity : $object->entity);
1586  $showbarcode = empty($conf->barcode->enabled) ? 0 : ($object->barcode ? 1 : 0);
1587  if (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->barcode->lire_advance)) $showbarcode = 0;
1588  $modulepart = 'unknown';
1589 
1590  if ($object->element == 'societe') $modulepart = 'societe';
1591  if ($object->element == 'contact') $modulepart = 'contact';
1592  if ($object->element == 'member') $modulepart = 'memberphoto';
1593  if ($object->element == 'user') $modulepart = 'userphoto';
1594  if ($object->element == 'product') $modulepart = 'product';
1595  if ($object->element == 'ticket') $modulepart = 'ticket';
1596 
1597  if (class_exists("Imagick"))
1598  {
1599  if ($object->element == 'propal') $modulepart = 'propal';
1600  if ($object->element == 'commande') $modulepart = 'commande';
1601  if ($object->element == 'facture') $modulepart = 'facture';
1602  if ($object->element == 'fichinter') $modulepart = 'ficheinter';
1603  if ($object->element == 'contrat') $modulepart = 'contract';
1604  if ($object->element == 'supplier_proposal') $modulepart = 'supplier_proposal';
1605  if ($object->element == 'order_supplier') $modulepart = 'supplier_order';
1606  if ($object->element == 'invoice_supplier') $modulepart = 'supplier_invoice';
1607  if ($object->element == 'expensereport') $modulepart = 'expensereport';
1608  }
1609 
1610  if ($object->element == 'product')
1611  {
1612  $width = 80; $cssclass = 'photoref';
1613  $showimage = $object->is_photo_available($conf->product->multidir_output[$entity]);
1614  $maxvisiblephotos = (isset($conf->global->PRODUCT_MAX_VISIBLE_PHOTO) ? $conf->global->PRODUCT_MAX_VISIBLE_PHOTO : 5);
1615  if ($conf->browser->layout == 'phone') $maxvisiblephotos = 1;
1616  if ($showimage) {
1617  $morehtmlleft .= '<div class="floatleft inline-block valignmiddle divphotoref">'.$object->show_photos('product', $conf->product->multidir_output[$entity], 'small', $maxvisiblephotos, 0, 0, 0, $width, 0).'</div>';
1618  } else {
1619  if (!empty($conf->global->PRODUCT_NODISPLAYIFNOPHOTO)) {
1620  $nophoto = '';
1621  $morehtmlleft .= '<div class="floatleft inline-block valignmiddle divphotoref"></div>';
1622  } else { // Show no photo link
1623  $nophoto = '/public/theme/common/nophoto.png';
1624  $morehtmlleft .= '<div class="floatleft inline-block valignmiddle divphotoref"><img class="photo'.$modulepart.($cssclass ? ' '.$cssclass : '').'" alt="No photo"'.($width ? ' style="width: '.$width.'px"' : '').' src="'.DOL_URL_ROOT.$nophoto.'"></div>';
1625  }
1626  }
1627  } elseif ($object->element == 'ticket') {
1628  $width = 80; $cssclass = 'photoref';
1629  $showimage = $object->is_photo_available($conf->ticket->multidir_output[$entity].'/'.$object->ref);
1630  $maxvisiblephotos = (isset($conf->global->TICKET_MAX_VISIBLE_PHOTO) ? $conf->global->TICKET_MAX_VISIBLE_PHOTO : 2);
1631  if ($conf->browser->layout == 'phone') $maxvisiblephotos = 1;
1632 
1633  if ($showimage)
1634  {
1635  $showphoto = $object->show_photos('ticket', $conf->ticket->multidir_output[$entity], 'small', $maxvisiblephotos, 0, 0, 0, $width, 0);
1636  if ($object->nbphoto > 0)
1637  {
1638  $morehtmlleft .= '<div class="floatleft inline-block valignmiddle divphotoref">'.$showphoto.'</div>';
1639  } else {
1640  $showimage = 0;
1641  }
1642  }
1643  if (!$showimage)
1644  {
1645  if (!empty($conf->global->TICKET_NODISPLAYIFNOPHOTO)) {
1646  $nophoto = '';
1647  $morehtmlleft .= '<div class="floatleft inline-block valignmiddle divphotoref"></div>';
1648  } else { // Show no photo link
1649  $nophoto = img_picto('No photo', 'object_ticket');
1650  $morehtmlleft .= '<!-- No photo to show -->';
1651  $morehtmlleft .= '<div class="floatleft inline-block valignmiddle divphotoref"><div class="photoref">';
1652  $morehtmlleft .= $nophoto;
1653  $morehtmlleft .= '</div></div>';
1654  }
1655  }
1656  } else {
1657  if ($showimage)
1658  {
1659  if ($modulepart != 'unknown')
1660  {
1661  $phototoshow = '';
1662  // Check if a preview file is available
1663  if (in_array($modulepart, array('propal', 'commande', 'facture', 'ficheinter', 'contract', 'supplier_order', 'supplier_proposal', 'supplier_invoice', 'expensereport')) && class_exists("Imagick"))
1664  {
1665  $objectref = dol_sanitizeFileName($object->ref);
1666  $dir_output = (empty($conf->$modulepart->multidir_output[$entity]) ? $conf->$modulepart->dir_output : $conf->$modulepart->multidir_output[$entity])."/";
1667  if (in_array($modulepart, array('invoice_supplier', 'supplier_invoice')))
1668  {
1669  $subdir = get_exdir($object->id, 2, 0, 1, $object, $modulepart);
1670  $subdir .= ((!empty($subdir) && !preg_match('/\/$/', $subdir)) ? '/' : '').$objectref; // the objectref dir is not included into get_exdir when used with level=2, so we add it at end
1671  } else {
1672  $subdir = get_exdir($object->id, 0, 0, 1, $object, $modulepart);
1673  }
1674  if (empty($subdir)) $subdir = 'errorgettingsubdirofobject'; // Protection to avoid to return empty path
1675 
1676  $filepath = $dir_output.$subdir."/";
1677 
1678  $filepdf = $filepath.$objectref.".pdf";
1679  $relativepath = $subdir.'/'.$objectref.'.pdf';
1680 
1681  // Define path to preview pdf file (preview precompiled "file.ext" are "file.ext_preview.png")
1682  $fileimage = $filepdf.'_preview.png';
1683  $relativepathimage = $relativepath.'_preview.png';
1684 
1685  $pdfexists = file_exists($filepdf);
1686 
1687  // If PDF file exists
1688  if ($pdfexists)
1689  {
1690  // Conversion du PDF en image png si fichier png non existant
1691  if (!file_exists($fileimage) || (filemtime($fileimage) < filemtime($filepdf)))
1692  {
1693  if (empty($conf->global->MAIN_DISABLE_PDF_THUMBS)) // If you experience trouble with pdf thumb generation and imagick, you can disable here.
1694  {
1695  include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
1696  $ret = dol_convert_file($filepdf, 'png', $fileimage, '0'); // Convert first page of PDF into a file _preview.png
1697  if ($ret < 0) $error++;
1698  }
1699  }
1700  }
1701 
1702  if ($pdfexists && !$error)
1703  {
1704  $heightforphotref = 80;
1705  if (!empty($conf->dol_optimize_smallscreen)) $heightforphotref = 60;
1706  // If the preview file is found
1707  if (file_exists($fileimage))
1708  {
1709  $phototoshow = '<div class="photoref">';
1710  $phototoshow .= '<img height="'.$heightforphotref.'" class="photo photowithmargin photowithborder" src="'.DOL_URL_ROOT.'/viewimage.php?modulepart=apercu'.$modulepart.'&amp;file='.urlencode($relativepathimage).'">';
1711  $phototoshow .= '</div>';
1712  }
1713  }
1714  } elseif (!$phototoshow) { // example if modulepart = 'photo'
1715  $phototoshow .= $form->showphoto($modulepart, $object, 0, 0, 0, 'photoref', 'small', 1, 0, $maxvisiblephotos);
1716  }
1717 
1718  if ($phototoshow) {
1719  $morehtmlleft .= '<div class="floatleft inline-block valignmiddle divphotoref">';
1720  $morehtmlleft .= $phototoshow;
1721  $morehtmlleft .= '</div>';
1722  }
1723  }
1724 
1725  if (!$phototoshow) // Show No photo link (picto of object)
1726  {
1727  $morehtmlleft .= '<div class="floatleft inline-block valignmiddle divphotoref">';
1728  if ($object->element == 'action')
1729  {
1730  $width = 80;
1731  $cssclass = 'photorefcenter';
1732  $nophoto = img_picto('No photo', 'title_agenda');
1733  } else {
1734  $width = 14; $cssclass = 'photorefcenter';
1735  $picto = $object->picto;
1736  if ($object->element == 'project' && !$object->public) $picto = 'project'; // instead of projectpub
1737  $nophoto = img_picto('No photo', 'object_'.$picto);
1738  }
1739  $morehtmlleft .= '<!-- No photo to show -->';
1740  $morehtmlleft .= '<div class="floatleft inline-block valignmiddle divphotoref"><div class="photoref">';
1741  $morehtmlleft .= $nophoto;
1742  $morehtmlleft .= '</div></div>';
1743 
1744  $morehtmlleft .= '</div>';
1745  }
1746  }
1747  }
1748 
1749  if ($showbarcode) $morehtmlleft .= '<div class="floatleft inline-block valignmiddle divphotoref">'.$form->showbarcode($object).'</div>';
1750 
1751  if ($object->element == 'societe')
1752  {
1753  if (!empty($conf->use_javascript_ajax) && $user->rights->societe->creer && !empty($conf->global->MAIN_DIRECT_STATUS_UPDATE))
1754  {
1755  $morehtmlstatus .= ajax_object_onoff($object, 'status', 'status', 'InActivity', 'ActivityCeased');
1756  } else {
1757  $morehtmlstatus .= $object->getLibStatut(6);
1758  }
1759  } elseif ($object->element == 'product')
1760  {
1761  //$morehtmlstatus.=$langs->trans("Status").' ('.$langs->trans("Sell").') ';
1762  if (!empty($conf->use_javascript_ajax) && $user->rights->produit->creer && !empty($conf->global->MAIN_DIRECT_STATUS_UPDATE)) {
1763  $morehtmlstatus .= ajax_object_onoff($object, 'status', 'tosell', 'ProductStatusOnSell', 'ProductStatusNotOnSell');
1764  } else {
1765  $morehtmlstatus .= '<span class="statusrefsell">'.$object->getLibStatut(6, 0).'</span>';
1766  }
1767  $morehtmlstatus .= ' &nbsp; ';
1768  //$morehtmlstatus.=$langs->trans("Status").' ('.$langs->trans("Buy").') ';
1769  if (!empty($conf->use_javascript_ajax) && $user->rights->produit->creer && !empty($conf->global->MAIN_DIRECT_STATUS_UPDATE)) {
1770  $morehtmlstatus .= ajax_object_onoff($object, 'status_buy', 'tobuy', 'ProductStatusOnBuy', 'ProductStatusNotOnBuy');
1771  } else {
1772  $morehtmlstatus .= '<span class="statusrefbuy">'.$object->getLibStatut(6, 1).'</span>';
1773  }
1774  } elseif (in_array($object->element, array('facture', 'invoice', 'invoice_supplier', 'chargesociales', 'loan'))) {
1775  $tmptxt = $object->getLibStatut(6, $object->totalpaye);
1776  if (empty($tmptxt) || $tmptxt == $object->getLibStatut(3)) $tmptxt = $object->getLibStatut(5, $object->totalpaye);
1777  $morehtmlstatus .= $tmptxt;
1778  } elseif ($object->element == 'contrat' || $object->element == 'contract') {
1779  if ($object->statut == 0) $morehtmlstatus .= $object->getLibStatut(5);
1780  else $morehtmlstatus .= $object->getLibStatut(4);
1781  } elseif ($object->element == 'facturerec') {
1782  if ($object->frequency == 0) $morehtmlstatus .= $object->getLibStatut(2);
1783  else $morehtmlstatus .= $object->getLibStatut(5);
1784  } elseif ($object->element == 'project_task') {
1785  $object->fk_statut = 1;
1786  if ($object->progress > 0) $object->fk_statut = 2;
1787  if ($object->progress >= 100) $object->fk_statut = 3;
1788  $tmptxt = $object->getLibStatut(5);
1789  $morehtmlstatus .= $tmptxt; // No status on task
1790  } else { // Generic case
1791  $tmptxt = $object->getLibStatut(6);
1792  if (empty($tmptxt) || $tmptxt == $object->getLibStatut(3)) $tmptxt = $object->getLibStatut(5);
1793  $morehtmlstatus .= $tmptxt;
1794  }
1795 
1796  // Add if object was dispatched "into accountancy"
1797  if (!empty($conf->accounting->enabled) && in_array($object->element, array('bank', 'paiementcharge', 'facture', 'invoice', 'invoice_supplier', 'expensereport', 'payment_various')))
1798  {
1799  // Note: For 'chargesociales', 'salaries'... this is the payments that are dispatched (so element = 'bank')
1800  if (method_exists($object, 'getVentilExportCompta'))
1801  {
1802  $accounted = $object->getVentilExportCompta();
1803  $langs->load("accountancy");
1804  $morehtmlstatus .= '</div><div class="statusref statusrefbis"><span class="opacitymedium">'.($accounted > 0 ? $langs->trans("Accounted") : $langs->trans("NotYetAccounted")).'</span>';
1805  }
1806  }
1807 
1808  // Add alias for thirdparty
1809  if (!empty($object->name_alias)) $morehtmlref .= '<div class="refidno">'.$object->name_alias.'</div>';
1810 
1811  // Add label
1812  if (in_array($object->element, array('product', 'bank_account', 'project_task')))
1813  {
1814  if (!empty($object->label)) $morehtmlref .= '<div class="refidno">'.$object->label.'</div>';
1815  }
1816 
1817  if (method_exists($object, 'getBannerAddress') && !in_array($object->element, array('product', 'bookmark', 'ecm_directories', 'ecm_files')))
1818  {
1819  $moreaddress = $object->getBannerAddress('refaddress', $object);
1820  if ($moreaddress) {
1821  $morehtmlref .= '<div class="refidno">';
1822  $morehtmlref .= $moreaddress;
1823  $morehtmlref .= '</div>';
1824  }
1825  }
1826  if (!empty($conf->global->MAIN_SHOW_TECHNICAL_ID) && ($conf->global->MAIN_SHOW_TECHNICAL_ID == '1' || preg_match('/'.preg_quote($object->element, '/').'/i', $conf->global->MAIN_SHOW_TECHNICAL_ID)) && !empty($object->id))
1827  {
1828  $morehtmlref .= '<div style="clear: both;"></div>';
1829  $morehtmlref .= '<div class="refidno">';
1830  $morehtmlref .= $langs->trans("TechnicalID").': '.$object->id;
1831  $morehtmlref .= '</div>';
1832  }
1833 
1834  print '<div class="'.($onlybanner ? 'arearefnobottom ' : 'arearef ').'heightref valignmiddle centpercent">';
1835  print $form->showrefnav($object, $paramid, $morehtml, $shownav, $fieldid, $fieldref, $morehtmlref, $moreparam, $nodbprefix, $morehtmlleft, $morehtmlstatus, $morehtmlright);
1836  print '</div>';
1837  print '<div class="underrefbanner clearboth"></div>';
1838 }
1839 
1849 function fieldLabel($langkey, $fieldkey, $fieldrequired = 0)
1850 {
1851  global $langs;
1852  $ret = '';
1853  if ($fieldrequired) $ret .= '<span class="fieldrequired">';
1854  $ret .= '<label for="'.$fieldkey.'">';
1855  $ret .= $langs->trans($langkey);
1856  $ret .= '</label>';
1857  if ($fieldrequired) $ret .= '</span>';
1858  return $ret;
1859 }
1860 
1868 function dol_bc($var, $moreclass = '')
1869 {
1870  global $bc;
1871  $ret = ' '.$bc[$var];
1872  if ($moreclass) $ret = preg_replace('/class=\"/', 'class="'.$moreclass.' ', $ret);
1873  return $ret;
1874 }
1875 
1889 function dol_format_address($object, $withcountry = 0, $sep = "\n", $outputlangs = '', $mode = 0, $extralangcode = '')
1890 {
1891  global $conf, $langs;
1892 
1893  $ret = '';
1894  $countriesusingstate = array('AU', 'CA', 'US', 'IN', 'GB', 'ES', 'UK', 'TR'); // See also MAIN_FORCE_STATE_INTO_ADDRESS
1895 
1896  // See format of addresses on https://en.wikipedia.org/wiki/Address
1897  // Address
1898  if (empty($mode)) {
1899  $ret .= ($extralangcode ? $object->array_languages['address'][$extralangcode] : $object->address);
1900  }
1901  // Zip/Town/State
1902  if (isset($object->country_code) && in_array($object->country_code, array('AU', 'CA', 'US')) || !empty($conf->global->MAIN_FORCE_STATE_INTO_ADDRESS)) { // US: title firstname name \n address lines \n town, state, zip \n country
1903  $town = ($extralangcode ? $object->array_languages['town'][$extralangcode] : $object->town);
1904  $ret .= ($ret ? $sep : '').$town;
1905  if (!empty($object->state)) {
1906  $ret .= ($ret ? ", " : '').$object->state;
1907  }
1908  if ($object->zip) $ret .= ($ret ? ", " : '').$object->zip;
1909  } elseif (isset($object->country_code) && in_array($object->country_code, array('GB', 'UK'))) { // UK: title firstname name \n address lines \n town state \n zip \n country
1910  $town = ($extralangcode ? $object->array_languages['town'][$extralangcode] : $object->town);
1911  $ret .= ($ret ? $sep : '').$town;
1912  if (!empty($object->state)) {
1913  $ret .= ($ret ? ", " : '').$object->state;
1914  }
1915  if ($object->zip) $ret .= ($ret ? $sep : '').$object->zip;
1916  } elseif (isset($object->country_code) && in_array($object->country_code, array('ES', 'TR'))) { // ES: title firstname name \n address lines \n zip town \n state \n country
1917  $ret .= ($ret ? $sep : '').$object->zip;
1918  $town = ($extralangcode ? $object->array_languages['town'][$extralangcode] : $object->town);
1919  $ret .= ($town ? (($object->zip ? ' ' : '').$town) : '');
1920  if (!empty($object->state)) {
1921  $ret .= "\n".$object->state;
1922  }
1923  } elseif (isset($object->country_code) && in_array($object->country_code, array('IT'))) { // IT: tile firstname name\n address lines \n zip (Code Departement) \n country
1924  $ret .= ($ret ? $sep : '').$object->zip;
1925  $town = ($extralangcode ? $object->array_languages['town'][$extralangcode] : $object->town);
1926  $ret .= ($town ? (($object->zip ? ' ' : '').$town) : '');
1927  $ret .= (empty($object->state_code) ? '' : (' '.$object->state_code));
1928  } else { // Other: title firstname name \n address lines \n zip town \n country
1929  $town = ($extralangcode ? $object->array_languages['town'][$extralangcode] : $object->town);
1930  $ret .= $object->zip ? (($ret ? $sep : '').$object->zip) : '';
1931  $ret .= ($town ? (($object->zip ? ' ' : ($ret ? $sep : '')).$town) : '');
1932  if (!empty($object->state) && in_array($object->country_code, $countriesusingstate)) {
1933  $ret .= ($ret ? ", " : '').$object->state;
1934  }
1935  }
1936  if (!is_object($outputlangs)) $outputlangs = $langs;
1937  if ($withcountry) {
1938  $langs->load("dict");
1939  $ret .= (empty($object->country_code) ? '' : ($ret ? $sep : '').$outputlangs->convToOutputCharset($outputlangs->transnoentitiesnoconv("Country".$object->country_code)));
1940  }
1941 
1942  return $ret;
1943 }
1944 
1945 
1946 
1955 function dol_strftime($fmt, $ts = false, $is_gmt = false)
1956 {
1957  if ((abs($ts) <= 0x7FFFFFFF)) { // check if number in 32-bit signed range
1958  return ($is_gmt) ? @gmstrftime($fmt, $ts) : @strftime($fmt, $ts);
1959  } else return 'Error date into a not supported range';
1960 }
1961 
1983 function dol_print_date($time, $format = '', $tzoutput = 'auto', $outputlangs = '', $encodetooutput = false)
1984 {
1985  global $conf, $langs;
1986 
1987  if ($tzoutput === 'auto') {
1988  $tzoutput = (empty($conf) ? 'tzserver' : (isset($conf->tzuserinputkey) ? $conf->tzuserinputkey : 'tzserver'));
1989  }
1990 
1991  // Clean parameters
1992  $to_gmt = false;
1993  $offsettz = $offsetdst = 0;
1994  if ($tzoutput)
1995  {
1996  $to_gmt = true; // For backward compatibility
1997  if (is_string($tzoutput))
1998  {
1999  if ($tzoutput == 'tzserver')
2000  {
2001  $to_gmt = false;
2002  $offsettzstring = @date_default_timezone_get(); // Example 'Europe/Berlin' or 'Indian/Reunion'
2003  $offsettz = 0;
2004  $offsetdst = 0;
2005  } elseif ($tzoutput == 'tzuser' || $tzoutput == 'tzuserrel')
2006  {
2007  $to_gmt = true;
2008  $offsettzstring = (empty($_SESSION['dol_tz_string']) ? 'UTC' : $_SESSION['dol_tz_string']); // Example 'Europe/Berlin' or 'Indian/Reunion'
2009  $offsettz = (empty($_SESSION['dol_tz']) ? 0 : $_SESSION['dol_tz']) * 60 * 60; // Will not be used anymore
2010  $offsetdst = (empty($_SESSION['dol_dst']) ? 0 : $_SESSION['dol_dst']) * 60 * 60; // Will not be used anymore
2011  }
2012  }
2013  }
2014  if (!is_object($outputlangs)) $outputlangs = $langs;
2015  if (!$format) $format = 'daytextshort';
2016 
2017  // Do we have to reduce the length of date (year on 2 chars) to save space.
2018  // Note: dayinputnoreduce is same than day but no reduction of year length will be done
2019  $reduceformat = (!empty($conf->dol_optimize_smallscreen) && in_array($format, array('day', 'dayhour'))) ? 1 : 0; // Test on original $format param.
2020  $format = preg_replace('/inputnoreduce/', '', $format); // so format 'dayinputnoreduce' is processed like day
2021  $formatwithoutreduce = preg_replace('/reduceformat/', '', $format);
2022  if ($formatwithoutreduce != $format) { $format = $formatwithoutreduce; $reduceformat = 1; } // so format 'dayreduceformat' is processed like day
2023 
2024  // Change predefined format into computer format. If found translation in lang file we use it, otherwise we use default.
2025  // TODO Add format daysmallyear and dayhoursmallyear
2026  if ($format == 'day') $format = ($outputlangs->trans("FormatDateShort") != "FormatDateShort" ? $outputlangs->trans("FormatDateShort") : $conf->format_date_short);
2027  elseif ($format == 'hour') $format = ($outputlangs->trans("FormatHourShort") != "FormatHourShort" ? $outputlangs->trans("FormatHourShort") : $conf->format_hour_short);
2028  elseif ($format == 'hourduration') $format = ($outputlangs->trans("FormatHourShortDuration") != "FormatHourShortDuration" ? $outputlangs->trans("FormatHourShortDuration") : $conf->format_hour_short_duration);
2029  elseif ($format == 'daytext') $format = ($outputlangs->trans("FormatDateText") != "FormatDateText" ? $outputlangs->trans("FormatDateText") : $conf->format_date_text);
2030  elseif ($format == 'daytextshort') $format = ($outputlangs->trans("FormatDateTextShort") != "FormatDateTextShort" ? $outputlangs->trans("FormatDateTextShort") : $conf->format_date_text_short);
2031  elseif ($format == 'dayhour') $format = ($outputlangs->trans("FormatDateHourShort") != "FormatDateHourShort" ? $outputlangs->trans("FormatDateHourShort") : $conf->format_date_hour_short);
2032  elseif ($format == 'dayhoursec') $format = ($outputlangs->trans("FormatDateHourSecShort") != "FormatDateHourSecShort" ? $outputlangs->trans("FormatDateHourSecShort") : $conf->format_date_hour_sec_short);
2033  elseif ($format == 'dayhourtext') $format = ($outputlangs->trans("FormatDateHourText") != "FormatDateHourText" ? $outputlangs->trans("FormatDateHourText") : $conf->format_date_hour_text);
2034  elseif ($format == 'dayhourtextshort') $format = ($outputlangs->trans("FormatDateHourTextShort") != "FormatDateHourTextShort" ? $outputlangs->trans("FormatDateHourTextShort") : $conf->format_date_hour_text_short);
2035  // Format not sensitive to language
2036  elseif ($format == 'dayhourlog') $format = '%Y%m%d%H%M%S';
2037  elseif ($format == 'dayhourldap') $format = '%Y%m%d%H%M%SZ';
2038  elseif ($format == 'dayhourxcard') $format = '%Y%m%dT%H%M%SZ';
2039  elseif ($format == 'dayxcard') $format = '%Y%m%d';
2040  elseif ($format == 'dayrfc') $format = '%Y-%m-%d'; // DATE_RFC3339
2041  elseif ($format == 'dayhourrfc') $format = '%Y-%m-%dT%H:%M:%SZ'; // DATETIME RFC3339
2042  elseif ($format == 'standard') $format = '%Y-%m-%d %H:%M:%S';
2043 
2044  if ($reduceformat)
2045  {
2046  $format = str_replace('%Y', '%y', $format);
2047  $format = str_replace('yyyy', 'yy', $format);
2048  }
2049 
2050  // If date undefined or "", we return ""
2051  if (dol_strlen($time) == 0) return ''; // $time=0 allowed (it means 01/01/1970 00:00:00)
2052 
2053  // Clean format
2054  if (preg_match('/%b/i', $format)) // There is some text to translate
2055  {
2056  // We inhibate translation to text made by strftime functions. We will use trans instead later.
2057  $format = str_replace('%b', '__b__', $format);
2058  $format = str_replace('%B', '__B__', $format);
2059  }
2060  if (preg_match('/%a/i', $format)) // There is some text to translate
2061  {
2062  // We inhibate translation to text made by strftime functions. We will use trans instead later.
2063  $format = str_replace('%a', '__a__', $format);
2064  $format = str_replace('%A', '__A__', $format);
2065  }
2066 
2067 
2068  // Analyze date
2069  $reg = array();
2070  if (preg_match('/^([0-9][0-9][0-9][0-9])([0-9][0-9])([0-9][0-9])([0-9][0-9])([0-9][0-9])([0-9][0-9])$/i', $time, $reg)) // Deprecated. Ex: 1970-01-01, 1970-01-01 01:00:00, 19700101010000
2071  {
2072  dol_print_error("Functions.lib::dol_print_date function called with a bad value from page ".$_SERVER["PHP_SELF"]);
2073  return '';
2074  } elseif (preg_match('/^([0-9]+)\-([0-9]+)\-([0-9]+) ?([0-9]+)?:?([0-9]+)?:?([0-9]+)?/i', $time, $reg)) // Still available to solve problems in extrafields of type date
2075  {
2076  // This part of code should not be used.
2077  dol_syslog("Functions.lib::dol_print_date function called with a bad value from page ".$_SERVER["PHP_SELF"], LOG_WARNING);
2078  //if (function_exists('debug_print_backtrace')) debug_print_backtrace();
2079  // Date has format 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS'
2080  $syear = (!empty($reg[1]) ? $reg[1] : '');
2081  $smonth = (!empty($reg[2]) ? $reg[2] : '');
2082  $sday = (!empty($reg[3]) ? $reg[3] : '');
2083  $shour = (!empty($reg[4]) ? $reg[4] : '');
2084  $smin = (!empty($reg[5]) ? $reg[5] : '');
2085  $ssec = (!empty($reg[6]) ? $reg[6] : '');
2086 
2087  $time = dol_mktime($shour, $smin, $ssec, $smonth, $sday, $syear, true);
2088  $ret = adodb_strftime($format, $time + $offsettz + $offsetdst, $to_gmt);
2089  } else {
2090  // Date is a timestamps
2091  if ($time < 100000000000) // Protection against bad date values
2092  {
2093  $timetouse = $time + $offsettz + $offsetdst; // TODO Replace this with function Date PHP. We also should not use anymore offsettz and offsetdst but only offsettzstring.
2094 
2095  $ret = adodb_strftime($format, $timetouse, $to_gmt);
2096  } else $ret = 'Bad value '.$time.' for date';
2097  }
2098 
2099  if (preg_match('/__b__/i', $format))
2100  {
2101  $timetouse = $time + $offsettz + $offsetdst; // TODO Replace this with function Date PHP. We also should not use anymore offsettz and offsetdst but only offsettzstring.
2102 
2103  // Here ret is string in PHP setup language (strftime was used). Now we convert to $outputlangs.
2104  $month = adodb_strftime('%m', $timetouse);
2105  $month = sprintf("%02d", $month); // $month may be return with format '06' on some installation and '6' on other, so we force it to '06'.
2106  if ($encodetooutput)
2107  {
2108  $monthtext = $outputlangs->transnoentities('Month'.$month);
2109  $monthtextshort = $outputlangs->transnoentities('MonthShort'.$month);
2110  } else {
2111  $monthtext = $outputlangs->transnoentitiesnoconv('Month'.$month);
2112  $monthtextshort = $outputlangs->transnoentitiesnoconv('MonthShort'.$month);
2113  }
2114  //print 'monthtext='.$monthtext.' monthtextshort='.$monthtextshort;
2115  $ret = str_replace('__b__', $monthtextshort, $ret);
2116  $ret = str_replace('__B__', $monthtext, $ret);
2117  //print 'x'.$outputlangs->charset_output.'-'.$ret.'x';
2118  //return $ret;
2119  }
2120  if (preg_match('/__a__/i', $format))
2121  {
2122  $timetouse = $time + $offsettz + $offsetdst; // TODO Replace this with function Date PHP. We also should not use anymore offsettz and offsetdst but only offsettzstring.
2123 
2124  $w = adodb_strftime('%w', $timetouse); // TODO Replace this with function Date PHP. We also should not use anymore offsettz and offsetdst but only offsettzstring.
2125  $dayweek = $outputlangs->transnoentitiesnoconv('Day'.$w);
2126  $ret = str_replace('__A__', $dayweek, $ret);
2127  $ret = str_replace('__a__', dol_substr($dayweek, 0, 3), $ret);
2128  }
2129 
2130  return $ret;
2131 }
2132 
2133 
2154 function dol_getdate($timestamp, $fast = false, $forcetimezone = '')
2155 {
2156  global $conf;
2157 
2158  if (empty($conf->global->MAIN_USE_OLD_FUNCTIONS_FOR_GETDATE)) {
2159  //$datetimeobj = new DateTime('@'.$timestamp);
2160  $datetimeobj = new DateTime();
2161  $datetimeobj->setTimestamp($timestamp); // Use local PHP server timezone
2162  if ($forcetimezone) $datetimeobj->setTimezone(new DateTimeZone($forcetimezone)); // (add timezone relative to the date entered)
2163  $arrayinfo = array(
2164  'year'=>((int) date_format($datetimeobj, 'Y')),
2165  'mon'=>((int) date_format($datetimeobj, 'm')),
2166  'mday'=>((int) date_format($datetimeobj, 'd')),
2167  'wday'=>((int) date_format($datetimeobj, 'w')),
2168  'yday'=>((int) date_format($datetimeobj, 'z')),
2169  'hours'=>((int) date_format($datetimeobj, 'H')),
2170  'minutes'=>((int) date_format($datetimeobj, 'i')),
2171  'seconds'=>((int) date_format($datetimeobj, 's')),
2172  '0'=>$timestamp
2173  );
2174  } else {
2175  // PHP getdate is restricted to the years 1901-2038 on Unix and 1970-2038 on Windows
2176  $usealternatemethod = false;
2177  if ($timestamp <= 0) $usealternatemethod = true; // <= 1970
2178  if ($timestamp >= 2145913200) $usealternatemethod = true; // >= 2038
2179 
2180  if ($usealternatemethod)
2181  {
2182  $arrayinfo = adodb_getdate($timestamp, $fast);
2183  } else {
2184  $arrayinfo = getdate($timestamp);
2185  }
2186  }
2187 
2188  return $arrayinfo;
2189 }
2190 
2212 function dol_mktime($hour, $minute, $second, $month, $day, $year, $gm = 'auto', $check = 1)
2213 {
2214  global $conf;
2215  //print "- ".$hour.",".$minute.",".$second.",".$month.",".$day.",".$year.",".$_SERVER["WINDIR"]." -";
2216  //print 'gm:'.$gm.' gm==auto:'.($gm == 'auto').'<br>';
2217 
2218  if ($gm === 'auto') {
2219  $gm = (empty($conf) ? 'tzserver' : $conf->tzuserinputkey);
2220  }
2221 
2222  // Clean parameters
2223  if ($hour == -1 || empty($hour)) $hour = 0;
2224  if ($minute == -1 || empty($minute)) $minute = 0;
2225  if ($second == -1 || empty($second)) $second = 0;
2226 
2227  // Check parameters
2228  if ($check)
2229  {
2230  if (!$month || !$day) return '';
2231  if ($day > 31) return '';
2232  if ($month > 12) return '';
2233  if ($hour < 0 || $hour > 24) return '';
2234  if ($minute < 0 || $minute > 60) return '';
2235  if ($second < 0 || $second > 60) return '';
2236  }
2237 
2238  if (empty($gm) || ($gm === 'server' || $gm === 'tzserver'))
2239  {
2240  $default_timezone = @date_default_timezone_get(); // Example 'Europe/Berlin'
2241  $localtz = new DateTimeZone($default_timezone);
2242  } elseif ($gm === 'user' || $gm === 'tzuser' || $gm === 'tzuserrel')
2243  {
2244  // We use dol_tz_string first because it is more reliable.
2245  $default_timezone = (empty($_SESSION["dol_tz_string"]) ? @date_default_timezone_get() : $_SESSION["dol_tz_string"]); // Example 'Europe/Berlin'
2246  try {
2247  $localtz = new DateTimeZone($default_timezone);
2248  } catch (Exception $e)
2249  {
2250  dol_syslog("Warning dol_tz_string contains an invalid value ".$_SESSION["dol_tz_string"], LOG_WARNING);
2251  $default_timezone = @date_default_timezone_get();
2252  }
2253  } elseif (strrpos($gm, "tz,") !== false)
2254  {
2255  $timezone = str_replace("tz,", "", $gm); // Example 'tz,Europe/Berlin'
2256  try {
2257  $localtz = new DateTimeZone($timezone);
2258  } catch (Exception $e)
2259  {
2260  dol_syslog("Warning passed timezone contains an invalid value ".$timezone, LOG_WARNING);
2261  }
2262  }
2263 
2264  if (empty($localtz)) {
2265  $localtz = new DateTimeZone('UTC');
2266  }
2267  //var_dump($localtz);
2268  //var_dump($year.'-'.$month.'-'.$day.'-'.$hour.'-'.$minute);
2269  $dt = new DateTime(null, $localtz);
2270  $dt->setDate((int) $year, (int) $month, (int) $day);
2271  $dt->setTime((int) $hour, (int) $minute, (int) $second);
2272  $date = $dt->getTimestamp(); // should include daylight saving time
2273  //var_dump($date);
2274  return $date;
2275 }
2276 
2277 
2288 function dol_now($mode = 'auto')
2289 {
2290  $ret = 0;
2291 
2292  if ($mode === 'auto') {
2293  $mode = 'gmt';
2294  }
2295 
2296  if ($mode == 'gmt') $ret = time(); // Time for now at greenwich.
2297  elseif ($mode == 'tzserver') // Time for now with PHP server timezone added
2298  {
2299  require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
2300  $tzsecond = getServerTimeZoneInt('now'); // Contains tz+dayling saving time
2301  $ret = (int) (dol_now('gmt') + ($tzsecond * 3600));
2302  } /*elseif ($mode == 'tzref') // Time for now with parent company timezone is added
2303  {
2304  require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
2305  $tzsecond=getParentCompanyTimeZoneInt(); // Contains tz+dayling saving time
2306  $ret=dol_now('gmt')+($tzsecond*3600);
2307  }*/
2308  elseif ($mode == 'tzuser' || $mode == 'tzuserrel') // Time for now with user timezone added
2309  {
2310  //print 'time: '.time();
2311  $offsettz = (empty($_SESSION['dol_tz']) ? 0 : $_SESSION['dol_tz']) * 60 * 60;
2312  $offsetdst = (empty($_SESSION['dol_dst']) ? 0 : $_SESSION['dol_dst']) * 60 * 60;
2313  $ret = (int) (dol_now('gmt') + ($offsettz + $offsetdst));
2314  }
2315 
2316  return $ret;
2317 }
2318 
2319 
2328 function dol_print_size($size, $shortvalue = 0, $shortunit = 0)
2329 {
2330  global $conf, $langs;
2331  $level = 1024;
2332 
2333  if (!empty($conf->dol_optimize_smallscreen)) $shortunit = 1;
2334 
2335  // Set value text
2336  if (empty($shortvalue) || $size < ($level * 10))
2337  {
2338  $ret = $size;
2339  $textunitshort = $langs->trans("b");
2340  $textunitlong = $langs->trans("Bytes");
2341  } else {
2342  $ret = round($size / $level, 0);
2343  $textunitshort = $langs->trans("Kb");
2344  $textunitlong = $langs->trans("KiloBytes");
2345  }
2346  // Use long or short text unit
2347  if (empty($shortunit)) { $ret .= ' '.$textunitlong; } else { $ret .= ' '.$textunitshort; }
2348 
2349  return $ret;
2350 }
2351 
2361 function dol_print_url($url, $target = '_blank', $max = 32, $withpicto = 0)
2362 {
2363  global $langs;
2364 
2365  if (empty($url)) return '';
2366 
2367  $link = '<a href="';
2368  if (!preg_match('/^http/i', $url)) $link .= 'http://';
2369  $link .= $url;
2370  $link .= '"';
2371  if ($target) $link .= ' target="'.$target.'"';
2372  $link .= '>';
2373  if (!preg_match('/^http/i', $url)) $link .= 'http://';
2374  $link .= dol_trunc($url, $max);
2375  $link .= '</a>';
2376  return '<div class="nospan float" style="margin-right: 10px">'.($withpicto ?img_picto($langs->trans("Url"), 'globe').' ' : '').$link.'</div>';
2377 }
2378 
2391 function dol_print_email($email, $cid = 0, $socid = 0, $addlink = 0, $max = 64, $showinvalid = 1, $withpicto = 0)
2392 {
2393  global $conf, $user, $langs, $hookmanager;
2394 
2395  $newemail = dol_escape_htmltag($email);
2396 
2397  if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER) && $withpicto) $withpicto = 0;
2398 
2399  if (empty($email)) return '&nbsp;';
2400 
2401  if (!empty($addlink))
2402  {
2403  $newemail = '<a style="text-overflow: ellipsis;" href="';
2404  if (!preg_match('/^mailto:/i', $email)) $newemail .= 'mailto:';
2405  $newemail .= $email;
2406  $newemail .= '">';
2407  $newemail .= dol_trunc($email, $max);
2408  $newemail .= '</a>';
2409  if ($showinvalid && !isValidEmail($email))
2410  {
2411  $langs->load("errors");
2412  $newemail .= img_warning($langs->trans("ErrorBadEMail", $email));
2413  }
2414 
2415  if (($cid || $socid) && !empty($conf->agenda->enabled) && $user->rights->agenda->myactions->create)
2416  {
2417  $type = 'AC_EMAIL'; $link = '';
2418  if (!empty($conf->global->AGENDA_ADDACTIONFOREMAIL)) $link = '<a href="'.DOL_URL_ROOT.'/comm/action/card.php?action=create&amp;backtopage=1&amp;actioncode='.$type.'&amp;contactid='.$cid.'&amp;socid='.$socid.'">'.img_object($langs->trans("AddAction"), "calendar").'</a>';
2419  if ($link) $newemail = '<div>'.$newemail.' '.$link.'</div>';
2420  }
2421  } else {
2422  if ($showinvalid && !isValidEmail($email))
2423  {
2424  $langs->load("errors");
2425  $newemail .= img_warning($langs->trans("ErrorBadEMail", $email));
2426  }
2427  }
2428 
2429  //$rep = '<div class="nospan" style="margin-right: 10px">';
2430  $rep = ($withpicto ? img_picto($langs->trans("EMail").' : '.$email, 'object_email.png').' ' : '').$newemail;
2431  //$rep .= '</div>';
2432  if ($hookmanager) {
2433  $parameters = array('cid' => $cid, 'socid' => $socid, 'addlink' => $addlink, 'picto' => $withpicto);
2434  $reshook = $hookmanager->executeHooks('printEmail', $parameters, $email);
2435  if ($reshook > 0) {
2436  $rep = '';
2437  }
2438  $rep .= $hookmanager->resPrint;
2439  }
2440 
2441  return $rep;
2442 }
2443 
2450 {
2451  global $conf, $db;
2452  $sql = "SELECT rowid, code, label, url, icon, active FROM ".MAIN_DB_PREFIX."c_socialnetworks";
2453  $sql .= " WHERE entity=".$conf->entity;
2454  $socialnetworks = array();
2455  $resql = $db->query($sql);
2456  if ($resql) {
2457  while ($obj = $db->fetch_object($resql)) {
2458  $socialnetworks[$obj->code] = array(
2459  'rowid' => $obj->rowid,
2460  'label' => $obj->label,
2461  'url' => $obj->url,
2462  'icon' => $obj->icon,
2463  'active' => $obj->active,
2464  );
2465  }
2466  }
2467  return $socialnetworks;
2468 }
2469 
2480 function dol_print_socialnetworks($value, $cid, $socid, $type, $dictsocialnetworks = array())
2481 {
2482  global $conf, $user, $langs;
2483 
2484  $htmllink = $value;
2485 
2486  if (empty($value)) return '&nbsp;';
2487 
2488  if (!empty($type)) {
2489  $htmllink = '<div class="divsocialnetwork inline-block valignmiddle">';
2490  // TODO use dictionary definition for picto $dictsocialnetworks[$type]['icon']
2491  $htmllink .= img_picto($langs->trans(dol_ucfirst($type)), $type.'.png', '', false, 0, 0, '', 'paddingright', 0);
2492  if ($type == 'skype') {
2493  $htmllink .= $value;
2494  $htmllink .= '&nbsp;';
2495  $htmllink .= '<a href="skype:';
2496  $htmllink .= $value;
2497  $htmllink .= '?call" alt="'.$langs->trans("Call").'&nbsp;'.$value.'" title="'.$langs->trans("Call").'&nbsp;'.$value.'">';
2498  $htmllink .= '<img src="'.DOL_URL_ROOT.'/theme/common/skype_callbutton.png" border="0">';
2499  $htmllink .= '</a><a href="skype:';
2500  $htmllink .= $value;
2501  $htmllink .= '?chat" alt="'.$langs->trans("Chat").'&nbsp;'.$value.'" title="'.$langs->trans("Chat").'&nbsp;'.$value.'">';
2502  $htmllink .= '<img class="paddingleft" src="'.DOL_URL_ROOT.'/theme/common/skype_chatbutton.png" border="0">';
2503  $htmllink .= '</a>';
2504  if (($cid || $socid) && !empty($conf->agenda->enabled) && $user->rights->agenda->myactions->create) {
2505  $addlink = 'AC_SKYPE';
2506  $link = '';
2507  if (!empty($conf->global->AGENDA_ADDACTIONFORSKYPE)) $link = '<a href="'.DOL_URL_ROOT.'/comm/action/card.php?action=create&amp;backtopage=1&amp;actioncode='.$addlink.'&amp;contactid='.$cid.'&amp;socid='.$socid.'">'.img_object($langs->trans("AddAction"), "calendar").'</a>';
2508  $htmllink .= ($link ? ' '.$link : '');
2509  }
2510  } else {
2511  if (!empty($dictsocialnetworks[$type]['url'])) {
2512  $link = str_replace('{socialid}', $value, $dictsocialnetworks[$type]['url']);
2513  $htmllink .= '&nbsp;<a href="'.$link.'" target="_blank">'.$value.'</a>';
2514  } else {
2515  $htmllink .= $value;
2516  }
2517  }
2518  $htmllink .= '</div>';
2519  } else {
2520  $langs->load("errors");
2521  $htmllink .= img_warning($langs->trans("ErrorBadSocialNetworkValue", $value));
2522  }
2523  return $htmllink;
2524 }
2525 
2540 function dol_print_phone($phone, $countrycode = '', $cid = 0, $socid = 0, $addlink = '', $separ = "&nbsp;", $withpicto = '', $titlealt = '', $adddivfloat = 0)
2541 {
2542  global $conf, $user, $langs, $mysoc, $hookmanager;
2543 
2544  // Clean phone parameter
2545  $phone = preg_replace("/[\s.-]/", "", trim($phone));
2546  if (empty($phone)) { return ''; }
2547  if (!empty($conf->global->MAIN_PHONE_SEPAR)) $separ = $conf->global->MAIN_PHONE_SEPAR;
2548  if (empty($countrycode)) $countrycode = $mysoc->country_code;
2549 
2550  // Short format for small screens
2551  if ($conf->dol_optimize_smallscreen) $separ = '';
2552 
2553  $newphone = $phone;
2554  if (strtoupper($countrycode) == "FR")
2555  {
2556  // France
2557  if (dol_strlen($phone) == 10) {
2558  $newphone = substr($newphone, 0, 2).$separ.substr($newphone, 2, 2).$separ.substr($newphone, 4, 2).$separ.substr($newphone, 6, 2).$separ.substr($newphone, 8, 2);
2559  } elseif (dol_strlen($phone) == 7)
2560  {
2561  $newphone = substr($newphone, 0, 3).$separ.substr($newphone, 3, 2).$separ.substr($newphone, 5, 2);
2562  } elseif (dol_strlen($phone) == 9)
2563  {
2564  $newphone = substr($newphone, 0, 2).$separ.substr($newphone, 2, 3).$separ.substr($newphone, 5, 2).$separ.substr($newphone, 7, 2);
2565  } elseif (dol_strlen($phone) == 11)
2566  {
2567  $newphone = substr($newphone, 0, 3).$separ.substr($newphone, 3, 2).$separ.substr($newphone, 5, 2).$separ.substr($newphone, 7, 2).$separ.substr($newphone, 9, 2);
2568  } elseif (dol_strlen($phone) == 12)
2569  {
2570  $newphone = substr($newphone, 0, 4).$separ.substr($newphone, 4, 2).$separ.substr($newphone, 6, 2).$separ.substr($newphone, 8, 2).$separ.substr($newphone, 10, 2);
2571  }
2572  } elseif (strtoupper($countrycode) == "CA")
2573  {
2574  if (dol_strlen($phone) == 10) {
2575  $newphone = ($separ != '' ? '(' : '').substr($newphone, 0, 3).($separ != '' ? ')' : '').$separ.substr($newphone, 3, 3).($separ != '' ? '-' : '').substr($newphone, 6, 4);
2576  }
2577  } elseif (strtoupper($countrycode) == "PT")
2578  {//Portugal
2579  if (dol_strlen($phone) == 13)
2580  {//ex: +351_ABC_DEF_GHI
2581  $newphone = substr($newphone, 0, 4).$separ.substr($newphone, 4, 3).$separ.substr($newphone, 7, 3).$separ.substr($newphone, 10, 3);
2582  }
2583  } elseif (strtoupper($countrycode) == "SR")
2584  {//Suriname
2585  if (dol_strlen($phone) == 10)
2586  {//ex: +597_ABC_DEF
2587  $newphone = substr($newphone, 0, 4).$separ.substr($newphone, 4, 3).$separ.substr($newphone, 7, 3);
2588  } elseif (dol_strlen($phone) == 11)
2589  {//ex: +597_ABC_DEFG
2590  $newphone = substr($newphone, 0, 4).$separ.substr($newphone, 4, 3).$separ.substr($newphone, 7, 4);
2591  }
2592  } elseif (strtoupper($countrycode) == "DE")
2593  {//Allemagne
2594  if (dol_strlen($phone) == 14)
2595  {//ex: +49_ABCD_EFGH_IJK
2596  $newphone = substr($newphone, 0, 3).$separ.substr($newphone, 3, 4).$separ.substr($newphone, 7, 4).$separ.substr($newphone, 11, 3);
2597  } elseif (dol_strlen($phone) == 13)
2598  {//ex: +49_ABC_DEFG_HIJ
2599  $newphone = substr($newphone, 0, 3).$separ.substr($newphone, 3, 3).$separ.substr($newphone, 6, 4).$separ.substr($newphone, 10, 3);
2600  }
2601  } elseif (strtoupper($countrycode) == "ES")
2602  {//Espagne
2603  if (dol_strlen($phone) == 12)
2604  {//ex: +34_ABC_DEF_GHI
2605  $newphone = substr($newphone, 0, 3).$separ.substr($newphone, 3, 3).$separ.substr($newphone, 6, 3).$separ.substr($newphone, 9, 3);
2606  }
2607  } elseif (strtoupper($countrycode) == "BF")
2608  {// Burkina Faso
2609  if (dol_strlen($phone) == 12)
2610  {//ex : +22 A BC_DE_FG_HI
2611  $newphone = substr($newphone, 0, 3).$separ.substr($newphone, 3, 1).$separ.substr($newphone, 4, 2).$separ.substr($newphone, 6, 2).$separ.substr($newphone, 8, 2).$separ.substr($newphone, 10, 2);
2612  }
2613  } elseif (strtoupper($countrycode) == "RO")
2614  {// Roumanie
2615  if (dol_strlen($phone) == 12)
2616  {//ex : +40 AB_CDE_FG_HI
2617  $newphone = substr($newphone, 0, 3).$separ.substr($newphone, 3, 2).$separ.substr($newphone, 5, 3).$separ.substr($newphone, 8, 2).$separ.substr($newphone, 10, 2);
2618  }
2619  } elseif (strtoupper($countrycode) == "TR")
2620  {//Turquie
2621  if (dol_strlen($phone) == 13)
2622  {//ex : +90 ABC_DEF_GHIJ
2623  $newphone = substr($newphone, 0, 3).$separ.substr($newphone, 3, 3).$separ.substr($newphone, 6, 3).$separ.substr($newphone, 9, 4);
2624  }
2625  } elseif (strtoupper($countrycode) == "US")
2626  {//Etat-Unis
2627  if (dol_strlen($phone) == 12)
2628  {//ex: +1 ABC_DEF_GHIJ
2629  $newphone = substr($newphone, 0, 2).$separ.substr($newphone, 2, 3).$separ.substr($newphone, 5, 3).$separ.substr($newphone, 8, 4);
2630  }
2631  } elseif (strtoupper($countrycode) == "MX")
2632  {//Mexique
2633  if (dol_strlen($phone) == 12)
2634  {//ex: +52 ABCD_EFG_HI
2635  $newphone = substr($newphone, 0, 3).$separ.substr($newphone, 3, 4).$separ.substr($newphone, 7, 3).$separ.substr($newphone, 10, 2);
2636  } elseif (dol_strlen($phone) == 11)
2637  {//ex: +52 AB_CD_EF_GH
2638  $newphone = substr($newphone, 0, 3).$separ.substr($newphone, 3, 2).$separ.substr($newphone, 5, 2).$separ.substr($newphone, 7, 2).$separ.substr($newphone, 9, 2);
2639  } elseif (dol_strlen($phone) == 13)
2640  {//ex: +52 ABC_DEF_GHIJ
2641  $newphone = substr($newphone, 0, 3).$separ.substr($newphone, 3, 3).$separ.substr($newphone, 6, 3).$separ.substr($newphone, 9, 4);
2642  }
2643  } elseif (strtoupper($countrycode) == "ML")
2644  {//Mali
2645  if (dol_strlen($phone) == 12)
2646  {//ex: +223 AB_CD_EF_GH
2647  $newphone = substr($newphone, 0, 4).$separ.substr($newphone, 4, 2).$separ.substr($newphone, 6, 2).$separ.substr($newphone, 8, 2).$separ.substr($newphone, 10, 2);
2648  }
2649  } elseif (strtoupper($countrycode) == "TH")
2650  {//Thaïlande
2651  if (dol_strlen($phone) == 11)
2652  {//ex: +66_ABC_DE_FGH
2653  $newphone = substr($newphone, 0, 3).$separ.substr($newphone, 3, 3).$separ.substr($newphone, 6, 2).$separ.substr($newphone, 8, 3);
2654  } elseif (dol_strlen($phone) == 12)
2655  {//ex: +66_A_BCD_EF_GHI
2656  $newphone = substr($newphone, 0, 3).$separ.substr($newphone, 3, 1).$separ.substr($newphone, 4, 3).$separ.substr($newphone, 7, 2).$separ.substr($newphone, 9, 3);
2657  }
2658  } elseif (strtoupper($countrycode) == "MU")
2659  {
2660  //Maurice
2661  if (dol_strlen($phone) == 11)
2662  {//ex: +230_ABC_DE_FG
2663  $newphone = substr($newphone, 0, 4).$separ.substr($newphone, 4, 3).$separ.substr($newphone, 7, 2).$separ.substr($newphone, 9, 2);
2664  } elseif (dol_strlen($phone) == 12)
2665  {//ex: +230_ABCD_EF_GH
2666  $newphone = substr($newphone, 0, 4).$separ.substr($newphone, 4, 4).$separ.substr($newphone, 8, 2).$separ.substr($newphone, 10, 2);
2667  }
2668  } elseif (strtoupper($countrycode) == "ZA")
2669  {//Afrique du sud
2670  if (dol_strlen($phone) == 12)
2671  {//ex: +27_AB_CDE_FG_HI
2672  $newphone = substr($newphone, 0, 3).$separ.substr($newphone, 3, 2).$separ.substr($newphone, 5, 3).$separ.substr($newphone, 8, 2).$separ.substr($newphone, 10, 2);
2673  }
2674  } elseif (strtoupper($countrycode) == "SY")
2675  {//Syrie
2676  if (dol_strlen($phone) == 12)
2677  {//ex: +963_AB_CD_EF_GH
2678  $newphone = substr($newphone, 0, 4).$separ.substr($newphone, 4, 2).$separ.substr($newphone, 6, 2).$separ.substr($newphone, 8, 2).$separ.substr($newphone, 10, 2);
2679  } elseif (dol_strlen($phone) == 13)
2680  {//ex: +963_AB_CD_EF_GHI
2681  $newphone = substr($newphone, 0, 4).$separ.substr($newphone, 4, 2).$separ.substr($newphone, 6, 2).$separ.substr($newphone, 8, 2).$separ.substr($newphone, 10, 3);
2682  }
2683  } elseif (strtoupper($countrycode) == "AE")
2684  {//Emirats Arabes Unis
2685  if (dol_strlen($phone) == 12)
2686  {//ex: +971_ABC_DEF_GH
2687  $newphone = substr($newphone, 0, 4).$separ.substr($newphone, 4, 3).$separ.substr($newphone, 7, 3).$separ.substr($newphone, 10, 2);
2688  } elseif (dol_strlen($phone) == 13)
2689  {//ex: +971_ABC_DEF_GHI
2690  $newphone = substr($newphone, 0, 4).$separ.substr($newphone, 4, 3).$separ.substr($newphone, 7, 3).$separ.substr($newphone, 10, 3);
2691  } elseif (dol_strlen($phone) == 14)
2692  {//ex: +971_ABC_DEF_GHIK
2693  $newphone = substr($newphone, 0, 4).$separ.substr($newphone, 4, 3).$separ.substr($newphone, 7, 3).$separ.substr($newphone, 10, 4);
2694  }
2695  } elseif (strtoupper($countrycode) == "DZ")
2696  {//Algérie
2697  if (dol_strlen($phone) == 13)
2698  {//ex: +213_ABC_DEF_GHI
2699  $newphone = substr($newphone, 0, 4).$separ.substr($newphone, 4, 3).$separ.substr($newphone, 7, 3).$separ.substr($newphone, 10, 3);
2700  }
2701  } elseif (strtoupper($countrycode) == "BE")
2702  {//Belgique
2703  if (dol_strlen($phone) == 11)
2704  {//ex: +32_ABC_DE_FGH
2705  $newphone = substr($newphone, 0, 3).$separ.substr($newphone, 3, 3).$separ.substr($newphone, 6, 2).$separ.substr($newphone, 8, 3);
2706  } elseif (dol_strlen($phone) == 12)
2707  {//ex: +32_ABC_DEF_GHI
2708  $newphone = substr($newphone, 0, 3).$separ.substr($newphone, 3, 3).$separ.substr($newphone, 6, 3).$separ.substr($newphone, 9, 3);
2709  }
2710  } elseif (strtoupper($countrycode) == "PF")
2711  {//Polynésie française
2712  if (dol_strlen($phone) == 12)
2713  {//ex: +689_AB_CD_EF_GH
2714  $newphone = substr($newphone, 0, 4).$separ.substr($newphone, 4, 2).$separ.substr($newphone, 6, 2).$separ.substr($newphone, 8, 2).$separ.substr($newphone, 10, 2);
2715  }
2716  } elseif (strtoupper($countrycode) == "CO")
2717  {//Colombie
2718  if (dol_strlen($phone) == 13)
2719  {//ex: +57_ABC_DEF_GH_IJ
2720  $newphone = substr($newphone, 0, 3).$separ.substr($newphone, 3, 3).$separ.substr($newphone, 6, 3).$separ.substr($newphone, 9, 2).$separ.substr($newphone, 11, 2);
2721  }
2722  } elseif (strtoupper($countrycode) == "JO")
2723  {//Jordanie
2724  if (dol_strlen($phone) == 12)
2725  {//ex: +962_A_BCD_EF_GH
2726  $newphone = substr($newphone, 0, 4).$separ.substr($newphone, 4, 1).$separ.substr($newphone, 5, 3).$separ.substr($newphone, 7, 2).$separ.substr($newphone, 9, 2);
2727  }
2728  } elseif (strtoupper($countrycode) == "JM")
2729  {//Jamaïque
2730  if (dol_strlen($newphone) == 12)
2731  {//ex: +1867_ABC_DEFG
2732  $newphone = substr($newphone, 0, 5).$separ.substr($newphone, 5, 3).$separ.substr($newphone, 8, 4);
2733  }
2734  } elseif (strtoupper($countrycode) == "MG")
2735  {//Madagascar
2736  if (dol_strlen($phone) == 13)
2737  {//ex: +261_AB_CD_EF_GHI
2738  $newphone = substr($newphone, 0, 4).$separ.substr($newphone, 4, 2).$separ.substr($newphone, 6, 2).$separ.substr($newphone, 8, 2).$separ.substr($newphone, 10, 3);
2739  }
2740  } elseif (strtoupper($countrycode) == "GB")
2741  {//Royaume uni
2742  if (dol_strlen($phone) == 13)
2743  {//ex: +44_ABCD_EFG_HIJ
2744  $newphone = substr($newphone, 0, 3).$separ.substr($newphone, 3, 4).$separ.substr($newphone, 7, 3).$separ.substr($newphone, 10, 3);
2745  }
2746  } elseif (strtoupper($countrycode) == "CH")
2747  {//Suisse
2748  if (dol_strlen($phone) == 12)
2749  {//ex: +41_AB_CDE_FG_HI
2750  $newphone = substr($newphone, 0, 3).$separ.substr($newphone, 3, 2).$separ.substr($newphone, 5, 3).$separ.substr($newphone, 8, 2).$separ.substr($newphone, 10, 2);
2751  } elseif (dol_strlen($phone) == 15)
2752  {// +41_AB_CDE_FGH_IJKL
2753  $newphone = $newphone = substr($newphone, 0, 3).$separ.substr($newphone, 3, 2).$separ.substr($newphone, 5, 3).$separ.substr($newphone, 8, 3).$separ.substr($newphone, 11, 4);
2754  }
2755  } elseif (strtoupper($countrycode) == "TN")
2756  {//Tunisie
2757  if (dol_strlen($phone) == 12)
2758  {//ex: +216_AB_CDE_FGH
2759  $newphone = substr($newphone, 0, 4).$separ.substr($newphone, 4, 2).$separ.substr($newphone, 6, 3).$separ.substr($newphone, 9, 3);
2760  }
2761  } elseif (strtoupper($countrycode) == "GF")
2762  {//Guyane francaise
2763  if (dol_strlen($phone) == 13)
2764  {//ex: +594_ABC_DE_FG_HI (ABC=594 de nouveau)
2765  $newphone = substr($newphone, 0, 4).$separ.substr($newphone, 4, 3).$separ.substr($newphone, 7, 2).$separ.substr($newphone, 9, 2).$separ.substr($newphone, 11, 2);
2766  }
2767  } elseif (strtoupper($countrycode) == "GP")
2768  {//Guadeloupe
2769  if (dol_strlen($phone) == 13)
2770  {//ex: +590_ABC_DE_FG_HI (ABC=590 de nouveau)
2771  $newphone = substr($newphone, 0, 4).$separ.substr($newphone, 4, 3).$separ.substr($newphone, 7, 2).$separ.substr($newphone, 9, 2).$separ.substr($newphone, 11, 2);
2772  }
2773  } elseif (strtoupper($countrycode) == "MQ")
2774  {//Martinique
2775  if (dol_strlen($phone) == 13)
2776  {//ex: +596_ABC_DE_FG_HI (ABC=596 de nouveau)
2777  $newphone = substr($newphone, 0, 4).$separ.substr($newphone, 4, 3).$separ.substr($newphone, 7, 2).$separ.substr($newphone, 9, 2).$separ.substr($newphone, 11, 2);
2778  }
2779  } elseif (strtoupper($countrycode) == "IT")
2780  {//Italie
2781  if (dol_strlen($phone) == 12)
2782  {//ex: +39_ABC_DEF_GHI
2783  $newphone = substr($newphone, 0, 3).$separ.substr($newphone, 3, 3).$separ.substr($newphone, 6, 3).$separ.substr($newphone, 9, 3);
2784  } elseif (dol_strlen($phone) == 13)
2785  {//ex: +39_ABC_DEF_GH_IJ
2786  $newphone = substr($newphone, 0, 3).$separ.substr($newphone, 3, 3).$separ.substr($newphone, 6, 3).$separ.substr($newphone, 9, 2).$separ.substr($newphone, 11, 2);
2787  }
2788  } elseif (strtoupper($countrycode) == "AU")
2789  {
2790  //Australie
2791  if (dol_strlen($phone) == 12)
2792  {
2793  //ex: +61_A_BCDE_FGHI
2794  $newphone = substr($newphone, 0, 3).$separ.substr($newphone, 3, 1).$separ.substr($newphone, 4, 4).$separ.substr($newphone, 8, 4);
2795  }
2796  }
2797  if (!empty($addlink)) // Link on phone number (+ link to add action if conf->global->AGENDA_ADDACTIONFORPHONE set)
2798  {
2799  if ($conf->browser->layout == 'phone' || (!empty($conf->clicktodial->enabled) && !empty($conf->global->CLICKTODIAL_USE_TEL_LINK_ON_PHONE_NUMBERS))) // If phone or option for, we use link of phone
2800  {
2801  $newphoneform = $newphone;
2802  $newphone = '<a href="tel:'.$phone.'"';
2803  $newphone .= '>'.$newphoneform.'</a>';
2804  } elseif (!empty($conf->clicktodial->enabled) && $addlink == 'AC_TEL') // If click to dial, we use click to dial url
2805  {
2806  if (empty($user->clicktodial_loaded)) $user->fetch_clicktodial();
2807 
2808  // Define urlmask
2809  $urlmask = 'ErrorClickToDialModuleNotConfigured';
2810  if (!empty($conf->global->CLICKTODIAL_URL)) $urlmask = $conf->global->CLICKTODIAL_URL;
2811  if (!empty($user->clicktodial_url)) $urlmask = $user->clicktodial_url;
2812 
2813  $clicktodial_poste = (!empty($user->clicktodial_poste) ?urlencode($user->clicktodial_poste) : '');
2814  $clicktodial_login = (!empty($user->clicktodial_login) ?urlencode($user->clicktodial_login) : '');
2815  $clicktodial_password = (!empty($user->clicktodial_password) ?urlencode($user->clicktodial_password) : '');
2816  // This line is for backward compatibility
2817  $url = sprintf($urlmask, urlencode($phone), $clicktodial_poste, $clicktodial_login, $clicktodial_password);
2818  // Thoose lines are for substitution
2819  $substitarray = array('__PHONEFROM__'=>$clicktodial_poste,
2820  '__PHONETO__'=>urlencode($phone),
2821  '__LOGIN__'=>$clicktodial_login,
2822  '__PASS__'=>$clicktodial_password);
2823  $url = make_substitutions($url, $substitarray);
2824  $newphonesav = $newphone;
2825  $newphone = '<a href="'.$url.'"';
2826  if (!empty($conf->global->CLICKTODIAL_FORCENEWTARGET)) $newphone .= ' target="_blank"';
2827  $newphone .= '>'.$newphonesav.'</a>';
2828  }
2829 
2830  //if (($cid || $socid) && ! empty($conf->agenda->enabled) && $user->rights->agenda->myactions->create)
2831  if (!empty($conf->agenda->enabled) && $user->rights->agenda->myactions->create)
2832  {
2833  $type = 'AC_TEL'; $link = '';
2834  if ($addlink == 'AC_FAX') $type = 'AC_FAX';
2835  if (!empty($conf->global->AGENDA_ADDACTIONFORPHONE)) $link = '<a href="'.DOL_URL_ROOT.'/comm/action/card.php?action=create&amp;backtopage=1&amp;actioncode='.$type.($cid ? '&amp;contactid='.$cid : '').($socid ? '&amp;socid='.$socid : '').'">'.img_object($langs->trans("AddAction"), "calendar").'</a>';
2836  if ($link) $newphone = '<div>'.$newphone.' '.$link.'</div>';
2837  }
2838  }
2839 
2840  if (empty($titlealt))
2841  {
2842  $titlealt = ($withpicto == 'fax' ? $langs->trans("Fax") : $langs->trans("Phone"));
2843  }
2844  $rep = '';
2845 
2846  if ($hookmanager) {
2847  $parameters = array('countrycode' => $countrycode, 'cid' => $cid, 'socid' => $socid, 'titlealt' => $titlealt, 'picto' => $withpicto);
2848  $reshook = $hookmanager->executeHooks('printPhone', $parameters, $phone);
2849  $rep .= $hookmanager->resPrint;
2850  }
2851  if (empty($reshook))
2852  {
2853  $picto = '';
2854  if ($withpicto) {
2855  if ($withpicto == 'fax') {
2856  $picto = 'phoning_fax';
2857  } elseif ($withpicto == 'phone') {
2858  $picto = 'phoning';
2859  } elseif ($withpicto == 'mobile') {
2860  $picto = 'phoning_mobile';
2861  } else {
2862  $picto = '';
2863  }
2864  }
2865  if ($adddivfloat) $rep .= '<div class="nospan float" style="margin-right: 10px">';
2866  else $rep .= '<span style="margin-right: 10px;">';
2867  $rep .= ($withpicto ?img_picto($titlealt, 'object_'.$picto.'.png').' ' : '').$newphone;
2868  if ($adddivfloat) $rep .= '</div>';
2869  else $rep .= '</span>';
2870  }
2871 
2872  return $rep;
2873 }
2874 
2882 function dol_print_ip($ip, $mode = 0)
2883 {
2884  global $conf, $langs;
2885 
2886  $ret = '';
2887 
2888  if (empty($mode)) $ret .= $ip;
2889 
2890  if ($mode != 2)
2891  {
2892  $countrycode = dolGetCountryCodeFromIp($ip);
2893  if ($countrycode) // If success, countrycode is us, fr, ...
2894  {
2895  if (file_exists(DOL_DOCUMENT_ROOT.'/theme/common/flags/'.$countrycode.'.png'))
2896  {
2897  $ret .= ' '.img_picto($countrycode.' '.$langs->trans("AccordingToGeoIPDatabase"), DOL_URL_ROOT.'/theme/common/flags/'.$countrycode.'.png', '', 1);
2898  } else $ret .= ' ('.$countrycode.')';
2899  } else {
2900  // Nothing
2901  }
2902  }
2903 
2904  return $ret;
2905 }
2906 
2916 {
2917  if (empty($_SERVER['HTTP_X_FORWARDED_FOR']) || preg_match('/[^0-9\.\:,\[\]]/', $_SERVER['HTTP_X_FORWARDED_FOR'])) {
2918  if (empty($_SERVER['HTTP_CLIENT_IP']) || preg_match('/[^0-9\.\:,\[\]]/', $_SERVER['HTTP_CLIENT_IP'])) {
2919  if (empty($_SERVER["HTTP_CF_CONNECTING_IP"])) {
2920  $ip = (empty($_SERVER['REMOTE_ADDR']) ? '' : $_SERVER['REMOTE_ADDR']); // value may have been forged by client
2921  } else {
2922  $ip = $_SERVER["HTTP_CF_CONNECTING_IP"]; // value here may have been forged by client
2923  }
2924  } else {
2925  $ip = $_SERVER['HTTP_CLIENT_IP']; // value is clean here but may have been forged by proxy
2926  }
2927  } else {
2928  $ip = $_SERVER['HTTP_X_FORWARDED_FOR']; // value is clean here but may have been forged by proxy
2929  }
2930  return $ip;
2931 }
2932 
2941 function isHTTPS()
2942 {
2943  $isSecure = false;
2944  if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') {
2945  $isSecure = true;
2946  }
2947  elseif (!empty($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https' || !empty($_SERVER['HTTP_X_FORWARDED_SSL']) && $_SERVER['HTTP_X_FORWARDED_SSL'] == 'on') {
2948  $isSecure = true;
2949  }
2950  return $isSecure;
2951 }
2952 
2960 {
2961  global $conf;
2962 
2963  $countrycode = '';
2964 
2965  if (!empty($conf->geoipmaxmind->enabled))
2966  {
2967  $datafile = $conf->global->GEOIPMAXMIND_COUNTRY_DATAFILE;
2968  //$ip='24.24.24.24';
2969  //$datafile='/usr/share/GeoIP/GeoIP.dat'; Note that this must be downloaded datafile (not same than datafile provided with ubuntu packages)
2970  include_once DOL_DOCUMENT_ROOT.'/core/class/dolgeoip.class.php';
2971  $geoip = new DolGeoIP('country', $datafile);
2972  //print 'ip='.$ip.' databaseType='.$geoip->gi->databaseType." GEOIP_CITY_EDITION_REV1=".GEOIP_CITY_EDITION_REV1."\n";
2973  $countrycode = $geoip->getCountryCodeFromIP($ip);
2974  }
2975 
2976  return $countrycode;
2977 }
2978 
2979 
2987 {
2988  global $conf, $langs, $user;
2989 
2990  //$ret=$user->xxx;
2991  $ret = '';
2992  if (!empty($conf->geoipmaxmind->enabled))
2993  {
2994  $ip = getUserRemoteIP();
2995  $datafile = $conf->global->GEOIPMAXMIND_COUNTRY_DATAFILE;
2996  //$ip='24.24.24.24';
2997  //$datafile='E:\Mes Sites\Web\Admin1\awstats\maxmind\GeoIP.dat';
2998  include_once DOL_DOCUMENT_ROOT.'/core/class/dolgeoip.class.php';
2999  $geoip = new DolGeoIP('country', $datafile);
3000  $countrycode = $geoip->getCountryCodeFromIP($ip);
3001  $ret = $countrycode;
3002  }
3003  return $ret;
3004 }
3005 
3018 function dol_print_address($address, $htmlid, $element, $id, $noprint = 0, $charfornl = '')
3019 {
3020  global $conf, $user, $langs, $hookmanager;
3021 
3022  $out = '';
3023 
3024  if ($address)
3025  {
3026  if ($hookmanager) {
3027  $parameters = array('element' => $element, 'id' => $id);
3028  $reshook = $hookmanager->executeHooks('printAddress', $parameters, $address);
3029  $out .= $hookmanager->resPrint;
3030  }
3031  if (empty($reshook))
3032  {
3033  if (empty($charfornl)) $out .= nl2br($address);
3034  else $out .= preg_replace('/[\r\n]+/', $charfornl, $address);
3035 
3036  // TODO Remove this block, we can add this using the hook now
3037  $showgmap = $showomap = 0;
3038  if (($element == 'thirdparty' || $element == 'societe') && !empty($conf->google->enabled) && !empty($conf->global->GOOGLE_ENABLE_GMAPS)) $showgmap = 1;
3039  if ($element == 'contact' && !empty($conf->google->enabled) && !empty($conf->global->GOOGLE_ENABLE_GMAPS_CONTACTS)) $showgmap = 1;
3040  if ($element == 'member' && !empty($conf->google->enabled) && !empty($conf->global->GOOGLE_ENABLE_GMAPS_MEMBERS)) $showgmap = 1;
3041  if (($element == 'thirdparty' || $element == 'societe') && !empty($conf->openstreetmap->enabled) && !empty($conf->global->OPENSTREETMAP_ENABLE_MAPS)) $showomap = 1;
3042  if ($element == 'contact' && !empty($conf->openstreetmap->enabled) && !empty($conf->global->OPENSTREETMAP_ENABLE_MAPS_CONTACTS)) $showomap = 1;
3043  if ($element == 'member' && !empty($conf->openstreetmap->enabled) && !empty($conf->global->OPENSTREETMAP_ENABLE_MAPS_MEMBERS)) $showomap = 1;
3044  if ($showgmap)
3045  {
3046  $url = dol_buildpath('/google/gmaps.php?mode='.$element.'&id='.$id, 1);
3047  $out .= ' <a href="'.$url.'" target="_gmaps"><img id="'.$htmlid.'" class="valigntextbottom" src="'.DOL_URL_ROOT.'/theme/common/gmap.png"></a>';
3048  }
3049  if ($showomap)
3050  {
3051  $url = dol_buildpath('/openstreetmap/maps.php?mode='.$element.'&id='.$id, 1);
3052  $out .= ' <a href="'.$url.'" target="_gmaps"><img id="'.$htmlid.'_openstreetmap" class="valigntextbottom" src="'.DOL_URL_ROOT.'/theme/common/gmap.png"></a>';
3053  }
3054  }
3055  }
3056  if ($noprint) return $out;
3057  else print $out;
3058 }
3059 
3060 
3069 function isValidEmail($address, $acceptsupervisorkey = 0)
3070 {
3071  if ($acceptsupervisorkey && $address == '__SUPERVISOREMAIL__') return true;
3072  if (filter_var($address, FILTER_VALIDATE_EMAIL)) return true;
3073 
3074  return false;
3075 }
3076 
3085 function isValidMXRecord($domain)
3086 {
3087  if (function_exists('idn_to_ascii') && function_exists('checkdnsrr'))
3088  {
3089  if (!checkdnsrr(idn_to_ascii($domain), 'MX'))
3090  {
3091  return 0;
3092  }
3093  if (function_exists('getmxrr'))
3094  {
3095  $mxhosts = array();
3096  $weight = array();
3097  getmxrr(idn_to_ascii($domain), $mxhosts, $weight);
3098  if (count($mxhosts) > 1) return 1;
3099  if (count($mxhosts) == 1 && !empty($mxhosts[0])) return 1;
3100 
3101  return 0;
3102  }
3103  }
3104  return -1;
3105 }
3106 
3114 function isValidPhone($phone)
3115 {
3116  return true;
3117 }
3118 
3119 
3127 function dol_strlen($string, $stringencoding = 'UTF-8')
3128 {
3129  if (function_exists('mb_strlen')) return mb_strlen($string, $stringencoding);
3130  else return strlen($string);
3131 }
3132 
3143 function dol_substr($string, $start, $length, $stringencoding = '', $trunconbytes = 0)
3144 {
3145  global $langs;
3146 
3147  if (empty($stringencoding)) $stringencoding = $langs->charset_output;
3148 
3149  $ret = '';
3150  if (empty($trunconbytes))
3151  {
3152  if (function_exists('mb_substr'))
3153  {
3154  $ret = mb_substr($string, $start, $length, $stringencoding);
3155  } else {
3156  $ret = substr($string, $start, $length);
3157  }
3158  } else {
3159  if (function_exists('mb_strcut'))
3160  {
3161  $ret = mb_strcut($string, $start, $length, $stringencoding);
3162  } else {
3163  $ret = substr($string, $start, $length);
3164  }
3165  }
3166  return $ret;
3167 }
3168 
3169 
3183 function dol_trunc($string, $size = 40, $trunc = 'right', $stringencoding = 'UTF-8', $nodot = 0, $display = 0)
3184 {
3185  global $conf;
3186 
3187  if ($size == 0 || !empty($conf->global->MAIN_DISABLE_TRUNC)) return $string;
3188 
3189  if (empty($stringencoding)) $stringencoding = 'UTF-8';
3190  // reduce for small screen
3191  if ($conf->dol_optimize_smallscreen == 1 && $display == 1) $size = round($size / 3);
3192 
3193  // We go always here
3194  if ($trunc == 'right')
3195  {
3196  $newstring = dol_textishtml($string) ?dol_string_nohtmltag($string, 1) : $string;
3197  if (dol_strlen($newstring, $stringencoding) > ($size + ($nodot ? 0 : 3))) // If nodot is 0 and size is 1,2 or 3 chars more, we don't trunc and don't add ...
3198  return dol_substr($newstring, 0, $size, $stringencoding).($nodot ? '' : '...');
3199  else //return 'u'.$size.'-'.$newstring.'-'.dol_strlen($newstring,$stringencoding).'-'.$string;
3200  return $string;
3201  } elseif ($trunc == 'middle')
3202  {
3203  $newstring = dol_textishtml($string) ?dol_string_nohtmltag($string, 1) : $string;
3204  if (dol_strlen($newstring, $stringencoding) > 2 && dol_strlen($newstring, $stringencoding) > ($size + 1))
3205  {
3206  $size1 = round($size / 2);
3207  $size2 = round($size / 2);
3208  return dol_substr($newstring, 0, $size1, $stringencoding).'...'.dol_substr($newstring, dol_strlen($newstring, $stringencoding) - $size2, $size2, $stringencoding);
3209  } else return $string;
3210  } elseif ($trunc == 'left')
3211  {
3212  $newstring = dol_textishtml($string) ?dol_string_nohtmltag($string, 1) : $string;
3213  if (dol_strlen($newstring, $stringencoding) > ($size + ($nodot ? 0 : 3))) // If nodot is 0 and size is 1,2 or 3 chars more, we don't trunc and don't add ...
3214  return '...'.dol_substr($newstring, dol_strlen($newstring, $stringencoding) - $size, $size, $stringencoding);
3215  else return $string;
3216  } elseif ($trunc == 'wrap')
3217  {
3218  $newstring = dol_textishtml($string) ?dol_string_nohtmltag($string, 1) : $string;
3219  if (dol_strlen($newstring, $stringencoding) > ($size + 1))
3220  return dol_substr($newstring, 0, $size, $stringencoding)."\n".dol_trunc(dol_substr($newstring, $size, dol_strlen($newstring, $stringencoding) - $size, $stringencoding), $size, $trunc);
3221  else return $string;
3222  } else return 'BadParam3CallingDolTrunc';
3223 }
3224 
3244 function img_picto($titlealt, $picto, $moreatt = '', $pictoisfullpath = false, $srconly = 0, $notitle = 0, $alt = '', $morecss = '', $marginleftonlyshort = 2)
3245 {
3246  global $conf, $langs;
3247 
3248  // We forge fullpathpicto for image to $path/img/$picto. By default, we take DOL_URL_ROOT/theme/$conf->theme/img/$picto
3249  $url = DOL_URL_ROOT;
3250  $theme = isset($conf->theme) ? $conf->theme : null;
3251  $path = 'theme/'.$theme;
3252  // Define fullpathpicto to use into src
3253  if ($pictoisfullpath) {
3254  // Clean parameters
3255  if (!preg_match('/(\.png|\.gif|\.svg)$/i', $picto)) {
3256  $picto .= '.png';
3257  }
3258  $fullpathpicto = $picto;
3259  $reg = array();
3260  if (preg_match('/class="([^"]+)"/', $moreatt, $reg)) {
3261  $morecss .= ($morecss ? ' ' : '').$reg[1];
3262  $moreatt = str_replace('class="'.$reg[1].'"', '', $moreatt);
3263  }
3264  } else {
3265  $pictowithouttext = preg_replace('/(\.png|\.gif|\.svg)$/', '', $picto);
3266  if (empty($srconly) && in_array($pictowithouttext, array(
3267  '1downarrow', '1uparrow', '1leftarrow', '1rightarrow', '1uparrow_selected', '1downarrow_selected', '1leftarrow_selected', '1rightarrow_selected',
3268  'accountancy', 'account', 'accountline', 'action', 'add', 'address', 'bank_account', 'barcode', 'bank', 'bill', 'billa', 'billr', 'billd', 'bookmark', 'bom', 'building',
3269  'cash-register', 'category', 'check', 'clock', 'close_title', 'company', 'contact', 'contract', 'cron', 'cubes',
3270  'delete', 'dolly', 'dollyrevert', 'donation', 'download', 'edit', 'ellipsis-h', 'email', 'eraser', 'external-link-alt', 'external-link-square-alt',
3271  'filter', 'file-code', 'file-export', 'file-import', 'file-upload', 'folder', 'folder-open', 'globe', 'globe-americas', 'grip', 'grip_title', 'group',
3272  'help', 'holiday',
3273  'intervention', 'label', 'language', 'link', 'list', 'listlight', 'lot',
3274  'map-marker-alt', 'member', 'money-bill-alt', 'mrp', 'note', 'next',
3275  'object_accounting', 'object_account', 'object_accountline', 'object_action', 'object_barcode', 'object_bill', 'object_billa', 'object_billr', 'object_billd', 'object_bom',
3276  'object_category', 'object_conversation', 'object_bookmark', 'object_bug', 'object_clock', 'object_dolly', 'object_dollyrevert', 'object_generic', 'object_folder',
3277  'object_list-alt', 'object_calendar', 'object_calendarweek', 'object_calendarmonth', 'object_calendarday', 'object_calendarperuser',
3278  'object_cash-register', 'object_company', 'object_contact', 'object_contract', 'object_donation', 'object_dynamicprice',
3279  'object_globe', 'object_holiday', 'object_hrm', 'object_invoice', 'object_intervention', 'object_label',
3280  'object_margin', 'object_money-bill-alt', 'object_multicurrency', 'object_order', 'object_payment',
3281  'object_lot', 'object_mrp', 'object_other',
3282  'object_payment', 'object_pdf', 'object_product', 'object_propal',
3283  'object_paragraph', 'object_poll', 'object_printer', 'object_project', 'object_projectpub', 'object_propal', 'object_resource', 'object_rss', 'object_projecttask',
3284  'object_recruitmentjobposition', 'object_recruitmentcandidature',
3285  'object_shipment', 'object_share-alt', 'object_supplier_invoice', 'object_supplier_invoicea', 'object_supplier_invoiced', 'object_supplier_order', 'object_supplier_proposal', 'object_service', 'object_stock',
3286  'object_technic', 'object_ticket', 'object_trip', 'object_user', 'object_group', 'object_member',
3287  'object_phoning', 'object_phoning_mobile', 'object_phoning_fax', 'object_email', 'object_website', 'object_movement',
3288  'off', 'on', 'order',
3289  'paiment', 'play', 'pdf', 'playdisabled', 'previous', 'poll', 'printer', 'product', 'propal', 'projecttask', 'stock', 'resize', 'service', 'stats', 'trip',
3290  'setup', 'share-alt', 'sign-out', 'split', 'stripe-s', 'switch_off', 'switch_on', 'tools', 'unlink', 'uparrow', 'user', 'vcard', 'wrench',
3291  'jabber', 'skype', 'twitter', 'facebook', 'linkedin', 'instagram', 'snapchat', 'youtube', 'google-plus-g', 'whatsapp',
3292  'chevron-left', 'chevron-right', 'chevron-down', 'chevron-top', 'commercial', 'companies',
3293  'generic', 'home', 'hrm', 'members', 'products', 'invoicing',
3294  'payment', 'pencil-ruler', 'preview', 'project', 'projectpub', 'refresh', 'supplier_invoice', 'ticket',
3295  'error', 'warning',
3296  'recruitmentcandidature', 'recruitmentjobposition', 'resource',
3297  'supplier_proposal', 'supplier_order', 'supplier_invoice',
3298  'title_setup', 'title_accountancy', 'title_bank', 'title_hrm', 'title_agenda'
3299  )
3300  )) {
3301  $pictowithouttext = str_replace('object_', '', $pictowithouttext);
3302 
3303  $fakey = $pictowithouttext;
3304  $facolor = ''; $fasize = '';
3305  $fa = 'fas';
3306  if (in_array($pictowithouttext, array('clock', 'generic', 'minus-square', 'object_generic', 'pdf', 'plus-square', 'note', 'off', 'on', 'object_bookmark', 'bookmark', 'vcard'))) {
3307  $fa = 'far';
3308  }
3309  if (in_array($pictowithouttext, array('black-tie', 'skype', 'twitter', 'facebook', 'linkedin', 'instagram', 'snapchat', 'stripe-s', 'youtube', 'google-plus-g', 'whatsapp'))) {
3310  $fa = 'fab';
3311  }
3312 
3313  $arrayconvpictotofa = array(
3314  'account'=>'university', 'accountline'=>'receipt', 'accountancy'=>'money-check-alt', 'action'=>'calendar-alt', 'add'=>'plus-circle', 'address'=> 'address-book',
3315  'bank_account'=>'university', 'bill'=>'file-invoice-dollar', 'billa'=>'file-excel', 'billr'=>'file-invoice-dollar', 'supplier_invoicea'=>'file-excel', 'billd'=>'file-medical', 'supplier_invoiced'=>'file-medical', 'bom'=>'cubes',
3316  'company'=>'building', 'contact'=>'address-book', 'contract'=>'suitcase', 'conversation'=>'comments', 'donation'=>'file-alt', 'dynamicprice'=>'hand-holding-usd',
3317  'setup'=>'cog', 'companies'=>'building', 'products'=>'cube', 'commercial'=>'suitcase', 'invoicing'=>'coins',
3318  'accounting'=>'chart-line', 'category'=>'tag', 'dollyrevert'=>'dolly',
3319  'hrm'=>'user-tie', 'margin'=>'calculator', 'members'=>'users', 'ticket'=>'ticket-alt', 'globe'=>'external-link-alt', 'lot'=>'barcode',
3320  'email'=>'at',
3321  'edit'=>'pencil-alt', 'grip_title'=>'arrows-alt', 'grip'=>'arrows-alt', 'help'=>'question-circle',
3322  'generic'=>'file', 'holiday'=>'umbrella-beach', 'label'=>'layer-group',
3323  'member'=>'users', 'mrp'=>'cubes', 'next'=>'arrow-alt-circle-right',
3324  'trip'=>'wallet', 'group'=>'users', 'movement'=>'people-carry',
3325  'sign-out'=>'sign-out-alt',
3326  'switch_off'=>'toggle-off', 'switch_on'=>'toggle-on', 'check'=>'check', 'bookmark'=>'star', 'bookmark'=>'star',
3327  'bank'=>'university', 'close_title'=>'times', 'delete'=>'trash', 'edit'=>'pencil-alt', 'filter'=>'filter',
3328  'list-alt'=>'list-alt', 'calendar'=>'calendar-alt', 'calendarweek'=>'calendar-week', 'calendarmonth'=>'calendar-alt', 'calendarday'=>'calendar-day', 'calendarperuser'=>'table',
3329  'intervention'=>'ambulance', 'invoice'=>'file-invoice-dollar', 'multicurrency'=>'dollar-sign', 'order'=>'file-invoice',
3330  'error'=>'exclamation-triangle', 'warning'=>'exclamation-triangle',
3331  'other'=>'square',
3332  'playdisabled'=>'play', 'pdf'=>'file-pdf', 'poll'=>'check-double', 'preview'=>'binoculars', 'project'=>'sitemap', 'projectpub'=>'sitemap', 'projecttask'=>'tasks', 'propal'=>'file-signature',
3333  'payment'=>'money-check-alt', 'phoning'=>'phone', 'phoning_mobile'=>'mobile-alt', 'phoning_fax'=>'fax', 'previous'=>'arrow-alt-circle-left', 'printer'=>'print', 'product'=>'cube', 'service'=>'concierge-bell',
3334  'recruitmentjobposition'=>'id-card-alt', 'recruitmentcandidature'=>'id-badge',
3335  'resize'=>'crop', 'supplier_order'=>'dol-order_supplier', 'supplier_proposal'=>'file-signature',
3336  'refresh'=>'redo', 'resource'=>'laptop-house',
3337  'shipment'=>'dolly', 'stock'=>'box-open', 'stats' => 'chart-bar', 'split'=>'code-branch', 'supplier_invoice'=>'file-invoice-dollar', 'technic'=>'cogs', 'ticket'=>'ticket-alt',
3338  'title_setup'=>'tools', 'title_accountancy'=>'money-check-alt', 'title_bank'=>'university', 'title_hrm'=>'umbrella-beach',
3339  'title_agenda'=>'calendar-alt',
3340  'uparrow'=>'mail-forward', 'vcard'=>'address-card',
3341  'jabber'=>'comment-o',
3342  'website'=>'globe-americas'
3343  );
3344  if ($pictowithouttext == 'off') {
3345  $fakey = 'fa-square';
3346  $fasize = '1.3em';
3347  } elseif ($pictowithouttext == 'on') {
3348  $fakey = 'fa-check-square';
3349  $fasize = '1.3em';
3350  } elseif ($pictowithouttext == 'listlight') {
3351  $fakey = 'fa-download';
3352  $marginleftonlyshort = 1;
3353  } elseif ($pictowithouttext == 'printer') {
3354  $fakey = 'fa-print';
3355  $fasize = '1.2em';
3356  } elseif ($pictowithouttext == 'note') {
3357  $fakey = 'fa-sticky-note';
3358  $marginleftonlyshort = 1;
3359  } elseif (in_array($pictowithouttext, array('1uparrow', '1downarrow', '1leftarrow', '1rightarrow', '1uparrow_selected', '1downarrow_selected', '1leftarrow_selected', '1rightarrow_selected'))) {
3360  $convertarray = array('1uparrow'=>'caret-up', '1downarrow'=>'caret-down', '1leftarrow'=>'caret-left', '1rightarrow'=>'caret-right', '1uparrow_selected'=>'caret-up', '1downarrow_selected'=>'caret-down', '1leftarrow_selected'=>'caret-left', '1rightarrow_selected'=>'caret-right');
3361  $fakey = 'fa-'.$convertarray[$pictowithouttext];
3362  if (preg_match('/selected/', $pictowithouttext)) $facolor = '#888';
3363  $marginleftonlyshort = 1;
3364  } elseif (!empty($arrayconvpictotofa[$pictowithouttext])) {
3365  $fakey = 'fa-'.$arrayconvpictotofa[$pictowithouttext];
3366  } else {
3367  $fakey = 'fa-'.$pictowithouttext;
3368  }
3369 
3370  // Define $marginleftonlyshort
3371  $arrayconvpictotomarginleftonly = array(
3372  'bank', 'check', 'delete', 'generic', 'grip', 'grip_title', 'jabber',
3373  'grip_title', 'grip', 'listlight', 'note', 'on', 'off', 'playdisabled', 'printer', 'resize', 'sign-out', 'stats', 'switch_on', 'switch_off',
3374  'uparrow', '1uparrow', '1downarrow', '1leftarrow', '1rightarrow', '1uparrow_selected', '1downarrow_selected', '1leftarrow_selected', '1rightarrow_selected'
3375  );
3376  if (!isset($arrayconvpictotomarginleftonly[$pictowithouttext])) {
3377  $marginleftonlyshort = 0;
3378  }
3379 
3380  // Add CSS
3381  $arrayconvpictotomorcess = array(
3382  'action'=>'infobox-action', 'account'=>'infobox-bank_account', 'accountline'=>'infobox-bank_account', 'accountancy'=>'infobox-bank_account',
3383  'bank_account'=>'bg-infobox-bank_account',
3384  'bill'=>'infobox-commande', 'billa'=>'infobox-commande', 'billr'=>'infobox-commande', 'billd'=>'infobox-commande',
3385  'cash-register'=>'infobox-bank_account', 'contract'=>'infobox-contrat', 'check'=>'font-status4', 'conversation'=>'infobox-contrat',
3386  'donation'=>'infobox-commande', 'dollyrevert'=>'flip', 'ecm'=>'infobox-action',
3387  'hrm'=>'infobox-adherent', 'group'=>'infobox-adherent', 'intervention'=>'infobox-contrat',
3388  'multicurrency'=>'infobox-bank_account',
3389  'members'=>'infobox-adherent', 'member'=>'infobox-adherent', 'money-bill-alt'=>'infobox-bank_account',
3390  'order'=>'infobox-commande',
3391  'user'=>'infobox-adherent', 'users'=>'infobox-adherent',
3392  'error'=>'pictoerror', 'warning'=>'pictowarning', 'switch_on'=>'font-status4',
3393  'holiday'=>'infobox-holiday', 'invoice'=>'infobox-commande',
3394  'payment'=>'infobox-bank_account', 'poll'=>'infobox-adherent', 'project'=>'infobox-project', 'projecttask'=>'infobox-project', 'propal'=>'infobox-propal',
3395  'recruitmentjobposition'=>'infobox-adherent', 'recruitmentcandidature'=>'infobox-adherent',
3396  'resource'=>'infobox-action',
3397  'supplier_invoice'=>'infobox-order_supplier', 'supplier_invoicea'=>'infobox-order_supplier', 'supplier_invoiced'=>'infobox-order_supplier',
3398  'supplier_order'=>'infobox-order_supplier', 'supplier_proposal'=>'infobox-supplier_proposal',
3399  'ticket'=>'infobox-contrat', 'title_accountancy'=>'infobox-bank_account', 'title_hrm'=>'infobox-holiday', 'trip'=>'infobox-expensereport', 'title_agenda'=>'infobox-action',
3400  //'title_setup'=>'infobox-action', 'tools'=>'infobox-action',
3401  'list-alt'=>'imgforviewmode', 'calendar'=>'imgforviewmode', 'calendarweek'=>'imgforviewmode', 'calendarmonth'=>'imgforviewmode', 'calendarday'=>'imgforviewmode', 'calendarperuser'=>'imgforviewmode'
3402  );
3403  if (!empty($arrayconvpictotomorcess[$pictowithouttext])) {
3404  $morecss .= ($morecss ? ' ' : '').$arrayconvpictotomorcess[$pictowithouttext];
3405  }
3406 
3407  // Define $color
3408  $arrayconvpictotocolor = array(
3409  'address'=>'#6c6aa8', 'building'=>'#6c6aa8', 'bom'=>'#a69944',
3410  'companies'=>'#6c6aa8', 'company'=>'#6c6aa8', 'contact'=>'#6c6aa8', 'dynamicprice'=>'#a69944',
3411  'edit'=>'#444', 'note'=>'#999', 'error'=>'', 'help'=>'#bbb', 'listlight'=>'#999',
3412  'dolly'=>'#a69944', 'dollyrevert'=>'#a69944', 'lot'=>'#a69944',
3413  'map-marker-alt'=>'#aaa', 'mrp'=>'#a69944', 'product'=>'#a69944', 'service'=>'#a69944', 'stock'=>'#a69944', 'movement'=>'#a69944',
3414  'other'=>'#ddd',
3415  'playdisabled'=>'#ccc', 'printer'=>'#444', 'projectpub'=>'#986c6a', 'resize'=>'#444', 'rss'=>'#cba',
3416  'shipment'=>'#a69944', 'stats'=>'#444', 'switch_off'=>'#999', 'uparrow'=>'#555', 'globe-americas'=>'#aaa',
3417  'website'=>'#304'
3418  );
3419  if (isset($arrayconvpictotocolor[$pictowithouttext])) {
3420  $facolor = $arrayconvpictotocolor[$pictowithouttext];
3421  }
3422 
3423  // This snippet only needed since function img_edit accepts only one additional parameter: no separate one for css only.
3424  // class/style need to be extracted to avoid duplicate class/style validation errors when $moreatt is added to the end of the attributes.
3425  $morestyle = '';
3426  $reg = array();
3427  if (preg_match('/class="([^"]+)"/', $moreatt, $reg)) {
3428  $morecss .= ($morecss ? ' ' : '').$reg[1];
3429  $moreatt = str_replace('class="'.$reg[1].'"', '', $moreatt);
3430  }
3431  if (preg_match('/style="([^"]+)"/', $moreatt, $reg)) {
3432  $morestyle = $reg[1];
3433  $moreatt = str_replace('style="'.$reg[1].'"', '', $moreatt);
3434  }
3435  $moreatt = trim($moreatt);
3436 
3437  $enabledisablehtml = '<span class="'.$fa.' '.$fakey.($marginleftonlyshort ? ($marginleftonlyshort == 1 ? ' marginleftonlyshort' : ' marginleftonly') : '');
3438  $enabledisablehtml .= ($morecss ? ' '.$morecss : '').'" style="'.($fasize ? ('font-size: '.$fasize.';') : '').($facolor ? (' color: '.$facolor.';') : '').($morestyle ? ' '.$morestyle : '').'"'.(($notitle || empty($titlealt)) ? '' : ' title="'.dol_escape_htmltag($titlealt).'"').($moreatt ? ' '.$moreatt : '').'>';
3439  /*if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) {
3440  $enabledisablehtml .= $titlealt;
3441  }*/
3442  $enabledisablehtml .= '</span>';
3443 
3444  return $enabledisablehtml;
3445  }
3446 
3447  if (!empty($conf->global->MAIN_OVERWRITE_THEME_PATH)) {
3448  $path = $conf->global->MAIN_OVERWRITE_THEME_PATH.'/theme/'.$theme; // If the theme does not have the same name as the module
3449  } elseif (!empty($conf->global->MAIN_OVERWRITE_THEME_RES)) {
3450  $path = $conf->global->MAIN_OVERWRITE_THEME_RES.'/theme/'.$conf->global->MAIN_OVERWRITE_THEME_RES; // To allow an external module to overwrite image resources whatever is activated theme
3451  } elseif (!empty($conf->modules_parts['theme']) && array_key_exists($theme, $conf->modules_parts['theme'])) {
3452  $path = $theme.'/theme/'.$theme; // If the theme have the same name as the module
3453  }
3454 
3455  // If we ask an image into $url/$mymodule/img (instead of default path)
3456  $regs = array();
3457  if (preg_match('/^([^@]+)@([^@]+)$/i', $picto, $regs)) {
3458  $picto = $regs[1];
3459  $path = $regs[2]; // $path is $mymodule
3460  }
3461 
3462  // Clean parameters
3463  if (!preg_match('/(\.png|\.gif|\.svg)$/i', $picto)) {
3464  $picto .= '.png';
3465  }
3466  // If alt path are defined, define url where img file is, according to physical path
3467  // ex: array(["main"]=>"/home/maindir/htdocs", ["alt0"]=>"/home/moddir0/htdocs", ...)
3468  foreach ($conf->file->dol_document_root as $type => $dirroot) {
3469  if ($type == 'main') {
3470  continue;
3471  }
3472  // This need a lot of time, that's why enabling alternative dir like "custom" dir is not recommanded
3473  if (file_exists($dirroot.'/'.$path.'/img/'.$picto)) {
3474  $url = DOL_URL_ROOT.$conf->file->dol_url_root[$type];
3475  break;
3476  }
3477  }
3478 
3479  // $url is '' or '/custom', $path is current theme or
3480  $fullpathpicto = $url.'/'.$path.'/img/'.$picto;
3481  }
3482 
3483  if ($srconly) {
3484  return $fullpathpicto;
3485  }
3486  // tag title is used for tooltip on <a>, tag alt can be used with very simple text on image for blind people
3487  return '<img src="'.$fullpathpicto.'" alt="'.dol_escape_htmltag($alt).'"'.(($notitle || empty($titlealt)) ? '' : ' title="'.dol_escape_htmltag($titlealt).'"').($moreatt ? ' '.$moreatt.($morecss ? ' class="'.$morecss.'"' : '') : ' class="inline-block'.($morecss ? ' '.$morecss : '').'"').'>'; // Alt is used for accessibility, title for popup
3488 }
3489 
3503 function img_object($titlealt, $picto, $moreatt = '', $pictoisfullpath = false, $srconly = 0, $notitle = 0)
3504 {
3505  if (strpos($picto, '^') === 0) return img_picto($titlealt, str_replace('^', '', $picto), $moreatt, $pictoisfullpath, $srconly, $notitle);
3506  else return img_picto($titlealt, 'object_'.$picto, $moreatt, $pictoisfullpath, $srconly, $notitle);
3507 }
3508 
3520 function img_weather($titlealt, $picto, $moreatt = '', $pictoisfullpath = 0, $morecss = '')
3521 {
3522  global $conf;
3523 
3524  if (is_numeric($picto)) {
3525  //$leveltopicto = array(0=>'weather-clear.png', 1=>'weather-few-clouds.png', 2=>'weather-clouds.png', 3=>'weather-many-clouds.png', 4=>'weather-storm.png');
3526  //$picto = $leveltopicto[$picto];
3527  return '<i class="fa fa-weather-level'.$picto.'"></i>';
3528  } elseif (!preg_match('/(\.png|\.gif)$/i', $picto)) {
3529  $picto .= '.png';
3530  }
3531 
3532  $path = DOL_URL_ROOT.'/theme/'.$conf->theme.'/img/weather/'.$picto;
3533 
3534  return img_picto($titlealt, $path, $moreatt, 1, 0, 0, '', $morecss);
3535 }
3536 
3547 function img_picto_common($titlealt, $picto, $moreatt = '', $pictoisfullpath = 0)
3548 {
3549  global $conf;
3550 
3551  if (!preg_match('/(\.png|\.gif)$/i', $picto)) $picto .= '.png';
3552 
3553  if ($pictoisfullpath) $path = $picto;
3554  else {
3555  $path = DOL_URL_ROOT.'/theme/common/'.$picto;
3556 
3557  if (!empty($conf->global->MAIN_MODULE_CAN_OVERWRITE_COMMONICONS))
3558  {
3559  $themepath = DOL_DOCUMENT_ROOT.'/theme/'.$conf->theme.'/img/'.$picto;
3560 
3561  if (file_exists($themepath)) $path = $themepath;
3562  }
3563  }
3564 
3565  return img_picto($titlealt, $path, $moreatt, 1);
3566 }
3567 
3580 function img_action($titlealt, $numaction, $picto = '')
3581 {
3582  global $langs;
3583 
3584  if (empty($titlealt) || $titlealt == 'default')
3585  {
3586  if ($numaction == '-1' || $numaction == 'ST_NO') {
3587  $numaction = -1;
3588  $titlealt = $langs->transnoentitiesnoconv('ChangeDoNotContact');
3589  } elseif ($numaction == '0' || $numaction == 'ST_NEVER') {
3590  $numaction = 0;
3591  $titlealt = $langs->transnoentitiesnoconv('ChangeNeverContacted');
3592  } elseif ($numaction == '1' || $numaction == 'ST_TODO') {
3593  $numaction = 1;
3594  $titlealt = $langs->transnoentitiesnoconv('ChangeToContact');
3595  } elseif ($numaction == '2' || $numaction == 'ST_PEND') {
3596  $numaction = 2;
3597  $titlealt = $langs->transnoentitiesnoconv('ChangeContactInProcess');
3598  } elseif ($numaction == '3' || $numaction == 'ST_DONE') {
3599  $numaction = 3;
3600  $titlealt = $langs->transnoentitiesnoconv('ChangeContactDone');
3601  } else {
3602  $titlealt = $langs->transnoentitiesnoconv('ChangeStatus '.$numaction);
3603  $numaction = 0;
3604  }
3605  }
3606  if (!is_numeric($numaction)) $numaction = 0;
3607 
3608  return img_picto($titlealt, !empty($picto) ? $picto : 'stcomm'.$numaction.'.png');
3609 }
3610 
3618 function img_pdf($titlealt = 'default', $size = 3)
3619 {
3620  global $langs;
3621 
3622  if ($titlealt == 'default') $titlealt = $langs->trans('Show');
3623 
3624  return img_picto($titlealt, 'pdf'.$size.'.png');
3625 }
3626 
3634 function img_edit_add($titlealt = 'default', $other = '')
3635 {
3636  global $langs;
3637 
3638  if ($titlealt == 'default') $titlealt = $langs->trans('Add');
3639 
3640  return img_picto($titlealt, 'edit_add.png', $other);
3641 }
3649 function img_edit_remove($titlealt = 'default', $other = '')
3650 {
3651  global $langs;
3652 
3653  if ($titlealt == 'default') $titlealt = $langs->trans('Remove');
3654 
3655  return img_picto($titlealt, 'edit_remove.png', $other);
3656 }
3657 
3666 function img_edit($titlealt = 'default', $float = 0, $other = '')
3667 {
3668  global $langs;
3669 
3670  if ($titlealt == 'default') $titlealt = $langs->trans('Modify');
3671 
3672  return img_picto($titlealt, 'edit.png', ($float ? 'style="float: '.($langs->tab_translate["DIRECTION"] == 'rtl' ? 'left' : 'right').'"' : "").($other ? ' '.$other : ''));
3673 }
3674 
3683 function img_view($titlealt = 'default', $float = 0, $other = '')
3684 {
3685  global $langs;
3686 
3687  if ($titlealt == 'default') $titlealt = $langs->trans('View');
3688 
3689  $moreatt = ($float ? 'style="float: right" ' : '').$other;
3690 
3691  return img_picto($titlealt, 'view.png', $moreatt);
3692 }
3693 
3702 function img_delete($titlealt = 'default', $other = 'class="pictodelete"', $morecss = '')
3703 {
3704  global $langs;
3705 
3706  if ($titlealt == 'default') $titlealt = $langs->trans('Delete');
3707 
3708  return img_picto($titlealt, 'delete.png', $other, false, 0, 0, '', $morecss);
3709 }
3710 
3718 function img_printer($titlealt = "default", $other = '')
3719 {
3720  global $langs;
3721  if ($titlealt == "default") $titlealt = $langs->trans("Print");
3722  return img_picto($titlealt, 'printer.png', $other);
3723 }
3724 
3732 function img_split($titlealt = 'default', $other = 'class="pictosplit"')
3733 {
3734  global $langs;
3735 
3736  if ($titlealt == 'default') $titlealt = $langs->trans('Split');
3737 
3738  return img_picto($titlealt, 'split.png', $other);
3739 }
3740 
3748 function img_help($usehelpcursor = 1, $usealttitle = 1)
3749 {
3750  global $langs;
3751 
3752  if ($usealttitle)
3753  {
3754  if (is_string($usealttitle)) $usealttitle = dol_escape_htmltag($usealttitle);
3755  else $usealttitle = $langs->trans('Info');
3756  }
3757 
3758  return img_picto($usealttitle, 'info.png', 'style="vertical-align: middle;'.($usehelpcursor == 1 ? ' cursor: help' : ($usehelpcursor == 2 ? ' cursor: pointer' : '')).'"');
3759 }
3760 
3767 function img_info($titlealt = 'default')
3768 {
3769  global $langs;
3770 
3771  if ($titlealt == 'default') $titlealt = $langs->trans('Informations');
3772 
3773  return img_picto($titlealt, 'info.png', 'style="vertical-align: middle;"');
3774 }
3775 
3784 function img_warning($titlealt = 'default', $moreatt = '', $morecss = 'pictowarning')
3785 {
3786  global $langs;
3787 
3788  if ($titlealt == 'default') $titlealt = $langs->trans('Warning');
3789 
3790  //return '<div class="imglatecoin">'.img_picto($titlealt, 'warning_white.png', 'class="pictowarning valignmiddle"'.($moreatt ? ($moreatt == '1' ? ' style="float: right"' : ' '.$moreatt): '')).'</div>';
3791  return img_picto($titlealt, 'warning.png', 'class="'.$morecss.'"'.($moreatt ? ($moreatt == '1' ? ' style="float: right"' : ' '.$moreatt) : ''));
3792 }
3793 
3800 function img_error($titlealt = 'default')
3801 {
3802  global $langs;
3803 
3804  if ($titlealt == 'default') $titlealt = $langs->trans('Error');
3805 
3806  return img_picto($titlealt, 'error.png');
3807 }
3808 
3816 function img_next($titlealt = 'default', $moreatt = '')
3817 {
3818  global $langs;
3819 
3820  if ($titlealt == 'default') $titlealt = $langs->trans('Next');
3821 
3822  //return img_picto($titlealt, 'next.png', $moreatt);
3823  return '<span class="fa fa-chevron-right paddingright paddingleft" title="'.dol_escape_htmltag($titlealt).'"></span>';
3824 }
3825 
3833 function img_previous($titlealt = 'default', $moreatt = '')
3834 {
3835  global $langs;
3836 
3837  if ($titlealt == 'default') $titlealt = $langs->trans('Previous');
3838 
3839  //return img_picto($titlealt, 'previous.png', $moreatt);
3840  return '<span class="fa fa-chevron-left paddingright paddingleft" title="'.dol_escape_htmltag($titlealt).'"></span>';
3841 }
3842 
3851 function img_down($titlealt = 'default', $selected = 0, $moreclass = '')
3852 {
3853  global $langs;
3854 
3855  if ($titlealt == 'default') $titlealt = $langs->trans('Down');
3856 
3857  return img_picto($titlealt, ($selected ? '1downarrow_selected.png' : '1downarrow.png'), 'class="imgdown'.($moreclass ? " ".$moreclass : "").'"');
3858 }
3859 
3868 function img_up($titlealt = 'default', $selected = 0, $moreclass = '')
3869 {
3870  global $langs;
3871 
3872  if ($titlealt == 'default') $titlealt = $langs->trans('Up');
3873 
3874  return img_picto($titlealt, ($selected ? '1uparrow_selected.png' : '1uparrow.png'), 'class="imgup'.($moreclass ? " ".$moreclass : "").'"');
3875 }
3876 
3885 function img_left($titlealt = 'default', $selected = 0, $moreatt = '')
3886 {
3887  global $langs;
3888 
3889  if ($titlealt == 'default') {
3890  $titlealt = $langs->trans('Left');
3891  }
3892 
3893  return img_picto($titlealt, ($selected ? '1leftarrow_selected.png' : '1leftarrow.png'), $moreatt);
3894 }
3895 
3904 function img_right($titlealt = 'default', $selected = 0, $moreatt = '')
3905 {
3906  global $langs;
3907 
3908  if ($titlealt == 'default') $titlealt = $langs->trans('Right');
3909 
3910  return img_picto($titlealt, ($selected ? '1rightarrow_selected.png' : '1rightarrow.png'), $moreatt);
3911 }
3912 
3920 function img_allow($allow, $titlealt = 'default')
3921 {
3922  global $langs;
3923 
3924  if ($titlealt == 'default') $titlealt = $langs->trans('Active');
3925 
3926  if ($allow == 1) return img_picto($titlealt, 'tick.png');
3927 
3928  return '-';
3929 }
3930 
3938 function img_credit_card($brand, $morecss = null)
3939 {
3940  if (is_null($morecss)) $morecss = 'fa-2x';
3941 
3942  if ($brand == 'visa' || $brand == 'Visa') {
3943  $brand = 'cc-visa';
3944  } elseif ($brand == 'mastercard' || $brand == 'MasterCard') {
3945  $brand = 'cc-mastercard';
3946  } elseif ($brand == 'amex' || $brand == 'American Express') {
3947  $brand = 'cc-amex';
3948  } elseif ($brand == 'discover' || $brand == 'Discover') {
3949  $brand = 'cc-discover';
3950  } elseif ($brand == 'jcb' || $brand == 'JCB') {
3951  $brand = 'cc-jcb';
3952  } elseif ($brand == 'diners' || $brand == 'Diners club') {
3953  $brand = 'cc-diners-club';
3954  } elseif (!in_array($brand, array('cc-visa', 'cc-mastercard', 'cc-amex', 'cc-discover', 'cc-jcb', 'cc-diners-club'))) {
3955  $brand = 'credit-card';
3956  }
3957 
3958  return '<span class="fa fa-'.$brand.' fa-fw'.($morecss ? ' '.$morecss : '').'"></span>';
3959 }
3960 
3969 function img_mime($file, $titlealt = '', $morecss = '')
3970 {
3971  require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
3972 
3973  $mimetype = dol_mimetype($file, '', 1);
3974  $mimeimg = dol_mimetype($file, '', 2);
3975  $mimefa = dol_mimetype($file, '', 4);
3976 
3977  if (empty($titlealt)) $titlealt = 'Mime type: '.$mimetype;
3978 
3979  //return img_picto_common($titlealt, 'mime/'.$mimeimg, 'class="'.$morecss.'"');
3980  return '<i class="fa fa-'.$mimefa.' paddingright"'.($titlealt ? ' title="'.$titlealt.'"' : '').'></i>';
3981 }
3982 
3983 
3991 function img_search($titlealt = 'default', $other = '')
3992 {
3993  global $conf, $langs;
3994 
3995  if ($titlealt == 'default') $titlealt = $langs->trans('Search');
3996 
3997  $img = img_picto($titlealt, 'search.png', $other, false, 1);
3998 
3999  $input = '<input type="image" class="liste_titre" name="button_search" src="'.$img.'" ';
4000  $input .= 'value="'.dol_escape_htmltag($titlealt).'" title="'.dol_escape_htmltag($titlealt).'" >';
4001 
4002  return $input;
4003 }
4004 
4012 function img_searchclear($titlealt = 'default', $other = '')
4013 {
4014  global $conf, $langs;
4015 
4016  if ($titlealt == 'default') $titlealt = $langs->trans('Search');
4017 
4018  $img = img_picto($titlealt, 'searchclear.png', $other, false, 1);
4019 
4020  $input = '<input type="image" class="liste_titre" name="button_removefilter" src="'.$img.'" ';
4021  $input .= 'value="'.dol_escape_htmltag($titlealt).'" title="'.dol_escape_htmltag($titlealt).'" >';
4022 
4023  return $input;
4024 }
4025 
4037 function info_admin($text, $infoonimgalt = 0, $nodiv = 0, $admin = '1', $morecss = '', $textfordropdown = '')
4038 {
4039  global $conf, $langs;
4040 
4041  if ($infoonimgalt)
4042  {
4043  $result = img_picto($text, 'info', 'class="hideonsmartphone'.($morecss ? ' '.$morecss : '').'"');
4044  } else {
4045  if (empty($conf->use_javascript_ajax)) $textfordropdown = '';
4046 
4047  $class = (empty($admin) ? 'undefined' : ($admin == '1' ? 'info' : $admin));
4048  $result = ($nodiv ? '' : '<div class="'.$class.' hideonsmartphone'.($morecss ? ' '.$morecss : '').($textfordropdown ? ' hidden' : '').'">').'<span class="fa fa-info-circle" title="'.dol_escape_htmltag($admin ? $langs->trans('InfoAdmin') : $langs->trans('Note')).'"></span> '.$text.($nodiv ? '' : '</div>');
4049 
4050  if ($textfordropdown) {
4051  $tmpresult .= '<span class="'.$class.'text opacitymedium cursorpointer">'.$langs->trans($textfordropdown).' '.img_picto($langs->trans($textfordropdown), '1downarrow').'</span>';
4052  $tmpresult .= '<script type="text/javascript" language="javascript">
4053  jQuery(document).ready(function() {
4054  jQuery(".'.$class.'text").click(function() {
4055  console.log("toggle text");
4056  jQuery(".'.$class.'").toggle();
4057  });
4058  });
4059  </script>';
4060 
4061  $result = $tmpresult.$result;
4062  }
4063  }
4064 
4065  return $result;
4066 }
4067 
4068 
4080 function dol_print_error($db = '', $error = '', $errors = null)
4081 {
4082  global $conf, $langs, $argv;
4083  global $dolibarr_main_prod;
4084 
4085  $out = '';
4086  $syslog = '';
4087 
4088  // If error occurs before the $lang object was loaded
4089  if (!$langs)
4090  {
4091  require_once DOL_DOCUMENT_ROOT.'/core/class/translate.class.php';
4092  $langs = new Translate('', $conf);
4093  $langs->load("main");
4094  }
4095 
4096  // Load translation files required by the error messages
4097  $langs->loadLangs(array('main', 'errors'));
4098 
4099  if ($_SERVER['DOCUMENT_ROOT']) // Mode web
4100  {
4101  $out .= $langs->trans("DolibarrHasDetectedError").".<br>\n";
4102  if (!empty($conf->global->MAIN_FEATURES_LEVEL)) $out .= "You use an experimental or develop level of features, so please do NOT report any bugs or vulnerability, except if problem is confirmed after moving option MAIN_FEATURES_LEVEL back to 0.<br>\n";
4103  $out .= $langs->trans("InformationToHelpDiagnose").":<br>\n";
4104 
4105  $out .= "<b>".$langs->trans("Date").":</b> ".dol_print_date(time(), 'dayhourlog')."<br>\n";
4106  $out .= "<b>".$langs->trans("Dolibarr").":</b> ".DOL_VERSION." - https://www.dolibarr.org<br>\n";
4107  if (isset($conf->global->MAIN_FEATURES_LEVEL)) $out .= "<b>".$langs->trans("LevelOfFeature").":</b> ".$conf->global->MAIN_FEATURES_LEVEL."<br>\n";
4108  if (function_exists("phpversion"))
4109  {
4110  $out .= "<b>".$langs->trans("PHP").":</b> ".phpversion()."<br>\n";
4111  }
4112  $out .= "<b>".$langs->trans("Server").":</b> ".dol_htmlentities($_SERVER["SERVER_SOFTWARE"])."<br>\n";
4113  if (function_exists("php_uname"))
4114  {
4115  $out .= "<b>".$langs->trans("OS").":</b> ".php_uname()."<br>\n";
4116  }
4117  $out .= "<b>".$langs->trans("UserAgent").":</b> ".dol_htmlentities($_SERVER["HTTP_USER_AGENT"], ENT_COMPAT, 'UTF-8')."<br>\n";
4118  $out .= "<br>\n";
4119  $out .= "<b>".$langs->trans("RequestedUrl").":</b> ".dol_htmlentities($_SERVER["REQUEST_URI"], ENT_COMPAT, 'UTF-8')."<br>\n";
4120  $out .= "<b>".$langs->trans("Referer").":</b> ".(isset($_SERVER["HTTP_REFERER"]) ? dol_htmlentities($_SERVER["HTTP_REFERER"], ENT_COMPAT, 'UTF-8') : '')."<br>\n";
4121  $out .= "<b>".$langs->trans("MenuManager").":</b> ".(isset($conf->standard_menu) ? dol_htmlentities($conf->standard_menu) : '')."<br>\n";
4122  $out .= "<br>\n";
4123  $syslog .= "url=".dol_escape_htmltag($_SERVER["REQUEST_URI"]);
4124  $syslog .= ", query_string=".dol_escape_htmltag($_SERVER["QUERY_STRING"]);
4125  } else // Mode CLI
4126  {
4127  $out .= '> '.$langs->transnoentities("ErrorInternalErrorDetected").":\n".$argv[0]."\n";
4128  $syslog .= "pid=".dol_getmypid();
4129  }
4130 
4131  if (!empty($conf->modules))
4132  {
4133  $out .= "<b>".$langs->trans("Modules").":</b> ".join(', ', $conf->modules)."<br>\n";
4134  }
4135 
4136  if (is_object($db))
4137  {
4138  if ($_SERVER['DOCUMENT_ROOT']) // Mode web
4139  {
4140  $out .= "<b>".$langs->trans("DatabaseTypeManager").":</b> ".$db->type."<br>\n";
4141  $out .= "<b>".$langs->trans("RequestLastAccessInError").":</b> ".($db->lastqueryerror() ? dol_escape_htmltag($db->lastqueryerror()) : $langs->trans("ErrorNoRequestInError"))."<br>\n";
4142  $out .= "<b>".$langs->trans("ReturnCodeLastAccessInError").":</b> ".($db->lasterrno() ? dol_escape_htmltag($db->lasterrno()) : $langs->trans("ErrorNoRequestInError"))."<br>\n";
4143  $out .= "<b>".$langs->trans("InformationLastAccessInError").":</b> ".($db->lasterror() ? dol_escape_htmltag($db->lasterror()) : $langs->trans("ErrorNoRequestInError"))."<br>\n";
4144  $out .= "<br>\n";
4145  } else // Mode CLI
4146  {
4147  // No dol_escape_htmltag for output, we are in CLI mode
4148  $out .= '> '.$langs->transnoentities("DatabaseTypeManager").":\n".$db->type."\n";
4149  $out .= '> '.$langs->transnoentities("RequestLastAccessInError").":\n".($db->lastqueryerror() ? $db->lastqueryerror() : $langs->transnoentities("ErrorNoRequestInError"))."\n";
4150  $out .= '> '.$langs->transnoentities("ReturnCodeLastAccessInError").":\n".($db->lasterrno() ? $db->lasterrno() : $langs->transnoentities("ErrorNoRequestInError"))."\n";
4151  $out .= '> '.$langs->transnoentities("InformationLastAccessInError").":\n".($db->lasterror() ? $db->lasterror() : $langs->transnoentities("ErrorNoRequestInError"))."\n";
4152  }
4153  $syslog .= ", sql=".$db->lastquery();
4154  $syslog .= ", db_error=".$db->lasterror();
4155  }
4156 
4157  if ($error || $errors)
4158  {
4159  $langs->load("errors");
4160 
4161  // Merge all into $errors array
4162  if (is_array($error) && is_array($errors)) $errors = array_merge($error, $errors);
4163  elseif (is_array($error)) $errors = $error;
4164  elseif (is_array($errors)) $errors = array_merge(array($error), $errors);
4165  else $errors = array_merge(array($error));
4166 
4167  foreach ($errors as $msg)
4168  {
4169  if (empty($msg)) continue;
4170  if ($_SERVER['DOCUMENT_ROOT']) // Mode web
4171  {
4172  $out .= "<b>".$langs->trans("Message").":</b> ".dol_escape_htmltag($msg)."<br>\n";
4173  } else // Mode CLI
4174  {
4175  $out .= '> '.$langs->transnoentities("Message").":\n".$msg."\n";
4176  }
4177  $syslog .= ", msg=".$msg;
4178  }
4179  }
4180  if (empty($dolibarr_main_prod) && $_SERVER['DOCUMENT_ROOT'] && function_exists('xdebug_print_function_stack') && function_exists('xdebug_call_file'))
4181  {
4182  xdebug_print_function_stack();
4183  $out .= '<b>XDebug informations:</b>'."<br>\n";
4184  $out .= 'File: '.xdebug_call_file()."<br>\n";
4185  $out .= 'Line: '.xdebug_call_line()."<br>\n";
4186  $out .= 'Function: '.xdebug_call_function()."<br>\n";
4187  $out .= "<br>\n";
4188  }
4189 
4190  // Return a http error code if possible
4191  if (!headers_sent()) {
4192  http_response_code(500);
4193  }
4194 
4195  if (empty($dolibarr_main_prod)) {
4196  print $out;
4197  } else {
4198  if (empty($langs->defaultlang)) $langs->setDefaultLang();
4199  $langs->loadLangs(array("main", "errors")); // Reload main because language may have been set only on previous line so we have to reload files we need.
4200  // This should not happen, except if there is a bug somewhere. Enabled and check log in such case.
4201  print 'This website or feature is currently temporarly not available or failed after a technical error.<br><br>This may be due to a maintenance operation. Current status of operation are on next line...<br><br>'."\n";
4202  print $langs->trans("DolibarrHasDetectedError").'. ';
4203  print $langs->trans("YouCanSetOptionDolibarrMainProdToZero");
4204  define("MAIN_CORE_ERROR", 1);
4205  }
4206 
4207  dol_syslog("Error ".$syslog, LOG_ERR);
4208 }
4209 
4220 function dol_print_error_email($prefixcode, $errormessage = '', $errormessages = array(), $morecss = 'error', $email = '')
4221 {
4222  global $langs, $conf;
4223 
4224  if (empty($email)) $email = $conf->global->MAIN_INFO_SOCIETE_MAIL;
4225 
4226  $langs->load("errors");
4227  $now = dol_now();
4228 
4229  print '<br><div class="center login_main_message"><div class="'.$morecss.'">';
4230  print $langs->trans("ErrorContactEMail", $email, $prefixcode.dol_print_date($now, '%Y%m%d%H%M%S'));
4231  if ($errormessage) print '<br><br>'.$errormessage;
4232  if (is_array($errormessages) && count($errormessages))
4233  {
4234  foreach ($errormessages as $mesgtoshow)
4235  {
4236  print '<br><br>'.$mesgtoshow;
4237  }
4238  }
4239  print '</div></div>';
4240 }
4241 
4258 function print_liste_field_titre($name, $file = "", $field = "", $begin = "", $moreparam = "", $moreattrib = "", $sortfield = "", $sortorder = "", $prefix = "", $tooltip = "", $forcenowrapcolumntitle = 0)
4259 {
4260  print getTitleFieldOfList($name, 0, $file, $field, $begin, $moreparam, $moreattrib, $sortfield, $sortorder, $prefix, 0, $tooltip, $forcenowrapcolumntitle);
4261 }
4262 
4281 function getTitleFieldOfList($name, $thead = 0, $file = "", $field = "", $begin = "", $moreparam = "", $moreattrib = "", $sortfield = "", $sortorder = "", $prefix = "", $disablesortlink = 0, $tooltip = '', $forcenowrapcolumntitle = 0)
4282 {
4283  global $conf, $langs, $form;
4284  //print "$name, $file, $field, $begin, $options, $moreattrib, $sortfield, $sortorder<br>\n";
4285 
4286  if ($moreattrib == 'class="right"') $prefix .= 'right '; // For backward compatibility
4287 
4288  $sortorder = strtoupper($sortorder);
4289  $out = '';
4290  $sortimg = '';
4291 
4292  $tag = 'th';
4293  if ($thead == 2) $tag = 'div';
4294 
4295  $tmpsortfield = explode(',', $sortfield);
4296  $sortfield1 = trim($tmpsortfield[0]); // If $sortfield is 'd.datep,d.id', it becomes 'd.datep'
4297  $tmpfield = explode(',', $field);
4298  $field1 = trim($tmpfield[0]); // If $field is 'd.datep,d.id', it becomes 'd.datep'
4299 
4300  if (empty($conf->global->MAIN_DISABLE_WRAPPING_ON_COLUMN_TITLE) && empty($forcenowrapcolumntitle)) {
4301  $prefix = 'wrapcolumntitle '.$prefix;
4302  }
4303 
4304  //var_dump('field='.$field.' field1='.$field1.' sortfield='.$sortfield.' sortfield1='.$sortfield1);
4305  // If field is used as sort criteria we use a specific css class liste_titre_sel
4306  // Example if (sortfield,field)=("nom","xxx.nom") or (sortfield,field)=("nom","nom")
4307  $liste_titre = 'liste_titre';
4308  if ($field1 && ($sortfield1 == $field1 || $sortfield1 == preg_replace("/^[^\.]+\./", "", $field1))) {
4309  $liste_titre = 'liste_titre_sel';
4310  }
4311  $out .= '<'.$tag.' class="'.$prefix.$liste_titre.'" '.$moreattrib;
4312  //$out .= (($field && empty($conf->global->MAIN_DISABLE_WRAPPING_ON_COLUMN_TITLE) && preg_match('/^[a-zA-Z_0-9\s\.\-:&;]*$/', $name)) ? ' title="'.dol_escape_htmltag($langs->trans($name)).'"' : '');
4313  $out .= ($name && empty($conf->global->MAIN_DISABLE_WRAPPING_ON_COLUMN_TITLE) && empty($forcenowrapcolumntitle) && !dol_textishtml($name)) ? ' title="'.dol_escape_htmltag($langs->trans($name)).'"' : '';
4314  $out .= '>';
4315 
4316  if (empty($thead) && $field && empty($disablesortlink)) // If this is a sort field
4317  {
4318  $options = preg_replace('/sortfield=([a-zA-Z0-9,\s\.]+)/i', '', (is_scalar($moreparam) ? $moreparam : ''));
4319  $options = preg_replace('/sortorder=([a-zA-Z0-9,\s\.]+)/i', '', $options);
4320  $options = preg_replace('/&+/i', '&', $options);
4321  if (!preg_match('/^&/', $options)) $options = '&'.$options;
4322 
4323  $sortordertouseinlink = '';
4324  if ($field1 != $sortfield1) // We are on another field than current sorted field
4325  {
4326  if (preg_match('/^DESC/i', $sortorder))
4327  {
4328  $sortordertouseinlink .= str_repeat('desc,', count(explode(',', $field)));
4329  } else // We reverse the var $sortordertouseinlink
4330  {
4331  $sortordertouseinlink .= str_repeat('asc,', count(explode(',', $field)));
4332  }
4333  } else // We are on field that is the first current sorting criteria
4334  {
4335  if (preg_match('/^ASC/i', $sortorder)) // We reverse the var $sortordertouseinlink
4336  {
4337  $sortordertouseinlink .= str_repeat('desc,', count(explode(',', $field)));
4338  } else {
4339  $sortordertouseinlink .= str_repeat('asc,', count(explode(',', $field)));
4340  }
4341  }
4342  $sortordertouseinlink = preg_replace('/,$/', '', $sortordertouseinlink);
4343  $out .= '<a class="reposition" href="'.$file.'?sortfield='.$field.'&sortorder='.$sortordertouseinlink.'&begin='.$begin.$options.'"';
4344  //$out .= (empty($conf->global->MAIN_DISABLE_WRAPPING_ON_COLUMN_TITLE) ? ' title="'.dol_escape_htmltag($langs->trans($name)).'"' : '');
4345  $out .= '>';
4346  }
4347 
4348  if ($tooltip) {
4349  // You can also use 'TranslationString:keyfortooltiponlick' for a tooltip on click.
4350  $tmptooltip = explode(':', $tooltip);
4351  $out .= $form->textwithpicto($langs->trans($name), $langs->trans($tmptooltip[0]), 1, 'help', '', 0, 3, (empty($tmptooltip[1]) ? '' : 'extra_'.str_replace('.', '_', $field).'_'.$tmptooltip[1]));
4352  }
4353  else $out .= $langs->trans($name);
4354 
4355  if (empty($thead) && $field && empty($disablesortlink)) // If this is a sort field
4356  {
4357  $out .= '</a>';
4358  }
4359 
4360  if (empty($thead) && $field) // If this is a sort field
4361  {
4362  $options = preg_replace('/sortfield=([a-zA-Z0-9,\s\.]+)/i', '', (is_scalar($moreparam) ? $moreparam : ''));
4363  $options = preg_replace('/sortorder=([a-zA-Z0-9,\s\.]+)/i', '', $options);
4364  $options = preg_replace('/&+/i', '&', $options);
4365  if (!preg_match('/^&/', $options)) $options = '&'.$options;
4366 
4367  if (!$sortorder || $field1 != $sortfield1)
4368  {
4369  //$out.= '<a href="'.$file.'?sortfield='.$field.'&sortorder=asc&begin='.$begin.$options.'">'.img_down("A-Z",0).'</a>';
4370  //$out.= '<a href="'.$file.'?sortfield='.$field.'&sortorder=desc&begin='.$begin.$options.'">'.img_up("Z-A",0).'</a>';
4371  } else {
4372  if (preg_match('/^DESC/', $sortorder)) {
4373  //$out.= '<a href="'.$file.'?sortfield='.$field.'&sortorder=asc&begin='.$begin.$options.'">'.img_down("A-Z",0).'</a>';
4374  //$out.= '<a href="'.$file.'?sortfield='.$field.'&sortorder=desc&begin='.$begin.$options.'">'.img_up("Z-A",1).'</a>';
4375  $sortimg .= '<span class="nowrap">'.img_up("Z-A", 0, 'paddingleft').'</span>';
4376  }
4377  if (preg_match('/^ASC/', $sortorder)) {
4378  //$out.= '<a href="'.$file.'?sortfield='.$field.'&sortorder=asc&begin='.$begin.$options.'">'.img_down("A-Z",1).'</a>';
4379  //$out.= '<a href="'.$file.'?sortfield='.$field.'&sortorder=desc&begin='.$begin.$options.'">'.img_up("Z-A",0).'</a>';
4380  $sortimg .= '<span class="nowrap">'.img_down("A-Z", 0, 'paddingleft').'</span>';
4381  }
4382  }
4383  }
4384 
4385  $out .= $sortimg;
4386 
4387  $out .= '</'.$tag.'>';
4388 
4389  return $out;
4390 }
4391 
4400 function print_titre($title)
4401 {
4402  dol_syslog(__FUNCTION__." is deprecated", LOG_WARNING);
4403 
4404  print '<div class="titre">'.$title.'</div>';
4405 }
4406 
4418 function print_fiche_titre($title, $mesg = '', $picto = 'generic', $pictoisfullpath = 0, $id = '')
4419 {
4420  print load_fiche_titre($title, $mesg, $picto, $pictoisfullpath, $id);
4421 }
4422 
4436 function load_fiche_titre($titre, $morehtmlright = '', $picto = 'generic', $pictoisfullpath = 0, $id = '', $morecssontable = '', $morehtmlcenter = '')
4437 {
4438  global $conf;
4439 
4440  $return = '';
4441 
4442  if ($picto == 'setup') $picto = 'generic';
4443 
4444  $return .= "\n";
4445  $return .= '<table '.($id ? 'id="'.$id.'" ' : '').'class="centpercent notopnoleftnoright table-fiche-title'.($morecssontable ? ' '.$morecssontable : '').'">'; // maring bottom must be same than into print_barre_list
4446  $return .= '<tr class="titre">';
4447  if ($picto) $return .= '<td class="nobordernopadding widthpictotitle valignmiddle col-picto">'.img_picto('', $picto, 'class="valignmiddle widthpictotitle pictotitle"', $pictoisfullpath).'</td>';
4448  $return .= '<td class="nobordernopadding valignmiddle col-title">';
4449  $return .= '<div class="titre inline-block">'.$titre.'</div>';
4450  $return .= '</td>';
4451  if (dol_strlen($morehtmlcenter))
4452  {
4453  $return .= '<td class="nobordernopadding center valignmiddle">'.$morehtmlcenter.'</td>';
4454  }
4455  if (dol_strlen($morehtmlright))
4456  {
4457  $return .= '<td class="nobordernopadding titre_right wordbreakimp right valignmiddle">'.$morehtmlright.'</td>';
4458  }
4459  $return .= '</tr></table>'."\n";
4460 
4461  return $return;
4462 }
4463 
4487 function print_barre_liste($titre, $page, $file, $options = '', $sortfield = '', $sortorder = '', $morehtmlcenter = '', $num = -1, $totalnboflines = '', $picto = 'generic', $pictoisfullpath = 0, $morehtmlright = '', $morecss = '', $limit = -1, $hideselectlimit = 0, $hidenavigation = 0, $pagenavastextinput = 0, $morehtmlrightbeforearrow = '')
4488 {
4489  global $conf, $langs;
4490 
4491  $savlimit = $limit;
4492  $savtotalnboflines = $totalnboflines;
4493  $totalnboflines = abs((int) $totalnboflines);
4494 
4495  if ($picto == 'setup') $picto = 'title_setup.png';
4496  if (($conf->browser->name == 'ie') && $picto == 'generic') $picto = 'title.gif';
4497  if ($limit < 0) $limit = $conf->liste_limit;
4498  if ($savlimit != 0 && (($num > $limit) || ($num == -1) || ($limit == 0)))
4499  {
4500  $nextpage = 1;
4501  } else {
4502  $nextpage = 0;
4503  }
4504  //print 'totalnboflines='.$totalnboflines.'-savlimit='.$savlimit.'-limit='.$limit.'-num='.$num.'-nextpage='.$nextpage;
4505 
4506  print "\n";
4507  print "<!-- Begin title -->\n";
4508  print '<table class="centpercent notopnoleftnoright table-fiche-title'.($morecss ? ' '.$morecss : '').'"><tr>'; // maring bottom must be same than into load_fiche_tire
4509 
4510  // Left
4511 
4512  if ($picto && $titre) print '<td class="nobordernopadding widthpictotitle valignmiddle col-picto">'.img_picto('', $picto, 'class="valignmiddle pictotitle widthpictotitle"', $pictoisfullpath).'</td>';
4513  print '<td class="nobordernopadding valignmiddle col-title">';
4514  print '<div class="titre inline-block">'.$titre;
4515  if (!empty($titre) && $savtotalnboflines >= 0 && (string) $savtotalnboflines != '') print '<span class="opacitymedium colorblack paddingleft">('.$totalnboflines.')</span>';
4516  print '</div></td>';
4517 
4518  // Center
4519  if ($morehtmlcenter)
4520  {
4521  print '<td class="nobordernopadding center valignmiddle">'.$morehtmlcenter.'</td>';
4522  }
4523 
4524  // Right
4525  print '<td class="nobordernopadding valignmiddle right">';
4526  print '<input type="hidden" name="pageplusoneold" value="'.((int) $page + 1).'">';
4527  if ($sortfield) $options .= "&sortfield=".urlencode($sortfield);
4528  if ($sortorder) $options .= "&sortorder=".urlencode($sortorder);
4529  // Show navigation bar
4530  $pagelist = '';
4531  if ($savlimit != 0 && ($page > 0 || $num > $limit))
4532  {
4533  if ($totalnboflines) // If we know total nb of lines
4534  {
4535  // Define nb of extra page links before and after selected page + ... + first or last
4536  $maxnbofpage = (empty($conf->dol_optimize_smallscreen) ? 4 : 0);
4537 
4538  if ($limit > 0) $nbpages = ceil($totalnboflines / $limit);
4539  else $nbpages = 1;
4540  $cpt = ($page - $maxnbofpage);
4541  if ($cpt < 0) { $cpt = 0; }
4542 
4543  if ($cpt >= 1)
4544  {
4545  if (empty($pagenavastextinput)) {
4546  $pagelist .= '<li class="pagination"><a href="'.$file.'?page=0'.$options.'">1</a></li>';
4547  if ($cpt > 2) $pagelist .= '<li class="pagination"><span class="inactive">...</span></li>';
4548  elseif ($cpt == 2) $pagelist .= '<li class="pagination"><a href="'.$file.'?page=1'.$options.'">2</a></li>';
4549  }
4550  }
4551 
4552  do {
4553  if ($pagenavastextinput) {
4554  if ($cpt == $page)
4555  {
4556  $pagelist .= '<li class="pagination"><input type="text" class="width25 center pageplusone" name="pageplusone" value="'.($page + 1).'"></li>';
4557  $pagelist .= '/';
4558  //if (($cpt + 1) < $nbpages) $pagelist .= '/';
4559  }
4560  } else {
4561  if ($cpt == $page)
4562  {
4563  $pagelist .= '<li class="pagination"><span class="active">'.($page + 1).'</span></li>';
4564  } else {
4565  $pagelist .= '<li class="pagination"><a href="'.$file.'?page='.$cpt.$options.'">'.($cpt + 1).'</a></li>';
4566  }
4567  }
4568  $cpt++;
4569  } while ($cpt < $nbpages && $cpt <= ($page + $maxnbofpage));
4570 
4571  if (empty($pagenavastextinput)) {
4572  if ($cpt < $nbpages)
4573  {
4574  if ($cpt < $nbpages - 2) $pagelist .= '<li class="pagination"><span class="inactive">...</span></li>';
4575  elseif ($cpt == $nbpages - 2) $pagelist .= '<li class="pagination"><a href="'.$file.'?page='.($nbpages - 2).$options.'">'.($nbpages - 1).'</a></li>';
4576  $pagelist .= '<li class="pagination"><a href="'.$file.'?page='.($nbpages - 1).$options.'">'.$nbpages.'</a></li>';
4577  }
4578  } else {
4579  //var_dump($page.' '.$cpt.' '.$nbpages);
4580  //if (($page + 1) < $nbpages) {
4581  $pagelist .= '<li class="pagination"><a href="'.$file.'?page='.($nbpages - 1).$options.'">'.$nbpages.'</a></li>';
4582  //}
4583  }
4584  } else {
4585  $pagelist .= '<li class="pagination"><span class="active">'.($page + 1)."</li>";
4586  }
4587  }
4588 
4589  if ($savlimit || $morehtmlright || $morehtmlrightbeforearrow) {
4590  print_fleche_navigation($page, $file, $options, $nextpage, $pagelist, $morehtmlright, $savlimit, $totalnboflines, $hideselectlimit, $morehtmlrightbeforearrow); // output the div and ul for previous/last completed with page numbers into $pagelist
4591  }
4592 
4593  // js to autoselect page field on focus
4594  if ($pagenavastextinput) {
4595  print ajax_autoselect('.pageplusone');
4596  }
4597 
4598  print '</td>';
4599 
4600  print '</tr></table>'."\n";
4601  print "<!-- End title -->\n\n";
4602 }
4603 
4619 function print_fleche_navigation($page, $file, $options = '', $nextpage = 0, $betweenarrows = '', $afterarrows = '', $limit = -1, $totalnboflines = 0, $hideselectlimit = 0, $beforearrows = '')
4620 {
4621  global $conf, $langs;
4622 
4623  print '<div class="pagination"><ul>';
4624  if ($beforearrows)
4625  {
4626  print '<li class="paginationbeforearrows">';
4627  print $beforearrows;
4628  print '</li>';
4629  }
4630  if ((int) $limit > 0 && empty($hideselectlimit))
4631  {
4632  $pagesizechoices = '10:10,15:15,20:20,30:30,40:40,50:50,100:100,250:250,500:500,1000:1000,5000:5000,25000:25000';
4633  //$pagesizechoices.=',0:'.$langs->trans("All"); // Not yet supported
4634  //$pagesizechoices.=',2:2';
4635  if (!empty($conf->global->MAIN_PAGESIZE_CHOICES)) $pagesizechoices = $conf->global->MAIN_PAGESIZE_CHOICES;
4636 
4637  print '<li class="pagination">';
4638  print '<select class="flat selectlimit" name="limit" title="'.dol_escape_htmltag($langs->trans("MaxNbOfRecordPerPage")).'">';
4639  $tmpchoice = explode(',', $pagesizechoices);
4640  $tmpkey = $limit.':'.$limit;
4641  if (!in_array($tmpkey, $tmpchoice)) $tmpchoice[] = $tmpkey;
4642  $tmpkey = $conf->liste_limit.':'.$conf->liste_limit;
4643  if (!in_array($tmpkey, $tmpchoice)) $tmpchoice[] = $tmpkey;
4644  asort($tmpchoice, SORT_NUMERIC);
4645  foreach ($tmpchoice as $val)
4646  {
4647  $selected = '';
4648  $tmp = explode(':', $val);
4649  $key = $tmp[0];
4650  $val = $tmp[1];
4651  if ($key != '' && $val != '')
4652  {
4653  if ((int) $key == (int) $limit)
4654  {
4655  $selected = ' selected="selected"';
4656  }
4657  print '<option name="'.$key.'"'.$selected.'>'.dol_escape_htmltag($val).'</option>'."\n";
4658  }
4659  }
4660  print '</select>';
4661  if ($conf->use_javascript_ajax)
4662  {
4663  print '<!-- JS CODE TO ENABLE select limit to launch submit of page -->
4664  <script>
4665  jQuery(document).ready(function () {
4666  jQuery(".selectlimit").change(function() {
4667  console.log("Change limit. Send submit");
4668  $(this).parents(\'form:first\').submit();
4669  });
4670  });
4671  </script>
4672  ';
4673  }
4674  print '</li>';
4675  }
4676  if ($page > 0)
4677  {
4678  print '<li class="pagination paginationpage paginationpageleft"><a class="paginationprevious" href="'.$file.'?page='.($page - 1).$options.'"><i class="fa fa-chevron-left" title="'.dol_escape_htmltag($langs->trans("Previous")).'"></i></a></li>';
4679  }
4680  if ($betweenarrows)
4681  {
4682  print '<!--<div class="betweenarrows nowraponall inline-block">-->';
4683  print $betweenarrows;
4684  print '<!--</div>-->';
4685  }
4686  if ($nextpage > 0)
4687  {
4688  print '<li class="pagination paginationpage paginationpageright"><a class="paginationnext" href="'.$file.'?page='.($page + 1).$options.'"><i class="fa fa-chevron-right" title="'.dol_escape_htmltag($langs->trans("Next")).'"></i></a></li>';
4689  }
4690  if ($afterarrows)
4691  {
4692  print '<li class="paginationafterarrows">';
4693  print $afterarrows;
4694  print '</li>';
4695  }
4696  print '</ul></div>'."\n";
4697 }
4698 
4699 
4710 function vatrate($rate, $addpercent = false, $info_bits = 0, $usestarfornpr = 0)
4711 {
4712  $morelabel = '';
4713 
4714  if (preg_match('/%/', $rate))
4715  {
4716  $rate = str_replace('%', '', $rate);
4717  $addpercent = true;
4718  }
4719  if (preg_match('/\((.*)\)/', $rate, $reg))
4720  {
4721  $morelabel = ' ('.$reg[1].')';
4722  $rate = preg_replace('/\s*'.preg_quote($morelabel, '/').'/', '', $rate);
4723  }
4724  if (preg_match('/\*/', $rate))
4725  {
4726  $rate = str_replace('*', '', $rate);
4727  $info_bits |= 1;
4728  }
4729 
4730  // If rate is '9/9/9' we don't change it. If rate is '9.000' we apply price()
4731  if (!preg_match('/\//', $rate)) $ret = price($rate, 0, '', 0, 0).($addpercent ? '%' : '');
4732  else {
4733  // TODO Split on / and output with a price2num to have clean numbers without ton of 000.
4734  $ret = $rate.($addpercent ? '%' : '');
4735  }
4736  if (($info_bits & 1) && $usestarfornpr >= 0) $ret .= ' *';
4737  $ret .= $morelabel;
4738  return $ret;
4739 }
4740 
4741 
4757 function price($amount, $form = 0, $outlangs = '', $trunc = 1, $rounding = -1, $forcerounding = -1, $currency_code = '')
4758 {
4759  global $langs, $conf;
4760 
4761  // Clean parameters
4762  if (empty($amount)) $amount = 0; // To have a numeric value if amount not defined or = ''
4763  $amount = (is_numeric($amount) ? $amount : 0); // Check if amount is numeric, for example, an error occured when amount value = o (letter) instead 0 (number)
4764  if ($rounding < 0) $rounding = min($conf->global->MAIN_MAX_DECIMALS_UNIT, $conf->global->MAIN_MAX_DECIMALS_TOT);
4765  $nbdecimal = $rounding;
4766 
4767  // Output separators by default (french)
4768  $dec = ','; $thousand = ' ';
4769 
4770  // If $outlangs not forced, we use use language
4771  if (!is_object($outlangs)) $outlangs = $langs;
4772 
4773  if ($outlangs->transnoentitiesnoconv("SeparatorDecimal") != "SeparatorDecimal") $dec = $outlangs->transnoentitiesnoconv("SeparatorDecimal");
4774  if ($outlangs->transnoentitiesnoconv("SeparatorThousand") != "SeparatorThousand") $thousand = $outlangs->transnoentitiesnoconv("SeparatorThousand");
4775  if ($thousand == 'None') $thousand = '';
4776  elseif ($thousand == 'Space') $thousand = ' ';
4777  //print "outlangs=".$outlangs->defaultlang." amount=".$amount." html=".$form." trunc=".$trunc." nbdecimal=".$nbdecimal." dec='".$dec."' thousand='".$thousand."'<br>";
4778 
4779  //print "amount=".$amount."-";
4780  $amount = str_replace(',', '.', $amount); // should be useless
4781  //print $amount."-";
4782  $datas = explode('.', $amount);
4783  $decpart = isset($datas[1]) ? $datas[1] : '';
4784  $decpart = preg_replace('/0+$/i', '', $decpart); // Supprime les 0 de fin de partie decimale
4785  //print "decpart=".$decpart."<br>";
4786  $end = '';
4787 
4788  // We increase nbdecimal if there is more decimal than asked (to not loose information)
4789  if (dol_strlen($decpart) > $nbdecimal) $nbdecimal = dol_strlen($decpart);
4790  // Si on depasse max
4791  if ($trunc && $nbdecimal > $conf->global->MAIN_MAX_DECIMALS_SHOWN)
4792  {
4793  $nbdecimal = $conf->global->MAIN_MAX_DECIMALS_SHOWN;
4794  if (preg_match('/\.\.\./i', $conf->global->MAIN_MAX_DECIMALS_SHOWN))
4795  {
4796  // Si un affichage est tronque, on montre des ...
4797  $end = '...';
4798  }
4799  }
4800 
4801  // If force rounding
4802  if ($forcerounding >= 0) $nbdecimal = $forcerounding;
4803 
4804  // Format number
4805  $output = number_format($amount, $nbdecimal, $dec, $thousand);
4806  if ($form)
4807  {
4808  $output = preg_replace('/\s/', '&nbsp;', $output);
4809  $output = preg_replace('/\'/', '&#039;', $output);
4810  }
4811  // Add symbol of currency if requested
4812  $cursymbolbefore = $cursymbolafter = '';
4813  if ($currency_code)
4814  {
4815  if ($currency_code == 'auto') $currency_code = $conf->currency;
4816 
4817  $listofcurrenciesbefore = array('AUD', 'CAD', 'CNY', 'COP', 'CLP', 'GBP', 'HKD', 'MXN', 'PEN', 'USD');
4818  $listoflanguagesbefore = array('nl_NL');
4819  if (in_array($currency_code, $listofcurrenciesbefore) || in_array($outlangs->defaultlang, $listoflanguagesbefore))
4820  {
4821  $cursymbolbefore .= $outlangs->getCurrencySymbol($currency_code);
4822  } else {
4823  $tmpcur = $outlangs->getCurrencySymbol($currency_code);
4824  $cursymbolafter .= ($tmpcur == $currency_code ? ' '.$tmpcur : $tmpcur);
4825  }
4826  }
4827  $output = $cursymbolbefore.$output.$end.($cursymbolafter ? ' ' : '').$cursymbolafter;
4828 
4829  return $output;
4830 }
4831 
4853 function price2num($amount, $rounding = '', $option = 0)
4854 {
4855  global $langs, $conf;
4856 
4857  // Round PHP function does not allow number like '1,234.56' nor '1.234,56' nor '1 234,56'
4858  // Numbers must be '1234.56'
4859  // Decimal delimiter for PHP and database SQL requests must be '.'
4860  $dec = ','; $thousand = ' ';
4861  if ($langs->transnoentitiesnoconv("SeparatorDecimal") != "SeparatorDecimal") $dec = $langs->transnoentitiesnoconv("SeparatorDecimal");
4862  if ($langs->transnoentitiesnoconv("SeparatorThousand") != "SeparatorThousand") $thousand = $langs->transnoentitiesnoconv("SeparatorThousand");
4863  if ($thousand == 'None') $thousand = '';
4864  elseif ($thousand == 'Space') $thousand = ' ';
4865  //print "amount=".$amount." html=".$form." trunc=".$trunc." nbdecimal=".$nbdecimal." dec='".$dec."' thousand='".$thousand."'<br>";
4866 
4867  // Convert value to universal number format (no thousand separator, '.' as decimal separator)
4868  if ($option != 1) { // If not a PHP number or unknown, we change or clean format
4869  //print "\n".'PP'.$amount.' - '.$dec.' - '.$thousand.' - '.intval($amount).'<br>';
4870  if (!is_numeric($amount)) {
4871  $amount = preg_replace('/[a-zA-Z\/\\\*\(\)<>\_]/', '', $amount);
4872  }
4873 
4874  if ($option == 2 && $thousand == '.' && preg_match('/\.(\d\d\d)$/', (string) $amount)) { // It means the . is used as a thousand separator and string come from input data, so 1.123 is 1123
4875  $amount = str_replace($thousand, '', $amount);
4876  }
4877 
4878  // Convert amount to format with dolibarr dec and thousand (this is because PHP convert a number
4879  // to format defined by LC_NUMERIC after a calculation and we want source format to be like defined by Dolibarr setup.
4880  // So if number was already a good number, it is converted into local Dolibarr setup.
4881  if (is_numeric($amount))
4882  {
4883  // We put in temps value of decimal ("0.00001"). Works with 0 and 2.0E-5 and 9999.10
4884  $temps = sprintf("%0.10F", $amount - intval($amount)); // temps=0.0000000000 or 0.0000200000 or 9999.1000000000
4885  $temps = preg_replace('/([\.1-9])0+$/', '\\1', $temps); // temps=0. or 0.00002 or 9999.1
4886  $nbofdec = max(0, dol_strlen($temps) - 2); // -2 to remove "0."
4887  $amount = number_format($amount, $nbofdec, $dec, $thousand);
4888  }
4889  //print "QQ".$amount."<br>\n";
4890 
4891  // Now make replace (the main goal of function)
4892  if ($thousand != ',' && $thousand != '.') {
4893  $amount = str_replace(',', '.', $amount); // To accept 2 notations for french users
4894  }
4895  $amount = str_replace(' ', '', $amount); // To avoid spaces
4896  $amount = str_replace($thousand, '', $amount); // Replace of thousand before replace of dec to avoid pb if thousand is .
4897  $amount = str_replace($dec, '.', $amount);
4898  }
4899  //print ' XX'.$amount.' '.$rounding;
4900 
4901  // Now, make a rounding if required
4902  if ($rounding)
4903  {
4904  $nbofdectoround = '';
4905  if ($rounding == 'MU') {
4906  $nbofdectoround = $conf->global->MAIN_MAX_DECIMALS_UNIT;
4907  }
4908  elseif ($rounding == 'MT') {
4909  $nbofdectoround = $conf->global->MAIN_MAX_DECIMALS_TOT;
4910  }
4911  elseif ($rounding == 'MS') {
4912  $nbofdectoround = empty($conf->global->MAIN_MAX_DECIMALS_STOCK) ? 5 : $conf->global->MAIN_MAX_DECIMALS_STOCK;
4913  }
4914  elseif ($rounding == 'CU') {
4915  $nbofdectoround = max($conf->global->MAIN_MAX_DECIMALS_UNIT, 8); // TODO Use param of currency
4916  }
4917  elseif ($rounding == 'CT') {
4918  $nbofdectoround = max($conf->global->MAIN_MAX_DECIMALS_TOT, 8); // TODO Use param of currency
4919  }
4920  elseif (is_numeric($rounding)) $nbofdectoround = $rounding;
4921  //print " RR".$amount.' - '.$nbofdectoround.'<br>';
4922  if (dol_strlen($nbofdectoround)) $amount = round(is_string($amount) ? (float) $amount : $amount, $nbofdectoround); // $nbofdectoround can be 0.
4923  else return 'ErrorBadParameterProvidedToFunction';
4924  //print ' SS'.$amount.' - '.$nbofdec.' - '.$dec.' - '.$thousand.' - '.$nbofdectoround.'<br>';
4925 
4926  // Convert amount to format with dolibarr dec and thousand (this is because PHP convert a number
4927  // to format defined by LC_NUMERIC after a calculation and we want source format to be defined by Dolibarr setup.
4928  if (is_numeric($amount))
4929  {
4930  // We put in temps value of decimal ("0.00001"). Works with 0 and 2.0E-5 and 9999.10
4931  $temps = sprintf("%0.10F", $amount - intval($amount)); // temps=0.0000000000 or 0.0000200000 or 9999.1000000000
4932  $temps = preg_replace('/([\.1-9])0+$/', '\\1', $temps); // temps=0. or 0.00002 or 9999.1
4933  $nbofdec = max(0, dol_strlen($temps) - 2); // -2 to remove "0."
4934  $amount = number_format($amount, min($nbofdec, $nbofdectoround), $dec, $thousand); // Convert amount to format with dolibarr dec and thousand
4935  }
4936  //print "TT".$amount.'<br>';
4937 
4938  // Always make replace because each math function (like round) replace
4939  // with local values and we want a number that has a SQL string format x.y
4940  if ($thousand != ',' && $thousand != '.') $amount = str_replace(',', '.', $amount); // To accept 2 notations for french users
4941  $amount = str_replace(' ', '', $amount); // To avoid spaces
4942  $amount = str_replace($thousand, '', $amount); // Replace of thousand before replace of dec to avoid pb if thousand is .
4943  $amount = str_replace($dec, '.', $amount);
4944  }
4945 
4946  return $amount;
4947 }
4948 
4960 function showDimensionInBestUnit($dimension, $unit, $type, $outputlangs, $round = -1, $forceunitoutput = 'no')
4961 {
4962  require_once DOL_DOCUMENT_ROOT.'/core/lib/product.lib.php';
4963 
4964  if (($forceunitoutput == 'no' && $dimension < 1 / 10000 && $unit < 90) || (is_numeric($forceunitoutput) && $forceunitoutput == -6))
4965  {
4966  $dimension = $dimension * 1000000;
4967  $unit = $unit - 6;
4968  } elseif (($forceunitoutput == 'no' && $dimension < 1 / 10 && $unit < 90) || (is_numeric($forceunitoutput) && $forceunitoutput == -3))
4969  {
4970  $dimension = $dimension * 1000;
4971  $unit = $unit - 3;
4972  } elseif (($forceunitoutput == 'no' && $dimension > 100000000 && $unit < 90) || (is_numeric($forceunitoutput) && $forceunitoutput == 6))
4973  {
4974  $dimension = $dimension / 1000000;
4975  $unit = $unit + 6;
4976  } elseif (($forceunitoutput == 'no' && $dimension > 100000 && $unit < 90) || (is_numeric($forceunitoutput) && $forceunitoutput == 3))
4977  {
4978  $dimension = $dimension / 1000;
4979  $unit = $unit + 3;
4980  }
4981  // Special case when we want output unit into pound or ounce
4982  /* TODO
4983  if ($unit < 90 && $type == 'weight' && is_numeric($forceunitoutput) && (($forceunitoutput == 98) || ($forceunitoutput == 99))
4984  {
4985  $dimension = // convert dimension from standard unit into ounce or pound
4986  $unit = $forceunitoutput;
4987  }
4988  if ($unit > 90 && $type == 'weight' && is_numeric($forceunitoutput) && $forceunitoutput < 90)
4989  {
4990  $dimension = // convert dimension from standard unit into ounce or pound
4991  $unit = $forceunitoutput;
4992  }*/
4993 
4994  $ret = price($dimension, 0, $outputlangs, 0, 0, $round).' '.measuringUnitString(0, $type, $unit);
4995 
4996  return $ret;
4997 }
4998 
4999 
5012 function get_localtax($vatrate, $local, $thirdparty_buyer = "", $thirdparty_seller = "", $vatnpr = 0)
5013 {
5014  global $db, $conf, $mysoc;
5015 
5016  if (empty($thirdparty_seller) || !is_object($thirdparty_seller)) $thirdparty_seller = $mysoc;
5017 
5018  dol_syslog("get_localtax tva=".$vatrate." local=".$local." thirdparty_buyer id=".(is_object($thirdparty_buyer) ? $thirdparty_buyer->id : '')."/country_code=".(is_object($thirdparty_buyer) ? $thirdparty_buyer->country_code : '')." thirdparty_seller id=".$thirdparty_seller->id."/country_code=".$thirdparty_seller->country_code." thirdparty_seller localtax1_assuj=".$thirdparty_seller->localtax1_assuj." thirdparty_seller localtax2_assuj=".$thirdparty_seller->localtax2_assuj);
5019 
5020  $vatratecleaned = $vatrate;
5021  $reg = array();
5022  if (preg_match('/^(.*)\s*\((.*)\)$/', $vatrate, $reg)) { // If vat is "xx (yy)"
5023  $vatratecleaned = trim($reg[1]);
5024  $vatratecode = $reg[2];
5025  }
5026 
5027  /*if ($thirdparty_buyer->country_code != $thirdparty_seller->country_code)
5028  {
5029  return 0;
5030  }*/
5031 
5032  // Some test to guess with no need to make database access
5033  if ($mysoc->country_code == 'ES') { // For spain localtaxes 1 and 2, tax is qualified if buyer use local tax
5034  if ($local == 1) {
5035  if (!$mysoc->localtax1_assuj || (string) $vatratecleaned == "0") return 0;
5036  if ($thirdparty_seller->id == $mysoc->id) {
5037  if (!$thirdparty_buyer->localtax1_assuj) return 0;
5038  } else {
5039  if (!$thirdparty_seller->localtax1_assuj) return 0;
5040  }
5041  }
5042 
5043  if ($local == 2) {
5044  //if (! $mysoc->localtax2_assuj || (string) $vatratecleaned == "0") return 0;
5045  if (!$mysoc->localtax2_assuj) return 0; // If main vat is 0, IRPF may be different than 0.
5046  if ($thirdparty_seller->id == $mysoc->id) {
5047  if (!$thirdparty_buyer->localtax2_assuj) return 0;
5048  } else {
5049  if (!$thirdparty_seller->localtax2_assuj) return 0;
5050  }
5051  }
5052  } else {
5053  if ($local == 1 && !$thirdparty_seller->localtax1_assuj) return 0;
5054  if ($local == 2 && !$thirdparty_seller->localtax2_assuj) return 0;
5055  }
5056 
5057  // For some country MAIN_GET_LOCALTAXES_VALUES_FROM_THIRDPARTY is forced to on.
5058  if (in_array($mysoc->country_code, array('ES'))) {
5059  $conf->global->MAIN_GET_LOCALTAXES_VALUES_FROM_THIRDPARTY = 1;
5060  }
5061 
5062  // Search local taxes
5063  if (!empty($conf->global->MAIN_GET_LOCALTAXES_VALUES_FROM_THIRDPARTY))
5064  {
5065  if ($local == 1) {
5066  if ($thirdparty_seller != $mysoc) {
5067  if (!isOnlyOneLocalTax($local)) // TODO We should provide $vatrate to search on correct line and not always on line with highest vat rate
5068  {
5069  return $thirdparty_seller->localtax1_value;
5070  }
5071  } else { // i am the seller
5072  if (!isOnlyOneLocalTax($local)) { // TODO If seller is me, why not always returning this, even if there is only one locatax vat.
5073  return $conf->global->MAIN_INFO_VALUE_LOCALTAX1;
5074  }
5075  }
5076  }
5077  if ($local == 2) {
5078  if ($thirdparty_seller != $mysoc) {
5079  if (!isOnlyOneLocalTax($local)) // TODO We should provide $vatrate to search on correct line and not always on line with highest vat rate
5080  // TODO We should also return value defined on thirdparty only if defined
5081  {
5082  return $thirdparty_seller->localtax2_value;
5083  }
5084  } else { // i am the seller
5085  if (in_array($mysoc->country_code, array('ES'))) {
5086  return $thirdparty_buyer->localtax2_value;
5087  } else {
5088  return $conf->global->MAIN_INFO_VALUE_LOCALTAX2;
5089  }
5090  }
5091  }
5092  }
5093 
5094  // By default, search value of local tax on line of common tax
5095  $sql = "SELECT t.localtax1, t.localtax2, t.localtax1_type, t.localtax2_type";
5096  $sql .= " FROM ".MAIN_DB_PREFIX."c_tva as t, ".MAIN_DB_PREFIX."c_country as c";
5097  $sql .= " WHERE t.fk_pays = c.rowid AND c.code = '".$db->escape($thirdparty_seller->country_code)."'";
5098  $sql .= " AND t.taux = ".((float) $vatratecleaned)." AND t.active = 1";
5099  if (!empty($vatratecode)) $sql .= " AND t.code ='".$db->escape($vatratecode)."'"; // If we have the code, we use it in priority
5100  else $sql .= " AND t.recuperableonly = '".$db->escape($vatnpr)."'";
5101  dol_syslog("get_localtax", LOG_DEBUG);
5102  $resql = $db->query($sql);
5103 
5104  if ($resql)
5105  {
5106  $obj = $db->fetch_object($resql);
5107  if ($obj) {
5108  if ($local == 1) return $obj->localtax1;
5109  elseif ($local == 2) return $obj->localtax2;
5110  }
5111  }
5112 
5113  return 0;
5114 }
5115 
5116 
5125 function isOnlyOneLocalTax($local)
5126 {
5127  $tax = get_localtax_by_third($local);
5128 
5129  $valors = explode(":", $tax);
5130 
5131  if (count($valors) > 1) {
5132  return false;
5133  } else {
5134  return true;
5135  }
5136 }
5137 
5144 function get_localtax_by_third($local)
5145 {
5146  global $db, $mysoc;
5147  $sql = "SELECT t.localtax1, t.localtax2 ";
5148  $sql .= " FROM ".MAIN_DB_PREFIX."c_tva as t inner join ".MAIN_DB_PREFIX."c_country as c ON c.rowid=t.fk_pays";
5149  $sql .= " WHERE c.code = '".$db->escape($mysoc->country_code)."' AND t.active = 1 AND t.taux=(";
5150  $sql .= " SELECT max(tt.taux) FROM ".MAIN_DB_PREFIX."c_tva as tt inner join ".MAIN_DB_PREFIX."c_country as c ON c.rowid=tt.fk_pays";
5151  $sql .= " WHERE c.code = '".$db->escape($mysoc->country_code)."' AND tt.active = 1";
5152  $sql .= " )";
5153 
5154  $resql = $db->query($sql);
5155  if ($resql)
5156  {
5157  $obj = $db->fetch_object($resql);
5158  if ($local == 1) return $obj->localtax1;
5159  elseif ($local == 2) return $obj->localtax2;
5160  }
5161 
5162  return 0;
5163 }
5164 
5165 
5177 function getTaxesFromId($vatrate, $buyer = null, $seller = null, $firstparamisid = 1)
5178 {
5179  global $db, $mysoc;
5180 
5181  dol_syslog("getTaxesFromId vat id or rate = ".$vatrate);
5182 
5183  // Search local taxes
5184  $sql = "SELECT t.rowid, t.code, t.taux as rate, t.recuperableonly as npr, t.accountancy_code_sell, t.accountancy_code_buy,";
5185  $sql .= " t.localtax1, t.localtax1_type, t.localtax2, t.localtax2_type";
5186  $sql .= " FROM ".MAIN_DB_PREFIX."c_tva as t";
5187  if ($firstparamisid) {
5188  $sql .= " WHERE t.rowid = ".(int) $vatrate;
5189  } else {
5190  $vatratecleaned = $vatrate;
5191  $vatratecode = '';
5192  $reg = array();
5193  if (preg_match('/^(.*)\s*\((.*)\)$/', $vatrate, $reg)) // If vat is "xx (yy)"
5194  {
5195  $vatratecleaned = $reg[1];
5196  $vatratecode = $reg[2];
5197  }
5198 
5199  $sql .= ", ".MAIN_DB_PREFIX."c_country as c";
5200  /*if ($mysoc->country_code == 'ES') $sql.= " WHERE t.fk_pays = c.rowid AND c.code = '".$db->escape($buyer->country_code)."'"; // vat in spain use the buyer country ??
5201  else $sql.= " WHERE t.fk_pays = c.rowid AND c.code = '".$db->escape($seller->country_code)."'";*/
5202  $sql .= " WHERE t.fk_pays = c.rowid AND c.code = '".$db->escape($seller->country_code)."'";
5203  $sql .= " AND t.taux = ".((float) $vatratecleaned)." AND t.active = 1";
5204  if ($vatratecode) $sql .= " AND t.code = '".$db->escape($vatratecode)."'";
5205  }
5206 
5207  $resql = $db->query($sql);
5208  if ($resql) {
5209  $obj = $db->fetch_object($resql);
5210  if ($obj) return array(
5211  'rowid'=>$obj->rowid,
5212  'code'=>$obj->code,
5213  'rate'=>$obj->rate,
5214  'localtax1'=>$obj->localtax1,
5215  'localtax1_type'=>$obj->localtax1_type,
5216  'localtax2'=>$obj->localtax2,
5217  'localtax2_type'=>$obj->localtax2_type,
5218  'npr'=>$obj->npr,
5219  'accountancy_code_sell'=>$obj->accountancy_code_sell,
5220  'accountancy_code_buy'=>$obj->accountancy_code_buy
5221  );
5222  else return array();
5223  } else dol_print_error($db);
5224 
5225  return array();
5226 }
5227 
5244 function getLocalTaxesFromRate($vatrate, $local, $buyer, $seller, $firstparamisid = 0)
5245 {
5246  global $db, $mysoc;
5247 
5248  dol_syslog("getLocalTaxesFromRate vatrate=".$vatrate." local=".$local);
5249 
5250  // Search local taxes
5251  $sql = "SELECT t.taux as rate, t.code, t.localtax1, t.localtax1_type, t.localtax2, t.localtax2_type, t.accountancy_code_sell, t.accountancy_code_buy";
5252  $sql .= " FROM ".MAIN_DB_PREFIX."c_tva as t";
5253  if ($firstparamisid) {
5254  $sql .= " WHERE t.rowid = ".(int) $vatrate;
5255  } else {
5256  $vatratecleaned = $vatrate;
5257  $vatratecode = '';
5258  $reg = array();
5259  if (preg_match('/^(.*)\s*\((.*)\)$/', $vatrate, $reg)) { // If vat is "x.x (yy)"
5260  $vatratecleaned = $reg[1];
5261  $vatratecode = $reg[2];
5262  }
5263 
5264  $sql .= ", ".MAIN_DB_PREFIX."c_country as c";
5265  if ($mysoc->country_code == 'ES') $sql .= " WHERE t.fk_pays = c.rowid AND c.code = '".$db->escape($buyer->country_code)."'"; // local tax in spain use the buyer country ??
5266  else $sql .= " WHERE t.fk_pays = c.rowid AND c.code = '".$db->escape(empty($seller->country_code) ? $mysoc->country_code : $seller->country_code)."'";
5267  $sql .= " AND t.taux = ".((float) $vatratecleaned)." AND t.active = 1";
5268  if ($vatratecode) $sql .= " AND t.code = '".$db->escape($vatratecode)."'";
5269  }
5270 
5271  $resql = $db->query($sql);
5272  if ($resql) {
5273  $obj = $db->fetch_object($resql);
5274 
5275  if ($obj) {
5276  $vateratestring = $obj->rate.($obj->code ? ' ('.$obj->code.')' : '');
5277 
5278  if ($local == 1) {
5279  return array($obj->localtax1_type, get_localtax($vateratestring, $local, $buyer, $seller), $obj->accountancy_code_sell, $obj->accountancy_code_buy);
5280  } elseif ($local == 2) {
5281  return array($obj->localtax2_type, get_localtax($vateratestring, $local, $buyer, $seller), $obj->accountancy_code_sell, $obj->accountancy_code_buy);
5282  } else {
5283  return array($obj->localtax1_type, get_localtax($vateratestring, 1, $buyer, $seller), $obj->localtax2_type, get_localtax($vateratestring, 2, $buyer, $seller), $obj->accountancy_code_sell, $obj->accountancy_code_buy);
5284  }
5285  }
5286  }
5287 
5288  return array();
5289 }
5290 
5301 function get_product_vat_for_country($idprod, $thirdparty_seller, $idprodfournprice = 0)
5302 {
5303  global $db, $conf, $mysoc;
5304 
5305  require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
5306 
5307  $ret = 0;
5308  $found = 0;
5309 
5310  if ($idprod > 0)
5311  {
5312  // Load product
5313  $product = new Product($db);
5314  $result = $product->fetch($idprod);
5315 
5316  if ($mysoc->country_code == $thirdparty_seller->country_code) // If selling country is ours
5317  {
5318  if ($idprodfournprice > 0) // We want vat for product for a "supplier" object
5319  {
5320  $product->get_buyprice($idprodfournprice, 0, 0, 0);
5321  $ret = $product->vatrate_supplier;
5322  if ($product->default_vat_code) $ret .= ' ('.$product->default_vat_code.')';
5323  } else {
5324  $ret = $product->tva_tx; // Default vat of product we defined
5325  if ($product->default_vat_code) $ret .= ' ('.$product->default_vat_code.')';
5326  }
5327  $found = 1;
5328  } else {
5329  // TODO Read default product vat according to countrycode and product. Vat for couple countrycode/product is a feature not implemeted yet.
5330  // May be usefull/required if hidden option SERVICE_ARE_ECOMMERCE_200238EC is on
5331  }
5332  }
5333 
5334  if (!$found)
5335  {
5336  if (empty($conf->global->MAIN_VAT_DEFAULT_IF_AUTODETECT_FAILS))
5337  {
5338  // If vat of product for the country not found or not defined, we return the first higher vat of country.
5339  $sql = "SELECT t.taux as vat_rate, t.code as default_vat_code";
5340  $sql .= " FROM ".MAIN_DB_PREFIX."c_tva as t, ".MAIN_DB_PREFIX."c_country as c";
5341  $sql .= " WHERE t.active=1 AND t.fk_pays = c.rowid AND c.code='".$db->escape($thirdparty_seller->country_code)."'";
5342  $sql .= " ORDER BY t.taux DESC, t.code ASC, t.recuperableonly ASC";
5343  $sql .= $db->plimit(1);
5344 
5345  $resql = $db->query($sql);
5346  if ($resql)
5347  {
5348  $obj = $db->fetch_object($resql);
5349  if ($obj)
5350  {
5351  $ret = $obj->vat_rate;
5352  if ($obj->default_vat_code) $ret .= ' ('.$obj->default_vat_code.')';
5353  }
5354  $db->free($sql);
5355  } else dol_print_error($db);
5356  } else $ret = $conf->global->MAIN_VAT_DEFAULT_IF_AUTODETECT_FAILS; // Forced value if autodetect fails
5357  }
5358 
5359  dol_syslog("get_product_vat_for_country: ret=".$ret);
5360  return $ret;
5361 }
5362 
5372 function get_product_localtax_for_country($idprod, $local, $thirdparty_seller)
5373 {
5374  global $db, $mysoc;
5375 
5376  if (!class_exists('Product')) {
5377  require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
5378  }
5379 
5380  $ret = 0;
5381  $found = 0;
5382 
5383  if ($idprod > 0)
5384  {
5385  // Load product
5386  $product = new Product($db);
5387  $result = $product->fetch($idprod);
5388 
5389  if ($mysoc->country_code == $thirdparty_seller->country_code) // If selling country is ours
5390  {
5391  /* Not defined yet, so we don't use this
5392  if ($local==1) $ret=$product->localtax1_tx;
5393  elseif ($local==2) $ret=$product->localtax2_tx;
5394  $found=1;
5395  */
5396  } else {
5397  // TODO Read default product vat according to countrycode and product
5398  }
5399  }
5400 
5401  if (!$found)
5402  {
5403  // If vat of product for the country not found or not defined, we return higher vat of country.
5404  $sql = "SELECT taux as vat_rate, localtax1, localtax2";
5405  $sql .= " FROM ".MAIN_DB_PREFIX."c_tva as t, ".MAIN_DB_PREFIX."c_country as c";
5406  $sql .= " WHERE t.active=1 AND t.fk_pays = c.rowid AND c.code='".$db->escape($thirdparty_seller->country_code)."'";
5407  $sql .= " ORDER BY t.taux DESC, t.recuperableonly ASC";
5408  $sql .= $db->plimit(1);
5409 
5410  $resql = $db->query($sql);
5411  if ($resql)
5412  {
5413  $obj = $db->fetch_object($resql);
5414  if ($obj)
5415  {
5416  if ($local == 1) $ret = $obj->localtax1;
5417  elseif ($local == 2) $ret = $obj->localtax2;
5418  }
5419  } else dol_print_error($db);
5420  }
5421 
5422  dol_syslog("get_product_localtax_for_country: ret=".$ret);
5423  return $ret;
5424 }
5425 
5442 function get_default_tva(Societe $thirdparty_seller, Societe $thirdparty_buyer, $idprod = 0, $idprodfournprice = 0)
5443 {
5444  global $conf;
5445 
5446  require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
5447 
5448  // Note: possible values for tva_assuj are 0/1 or franchise/reel
5449  $seller_use_vat = ((is_numeric($thirdparty_seller->tva_assuj) && !$thirdparty_seller->tva_assuj) || (!is_numeric($thirdparty_seller->tva_assuj) && $thirdparty_seller->tva_assuj == 'franchise')) ? 0 : 1;
5450 
5451  $seller_country_code = $thirdparty_seller->country_code;
5452  $seller_in_cee = isInEEC($thirdparty_seller);
5453 
5454  $buyer_country_code = $thirdparty_buyer->country_code;
5455  $buyer_in_cee = isInEEC($thirdparty_buyer);
5456 
5457  dol_syslog("get_default_tva: seller use vat=".$seller_use_vat.", seller country=".$seller_country_code.", seller in cee=".$seller_in_cee.", buyer vat number=".$thirdparty_buyer->tva_intra." buyer country=".$buyer_country_code.", buyer in cee=".$buyer_in_cee.", idprod=".$idprod.", idprodfournprice=".$idprodfournprice.", SERVICE_ARE_ECOMMERCE_200238EC=".(!empty($conf->global->SERVICES_ARE_ECOMMERCE_200238EC) ? $conf->global->SERVICES_ARE_ECOMMERCE_200238EC : ''));
5458 
5459  // If services are eServices according to EU Council Directive 2002/38/EC (http://ec.europa.eu/taxation_customs/taxation/vat/traders/e-commerce/article_1610_en.htm)
5460  // we use the buyer VAT.
5461  if (!empty($conf->global->SERVICE_ARE_ECOMMERCE_200238EC))
5462  {
5463  if ($seller_in_cee && $buyer_in_cee && !$thirdparty_buyer->isACompany())
5464  {
5465  //print 'VATRULE 0';
5466  return get_product_vat_for_country($idprod, $thirdparty_buyer, $idprodfournprice);
5467  }
5468  }
5469 
5470  // If seller does not use VAT
5471  if (!$seller_use_vat)
5472  {
5473  //print 'VATRULE 1';
5474  return 0;
5475  }
5476 
5477  // Le test ci-dessus ne devrait pas etre necessaire. Me signaler l'exemple du cas juridique concerne si le test suivant n'est pas suffisant.
5478 
5479  // Si le (pays vendeur = pays acheteur) alors la TVA par defaut=TVA du produit vendu. Fin de regle.
5480  if (($seller_country_code == $buyer_country_code)
5481  || (in_array($seller_country_code, array('FR,MC')) && in_array($buyer_country_code, array('FR', 'MC')))) // Warning ->country_code not always defined
5482  {
5483  //print 'VATRULE 2';
5484  return get_product_vat_for_country($idprod, $thirdparty_seller, $idprodfournprice);
5485  }
5486 
5487  // Si (vendeur et acheteur dans Communaute europeenne) et (bien vendu = moyen de transports neuf comme auto, bateau, avion) alors TVA par defaut=0 (La TVA doit etre paye par l'acheteur au centre d'impots de son pays et non au vendeur). Fin de regle.
5488  // Not supported
5489 
5490  // Si (vendeur et acheteur dans Communaute europeenne) et (acheteur = entreprise) alors TVA par defaut=0. Fin de regle
5491  // Si (vendeur et acheteur dans Communaute europeenne) et (acheteur = particulier) alors TVA par defaut=TVA du produit vendu. Fin de regle
5492  if (($seller_in_cee && $buyer_in_cee))
5493  {
5494  $isacompany = $thirdparty_buyer->isACompany();
5495  if ($isacompany)
5496  {
5497  if (!empty($conf->global->MAIN_USE_VAT_OF_PRODUCT_FOR_COMPANIES_IN_EEC_WITH_INVALID_VAT_ID) && !isValidVATID($thirdparty_buyer)) {
5498  //print 'VATRULE 6';
5499  return get_product_vat_for_country($idprod, $thirdparty_seller, $idprodfournprice);
5500  }
5501  //print 'VATRULE 3';
5502  return 0;
5503  } else {
5504  //print 'VATRULE 4';
5505  return get_product_vat_for_country($idprod, $thirdparty_seller, $idprodfournprice);
5506  }
5507  }
5508 
5509  // Si (vendeur en France et acheteur hors Communaute europeenne et acheteur particulier) alors TVA par defaut=TVA du produit vendu. Fin de regle
5510  if (!empty($conf->global->MAIN_USE_VAT_OF_PRODUCT_FOR_INDIVIDUAL_CUSTOMER_OUT_OF_EEC) && empty($buyer_in_cee) && !$thirdparty_buyer->isACompany()) {
5511  return get_product_vat_for_country($idprod, $thirdparty_seller, $idprodfournprice);
5512  }
5513 
5514  // Sinon la TVA proposee par defaut=0. Fin de regle.
5515  // Rem: Cela signifie qu'au moins un des 2 est hors Communaute europeenne et que le pays differe
5516  //print 'VATRULE 5';
5517  return 0;
5518 }
5519 
5520 
5531 function get_default_npr(Societe $thirdparty_seller, Societe $thirdparty_buyer, $idprod = 0, $idprodfournprice = 0)
5532 {
5533  global $db;
5534 
5535  if ($idprodfournprice > 0)
5536  {
5537  if (!class_exists('ProductFournisseur')) {
5538  require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.product.class.php';
5539  }
5540  $prodprice = new ProductFournisseur($db);
5541  $prodprice->fetch_product_fournisseur_price($idprodfournprice);
5542  return $prodprice->fourn_tva_npr;
5543  } elseif ($idprod > 0)
5544  {
5545  if (!class_exists('Product')) {
5546  require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
5547  }
5548  $prod = new Product($db);
5549  $prod->fetch($idprod);
5550  return $prod->tva_npr;
5551  }
5552 
5553  return 0;
5554 }
5555 
5569 function get_default_localtax($thirdparty_seller, $thirdparty_buyer, $local, $idprod = 0)
5570 {
5571  global $mysoc;
5572 
5573  if (!is_object($thirdparty_seller)) return -1;
5574  if (!is_object($thirdparty_buyer)) return -1;
5575 
5576  if ($local == 1) // Localtax 1
5577  {
5578  if ($mysoc->country_code == 'ES')
5579  {
5580  if (is_numeric($thirdparty_buyer->localtax1_assuj) && !$thirdparty_buyer->localtax1_assuj) return 0;
5581  } else {
5582  // Si vendeur non assujeti a Localtax1, localtax1 par default=0
5583  if (is_numeric($thirdparty_seller->localtax1_assuj) && !$thirdparty_seller->localtax1_assuj) return 0;
5584  if (!is_numeric($thirdparty_seller->localtax1_assuj) && $thirdparty_seller->localtax1_assuj == 'localtax1off') return 0;
5585  }
5586  } elseif ($local == 2) //I Localtax 2
5587  {
5588  // Si vendeur non assujeti a Localtax2, localtax2 par default=0
5589  if (is_numeric($thirdparty_seller->localtax2_assuj) && !$thirdparty_seller->localtax2_assuj) return 0;
5590  if (!is_numeric($thirdparty_seller->localtax2_assuj) && $thirdparty_seller->localtax2_assuj == 'localtax2off') return 0;
5591  }
5592 
5593  if ($thirdparty_seller->country_code == $thirdparty_buyer->country_code)
5594  {
5595  return get_product_localtax_for_country($idprod, $local, $thirdparty_seller);
5596  }
5597 
5598  return 0;
5599 }
5600 
5609 function yn($yesno, $case = 1, $color = 0)
5610 {
5611  global $langs;
5612  $result = 'unknown'; $classname = '';
5613  if ($yesno == 1 || strtolower($yesno) == 'yes' || strtolower($yesno) == 'true') // A mettre avant test sur no a cause du == 0
5614  {
5615  $result = $langs->trans('yes');
5616  if ($case == 1 || $case == 3) $result = $langs->trans("Yes");
5617  if ($case == 2) $result = '<input type="checkbox" value="1" checked disabled>';
5618  if ($case == 3) $result = '<input type="checkbox" value="1" checked disabled> '.$result;
5619 
5620  $classname = 'ok';
5621  } elseif ($yesno == 0 || strtolower($yesno) == 'no' || strtolower($yesno) == 'false')
5622  {
5623  $result = $langs->trans("no");
5624  if ($case == 1 || $case == 3) $result = $langs->trans("No");
5625  if ($case == 2) $result = '<input type="checkbox" value="0" disabled>';
5626  if ($case == 3) $result = '<input type="checkbox" value="0" disabled> '.$result;
5627 
5628  if ($color == 2) $classname = 'ok';
5629  else $classname = 'error';
5630  }
5631  if ($color) return '<font class="'.$classname.'">'.$result.'</font>';
5632  return $result;
5633 }
5634 
5650 function get_exdir($num, $level, $alpha, $withoutslash, $object, $modulepart = '')
5651 {
5652  global $conf;
5653 
5654  if (empty($modulepart) && !empty($object->module)) $modulepart = $object->module;
5655 
5656  $path = '';
5657 
5658  $arrayforoldpath = array('cheque', 'category', 'holiday', 'supplier_invoice', 'invoice_supplier', 'mailing', 'supplier_payment');
5659  if (!empty($conf->global->PRODUCT_USE_OLD_PATH_FOR_PHOTO)) $arrayforoldpath[] = 'product';
5660  if (!empty($level) && in_array($modulepart, $arrayforoldpath)) {
5661  // This part should be removed once all code is using "get_exdir" to forge path, with parameter $object and $modulepart provided.
5662  if (empty($alpha)) $num = preg_replace('/([^0-9])/i', '', $num);
5663  else $num = preg_replace('/^.*\-/i', '', $num);
5664  $num = substr("000".$num, -$level);
5665  if ($level == 1) $path = substr($num, 0, 1);
5666  if ($level == 2) $path = substr($num, 1, 1).'/'.substr($num, 0, 1);
5667  if ($level == 3) $path = substr($num, 2, 1).'/'.substr($num, 1, 1).'/'.substr($num, 0, 1);
5668  } else {
5669  // We will enhance here a common way of forging path for document storage.
5670  // In a future, we may distribute directories on several levels depending on setup and object.
5671  // Here, $object->id, $object->ref and $modulepart are required.
5672  //var_dump($modulepart);
5673  $path = dol_sanitizeFileName(empty($object->ref) ? (string) $object->id : $object->ref);
5674  }
5675 
5676  if (empty($withoutslash) && !empty($path)) $path .= '/';
5677 
5678  return $path;
5679 }
5680 
5689 function dol_mkdir($dir, $dataroot = '', $newmask = null)
5690 {
5691  global $conf;
5692 
5693  dol_syslog("functions.lib::dol_mkdir: dir=".$dir, LOG_INFO);
5694 
5695  $dir_osencoded = dol_osencode($dir);
5696  if (@is_dir($dir_osencoded)) return 0;
5697 
5698  $nberr = 0;
5699  $nbcreated = 0;
5700 
5701  $ccdir = '';
5702  if (!empty($dataroot)) {
5703  // Remove data root from loop
5704  $dir = str_replace($dataroot.'/', '', $dir);
5705  $ccdir = $dataroot.'/';
5706  }
5707 
5708  $cdir = explode("/", $dir);
5709  $num = count($cdir);
5710  for ($i = 0; $i < $num; $i++)
5711  {
5712  if ($i > 0) $ccdir .= '/'.$cdir[$i];
5713  else $ccdir .= $cdir[$i];
5714  if (preg_match("/^.:$/", $ccdir, $regs)) continue; // Si chemin Windows incomplet, on poursuit par rep suivant
5715 
5716  // Attention, le is_dir() peut echouer bien que le rep existe.
5717  // (ex selon config de open_basedir)
5718  if ($ccdir)
5719  {
5720  $ccdir_osencoded = dol_osencode($ccdir);
5721  if (!@is_dir($ccdir_osencoded))
5722  {
5723  dol_syslog("functions.lib::dol_mkdir: Directory '".$ccdir."' does not exists or is outside open_basedir PHP setting.", LOG_DEBUG);
5724 
5725  umask(0);
5726  $dirmaskdec = octdec($newmask);
5727  if (empty($newmask)) {
5728  $dirmaskdec = empty($conf->global->MAIN_UMASK) ? octdec('0755') : octdec($conf->global->MAIN_UMASK);
5729  }
5730  $dirmaskdec |= octdec('0111'); // Set x bit required for directories
5731  if (!@mkdir($ccdir_osencoded, $dirmaskdec))
5732  {
5733  // Si le is_dir a renvoye une fausse info, alors on passe ici.
5734  dol_syslog("functions.lib::dol_mkdir: Fails to create directory '".$ccdir."' or directory already exists.", LOG_WARNING);
5735  $nberr++;
5736  } else {
5737  dol_syslog("functions.lib::dol_mkdir: Directory '".$ccdir."' created", LOG_DEBUG);
5738  $nberr = 0; // On remet a zero car si on arrive ici, cela veut dire que les echecs precedents peuvent etre ignore
5739  $nbcreated++;
5740  }
5741  } else {
5742  $nberr = 0; // On remet a zero car si on arrive ici, cela veut dire que les echecs precedents peuvent etre ignores
5743  }
5744  }
5745  }
5746  return ($nberr ? -$nberr : $nbcreated);
5747 }
5748 
5749 
5755 function picto_required()
5756 {
5757  return '<span class="fieldrequired">*</span>';
5758 }
5759 
5760 
5777 function dol_string_nohtmltag($stringtoclean, $removelinefeed = 1, $pagecodeto = 'UTF-8', $strip_tags = 0, $removedoublespaces = 1)
5778 {
5779  if ($removelinefeed == 2) $stringtoclean = preg_replace('/<br[^>]*>(\n|\r)+/ims', '<br>', $stringtoclean);
5780  $temp = preg_replace('/<br[^>]*>/i', "\n", $stringtoclean);
5781 
5782  // We remove entities BEFORE stripping (in case of an open separator char that is entity encoded and not the closing other, the strip will fails)
5783  $temp = dol_html_entity_decode($temp, ENT_COMPAT | ENT_HTML5, $pagecodeto);
5784 
5785  $temp = str_replace('< ', '__ltspace__', $temp);
5786 
5787  if ($strip_tags) {
5788  $temp = strip_tags($temp);
5789  } else {
5790  $pattern = "/<[^<>]+>/";
5791  // Example of $temp: <a href="/myurl" title="<u>A title</u>">0000-021</a>
5792  $temp = preg_replace($pattern, "", $temp); // pass 1 - $temp after pass 1: <a href="/myurl" title="A title">0000-021
5793  $temp = preg_replace($pattern, "", $temp); // pass 2 - $temp after pass 2: 0000-021
5794  // Remove '<' into remainging, so non closing html tags like '<abc'. Note: '<123abc' is not a html tag (can be kept), but '<abc123' is (must be removed).
5795  $temp = preg_replace('/<([a-z]+)/i', '\1', $temp);
5796  }
5797 
5798  $temp = dol_html_entity_decode($temp, ENT_COMPAT, $pagecodeto);
5799 
5800  // Remove also carriage returns
5801  if ($removelinefeed == 1) $temp = str_replace(array("\r\n", "\r", "\n"), " ", $temp);
5802 
5803  // And double quotes
5804  if ($removedoublespaces) {
5805  while (strpos($temp, " ")) {
5806  $temp = str_replace(" ", " ", $temp);
5807  }
5808  }
5809 
5810  $temp = str_replace('__ltspace__', '< ', $temp);
5811 
5812  return trim($temp);
5813 }
5814 
5827 function dol_string_onlythesehtmltags($stringtoclean, $cleanalsosomestyles = 1, $removeclassattribute = 1, $cleanalsojavascript = 0)
5828 {
5829  $allowed_tags = array(
5830  "html", "head", "meta", "body", "article", "a", "abbr", "b", "blockquote", "br", "cite", "div", "dl", "dd", "dt", "em", "font", "img", "ins", "hr", "i", "li", "link",
5831  "ol", "p", "q", "s", "section", "span", "strike", "strong", "title", "table", "tr", "th", "td", "u", "ul", "sup", "sub", "blockquote", "pre", "h1", "h2", "h3", "h4", "h5", "h6"
5832  );
5833 
5834  $allowed_tags_string = join("><", $allowed_tags);
5835  $allowed_tags_string = '<'.$allowed_tags_string.'>';
5836 
5837  $stringtoclean = str_replace('<!DOCTYPE html>', '__!DOCTYPE_HTML__', $stringtoclean); // Replace DOCTYPE to avoid to have it removed by the strip_tags
5838 
5839  $stringtoclean = dol_string_nounprintableascii($stringtoclean, 0);
5840  $stringtoclean = preg_replace('/&colon;/i', ':', $stringtoclean);
5841 
5842  $stringtoclean = preg_replace('/<!--[^>]*-->/', '', $stringtoclean);
5843  $stringtoclean = preg_replace('/&#58;|&#0000058|&#x3A/i', '', $stringtoclean); // refused string ':' encoded (no reason to have it encoded) to lock 'javascript:...'
5844  $stringtoclean = preg_replace('/javascript\s*:/i', '', $stringtoclean);
5845 
5846  $temp = strip_tags($stringtoclean, $allowed_tags_string);
5847 
5848  if ($cleanalsosomestyles) { // Clean for remaining html tags
5849  $temp = preg_replace('/position\s*:\s*(absolute|fixed)\s*!\s*important/i', '', $temp); // Note: If hacker try to introduce css comment into string to bypass this regex, the string must also be encoded by the dol_htmlentitiesbr during output so it become harmless
5850  }
5851  if ($removeclassattribute) { // Clean for remaining html tags
5852  $temp = preg_replace('/(<[^>]+)\s+class=((["\']).*?\\3|\\w*)/i', '\\1', $temp);
5853  }
5854 
5855  // Remove 'javascript:' that we should not find into a text with
5856  // Warning: This is not reliable to fight against obfuscated javascript, there is a lot of other solution to include js into a common html tag (only filtered by the GETPOST).
5857  if ($cleanalsojavascript) {
5858  $temp = preg_replace('/javascript\s*:/i', '', $temp);
5859  }
5860 
5861  $temp = str_replace('__!DOCTYPE_HTML__', '<!DOCTYPE html>', $temp); // Restore the DOCTYPE
5862 
5863  return $temp;
5864 }
5865 
5877 function dol_string_neverthesehtmltags($stringtoclean, $disallowed_tags = array('textarea'), $cleanalsosomestyles = 0)
5878 {
5879  $temp = $stringtoclean;
5880  foreach ($disallowed_tags as $tagtoremove)
5881  {
5882  $temp = preg_replace('/<\/?'.$tagtoremove.'>/', '', $temp);
5883  $temp = preg_replace('/<\/?'.$tagtoremove.'\s+[^>]*>/', '', $temp);
5884  }
5885 
5886  if ($cleanalsosomestyles) {
5887  $temp = preg_replace('/position\s*:\s*(absolute|fixed)\s*!\s*important/', '', $temp); // Note: If hacker try to introduce css comment into string to avoid this, string should be encoded by the dol_htmlentitiesbr so be harmless
5888  }
5889 
5890  return $temp;
5891 }
5892 
5893 
5903 function dolGetFirstLineOfText($text, $nboflines = 1, $charset = 'UTF-8')
5904 {
5905  if ($nboflines == 1)
5906  {
5907  if (dol_textishtml($text))
5908  {
5909  $firstline = preg_replace('/<br[^>]*>.*$/s', '', $text); // The s pattern modifier means the . can match newline characters
5910  $firstline = preg_replace('/<div[^>]*>.*$/s', '', $firstline); // The s pattern modifier means the . can match newline characters
5911  } else {
5912  $firstline = preg_replace('/[\n\r].*/', '', $text);
5913  }
5914  return $firstline.((strlen($firstline) != strlen($text)) ? '...' : '');
5915  } else {
5916  $ishtml = 0;
5917  if (dol_textishtml($text))
5918  {
5919  $text = preg_replace('/\n/', '', $text);
5920  $ishtml = 1;
5921  $repTable = array("\t" => " ", "\n" => " ", "\r" => " ", "\0" => " ", "\x0B" => " ");
5922  } else {
5923  $repTable = array("\t" => " ", "\n" => "<br>", "\r" => " ", "\0" => " ", "\x0B" => " ");
5924  }
5925 
5926  $text = strtr($text, $repTable);
5927  if ($charset == 'UTF-8') { $pattern = '/(<br[^>]*>)/Uu'; } // /U is to have UNGREEDY regex to limit to one html tag. /u is for UTF8 support
5928  else $pattern = '/(<br[^>]*>)/U'; // /U is to have UNGREEDY regex to limit to one html tag.
5929  $a = preg_split($pattern, $text, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
5930 
5931  $firstline = '';
5932  $i = 0;
5933  $nba = count($a); // 2x nb of lines in $a because $a contains also a line for each new line separator
5934  while (($i < $nba) && ($i < ($nboflines * 2)))
5935  {
5936  if ($i % 2 == 0) $firstline .= $a[$i];
5937  elseif (($i < (($nboflines * 2) - 1)) && ($i < ($nba - 1))) $firstline .= ($ishtml ? "<br>\n" : "\n");
5938  $i++;
5939  }
5940  unset($a);
5941  return $firstline.(($i < $nba) ? '...' : '');
5942  }
5943 }
5944 
5945 
5956 function dol_nl2br($stringtoencode, $nl2brmode = 0, $forxml = false)
5957 {
5958  if (!$nl2brmode) {
5959  return nl2br($stringtoencode, $forxml);
5960  } else {
5961  $ret = preg_replace('/(\r\n|\r|\n)/i', ($forxml ? '<br />' : '<br>'), $stringtoencode);
5962  return $ret;
5963  }
5964 }
5965 
5966 
5984 function dol_htmlentitiesbr($stringtoencode, $nl2brmode = 0, $pagecodefrom = 'UTF-8', $removelasteolbr = 1)
5985 {
5986  $newstring = $stringtoencode;
5987  if (dol_textishtml($stringtoencode)) // Check if text is already HTML or not
5988  {
5989  $newstring = preg_replace('/<br(\s[\sa-zA-Z_="]*)?\/?>/i', '<br>', $newstring); // Replace "<br type="_moz" />" by "<br>". It's same and avoid pb with FPDF.
5990  if ($removelasteolbr) $newstring = preg_replace('/<br>$/i', '', $newstring); // Remove last <br> (remove only last one)
5991  $newstring = strtr($newstring, array('&'=>'__and__', '<'=>'__lt__', '>'=>'__gt__', '"'=>'__dquot__'));
5992  $newstring = dol_htmlentities($newstring, ENT_COMPAT, $pagecodefrom); // Make entity encoding
5993  $newstring = strtr($newstring, array('__and__'=>'&', '__lt__'=>'<', '__gt__'=>'>', '__dquot__'=>'"'));
5994  } else {
5995  if ($removelasteolbr) $newstring = preg_replace('/(\r\n|\r|\n)$/i', '', $newstring); // Remove last \n (may remove several)
5996  $newstring = dol_nl2br(dol_htmlentities($newstring, ENT_COMPAT, $pagecodefrom), $nl2brmode);
5997  }
5998  // Other substitutions that htmlentities does not do
5999  //$newstring=str_replace(chr(128),'&euro;',$newstring); // 128 = 0x80. Not in html entity table. // Seems useles with TCPDF. Make bug with UTF8 languages
6000  return $newstring;
6001 }
6002 
6010 function dol_htmlentitiesbr_decode($stringtodecode, $pagecodeto = 'UTF-8')
6011 {
6012  $ret = dol_html_entity_decode($stringtodecode, ENT_COMPAT | ENT_HTML5, $pagecodeto);
6013  $ret = preg_replace('/'."\r\n".'<br(\s[\sa-zA-Z_="]*)?\/?>/i', "<br>", $ret);
6014  $ret = preg_replace('/<br(\s[\sa-zA-Z_="]*)?\/?>'."\r\n".'/i', "\r\n", $ret);
6015  $ret = preg_replace('/<br(\s[\sa-zA-Z_="]*)?\/?>'."\n".'/i', "\n", $ret);
6016  $ret = preg_replace('/<br(\s[\sa-zA-Z_="]*)?\/?>/i', "\n", $ret);
6017  return $ret;
6018 }
6019 
6026 function dol_htmlcleanlastbr($stringtodecode)
6027 {
6028  $ret = preg_replace('/(<br>|<br(\s[\sa-zA-Z_="]*)?\/?>|'."\n".'|'."\r".')+$/i', "", $stringtodecode);
6029  return $ret;
6030 }
6031 
6041 function dol_html_entity_decode($a, $b, $c = 'UTF-8', $keepsomeentities = 0)
6042 {
6043  $newstring = $a;
6044  if ($keepsomeentities) $newstring = strtr($newstring, array('&amp;'=>'__andamp__', '&lt;'=>'__andlt__', '&gt;'=>'__andgt__', '"'=>'__dquot__'));
6045  $newstring = html_entity_decode($newstring, $b, $c);
6046  if ($keepsomeentities) $newstring = strtr($newstring, array('__andamp__'=>'&amp;', '__andlt__'=>'&lt;', '__andgt__'=>'&gt;', '__dquot__'=>'"'));
6047  return $newstring;
6048 }
6049 
6060 function dol_htmlentities($string, $flags = null, $encoding = 'UTF-8', $double_encode = false)
6061 {
6062  return htmlentities($string, $flags, $encoding, $double_encode);
6063 }
6064 
6074 function dol_string_is_good_iso($s, $clean = 0)
6075 {
6076  $len = dol_strlen($s);
6077  $out = '';
6078  $ok = 1;
6079  for ($scursor = 0; $scursor < $len; $scursor++)
6080  {
6081  $ordchar = ord($s[$scursor]);
6082  //print $scursor.'-'.$ordchar.'<br>';
6083  if ($ordchar < 32 && $ordchar != 13 && $ordchar != 10) { $ok = 0; break; } elseif ($ordchar > 126 && $ordchar < 160) { $ok = 0; break; } elseif ($clean) {
6084  $out .= $s[$scursor];
6085  }
6086  }
6087  if ($clean) return $out;
6088  return $ok;
6089 }
6090 
6099 function dol_nboflines($s, $maxchar = 0)
6100 {
6101  if ($s == '') return 0;
6102  $arraystring = explode("\n", $s);
6103  $nb = count($arraystring);
6104 
6105  return $nb;
6106 }
6107 
6108 
6118 function dol_nboflines_bis($text, $maxlinesize = 0, $charset = 'UTF-8')
6119 {
6120  $repTable = array("\t" => " ", "\n" => "<br>", "\r" => " ", "\0" => " ", "\x0B" => " ");
6121  if (dol_textishtml($text)) $repTable = array("\t" => " ", "\n" => " ", "\r" => " ", "\0" => " ", "\x0B" => " ");
6122 
6123  $text = strtr($text, $repTable);
6124  if ($charset == 'UTF-8') { $pattern = '/(<br[^>]*>)/Uu'; } // /U is to have UNGREEDY regex to limit to one html tag. /u is for UTF8 support
6125  else $pattern = '/(<br[^>]*>)/U'; // /U is to have UNGREEDY regex to limit to one html tag.
6126  $a = preg_split($pattern, $text, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
6127 
6128  $nblines = (int) floor((count($a) + 1) / 2);
6129  // count possible auto line breaks
6130  if ($maxlinesize)
6131  {
6132  foreach ($a as $line)
6133  {
6134  if (dol_strlen($line) > $maxlinesize)
6135  {
6136  //$line_dec = html_entity_decode(strip_tags($line));
6137  $line_dec = html_entity_decode($line);
6138  if (dol_strlen($line_dec) > $maxlinesize)
6139  {
6140  $line_dec = wordwrap($line_dec, $maxlinesize, '\n', true);
6141  $nblines += substr_count($line_dec, '\n');
6142  }
6143  }
6144  }
6145  }
6146 
6147  unset($a);
6148  return $nblines;
6149 }
6150 
6159 function dol_textishtml($msg, $option = 0)
6160 {
6161  if ($option == 1)
6162  {
6163  if (preg_match('/<html/i', $msg)) return true;
6164  elseif (preg_match('/<body/i', $msg)) return true;
6165  elseif (preg_match('/<\/textarea/i', $msg)) return true;
6166  elseif (preg_match('/<br/i', $msg)) return true;
6167  return false;
6168  } else {
6169  if (preg_match('/<html/i', $msg)) return true;
6170  elseif (preg_match('/<body/i', $msg)) return true;
6171  elseif (preg_match('/<\/textarea/i', $msg)) return true;
6172  elseif (preg_match('/<(b|em|i|u)>/i', $msg)) return true;
6173  elseif (preg_match('/<br\/>/i', $msg)) return true;
6174  elseif (preg_match('/<(br|div|font|li|p|span|strong|table)>/i', $msg)) return true;
6175  elseif (preg_match('/<(br|div|font|li|p|span|strong|table)\s+[^<>\/]*>/i', $msg)) return true;
6176  elseif (preg_match('/<(br|div|font|li|p|span|strong|table)\s+[^<>\/]*\/>/i', $msg)) return true;
6177  elseif (preg_match('/<img\s+[^<>]*src[^<>]*>/i', $msg)) return true; // must accept <img src="http://example.com/aaa.png" />
6178  elseif (preg_match('/<a\s+[^<>]*href[^<>]*>/i', $msg)) return true; // must accept <a href="http://example.com/aaa.png" />
6179  elseif (preg_match('/<h[0-9]>/i', $msg)) return true;
6180  elseif (preg_match('/&[A-Z0-9]{1,6};/i', $msg)) return true; // Html entities names (http://www.w3schools.com/tags/ref_entities.asp)
6181  elseif (preg_match('/&#[0-9]{2,3};/i', $msg)) return true; // Html entities numbers (http://www.w3schools.com/tags/ref_entities.asp)
6182 
6183  return false;
6184  }
6185 }
6186 
6201 function dol_concatdesc($text1, $text2, $forxml = false, $invert = false)
6202 {
6203  if (!empty($invert))
6204  {
6205  $tmp = $text1;
6206  $text1 = $text2;
6207  $text2 = $tmp;
6208  }
6209 
6210  $ret = '';
6211  $ret .= (!dol_textishtml($text1) && dol_textishtml($text2)) ? dol_nl2br(dol_escape_htmltag($text1, 0, 1, '', 1), 0, $forxml) : $text1;
6212  $ret .= (!empty($text1) && !empty($text2)) ? ((dol_textishtml($text1) || dol_textishtml($text2)) ? ($forxml ? "<br >\n" : "<br>\n") : "\n") : "";
6213  $ret .= (dol_textishtml($text1) && !dol_textishtml($text2)) ? dol_nl2br(dol_escape_htmltag($text2, 0, 1, '', 1), 0, $forxml) : $text2;
6214  return $ret;
6215 }
6216 
6217 
6218 
6229 function getCommonSubstitutionArray($outputlangs, $onlykey = 0, $exclude = null, $object = null)
6230 {
6231  global $db, $conf, $mysoc, $user, $extrafields;
6232 
6233  $substitutionarray = array();
6234 
6235  if (empty($exclude) || !in_array('user', $exclude))
6236  {
6237  // Add SIGNATURE into substitutionarray first, so, when we will make the substitution,
6238  // this will include signature content first and then replace var found into content of signature
6239  $signature = $user->signature;
6240  $substitutionarray = array_merge($substitutionarray, array(
6241  '__USER_SIGNATURE__' => (string) (($signature && empty($conf->global->MAIN_MAIL_DO_NOT_USE_SIGN)) ? ($onlykey == 2 ? dol_trunc(dol_string_nohtmltag($signature), 30) : $signature) : '')
6242  )
6243  );
6244 
6245  $substitutionarray = array_merge($substitutionarray, array(
6246  '__USER_ID__' => (string) $user->id,
6247  '__USER_LOGIN__' => (string) $user->login,
6248  '__USER_EMAIL__' => (string) $user->email,
6249  '__USER_LASTNAME__' => (string) $user->lastname,
6250  '__USER_FIRSTNAME__' => (string) $user->firstname,
6251  '__USER_FULLNAME__' => (string) $user->getFullName($outputlangs),
6252  '__USER_SUPERVISOR_ID__' => (string) ($user->fk_user ? $user->fk_user : '0'),
6253  '__USER_REMOTE_IP__' => (string) getUserRemoteIP()
6254  )
6255  );
6256  }
6257  if ((empty($exclude) || !in_array('mycompany', $exclude)) && is_object($mysoc))
6258  {
6259  $substitutionarray = array_merge($substitutionarray, array(
6260  '__MYCOMPANY_NAME__' => $mysoc->name,
6261  '__MYCOMPANY_EMAIL__' => $mysoc->email,
6262  '__MYCOMPANY_PROFID1__' => $mysoc->idprof1,
6263  '__MYCOMPANY_PROFID2__' => $mysoc->idprof2,
6264  '__MYCOMPANY_PROFID3__' => $mysoc->idprof3,
6265  '__MYCOMPANY_PROFID4__' => $mysoc->idprof4,
6266  '__MYCOMPANY_PROFID5__' => $mysoc->idprof5,
6267  '__MYCOMPANY_PROFID6__' => $mysoc->idprof6,
6268  '__MYCOMPANY_CAPITAL__' => $mysoc->capital,
6269  '__MYCOMPANY_FULLADDRESS__' => $mysoc->getFullAddress(1, ', '),
6270  '__MYCOMPANY_ADDRESS__' => $mysoc->address,
6271  '__MYCOMPANY_ZIP__' => $mysoc->zip,
6272  '__MYCOMPANY_TOWN__' => $mysoc->town,
6273  '__MYCOMPANY_COUNTRY__' => $mysoc->country,
6274  '__MYCOMPANY_COUNTRY_ID__' => $mysoc->country_id,
6275  '__MYCOMPANY_COUNTRY_CODE__' => $mysoc->country_code,
6276  '__MYCOMPANY_CURRENCY_CODE__' => $conf->currency
6277  ));
6278  }
6279 
6280  if (($onlykey || is_object($object)) && (empty($exclude) || !in_array('object', $exclude)))
6281  {
6282  if ($onlykey)
6283  {
6284  $substitutionarray['__ID__'] = '__ID__';
6285  $substitutionarray['__REF__'] = '__REF__';
6286  $substitutionarray['__REF_CLIENT__'] = '__REF_CLIENT__';
6287  $substitutionarray['__REF_SUPPLIER__'] = '__REF_SUPPLIER__';
6288  $substitutionarray['__NOTE_PUBLIC__'] = '__NOTE_PUBLIC__';
6289  $substitutionarray['__NOTE_PRIVATE__'] = '__NOTE_PRIVATE__';
6290  $substitutionarray['__EXTRAFIELD_XXX__'] = '__EXTRAFIELD_XXX__';
6291 
6292  if (!empty($conf->societe->enabled)) // Most objects are concerned
6293  {
6294  $substitutionarray['__THIRDPARTY_ID__'] = '__THIRDPARTY_ID__';
6295  $substitutionarray['__THIRDPARTY_NAME__'] = '__THIRDPARTY_NAME__';
6296  $substitutionarray['__THIRDPARTY_NAME_ALIAS__'] = '__THIRDPARTY_NAME_ALIAS__';
6297  $substitutionarray['__THIRDPARTY_CODE_CLIENT__'] = '__THIRDPARTY_CODE_CLIENT__';
6298  $substitutionarray['__THIRDPARTY_CODE_FOURNISSEUR__'] = '__THIRDPARTY_CODE_FOURNISSEUR__';
6299  $substitutionarray['__THIRDPARTY_EMAIL__'] = '__THIRDPARTY_EMAIL__';
6300  $substitutionarray['__THIRDPARTY_PHONE__'] = '__THIRDPARTY_PHONE__';
6301  $substitutionarray['__THIRDPARTY_FAX__'] = '__THIRDPARTY_FAX__';
6302  $substitutionarray['__THIRDPARTY_ADDRESS__'] = '__THIRDPARTY_ADDRESS__';
6303  $substitutionarray['__THIRDPARTY_ZIP__'] = '__THIRDPARTY_ZIP__';
6304  $substitutionarray['__THIRDPARTY_TOWN__'] = '__THIRDPARTY_TOWN__';
6305  $substitutionarray['__THIRDPARTY_IDPROF1__'] = '__THIRDPARTY_IDPROF1__';
6306  $substitutionarray['__THIRDPARTY_IDPROF2__'] = '__THIRDPARTY_IDPROF2__';
6307  $substitutionarray['__THIRDPARTY_IDPROF3__'] = '__THIRDPARTY_IDPROF3__';
6308  $substitutionarray['__THIRDPARTY_IDPROF4__'] = '__THIRDPARTY_IDPROF4__';
6309  $substitutionarray['__THIRDPARTY_IDPROF5__'] = '__THIRDPARTY_IDPROF5__';
6310  $substitutionarray['__THIRDPARTY_IDPROF6__'] = '__THIRDPARTY_IDPROF6__';
6311  $substitutionarray['__THIRDPARTY_TVAINTRA__'] = '__THIRDPARTY_TVAINTRA__';
6312  $substitutionarray['__THIRDPARTY_NOTE_PUBLIC__'] = '__THIRDPARTY_NOTE_PUBLIC__';
6313  $substitutionarray['__THIRDPARTY_NOTE_PRIVATE__'] = '__THIRDPARTY_NOTE_PRIVATE__';
6314  }
6315  if (!empty($conf->adherent->enabled) && (!is_object($object) || $object->element == 'adherent'))
6316  {
6317  $substitutionarray['__MEMBER_ID__'] = '__MEMBER_ID__';
6318  $substitutionarray['__MEMBER_CIVILITY__'] = '__MEMBER_CIVILITY__';
6319  $substitutionarray['__MEMBER_FIRSTNAME__'] = '__MEMBER_FIRSTNAME__';
6320  $substitutionarray['__MEMBER_LASTNAME__'] = '__MEMBER_LASTNAME__';
6321  /*$substitutionarray['__MEMBER_NOTE_PUBLIC__'] = '__MEMBER_NOTE_PUBLIC__';
6322  $substitutionarray['__MEMBER_NOTE_PRIVATE__'] = '__MEMBER_NOTE_PRIVATE__';*/
6323  }
6324  if (!empty($conf->recruitment->enabled) && (!is_object($object) || $object->element == 'candidature'))
6325  {
6326  $substitutionarray['__CANDIDATE_FULLNAME__'] = '__CANDIDATE_FULLNAME__';
6327  $substitutionarray['__CANDIDATE_FIRSTNAME__'] = '__CANDIDATE_FIRSTNAME__';
6328  $substitutionarray['__CANDIDATE_LASTNAME__'] = '__CANDIDATE_LASTNAME__';
6329  }
6330  if (!empty($conf->projet->enabled)) // Most objects
6331  {
6332  $substitutionarray['__PROJECT_ID__'] = '__PROJECT_ID__';
6333  $substitutionarray['__PROJECT_REF__'] = '__PROJECT_REF__';
6334  $substitutionarray['__PROJECT_NAME__'] = '__PROJECT_NAME__';
6335  /*$substitutionarray['__PROJECT_NOTE_PUBLIC__'] = '__PROJECT_NOTE_PUBLIC__';
6336  $substitutionarray['__PROJECT_NOTE_PRIVATE__'] = '__PROJECT_NOTE_PRIVATE__';*/
6337  }
6338  if (!empty($conf->contrat->enabled) && (!is_object($object) || $object->element == 'contract'))
6339  {
6340  $substitutionarray['__CONTRACT_HIGHEST_PLANNED_START_DATE__'] = 'Highest date planned for a service start';
6341  $substitutionarray['__CONTRACT_HIGHEST_PLANNED_START_DATETIME__'] = 'Highest date and hour planned for service start';
6342  $substitutionarray['__CONTRACT_LOWEST_EXPIRATION_DATE__'] = 'Lowest data for planned expiration of service';
6343  $substitutionarray['__CONTRACT_LOWEST_EXPIRATION_DATETIME__'] = 'Lowest date and hour for planned expiration of service';
6344  }
6345  $substitutionarray['__ONLINE_PAYMENT_URL__'] = 'UrlToPayOnlineIfApplicable';
6346  $substitutionarray['__ONLINE_PAYMENT_TEXT_AND_URL__'] = 'TextAndUrlToPayOnlineIfApplicable';
6347  $substitutionarray['__SECUREKEYPAYMENT__'] = 'Security key (if key is not unique per record)';
6348  $substitutionarray['__SECUREKEYPAYMENT_MEMBER__'] = 'Security key for payment on a member subscription (one key per member)';
6349  $substitutionarray['__SECUREKEYPAYMENT_ORDER__'] = 'Security key for payment on an order';
6350  $substitutionarray['__SECUREKEYPAYMENT_INVOICE__'] = 'Security key for payment on an invoice';
6351  $substitutionarray['__SECUREKEYPAYMENT_CONTRACTLINE__'] = 'Security key for payment on a a service';
6352 
6353  $substitutionarray['__DIRECTDOWNLOAD_URL_PROPOSAL__'] = 'Direct download url of a proposal';
6354  $substitutionarray['__DIRECTDOWNLOAD_URL_ORDER__'] = 'Direct download url of an order';
6355  $substitutionarray['__DIRECTDOWNLOAD_URL_INVOICE__'] = 'Direct download url of an invoice';
6356 
6357  if (!empty($conf->expedition->enabled) && (!is_object($object) || $object->element == 'shipping'))
6358  {
6359  $substitutionarray['__SHIPPINGTRACKNUM__'] = 'Shipping tracking number';
6360  $substitutionarray['__SHIPPINGTRACKNUMURL__'] = 'Shipping tracking url';
6361  }
6362  if (!empty($conf->reception->enabled) && (!is_object($object) || $object->element == 'reception'))
6363  {
6364  $substitutionarray['__RECEPTIONTRACKNUM__'] = 'Shippin tracking number of shipment';
6365  $substitutionarray['__RECEPTIONTRACKNUMURL__'] = 'Shipping tracking url';
6366  }
6367  } else {
6368  $substitutionarray['__ID__'] = $object->id;
6369  $substitutionarray['__REF__'] = $object->ref;
6370  $substitutionarray['__REF_CLIENT__'] = (isset($object->ref_client) ? $object->ref_client : (isset($object->ref_customer) ? $object->ref_customer : null));
6371  $substitutionarray['__REF_SUPPLIER__'] = (isset($object->ref_supplier) ? $object->ref_supplier : null);
6372  $substitutionarray['__NOTE_PUBLIC__'] = (isset($object->note_public) ? $object->note_public : null);
6373  $substitutionarray['__NOTE_PRIVATE__'] = (isset($object->note_private) ? $object->note_private : null);
6374 
6375  $substitutionarray['__DATE_DELIVERY__'] = (isset($object->date_livraison) ? dol_print_date($object->date_livraison, 'day', 0, $outputlangs) : '');
6376 
6377  // For backward compatibility
6378  $substitutionarray['__REFCLIENT__'] = (isset($object->ref_client) ? $object->ref_client : (isset($object->ref_customer) ? $object->ref_customer : null));
6379  $substitutionarray['__REFSUPPLIER__'] = (isset($object->ref_supplier) ? $object->ref_supplier : null);
6380  $substitutionarray['__REFCLIENT__'] = (isset($object->ref_client) ? $object->ref_client : (isset($object->ref_customer) ? $object->ref_customer : null));
6381  $substitutionarray['__REFSUPPLIER__'] = (isset($object->ref_supplier) ? $object->ref_supplier : null);
6382  $substitutionarray['__SUPPLIER_ORDER_DATE_DELIVERY__'] = (isset($object->date_livraison) ? dol_print_date($object->date_livraison, 'day', 0, $outputlangs) : '');
6383  $substitutionarray['__SUPPLIER_ORDER_DELAY_DELIVERY__'] = (isset($object->availability_code) ? ($outputlangs->transnoentities("AvailabilityType".$object->availability_code) != ('AvailabilityType'.$object->availability_code) ? $outputlangs->transnoentities("AvailabilityType".$object->availability_code) : $outputlangs->convToOutputCharset(isset($object->availability) ? $object->availability : '')) : '');
6384 
6385  if (is_object($object) && ($object->element == 'adherent' || $object->element == 'member') && $object->id > 0)
6386  {
6387  $birthday = (empty($object->birth) ? '' : dol_print_date($object->birth, 'day'));
6388 
6389  $substitutionarray['__MEMBER_ID__'] = (isset($object->id) ? $object->id : '');
6390  if (method_exists($object, 'getCivilityLabel')) $substitutionarray['__MEMBER_CIVILITY__'] = $object->getCivilityLabel();
6391  $substitutionarray['__MEMBER_FIRSTNAME__'] = (isset($object->firstname) ? $object->firstname : '');
6392  $substitutionarray['__MEMBER_LASTNAME__'] = (isset($object->lastname) ? $object->lastname : '');
6393  if (method_exists($object, 'getFullName')) $substitutionarray['__MEMBER_FULLNAME__'] = $object->getFullName($outputlangs);
6394  $substitutionarray['__MEMBER_COMPANY__'] = (isset($object->societe) ? $object->societe : '');
6395  $substitutionarray['__MEMBER_ADDRESS__'] = (isset($object->address) ? $object->address : '');
6396  $substitutionarray['__MEMBER_ZIP__'] = (isset($object->zip) ? $object->zip : '');
6397  $substitutionarray['__MEMBER_TOWN__'] = (isset($object->town) ? $object->town : '');
6398  $substitutionarray['__MEMBER_COUNTRY__'] = (isset($object->country) ? $object->country : '');
6399  $substitutionarray['__MEMBER_EMAIL__'] = (isset($object->email) ? $object->email : '');
6400  $substitutionarray['__MEMBER_BIRTH__'] = (isset($birthday) ? $birthday : '');
6401  $substitutionarray['__MEMBER_PHOTO__'] = (isset($object->photo) ? $object->photo : '');
6402  $substitutionarray['__MEMBER_LOGIN__'] = (isset($object->login) ? $object->login : '');
6403  $substitutionarray['__MEMBER_PASSWORD__'] = (isset($object->pass) ? $object->pass : '');
6404  $substitutionarray['__MEMBER_PHONE__'] = (isset($object->phone) ? $object->phone : '');
6405  $substitutionarray['__MEMBER_PHONEPRO__'] = (isset($object->phone_perso) ? $object->phone_perso : '');
6406  $substitutionarray['__MEMBER_PHONEMOBILE__'] = (isset($object->phone_mobile) ? $object->phone_mobile : '');
6407  $substitutionarray['__MEMBER_TYPE__'] = (isset($object->type) ? $object->type : '');
6408  $substitutionarray['__MEMBER_FIRST_SUBSCRIPTION_DATE__'] = dol_print_date($object->first_subscription_date, 'dayrfc');
6409  $substitutionarray['__MEMBER_FIRST_SUBSCRIPTION_DATE_START__'] = dol_print_date($object->first_subscription_date_start, 'dayrfc');
6410  $substitutionarray['__MEMBER_FIRST_SUBSCRIPTION_DATE_END__'] = dol_print_date($object->first_subscription_date_end, 'dayrfc');
6411  $substitutionarray['__MEMBER_LAST_SUBSCRIPTION_DATE__'] = dol_print_date($object->last_subscription_date, 'dayrfc');
6412  $substitutionarray['__MEMBER_LAST_SUBSCRIPTION_DATE_START__'] = dol_print_date($object->last_subscription_date_start, 'dayrfc');
6413  $substitutionarray['__MEMBER_LAST_SUBSCRIPTION_DATE_END__'] = dol_print_date($object->last_subscription_date_end, 'dayrfc');
6414  }
6415 
6416  if (is_object($object) && $object->element == 'societe') {
6417  $substitutionarray['__THIRDPARTY_ID__'] = (is_object($object) ? $object->id : '');
6418  $substitutionarray['__THIRDPARTY_NAME__'] = (is_object($object) ? $object->name : '');
6419  $substitutionarray['__THIRDPARTY_NAME_ALIAS__'] = (is_object($object) ? $object->name_alias : '');
6420  $substitutionarray['__THIRDPARTY_CODE_CLIENT__'] = (is_object($object) ? $object->code_client : '');
6421  $substitutionarray['__THIRDPARTY_CODE_FOURNISSEUR__'] = (is_object($object) ? $object->code_fournisseur : '');
6422  $substitutionarray['__THIRDPARTY_EMAIL__'] = (is_object($object) ? $object->email : '');
6423  $substitutionarray['__THIRDPARTY_PHONE__'] = (is_object($object) ? $object->phone : '');
6424  $substitutionarray['__THIRDPARTY_FAX__'] = (is_object($object) ? $object->fax : '');
6425  $substitutionarray['__THIRDPARTY_ADDRESS__'] = (is_object($object) ? $object->address : '');
6426  $substitutionarray['__THIRDPARTY_ZIP__'] = (is_object($object) ? $object->zip : '');
6427  $substitutionarray['__THIRDPARTY_TOWN__'] = (is_object($object) ? $object->town : '');
6428  $substitutionarray['__THIRDPARTY_COUNTRY_ID__'] = (is_object($object) ? $object->country_id : '');
6429  $substitutionarray['__THIRDPARTY_COUNTRY_CODE__'] = (is_object($object) ? $object->country_code : '');
6430  $substitutionarray['__THIRDPARTY_IDPROF1__'] = (is_object($object) ? $object->idprof1 : '');
6431  $substitutionarray['__THIRDPARTY_IDPROF2__'] = (is_object($object) ? $object->idprof2 : '');
6432  $substitutionarray['__THIRDPARTY_IDPROF3__'] = (is_object($object) ? $object->idprof3 : '');
6433  $substitutionarray['__THIRDPARTY_IDPROF4__'] = (is_object($object) ? $object->idprof4 : '');
6434  $substitutionarray['__THIRDPARTY_IDPROF5__'] = (is_object($object) ? $object->idprof5 : '');
6435  $substitutionarray['__THIRDPARTY_IDPROF6__'] = (is_object($object) ? $object->idprof6 : '');
6436  $substitutionarray['__THIRDPARTY_TVAINTRA__'] = (is_object($object) ? $object->tva_intra : '');
6437  $substitutionarray['__THIRDPARTY_NOTE_PUBLIC__'] = (is_object($object) ? dol_htmlentitiesbr($object->note_public) : '');
6438  $substitutionarray['__THIRDPARTY_NOTE_PRIVATE__'] = (is_object($object) ? dol_htmlentitiesbr($object->note_private) : '');
6439  } elseif (is_object($object->thirdparty)) {
6440  $substitutionarray['__THIRDPARTY_ID__'] = (is_object($object->thirdparty) ? $object->thirdparty->id : '');
6441  $substitutionarray['__THIRDPARTY_NAME__'] = (is_object($object->thirdparty) ? $object->thirdparty->name : '');
6442  $substitutionarray['__THIRDPARTY_NAME_ALIAS__'] = (is_object($object->thirdparty) ? $object->thirdparty->name_alias : '');
6443  $substitutionarray['__THIRDPARTY_CODE_CLIENT__'] = (is_object($object->thirdparty) ? $object->thirdparty->code_client : '');
6444  $substitutionarray['__THIRDPARTY_CODE_FOURNISSEUR__'] = (is_object($object->thirdparty) ? $object->thirdparty->code_fournisseur : '');
6445  $substitutionarray['__THIRDPARTY_EMAIL__'] = (is_object($object->thirdparty) ? $object->thirdparty->email : '');
6446  $substitutionarray['__THIRDPARTY_PHONE__'] = (is_object($object->thirdparty) ? $object->thirdparty->phone : '');
6447  $substitutionarray['__THIRDPARTY_FAX__'] = (is_object($object->thirdparty) ? $object->thirdparty->fax : '');
6448  $substitutionarray['__THIRDPARTY_ADDRESS__'] = (is_object($object->thirdparty) ? $object->thirdparty->address : '');
6449  $substitutionarray['__THIRDPARTY_ZIP__'] = (is_object($object->thirdparty) ? $object->thirdparty->zip : '');
6450  $substitutionarray['__THIRDPARTY_TOWN__'] = (is_object($object->thirdparty) ? $object->thirdparty->town : '');
6451  $substitutionarray['__THIRDPARTY_COUNTRY_ID__'] = (is_object($object->thirdparty) ? $object->thirdparty->country_id : '');
6452  $substitutionarray['__THIRDPARTY_COUNTRY_CODE__'] = (is_object($object->thirdparty) ? $object->thirdparty->country_code : '');
6453  $substitutionarray['__THIRDPARTY_IDPROF1__'] = (is_object($object->thirdparty) ? $object->thirdparty->idprof1 : '');
6454  $substitutionarray['__THIRDPARTY_IDPROF2__'] = (is_object($object->thirdparty) ? $object->thirdparty->idprof2 : '');
6455  $substitutionarray['__THIRDPARTY_IDPROF3__'] = (is_object($object->thirdparty) ? $object->thirdparty->idprof3 : '');
6456  $substitutionarray['__THIRDPARTY_IDPROF4__'] = (is_object($object->thirdparty) ? $object->thirdparty->idprof4 : '');
6457  $substitutionarray['__THIRDPARTY_IDPROF5__'] = (is_object($object->thirdparty) ? $object->thirdparty->idprof5 : '');
6458  $substitutionarray['__THIRDPARTY_IDPROF6__'] = (is_object($object->thirdparty) ? $object->thirdparty->idprof6 : '');
6459  $substitutionarray['__THIRDPARTY_TVAINTRA__'] = (is_object($object->thirdparty) ? $object->thirdparty->tva_intra : '');
6460  $substitutionarray['__THIRDPARTY_NOTE_PUBLIC__'] = (is_object($object->thirdparty) ? dol_htmlentitiesbr($object->thirdparty->note_public) : '');
6461  $substitutionarray['__THIRDPARTY_NOTE_PRIVATE__'] = (is_object($object->thirdparty) ? dol_htmlentitiesbr($object->thirdparty->note_private) : '');
6462  }
6463 
6464  if (is_object($object) && $object->element == 'recruitmentcandidature') {
6465  $substitutionarray['__CANDIDATE_FULLNAME__'] = $object->getFullName($outputlangs);
6466  $substitutionarray['__CANDIDATE_FIRSTNAME__'] = $object->firstname;
6467  $substitutionarray['__CANDIDATE_LASTNAME__'] = $object->lastname;
6468  }
6469 
6470  if (is_object($object->project))
6471  {
6472  $substitutionarray['__PROJECT_ID__'] = (is_object($object->project) ? $object->project->id : '');
6473  $substitutionarray['__PROJECT_REF__'] = (is_object($object->project) ? $object->project->ref : '');
6474  $substitutionarray['__PROJECT_NAME__'] = (is_object($object->project) ? $object->project->title : '');
6475  }
6476  if (is_object($object->projet)) // Deprecated, for backward compatibility
6477  {
6478  $substitutionarray['__PROJECT_ID__'] = (is_object($object->projet) ? $object->projet->id : '');
6479  $substitutionarray['__PROJECT_REF__'] = (is_object($object->projet) ? $object->projet->ref : '');
6480  $substitutionarray['__PROJECT_NAME__'] = (is_object($object->projet) ? $object->projet->title : '');
6481  }
6482 
6483  if (is_object($object) && $object->element == 'shipping')
6484  {
6485  $substitutionarray['__SHIPPINGTRACKNUM__'] = $object->tracking_number;
6486  $substitutionarray['__SHIPPINGTRACKNUMURL__'] = $object->tracking_url;
6487  }
6488  if (is_object($object) && $object->element == 'reception')
6489  {
6490  $substitutionarray['__RECEPTIONTRACKNUM__'] = $object->tracking_number;
6491  $substitutionarray['__RECEPTIONTRACKNUMURL__'] = $object->tracking_url;
6492  }
6493 
6494  if (is_object($object) && $object->element == 'contrat' && $object->id > 0 && is_array($object->lines))
6495  {
6496  $dateplannedstart = '';
6497  $datenextexpiration = '';
6498  foreach ($object->lines as $line)
6499  {
6500  if ($line->date_ouverture_prevue > $dateplannedstart) $dateplannedstart = $line->date_ouverture_prevue;
6501  if ($line->statut == 4 && $line->date_fin_prevue && (!$datenextexpiration || $line->date_fin_prevue < $datenextexpiration)) $datenextexpiration = $line->date_fin_prevue;
6502  }
6503  $substitutionarray['__CONTRACT_HIGHEST_PLANNED_START_DATE__'] = dol_print_date($dateplannedstart, 'dayrfc');
6504  $substitutionarray['__CONTRACT_HIGHEST_PLANNED_START_DATETIME__'] = dol_print_date($dateplannedstart, 'standard');
6505  $substitutionarray['__CONTRACT_LOWEST_EXPIRATION_DATE__'] = dol_print_date($datenextexpiration, 'dayrfc');
6506  $substitutionarray['__CONTRACT_LOWEST_EXPIRATION_DATETIME__'] = dol_print_date($datenextexpiration, 'standard');
6507  }
6508 
6509  // Create dynamic tags for __EXTRAFIELD_FIELD__
6510  if ($object->table_element && $object->id > 0)
6511  {
6512  if (!is_object($extrafields)) $extrafields = new ExtraFields($db);
6513  $extrafields->fetch_name_optionals_label($object->table_element, true);
6514 
6515  if ($object->fetch_optionals() > 0)
6516  {
6517  if (is_array($extrafields->attributes[$object->table_element]['label']) && count($extrafields->attributes[$object->table_element]['label']) > 0)
6518  {
6519  foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $label) {
6520  $substitutionarray['__EXTRAFIELD_'.strtoupper($key).'__'] = $object->array_options['options_'.$key];
6521  if ($extrafields->attributes[$object->table_element]['type'][$key] == 'date') {
6522  $substitutionarray['__EXTRAFIELD_'.strtoupper($key).'__'] = dol_print_date($object->array_options['options_'.$key], 'day');
6523  $substitutionarray['__EXTRAFIELD_'.strtoupper($key).'_LOCALE__'] = dol_print_date($object->array_options['options_'.$key], 'day', 'tzserver', $outputlangs);
6524  $substitutionarray['__EXTRAFIELD_'.strtoupper($key).'_RFC__'] = dol_print_date($object->array_options['options_'.$key], 'dayrfc');
6525  } elseif ($extrafields->attributes[$object->table_element]['type'][$key] == 'datetime') {
6526  $datetime = $object->array_options['options_'.$key];
6527  $substitutionarray['__EXTRAFIELD_'.strtoupper($key).'__'] = ($datetime != "0000-00-00 00:00:00" ? dol_print_date($datetime, 'dayhour') : '');
6528  $substitutionarray['__EXTRAFIELD_'.strtoupper($key).'_LOCALE__'] = ($datetime != "0000-00-00 00:00:00" ? dol_print_date($datetime, 'dayhour', 'tzserver', $outputlangs) : '');
6529  $substitutionarray['__EXTRAFIELD_'.strtoupper($key).'_DAY_LOCALE__'] = ($datetime != "0000-00-00 00:00:00" ? dol_print_date($datetime, 'day', 'tzserver', $outputlangs) : '');
6530  $substitutionarray['__EXTRAFIELD_'.strtoupper($key).'_RFC__'] = ($datetime != "0000-00-00 00:00:00" ? dol_print_date($datetime, 'dayhourrfc') : '');
6531  }
6532  }
6533  }
6534  }
6535  }
6536 
6537  // Complete substitution array with the url to make online payment
6538  $paymenturl = '';
6539  if (empty($substitutionarray['__REF__']))
6540  {
6541  $paymenturl = '';
6542  } else {
6543  // Set the online payment url link into __ONLINE_PAYMENT_URL__ key
6544  require_once DOL_DOCUMENT_ROOT.'/core/lib/payments.lib.php';
6545  $outputlangs->loadLangs(array('paypal', 'other'));
6546  $typeforonlinepayment = 'free';
6547  if (is_object($object) && $object->element == 'commande') $typeforonlinepayment = 'order';
6548  if (is_object($object) && $object->element == 'facture') $typeforonlinepayment = 'invoice';
6549  if (is_object($object) && $object->element == 'member') $typeforonlinepayment = 'member';
6550  $url = getOnlinePaymentUrl(0, $typeforonlinepayment, $substitutionarray['__REF__']);
6551  $paymenturl = $url;
6552  }
6553 
6554  if ($object->id > 0)
6555  {
6556  $substitutionarray['__ONLINE_PAYMENT_TEXT_AND_URL__'] = ($paymenturl ?str_replace('\n', "\n", $outputlangs->trans("PredefinedMailContentLink", $paymenturl)) : '');
6557  $substitutionarray['__ONLINE_PAYMENT_URL__'] = $paymenturl;
6558 
6559  if (!empty($conf->global->PROPOSAL_ALLOW_EXTERNAL_DOWNLOAD) && is_object($object) && $object->element == 'propal')
6560  {
6561  $substitutionarray['__DIRECTDOWNLOAD_URL_PROPOSAL__'] = $object->getLastMainDocLink($object->element);
6562  } else $substitutionarray['__DIRECTDOWNLOAD_URL_PROPOSAL__'] = '';
6563  if (!empty($conf->global->ORDER_ALLOW_EXTERNAL_DOWNLOAD) && is_object($object) && $object->element == 'commande')
6564  {
6565  $substitutionarray['__DIRECTDOWNLOAD_URL_ORDER__'] = $object->getLastMainDocLink($object->element);
6566  } else $substitutionarray['__DIRECTDOWNLOAD_URL_ORDER__'] = '';
6567  if (!empty($conf->global->INVOICE_ALLOW_EXTERNAL_DOWNLOAD) && is_object($object) && $object->element == 'facture')
6568  {
6569  $substitutionarray['__DIRECTDOWNLOAD_URL_INVOICE__'] = $object->getLastMainDocLink($object->element);
6570  } else $substitutionarray['__DIRECTDOWNLOAD_URL_INVOICE__'] = '';
6571 
6572  if (is_object($object) && $object->element == 'propal') $substitutionarray['__URL_PROPOSAL__'] = DOL_MAIN_URL_ROOT."/comm/propal/card.php?id=".$object->id;
6573  if (is_object($object) && $object->element == 'commande') $substitutionarray['__URL_ORDER__'] = DOL_MAIN_URL_ROOT."/commande/card.php?id=".$object->id;
6574  if (is_object($object) && $object->element == 'facture') $substitutionarray['__URL_INVOICE__'] = DOL_MAIN_URL_ROOT."/compta/facture/card.php?id=".$object->id;
6575  }
6576 
6577  if (is_object($object) && $object->element == 'action')
6578  {
6579  $substitutionarray['__EVENT_LABEL__'] = $object->label;
6580  $substitutionarray['__EVENT_DATE__'] = dol_print_date($object->datep, '%A %d %b %Y');
6581  $substitutionarray['__EVENT_TIME__'] = dol_print_date($object->datep, '%H:%M:%S');
6582  }
6583  }
6584  }
6585  if (empty($exclude) || !in_array('objectamount', $exclude))
6586  {
6587  include_once DOL_DOCUMENT_ROOT.'/core/lib/functionsnumtoword.lib.php';
6588 
6589  $substitutionarray['__DATE_YMD__'] = is_object($object) ? (isset($object->date) ? dol_print_date($object->date, 'day', 0, $outputlangs) : null) : '';
6590  $substitutionarray['__DATE_DUE_YMD__'] = is_object($object) ? (isset($object->date_lim_reglement) ? dol_print_date($object->date_lim_reglement, 'day', 0, $outputlangs) : null) : '';
6591 
6592  $substitutionarray['__AMOUNT__'] = is_object($object) ? $object->total_ttc : '';
6593  $substitutionarray['__AMOUNT_TEXT__'] = is_object($object) ? dol_convertToWord($object->total_ttc, $outputlangs, '', true) : '';
6594  $substitutionarray['__AMOUNT_TEXTCURRENCY__'] = is_object($object) ? dol_convertToWord($object->total_ttc, $outputlangs, $conf->currency, true) : '';
6595  $substitutionarray['__AMOUNT_EXCL_TAX__'] = is_object($object) ? $object->total_ht : '';
6596  $substitutionarray['__AMOUNT_VAT__'] = is_object($object) ? (isset($object->total_vat) ? $object->total_vat : $object->total_tva) : '';
6597  $substitutionarray['__AMOUNT_VAT_TEXT__'] = is_object($object) ? (isset($object->total_vat) ? dol_convertToWord($object->total_vat, $outputlangs, '', true) : dol_convertToWord($object->total_tva, $outputlangs, '', true)) : '';
6598  $substitutionarray['__AMOUNT_VAT_TEXTCURRENCY__'] = is_object($object) ? (isset($object->total_vat) ? dol_convertToWord($object->total_vat, $outputlangs, $conf->currency, true) : dol_convertToWord($object->total_tva, $outputlangs, $conf->currency, true)) : '';
6599  if ($onlykey != 2 || $mysoc->useLocalTax(1)) $substitutionarray['__AMOUNT_TAX2__'] = is_object($object) ? $object->total_localtax1 : '';
6600  if ($onlykey != 2 || $mysoc->useLocalTax(2)) $substitutionarray['__AMOUNT_TAX3__'] = is_object($object) ? $object->total_localtax2 : '';
6601 
6602  $substitutionarray['__AMOUNT_FORMATED__'] = is_object($object) ? ($object->total_ttc ? price($object->total_ttc, 0, $outputlangs, 0, 0, -1, $conf->currency) : null) : '';
6603  $substitutionarray['__AMOUNT_EXCL_TAX_FORMATED__'] = is_object($object) ? ($object->total_ht ? price($object->total_ht, 0, $outputlangs, 0, 0, -1, $conf->currency) : null) : '';
6604  $substitutionarray['__AMOUNT_VAT_FORMATED__'] = is_object($object) ? (isset($object->total_vat) ? price($object->total_vat, 0, $outputlangs, 0, 0, -1, $conf->currency) : ($object->total_tva ? price($object->total_tva, 0, $outputlangs, 0, 0, -1, $conf->currency) : null)) : '';
6605  if ($onlykey != 2 || $mysoc->useLocalTax(1)) $substitutionarray['__AMOUNT_TAX2_FORMATED__'] = is_object($object) ? ($object->total_localtax1 ? price($object->total_localtax1, 0, $outputlangs, 0, 0, -1, $conf->currency) : null) : '';
6606  if ($onlykey != 2 || $mysoc->useLocalTax(2)) $substitutionarray['__AMOUNT_TAX3_FORMATED__'] = is_object($object) ? ($object->total_localtax2 ? price($object->total_localtax2, 0, $outputlangs, 0, 0, -1, $conf->currency) : null) : '';
6607 
6608  $substitutionarray['__AMOUNT_MULTICURRENCY__'] = (is_object($object) && isset($object->multicurrency_total_ttc)) ? $object->multicurrency_total_ttc : '';
6609  $substitutionarray['__AMOUNT_MULTICURRENCY_TEXT__'] = (is_object($object) && isset($object->multicurrency_total_ttc)) ? dol_convertToWord($object->multicurrency_total_ttc, $outputlangs, '', true) : '';
6610  $substitutionarray['__AMOUNT_MULTICURRENCY_TEXTCURRENCY__'] = (is_object($object) && isset($object->multicurrency_total_ttc)) ? dol_convertToWord($object->multicurrency_total_ttc, $outputlangs, $object->multicurrency_code, true) : '';
6611  // TODO Add other keys for foreign multicurrency
6612 
6613  // For backward compatibility
6614  if ($onlykey != 2)
6615  {
6616  $substitutionarray['__TOTAL_TTC__'] = is_object($object) ? $object->total_ttc : '';
6617  $substitutionarray['__TOTAL_HT__'] = is_object($object) ? $object->total_ht : '';
6618  $substitutionarray['__TOTAL_VAT__'] = is_object($object) ? (isset($object->total_vat) ? $object->total_vat : $object->total_tva) : '';
6619  }
6620  }
6621 
6622  //var_dump($substitutionarray['__AMOUNT_FORMATED__']);
6623  if (empty($exclude) || !in_array('date', $exclude))
6624  {
6625  include_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
6626 
6627  $tmp = dol_getdate(dol_now(), true);
6628  $tmp2 = dol_get_prev_day($tmp['mday'], $tmp['mon'], $tmp['year']);
6629  $tmp3 = dol_get_prev_month($tmp['mon'], $tmp['year']);
6630  $tmp4 = dol_get_next_day($tmp['mday'], $tmp['mon'], $tmp['year']);
6631  $tmp5 = dol_get_next_month($tmp['mon'], $tmp['year']);
6632 
6633  $daytext = $outputlangs->trans('Day'.$tmp['wday']);
6634 
6635  $substitutionarray = array_merge($substitutionarray, array(
6636  '__DAY__' => (string) $tmp['mday'],
6637  '__DAY_TEXT__' => $daytext, // Monday
6638  '__DAY_TEXT_SHORT__' => dol_trunc($daytext, 3, 'right', 'UTF-8', 1), // Mon
6639  '__DAY_TEXT_MIN__' => dol_trunc($daytext, 1, 'right', 'UTF-8', 1), // M
6640  '__MONTH__' => (string) $tmp['mon'],
6641  '__MONTH_TEXT__' => $outputlangs->trans('Month'.sprintf("%02d", $tmp['mon'])),
6642  '__MONTH_TEXT_SHORT__' => $outputlangs->trans('MonthShort'.sprintf("%02d", $tmp['mon'])),
6643  '__MONTH_TEXT_MIN__' => $outputlangs->trans('MonthVeryShort'.sprintf("%02d", $tmp['mon'])),
6644  '__YEAR__' => (string) $tmp['year'],
6645  '__PREVIOUS_DAY__' => (string) $tmp2['day'],
6646  '__PREVIOUS_MONTH__' => (string) $tmp3['month'],
6647  '__PREVIOUS_YEAR__' => (string) ($tmp['year'] - 1),
6648  '__NEXT_DAY__' => (string) $tmp4['day'],
6649  '__NEXT_MONTH__' => (string) $tmp5['month'],
6650  '__NEXT_YEAR__' => (string) ($tmp['year'] + 1),
6651  ));
6652  }
6653 
6654  if (!empty($conf->multicompany->enabled))
6655  {
6656  $substitutionarray = array_merge($substitutionarray, array('__ENTITY_ID__' => $conf->entity));
6657  }
6658  if (empty($exclude) || !in_array('system', $exclude))
6659  {
6660  $substitutionarray['__DOL_MAIN_URL_ROOT__'] = DOL_MAIN_URL_ROOT;
6661  $substitutionarray['__(AnyTranslationKey)__'] = $outputlangs->trans('TranslationOfKey');
6662  $substitutionarray['__(AnyTranslationKey|langfile)__'] = $outputlangs->trans('TranslationOfKey').' (load also language file before)';
6663  $substitutionarray['__[AnyConstantKey]__'] = $outputlangs->trans('ValueOfConstantKey');
6664  }
6665 
6666  return $substitutionarray;
6667 }
6668 
6683 function make_substitutions($text, $substitutionarray, $outputlangs = null)
6684 {
6685  global $conf, $langs;
6686 
6687  if (!is_array($substitutionarray)) return 'ErrorBadParameterSubstitutionArrayWhenCalling_make_substitutions';
6688 
6689  if (empty($outputlangs)) $outputlangs = $langs;
6690 
6691  // Make substitution for language keys: __(AnyTranslationKey)__ or __(AnyTranslationKey|langfile)__
6692  if (is_object($outputlangs))
6693  {
6694  $reg = array();
6695  while (preg_match('/__\(([^\)]+)\)__/', $text, $reg))
6696  {
6697  $msgishtml = 0;
6698  if (dol_textishtml($text, 1)) $msgishtml = 1;
6699 
6700  // If key is __(TranslationKey|langfile)__, then force load of langfile.lang
6701  $tmp = explode('|', $reg[1]);
6702  if (!empty($tmp[1])) $outputlangs->load($tmp[1]);
6703 
6704  $text = preg_replace('/__\('.preg_quote($reg[1], '/').'\)__/', $msgishtml ?dol_htmlentitiesbr($outputlangs->transnoentitiesnoconv($reg[1])) : $outputlangs->transnoentitiesnoconv($reg[1]), $text);
6705  }
6706  }
6707 
6708  // Make substitution for constant keys.
6709  // Must be after the substitution of translation, so if the text of translation contains a string __[xxx]__, it is also converted.
6710  $reg = array();
6711  while (preg_match('/__\[([^\]]+)\]__/', $text, $reg))
6712  {
6713  $msgishtml = 0;
6714  if (dol_textishtml($text, 1)) $msgishtml = 1;
6715 
6716  $keyfound = $reg[1];
6717  if (isASecretKey($keyfound)) $newval = '*****forbidden*****';
6718  else $newval = empty($conf->global->$keyfound) ? '' : $conf->global->$keyfound;
6719  $text = preg_replace('/__\['.preg_quote($keyfound, '/').'\]__/', $msgishtml ?dol_htmlentitiesbr($newval) : $newval, $text);
6720  }
6721 
6722  // Make substitition for array $substitutionarray
6723  foreach ($substitutionarray as $key => $value)
6724  {
6725  if (!isset($value)) continue; // If value is null, it same than not having substitution key at all into array, we do not replace.
6726 
6727  if ($key == '__USER_SIGNATURE__' && (!empty($conf->global->MAIN_MAIL_DO_NOT_USE_SIGN))) $value = ''; // Protection
6728 
6729  $text = str_replace("$key", "$value", $text); // We must keep the " to work when value is 123.5 for example
6730  }
6731 
6732  return $text;
6733 }
6734 
6747 function complete_substitutions_array(&$substitutionarray, $outputlangs, $object = null, $parameters = null, $callfunc = "completesubstitutionarray")
6748 {
6749  global $conf, $user;
6750 
6751  require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
6752 
6753  // Add a substitution key for each extrafields, using key __EXTRA_XXX__
6754  // TODO Remove this. Already available into the getCommonSubstitutionArray used to build the substitution array.
6755  /*if (is_object($object) && is_array($object->array_options))
6756  {
6757  foreach($object->array_options as $key => $val)
6758  {
6759  $keyshort=preg_replace('/^(options|extra)_/','',$key);
6760  $substitutionarray['__EXTRAFIELD_'.$keyshort.'__']=$val;
6761  // For backward compatibiliy
6762  $substitutionarray['%EXTRA_'.$keyshort.'%']=$val;
6763  }
6764  }*/
6765 
6766  // Check if there is external substitution to do, requested by plugins
6767  $dirsubstitutions = array_merge(array(), (array) $conf->modules_parts['substitutions']);
6768 
6769  foreach ($dirsubstitutions as $reldir)
6770  {
6771  $dir = dol_buildpath($reldir, 0);
6772 
6773  // Check if directory exists
6774  if (!dol_is_dir($dir)) continue;
6775 
6776  $substitfiles = dol_dir_list($dir, 'files', 0, 'functions_');
6777  foreach ($substitfiles as $substitfile)
6778  {
6779  $reg = array();
6780  if (preg_match('/functions_(.*)\.lib\.php/i', $substitfile['name'], $reg))
6781  {
6782  $module = $reg[1];
6783 
6784  dol_syslog("Library ".$substitfile['name']." found into ".$dir);
6785  // Include the user's functions file
6786  require_once $dir.$substitfile['name'];
6787  // Call the user's function, and only if it is defined
6788  $function_name = $module."_".$callfunc;
6789  if (function_exists($function_name)) {
6790  $function_name($substitutionarray, $outputlangs, $object, $parameters);
6791  }
6792  }
6793  }
6794  }
6795  if (!empty($conf->global->ODT_ENABLE_ALL_TAGS_IN_SUBSTITUTIONS)) {
6796  // to list all tags in odt template
6797  $tags = '';
6798  foreach ($substitutionarray as $key => $value) {
6799  $tags .= '{'.$key.'} => '.$value."\n";
6800  }
6801  $substitutionarray = array_merge($substitutionarray, array('__ALL_TAGS__' => $tags));
6802  }
6803 }
6804 
6814 function print_date_range($date_start, $date_end, $format = '', $outputlangs = '')
6815 {
6816  print get_date_range($date_start, $date_end, $format, $outputlangs);
6817 }
6818 
6829 function get_date_range($date_start, $date_end, $format = '', $outputlangs = '', $withparenthesis = 1)
6830 {
6831  global $langs;
6832 
6833  $out = '';
6834 
6835  if (!is_object($outputlangs)) $outputlangs = $langs;
6836 
6837  if ($date_start && $date_end)
6838  {
6839  $out .= ($withparenthesis ? ' (' : '').$outputlangs->transnoentitiesnoconv('DateFromTo', dol_print_date($date_start, $format, false, $outputlangs), dol_print_date($date_end, $format, false, $outputlangs)).($withparenthesis ? ')' : '');
6840  }
6841  if ($date_start && !$date_end)
6842  {
6843  $out .= ($withparenthesis ? ' (' : '').$outputlangs->transnoentitiesnoconv('DateFrom', dol_print_date($date_start, $format, false, $outputlangs)).($withparenthesis ? ')' : '');
6844  }
6845  if (!$date_start && $date_end)
6846  {
6847  $out .= ($withparenthesis ? ' (' : '').$outputlangs->transnoentitiesnoconv('DateUntil', dol_print_date($date_end, $format, false, $outputlangs)).($withparenthesis ? ')' : '');
6848  }
6849 
6850  return $out;
6851 }
6852 
6861 function dolGetFirstLastname($firstname, $lastname, $nameorder = -1)
6862 {
6863  global $conf;
6864 
6865  $ret = '';
6866  // If order not defined, we use the setup
6867  if ($nameorder < 0) $nameorder = (empty($conf->global->MAIN_FIRSTNAME_NAME_POSITION) ? 1 : 0);
6868  if ($nameorder == 1) {
6869  $ret .= $firstname;
6870  if ($firstname && $lastname) $ret .= ' ';
6871  $ret .= $lastname;
6872  } elseif ($nameorder == 2 || $nameorder == 3) {
6873  $ret .= $firstname;
6874  if (empty($ret) && $nameorder == 3) {
6875  $ret .= $lastname;
6876  }
6877  } else { // 0, 4 or 5
6878  $ret .= $lastname;
6879  if (empty($ret) && $nameorder == 5) {
6880  $ret .= $firstname;
6881  }
6882  if ($nameorder == 0) {
6883  if ($firstname && $lastname) $ret .= ' ';
6884  $ret .= $firstname;
6885  }
6886  }
6887  return $ret;
6888 }
6889 
6890 
6901 function setEventMessage($mesgs, $style = 'mesgs')
6902 {
6903  //dol_syslog(__FUNCTION__ . " is deprecated", LOG_WARNING); This is not deprecated, it is used by setEventMessages function
6904  if (!is_array($mesgs)) {
6905  // If mesgs is a string
6906  if ($mesgs) $_SESSION['dol_events'][$style][] = $mesgs;
6907  } else {
6908  // If mesgs is an array
6909  foreach ($mesgs as $mesg)
6910  {
6911  if ($mesg) $_SESSION['dol_events'][$style][] = $mesg;
6912  }
6913  }
6914 }
6915 
6927 function setEventMessages($mesg, $mesgs, $style = 'mesgs', $messagekey = '')
6928 {
6929  if (empty($mesg) && empty($mesgs))
6930  {
6931  dol_syslog("Try to add a message in stack with empty message", LOG_WARNING);
6932  } else {
6933  if ($messagekey)
6934  {
6935  // Complete message with a js link to set a cookie "DOLHIDEMESSAGE".$messagekey;
6936  // TODO
6937  $mesg .= '';
6938  }
6939  if (empty($messagekey) || empty($_COOKIE["DOLHIDEMESSAGE".$messagekey]))
6940  {
6941  if (!in_array((string) $style, array('mesgs', 'warnings', 'errors'))) dol_print_error('', 'Bad parameter style='.$style.' for setEventMessages');
6942  if (empty($mesgs)) setEventMessage($mesg, $style);
6943  else {
6944  if (!empty($mesg) && !in_array($mesg, $mesgs)) setEventMessage($mesg, $style); // Add message string if not already into array
6945  setEventMessage($mesgs, $style);
6946  }
6947  }
6948  }
6949 }
6950 
6960 function dol_htmloutput_events($disabledoutputofmessages = 0)
6961 {
6962  // Show mesgs
6963  if (isset($_SESSION['dol_events']['mesgs'])) {
6964  if (empty($disabledoutputofmessages)) dol_htmloutput_mesg('', $_SESSION['dol_events']['mesgs']);
6965  unset($_SESSION['dol_events']['mesgs']);
6966  }
6967 
6968  // Show errors
6969  if (isset($_SESSION['dol_events']['errors'])) {
6970  if (empty($disabledoutputofmessages)) dol_htmloutput_mesg('', $_SESSION['dol_events']['errors'], 'error');
6971  unset($_SESSION['dol_events']['errors']);
6972  }
6973 
6974  // Show warnings
6975  if (isset($_SESSION['dol_events']['warnings'])) {
6976  if (empty($disabledoutputofmessages)) dol_htmloutput_mesg('', $_SESSION['dol_events']['warnings'], 'warning');
6977  unset($_SESSION['dol_events']['warnings']);
6978  }
6979 }
6980 
6995 function get_htmloutput_mesg($mesgstring = '', $mesgarray = '', $style = 'ok', $keepembedded = 0)
6996 {
6997  global $conf, $langs;
6998 
6999  $ret = 0; $return = '';
7000  $out = '';
7001  $divstart = $divend = '';
7002 
7003  // If inline message with no format, we add it.
7004  if ((empty($conf->use_javascript_ajax) || !empty($conf->global->MAIN_DISABLE_JQUERY_JNOTIFY) || $keepembedded) && !preg_match('/<div class=".*">/i', $out))
7005  {
7006  $divstart = '<div class="'.$style.' clearboth">';
7007  $divend = '</div>';
7008  }
7009 
7010  if ((is_array($mesgarray) && count($mesgarray)) || $mesgstring)
7011  {
7012  $langs->load("errors");
7013  $out .= $divstart;
7014  if (is_array($mesgarray) && count($mesgarray))
7015  {
7016  foreach ($mesgarray as $message)
7017  {
7018  $ret++;
7019  $out .= $langs->trans($message);
7020  if ($ret < count($mesgarray)) $out .= "<br>\n";
7021  }
7022  }
7023  if ($mesgstring)
7024  {
7025  $langs->load("errors");
7026  $ret++;
7027  $out .= $langs->trans($mesgstring);
7028  }
7029  $out .= $divend;
7030  }
7031 
7032  if ($out)
7033  {
7034  if (!empty($conf->use_javascript_ajax) && empty($conf->global->MAIN_DISABLE_JQUERY_JNOTIFY) && empty($keepembedded))
7035  {
7036  $return = '<script>
7037  $(document).ready(function() {
7038  var block = '.(!empty($conf->global->MAIN_USE_JQUERY_BLOCKUI) ? "true" : "false").'
7039  if (block) {
7040  $.dolEventValid("","'.dol_escape_js($out).'");
7041  } else {
7042  /* jnotify(message, preset of message type, keepmessage) */
7043  $.jnotify("'.dol_escape_js($out).'",
7044  "'.($style == "ok" ? 3000 : $style).'",
7045  '.($style == "ok" ? "false" : "true").',
7046  { remove: function (){} } );
7047  }
7048  });
7049  </script>';
7050  } else {
7051  $return = $out;
7052  }
7053  }
7054 
7055  return $return;
7056 }
7057 
7069 function get_htmloutput_errors($mesgstring = '', $mesgarray = array(), $keepembedded = 0)
7070 {
7071  return get_htmloutput_mesg($mesgstring, $mesgarray, 'error', $keepembedded);
7072 }
7073 
7087 function dol_htmloutput_mesg($mesgstring = '', $mesgarray = array(), $style = 'ok', $keepembedded = 0)
7088 {
7089  if (empty($mesgstring) && (!is_array($mesgarray) || count($mesgarray) == 0)) return;
7090 
7091  $iserror = 0;
7092  $iswarning = 0;
7093  if (is_array($mesgarray))
7094  {
7095  foreach ($mesgarray as $val)
7096  {
7097  if ($val && preg_match('/class="error"/i', $val)) { $iserror++; break; }
7098  if ($val && preg_match('/class="warning"/i', $val)) { $iswarning++; break; }
7099  }
7100  } elseif ($mesgstring && preg_match('/class="error"/i', $mesgstring)) $iserror++;
7101  elseif ($mesgstring && preg_match('/class="warning"/i', $mesgstring)) $iswarning++;
7102  if ($style == 'error') $iserror++;
7103  if ($style == 'warning') $iswarning++;
7104 
7105  if ($iserror || $iswarning)
7106  {
7107  // Remove div from texts
7108  $mesgstring = preg_replace('/<\/div><div class="(error|warning)">/', '<br>', $mesgstring);
7109  $mesgstring = preg_replace('/<div class="(error|warning)">/', '', $mesgstring);
7110  $mesgstring = preg_replace('/<\/div>/', '', $mesgstring);
7111  // Remove div from texts array
7112  if (is_array($mesgarray))
7113  {
7114  $newmesgarray = array();
7115  foreach ($mesgarray as $val)
7116  {
7117  if (is_string($val))
7118  {
7119  $tmpmesgstring = preg_replace('/<\/div><div class="(error|warning)">/', '<br>', $val);
7120  $tmpmesgstring = preg_replace('/<div class="(error|warning)">/', '', $tmpmesgstring);
7121  $tmpmesgstring = preg_replace('/<\/div>/', '', $tmpmesgstring);
7122  $newmesgarray[] = $tmpmesgstring;
7123  } else {
7124  dol_syslog("Error call of dol_htmloutput_mesg with an array with a value that is not a string", LOG_WARNING);
7125  }
7126  }
7127  $mesgarray = $newmesgarray;
7128  }
7129  print get_htmloutput_mesg($mesgstring, $mesgarray, ($iserror ? 'error' : 'warning'), $keepembedded);
7130  } else print get_htmloutput_mesg($mesgstring, $mesgarray, 'ok', $keepembedded);
7131 }
7132 
7144 function dol_htmloutput_errors($mesgstring = '', $mesgarray = array(), $keepembedded = 0)
7145 {
7146  dol_htmloutput_mesg($mesgstring, $mesgarray, 'error', $keepembedded);
7147 }
7148 
7162 function dol_sort_array(&$array, $index, $order = 'asc', $natsort = 0, $case_sensitive = 0, $keepindex = 0)
7163 {
7164  // Clean parameters
7165  $order = strtolower($order);
7166 
7167  if (is_array($array))
7168  {
7169  $sizearray = count($array);
7170  if ($sizearray > 0)
7171  {
7172  $temp = array();
7173  foreach (array_keys($array) as $key)
7174  {
7175  if (is_object($array[$key])) {
7176  $temp[$key] = empty($array[$key]->$index) ? 0 : $array[$key]->$index;
7177  } else {
7178  $temp[$key] = empty($array[$key][$index]) ? 0 : $array[$key][$index];
7179  }
7180  }
7181 
7182  if (!$natsort) {
7183  ($order == 'asc') ? asort($temp) : arsort($temp);
7184  } else {
7185  ($case_sensitive) ? natsort($temp) : natcasesort($temp);
7186  if ($order != 'asc') $temp = array_reverse($temp, true);
7187  }
7188 
7189  $sorted = array();
7190 
7191  foreach (array_keys($temp) as $key)
7192  {
7193  (is_numeric($key) && empty($keepindex)) ? $sorted[] = $array[$key] : $sorted[$key] = $array[$key];
7194  }
7195 
7196  return $sorted;
7197  }
7198  }
7199  return $array;
7200 }
7201 
7202 
7209 function utf8_check($str)
7210 {
7211  $str = (string) $str; // Sometimes string is an int.
7212 
7213  // We must use here a binary strlen function (so not dol_strlen)
7214  $strLength = dol_strlen($str);
7215  for ($i = 0; $i < $strLength; $i++) {
7216  if (ord($str[$i]) < 0x80) continue; // 0bbbbbbb
7217  elseif ((ord($str[$i]) & 0xE0) == 0xC0) $n = 1; // 110bbbbb
7218  elseif ((ord($str[$i]) & 0xF0) == 0xE0) $n = 2; // 1110bbbb
7219  elseif ((ord($str[$i]) & 0xF8) == 0xF0) $n = 3; // 11110bbb
7220  elseif ((ord($str[$i]) & 0xFC) == 0xF8) $n = 4; // 111110bb
7221  elseif ((ord($str[$i]) & 0xFE) == 0xFC) $n = 5; // 1111110b
7222  else return false; // Does not match any model
7223  for ($j = 0; $j < $n; $j++) { // n bytes matching 10bbbbbb follow ?
7224  if ((++$i == strlen($str)) || ((ord($str[$i]) & 0xC0) != 0x80))
7225  return false;
7226  }
7227  }
7228  return true;
7229 }
7230 
7237 function ascii_check($str)
7238 {
7239  if (function_exists('mb_check_encoding')) {
7240  //if (mb_detect_encoding($str, 'ASCII', true) return false;
7241  if (!mb_check_encoding($str, 'ASCII')) return false;
7242  } else {
7243  if (preg_match('/[^\x00-\x7f]/', $str)) return false; // Contains a byte > 7f
7244  }
7245 
7246  return true;
7247 }
7248 
7249 
7257 function dol_osencode($str)
7258 {
7259  global $conf;
7260 
7261  $tmp = ini_get("unicode.filesystem_encoding"); // Disponible avec PHP 6.0
7262  if (empty($tmp) && !empty($_SERVER["WINDIR"])) $tmp = 'iso-8859-1'; // By default for windows
7263  if (empty($tmp)) $tmp = 'utf-8'; // By default for other
7264  if (!empty($conf->global->MAIN_FILESYSTEM_ENCODING)) $tmp = $conf->global->MAIN_FILESYSTEM_ENCODING;
7265 
7266  if ($tmp == 'iso-8859-1') return utf8_decode($str);
7267  return $str;
7268 }
7269 
7270 
7284 function dol_getIdFromCode($db, $key, $tablename, $fieldkey = 'code', $fieldid = 'id', $entityfilter = 0)
7285 {
7286  global $cache_codes;
7287 
7288  // If key empty
7289  if ($key == '') return '';
7290 
7291  // Check in cache
7292  if (isset($cache_codes[$tablename][$key][$fieldid])) // Can be defined to 0 or ''
7293  {
7294  return $cache_codes[$tablename][$key][$fieldid]; // Found in cache
7295  }
7296 
7297  dol_syslog('dol_getIdFromCode (value for field '.$fieldid.' from key '.$key.' not found into cache)', LOG_DEBUG);
7298 
7299  $sql = "SELECT ".$fieldid." as valuetoget";
7300  $sql .= " FROM ".MAIN_DB_PREFIX.$tablename;
7301  $sql .= " WHERE ".$fieldkey." = '".$db->escape($key)."'";
7302  if (!empty($entityfilter))
7303  $sql .= " AND entity IN (".getEntity($tablename).")";
7304 
7305  $resql = $db->query($sql);
7306  if ($resql)
7307  {
7308  $obj = $db->fetch_object($resql);
7309  if ($obj) $cache_codes[$tablename][$key][$fieldid] = $obj->valuetoget;
7310  else $cache_codes[$tablename][$key][$fieldid] = '';
7311  $db->free($resql);
7312  return $cache_codes[$tablename][$key][$fieldid];
7313  } else {
7314  return -1;
7315  }
7316 }
7317 
7324 function verifCond($strRights)
7325 {
7326  global $user, $conf, $langs;
7327  global $leftmenu;
7328  global $rights; // To export to dol_eval function
7329 
7330  //print $strRights."<br>\n";
7331  $rights = true;
7332  if ($strRights != '')
7333  {
7334  $str = 'if(!('.$strRights.')) { $rights = false; }';
7335  dol_eval($str); // The dol_eval must contains all the global $xxx used into a condition
7336  }
7337  return $rights;
7338 }
7339 
7349 function dol_eval($s, $returnvalue = 0, $hideerrors = 1)
7350 {
7351  // Only global variables can be changed by eval function and returned to caller
7352  global $db, $langs, $user, $conf, $website, $websitepage;
7353  global $action, $mainmenu, $leftmenu;
7354  global $rights;
7355  global $object;
7356  global $mysoc;
7357 
7358  global $obj; // To get $obj used into list when dol_eval is used for computed fields and $obj is not yet $object
7359  global $soc; // For backward compatibility
7360 
7361  //print $s."<br>\n";
7362  if ($returnvalue) {
7363  if ($hideerrors) return @eval('return '.$s.';');
7364  else return eval('return '.$s.';');
7365  } else {
7366  if ($hideerrors) @eval($s);
7367  else eval($s);
7368  }
7369 }
7370 
7377 function dol_validElement($element)
7378 {
7379  return (trim($element) != '');
7380 }
7381 
7389 function picto_from_langcode($codelang, $moreatt = '')
7390 {
7391  if (empty($codelang)) return '';
7392 
7393  if ($codelang == 'auto')
7394  {
7395  return '<span class="fa fa-globe"></span>';
7396  }
7397 
7398  $langtocountryflag = array(
7399  'ar_AR' => '',
7400  'ca_ES' => 'catalonia',
7401  'da_DA' => 'dk',
7402  'fr_CA' => 'mq',
7403  'sv_SV' => 'se',
7404  'sw_SW' => 'unknown',
7405  'AQ' => 'unknown',
7406  'CW' => 'unknown',
7407  'IM' => 'unknown',
7408  'JE' => 'unknown',
7409  'MF' => 'unknown',
7410  'BL' => 'unknown',
7411  'SX' => 'unknown'
7412  );
7413 
7414  if (isset($langtocountryflag[$codelang])) $flagImage = $langtocountryflag[$codelang];
7415  else {
7416  $tmparray = explode('_', $codelang);
7417  $flagImage = empty($tmparray[1]) ? $tmparray[0] : $tmparray[1];
7418  }
7419 
7420  return img_picto_common($codelang, 'flags/'.strtolower($flagImage).'.png', $moreatt);
7421 }
7422 
7430 function getLanguageCodeFromCountryCode($countrycode)
7431 {
7432  global $mysoc;
7433 
7434  if (empty($countrycode)) return null;
7435 
7436  if (strtoupper($countrycode) == 'MQ') return 'fr_CA';
7437  if (strtoupper($countrycode) == 'SE') return 'sv_SE'; // se_SE is Sami/Sweden, and we want in priority sv_SE for SE country
7438  if (strtoupper($countrycode) == 'CH')
7439  {
7440  if ($mysoc->country_code == 'FR') return 'fr_CH';
7441  if ($mysoc->country_code == 'DE') return 'de_CH';
7442  }
7443 
7444  // Locale list taken from:
7445  // http://stackoverflow.com/questions/3191664/
7446  // list-of-all-locales-and-their-short-codes
7447  $locales = array(
7448  'af-ZA',
7449  'am-ET',
7450  'ar-AE',
7451  'ar-BH',
7452  'ar-DZ',
7453  'ar-EG',
7454  'ar-IQ',
7455  'ar-JO',
7456  'ar-KW',
7457  'ar-LB',
7458  'ar-LY',
7459  'ar-MA',
7460  'ar-OM',
7461  'ar-QA',
7462  'ar-SA',
7463  'ar-SY',
7464  'ar-TN',
7465  'ar-YE',
7466  'as-IN',
7467  'ba-RU',
7468  'be-BY',
7469  'bg-BG',
7470  'bn-BD',
7471  'bn-IN',
7472  'bo-CN',
7473  'br-FR',
7474  'ca-ES',
7475  'co-FR',
7476  'cs-CZ',
7477  'cy-GB',
7478  'da-DK',
7479  'de-AT',
7480  'de-CH',
7481  'de-DE',
7482  'de-LI',
7483  'de-LU',
7484  'dv-MV',
7485  'el-GR',
7486  'en-AU',
7487  'en-BZ',
7488  'en-CA',
7489  'en-GB',
7490  'en-IE',
7491  'en-IN',
7492  'en-JM',
7493  'en-MY',
7494  'en-NZ',
7495  'en-PH',
7496  'en-SG',
7497  'en-TT',
7498  'en-US',
7499  'en-ZA',
7500  'en-ZW',
7501  'es-AR',
7502  'es-BO',
7503  'es-CL',
7504  'es-CO',
7505  'es-CR',
7506  'es-DO',
7507  'es-EC',
7508  'es-ES',
7509  'es-GT',
7510  'es-HN',
7511  'es-MX',
7512  'es-NI',
7513  'es-PA',
7514  'es-PE',
7515  'es-PR',
7516  'es-PY',
7517  'es-SV',
7518  'es-US',
7519  'es-UY',
7520  'es-VE',
7521  'et-EE',
7522  'eu-ES',
7523  'fa-IR',
7524  'fi-FI',
7525  'fo-FO',
7526  'fr-BE',
7527  'fr-CA',
7528  'fr-CH',
7529  'fr-FR',
7530  'fr-LU',
7531  'fr-MC',
7532  'fy-NL',
7533  'ga-IE',
7534  'gd-GB',
7535  'gl-ES',
7536  'gu-IN',
7537  'he-IL',
7538  'hi-IN',
7539  'hr-BA',
7540  'hr-HR',
7541  'hu-HU',
7542  'hy-AM',
7543  'id-ID',
7544  'ig-NG',
7545  'ii-CN',
7546  'is-IS',
7547  'it-CH',
7548  'it-IT',
7549  'ja-JP',
7550  'ka-GE',
7551  'kk-KZ',
7552  'kl-GL',
7553  'km-KH',
7554  'kn-IN',
7555  'ko-KR',
7556  'ky-KG',
7557  'lb-LU',
7558  'lo-LA',
7559  'lt-LT',
7560  'lv-LV',
7561  'mi-NZ',
7562  'mk-MK',
7563  'ml-IN',
7564  'mn-MN',
7565  'mr-IN',
7566  'ms-BN',
7567  'ms-MY',
7568  'mt-MT',
7569  'nb-NO',
7570  'ne-NP',
7571  'nl-BE',
7572  'nl-NL',
7573  'nn-NO',
7574  'oc-FR',
7575  'or-IN',
7576  'pa-IN',
7577  'pl-PL',
7578  'ps-AF',
7579  'pt-BR',
7580  'pt-PT',
7581  'rm-CH',
7582  'ro-RO',
7583  'ru-RU',
7584  'rw-RW',
7585  'sa-IN',
7586  'se-FI',
7587  'se-NO',
7588  'se-SE',
7589  'si-LK',
7590  'sk-SK',
7591  'sl-SI',
7592  'sq-AL',
7593  'sv-FI',
7594  'sv-SE',
7595  'sw-KE',
7596  'ta-IN',
7597  'te-IN',
7598  'th-TH',
7599  'tk-TM',
7600  'tn-ZA',
7601  'tr-TR',
7602  'tt-RU',
7603  'ug-CN',
7604  'uk-UA',
7605  'ur-PK',
7606  'vi-VN',
7607  'wo-SN',
7608  'xh-ZA',
7609  'yo-NG',
7610  'zh-CN',
7611  'zh-HK',
7612  'zh-MO',
7613  'zh-SG',
7614  'zh-TW',
7615  'zu-ZA',
7616  );
7617 
7618  $buildprimarykeytotest = strtolower($countrycode).'-'.strtoupper($countrycode);
7619  if (in_array($buildprimarykeytotest, $locales)) return strtolower($countrycode).'_'.strtoupper($countrycode);
7620 
7621  if (function_exists('locale_get_primary_language') && function_exists('locale_get_region')) // Need extension php-intl
7622  {
7623  foreach ($locales as $locale)
7624  {
7625  $locale_language = locale_get_primary_language($locale);
7626  $locale_region = locale_get_region($locale);
7627  if (strtoupper($countrycode) == $locale_region)
7628  {
7629  //var_dump($locale.'-'.$locale_language.'-'.$locale_region);
7630  return strtolower($locale_language).'_'.strtoupper($locale_region);
7631  }
7632  }
7633  } else {
7634  dol_syslog("Warning Exention php-intl is not available", LOG_WARNING);
7635  }
7636 
7637  return null;
7638 }
7639 
7669 function complete_head_from_modules($conf, $langs, $object, &$head, &$h, $type, $mode = 'add')
7670 {
7671  global $hookmanager;
7672 
7673  if (isset($conf->modules_parts['tabs'][$type]) && is_array($conf->modules_parts['tabs'][$type]))
7674  {
7675  foreach ($conf->modules_parts['tabs'][$type] as $value)
7676  {
7677  $values = explode(':', $value);
7678 
7679  if ($mode == 'add' && !preg_match('/^\-/', $values[1]))
7680  {
7681  if (count($values) == 6) // new declaration with permissions: $value='objecttype:+tabname1:Title1:langfile@mymodule:$user->rights->mymodule->read:/mymodule/mynewtab1.php?id=__ID__'
7682  {
7683  if ($values[0] != $type) continue;
7684 
7685  if (verifCond($values[4]))
7686  {
7687  if ($values[3]) $langs->load($values[3]);
7688  if (preg_match('/SUBSTITUTION_([^_]+)/i', $values[2], $reg))
7689  {
7690  $substitutionarray = array();
7691  complete_substitutions_array($substitutionarray, $langs, $object, array('needforkey'=>$values[2]));
7692  $label = make_substitutions($reg[1], $substitutionarray);
7693  } else $label = $langs->trans($values[2]);
7694 
7695  $head[$h][0] = dol_buildpath(preg_replace('/__ID__/i', ((is_object($object) && !empty($object->id)) ? $object->id : ''), $values[5]), 1);
7696  $head[$h][1] = $label;
7697  $head[$h][2] = str_replace('+', '', $values[1]);
7698  $h++;
7699  }
7700  } elseif (count($values) == 5) // deprecated
7701  {
7702  dol_syslog('Passing 5 values in tabs module_parts is deprecated. Please update to 6 with permissions.', LOG_WARNING);
7703 
7704  if ($values[0] != $type) continue;
7705  if ($values[3]) $langs->load($values[3]);
7706  if (preg_match('/SUBSTITUTION_([^_]+)/i', $values[2], $reg))
7707  {
7708  $substitutionarray = array();
7709  complete_substitutions_array($substitutionarray, $langs, $object, array('needforkey'=>$values[2]));
7710  $label = make_substitutions($reg[1], $substitutionarray);
7711  } else $label = $langs->trans($values[2]);
7712 
7713  $head[$h][0] = dol_buildpath(preg_replace('/__ID__/i', ((is_object($object) && !empty($object->id)) ? $object->id : ''), $values[4]), 1);
7714  $head[$h][1] = $label;
7715  $head[$h][2] = str_replace('+', '', $values[1]);
7716  $h++;
7717  }
7718  } elseif ($mode == 'remove' && preg_match('/^\-/', $values[1]))
7719  {
7720  if ($values[0] != $type) continue;
7721  $tabname = str_replace('-', '', $values[1]);
7722  foreach ($head as $key => $val)
7723  {
7724  $condition = (!empty($values[3]) ? verifCond($values[3]) : 1);
7725  //var_dump($key.' - '.$tabname.' - '.$head[$key][2].' - '.$values[3].' - '.$condition);
7726  if ($head[$key][2] == $tabname && $condition)
7727  {
7728  unset($head[$key]);
7729  break;
7730  }
7731  }
7732  }
7733  }
7734  }
7735 
7736  // No need to make a return $head. Var is modified as a reference
7737  if (!empty($hookmanager))
7738  {
7739  $parameters = array('object' => $object, 'mode' => $mode, 'head' => $head);
7740  $reshook = $hookmanager->executeHooks('completeTabsHead', $parameters);
7741  if ($reshook > 0)
7742  {
7743  $head = $hookmanager->resArray;
7744  $h = count($head);
7745  }
7746  }
7747 }
7748 
7760 function printCommonFooter($zone = 'private')
7761 {
7762  global $conf, $hookmanager, $user, $debugbar;
7763  global $action;
7764  global $micro_start_time;
7765 
7766  if ($zone == 'private') print "\n".'<!-- Common footer for private page -->'."\n";
7767  else print "\n".'<!-- Common footer for public page -->'."\n";
7768 
7769  // A div to store page_y POST parameter so we can read it using javascript
7770  print "\n<!-- A div to store page_y POST parameter -->\n";
7771  print '<div id="page_y" style="display: none;">'.(empty($_POST['page_y']) ? '' : $_POST['page_y']).'</div>'."\n";
7772 
7773  $parameters = array();
7774  $reshook = $hookmanager->executeHooks('printCommonFooter', $parameters); // Note that $action and $object may have been modified by some hooks
7775  if (empty($reshook))
7776  {
7777  if (!empty($conf->global->MAIN_HTML_FOOTER)) print $conf->global->MAIN_HTML_FOOTER."\n";
7778 
7779  print "\n";
7780  if (!empty($conf->use_javascript_ajax))
7781  {
7782  print '<script>'."\n";
7783  print 'jQuery(document).ready(function() {'."\n";
7784 
7785  if ($zone == 'private' && empty($conf->dol_use_jmobile))
7786  {
7787  print "\n";
7788  print '/* JS CODE TO ENABLE to manage handler to switch left menu page (menuhider) */'."\n";
7789  print 'jQuery("li.menuhider").click(function(event) {';
7790  print ' if (!$( "body" ).hasClass( "sidebar-collapse" )){ event.preventDefault(); }'."\n";
7791  print ' console.log("We click on .menuhider");'."\n";
7792  print ' $("body").toggleClass("sidebar-collapse")'."\n";
7793  print '});'."\n";
7794  }
7795 
7796  // Management of focus and mandatory for fields
7797  if ($action == 'create' || $action == 'edit' || (empty($action) && (preg_match('/new\.php/', $_SERVER["PHP_SELF"]))))
7798  {
7799  print '/* JS CODE TO ENABLE to manage focus and mandatory form fields */'."\n";
7800  $relativepathstring = $_SERVER["PHP_SELF"];
7801  // Clean $relativepathstring
7802  if (constant('DOL_URL_ROOT')) $relativepathstring = preg_replace('/^'.preg_quote(constant('DOL_URL_ROOT'), '/').'/', '', $relativepathstring);
7803  $relativepathstring = preg_replace('/^\//', '', $relativepathstring);
7804  $relativepathstring = preg_replace('/^custom\//', '', $relativepathstring);
7805  //$tmpqueryarraywehave = explode('&', dol_string_nohtmltag($_SERVER['QUERY_STRING']));
7806  if (!empty($user->default_values[$relativepathstring]['focus']))
7807  {
7808  foreach ($user->default_values[$relativepathstring]['focus'] as $defkey => $defval)
7809  {
7810  $qualified = 0;
7811  if ($defkey != '_noquery_')
7812  {
7813  $tmpqueryarraytohave = explode('&', $defkey);
7814  $foundintru = 0;
7815  foreach ($tmpqueryarraytohave as $tmpquerytohave)
7816  {
7817  $tmpquerytohaveparam = explode('=', $tmpquerytohave);
7818  //print "console.log('".$tmpquerytohaveparam[0]." ".$tmpquerytohaveparam[1]." ".GETPOST($tmpquerytohaveparam[0])."');";
7819  if (!GETPOSTISSET($tmpquerytohaveparam[0]) || ($tmpquerytohaveparam[1] != GETPOST($tmpquerytohaveparam[0]))) $foundintru = 1;
7820  }
7821  if (!$foundintru) $qualified = 1;
7822  //var_dump($defkey.'-'.$qualified);
7823  } else $qualified = 1;
7824 
7825  if ($qualified)
7826  {
7827  foreach ($defval as $paramkey => $paramval)
7828  {
7829  // Set focus on field
7830  print 'jQuery("input[name=\''.$paramkey.'\']").focus();'."\n";
7831  print 'jQuery("textarea[name=\''.$paramkey.'\']").focus();'."\n";
7832  print 'jQuery("select[name=\''.$paramkey.'\']").focus();'."\n"; // Not really usefull, but we keep it in case of.
7833  }
7834  }
7835  }
7836  }
7837  if (!empty($user->default_values[$relativepathstring]['mandatory']))
7838  {
7839  foreach ($user->default_values[$relativepathstring]['mandatory'] as $defkey => $defval)
7840  {
7841  $qualified = 0;
7842  if ($defkey != '_noquery_')
7843  {
7844  $tmpqueryarraytohave = explode('&', $defkey);
7845  $foundintru = 0;
7846  foreach ($tmpqueryarraytohave as $tmpquerytohave)
7847  {
7848  $tmpquerytohaveparam = explode('=', $tmpquerytohave);
7849  //print "console.log('".$tmpquerytohaveparam[0]." ".$tmpquerytohaveparam[1]." ".GETPOST($tmpquerytohaveparam[0])."');";
7850  if (!GETPOSTISSET($tmpquerytohaveparam[0]) || ($tmpquerytohaveparam[1] != GETPOST($tmpquerytohaveparam[0]))) $foundintru = 1;
7851  }
7852  if (!$foundintru) $qualified = 1;
7853  //var_dump($defkey.'-'.$qualified);
7854  } else $qualified = 1;
7855 
7856  if ($qualified)
7857  {
7858  foreach ($defval as $paramkey => $paramval)
7859  {
7860  // Add property 'required' on input
7861  print 'jQuery("input[name=\''.$paramkey.'\']").prop(\'required\',true);'."\n";
7862  print 'jQuery("textarea[name=\''.$paramkey.'\']").prop(\'required\',true);'."\n";
7863  print 'jQuery("select[name=\''.$paramkey.'\']").prop(\'required\',true);'."\n"; // required on a select works only if key is "", this does not happen in Dolibarr
7864  }
7865  }
7866  }
7867  }
7868  }
7869 
7870  print '});'."\n";
7871 
7872  // End of tuning
7873  if (!empty($_SERVER['MAIN_SHOW_TUNING_INFO']) || !empty($conf->global->MAIN_SHOW_TUNING_INFO))
7874  {
7875  print "\n";
7876  print "/* JS CODE TO ENABLE to add memory info */\n";
7877  print 'window.console && console.log("';
7878  if (!empty($conf->global->MEMCACHED_SERVER)) print 'MEMCACHED_SERVER='.$conf->global->MEMCACHED_SERVER.' - ';
7879  print 'MAIN_OPTIMIZE_SPEED='.(isset($conf->global->MAIN_OPTIMIZE_SPEED) ? $conf->global->MAIN_OPTIMIZE_SPEED : 'off');
7880  if (!empty($micro_start_time)) // Works only if MAIN_SHOW_TUNING_INFO is defined at $_SERVER level. Not in global variable.
7881  {
7882  $micro_end_time = microtime(true);
7883  print ' - Build time: '.ceil(1000 * ($micro_end_time - $micro_start_time)).' ms';
7884  }
7885 
7886  if (function_exists("memory_get_usage")) {
7887  print ' - Mem: '.memory_get_usage(); // Do not use true here, it seems it takes the peak amount
7888  }
7889  if (function_exists("memory_get_peak_usage")) {
7890  print ' - Real mem peak: '.memory_get_peak_usage(true);
7891  }
7892  if (function_exists("zend_loader_file_encoded"))
7893  {
7894  print ' - Zend encoded file: '.(zend_loader_file_encoded() ? 'yes' : 'no');
7895  }
7896  print '");'."\n";
7897  }
7898 
7899  print "\n".'</script>'."\n";
7900 
7901  // Google Analytics
7902  // TODO Add a hook here
7903  if (!empty($conf->google->enabled) && !empty($conf->global->MAIN_GOOGLE_AN_ID))
7904  {
7905  $tmptagarray = explode(',', $conf->global->MAIN_GOOGLE_AN_ID);
7906  foreach ($tmptagarray as $tmptag) {
7907  print "\n";
7908  print "<!-- JS CODE TO ENABLE for google analtics tag -->\n";
7909  print "
7910  <!-- Global site tag (gtag.js) - Google Analytics -->
7911  <script async src=\"https://www.googletagmanager.com/gtag/js?id=".trim($tmptag)."\"></script>
7912  <script>
7913  window.dataLayer = window.dataLayer || [];
7914  function gtag(){dataLayer.push(arguments);}
7915  gtag('js', new Date());
7916 
7917  gtag('config', '".trim($tmptag)."');
7918  </script>";
7919  print "\n";
7920  }
7921  }
7922  }
7923 
7924  // Add Xdebug coverage of code
7925  if (defined('XDEBUGCOVERAGE'))
7926  {
7927  print_r(xdebug_get_code_coverage());
7928  }
7929 
7930  // Add DebugBar data
7931  if (!empty($user->rights->debugbar->read) && is_object($debugbar))
7932  {
7933  $debugbar['time']->stopMeasure('pageaftermaster');
7934  print '<!-- Output debugbar data -->'."\n";
7935  $renderer = $debugbar->getRenderer();
7936  print $debugbar->getRenderer()->render();
7937  } elseif (count($conf->logbuffer)) // If there is some logs in buffer to show
7938  {
7939  print "\n";
7940  print "<!-- Start of log output\n";
7941  //print '<div class="hidden">'."\n";
7942  foreach ($conf->logbuffer as $logline)
7943  {
7944  print $logline."<br>\n";
7945  }
7946  //print '</div>'."\n";
7947  print "End of log output -->\n";
7948  }
7949  }
7950 }
7951 
7961 function dolExplodeIntoArray($string, $delimiter = ';', $kv = '=')
7962 {
7963  if ($a = explode($delimiter, $string))
7964  {
7965  $ka = array();
7966  foreach ($a as $s) { // each part
7967  if ($s) {
7968  if ($pos = strpos($s, $kv)) { // key/value delimiter
7969  $ka[trim(substr($s, 0, $pos))] = trim(substr($s, $pos + strlen($kv)));
7970  } else { // key delimiter not found
7971  $ka[] = trim($s);
7972  }
7973  }
7974  }
7975  return $ka;
7976  }
7977  return array();
7978 }
7979 
7980 
7987 function dol_set_focus($selector)
7988 {
7989  print "\n".'<!-- Set focus onto a specific field -->'."\n";
7990  print '<script>jQuery(document).ready(function() { jQuery("'.dol_escape_js($selector).'").focus(); });</script>'."\n";
7991 }
7992 
7993 
8001 function dol_getmypid()
8002 {
8003  if (!function_exists('getmypid')) {
8004  return mt_rand(1, 32768);
8005  } else {
8006  return getmypid();
8007  }
8008 }
8009 
8010 
8027 function natural_search($fields, $value, $mode = 0, $nofirstand = 0)
8028 {
8029  global $db, $langs;
8030 
8031  $value = trim($value);
8032 
8033  if ($mode == 0)
8034  {
8035  $value = preg_replace('/\*/', '%', $value); // Replace * with %
8036  }
8037  if ($mode == 1)
8038  {
8039  $value = preg_replace('/([<>=]+)\s+([0-9'.preg_quote($langs->trans("DecimalSeparator"), '/').'\-])/', '\1\2', $value); // Clean string '< 10' into '<10' so we can the explode on space to get all tests to do
8040  }
8041 
8042  $value = preg_replace('/\s*\|\s*/', '|', $value);
8043 
8044  $crits = explode(' ', $value);
8045  $res = '';
8046  if (!is_array($fields)) $fields = array($fields);
8047 
8048  $j = 0;
8049  foreach ($crits as $crit)
8050  {
8051  $crit = trim($crit);
8052  $i = 0; $i2 = 0;
8053  $newres = '';
8054  foreach ($fields as $field)
8055  {
8056  if ($mode == 1)
8057  {
8058  $operator = '=';
8059  $newcrit = preg_replace('/([<>=]+)/', '', $crit);
8060 
8061  $reg = array();
8062  preg_match('/([<>=]+)/', $crit, $reg);
8063  if ($reg[1])
8064  {
8065  $operator = $reg[1];
8066  }
8067  if ($newcrit != '')
8068  {
8069  $numnewcrit = price2num($newcrit);
8070  if (is_numeric($numnewcrit))
8071  {
8072  $newres .= ($i2 > 0 ? ' OR ' : '').$field.' '.$operator.' '.$db->sanitize($numnewcrit); // should be a numeric
8073  } else {
8074  $newres .= ($i2 > 0 ? ' OR ' : '').'1 = 2'; // force false
8075  }
8076  $i2++; // a criteria was added to string
8077  }
8078  } elseif ($mode == 2 || $mode == -2)
8079  {
8080  $crit = preg_replace('/[^0-9,]/', '', $crit); // ID are always integer
8081  $newres .= ($i2 > 0 ? ' OR ' : '').$field." ".($mode == -2 ? 'NOT ' : '');
8082  $newres .= $crit ? "IN (".$db->sanitize($db->escape($crit)).")" : "IN (0)";
8083  if ($mode == -2) $newres .= ' OR '.$field.' IS NULL';
8084  $i2++; // a criteria was added to string
8085  } elseif ($mode == 3 || $mode == -3)
8086  {
8087  $tmparray = explode(',', $crit);
8088  if (count($tmparray))
8089  {
8090  $listofcodes = '';
8091  foreach ($tmparray as $val)
8092  {
8093  $val = trim($val);
8094  if ($val)
8095  {
8096  $listofcodes .= ($listofcodes ? ',' : '');
8097  $listofcodes .= "'".$db->escape($val)."'";
8098  }
8099  }
8100  $newres .= ($i2 > 0 ? ' OR ' : '').$field." ".($mode == -3 ? 'NOT ' : '')."IN (".$db->sanitize($listofcodes, 1).")";
8101  $i2++; // a criteria was added to string
8102  }
8103  if ($mode == -3) $newres .= ' OR '.$field.' IS NULL';
8104  } elseif ($mode == 4)
8105  {
8106  $tmparray = explode(',', $crit);
8107  if (count($tmparray))
8108  {
8109  $listofcodes = '';
8110  foreach ($tmparray as $val)
8111  {
8112  $val = trim($val);
8113  if ($val)
8114  {
8115  $newres .= ($i2 > 0 ? ' OR (' : '(').$field.' LIKE \''.$db->escape($val).',%\'';
8116  $newres .= ' OR '.$field.' = \''.$db->escape($val).'\'';
8117  $newres .= ' OR '.$field.' LIKE \'%,'.$db->escape($val).'\'';
8118  $newres .= ' OR '.$field.' LIKE \'%,'.$db->escape($val).',%\'';
8119  $newres .= ')';
8120  $i2++;
8121  }
8122  }
8123  }
8124  } else // $mode=0
8125  {
8126  $tmpcrits = explode('|', $crit);
8127  $i3 = 0;
8128  foreach ($tmpcrits as $tmpcrit)
8129  {
8130  if ($tmpcrit !== '0' && empty($tmpcrit)) continue;
8131 
8132  $newres .= (($i2 > 0 || $i3 > 0) ? ' OR ' : '');
8133 
8134  if (preg_match('/\.(id|rowid)$/', $field)) // Special case for rowid that is sometimes a ref so used as a search field
8135  {
8136  $newres .= $field." = ".(is_numeric(trim($tmpcrit)) ?trim($tmpcrit) : '0');
8137  } else {
8138  $newres .= $field." LIKE '";
8139 
8140  $tmpcrit = trim($tmpcrit);
8141  $tmpcrit2 = $tmpcrit;
8142  $tmpbefore = '%'; $tmpafter = '%';
8143  if (preg_match('/^[\^\$]/', $tmpcrit))
8144  {
8145  $tmpbefore = '';
8146  $tmpcrit2 = preg_replace('/^[\^\$]/', '', $tmpcrit2);
8147  }
8148  if (preg_match('/[\^\$]$/', $tmpcrit))
8149  {
8150  $tmpafter = '';
8151  $tmpcrit2 = preg_replace('/[\^\$]$/', '', $tmpcrit2);
8152  }
8153  $newres .= $tmpbefore;
8154  $newres .= $db->escape($tmpcrit2);
8155  $newres .= $tmpafter;
8156  $newres .= "'";
8157  if ($tmpcrit2 == '')
8158  {
8159  $newres .= ' OR '.$field." IS NULL";
8160  }
8161  }
8162 
8163  $i3++;
8164  }
8165  $i2++; // a criteria was added to string
8166  }
8167  $i++;
8168  }
8169  if ($newres) $res = $res.($res ? ' AND ' : '').($i2 > 1 ? '(' : '').$newres.($i2 > 1 ? ')' : '');
8170  $j++;
8171  }
8172  $res = ($nofirstand ? "" : " AND ")."(".$res.")";
8173  //print 'xx'.$res.'yy';
8174  return $res;
8175 }
8176 
8183 function showDirectDownloadLink($object)
8184 {
8185  global $conf, $langs;
8186 
8187  $out = '';
8188  $url = $object->getLastMainDocLink($object->element);
8189 
8190  if ($url)
8191  {
8192  $out .= img_picto('', 'globe').' '.$langs->trans("DirectDownloadLink").'<br>';
8193  $out .= '<input type="text" id="directdownloadlink" class="quatrevingtpercent" value="'.$url.'">';
8194  $out .= ajax_autoselect("directdownloadlink", 0);
8195  }
8196  return $out;
8197 }
8198 
8207 function getImageFileNameForSize($file, $extName, $extImgTarget = '')
8208 {
8209  $dirName = dirname($file);
8210  if ($dirName == '.') $dirName = '';
8211 
8212  $fileName = preg_replace('/(\.gif|\.jpeg|\.jpg|\.png|\.bmp|\.webp)$/i', '', $file); // We remove extension, whatever is its case
8213  $fileName = basename($fileName);
8214 
8215  if (empty($extImgTarget)) $extImgTarget = (preg_match('/\.jpg$/i', $file) ? '.jpg' : '');
8216  if (empty($extImgTarget)) $extImgTarget = (preg_match('/\.jpeg$/i', $file) ? '.jpeg' : '');
8217  if (empty($extImgTarget)) $extImgTarget = (preg_match('/\.gif$/i', $file) ? '.gif' : '');
8218  if (empty($extImgTarget)) $extImgTarget = (preg_match('/\.png$/i', $file) ? '.png' : '');
8219  if (empty($extImgTarget)) $extImgTarget = (preg_match('/\.bmp$/i', $file) ? '.bmp' : '');
8220  if (empty($extImgTarget)) $extImgTarget = (preg_match('/\.webp$/i', $file) ? '.webp' : '');
8221 
8222  if (!$extImgTarget) return $file;
8223 
8224  $subdir = '';
8225  if ($extName) $subdir = 'thumbs/';
8226 
8227  return ($dirName ? $dirName.'/' : '').$subdir.$fileName.$extName.$extImgTarget; // New filename for thumb
8228 }
8229 
8230 
8240 function getAdvancedPreviewUrl($modulepart, $relativepath, $alldata = 0, $param = '')
8241 {
8242  global $conf, $langs;
8243 
8244  if (empty($conf->use_javascript_ajax)) return '';
8245 
8246  $isAllowedForPreview = dolIsAllowedForPreview($relativepath);
8247 
8248  if ($alldata == 1)
8249  {
8250  if ($isAllowedForPreview) return array('target'=>'_blank', 'css'=>'documentpreview', 'url'=>DOL_URL_ROOT.'/document.php?modulepart='.$modulepart.'&attachment=0&file='.urlencode($relativepath).($param ? '&'.$param : ''), 'mime'=>dol_mimetype($relativepath));
8251  else return array();
8252  }
8253 
8254  // old behavior, return a string
8255  if ($isAllowedForPreview) return 'javascript:document_preview(\''.dol_escape_js(DOL_URL_ROOT.'/document.php?modulepart='.$modulepart.'&attachment=0&file='.urlencode($relativepath).($param ? '&'.$param : '')).'\', \''.dol_mimetype($relativepath).'\', \''.dol_escape_js($langs->trans('Preview')).'\')';
8256  else return '';
8257 }
8258 
8259 
8267 function ajax_autoselect($htmlname, $addlink = '')
8268 {
8269  global $langs;
8270  $out = '<script>
8271  jQuery(document).ready(function () {
8272  jQuery("'.((strpos($htmlname, '.') === 0 ? '' : '#').$htmlname).'").click(function() { jQuery(this).select(); } );
8273  });
8274  </script>';
8275  if ($addlink) $out .= ' <a href="'.$addlink.'" target="_blank">'.$langs->trans("Link").'</a>';
8276  return $out;
8277 }
8278 
8286 function dolIsAllowedForPreview($file)
8287 {
8288  global $conf;
8289 
8290  // Check .noexe extension in filename
8291  if (preg_match('/\.noexe$/i', $file)) return 0;
8292 
8293  // Check mime types
8294  $mime_preview = array('bmp', 'jpeg', 'png', 'gif', 'tiff', 'pdf', 'plain', 'css', 'webp');
8295  if (!empty($conf->global->MAIN_ALLOW_SVG_FILES_AS_IMAGES)) $mime_preview[] = 'svg+xml';
8296  //$mime_preview[]='vnd.oasis.opendocument.presentation';
8297  //$mime_preview[]='archive';
8298  $num_mime = array_search(dol_mimetype($file, '', 1), $mime_preview);
8299  if ($num_mime !== false) return 1;
8300 
8301  // By default, not allowed for preview
8302  return 0;
8303 }
8304 
8305 
8315 function dol_mimetype($file, $default = 'application/octet-stream', $mode = 0)
8316 {
8317  $mime = $default;
8318  $imgmime = 'other.png';
8319  $famime = 'file-o';
8320  $srclang = '';
8321 
8322  $tmpfile = preg_replace('/\.noexe$/', '', $file);
8323 
8324  // Plain text files
8325  if (preg_match('/\.txt$/i', $tmpfile)) { $mime = 'text/plain'; $imgmime = 'text.png'; $famime = 'file-text-o'; }
8326  if (preg_match('/\.rtx$/i', $tmpfile)) { $mime = 'text/richtext'; $imgmime = 'text.png'; $famime = 'file-text-o'; }
8327  if (preg_match('/\.csv$/i', $tmpfile)) { $mime = 'text/csv'; $imgmime = 'text.png'; $famime = 'file-text-o'; }
8328  if (preg_match('/\.tsv$/i', $tmpfile)) { $mime = 'text/tab-separated-values'; $imgmime = 'text.png'; $famime = 'file-text-o'; }
8329  if (preg_match('/\.(cf|conf|log)$/i', $tmpfile)) { $mime = 'text/plain'; $imgmime = 'text.png'; $famime = 'file-text-o'; }
8330  if (preg_match('/\.ini$/i', $tmpfile)) { $mime = 'text/plain'; $imgmime = 'text.png'; $srclang = 'ini'; $famime = 'file-text-o'; }
8331  if (preg_match('/\.md$/i', $tmpfile)) { $mime = 'text/plain'; $imgmime = 'text.png'; $srclang = 'md'; $famime = 'file-text-o'; }
8332  if (preg_match('/\.css$/i', $tmpfile)) { $mime = 'text/css'; $imgmime = 'css.png'; $srclang = 'css'; $famime = 'file-text-o'; }
8333  if (preg_match('/\.lang$/i', $tmpfile)) { $mime = 'text/plain'; $imgmime = 'text.png'; $srclang = 'lang'; $famime = 'file-text-o'; }
8334  // Certificate files
8335  if (preg_match('/\.(crt|cer|key|pub)$/i', $tmpfile)) { $mime = 'text/plain'; $imgmime = 'text.png'; $famime = 'file-text-o'; }
8336  // XML based (HTML/XML/XAML)
8337  if (preg_match('/\.(html|htm|shtml)$/i', $tmpfile)) { $mime = 'text/html'; $imgmime = 'html.png'; $srclang = 'html'; $famime = 'file-text-o'; }
8338  if (preg_match('/\.(xml|xhtml)$/i', $tmpfile)) { $mime = 'text/xml'; $imgmime = 'other.png'; $srclang = 'xml'; $famime = 'file-text-o'; }
8339  if (preg_match('/\.xaml$/i', $tmpfile)) { $mime = 'text/xml'; $imgmime = 'other.png'; $srclang = 'xaml'; $famime = 'file-text-o'; }
8340  // Languages
8341  if (preg_match('/\.bas$/i', $tmpfile)) { $mime = 'text/plain'; $imgmime = 'text.png'; $srclang = 'bas'; $famime = 'file-code-o'; }
8342  if (preg_match('/\.(c)$/i', $tmpfile)) { $mime = 'text/plain'; $imgmime = 'text.png'; $srclang = 'c'; $famime = 'file-code-o'; }
8343  if (preg_match('/\.(cpp)$/i', $tmpfile)) { $mime = 'text/plain'; $imgmime = 'text.png'; $srclang = 'cpp'; $famime = 'file-code-o'; }
8344  if (preg_match('/\.cs$/i', $tmpfile)) { $mime = 'text/plain'; $imgmime = 'text.png'; $srclang = 'cs'; $famime = 'file-code-o'; }
8345  if (preg_match('/\.(h)$/i', $tmpfile)) { $mime = 'text/plain'; $imgmime = 'text.png'; $srclang = 'h'; $famime = 'file-code-o'; }
8346  if (preg_match('/\.(java|jsp)$/i', $tmpfile)) { $mime = 'text/plain'; $imgmime = 'text.png'; $srclang = 'java'; $famime = 'file-code-o'; }
8347  if (preg_match('/\.php([0-9]{1})?$/i', $tmpfile)) { $mime = 'text/plain'; $imgmime = 'php.png'; $srclang = 'php'; $famime = 'file-code-o'; }
8348  if (preg_match('/\.phtml$/i', $tmpfile)) { $mime = 'text/plain'; $imgmime = 'php.png'; $srclang = 'php'; $famime = 'file-code-o'; }
8349  if (preg_match('/\.(pl|pm)$/i', $tmpfile)) { $mime = 'text/plain'; $imgmime = 'pl.png'; $srclang = 'perl'; $famime = 'file-code-o'; }
8350  if (preg_match('/\.sql$/i', $tmpfile)) { $mime = 'text/plain'; $imgmime = 'text.png'; $srclang = 'sql'; $famime = 'file-code-o'; }
8351  if (preg_match('/\.js$/i', $tmpfile)) { $mime = 'text/x-javascript'; $imgmime = 'jscript.png'; $srclang = 'js'; $famime = 'file-code-o'; }
8352  // Open office
8353  if (preg_match('/\.odp$/i', $tmpfile)) { $mime = 'application/vnd.oasis.opendocument.presentation'; $imgmime = 'ooffice.png'; $famime = 'file-powerpoint-o'; }
8354  if (preg_match('/\.ods$/i', $tmpfile)) { $mime = 'application/vnd.oasis.opendocument.spreadsheet'; $imgmime = 'ooffice.png'; $famime = 'file-excel-o'; }
8355  if (preg_match('/\.odt$/i', $tmpfile)) { $mime = 'application/vnd.oasis.opendocument.text'; $imgmime = 'ooffice.png'; $famime = 'file-word-o'; }
8356  // MS Office
8357  if (preg_match('/\.mdb$/i', $tmpfile)) { $mime = 'application/msaccess'; $imgmime = 'mdb.png'; $famime = 'file-o'; }
8358  if (preg_match('/\.doc(x|m)?$/i', $tmpfile)) { $mime = 'application/msword'; $imgmime = 'doc.png'; $famime = 'file-word-o'; }
8359  if (preg_match('/\.dot(x|m)?$/i', $tmpfile)) { $mime = 'application/msword'; $imgmime = 'doc.png'; $famime = 'file-word-o'; }
8360  if (preg_match('/\.xlt(x)?$/i', $tmpfile)) { $mime = 'application/vnd.ms-excel'; $imgmime = 'xls.png'; $famime = 'file-excel-o'; }
8361  if (preg_match('/\.xla(m)?$/i', $tmpfile)) { $mime = 'application/vnd.ms-excel'; $imgmime = 'xls.png'; $famime = 'file-excel-o'; }
8362  if (preg_match('/\.xls$/i', $tmpfile)) { $mime = 'application/vnd.ms-excel'; $imgmime = 'xls.png'; $famime = 'file-excel-o'; }
8363  if (preg_match('/\.xls(b|m|x)$/i', $tmpfile)) { $mime = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'; $imgmime = 'xls.png'; $famime = 'file-excel-o'; }
8364  if (preg_match('/\.pps(m|x)?$/i', $tmpfile)) { $mime = 'application/vnd.ms-powerpoint'; $imgmime = 'ppt.png'; $famime = 'file-powerpoint-o'; }
8365  if (preg_match('/\.ppt(m|x)?$/i', $tmpfile)) { $mime = 'application/x-mspowerpoint'; $imgmime = 'ppt.png'; $famime = 'file-powerpoint-o'; }
8366  // Other
8367  if (preg_match('/\.pdf$/i', $tmpfile)) { $mime = 'application/pdf'; $imgmime = 'pdf.png'; $famime = 'file-pdf-o'; }
8368  // Scripts
8369  if (preg_match('/\.bat$/i', $tmpfile)) { $mime = 'text/x-bat'; $imgmime = 'script.png'; $srclang = 'dos'; $famime = 'file-code-o'; }
8370  if (preg_match('/\.sh$/i', $tmpfile)) { $mime = 'text/x-sh'; $imgmime = 'script.png'; $srclang = 'bash'; $famime = 'file-code-o'; }
8371  if (preg_match('/\.ksh$/i', $tmpfile)) { $mime = 'text/x-ksh'; $imgmime = 'script.png'; $srclang = 'bash'; $famime = 'file-code-o'; }
8372  if (preg_match('/\.bash$/i', $tmpfile)) { $mime = 'text/x-bash'; $imgmime = 'script.png'; $srclang = 'bash'; $famime = 'file-code-o'; }
8373  // Images
8374  if (preg_match('/\.ico$/i', $tmpfile)) { $mime = 'image/x-icon'; $imgmime = 'image.png'; $famime = 'file-image-o'; }
8375  if (preg_match('/\.(jpg|jpeg)$/i', $tmpfile)) { $mime = 'image/jpeg'; $imgmime = 'image.png'; $famime = 'file-image-o'; }
8376  if (preg_match('/\.png$/i', $tmpfile)) { $mime = 'image/png'; $imgmime = 'image.png'; $famime = 'file-image-o'; }
8377  if (preg_match('/\.gif$/i', $tmpfile)) { $mime = 'image/gif'; $imgmime = 'image.png'; $famime = 'file-image-o'; }
8378  if (preg_match('/\.bmp$/i', $tmpfile)) { $mime = 'image/bmp'; $imgmime = 'image.png'; $famime = 'file-image-o'; }
8379  if (preg_match('/\.(tif|tiff)$/i', $tmpfile)) { $mime = 'image/tiff'; $imgmime = 'image.png'; $famime = 'file-image-o'; }
8380  if (preg_match('/\.svg$/i', $tmpfile)) { $mime = 'image/svg+xml'; $imgmime = 'image.png'; $famime = 'file-image-o'; }
8381  if (preg_match('/\.webp$/i', $tmpfile)) { $mime = 'image/webp'; $imgmime = 'image.png'; $famime = 'file-image-o'; }
8382  // Calendar
8383  if (preg_match('/\.vcs$/i', $tmpfile)) { $mime = 'text/calendar'; $imgmime = 'other.png'; $famime = 'file-text-o'; }
8384  if (preg_match('/\.ics$/i', $tmpfile)) { $mime = 'text/calendar'; $imgmime = 'other.png'; $famime = 'file-text-o'; }
8385  // Other
8386  if (preg_match('/\.torrent$/i', $tmpfile)) { $mime = 'application/x-bittorrent'; $imgmime = 'other.png'; $famime = 'file-o'; }
8387  // Audio
8388  if (preg_match('/\.(mp3|ogg|au|wav|wma|mid)$/i', $tmpfile)) { $mime = 'audio'; $imgmime = 'audio.png'; $famime = 'file-audio-o'; }
8389  // Video
8390  if (preg_match('/\.mp4$/i', $tmpfile)) { $mime = 'video/mp4'; $imgmime = 'video.png'; $famime = 'file-video-o'; }
8391  if (preg_match('/\.ogv$/i', $tmpfile)) { $mime = 'video/ogg'; $imgmime = 'video.png'; $famime = 'file-video-o'; }
8392  if (preg_match('/\.webm$/i', $tmpfile)) { $mime = 'video/webm'; $imgmime = 'video.png'; $famime = 'file-video-o'; }
8393  if (preg_match('/\.avi$/i', $tmpfile)) { $mime = 'video/x-msvideo'; $imgmime = 'video.png'; $famime = 'file-video-o'; }
8394  if (preg_match('/\.divx$/i', $tmpfile)) { $mime = 'video/divx'; $imgmime = 'video.png'; $famime = 'file-video-o'; }
8395  if (preg_match('/\.xvid$/i', $tmpfile)) { $mime = 'video/xvid'; $imgmime = 'video.png'; $famime = 'file-video-o'; }
8396  if (preg_match('/\.(wmv|mpg|mpeg)$/i', $tmpfile)) { $mime = 'video'; $imgmime = 'video.png'; $famime = 'file-video-o'; }
8397  // Archive
8398  if (preg_match('/\.(zip|rar|gz|tgz|z|cab|bz2|7z|tar|lzh)$/i', $tmpfile)) { $mime = 'archive'; $imgmime = 'archive.png'; $famime = 'file-archive-o'; } // application/xxx where zzz is zip, ...
8399  // Exe
8400  if (preg_match('/\.(exe|com)$/i', $tmpfile)) { $mime = 'application/octet-stream'; $imgmime = 'other.png'; $famime = 'file-o'; }
8401  // Lib
8402  if (preg_match('/\.(dll|lib|o|so|a)$/i', $tmpfile)) { $mime = 'library'; $imgmime = 'library.png'; $famime = 'file-o'; }
8403  // Err
8404  if (preg_match('/\.err$/i', $tmpfile)) { $mime = 'error'; $imgmime = 'error.png'; $famime = 'file-text-o'; }
8405 
8406  // Return string
8407  if ($mode == 1)
8408  {
8409  $tmp = explode('/', $mime);
8410  return (!empty($tmp[1]) ? $tmp[1] : $tmp[0]);
8411  }
8412  if ($mode == 2)
8413  {
8414  return $imgmime;
8415  }
8416  if ($mode == 3)
8417  {
8418  return $srclang;
8419  }
8420  if ($mode == 4)
8421  {
8422  return $famime;
8423  }
8424  return $mime;
8425 }
8426 
8437 function getDictvalue($tablename, $field, $id, $checkentity = false, $rowidfield = 'rowid')
8438 {
8439  global $dictvalues, $db, $langs;
8440 
8441  if (!isset($dictvalues[$tablename]))
8442  {
8443  $dictvalues[$tablename] = array();
8444  $sql = 'SELECT * FROM '.$tablename.' WHERE 1'; // Here select * is allowed as it is generic code and we don't have list of fields
8445  if ($checkentity) $sql .= ' AND entity IN (0,'.getEntity($tablename).')';
8446 
8447  $resql = $db->query($sql);
8448  if ($resql)
8449  {
8450  while ($obj = $db->fetch_object($resql))
8451  {
8452  $dictvalues[$tablename][$obj->{$rowidfield}] = $obj;
8453  }
8454  } else {
8455  dol_print_error($db);
8456  }
8457  }
8458 
8459  if (!empty($dictvalues[$tablename][$id])) return $dictvalues[$tablename][$id]->{$field}; // Found
8460  else // Not found
8461  {
8462  if ($id > 0) return $id;
8463  return '';
8464  }
8465 }
8466 
8473 function colorIsLight($stringcolor)
8474 {
8475  $stringcolor = str_replace('#', '', $stringcolor);
8476  $res = -1;
8477  if (!empty($stringcolor))
8478  {
8479  $res = 0;
8480  $tmp = explode(',', $stringcolor);
8481  if (count($tmp) > 1) // This is a comma RGB ('255','255','255')
8482  {
8483  $r = $tmp[0];
8484  $g = $tmp[1];
8485  $b = $tmp[2];
8486  } else {
8487  $hexr = $stringcolor[0].$stringcolor[1];
8488  $hexg = $stringcolor[2].$stringcolor[3];
8489  $hexb = $stringcolor[4].$stringcolor[5];
8490  $r = hexdec($hexr);
8491  $g = hexdec($hexg);
8492  $b = hexdec($hexb);
8493  }
8494  $bright = (max($r, $g, $b) + min($r, $g, $b)) / 510.0; // HSL algorithm
8495  if ($bright > 0.6) $res = 1;
8496  }
8497  return $res;
8498 }
8499 
8508 function isVisibleToUserType($type_user, &$menuentry, &$listofmodulesforexternal)
8509 {
8510  global $conf;
8511 
8512  //print 'type_user='.$type_user.' module='.$menuentry['module'].' enabled='.$menuentry['enabled'].' perms='.$menuentry['perms'];
8513  //print 'ok='.in_array($menuentry['module'], $listofmodulesforexternal);
8514  if (empty($menuentry['enabled'])) return 0; // Entry disabled by condition
8515  if ($type_user && $menuentry['module'])
8516  {
8517  $tmploops = explode('|', $menuentry['module']);
8518  $found = 0;
8519  foreach ($tmploops as $tmploop)
8520  {
8521  if (in_array($tmploop, $listofmodulesforexternal)) {
8522  $found++; break;
8523  }
8524  }
8525  if (!$found) return 0; // Entry is for menus all excluded to external users
8526  }
8527  if (!$menuentry['perms'] && $type_user) return 0; // No permissions and user is external
8528  if (!$menuentry['perms'] && !empty($conf->global->MAIN_MENU_HIDE_UNAUTHORIZED)) return 0; // No permissions and option to hide when not allowed, even for internal user, is on
8529  if (!$menuentry['perms']) return 2; // No permissions and user is external
8530  return 1;
8531 }
8532 
8540 function roundUpToNextMultiple($n, $x = 5)
8541 {
8542  return (ceil($n) % $x === 0) ? ceil($n) : round(($n + $x / 2) / $x) * $x;
8543 }
8544 
8556 function dolGetBadge($label, $html = '', $type = 'primary', $mode = '', $url = '', $params = array())
8557 {
8558  $attr = array(
8559  'class'=>'badge '.(!empty($mode) ? ' badge-'.$mode : '').(!empty($type) ? ' badge-'.$type : '').(empty($params['css']) ? '' : ' '.$params['css'])
8560  );
8561 
8562  if (empty($html)) {
8563  $html = $label;
8564  }
8565 
8566  if (!empty($url)) {
8567  $attr['href'] = $url;
8568  }
8569 
8570  if ($mode === 'dot') {
8571  $attr['class'] .= ' classfortooltip';
8572  $attr['title'] = $html;
8573  $attr['aria-label'] = $label;
8574  $html = '';
8575  }
8576 
8577  // Override attr
8578  if (!empty($params['attr']) && is_array($params['attr'])) {
8579  foreach ($params['attr']as $key => $value) {
8580  if ($key == 'class') {
8581  $attr['class'] .= ' '.$value;
8582  } elseif ($key == 'classOverride') {
8583  $attr['class'] = $value;
8584  } else {
8585  $attr[$key] = $value;
8586  }
8587  }
8588  }
8589 
8590  // TODO: add hook
8591 
8592  // escape all attribute
8593  $attr = array_map('dol_escape_htmltag', $attr);
8594 
8595  $TCompiledAttr = array();
8596  foreach ($attr as $key => $value) {
8597  $TCompiledAttr[] = $key.'="'.$value.'"';
8598  }
8599 
8600  $compiledAttributes = !empty($TCompiledAttr) ?implode(' ', $TCompiledAttr) : '';
8601 
8602  $tag = !empty($url) ? 'a' : 'span';
8603 
8604  return '<'.$tag.' '.$compiledAttributes.'>'.$html.'</'.$tag.'>';
8605 }
8606 
8607 
8620 function dolGetStatus($statusLabel = '', $statusLabelShort = '', $html = '', $statusType = 'status0', $displayMode = 0, $url = '', $params = array())
8621 {
8622  global $conf;
8623 
8624  $return = '';
8625  $dolGetBadgeParams = array();
8626 
8627  if (!empty($params['badgeParams'])) {
8628  $dolGetBadgeParams = $params['badgeParams'];
8629  }
8630 
8631  // TODO : add a hook
8632  if ($displayMode == 0) {
8633  $return = !empty($html) ? $html : (empty($conf->dol_optimize_smallscreen) ? $statusLabel : (empty($statusLabelShort) ? $statusLabel : $statusLabelShort));
8634  } elseif ($displayMode == 1) {
8635  $return = !empty($html) ? $html : (empty($statusLabelShort) ? $statusLabel : $statusLabelShort);
8636  } // Use status with images (for backward compatibility)
8637  elseif (!empty($conf->global->MAIN_STATUS_USES_IMAGES)) {
8638  $return = '';
8639  $htmlLabel = (in_array($displayMode, array(1, 2, 5)) ? '<span class="hideonsmartphone">' : '').(!empty($html) ? $html : $statusLabel).(in_array($displayMode, array(1, 2, 5)) ? '</span>' : '');
8640  $htmlLabelShort = (in_array($displayMode, array(1, 2, 5)) ? '<span class="hideonsmartphone">' : '').(!empty($html) ? $html : (!empty($statusLabelShort) ? $statusLabelShort : $statusLabel)).(in_array($displayMode, array(1, 2, 5)) ? '</span>' : '');
8641 
8642  // For small screen, we always use the short label instead of long label.
8643  if (!empty($conf->dol_optimize_smallscreen))
8644  {
8645  if ($displayMode == 0) $displayMode = 1;
8646  elseif ($displayMode == 4) $displayMode = 2;
8647  elseif ($displayMode == 6) $displayMode = 5;
8648  }
8649 
8650  // For backward compatibility. Image's filename are still in French, so we use this array to convert
8651  $statusImg = array(
8652  'status0' => 'statut0',
8653  'status1' => 'statut1',
8654  'status2' => 'statut2',
8655  'status3' => 'statut3',
8656  'status4' => 'statut4',
8657  'status5' => 'statut5',
8658  'status6' => 'statut6',
8659  'status7' => 'statut7',
8660  'status8' => 'statut8',
8661  'status9' => 'statut9'
8662  );
8663 
8664  if (!empty($statusImg[$statusType])) {
8665  $htmlImg = img_picto($statusLabel, $statusImg[$statusType]);
8666  } else {
8667  $htmlImg = img_picto($statusLabel, $statusType);
8668  }
8669 
8670  if ($displayMode === 2) {
8671  $return = $htmlImg.' '.$htmlLabelShort;
8672  } elseif ($displayMode === 3) {
8673  $return = $htmlImg;
8674  } elseif ($displayMode === 4) {
8675  $return = $htmlImg.' '.$htmlLabel;
8676  } elseif ($displayMode === 5) {
8677  $return = $htmlLabelShort.' '.$htmlImg;
8678  } else { // $displayMode >= 6
8679  $return = $htmlLabel.' '.$htmlImg;
8680  }
8681  } // Use new badge
8682  elseif (empty($conf->global->MAIN_STATUS_USES_IMAGES) && !empty($displayMode)) {
8683  $statusLabelShort = (empty($statusLabelShort) ? $statusLabel : $statusLabelShort);
8684 
8685  $dolGetBadgeParams['attr']['class'] = 'badge-status';
8686  $dolGetBadgeParams['attr']['title'] = empty($params['tooltip']) ? $statusLabel : ($params['tooltip'] != 'no' ? $params['tooltip'] : '');
8687 
8688  if ($displayMode == 3) {
8689  $return = dolGetBadge((empty($conf->dol_optimize_smallscreen) ? $statusLabel : (empty($statusLabelShort) ? $statusLabel : $statusLabelShort)), '', $statusType, 'dot', $url, $dolGetBadgeParams);
8690  } elseif ($displayMode === 5) {
8691  $return = dolGetBadge($statusLabelShort, $html, $statusType, '', $url, $dolGetBadgeParams);
8692  } else {
8693  $return = dolGetBadge((empty($conf->dol_optimize_smallscreen) ? $statusLabel : (empty($statusLabelShort) ? $statusLabel : $statusLabelShort)), $html, $statusType, '', $url, $dolGetBadgeParams);
8694  }
8695  }
8696 
8697  return $return;
8698 }
8699 
8700 
8713 function dolGetButtonAction($label, $html = '', $actionType = 'default', $url = '', $id = '', $userRight = 1, $params = array())
8714 {
8715  $class = 'butAction';
8716  if ($actionType == 'danger' || $actionType == 'delete') {
8717  $class = 'butActionDelete';
8718  }
8719 
8720  $attr = array(
8721  'class' => $class
8722  ,'href' => empty($url) ? '' : $url
8723  );
8724 
8725  if (empty($html)) {
8726  $html = $label;
8727  } else {
8728  $attr['aria-label'] = $label;
8729  }
8730 
8731  if (empty($userRight)) {
8732  $attr['class'] = 'butActionRefused';
8733  $attr['href'] = '';
8734  }
8735 
8736  if (!empty($id)) {
8737  $attr['id'] = $id;
8738  }
8739 
8740  // Override attr
8741  if (!empty($params['attr']) && is_array($params['attr'])) {
8742  foreach ($params['attr'] as $key => $value) {
8743  if ($key == 'class') {
8744  $attr['class'] .= ' '.$value;
8745  } elseif ($key == 'classOverride') {
8746  $attr['class'] = $value;
8747  } else {
8748  $attr[$key] = $value;
8749  }
8750  }
8751  }
8752 
8753  if (isset($attr['href']) && empty($attr['href'])) {
8754  unset($attr['href']);
8755  }
8756 
8757  // TODO : add a hook
8758 
8759  // escape all attribute
8760  $attr = array_map('dol_escape_htmltag', $attr);
8761 
8762  $TCompiledAttr = array();
8763  foreach ($attr as $key => $value) {
8764  $TCompiledAttr[] = $key.'="'.$value.'"';
8765  }
8766 
8767  $compiledAttributes = !empty($TCompiledAttr) ?implode(' ', $TCompiledAttr) : '';
8768 
8769  $tag = !empty($attr['href']) ? 'a' : 'span';
8770 
8771  return '<div class="inline-block divButAction"><'.$tag.' '.$compiledAttributes.'>'.$html.'</'.$tag.'></div>';
8772 }
8773 
8786 function dolGetButtonTitle($label, $helpText = '', $iconClass = 'fa fa-file', $url = '', $id = '', $status = 1, $params = array())
8787 {
8788  global $langs, $conf, $user;
8789 
8790  // Actually this conf is used in css too for external module compatibility and smooth transition to this function
8791  if (!empty($conf->global->MAIN_BUTTON_HIDE_UNAUTHORIZED) && (!$user->admin) && $status <= 0) {
8792  return '';
8793  }
8794 
8795  $class = 'btnTitle';
8796  if (in_array($iconClass, array('fa fa-plus-circle', 'fa fa-comment-dots'))) $class .= ' btnTitlePlus';
8797  $useclassfortooltip = 1;
8798 
8799  if (!empty($params['morecss'])) $class .= ' '.$params['morecss'];
8800 
8801  $attr = array(
8802  'class' => $class,
8803  'href' => empty($url) ? '' : $url
8804  );
8805 
8806  if (!empty($helpText)) {
8807  $attr['title'] = dol_escape_htmltag($helpText);
8808  } elseif (empty($attr['title']) && $label) {
8809  $attr['title'] = $label;
8810  $useclassfortooltip = 0;
8811  }
8812 
8813  if ($status <= 0) {
8814  $attr['class'] .= ' refused';
8815 
8816  $attr['href'] = '';
8817 
8818  if ($status == -1) { // disable
8819  $attr['title'] = dol_escape_htmltag($langs->transnoentitiesnoconv("FeatureDisabled"));
8820  } elseif ($status == 0) { // Not enough permissions
8821  $attr['title'] = dol_escape_htmltag($langs->transnoentitiesnoconv("NotEnoughPermissions"));
8822  }
8823  }
8824 
8825  if (!empty($attr['title']) && $useclassfortooltip) {
8826  $attr['class'] .= ' classfortooltip';
8827  }
8828 
8829  if (!empty($id)) {
8830  $attr['id'] = $id;
8831  }
8832 
8833  // Override attr
8834  if (!empty($params['attr']) && is_array($params['attr'])) {
8835  foreach ($params['attr'] as $key => $value) {
8836  if ($key == 'class') {
8837  $attr['class'] .= ' '.$value;
8838  } elseif ($key == 'classOverride') {
8839  $attr['class'] = $value;
8840  } else {
8841  $attr[$key] = $value;
8842  }
8843  }
8844  }
8845 
8846  if (isset($attr['href']) && empty($attr['href'])) {
8847  unset($attr['href']);
8848  }
8849 
8850  // TODO : add a hook
8851 
8852  // escape all attribute
8853  $attr = array_map('dol_escape_htmltag', $attr);
8854 
8855  $TCompiledAttr = array();
8856  foreach ($attr as $key => $value) {
8857  $TCompiledAttr[] = $key.'="'.$value.'"';
8858  }
8859 
8860  $compiledAttributes = (empty($TCompiledAttr) ? '' : implode(' ', $TCompiledAttr));
8861 
8862  $tag = (empty($attr['href']) ? 'span' : 'a');
8863 
8864  $button = '<'.$tag.' '.$compiledAttributes.'>';
8865  $button .= '<span class="'.$iconClass.' valignmiddle btnTitle-icon"></span>';
8866  if (!empty($params['forcenohideoftext'])) {
8867  $button .= '<span class="valignmiddle text-plus-circle btnTitle-label'.(empty($params['forcenohideoftext']) ? ' hideonsmartphone' : '').'">'.$label.'</span>';
8868  }
8869  $button .= '</'.$tag.'>';
8870 
8871  return $button;
8872 }
8873 
8881 function getElementProperties($element_type)
8882 {
8883  $regs = array();
8884 
8885  $classfile = $classname = $classpath = '';
8886 
8887  // Parse element/subelement (ex: project_task)
8888  $module = $element_type;
8889  $element = $element_type;
8890  $subelement = $element_type;
8891 
8892  // If we ask an resource form external module (instead of default path)
8893  if (preg_match('/^([^@]+)@([^@]+)$/i', $element_type, $regs)) {
8894  $element = $subelement = $regs[1];
8895  $module = $regs[2];
8896  }
8897 
8898  //print '<br>1. element : '.$element.' - module : '.$module .'<br>';
8899  if (preg_match('/^([^_]+)_([^_]+)/i', $element, $regs)) {
8900  $module = $element = $regs[1];
8901  $subelement = $regs[2];
8902  }
8903 
8904  // For compat
8905  if ($element_type == "action") {
8906  $classpath = 'comm/action/class';
8907  $subelement = 'Actioncomm';
8908  $module = 'agenda';
8909  }
8910 
8911  // To work with non standard path
8912  if ($element_type == 'facture' || $element_type == 'invoice') {
8913  $classpath = 'compta/facture/class';
8914  $module = 'facture';
8915  $subelement = 'facture';
8916  }
8917  if ($element_type == 'commande' || $element_type == 'order') {
8918  $classpath = 'commande/class';
8919  $module = 'commande';
8920  $subelement = 'commande';
8921  }
8922  if ($element_type == 'propal') {
8923  $classpath = 'comm/propal/class';
8924  }
8925  if ($element_type == 'supplier_proposal') {
8926  $classpath = 'supplier_proposal/class';
8927  }
8928  if ($element_type == 'shipping') {
8929  $classpath = 'expedition/class';
8930  $subelement = 'expedition';
8931  $module = 'expedition_bon';
8932  }
8933  if ($element_type == 'delivery') {
8934  $classpath = 'delivery/class';
8935  $subelement = 'delivery';
8936  $module = 'delivery_note';
8937  }
8938  if ($element_type == 'contract') {
8939  $classpath = 'contrat/class';
8940  $module = 'contrat';
8941  $subelement = 'contrat';
8942  }
8943  if ($element_type == 'member') {
8944  $classpath = 'adherents/class';
8945  $module = 'adherent';
8946  $subelement = 'adherent';
8947  }
8948  if ($element_type == 'cabinetmed_cons') {
8949  $classpath = 'cabinetmed/class';
8950  $module = 'cabinetmed';
8951  $subelement = 'cabinetmedcons';
8952  }
8953  if ($element_type == 'fichinter') {
8954  $classpath = 'fichinter/class';
8955  $module = 'ficheinter';
8956  $subelement = 'fichinter';
8957  }
8958  if ($element_type == 'dolresource' || $element_type == 'resource') {
8959  $classpath = 'resource/class';
8960  $module = 'resource';
8961  $subelement = 'dolresource';
8962  }
8963  if ($element_type == 'propaldet') {
8964  $classpath = 'comm/propal/class';
8965  $module = 'propal';
8966  $subelement = 'propaleligne';
8967  }
8968  if ($element_type == 'order_supplier') {
8969  $classpath = 'fourn/class';
8970  $module = 'fournisseur';
8971  $subelement = 'commandefournisseur';
8972  $classfile = 'fournisseur.commande';
8973  }
8974  if ($element_type == 'invoice_supplier') {
8975  $classpath = 'fourn/class';
8976  $module = 'fournisseur';
8977  $subelement = 'facturefournisseur';
8978  $classfile = 'fournisseur.facture';
8979  }
8980  if ($element_type == "service") {
8981  $classpath = 'product/class';
8982  $subelement = 'product';
8983  }
8984 
8985  if (empty($classfile)) $classfile = strtolower($subelement);
8986  if (empty($classname)) $classname = ucfirst($subelement);
8987  if (empty($classpath)) $classpath = $module.'/class';
8988 
8989  $element_properties = array(
8990  'module' => $module,
8991  'classpath' => $classpath,
8992  'element' => $element,
8993  'subelement' => $subelement,
8994  'classfile' => $classfile,
8995  'classname' => $classname
8996  );
8997  return $element_properties;
8998 }
8999 
9009 function fetchObjectByElement($element_id, $element_type, $element_ref = '')
9010 {
9011  global $conf, $db;
9012 
9013  $element_prop = getElementProperties($element_type);
9014  if (is_array($element_prop) && $conf->{$element_prop['module']}->enabled)
9015  {
9016  dol_include_once('/'.$element_prop['classpath'].'/'.$element_prop['classfile'].'.class.php');
9017 
9018  $objecttmp = new $element_prop['classname']($db);
9019  $ret = $objecttmp->fetch($element_id, $element_ref);
9020  if ($ret >= 0)
9021  {
9022  return $objecttmp;
9023  }
9024  }
9025  return 0;
9026 }
9027 
9034 function isAFileWithExecutableContent($filename)
9035 {
9036  if (preg_match('/\.(htm|html|js|phar|php|php\d+|phtml|pht|pl|py|cgi|ksh|sh|shtml|bash|bat|cmd|wpk|exe|dmg)$/i', $filename))
9037  {
9038  return true;
9039  }
9040 
9041  return false;
9042 }
9043 
9050 function newToken()
9051 {
9052  return $_SESSION['newtoken'];
9053 }
9054 
9060 function currentToken()
9061 {
9062  return $_SESSION['token'];
9063 }
9064 
9077 function startSimpleTable($header, $link = "", $arguments = "", $emptyRows = 0, $number = -1)
9078 {
9079  global $langs;
9080 
9081  print '<div class="div-table-responsive-no-min">';
9082  print '<table class="noborder centpercent">';
9083  print '<tr class="liste_titre">';
9084 
9085  print $emptyRows < 1 ? '<th>' : '<th colspan="'.($emptyRows + 1).'">';
9086 
9087  print $langs->trans($header);
9088 
9089  // extra space between the first header and the number
9090  if ($number > -1) {
9091  print ' ';
9092  }
9093 
9094  if (!empty($link)) {
9095  if (!empty($arguments)) {
9096  print '<a href="'.DOL_URL_ROOT.'/'.$link.'?'.$arguments.'">';
9097  } else {
9098  print '<a href="'.DOL_URL_ROOT.'/'.$link.'">';
9099  }
9100  }
9101 
9102  if ($number > -1) {
9103  print '<span class="badge">'.$number.'</span>';
9104  }
9105 
9106  if (!empty($link)) {
9107  print '</a>';
9108  }
9109 
9110  print '</th>';
9111 
9112  if ($number < 0 && !empty($link)) {
9113  print '<th class="right">';
9114 
9115  if (!empty($arguments)) {
9116  print '<a class="commonlink" href="'.DOL_URL_ROOT.'/'.$link.'?'.$arguments.'">';
9117  } else {
9118  print '<a class="commonlink" href="'.DOL_URL_ROOT.'/'.$link.'">';
9119  }
9120 
9121  print $langs->trans("FullList");
9122  print '</a>';
9123  print '</th>';
9124  }
9125 
9126  print '</tr>';
9127 }
9128 
9137 function finishSimpleTable($addLineBreak = false)
9138 {
9139  print '</table>';
9140  print '</div>';
9141 
9142  if ($addLineBreak) {
9143  print '<br>';
9144  }
9145 }
9146 
9158 function addSummaryTableLine($tableColumnCount, $num, $nbofloop = 0, $total = 0, $noneWord = "None", $extraRightColumn = false)
9159 {
9160  global $langs;
9161 
9162  if ($num === 0) {
9163  print '<tr class="oddeven">';
9164  print '<td colspan="'.$tableColumnCount.'" class="opacitymedium">'.$langs->trans($noneWord).'</td>';
9165  print '</tr>';
9166  return;
9167  }
9168 
9169  if ($nbofloop === 0)
9170  {
9171  // don't show a summary line
9172  return;
9173  }
9174 
9175  if ($num === 0) {
9176  $colspan = $tableColumnCount;
9177  }
9178  elseif ($num > $nbofloop) {
9179  $colspan = $tableColumnCount;
9180  } else {
9181  $colspan = $tableColumnCount - 1;
9182  }
9183 
9184  if ($extraRightColumn) {
9185  $colspan--;
9186  }
9187 
9188  print '<tr class="liste_total">';
9189 
9190  if ($nbofloop > 0 && $num > $nbofloop) {
9191  print '<td colspan="'.$colspan.'" class="right">'.$langs->trans("XMoreLines", ($num - $nbofloop)).'</td>';
9192  } else {
9193  print '<td colspan="'.$colspan.'" class="right"> '.$langs->trans("Total").'</td>';
9194  print '<td class="right" width="100">'.price($total).'</td>';
9195  }
9196 
9197  if ($extraRightColumn) {
9198  print '<td></td>';
9199  }
9200 
9201  print '</tr>';
9202 }
9203 
9212 function readfileLowMemory($fullpath_original_file_osencoded, $method = -1)
9213 {
9214  global $conf;
9215 
9216  if ($method == -1) {
9217  $method = 0;
9218  if (!empty($conf->global->MAIN_FORCE_READFILE_WITH_FREAD)) $method = 1;
9219  if (!empty($conf->global->MAIN_FORCE_READFILE_WITH_STREAM_COPY)) $method = 2;
9220  }
9221 
9222  // Be sure we don't have output buffering enabled to have readfile working correctly
9223  while (ob_get_level()) ob_end_flush();
9224 
9225  // Solution 0
9226  if ($method == 0) {
9227  readfile($fullpath_original_file_osencoded);
9228  }
9229  // Solution 1
9230  elseif ($method == 1) {
9231  $handle = fopen($fullpath_original_file_osencoded, "rb");
9232  while (!feof($handle)) {
9233  print fread($handle, 8192);
9234  }
9235  fclose($handle);
9236  }
9237  // Solution 2
9238  elseif ($method == 2) {
9239  $handle1 = fopen($fullpath_original_file_osencoded, "rb");
9240  $handle2 = fopen("php://output", "wb");
9241  stream_copy_to_stream($handle1, $handle2);
9242  fclose($handle1);
9243  fclose($handle2);
9244  }
9245 }
dol_convert_file($fileinput, $ext= 'png', $fileoutput= '', $page= '')
Convert an image file into another format.
Definition: files.lib.php:1852
verifCond($strRights)
Verify if condition in string is ok or not.
dol_nboflines_bis($text, $maxlinesize=0, $charset= 'UTF-8')
Return nb of lines of a formated text with and (WARNING: string must not have mixed and br sepa...
if(!function_exists('dol_getprefix')) dol_include_once($relpath, $classname= '')
Make an include_once using default root and alternate root if it fails.
dol_osencode($str)
Return a string encoded into OS filesystem encoding.
GETPOST($paramname, $check= 'alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
dolIsAllowedForPreview($file)
Return if a file is qualified for preview.
dol_string_nohtmltag($stringtoclean, $removelinefeed=1, $pagecodeto= 'UTF-8', $strip_tags=0, $removedoublespaces=1)
Clean a string from all HTML tags and entities.
dol_sanitizePathName($str, $newstr= '_', $unaccent=1)
Clean a string to use it as a path name.
dol_hash($chain, $type= '0')
Returns a hash of a string.
img_edit($titlealt= 'default', $float=0, $other= '')
Show logo editer/modifier fiche.
dol_htmloutput_events($disabledoutputofmessages=0)
Print formated messages to output (Used to show messages on html output).
img_picto_common($titlealt, $picto, $moreatt= '', $pictoisfullpath=0)
Show picto (generic function)
dol_substr($string, $start, $length, $stringencoding= '', $trunconbytes=0)
Make a substring.
yn($yesno, $case=1, $color=0)
Return yes or no in current language.
getDoliDBInstance($type, $host, $user, $pass, $name, $port)
Return a DoliDB instance (database handler).
dol_eval($s, $returnvalue=0, $hideerrors=1)
Replace eval function to add more security.
dol_mktime($hour, $minute, $second, $month, $day, $year, $gm= 'auto', $check=1)
Return a timestamp date built from detailed informations (by default a local PHP server timestamp) Re...
dolButtonToOpenUrlInDialogPopup($name, $label, $buttonstring, $url, $disabled= '')
Return HTML code to output a button to open a dialog popup box.
getUserRemoteIP()
Return the IP of remote user.
dol_get_prev_month($month, $year)
Return previous month.
Definition: date.lib.php:398
isACompany()
Return if third party is a company (Business) or an end user (Consumer)
if(!empty($arrayfields['country.code_iso']['checked'])) print_liste_field_titre($arrayfields['country.code_iso']['label'] country if(!empty($arrayfields['typent.code']['checked'])) print_liste_field_titre($arrayfields['typent.code']['label'] typent code
Definition: list.php:566
dol_print_url($url, $target= '_blank', $max=32, $withpicto=0)
Show Url link.
dol_format_address($object, $withcountry=0, $sep="\n", $outputlangs= '', $mode=0, $extralangcode= '')
Return a formated address (part address/zip/town/state) according to country rules.
conf($dolibarr_main_document_root)
Load conf file (file must exists)
Definition: inc.php:262
img_help($usehelpcursor=1, $usealttitle=1)
Show help logo with cursor &quot;?&quot;.
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.
getArrayOfSocialNetworks()
Get array of social network dictionary.
setEntity($currentobject)
Set entity id to use when to create an object.
printCommonFooter($zone= 'private')
Print common footer : conf-&gt;global-&gt;MAIN_HTML_FOOTER js for switch of menu hider js for conf-&gt;global-...
img_weather($titlealt, $picto, $moreatt= '', $pictoisfullpath=0, $morecss= '')
Show weather picto.
img_credit_card($brand, $morecss=null)
Return image of a credit card according to its brand name.
</td >< tdcolspan="3">< spanclass="opacitymedium"></span ></td ></tr >< trclass="liste_total"> CREANCES DETTES< tdcolspan="3"class="right"></td >< tdcolspan="3"class="right"></td ></tr > CREANCES DETTES RECETTES DEPENSES trips CREANCES DETTES Y m expensereport p date_valid Y m expensereport pe datep $db idate($date_start)."' AND $column < p rowid
foreach($object->fields as $key=> $val) if(is_array($extrafields->attributes[$object->table_element]['label'])&&count($extrafields->attributes[$object->table_element]['label']) > 0) $object fields
dol_escape_json($stringtoescape)
Returns text escaped for inclusion into javascript code.
dol_shutdown()
Function called at end of web php process.
dol_html_entity_decode($a, $b, $c= 'UTF-8', $keepsomeentities=0)
Replace html_entity_decode functions to manage errors.
Class to manage products or services.
dol_fiche_head($links=array(), $active= '0', $title= '', $notab=0, $picto= '', $pictoisfullpath=0, $morehtmlright= '', $morecss= '', $limittoshow=0, $moretabssuffix= '')
Show tab header of a card.
dol_escape_js($stringtoescape, $mode=0, $noescapebackslashn=0)
Returns text escaped for inclusion into javascript code.
dol_now($mode= 'auto')
Return date for now.
picto_required()
Return picto saying a field is required.
get_date_range($date_start, $date_end, $format= '', $outputlangs= '', $withparenthesis=1)
Format output for start and end date.
get_htmloutput_errors($mesgstring= '', $mesgarray=array(), $keepembedded=0)
Get formated error messages to output (Used to show messages on html output).
getTaxesFromId($vatrate, $buyer=null, $seller=null, $firstparamisid=1)
Get tax (VAT) main information from Id.
dol_strtoupper($string, $encoding="UTF-8")
Convert a string to upper.
isASecretKey($keyname)
Return if string has a name dedicated to store a secret.
dol_print_phone($phone, $countrycode= '', $cid=0, $socid=0, $addlink= '', $separ="&nbsp;", $withpicto= '', $titlealt= '', $adddivfloat=0)
Format phone numbers according to country.
dol_htmlentities($string, $flags=null, $encoding= 'UTF-8', $double_encode=false)
Replace htmlentities functions.
setEventMessage($mesgs, $style= 'mesgs')
Set event message in dol_events session object.
dol_clone($object, $native=0)
Create a clone of instance of object (new instance with same value for properties) With native = 0: P...
dol_getmypid()
Return getmypid() or random PID when function is disabled Some web hosts disable this php function fo...
dol_htmlentitiesbr($stringtoencode, $nl2brmode=0, $pagecodefrom= 'UTF-8', $removelasteolbr=1)
This function is called to encode a string into a HTML string but differs from htmlentities because a...
dolGetButtonAction($label, $html= '', $actionType= 'default', $url= '', $id= '', $userRight=1, $params=array())
Function dolGetButtonAction.
dol_nl2br($stringtoencode, $nl2brmode=0, $forxml=false)
Replace CRLF in string with a HTML BR tag.
dol_is_dir($folder)
Test if filename is a directory.
Definition: files.lib.php:432
get_default_npr(Societe $thirdparty_seller, Societe $thirdparty_buyer, $idprod=0, $idprodfournprice=0)
Fonction qui renvoie si tva doit etre tva percue recuperable.
isOnlyOneLocalTax($local)
Return true if LocalTax (1 or 2) is unique.
$conf db name
Only used if Module[ID]Name translation string is not found.
Definition: repair.php:108
checkVal($out= '', $check= 'alphanohtml', $filter=null, $options=null)
Return a value after checking on a rule.
dol_concatdesc($text1, $text2, $forxml=false, $invert=false)
Concat 2 descriptions with a new line between them (second operand after first one with appropriate n...
dol_get_prev_day($day, $month, $year)
Return previous day.
Definition: date.lib.php:367
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
dol_print_error_email($prefixcode, $errormessage= '', $errormessages=array(), $morecss= 'error', $email= '')
Show a public email and error code to contact if technical error.
dol_validElement($element)
Return if var element is ok.
get_localtax($vatrate, $local, $thirdparty_buyer="", $thirdparty_seller="", $vatnpr=0)
Return localtax rate for a particular vat, when selling a product with vat $vatrate, from a $thirdparty_buyer to a $thirdparty_seller Note: This function applies same rules than get_default_tva.
img_left($titlealt= 'default', $selected=0, $moreatt= '')
Show left arrow logo.
img_mime($file, $titlealt= '', $morecss= '')
Show MIME img of a file.
get_product_localtax_for_country($idprod, $local, $thirdparty_seller)
Return localtax vat rate of a product in a particular selling country or default country vat if produ...
img_action($titlealt, $numaction, $picto= '')
Show logo action.
img_warning($titlealt= 'default', $moreatt= '', $morecss= 'pictowarning')
Show warning logo.
getLanguageCodeFromCountryCode($countrycode)
Return default language from country code.
price($amount, $form=0, $outlangs= '', $trunc=1, $rounding=-1, $forcerounding=-1, $currency_code= '')
Function to format a value into an amount for visual output Function used into PDF and HTML pages...
dol_string_nounprintableascii($str, $removetabcrlf=1)
Clean a string from all non printable ASCII chars (0x00-0x1F and 0x7F).
img_search($titlealt= 'default', $other= '')
Show search logo.
dol_print_ip($ip, $mode=0)
Return an IP formated to be shown on screen.
getCommonSubstitutionArray($outputlangs, $onlykey=0, $exclude=null, $object=null)
Return array of possible common substitutions.
dol_string_nospecial($str, $newstr= '_', $badcharstoreplace= '')
Clean a string from all punctuation characters to use it as a ref or login.
dol_nboflines($s, $maxchar=0)
Return nb of lines of a clear text.
Class to manage standard extra fields.
getImageFileNameForSize($file, $extName, $extImgTarget= '')
Return the filename of file to get the thumbs.
setEventMessages($mesg, $mesgs, $style= 'mesgs', $messagekey= '')
Set event messages in dol_events session object.
img_error($titlealt= 'default')
Show error logo.
showDirectDownloadLink($object)
Return string with full Url.
print_barre_liste($titre, $page, $file, $options= '', $sortfield= '', $sortorder= '', $morehtmlcenter= '', $num=-1, $totalnboflines= '', $picto= 'generic', $pictoisfullpath=0, $morehtmlright= '', $morecss= '', $limit=-1, $hideselectlimit=0, $hidenavigation=0, $pagenavastextinput=0, $morehtmlrightbeforearrow= '')
Print a title with navigation controls for pagination.
isValidMXRecord($domain)
Return if the domain name has a valid MX record.
GETPOSTISSET($paramname)
Return true if we are in a context of submitting the parameter $paramname.
img_down($titlealt= 'default', $selected=0, $moreclass= '')
Show down arrow logo.
Class to manage third parties objects (customers, suppliers, prospects...)
dol_print_socialnetworks($value, $cid, $socid, $type, $dictsocialnetworks=array())
Show social network link.
img_pdf($titlealt= 'default', $size=3)
Show pdf logo.
print_liste_field_titre($name, $file="", $field="", $begin="", $moreparam="", $moreattrib="", $sortfield="", $sortorder="", $prefix="", $tooltip="", $forcenowrapcolumntitle=0)
Show title line of an array.
dol_string_neverthesehtmltags($stringtoclean, $disallowed_tags=array('textarea'), $cleanalsosomestyles=0)
Clean a string from some undesirable HTML tags.
get_default_localtax($thirdparty_seller, $thirdparty_buyer, $local, $idprod=0)
Function that return localtax of a product line (according to seller, buyer and product vat rate) Si ...
getEntity($element, $shared=1, $currentobject=null)
Get list of entity id to use.
get_htmloutput_mesg($mesgstring= '', $mesgarray= '', $style= 'ok', $keepembedded=0)
Get formated messages to output (Used to show messages on html output).
dol_convertToWord($num, $langs, $currency= '', $centimes=false)
Function to return a number into a text.
dolGetCountryCodeFromIp($ip)
Return a country code from IP.
getServerTimeZoneInt($refgmtdate= 'now')
Return server timezone int.
Definition: date.lib.php:83
dol_mimetype($file, $default= 'application/octet-stream', $mode=0)
Return mime type of a file.
load_fiche_titre($titre, $morehtmlright= '', $picto= 'generic', $pictoisfullpath=0, $id= '', $morecssontable= '', $morehtmlcenter= '')
Load a title with picto.
dol_strlen($string, $stringencoding= 'UTF-8')
Make a strlen call.
img_up($titlealt= 'default', $selected=0, $moreclass= '')
Show top arrow logo.
price2num($amount, $rounding= '', $option=0)
Function that return a number with universal decimal format (decimal separator is &#39;...
isVisibleToUserType($type_user, &$menuentry, &$listofmodulesforexternal)
Function to test if an entry is enabled or not.
img_searchclear($titlealt= 'default', $other= '')
Show search logo.
dol_size($size, $type= '')
Optimize a size for some browsers (phone, smarphone, ...)
img_printer($titlealt="default", $other= '')
Show printer logo.
showDimensionInBestUnit($dimension, $unit, $type, $outputlangs, $round=-1, $forceunitoutput= 'no')
Output a dimension with best unit.
dol_get_next_month($month, $year)
Return next month.
Definition: date.lib.php:418
dol_fiche_end($notab=0)
Show tab footer of a card.
img_picto($titlealt, $picto, $moreatt= '', $pictoisfullpath=false, $srconly=0, $notitle=0, $alt= '', $morecss= '', $marginleftonlyshort=2)
Show picto whatever it&#39;s its name (generic function)
dol_ucfirst($string, $encoding="UTF-8")
Convert first character of the first word of a string to upper.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename= '', $restricttologhandler= '', $logcontext=null)
Write log message into outputs.
dol_get_next_day($day, $month, $year)
Return next day.
Definition: date.lib.php:383
get_exdir($num, $level, $alpha, $withoutslash, $object, $modulepart= '')
Return a path to have a the directory according to object where files are stored. ...
readfileLowMemory($fullpath_original_file_osencoded, $method=-1)
Return a file on output using a low memory.
dol_getdate($timestamp, $fast=false, $forcetimezone= '')
Return an array with locale date info.
img_object($titlealt, $picto, $moreatt= '', $pictoisfullpath=false, $srconly=0, $notitle=0)
Show a picto called object_picto (generic function)
getBrowserInfo($user_agent)
Return information about user browser.
natural_search($fields, $value, $mode=0, $nofirstand=0)
Generate natural SQL search string for a criteria (this criteria can be tested on one or several fiel...
Class to manage translations.
isValidVATID($company)
Check if VAT numero is valid (check done on syntax only, no database or remote access) ...
dol_sanitizeFileName($str, $newstr= '_', $unaccent=1)
Clean a string to use it as a file name.
dol_dir_list($path, $types="all", $recursive=0, $filter="", $excludefilter=null, $sortcriteria="name", $sortorder=SORT_ASC, $mode=0, $nohook=0, $relativename="", $donotfollowsymlinks=0)
Scan a directory and return a list of files/directories.
Definition: files.lib.php:60
dol_string_unaccent($str)
Clean a string from all accent characters to be used as ref, login or by dol_sanitizeFileName.
dol_user_country()
Return country code for current user.
utf8_check($str)
Check if a string is in UTF8.
vatrate($rate, $addpercent=false, $info_bits=0, $usestarfornpr=0)
Return a string with VAT rate label formated for view output Used into pdf and HTML pages...
img_right($titlealt= 'default', $selected=0, $moreatt= '')
Show right arrow logo.
ajax_autoselect($htmlname, $addlink= '')
Make content of an input box selected when we click into input field.
print $_SERVER["PHP_SELF"]
Edit parameters.
img_next($titlealt= 'default', $moreatt= '')
Show next logo.
dolExplodeIntoArray($string, $delimiter= ';', $kv= '=')
Split a string with 2 keys into key array.
getElementProperties($element_type)
Get an array with properties of an element.
img_edit_add($titlealt= 'default', $other= '')
Show logo +.
GETPOSTINT($paramname, $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
print_fiche_titre($title, $mesg= '', $picto= 'generic', $pictoisfullpath=0, $id= '')
Show a title with picto.
img_edit_remove($titlealt= 'default', $other= '')
Show logo -.
img_allow($allow, $titlealt= 'default')
Show tick logo if allowed.
dolGetFirstLineOfText($text, $nboflines=1, $charset= 'UTF-8')
Return first line of text.
dol_sort_array(&$array, $index, $order= 'asc', $natsort=0, $case_sensitive=0, $keepindex=0)
Advanced sort array by second index function, which produces ascending (default) or descending output...
dol_getIdFromCode($db, $key, $tablename, $fieldkey= 'code', $fieldid= 'id', $entityfilter=0)
Return an id or code from a code or id.
dol_ucwords($string, $encoding="UTF-8")
Convert first character of all the words of a string to upper.
dol_get_fiche_head($links=array(), $active= '', $title= '', $notab=0, $picto= '', $pictoisfullpath=0, $morehtmlright= '', $morecss= '', $limittoshow=0, $moretabssuffix= '')
Show tabs of a record.
dol_htmloutput_mesg($mesgstring= '', $mesgarray=array(), $style= 'ok', $keepembedded=0)
Print formated messages to output (Used to show messages on html output).
print
Draft customers invoices.
Definition: index.php:89
dol_print_size($size, $shortvalue=0, $shortunit=0)
Return string with formated size.
dol_print_date($time, $format= '', $tzoutput= 'auto', $outputlangs= '', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
img_previous($titlealt= 'default', $moreatt= '')
Show previous logo.
dol_string_is_good_iso($s, $clean=0)
Check if a string is a correct iso string If not, it will we considered not HTML encoded even if it i...
ajax_object_onoff($object, $code, $field, $text_on, $text_off, $input=array())
On/off button to change status of an object This is called when MAIN_DIRECT_STATUS_UPDATE is set and ...
Definition: ajax.lib.php:573
print_fleche_navigation($page, $file, $options= '', $nextpage=0, $betweenarrows= '', $afterarrows= '', $limit=-1, $totalnboflines=0, $hideselectlimit=0, $beforearrows= '')
Function to show navigation arrows into lists.
isAFileWithExecutableContent($filename)
Return if a file can contains executable content.
dol_htmlcleanlastbr($stringtodecode)
This function remove all ending and br at end.
isHTTPS()
Return if we are using a HTTPS connexion Check HTTPS (no way to be modified by user but may be empty ...
startSimpleTable($header, $link="", $arguments="", $emptyRows=0, $number=-1)
Start a table with headers and a optinal clickable number (don&#39;t forget to use &quot;finishSimpleTable()&quot; ...
dol_string_onlythesehtmltags($stringtoclean, $cleanalsosomestyles=1, $removeclassattribute=1, $cleanalsojavascript=0)
Clean a string to keep only desirable HTML tags.
get_product_vat_for_country($idprod, $thirdparty_seller, $idprodfournprice=0)
Return vat rate of a product in a particular selling country or default country vat if product is unk...
if(!empty($conf->facture->enabled)&&$user->rights->facture->lire) if((!empty($conf->fournisseur->enabled)&&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)||!empty($conf->supplier_invoice->enabled))&&$user->rights->fournisseur->facture->lire) if(!empty($conf->don->enabled)&&$user->rights->don->lire) if(!empty($conf->tax->enabled)&&$user->rights->tax->charges->lire) if(!empty($conf->facture->enabled)&&!empty($conf->commande->enabled)&&$user->rights->commande->lire &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) if(!empty($conf->facture->enabled)&&$user->rights->facture->lire) if((!empty($conf->fournisseur->enabled)&&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)||!empty($conf->supplier_invoice->enabled))&&$user->rights->fournisseur->facture->lire) $resql
Social contributions to pay.
Definition: index.php:1232
dol_print_error($db= '', $error= '', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
get_default_tva(Societe $thirdparty_seller, Societe $thirdparty_buyer, $idprod=0, $idprodfournprice=0)
Function that return vat rate of a product line (according to seller, buyer and product vat rate) Si ...
dolGetBadge($label, $html= '', $type= 'primary', $mode= '', $url= '', $params=array())
Function dolGetBadge.
dol_print_email($email, $cid=0, $socid=0, $addlink=0, $max=64, $showinvalid=1, $withpicto=0)
Show EMail link formatted for HTML output.
img_info($titlealt= 'default')
Show info logo.
get_localtax_by_third($local)
Get values of localtaxes (1 or 2) for company country for the common vat with the highest value...
newToken()
Return the value of token currently saved into session with name &#39;newtoken&#39;.
dol_htmlentitiesbr_decode($stringtodecode, $pagecodeto= 'UTF-8')
This function is called to decode a HTML string (it decodes entities and br tags) ...
dol_get_fiche_end($notab=0)
Return tab footer of a card.
img_view($titlealt= 'default', $float=0, $other= '')
Show logo view card.
print_titre($title)
Show a title.
print $_SERVER["PHP_SELF"] n
Edit parameters.
Definition: categories.php:101
dol_trunc($string, $size=40, $trunc= 'right', $stringencoding= 'UTF-8', $nodot=0, $display=0)
Truncate a string to a particular length adding &#39;...&#39; if string larger than length.
print_date_range($date_start, $date_end, $format= '', $outputlangs= '')
Format output for start and end date.
dolGetStatus($statusLabel= '', $statusLabelShort= '', $html= '', $statusType= 'status0', $displayMode=0, $url= '', $params=array())
Output the badge of a status.
make_substitutions($text, $substitutionarray, $outputlangs=null)
Make substitution into a text string, replacing keys with vals from $substitutionarray (oldval=&gt;newva...
fieldLabel($langkey, $fieldkey, $fieldrequired=0)
Show a string with the label tag dedicated to the HTML edit field.
getTitleFieldOfList($name, $thead=0, $file="", $field="", $begin="", $moreparam="", $moreattrib="", $sortfield="", $sortorder="", $prefix="", $disablesortlink=0, $tooltip= '', $forcenowrapcolumntitle=0)
Get title line of an array.
dol_banner_tab($object, $paramid, $morehtml= '', $shownav=1, $fieldid= 'rowid', $fieldref= 'ref', $morehtmlref= '', $moreparam= '', $nodbprefix=0, $morehtmlleft= '', $morehtmlstatus= '', $onlybanner=0, $morehtmlright= '')
Show tab footer of a card.
dol_htmloutput_errors($mesgstring= '', $mesgarray=array(), $keepembedded=0)
Print formated error messages to output (Used to show messages on html output).
getLocalTaxesFromRate($vatrate, $local, $buyer, $seller, $firstparamisid=0)
Get type and rate of localtaxes for a particular vat rate/country of a thirdparty.
fetchObjectByElement($element_id, $element_type, $element_ref= '')
Fetch an object from its id and element_type Inclusion of classes is automatic.
complete_head_from_modules($conf, $langs, $object, &$head, &$h, $type, $mode= 'add')
Complete or removed entries into a head array (used to build tabs).
colorIsLight($stringcolor)
Return true if the color is light.
img_delete($titlealt= 'default', $other= 'class="pictodelete"', $morecss= '')
Show delete logo.
img_split($titlealt= 'default', $other= 'class="pictosplit"')
Show split logo.
isValidEmail($address, $acceptsupervisorkey=0)
Return true if email syntax is ok.
if(!defined('CSRFCHECK_WITH_TOKEN')) define('CSRFCHECK_WITH_TOKEN'
Draft customers invoices.
currentToken()
Return the value of token currently saved into session with name &#39;token&#39;.
info_admin($text, $infoonimgalt=0, $nodiv=0, $admin= '1', $morecss= '', $textfordropdown= '')
Show information for admin users or standard users.
getAdvancedPreviewUrl($modulepart, $relativepath, $alldata=0, $param= '')
Return URL we can use for advanced preview links.
dol_print_address($address, $htmlid, $element, $id, $noprint=0, $charfornl= '')
Format address string.
dol_set_focus($selector)
Set focus onto field with selector (similar behaviour of &#39;autofocus&#39; HTML5 tag)
picto_from_langcode($codelang, $moreatt= '')
Return img flag of country for a language code or country code.
isInEEC($object)
Return if a country of an object is inside the EEC (European Economic Community)
Class to manage predefined suppliers products.
ascii_check($str)
Check if a string is in ASCII.
isValidPhone($phone)
Return true if phone number syntax is ok TODO Decide what to do with this.
dol_strtolower($string, $encoding="UTF-8")
Convert a string to lower.
dol_mkdir($dir, $dataroot= '', $newmask=null)
Creation of a directory (this can create recursive subdir)
roundUpToNextMultiple($n, $x=5)
Round to next multiple.
dolGetFirstLastname($firstname, $lastname, $nameorder=-1)
Return firstname and lastname in correct order.
measuringUnitString($unit, $measuring_style= '', $scale= '', $use_short_label=0, $outputlangs=null)
Return translation label of a unit key.
dol_strftime($fmt, $ts=false, $is_gmt=false)
Format a string.
dol_bc($var, $moreclass= '')
Return string to add class property on html element with pair/impair.
complete_substitutions_array(&$substitutionarray, $outputlangs, $object=null, $parameters=null, $callfunc="completesubstitutionarray")
Complete the $substitutionarray with more entries coming from external module that had set the &quot;subst...
Classe to manage GeoIP Usage: $geoip=new GeoIP(&#39;country&#39;,$datfile); $geoip-&gt;getCountryCodeFromIP($ip)...
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $keepmoretags= '', $escapeonlyhtmltags=0)
Returns text escaped for inclusion in HTML alt or title tags, or into values of HTML input fields...
dol_textishtml($msg, $option=0)
Return if a text is a html content.