dolibarr  9.0.0
functions2.lib.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2008-2011 Laurent Destailleur <eldy@users.sourceforge.net>
3  * Copyright (C) 2008-2012 Regis Houssin <regis.houssin@inodbox.com>
4  * Copyright (C) 2008 Raphael Bertrand (Resultic) <raphael.bertrand@resultic.fr>
5  * Copyright (C) 2014-2016 Marcos García <marcosgdf@gmail.com>
6  * Copyright (C) 2015 Ferran Marcet <fmarcet@2byte.es>
7  * Copyright (C) 2015-2016 Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr>
8  * Copyright (C) 2017 Juanjo Menent <jmenent@2byte.es>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 3 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program. If not, see <http://www.gnu.org/licenses/>.
22  * or see http://www.gnu.org/
23  */
24 
31 // Enable this line to trace path when function is called.
32 //print xdebug_print_function_stack('Functions2.lib was called');exit;
33 
40 function jsUnEscape($source)
41 {
42  $decodedStr = "";
43  $pos = 0;
44  $len = strlen($source);
45  while ($pos < $len) {
46  $charAt = substr($source, $pos, 1);
47  if ($charAt == '%') {
48  $pos++;
49  $charAt = substr($source, $pos, 1);
50  if ($charAt == 'u') {
51  // we got a unicode character
52  $pos++;
53  $unicodeHexVal = substr($source, $pos, 4);
54  $unicode = hexdec($unicodeHexVal);
55  $entity = "&#". $unicode . ';';
56  $decodedStr .= utf8_encode($entity);
57  $pos += 4;
58  }
59  else {
60  // we have an escaped ascii character
61  $hexVal = substr($source, $pos, 2);
62  $decodedStr .= chr(hexdec($hexVal));
63  $pos += 2;
64  }
65  } else {
66  $decodedStr .= $charAt;
67  $pos++;
68  }
69  }
70  return dol_html_entity_decode($decodedStr, ENT_COMPAT);
71 }
72 
73 
81 function dolGetModulesDirs($subdir='')
82 {
83  global $conf;
84 
85  $modulesdir=array();
86 
87  foreach ($conf->file->dol_document_root as $type => $dirroot)
88  {
89  // Default core/modules dir
90  if ($type === 'main') {
91  $modulesdir[$dirroot . '/core/modules' . $subdir . '/'] = $dirroot . '/core/modules' . $subdir . '/';
92  }
93 
94  // Scan dir from external modules
95  $handle=@opendir($dirroot);
96  if (is_resource($handle))
97  {
98  while (($file = readdir($handle))!==false)
99  {
100  if (preg_match('/disabled/',$file)) continue; // We discard module if it contains disabled into name.
101 
102  if (is_dir($dirroot.'/'.$file) && substr($file, 0, 1) <> '.' && substr($file, 0, 3) <> 'CVS' && $file != 'includes')
103  {
104  if (is_dir($dirroot . '/' . $file . '/core/modules'.$subdir.'/'))
105  {
106  $modulesdir[$dirroot . '/' . $file . '/core/modules'.$subdir.'/'] = $dirroot . '/' . $file . '/core/modules'.$subdir.'/';
107  }
108  }
109  }
110  closedir($handle);
111  }
112  }
113  return $modulesdir;
114 }
115 
116 
123 function dol_getDefaultFormat(Translate $outputlangs = null)
124 {
125  global $langs;
126 
127  $selected='EUA4';
128  if (!$outputlangs) {
129  $outputlangs=$langs;
130  }
131 
132  if ($outputlangs->defaultlang == 'ca_CA') $selected='CAP4'; // Canada
133  if ($outputlangs->defaultlang == 'en_US') $selected='USLetter'; // US
134  return $selected;
135 }
136 
145 function dol_print_file($langs,$filename,$searchalt=0)
146 {
147  global $conf;
148 
149  // Test if file is in lang directory
150  foreach($langs->dir as $searchdir)
151  {
152  $formfile=($searchdir."/langs/".$langs->defaultlang."/".$filename);
153  dol_syslog('functions2::dol_print_file search file '.$formfile, LOG_DEBUG);
154  if (is_readable($formfile))
155  {
156  $content=file_get_contents($formfile);
157  $isutf8=utf8_check($content);
158  if (! $isutf8 && $conf->file->character_set_client == 'UTF-8') print utf8_encode($content);
159  elseif ($isutf8 && $conf->file->character_set_client == 'ISO-8859-1') print utf8_decode($content);
160  else print $content;
161  return true;
162  }
163  else dol_syslog('functions2::dol_print_file not found', LOG_DEBUG);
164 
165  if ($searchalt) {
166  // Test si fichier dans repertoire de la langue alternative
167  if ($langs->defaultlang != "en_US") $formfilealt = $searchdir."/langs/en_US/".$filename;
168  else $formfilealt = $searchdir."/langs/fr_FR/".$filename;
169  dol_syslog('functions2::dol_print_file search alt file '.$formfilealt, LOG_DEBUG);
170  //print 'getcwd='.getcwd().' htmlfilealt='.$formfilealt.' X '.file_exists(getcwd().'/'.$formfilealt);
171  if (is_readable($formfilealt))
172  {
173  $content=file_get_contents($formfilealt);
174  $isutf8=utf8_check($content);
175  if (! $isutf8 && $conf->file->character_set_client == 'UTF-8') print utf8_encode($content);
176  elseif ($isutf8 && $conf->file->character_set_client == 'ISO-8859-1') print utf8_decode($content);
177  else print $content;
178  return true;
179  }
180  else dol_syslog('functions2::dol_print_file not found', LOG_DEBUG);
181  }
182  }
183 
184  return false;
185 }
186 
195 function dol_print_object_info($object, $usetable=0)
196 {
197  global $langs, $db;
198 
199  // Load translation files required by the page
200  $langs->loadLangs(array('other', 'admin'));
201 
202  include_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
203 
204  $deltadateforserver=getServerTimeZoneInt('now');
205  $deltadateforclient=((int) $_SESSION['dol_tz'] + (int) $_SESSION['dol_dst']);
206  //$deltadateforcompany=((int) $_SESSION['dol_tz'] + (int) $_SESSION['dol_dst']);
207  $deltadateforuser=round($deltadateforclient-$deltadateforserver);
208  //print "x".$deltadateforserver." - ".$deltadateforclient." - ".$deltadateforuser;
209 
210  if ($usetable) print '<table class="border centpercent">';
211 
212  // Import key
213  if (! empty($object->import_key))
214  {
215  if ($usetable) print '<tr><td class="titlefield">';
216  print $langs->trans("ImportedWithSet");
217  if ($usetable) print '</td><td>';
218  else print ': ';
219  print $object->import_key;
220  if ($usetable) print '</td></tr>';
221  else print '<br>';
222  }
223 
224  // User creation (old method using already loaded object and not id is kept for backward compatibility)
225  if (! empty($object->user_creation) || ! empty($object->user_creation_id))
226  {
227  if ($usetable) print '<tr><td class="titlefield">';
228  print $langs->trans("CreatedBy");
229  if ($usetable) print '</td><td>';
230  else print ': ';
231  if (is_object($object->user_creation))
232  {
233  if ($object->user_creation->id) print $object->user_creation->getNomUrl(1, '', 0, 0, 0);
234  else print $langs->trans("Unknown");
235  }
236  else
237  {
238  $userstatic=new User($db);
239  $userstatic->fetch($object->user_creation_id ? $object->user_creation_id : $object->user_creation);
240  if ($userstatic->id) print $userstatic->getNomUrl(1, '', 0, 0, 0);
241  else print $langs->trans("Unknown");
242  }
243  if ($usetable) print '</td></tr>';
244  else print '<br>';
245  }
246 
247  // Date creation
248  if (! empty($object->date_creation))
249  {
250  if ($usetable) print '<tr><td class="titlefield">';
251  print $langs->trans("DateCreation");
252  if ($usetable) print '</td><td>';
253  else print ': ';
254  print dol_print_date($object->date_creation, 'dayhour');
255  if ($deltadateforuser) print ' '.$langs->trans("CurrentHour").' &nbsp; / &nbsp; '.dol_print_date($object->date_creation+($deltadateforuser*3600),"dayhour").' &nbsp;'.$langs->trans("ClientHour");
256  if ($usetable) print '</td></tr>';
257  else print '<br>';
258  }
259 
260  // User change (old method using already loaded object and not id is kept for backward compatibility)
261  if (! empty($object->user_modification) || ! empty($object->user_modification_id))
262  {
263  if ($usetable) print '<tr><td class="titlefield">';
264  print $langs->trans("ModifiedBy");
265  if ($usetable) print '</td><td>';
266  else print ': ';
267  if (is_object($object->user_modification))
268  {
269  if ($object->user_modification->id) print $object->user_modification->getNomUrl(1, '', 0, 0, 0);
270  else print $langs->trans("Unknown");
271  }
272  else
273  {
274  $userstatic=new User($db);
275  $userstatic->fetch($object->user_modification_id ? $object->user_modification_id : $object->user_modification);
276  if ($userstatic->id) print $userstatic->getNomUrl(1, '', 0, 0, 0);
277  else print $langs->trans("Unknown");
278  }
279  if ($usetable) print '</td></tr>';
280  else print '<br>';
281  }
282 
283  // Date change
284  if (! empty($object->date_modification))
285  {
286  if ($usetable) print '<tr><td class="titlefield">';
287  print $langs->trans("DateLastModification");
288  if ($usetable) print '</td><td>';
289  else print ': ';
290  print dol_print_date($object->date_modification, 'dayhour');
291  if ($deltadateforuser) print ' '.$langs->trans("CurrentHour").' &nbsp; / &nbsp; '.dol_print_date($object->date_modification+($deltadateforuser*3600),"dayhour").' &nbsp;'.$langs->trans("ClientHour");
292  if ($usetable) print '</td></tr>';
293  else print '<br>';
294  }
295 
296  // User validation (old method using already loaded object and not id is kept for backward compatibility)
297  if (! empty($object->user_validation) || ! empty($object->user_validation_id))
298  {
299  if ($usetable) print '<tr><td class="titlefield">';
300  print $langs->trans("ValidatedBy");
301  if ($usetable) print '</td><td>';
302  else print ': ';
303  if (is_object($object->user_validation))
304  {
305  if ($object->user_validation->id) print $object->user_validation->getNomUrl(1, '', 0, 0, 0);
306  else print $langs->trans("Unknown");
307  }
308  else
309  {
310  $userstatic=new User($db);
311  $userstatic->fetch($object->user_validation_id ? $object->user_validation_id : $object->user_validation);
312  if ($userstatic->id) print $userstatic->getNomUrl(1, '', 0, 0, 0);
313  else print $langs->trans("Unknown");
314  }
315  if ($usetable) print '</td></tr>';
316  else print '<br>';
317  }
318 
319  // Date validation
320  if (! empty($object->date_validation))
321  {
322  if ($usetable) print '<tr><td class="titlefield">';
323  print $langs->trans("DateValidation");
324  if ($usetable) print '</td><td>';
325  else print ': ';
326  print dol_print_date($object->date_validation, 'dayhour');
327  if ($deltadateforuser) print ' '.$langs->trans("CurrentHour").' &nbsp; / &nbsp; '.dol_print_date($object->date_validation+($deltadateforuser*3600),"dayhour").' &nbsp;'.$langs->trans("ClientHour");
328  if ($usetable) print '</td></tr>';
329  else print '<br>';
330  }
331 
332  // User approve (old method using already loaded object and not id is kept for backward compatibility)
333  if (! empty($object->user_approve) || ! empty($object->user_approve_id))
334  {
335  if ($usetable) print '<tr><td class="titlefield">';
336  print $langs->trans("ApprovedBy");
337  if ($usetable) print '</td><td>';
338  else print ': ';
339  if (is_object($object->user_approve))
340  {
341  if ($object->user_approve->id) print $object->user_approve->getNomUrl(1, '', 0, 0, 0);
342  else print $langs->trans("Unknown");
343  }
344  else
345  {
346  $userstatic=new User($db);
347  $userstatic->fetch($object->user_approve_id ? $object->user_approve_id : $object->user_approve);
348  if ($userstatic->id) print $userstatic->getNomUrl(1, '', 0, 0, 0);
349  else print $langs->trans("Unknown");
350  }
351  if ($usetable) print '</td></tr>';
352  else print '<br>';
353  }
354 
355  // Date approve
356  if (! empty($object->date_approve))
357  {
358  if ($usetable) print '<tr><td class="titlefield">';
359  print $langs->trans("DateApprove");
360  if ($usetable) print '</td><td>';
361  else print ': ';
362  print dol_print_date($object->date_approve, 'dayhour');
363  if ($deltadateforuser) print ' '.$langs->trans("CurrentHour").' &nbsp; / &nbsp; '.dol_print_date($object->date_approve+($deltadateforuser*3600),"dayhour").' &nbsp;'.$langs->trans("ClientHour");
364  if ($usetable) print '</td></tr>';
365  else print '<br>';
366  }
367 
368  // User approve
369  if (! empty($object->user_approve_id2))
370  {
371  if ($usetable) print '<tr><td class="titlefield">';
372  print $langs->trans("ApprovedBy");
373  if ($usetable) print '</td><td>';
374  else print ': ';
375  $userstatic=new User($db);
376  $userstatic->fetch($object->user_approve_id2);
377  if ($userstatic->id) print $userstatic->getNomUrl(1, '', 0, 0, 0);
378  else print $langs->trans("Unknown");
379  if ($usetable) print '</td></tr>';
380  else print '<br>';
381  }
382 
383  // Date approve
384  if (! empty($object->date_approve2))
385  {
386  if ($usetable) print '<tr><td class="titlefield">';
387  print $langs->trans("DateApprove2");
388  if ($usetable) print '</td><td>';
389  else print ': ';
390  print dol_print_date($object->date_approve2, 'dayhour');
391  if ($deltadateforuser) print ' '.$langs->trans("CurrentHour").' &nbsp; / &nbsp; '.dol_print_date($object->date_approve2+($deltadateforuser*3600),"dayhour").' &nbsp;'.$langs->trans("ClientHour");
392  if ($usetable) print '</td></tr>';
393  else print '<br>';
394  }
395 
396  // User close
397  if (! empty($object->user_cloture))
398  {
399  if ($usetable) print '<tr><td class="titlefield">';
400  print $langs->trans("ClosedBy");
401  if ($usetable) print '</td><td>';
402  else print ': ';
403  if (is_object($object->user_cloture))
404  {
405  if ($object->user_cloture->id) print $object->user_cloture->getNomUrl(1, '', 0, 0, 0);
406  else print $langs->trans("Unknown");
407  }
408  else
409  {
410  $userstatic=new User($db);
411  $userstatic->fetch($object->user_cloture);
412  if ($userstatic->id) print $userstatic->getNomUrl(1, '', 0, 0, 0);
413  else print $langs->trans("Unknown");
414  }
415  if ($usetable) print '</td></tr>';
416  else print '<br>';
417  }
418 
419  // Date close
420  if (! empty($object->date_cloture))
421  {
422  if ($usetable) print '<tr><td class="titlefield">';
423  print $langs->trans("DateClosing");
424  if ($usetable) print '</td><td>';
425  else print ': ';
426  print dol_print_date($object->date_cloture, 'dayhour');
427  if ($deltadateforuser) print ' '.$langs->trans("CurrentHour").' &nbsp; / &nbsp; '.dol_print_date($object->date_cloture+($deltadateforuser*3600),"dayhour").' &nbsp;'.$langs->trans("ClientHour");
428  if ($usetable) print '</td></tr>';
429  else print '<br>';
430  }
431 
432  // User conciliate
433  if (! empty($object->user_rappro))
434  {
435  if ($usetable) print '<tr><td class="titlefield">';
436  print $langs->trans("ConciliatedBy");
437  if ($usetable) print '</td><td>';
438  else print ': ';
439  if (is_object($object->user_rappro))
440  {
441  if ($object->user_rappro->id) print $object->user_rappro->getNomUrl(1, '', 0, 0, 0);
442  else print $langs->trans("Unknown");
443  }
444  else
445  {
446  $userstatic=new User($db);
447  $userstatic->fetch($object->user_rappro);
448  if ($userstatic->id) print $userstatic->getNomUrl(1, '', 0, 0, 0);
449  else print $langs->trans("Unknown");
450  }
451  if ($usetable) print '</td></tr>';
452  else print '<br>';
453  }
454 
455  // Date conciliate
456  if (! empty($object->date_rappro))
457  {
458  if ($usetable) print '<tr><td class="titlefield">';
459  print $langs->trans("DateConciliating");
460  if ($usetable) print '</td><td>';
461  else print ': ';
462  print dol_print_date($object->date_rappro, 'dayhour');
463  if ($deltadateforuser) print ' '.$langs->trans("CurrentHour").' &nbsp; / &nbsp; '.dol_print_date($object->date_rappro+($deltadateforuser*3600),"dayhour").' &nbsp;'.$langs->trans("ClientHour");
464  if ($usetable) print '</td></tr>';
465  else print '<br>';
466  }
467 
468  // Date send
469  if (! empty($object->date_envoi))
470  {
471  if ($usetable) print '<tr><td class="titlefield">';
472  print $langs->trans("DateLastSend");
473  if ($usetable) print '</td><td>';
474  else print ': ';
475  print dol_print_date($object->date_envoi, 'dayhour');
476  if ($deltadateforuser) print ' '.$langs->trans("CurrentHour").' &nbsp; / &nbsp; '.dol_print_date($object->date_envoi+($deltadateforuser*3600),"dayhour").' &nbsp;'.$langs->trans("ClientHour");
477  if ($usetable) print '</td></tr>';
478  else print '<br>';
479  }
480 
481  if ($usetable) print '</table>';
482 }
483 
484 
493 function dolAddEmailTrackId($email, $trackingid)
494 {
495  $tmp=explode('@',$email);
496  return $tmp[0].'+'.$trackingid.'@'.(isset($tmp[1])?$tmp[1]:'');
497 }
498 
505 function isValidMailDomain($mail)
506 {
507  list($user, $domain) = explode("@", $mail, 2);
508  if (checkdnsrr($domain, "MX"))
509  {
510  return true;
511  }
512  else
513  {
514  return false;
515  }
516 }
517 
531 function isValidUrl($url,$http=0,$pass=0,$port=0,$path=0,$query=0,$anchor=0)
532 {
533  $ValidUrl = 0;
534  $urlregex = '';
535 
536  // SCHEME
537  if ($http) $urlregex .= "^(http:\/\/|https:\/\/)";
538 
539  // USER AND PASS
540  if ($pass) $urlregex .= "([a-z0-9+!*(),;?&=\$_.-]+(\:[a-z0-9+!*(),;?&=\$_.-]+)?@)";
541 
542  // HOSTNAME OR IP
543  //$urlregex .= "[a-z0-9+\$_-]+(\.[a-z0-9+\$_-]+)*"; // x allowed (ex. http://localhost, http://routerlogin)
544  //$urlregex .= "[a-z0-9+\$_-]+(\.[a-z0-9+\$_-]+)+"; // x.x
545  $urlregex .= "([a-z0-9+\$_\\\:-])+(\.[a-z0-9+\$_-][a-z0-9+\$_-]+)*"; // x ou x.xx (2 x ou plus)
546  //use only one of the above
547 
548  // PORT
549  if ($port) $urlregex .= "(\:[0-9]{2,5})";
550  // PATH
551  if ($path) $urlregex .= "(\/([a-z0-9+\$_-]\.?)+)*\/";
552  // GET Query
553  if ($query) $urlregex .= "(\?[a-z+&\$_.-][a-z0-9;:@\/&%=+\$_.-]*)";
554  // ANCHOR
555  if ($anchor) $urlregex .= "(#[a-z_.-][a-z0-9+\$_.-]*)$";
556 
557  // check
558  if (preg_match('/'.$urlregex.'/i', $url))
559  {
560  $ValidUrl = 1;
561  }
562  //print $urlregex.' - '.$url.' - '.$ValidUrl;
563 
564  return $ValidUrl;
565 }
566 
574 function clean_url($url,$http=1)
575 {
576  // Fixed by Matelli (see http://matelli.fr/showcases/patchs-dolibarr/fix-cleaning-url.html)
577  // To include the minus sign in a char class, we must not escape it but put it at the end of the class
578  // Also, there's no need of escape a dot sign in a class
579  if (preg_match('/^(https?:[\\/]+)?([0-9A-Z.-]+\.[A-Z]{2,4})(:[0-9]+)?/i',$url,$regs))
580  {
581  $proto=$regs[1];
582  $domain=$regs[2];
583  $port=isset($regs[3])?$regs[3]:'';
584  //print $url." -> ".$proto." - ".$domain." - ".$port;
585  //$url = dol_string_nospecial(trim($url));
586  $url = trim($url);
587 
588  // Si http: defini on supprime le http (Si https on ne supprime pas)
589  $newproto=$proto;
590  if ($http==0)
591  {
592  if (preg_match('/^http:[\\/]+/i',$url))
593  {
594  $url = preg_replace('/^http:[\\/]+/i','',$url);
595  $newproto = '';
596  }
597  }
598 
599  // On passe le nom de domaine en minuscule
600  $CleanUrl = preg_replace('/^'.preg_quote($proto.$domain,'/').'/i', $newproto.strtolower($domain), $url);
601 
602  return $CleanUrl;
603  }
604  else return $url;
605 }
606 
607 
608 
620 function dolObfuscateEmail($mail, $replace="*", $nbreplace=8, $nbdisplaymail=4, $nbdisplaydomain=3, $displaytld=true)
621 {
622  if(!isValidEmail($mail))return '';
623  $tab = explode('@', $mail);
624  $tab2 = explode('.',$tab[1]);
625  $string_replace = '';
626  $mail_name = $tab[0];
627  $mail_domaine = $tab2[0];
628  $mail_tld = '';
629 
630  $nbofelem = count($tab2);
631  for($i=1; $i < $nbofelem && $displaytld; $i++)
632  {
633  $mail_tld .= '.'.$tab2[$i];
634  }
635 
636  for($i=0; $i < $nbreplace; $i++){
637  $string_replace .= $replace;
638  }
639 
640  if(strlen($mail_name) > $nbdisplaymail){
641  $mail_name = substr($mail_name, 0, $nbdisplaymail);
642  }
643 
644  if(strlen($mail_domaine) > $nbdisplaydomain){
645  $mail_domaine = substr($mail_domaine, strlen($mail_domaine)-$nbdisplaydomain);
646  }
647 
648  return $mail_name . $string_replace . $mail_domaine . $mail_tld;
649 }
650 
651 
661 function array2tr($data,$troptions='',$tdoptions='')
662 {
663  $text = '<tr '.$troptions.'>' ;
664  foreach($data as $key => $item){
665  $text.= '<td '.$tdoptions.'>'.$item.'</td>' ;
666  }
667  $text.= '</tr>' ;
668  return $text ;
669 }
670 
681 function array2table($data,$tableMarkup=1,$tableoptions='',$troptions='',$tdoptions='')
682 {
683  $text='' ;
684  if($tableMarkup) $text = '<table '.$tableoptions.'>' ;
685  foreach($data as $key => $item){
686  if(is_array($item)){
687  $text.=array2tr($item,$troptions,$tdoptions);
688  } else {
689  $text.= '<tr '.$troptions.'>' ;
690  $text.= '<td '.$tdoptions.'>'.$key.'</td>' ;
691  $text.= '<td '.$tdoptions.'>'.$item.'</td>' ;
692  $text.= '</tr>' ;
693  }
694  }
695  if($tableMarkup) $text.= '</table>' ;
696  return $text ;
697 }
698 
715 function get_next_value($db,$mask,$table,$field,$where='',$objsoc='',$date='',$mode='next', $bentityon=true, $objuser=null, $forceentity=null)
716 {
717  global $conf,$user;
718 
719  if (! is_object($objsoc)) $valueforccc=$objsoc;
720  else if ($table == "commande_fournisseur" || $table == "facture_fourn" ) $valueforccc=$objsoc->code_fournisseur;
721  else $valueforccc=$objsoc->code_client;
722 
723  $sharetable = $table;
724  if ($table == 'facture' || $table == 'invoice') $sharetable = 'invoicenumber'; // for getEntity function
725 
726  // Clean parameters
727  if ($date == '') $date=dol_now(); // We use local year and month of PHP server to search numbers
728  // but we should use local year and month of user
729 
730  // For debugging
731  //dol_syslog("mask=".$mask, LOG_DEBUG);
732  //include_once(DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php');
733  //$mask='FA{yy}{mm}-{0000@99}';
734  //$date=dol_mktime(12, 0, 0, 1, 1, 1900);
735  //$date=dol_stringtotime('20130101');
736 
737  $hasglobalcounter=false;
738  // Extract value for mask counter, mask raz and mask offset
739  if (preg_match('/\{(0+)([@\+][0-9\-\+\=]+)?([@\+][0-9\-\+\=]+)?\}/i',$mask,$reg))
740  {
741  $masktri=$reg[1].(! empty($reg[2])?$reg[2]:'').(! empty($reg[3])?$reg[3]:'');
742  $maskcounter=$reg[1];
743  $hasglobalcounter=true;
744  }
745  else
746  {
747  // setting some defaults so the rest of the code won't fail if there is a third party counter
748  $masktri='00000';
749  $maskcounter='00000';
750  }
751 
752  $maskraz=-1;
753  $maskoffset=0;
754  $resetEveryMonth=false;
755  if (dol_strlen($maskcounter) < 3 && empty($conf->global->MAIN_COUNTER_WITH_LESS_3_DIGITS)) return 'ErrorCounterMustHaveMoreThan3Digits';
756 
757  // Extract value for third party mask counter
758  if (preg_match('/\{(c+)(0*)\}/i',$mask,$regClientRef))
759  {
760  $maskrefclient=$regClientRef[1].$regClientRef[2];
761  $maskrefclient_maskclientcode=$regClientRef[1];
762  $maskrefclient_maskcounter=$regClientRef[2];
763  $maskrefclient_maskoffset=0; //default value of maskrefclient_counter offset
764  $maskrefclient_clientcode=substr($valueforccc,0,dol_strlen($maskrefclient_maskclientcode));//get n first characters of client code where n is length in mask
765  $maskrefclient_clientcode=str_pad($maskrefclient_clientcode,dol_strlen($maskrefclient_maskclientcode),"#",STR_PAD_RIGHT);//padding maskrefclient_clientcode for having exactly n characters in maskrefclient_clientcode
766  $maskrefclient_clientcode=dol_string_nospecial($maskrefclient_clientcode);//sanitize maskrefclient_clientcode for sql insert and sql select like
767  if (dol_strlen($maskrefclient_maskcounter) > 0 && dol_strlen($maskrefclient_maskcounter) < 3) return 'ErrorCounterMustHaveMoreThan3Digits';
768  }
769  else $maskrefclient='';
770 
771  // fail if there is neither a global nor a third party counter
772  if (! $hasglobalcounter && ($maskrefclient_maskcounter == ''))
773  {
774  return 'ErrorBadMask';
775  }
776 
777  // Extract value for third party type
778  if (preg_match('/\{(t+)\}/i',$mask,$regType))
779  {
780  $masktype=$regType[1];
781  $masktype_value=substr(preg_replace('/^TE_/','',$objsoc->typent_code),0,dol_strlen($regType[1]));// get n first characters of thirdpaty typent_code (where n is length in mask)
782  $masktype_value=str_pad($masktype_value,dol_strlen($regType[1]),"#",STR_PAD_RIGHT); // we fill on right with # to have same number of char than into mask
783  }
784  else
785  {
786  $masktype='';
787  $masktype_value='';
788  }
789 
790  // Extract value for user
791  if (preg_match('/\{(u+)\}/i',$mask,$regType))
792  {
793  $lastname = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
794  if (is_object($objuser)) $lastname = $objuser->lastname;
795 
796  $maskuser=$regType[1];
797  $maskuser_value=substr($lastname,0,dol_strlen($regType[1]));// get n first characters of user firstname (where n is length in mask)
798  $maskuser_value=str_pad($maskuser_value,dol_strlen($regType[1]),"#",STR_PAD_RIGHT); // we fill on right with # to have same number of char than into mask
799  }
800  else
801  {
802  $maskuser='';
803  $maskuser_value='';
804  }
805 
806  // Personalized field {XXX-1} à {XXX-9}
807  $maskperso=array();
808  $maskpersonew=array();
809  $tmpmask=$mask;
810  while (preg_match('/\{([A-Z]+)\-([1-9])\}/',$tmpmask,$regKey))
811  {
812  $maskperso[$regKey[1]]='{'.$regKey[1].'-'.$regKey[2].'}';
813  $maskpersonew[$regKey[1]]=str_pad('', $regKey[2], '_', STR_PAD_RIGHT);
814  $tmpmask=preg_replace('/\{'.$regKey[1].'\-'.$regKey[2].'\}/i', $maskpersonew[$regKey[1]], $tmpmask);
815  }
816 
817  if (strstr($mask,'user_extra_'))
818  {
819  $start = "{user_extra_";
820  $end = "\}";
821  $extra= get_string_between($mask, "user_extra_", "}");
822  if(!empty($user->array_options['options_'.$extra])){
823  $mask = preg_replace('#('.$start.')(.*?)('.$end.')#si', $user->array_options['options_'.$extra], $mask);
824  }
825  }
826  $maskwithonlyymcode=$mask;
827  $maskwithonlyymcode=preg_replace('/\{(0+)([@\+][0-9\-\+\=]+)?([@\+][0-9\-\+\=]+)?\}/i',$maskcounter,$maskwithonlyymcode);
828  $maskwithonlyymcode=preg_replace('/\{dd\}/i','dd',$maskwithonlyymcode);
829  $maskwithonlyymcode=preg_replace('/\{(c+)(0*)\}/i',$maskrefclient,$maskwithonlyymcode);
830  $maskwithonlyymcode=preg_replace('/\{(t+)\}/i',$masktype_value,$maskwithonlyymcode);
831  $maskwithonlyymcode=preg_replace('/\{(u+)\}/i',$maskuser_value,$maskwithonlyymcode);
832  foreach($maskperso as $key => $val)
833  {
834  $maskwithonlyymcode=preg_replace('/'.preg_quote($val,'/').'/i', $maskpersonew[$key], $maskwithonlyymcode);
835  }
836  $maskwithnocode=$maskwithonlyymcode;
837  $maskwithnocode=preg_replace('/\{yyyy\}/i','yyyy',$maskwithnocode);
838  $maskwithnocode=preg_replace('/\{yy\}/i','yy',$maskwithnocode);
839  $maskwithnocode=preg_replace('/\{y\}/i','y',$maskwithnocode);
840  $maskwithnocode=preg_replace('/\{mm\}/i','mm',$maskwithnocode);
841  // Now maskwithnocode = 0000ddmmyyyyccc for example
842  // and maskcounter = 0000 for example
843  //print "maskwithonlyymcode=".$maskwithonlyymcode." maskwithnocode=".$maskwithnocode."\n<br>";
844  //var_dump($reg);
845 
846  // If an offset is asked
847  if (! empty($reg[2]) && preg_match('/^\+/',$reg[2])) $maskoffset=preg_replace('/^\+/','',$reg[2]);
848  if (! empty($reg[3]) && preg_match('/^\+/',$reg[3])) $maskoffset=preg_replace('/^\+/','',$reg[3]);
849 
850  // Define $sqlwhere
851  $sqlwhere='';
852  $yearoffset=0; // Use year of current $date by default
853  $yearoffsettype=false; // false: no reset, 0,-,=,+: reset at offset SOCIETE_FISCAL_MONTH_START, x=reset at offset x
854 
855  // If a restore to zero after a month is asked we check if there is already a value for this year.
856  if (! empty($reg[2]) && preg_match('/^@/',$reg[2])) $yearoffsettype = preg_replace('/^@/','',$reg[2]);
857  if (! empty($reg[3]) && preg_match('/^@/',$reg[3])) $yearoffsettype = preg_replace('/^@/','',$reg[3]);
858 
859  //print "yearoffset=".$yearoffset." yearoffsettype=".$yearoffsettype;
860  if (is_numeric($yearoffsettype) && $yearoffsettype >= 1)
861  $maskraz=$yearoffsettype; // For backward compatibility
862  else if ($yearoffsettype === '0' || (! empty($yearoffsettype) && ! is_numeric($yearoffsettype) && $conf->global->SOCIETE_FISCAL_MONTH_START > 1))
863  $maskraz = $conf->global->SOCIETE_FISCAL_MONTH_START;
864  //print "maskraz=".$maskraz; // -1=no reset
865 
866  if ($maskraz > 0) { // A reset is required
867  if ($maskraz == 99) {
868  $maskraz = date('m', $date);
869  $resetEveryMonth = true;
870  }
871  if ($maskraz > 12) return 'ErrorBadMaskBadRazMonth';
872 
873  // Define posy, posm and reg
874  if ($maskraz > 1) // if reset is not first month, we need month and year into mask
875  {
876  if (preg_match('/^(.*)\{(y+)\}\{(m+)\}/i',$maskwithonlyymcode,$reg)) { $posy=2; $posm=3; }
877  elseif (preg_match('/^(.*)\{(m+)\}\{(y+)\}/i',$maskwithonlyymcode,$reg)) { $posy=3; $posm=2; }
878  else return 'ErrorCantUseRazInStartedYearIfNoYearMonthInMask';
879 
880  if (dol_strlen($reg[$posy]) < 2) return 'ErrorCantUseRazWithYearOnOneDigit';
881  }
882  else // if reset is for a specific month in year, we need year
883  {
884  if (preg_match('/^(.*)\{(m+)\}\{(y+)\}/i',$maskwithonlyymcode,$reg)) { $posy=3; $posm=2; }
885  else if (preg_match('/^(.*)\{(y+)\}\{(m+)\}/i',$maskwithonlyymcode,$reg)) { $posy=2; $posm=3; }
886  else if (preg_match('/^(.*)\{(y+)\}/i',$maskwithonlyymcode,$reg)) { $posy=2; $posm=0; }
887  else return 'ErrorCantUseRazIfNoYearInMask';
888  }
889  // Define length
890  $yearlen = $posy?dol_strlen($reg[$posy]):0;
891  $monthlen = $posm?dol_strlen($reg[$posm]):0;
892  // Define pos
893  $yearpos = (dol_strlen($reg[1])+1);
894  $monthpos = ($yearpos+$yearlen);
895  if ($posy == 3 && $posm == 2) { // if month is before year
896  $monthpos = (dol_strlen($reg[1])+1);
897  $yearpos = ($monthpos+$monthlen);
898  }
899  //print "xxx ".$maskwithonlyymcode." maskraz=".$maskraz." posy=".$posy." yearlen=".$yearlen." yearpos=".$yearpos." posm=".$posm." monthlen=".$monthlen." monthpos=".$monthpos." yearoffsettype=".$yearoffsettype." resetEveryMonth=".$resetEveryMonth."\n";
900 
901  // Define $yearcomp and $monthcomp (that will be use in the select where to search max number)
902  $monthcomp=$maskraz;
903  $yearcomp=0;
904 
905  if (! empty($yearoffsettype) && ! is_numeric($yearoffsettype) && $yearoffsettype != '=') // $yearoffsettype is - or +
906  {
907  $currentyear=date("Y", $date);
908  $fiscaldate=dol_mktime('0','0','0',$maskraz,'1',$currentyear);
909  $newyeardate=dol_mktime('0','0','0','1','1',$currentyear);
910  $nextnewyeardate=dol_mktime('0','0','0','1','1',$currentyear+1);
911  //echo 'currentyear='.$currentyear.' date='.dol_print_date($date, 'day').' fiscaldate='.dol_print_date($fiscaldate, 'day').'<br>';
912 
913  // If after or equal of current fiscal date
914  if ($date >= $fiscaldate)
915  {
916  // If before of next new year date
917  if ($date < $nextnewyeardate && $yearoffsettype == '+') $yearoffset=1;
918  }
919  // If after or equal of current new year date
920  else if ($date >= $newyeardate && $yearoffsettype == '-') $yearoffset=-1;
921  }
922  // For backward compatibility
923  else if (date("m",$date) < $maskraz && empty($resetEveryMonth)) { $yearoffset=-1; } // If current month lower that month of return to zero, year is previous year
924 
925  if ($yearlen == 4) $yearcomp=sprintf("%04d",date("Y",$date)+$yearoffset);
926  elseif ($yearlen == 2) $yearcomp=sprintf("%02d",date("y",$date)+$yearoffset);
927  elseif ($yearlen == 1) $yearcomp=substr(date("y",$date),2,1)+$yearoffset;
928  if ($monthcomp > 1 && empty($resetEveryMonth)) // Test with month is useless if monthcomp = 0 or 1 (0 is same as 1) (regis: $monthcomp can't equal 0)
929  {
930  if ($yearlen == 4) $yearcomp1=sprintf("%04d",date("Y",$date)+$yearoffset+1);
931  elseif ($yearlen == 2) $yearcomp1=sprintf("%02d",date("y",$date)+$yearoffset+1);
932 
933  $sqlwhere.="(";
934  $sqlwhere.=" (SUBSTRING(".$field.", ".$yearpos.", ".$yearlen.") = '".$yearcomp."'";
935  $sqlwhere.=" AND SUBSTRING(".$field.", ".$monthpos.", ".$monthlen.") >= '".str_pad($monthcomp, $monthlen, '0', STR_PAD_LEFT)."')";
936  $sqlwhere.=" OR";
937  $sqlwhere.=" (SUBSTRING(".$field.", ".$yearpos.", ".$yearlen.") = '".$yearcomp1."'";
938  $sqlwhere.=" AND SUBSTRING(".$field.", ".$monthpos.", ".$monthlen.") < '".str_pad($monthcomp, $monthlen, '0', STR_PAD_LEFT)."') ";
939  $sqlwhere.=')';
940  }
941  else if ($resetEveryMonth)
942  {
943  $sqlwhere.="(SUBSTRING(".$field.", ".$yearpos.", ".$yearlen.") = '".$yearcomp."'";
944  $sqlwhere.=" AND SUBSTRING(".$field.", ".$monthpos.", ".$monthlen.") = '".str_pad($monthcomp, $monthlen, '0', STR_PAD_LEFT)."')";
945  }
946  else // reset is done on january
947  {
948  $sqlwhere.='(SUBSTRING('.$field.', '.$yearpos.', '.$yearlen.") = '".$yearcomp."')";
949  }
950  }
951  //print "sqlwhere=".$sqlwhere." yearcomp=".$yearcomp."<br>\n"; // sqlwhere and yearcomp defined only if we ask a reset
952  //print "masktri=".$masktri." maskcounter=".$maskcounter." maskraz=".$maskraz." maskoffset=".$maskoffset."<br>\n";
953 
954  // Define $sqlstring
955  if (function_exists('mb_strrpos'))
956  {
957  $posnumstart=mb_strrpos($maskwithnocode,$maskcounter, 'UTF-8');
958  }
959  else
960  {
961  $posnumstart=strrpos($maskwithnocode,$maskcounter);
962  } // Pos of counter in final string (from 0 to ...)
963  if ($posnumstart < 0) return 'ErrorBadMaskFailedToLocatePosOfSequence';
964  $sqlstring='SUBSTRING('.$field.', '.($posnumstart+1).', '.dol_strlen($maskcounter).')';
965 
966  // Define $maskLike
967  $maskLike = dol_string_nospecial($mask);
968  $maskLike = str_replace("%","_",$maskLike);
969  // Replace protected special codes with matching number of _ as wild card caracter
970  $maskLike = preg_replace('/\{yyyy\}/i','____',$maskLike);
971  $maskLike = preg_replace('/\{yy\}/i','__',$maskLike);
972  $maskLike = preg_replace('/\{y\}/i','_',$maskLike);
973  $maskLike = preg_replace('/\{mm\}/i','__',$maskLike);
974  $maskLike = preg_replace('/\{dd\}/i','__',$maskLike);
975  $maskLike = str_replace(dol_string_nospecial('{'.$masktri.'}'),str_pad("",dol_strlen($maskcounter),"_"),$maskLike);
976  if ($maskrefclient) $maskLike = str_replace(dol_string_nospecial('{'.$maskrefclient.'}'),str_pad("",dol_strlen($maskrefclient),"_"),$maskLike);
977  if ($masktype) $maskLike = str_replace(dol_string_nospecial('{'.$masktype.'}'),$masktype_value,$maskLike);
978  if ($maskuser) $maskLike = str_replace(dol_string_nospecial('{'.$maskuser.'}'),$maskuser_value,$maskLike);
979  foreach($maskperso as $key => $val)
980  {
981  $maskLike = str_replace(dol_string_nospecial($maskperso[$key]),$maskpersonew[$key],$maskLike);
982  }
983 
984  // Get counter in database
985  $counter=0;
986  $sql = "SELECT MAX(".$sqlstring.") as val";
987  $sql.= " FROM ".MAIN_DB_PREFIX.$table;
988  $sql.= " WHERE ".$field." LIKE '".$maskLike."'";
989  $sql.= " AND ".$field." NOT LIKE '(PROV%)'";
990  if ($bentityon) // only if entity enable
991  $sql.= " AND entity IN (".getEntity($sharetable).")";
992  else if (! empty($forceentity))
993  $sql.= " AND entity IN (".$forceentity.")";
994  if ($where) $sql.=$where;
995  if ($sqlwhere) $sql.=' AND '.$sqlwhere;
996 
997  //print $sql.'<br>';
998  dol_syslog("functions2::get_next_value mode=".$mode."", LOG_DEBUG);
999  $resql=$db->query($sql);
1000  if ($resql)
1001  {
1002  $obj = $db->fetch_object($resql);
1003  $counter = $obj->val;
1004  }
1005  else dol_print_error($db);
1006 
1007  // Check if we must force counter to maskoffset
1008  if (empty($counter)) $counter=$maskoffset;
1009  else if (preg_match('/[^0-9]/i',$counter))
1010  {
1011  $counter=0;
1012  dol_syslog("Error, the last counter found is '".$counter."' so is not a numeric value. We will restart to 1.", LOG_ERR);
1013  }
1014  else if ($counter < $maskoffset && empty($conf->global->MAIN_NUMBERING_OFFSET_ONLY_FOR_FIRST)) $counter=$maskoffset;
1015 
1016  if ($mode == 'last') // We found value for counter = last counter value. Now need to get corresponding ref of invoice.
1017  {
1018  $counterpadded=str_pad($counter,dol_strlen($maskcounter),"0",STR_PAD_LEFT);
1019 
1020  // Define $maskLike
1021  $maskLike = dol_string_nospecial($mask);
1022  $maskLike = str_replace("%","_",$maskLike);
1023  // Replace protected special codes with matching number of _ as wild card caracter
1024  $maskLike = preg_replace('/\{yyyy\}/i','____',$maskLike);
1025  $maskLike = preg_replace('/\{yy\}/i','__',$maskLike);
1026  $maskLike = preg_replace('/\{y\}/i','_',$maskLike);
1027  $maskLike = preg_replace('/\{mm\}/i','__',$maskLike);
1028  $maskLike = preg_replace('/\{dd\}/i','__',$maskLike);
1029  $maskLike = str_replace(dol_string_nospecial('{'.$masktri.'}'),$counterpadded,$maskLike);
1030  if ($maskrefclient) $maskLike = str_replace(dol_string_nospecial('{'.$maskrefclient.'}'),str_pad("",dol_strlen($maskrefclient),"_"),$maskLike);
1031  if ($masktype) $maskLike = str_replace(dol_string_nospecial('{'.$masktype.'}'),$masktype_value,$maskLike);
1032  if ($maskuser) $maskLike = str_replace(dol_string_nospecial('{'.$maskuser.'}'),$maskuser_value,$maskLike);
1033 
1034  $ref='';
1035  $sql = "SELECT ".$field." as ref";
1036  $sql.= " FROM ".MAIN_DB_PREFIX.$table;
1037  $sql.= " WHERE ".$field." LIKE '".$maskLike."'";
1038  $sql.= " AND ".$field." NOT LIKE '%PROV%'";
1039  if ($bentityon) // only if entity enable
1040  $sql.= " AND entity IN (".getEntity($sharetable).")";
1041  else if (! empty($forceentity))
1042  $sql.= " AND entity IN (".$forceentity.")";
1043  if ($where) $sql.=$where;
1044  if ($sqlwhere) $sql.=' AND '.$sqlwhere;
1045 
1046  dol_syslog("functions2::get_next_value mode=".$mode."", LOG_DEBUG);
1047  $resql=$db->query($sql);
1048  if ($resql)
1049  {
1050  $obj = $db->fetch_object($resql);
1051  if ($obj) $ref = $obj->ref;
1052  }
1053  else dol_print_error($db);
1054 
1055  $numFinal=$ref;
1056  }
1057  else if ($mode == 'next')
1058  {
1059  $counter++;
1060 
1061  // If value for $counter has a length higher than $maskcounter chars
1062  if ($counter >= pow(10, dol_strlen($maskcounter)))
1063  {
1064  $counter='ErrorMaxNumberReachForThisMask';
1065  }
1066 
1067  if (! empty($maskrefclient_maskcounter))
1068  {
1069  //print "maskrefclient_maskcounter=".$maskrefclient_maskcounter." maskwithnocode=".$maskwithnocode." maskrefclient=".$maskrefclient."\n<br>";
1070 
1071  // Define $sqlstring
1072  $maskrefclient_posnumstart=strpos($maskwithnocode,$maskrefclient_maskcounter,strpos($maskwithnocode,$maskrefclient)); // Pos of counter in final string (from 0 to ...)
1073  if ($maskrefclient_posnumstart <= 0) return 'ErrorBadMask';
1074  $maskrefclient_sqlstring='SUBSTRING('.$field.', '.($maskrefclient_posnumstart+1).', '.dol_strlen($maskrefclient_maskcounter).')';
1075  //print "x".$sqlstring;
1076 
1077  // Define $maskrefclient_maskLike
1078  $maskrefclient_maskLike = dol_string_nospecial($mask);
1079  $maskrefclient_maskLike = str_replace("%","_",$maskrefclient_maskLike);
1080  // Replace protected special codes with matching number of _ as wild card caracter
1081  $maskrefclient_maskLike = str_replace(dol_string_nospecial('{yyyy}'),'____',$maskrefclient_maskLike);
1082  $maskrefclient_maskLike = str_replace(dol_string_nospecial('{yy}'),'__',$maskrefclient_maskLike);
1083  $maskrefclient_maskLike = str_replace(dol_string_nospecial('{y}'),'_',$maskrefclient_maskLike);
1084  $maskrefclient_maskLike = str_replace(dol_string_nospecial('{mm}'),'__',$maskrefclient_maskLike);
1085  $maskrefclient_maskLike = str_replace(dol_string_nospecial('{dd}'),'__',$maskrefclient_maskLike);
1086  $maskrefclient_maskLike = str_replace(dol_string_nospecial('{'.$masktri.'}'),str_pad("",dol_strlen($maskcounter),"_"),$maskrefclient_maskLike);
1087  $maskrefclient_maskLike = str_replace(dol_string_nospecial('{'.$maskrefclient.'}'),$maskrefclient_clientcode.str_pad("",dol_strlen($maskrefclient_maskcounter),"_"),$maskrefclient_maskLike);
1088 
1089  // Get counter in database
1090  $maskrefclient_counter=0;
1091  $maskrefclient_sql = "SELECT MAX(".$maskrefclient_sqlstring.") as val";
1092  $maskrefclient_sql.= " FROM ".MAIN_DB_PREFIX.$table;
1093  //$sql.= " WHERE ".$field." not like '(%'";
1094  $maskrefclient_sql.= " WHERE ".$field." LIKE '".$maskrefclient_maskLike."'";
1095  if ($bentityon) // only if entity enable
1096  $maskrefclient_sql.= " AND entity IN (".getEntity($sharetable).")";
1097  else if (! empty($forceentity))
1098  $sql.= " AND entity IN (".$forceentity.")";
1099  if ($where) $maskrefclient_sql.=$where; //use the same optional where as general mask
1100  if ($sqlwhere) $maskrefclient_sql.=' AND '.$sqlwhere; //use the same sqlwhere as general mask
1101  $maskrefclient_sql.=' AND (SUBSTRING('.$field.', '.(strpos($maskwithnocode,$maskrefclient)+1).', '.dol_strlen($maskrefclient_maskclientcode).")='".$maskrefclient_clientcode."')";
1102 
1103  dol_syslog("functions2::get_next_value maskrefclient", LOG_DEBUG);
1104  $maskrefclient_resql=$db->query($maskrefclient_sql);
1105  if ($maskrefclient_resql)
1106  {
1107  $maskrefclient_obj = $db->fetch_object($maskrefclient_resql);
1108  $maskrefclient_counter = $maskrefclient_obj->val;
1109  }
1110  else dol_print_error($db);
1111 
1112  if (empty($maskrefclient_counter) || preg_match('/[^0-9]/i',$maskrefclient_counter)) $maskrefclient_counter=$maskrefclient_maskoffset;
1113  $maskrefclient_counter++;
1114  }
1115 
1116  // Build numFinal
1117  $numFinal = $mask;
1118 
1119  // We replace special codes except refclient
1120  if (! empty($yearoffsettype) && ! is_numeric($yearoffsettype) && $yearoffsettype != '=') // yearoffsettype is - or +, so we don't want current year
1121  {
1122  $numFinal = preg_replace('/\{yyyy\}/i',date("Y",$date)+$yearoffset, $numFinal);
1123  $numFinal = preg_replace('/\{yy\}/i', date("y",$date)+$yearoffset, $numFinal);
1124  $numFinal = preg_replace('/\{y\}/i', substr(date("y",$date),1,1)+$yearoffset, $numFinal);
1125  }
1126  else // we want yyyy to be current year
1127  {
1128  $numFinal = preg_replace('/\{yyyy\}/i',date("Y",$date), $numFinal);
1129  $numFinal = preg_replace('/\{yy\}/i', date("y",$date), $numFinal);
1130  $numFinal = preg_replace('/\{y\}/i', substr(date("y",$date),1,1), $numFinal);
1131  }
1132  $numFinal = preg_replace('/\{mm\}/i', date("m",$date), $numFinal);
1133  $numFinal = preg_replace('/\{dd\}/i', date("d",$date), $numFinal);
1134 
1135  // Now we replace the counter
1136  $maskbefore='{'.$masktri.'}';
1137  $maskafter=str_pad($counter,dol_strlen($maskcounter),"0",STR_PAD_LEFT);
1138  //print 'x'.$maskbefore.'-'.$maskafter.'y';
1139  $numFinal = str_replace($maskbefore,$maskafter,$numFinal);
1140 
1141  // Now we replace the refclient
1142  if ($maskrefclient)
1143  {
1144  //print "maskrefclient=".$maskrefclient." maskwithonlyymcode=".$maskwithonlyymcode." maskwithnocode=".$maskwithnocode."\n<br>";
1145  $maskrefclient_maskbefore='{'.$maskrefclient.'}';
1146  $maskrefclient_maskafter=$maskrefclient_clientcode.str_pad($maskrefclient_counter,dol_strlen($maskrefclient_maskcounter),"0",STR_PAD_LEFT);
1147  $numFinal = str_replace($maskrefclient_maskbefore,$maskrefclient_maskafter,$numFinal);
1148  }
1149 
1150  // Now we replace the type
1151  if ($masktype)
1152  {
1153  $masktype_maskbefore='{'.$masktype.'}';
1154  $masktype_maskafter=$masktype_value;
1155  $numFinal = str_replace($masktype_maskbefore,$masktype_maskafter,$numFinal);
1156  }
1157 
1158  // Now we replace the user
1159  if ($maskuser)
1160  {
1161  $maskuser_maskbefore='{'.$maskuser.'}';
1162  $maskuser_maskafter=$maskuser_value;
1163  $numFinal = str_replace($maskuser_maskbefore,$maskuser_maskafter,$numFinal);
1164  }
1165  }
1166 
1167  dol_syslog("functions2::get_next_value return ".$numFinal,LOG_DEBUG);
1168  return $numFinal;
1169 }
1170 
1179 function get_string_between($string, $start, $end)
1180 {
1181  $string = " ".$string;
1182  $ini = strpos($string,$start);
1183  if ($ini == 0) return "";
1184  $ini += strlen($start);
1185  $len = strpos($string,$end,$ini) - $ini;
1186  return substr($string,$ini,$len);
1187 }
1188 
1196 function check_value($mask,$value)
1197 {
1198  $result=0;
1199 
1200  $hasglobalcounter=false;
1201  // Extract value for mask counter, mask raz and mask offset
1202  if (preg_match('/\{(0+)([@\+][0-9]+)?([@\+][0-9]+)?\}/i',$mask,$reg))
1203  {
1204  $masktri=$reg[1].(isset($reg[2])?$reg[2]:'').(isset($reg[3])?$reg[3]:'');
1205  $maskcounter=$reg[1];
1206  $hasglobalcounter=true;
1207  }
1208  else
1209  {
1210  // setting some defaults so the rest of the code won't fail if there is a third party counter
1211  $masktri='00000';
1212  $maskcounter='00000';
1213  }
1214 
1215  $maskraz=-1;
1216  $maskoffset=0;
1217  if (dol_strlen($maskcounter) < 3) return 'ErrorCounterMustHaveMoreThan3Digits';
1218 
1219  // Extract value for third party mask counter
1220  if (preg_match('/\{(c+)(0*)\}/i',$mask,$regClientRef))
1221  {
1222  $maskrefclient=$regClientRef[1].$regClientRef[2];
1223  $maskrefclient_maskclientcode=$regClientRef[1];
1224  $maskrefclient_maskcounter=$regClientRef[2];
1225  $maskrefclient_maskoffset=0; //default value of maskrefclient_counter offset
1226  $maskrefclient_clientcode=substr('',0,dol_strlen($maskrefclient_maskclientcode));//get n first characters of client code to form maskrefclient_clientcode
1227  $maskrefclient_clientcode=str_pad($maskrefclient_clientcode,dol_strlen($maskrefclient_maskclientcode),"#",STR_PAD_RIGHT);//padding maskrefclient_clientcode for having exactly n characters in maskrefclient_clientcode
1228  $maskrefclient_clientcode=dol_string_nospecial($maskrefclient_clientcode);//sanitize maskrefclient_clientcode for sql insert and sql select like
1229  if (dol_strlen($maskrefclient_maskcounter) > 0 && dol_strlen($maskrefclient_maskcounter) < 3) return 'ErrorCounterMustHaveMoreThan3Digits';
1230  }
1231  else $maskrefclient='';
1232 
1233  // fail if there is neither a global nor a third party counter
1234  if (! $hasglobalcounter && ($maskrefclient_maskcounter == ''))
1235  {
1236  return 'ErrorBadMask';
1237  }
1238 
1239  $maskwithonlyymcode=$mask;
1240  $maskwithonlyymcode=preg_replace('/\{(0+)([@\+][0-9]+)?([@\+][0-9]+)?\}/i',$maskcounter,$maskwithonlyymcode);
1241  $maskwithonlyymcode=preg_replace('/\{dd\}/i','dd',$maskwithonlyymcode);
1242  $maskwithonlyymcode=preg_replace('/\{(c+)(0*)\}/i',$maskrefclient,$maskwithonlyymcode);
1243  $maskwithnocode=$maskwithonlyymcode;
1244  $maskwithnocode=preg_replace('/\{yyyy\}/i','yyyy',$maskwithnocode);
1245  $maskwithnocode=preg_replace('/\{yy\}/i','yy',$maskwithnocode);
1246  $maskwithnocode=preg_replace('/\{y\}/i','y',$maskwithnocode);
1247  $maskwithnocode=preg_replace('/\{mm\}/i','mm',$maskwithnocode);
1248  // Now maskwithnocode = 0000ddmmyyyyccc for example
1249  // and maskcounter = 0000 for example
1250  //print "maskwithonlyymcode=".$maskwithonlyymcode." maskwithnocode=".$maskwithnocode."\n<br>";
1251 
1252  // If an offset is asked
1253  if (! empty($reg[2]) && preg_match('/^\+/',$reg[2])) $maskoffset=preg_replace('/^\+/','',$reg[2]);
1254  if (! empty($reg[3]) && preg_match('/^\+/',$reg[3])) $maskoffset=preg_replace('/^\+/','',$reg[3]);
1255 
1256  // Define $sqlwhere
1257 
1258  // If a restore to zero after a month is asked we check if there is already a value for this year.
1259  if (! empty($reg[2]) && preg_match('/^@/',$reg[2])) $maskraz=preg_replace('/^@/','',$reg[2]);
1260  if (! empty($reg[3]) && preg_match('/^@/',$reg[3])) $maskraz=preg_replace('/^@/','',$reg[3]);
1261  if ($maskraz >= 0)
1262  {
1263  if ($maskraz > 12) return 'ErrorBadMaskBadRazMonth';
1264 
1265  // Define reg
1266  if ($maskraz > 1 && ! preg_match('/^(.*)\{(y+)\}\{(m+)\}/i',$maskwithonlyymcode,$reg)) return 'ErrorCantUseRazInStartedYearIfNoYearMonthInMask';
1267  if ($maskraz <= 1 && ! preg_match('/^(.*)\{(y+)\}/i',$maskwithonlyymcode,$reg)) return 'ErrorCantUseRazIfNoYearInMask';
1268  //print "x".$maskwithonlyymcode." ".$maskraz;
1269  }
1270  //print "masktri=".$masktri." maskcounter=".$maskcounter." maskraz=".$maskraz." maskoffset=".$maskoffset."<br>\n";
1271 
1272  // Check we have a number in ($posnumstart+1).', '.dol_strlen($maskcounter)
1273  //
1274 
1275  // Check length
1276  $len=dol_strlen($maskwithnocode);
1277  if (dol_strlen($value) != $len) $result=-1;
1278 
1279  // Define $maskLike
1280  /* seems not used
1281  $maskLike = dol_string_nospecial($mask);
1282  $maskLike = str_replace("%","_",$maskLike);
1283  // Replace protected special codes with matching number of _ as wild card caracter
1284  $maskLike = str_replace(dol_string_nospecial('{yyyy}'),'____',$maskLike);
1285  $maskLike = str_replace(dol_string_nospecial('{yy}'),'__',$maskLike);
1286  $maskLike = str_replace(dol_string_nospecial('{y}'),'_',$maskLike);
1287  $maskLike = str_replace(dol_string_nospecial('{mm}'),'__',$maskLike);
1288  $maskLike = str_replace(dol_string_nospecial('{dd}'),'__',$maskLike);
1289  $maskLike = str_replace(dol_string_nospecial('{'.$masktri.'}'),str_pad("",dol_strlen($maskcounter),"_"),$maskLike);
1290  if ($maskrefclient) $maskLike = str_replace(dol_string_nospecial('{'.$maskrefclient.'}'),str_pad("",strlen($maskrefclient),"_"),$maskLike);
1291  */
1292 
1293  dol_syslog("functions2::check_value result=".$result,LOG_DEBUG);
1294  return $result;
1295 }
1296 
1305 function binhex($bin, $pad=false, $upper=false)
1306 {
1307  $last = dol_strlen($bin)-1;
1308  for($i=0; $i<=$last; $i++){ $x += $bin[$last-$i] * pow(2,$i); }
1309  $x = dechex($x);
1310  if($pad){ while(dol_strlen($x) < intval(dol_strlen($bin))/4){ $x = "0$x"; } }
1311  if($upper){ $x = strtoupper($x); }
1312  return $x;
1313 }
1314 
1321 function hexbin($hexa)
1322 {
1323  $bin='';
1324  $strLength = dol_strlen($hexa);
1325  for($i=0;$i<$strLength;$i++)
1326  {
1327  $bin.=str_pad(decbin(hexdec($hexa{$i})),4,'0',STR_PAD_LEFT);
1328  }
1329  return $bin;
1330 }
1331 
1338 function numero_semaine($time)
1339 {
1340  $stime = strftime('%Y-%m-%d',$time);
1341 
1342  if (preg_match('/^([0-9]+)\-([0-9]+)\-([0-9]+)\s?([0-9]+)?:?([0-9]+)?/i',$stime,$reg))
1343  {
1344  // Date est au format 'YYYY-MM-DD' ou 'YYYY-MM-DD HH:MM:SS'
1345  $annee = $reg[1];
1346  $mois = $reg[2];
1347  $jour = $reg[3];
1348  }
1349 
1350  /*
1351  * Norme ISO-8601:
1352  * - La semaine 1 de toute annee est celle qui contient le 4 janvier ou que la semaine 1 de toute annee est celle qui contient le 1er jeudi de janvier.
1353  * - La majorite des annees ont 52 semaines mais les annees qui commence un jeudi et les annees bissextiles commencant un mercredi en possede 53.
1354  * - Le 1er jour de la semaine est le Lundi
1355  */
1356 
1357  // Definition du Jeudi de la semaine
1358  if (date("w",mktime(12,0,0,$mois,$jour,$annee))==0) // Dimanche
1359  $jeudiSemaine = mktime(12,0,0,$mois,$jour,$annee)-3*24*60*60;
1360  else if (date("w",mktime(12,0,0,$mois,$jour,$annee))<4) // du Lundi au Mercredi
1361  $jeudiSemaine = mktime(12,0,0,$mois,$jour,$annee)+(4-date("w",mktime(12,0,0,$mois,$jour,$annee)))*24*60*60;
1362  else if (date("w",mktime(12,0,0,$mois,$jour,$annee))>4) // du Vendredi au Samedi
1363  $jeudiSemaine = mktime(12,0,0,$mois,$jour,$annee)-(date("w",mktime(12,0,0,$mois,$jour,$annee))-4)*24*60*60;
1364  else // Jeudi
1365  $jeudiSemaine = mktime(12,0,0,$mois,$jour,$annee);
1366 
1367  // Definition du premier Jeudi de l'annee
1368  if (date("w",mktime(12,0,0,1,1,date("Y",$jeudiSemaine)))==0) // Dimanche
1369  {
1370  $premierJeudiAnnee = mktime(12,0,0,1,1,date("Y",$jeudiSemaine))+4*24*60*60;
1371  }
1372  else if (date("w",mktime(12,0,0,1,1,date("Y",$jeudiSemaine)))<4) // du Lundi au Mercredi
1373  {
1374  $premierJeudiAnnee = mktime(12,0,0,1,1,date("Y",$jeudiSemaine))+(4-date("w",mktime(12,0,0,1,1,date("Y",$jeudiSemaine))))*24*60*60;
1375  }
1376  else if (date("w",mktime(12,0,0,1,1,date("Y",$jeudiSemaine)))>4) // du Vendredi au Samedi
1377  {
1378  $premierJeudiAnnee = mktime(12,0,0,1,1,date("Y",$jeudiSemaine))+(7-(date("w",mktime(12,0,0,1,1,date("Y",$jeudiSemaine)))-4))*24*60*60;
1379  }
1380  else // Jeudi
1381  {
1382  $premierJeudiAnnee = mktime(12,0,0,1,1,date("Y",$jeudiSemaine));
1383  }
1384 
1385  // Definition du numero de semaine: nb de jours entre "premier Jeudi de l'annee" et "Jeudi de la semaine";
1386  $numeroSemaine = (
1387  (
1388  date("z",mktime(12,0,0,date("m",$jeudiSemaine),date("d",$jeudiSemaine),date("Y",$jeudiSemaine)))
1389  -
1390  date("z",mktime(12,0,0,date("m",$premierJeudiAnnee),date("d",$premierJeudiAnnee),date("Y",$premierJeudiAnnee)))
1391  ) / 7
1392  ) + 1;
1393 
1394  // Cas particulier de la semaine 53
1395  if ($numeroSemaine==53)
1396  {
1397  // Les annees qui commence un Jeudi et les annees bissextiles commencant un Mercredi en possede 53
1398  if (date("w",mktime(12,0,0,1,1,date("Y",$jeudiSemaine)))==4 || (date("w",mktime(12,0,0,1,1,date("Y",$jeudiSemaine)))==3 && date("z",mktime(12,0,0,12,31,date("Y",$jeudiSemaine)))==365))
1399  {
1400  $numeroSemaine = 53;
1401  }
1402  else
1403  {
1404  $numeroSemaine = 1;
1405  }
1406  }
1407 
1408  //echo $jour."-".$mois."-".$annee." (".date("d-m-Y",$premierJeudiAnnee)." - ".date("d-m-Y",$jeudiSemaine).") -> ".$numeroSemaine."<BR>";
1409 
1410  return sprintf("%02d",$numeroSemaine);
1411 }
1412 
1421 function weight_convert($weight,&$from_unit,$to_unit)
1422 {
1423  /* Pour convertire 320 gr en Kg appeler
1424  * $f = -3
1425  * weigh_convert(320, $f, 0) retournera 0.32
1426  *
1427  */
1428  while ($from_unit <> $to_unit)
1429  {
1430  if ($from_unit > $to_unit)
1431  {
1432  $weight = $weight * 10;
1433  $from_unit = $from_unit - 1;
1434  $weight = weight_convert($weight,$from_unit, $to_unit);
1435  }
1436  if ($from_unit < $to_unit)
1437  {
1438  $weight = $weight / 10;
1439  $from_unit = $from_unit + 1;
1440  $weight = weight_convert($weight,$from_unit, $to_unit);
1441  }
1442  }
1443 
1444  return $weight;
1445 }
1446 
1458 function dol_set_user_param($db, $conf, &$user, $tab)
1459 {
1460  // Verification parametres
1461  if (count($tab) < 1) return -1;
1462 
1463  $db->begin();
1464 
1465  // We remove old parameters for all keys in $tab
1466  $sql = "DELETE FROM ".MAIN_DB_PREFIX."user_param";
1467  $sql.= " WHERE fk_user = ".$user->id;
1468  $sql.= " AND entity = ".$conf->entity;
1469  $sql.= " AND param in (";
1470  $i=0;
1471  foreach ($tab as $key => $value)
1472  {
1473  if ($i > 0) $sql.=',';
1474  $sql.="'".$db->escape($key)."'";
1475  $i++;
1476  }
1477  $sql.= ")";
1478  dol_syslog("functions2.lib::dol_set_user_param", LOG_DEBUG);
1479 
1480  $resql=$db->query($sql);
1481  if (! $resql)
1482  {
1483  dol_print_error($db);
1484  $db->rollback();
1485  return -1;
1486  }
1487 
1488  foreach ($tab as $key => $value)
1489  {
1490  // Set new parameters
1491  if ($value)
1492  {
1493  $sql = "INSERT INTO ".MAIN_DB_PREFIX."user_param(fk_user,entity,param,value)";
1494  $sql.= " VALUES (".$user->id.",".$conf->entity.",";
1495  $sql.= " '".$db->escape($key)."','".$db->escape($value)."')";
1496 
1497  dol_syslog("functions2.lib::dol_set_user_param", LOG_DEBUG);
1498  $result=$db->query($sql);
1499  if (! $result)
1500  {
1501  dol_print_error($db);
1502  $db->rollback();
1503  return -1;
1504  }
1505  $user->conf->$key = $value;
1506  //print "key=".$key." user->conf->key=".$user->conf->$key;
1507  }
1508  else
1509  {
1510  unset($user->conf->$key);
1511  }
1512  }
1513 
1514  $db->commit();
1515  return 1;
1516 }
1517 
1525 function dol_print_reduction($reduction,$langs)
1526 {
1527  $string = '';
1528  if ($reduction == 100)
1529  {
1530  $string = $langs->transnoentities("Offered");
1531  }
1532  else
1533  {
1534  $string = vatrate($reduction,true);
1535  }
1536 
1537  return $string;
1538 }
1539 
1546 function version_os()
1547 {
1548  $osversion=php_uname();
1549  return $osversion;
1550 }
1551 
1558 function version_php()
1559 {
1560  return phpversion();
1561 }
1562 
1570 {
1571  return DOL_VERSION;
1572 }
1573 
1580 {
1581  return $_SERVER["SERVER_SOFTWARE"];
1582 }
1583 
1592 function getListOfModels($db,$type,$maxfilenamelength=0)
1593 {
1594  global $conf,$langs;
1595  $liste=array();
1596  $found=0;
1597  $dirtoscan='';
1598 
1599  $sql = "SELECT nom as id, nom as lib, libelle as label, description as description";
1600  $sql.= " FROM ".MAIN_DB_PREFIX."document_model";
1601  $sql.= " WHERE type = '".$type."'";
1602  $sql.= " AND entity IN (0,".$conf->entity.")";
1603  $sql.= " ORDER BY description DESC";
1604 
1605  dol_syslog('/core/lib/function2.lib.php::getListOfModels', LOG_DEBUG);
1606  $resql = $db->query($sql);
1607  if ($resql)
1608  {
1609  $num = $db->num_rows($resql);
1610  $i = 0;
1611  while ($i < $num)
1612  {
1613  $found=1;
1614 
1615  $obj = $db->fetch_object($resql);
1616 
1617  // If this generation module needs to scan a directory, then description field is filled
1618  // with the constant that contains list of directories to scan (COMPANY_ADDON_PDF_ODT_PATH, ...).
1619  if (! empty($obj->description)) // A list of directories to scan is defined
1620  {
1621  include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
1622 
1623  $const=$obj->description;
1624  //irtoscan.=($dirtoscan?',':'').preg_replace('/[\r\n]+/',',',trim($conf->global->$const));
1625  $dirtoscan= preg_replace('/[\r\n]+/',',',trim($conf->global->$const));
1626 
1627  $listoffiles=array();
1628 
1629  // Now we add models found in directories scanned
1630  $listofdir=explode(',',$dirtoscan);
1631  foreach($listofdir as $key=>$tmpdir)
1632  {
1633  $tmpdir=trim($tmpdir);
1634  $tmpdir=preg_replace('/DOL_DATA_ROOT/',DOL_DATA_ROOT,$tmpdir);
1635  if (! $tmpdir) { unset($listofdir[$key]); continue; }
1636  if (is_dir($tmpdir))
1637  {
1638  // all type of template is allowed
1639  $tmpfiles=dol_dir_list($tmpdir, 'files', 0, '', '', 'name', SORT_ASC, 0);
1640  if (count($tmpfiles)) $listoffiles=array_merge($listoffiles,$tmpfiles);
1641  }
1642  }
1643 
1644  if (count($listoffiles))
1645  {
1646  foreach($listoffiles as $record)
1647  {
1648  $max=($maxfilenamelength?$maxfilenamelength:28);
1649  $liste[$obj->id.':'.$record['fullname']]=dol_trunc($record['name'],$max,'middle');
1650  }
1651  }
1652  else
1653  {
1654  $liste[0]=$obj->label.': '.$langs->trans("None");
1655  }
1656  }
1657  else
1658  {
1659  if ($type == 'member' && $obj->lib == 'standard') // Special case, if member template, we add variant per format
1660  {
1661  global $_Avery_Labels;
1662  include_once DOL_DOCUMENT_ROOT.'/core/lib/format_cards.lib.php';
1663  foreach($_Avery_Labels as $key => $val)
1664  {
1665  $liste[$obj->id.':'.$key]=($obj->label?$obj->label:$obj->lib).' '.$val['name'];
1666  }
1667  }
1668  else // Common usage
1669  {
1670  $liste[$obj->id]=$obj->label?$obj->label:$obj->lib;
1671  }
1672  }
1673  $i++;
1674  }
1675  }
1676  else
1677  {
1678  dol_print_error($db);
1679  return -1;
1680  }
1681 
1682  if ($found) return $liste;
1683  else return 0;
1684 }
1685 
1693 function is_ip($ip)
1694 {
1695  // First we test if it is a valid IPv4
1696  if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
1697 
1698  // Then we test if it is a private range
1699  if (! filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE)) return 2;
1700 
1701  // Then we test if it is a reserved range
1702  if (! filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_RES_RANGE)) return 0;
1703 
1704  return 1;
1705  }
1706 
1707  return 0;
1708 }
1709 
1717 function dol_buildlogin($lastname,$firstname)
1718 {
1719  $login=strtolower(dol_string_unaccent($firstname));
1720  $login.=($login?'.':'');
1721  $login.=strtolower(dol_string_unaccent($lastname));
1722  $login=dol_string_nospecial($login,''); // For special names
1723  return $login;
1724 }
1725 
1731 function getSoapParams()
1732 {
1733  global $conf;
1734 
1735  $params=array();
1736  $proxyuse =(empty($conf->global->MAIN_PROXY_USE)?false:true);
1737  $proxyhost=(empty($conf->global->MAIN_PROXY_USE)?false:$conf->global->MAIN_PROXY_HOST);
1738  $proxyport=(empty($conf->global->MAIN_PROXY_USE)?false:$conf->global->MAIN_PROXY_PORT);
1739  $proxyuser=(empty($conf->global->MAIN_PROXY_USE)?false:$conf->global->MAIN_PROXY_USER);
1740  $proxypass=(empty($conf->global->MAIN_PROXY_USE)?false:$conf->global->MAIN_PROXY_PASS);
1741  $timeout =(empty($conf->global->MAIN_USE_CONNECT_TIMEOUT)?10:$conf->global->MAIN_USE_CONNECT_TIMEOUT); // Connection timeout
1742  $response_timeout=(empty($conf->global->MAIN_USE_RESPONSE_TIMEOUT)?30:$conf->global->MAIN_USE_RESPONSE_TIMEOUT); // Response timeout
1743  //print extension_loaded('soap');
1744  if ($proxyuse)
1745  {
1746  $params=array('connection_timeout'=>$timeout,
1747  'response_timeout'=>$response_timeout,
1748  'proxy_use' => 1,
1749  'proxy_host' => $proxyhost,
1750  'proxy_port' => $proxyport,
1751  'proxy_login' => $proxyuser,
1752  'proxy_password' => $proxypass,
1753  'trace' => 1
1754  );
1755  }
1756  else
1757  {
1758  $params=array('connection_timeout'=>$timeout,
1759  'response_timeout'=>$response_timeout,
1760  'proxy_use' => 0,
1761  'proxy_host' => false,
1762  'proxy_port' => false,
1763  'proxy_login' => false,
1764  'proxy_password' => false,
1765  'trace' => 1
1766  );
1767  }
1768  return $params;
1769 }
1770 
1771 
1781 function dolGetElementUrl($objectid,$objecttype,$withpicto=0,$option='')
1782 {
1783  global $db, $conf, $langs;
1784 
1785  $ret='';
1786 
1787  // Parse element/subelement (ex: project_task)
1788  $module = $element = $subelement = $objecttype;
1789  if (preg_match('/^([^_]+)_([^_]+)/i',$objecttype,$regs))
1790  {
1791  $module = $element = $regs[1];
1792  $subelement = $regs[2];
1793  }
1794 
1795  $classpath = $element.'/class';
1796 
1797  // To work with non standard path
1798  if ($objecttype == 'facture' || $objecttype == 'invoice') {
1799  $classpath = 'compta/facture/class';
1800  $module='facture';
1801  $subelement='facture';
1802  }
1803  if ($objecttype == 'commande' || $objecttype == 'order') {
1804  $classpath = 'commande/class';
1805  $module='commande';
1806  $subelement='commande';
1807  }
1808  if ($objecttype == 'propal') {
1809  $classpath = 'comm/propal/class';
1810  }
1811  if ($objecttype == 'supplier_proposal') {
1812  $classpath = 'supplier_proposal/class';
1813  }
1814  if ($objecttype == 'shipping') {
1815  $classpath = 'expedition/class';
1816  $subelement = 'expedition';
1817  $module = 'expedition_bon';
1818  }
1819  if ($objecttype == 'delivery') {
1820  $classpath = 'livraison/class';
1821  $subelement = 'livraison';
1822  $module = 'livraison_bon';
1823  }
1824  if ($objecttype == 'contract') {
1825  $classpath = 'contrat/class';
1826  $module='contrat';
1827  $subelement='contrat';
1828  }
1829  if ($objecttype == 'member') {
1830  $classpath = 'adherents/class';
1831  $module='adherent';
1832  $subelement='adherent';
1833  }
1834  if ($objecttype == 'cabinetmed_cons') {
1835  $classpath = 'cabinetmed/class';
1836  $module='cabinetmed';
1837  $subelement='cabinetmedcons';
1838  }
1839  if ($objecttype == 'fichinter') {
1840  $classpath = 'fichinter/class';
1841  $module='ficheinter';
1842  $subelement='fichinter';
1843  }
1844  if ($objecttype == 'task') {
1845  $classpath = 'projet/class';
1846  $module='projet';
1847  $subelement='task';
1848  }
1849  if ($objecttype == 'stock') {
1850  $classpath = 'product/stock/class';
1851  $module='stock';
1852  $subelement='stock';
1853  }
1854 
1855  //print "objecttype=".$objecttype." module=".$module." subelement=".$subelement;
1856 
1857  $classfile = strtolower($subelement); $classname = ucfirst($subelement);
1858  if ($objecttype == 'invoice_supplier') {
1859  $classfile = 'fournisseur.facture';
1860  $classname='FactureFournisseur';
1861  $classpath = 'fourn/class';
1862  $module='fournisseur';
1863  }
1864  elseif ($objecttype == 'order_supplier') {
1865  $classfile = 'fournisseur.commande';
1866  $classname='CommandeFournisseur';
1867  $classpath = 'fourn/class';
1868  $module='fournisseur';
1869  }
1870  elseif ($objecttype == 'stock') {
1871  $classpath = 'product/stock/class';
1872  $classfile='entrepot';
1873  $classname='Entrepot';
1874  }
1875  if (! empty($conf->$module->enabled))
1876  {
1877  $res=dol_include_once('/'.$classpath.'/'.$classfile.'.class.php');
1878  if ($res)
1879  {
1880  if (class_exists($classname))
1881  {
1882  $object = new $classname($db);
1883  $res=$object->fetch($objectid);
1884  if ($res > 0) {
1885  $ret=$object->getNomUrl($withpicto,$option);
1886  } elseif($res==0) {
1887  $ret=$langs->trans('Deleted');
1888  }
1889  unset($object);
1890  }
1891  else dol_syslog("Class with classname ".$classname." is unknown even after the include", LOG_ERR);
1892  }
1893  }
1894  return $ret;
1895 }
1896 
1897 
1906 function cleanCorruptedTree($db, $tabletocleantree, $fieldfkparent)
1907 {
1908  $totalnb=0;
1909  $listofid=array();
1910  $listofparentid=array();
1911 
1912  // Get list of all id in array listofid and all parents in array listofparentid
1913  $sql='SELECT rowid, '.$fieldfkparent.' as parent_id FROM '.MAIN_DB_PREFIX.$tabletocleantree;
1914  $resql = $db->query($sql);
1915  if ($resql)
1916  {
1917  $num = $db->num_rows($resql);
1918  $i = 0;
1919  while ($i < $num)
1920  {
1921  $obj = $db->fetch_object($resql);
1922  $listofid[]=$obj->rowid;
1923  if ($obj->parent_id > 0) $listofparentid[$obj->rowid]=$obj->parent_id;
1924  $i++;
1925  }
1926  }
1927  else
1928  {
1929  dol_print_error($db);
1930  }
1931 
1932  if (count($listofid))
1933  {
1934  print 'Code requested to clean tree (may be to solve data corruption), so we check/clean orphelins and loops.'."<br>\n";
1935 
1936  // Check loops on each other
1937  $sql = "UPDATE ".MAIN_DB_PREFIX.$tabletocleantree." SET ".$fieldfkparent." = 0 WHERE ".$fieldfkparent." = rowid"; // So we update only records linked to themself
1938  $resql = $db->query($sql);
1939  if ($resql)
1940  {
1941  $nb=$db->affected_rows($sql);
1942  if ($nb > 0)
1943  {
1944  print '<br>Some record that were parent of themself were cleaned.';
1945  }
1946 
1947  $totalnb+=$nb;
1948  }
1949  //else dol_print_error($db);
1950 
1951  // Check other loops
1952  $listofidtoclean=array();
1953  foreach($listofparentid as $id => $pid)
1954  {
1955  // Check depth
1956  //print 'Analyse record id='.$id.' with parent '.$pid.'<br>';
1957 
1958  $cursor=$id; $arrayidparsed=array(); // We start from child $id
1959  while ($cursor > 0)
1960  {
1961  $arrayidparsed[$cursor]=1;
1962  if ($arrayidparsed[$listofparentid[$cursor]]) // We detect a loop. A record with a parent that was already into child
1963  {
1964  print 'Found a loop between id '.$id.' - '.$cursor.'<br>';
1965  unset($arrayidparsed);
1966  $listofidtoclean[$cursor]=$id;
1967  break;
1968  }
1969  $cursor=$listofparentid[$cursor];
1970  }
1971 
1972  if (count($listofidtoclean)) break;
1973  }
1974 
1975  $sql = "UPDATE ".MAIN_DB_PREFIX.$tabletocleantree;
1976  $sql.= " SET ".$fieldfkparent." = 0";
1977  $sql.= " WHERE rowid IN (".join(',',$listofidtoclean).")"; // So we update only records detected wrong
1978  $resql = $db->query($sql);
1979  if ($resql)
1980  {
1981  $nb=$db->affected_rows($sql);
1982  if ($nb > 0)
1983  {
1984  // Removed orphelins records
1985  print '<br>Some records were detected to have parent that is a child, we set them as root record for id: ';
1986  print join(',',$listofidtoclean);
1987  }
1988 
1989  $totalnb+=$nb;
1990  }
1991  //else dol_print_error($db);
1992 
1993  // Check and clean orphelins
1994  $sql = "UPDATE ".MAIN_DB_PREFIX.$tabletocleantree;
1995  $sql.= " SET ".$fieldfkparent." = 0";
1996  $sql.= " WHERE ".$fieldfkparent." NOT IN (".join(',',$listofid).")"; // So we update only records linked to a non existing parent
1997  $resql = $db->query($sql);
1998  if ($resql)
1999  {
2000  $nb=$db->affected_rows($sql);
2001  if ($nb > 0)
2002  {
2003  // Removed orphelins records
2004  print '<br>Some orphelins were found and modified to be parent so records are visible again for id: ';
2005  print join(',',$listofid);
2006  }
2007 
2008  $totalnb+=$nb;
2009  }
2010  //else dol_print_error($db);
2011 
2012  print '<br>We fixed '.$totalnb.' record(s). Some records may still be corrupted. New check may be required.';
2013  return $totalnb;
2014  }
2015 }
2016 
2023 function getElementProperties($element_type)
2024 {
2025  // Parse element/subelement (ex: project_task)
2026  $module = $element = $subelement = $element_type;
2027 
2028  // If we ask an resource form external module (instead of default path)
2029  if (preg_match('/^([^@]+)@([^@]+)$/i',$element_type,$regs))
2030  {
2031  $element = $subelement = $regs[1];
2032  $module = $regs[2];
2033  }
2034 
2035  //print '<br>1. element : '.$element.' - module : '.$module .'<br>';
2036  if ( preg_match('/^([^_]+)_([^_]+)/i',$element,$regs))
2037  {
2038  $module = $element = $regs[1];
2039  $subelement = $regs[2];
2040  }
2041 
2042  // For compat
2043  if($element_type == "action") {
2044  $classpath = 'comm/action/class';
2045  $subelement = 'Actioncomm';
2046  $module = 'agenda';
2047  }
2048 
2049  // To work with non standard path
2050  if ($element_type == 'facture' || $element_type == 'invoice') {
2051  $classpath = 'compta/facture/class';
2052  $module='facture';
2053  $subelement='facture';
2054  }
2055  if ($element_type == 'commande' || $element_type == 'order') {
2056  $classpath = 'commande/class';
2057  $module='commande';
2058  $subelement='commande';
2059  }
2060  if ($element_type == 'propal') {
2061  $classpath = 'comm/propal/class';
2062  }
2063  if ($element_type == 'supplier_proposal') {
2064  $classpath = 'supplier_proposal/class';
2065  }
2066  if ($element_type == 'shipping') {
2067  $classpath = 'expedition/class';
2068  $subelement = 'expedition';
2069  $module = 'expedition_bon';
2070  }
2071  if ($element_type == 'delivery') {
2072  $classpath = 'livraison/class';
2073  $subelement = 'livraison';
2074  $module = 'livraison_bon';
2075  }
2076  if ($element_type == 'contract') {
2077  $classpath = 'contrat/class';
2078  $module='contrat';
2079  $subelement='contrat';
2080  }
2081  if ($element_type == 'member') {
2082  $classpath = 'adherents/class';
2083  $module='adherent';
2084  $subelement='adherent';
2085  }
2086  if ($element_type == 'cabinetmed_cons') {
2087  $classpath = 'cabinetmed/class';
2088  $module='cabinetmed';
2089  $subelement='cabinetmedcons';
2090  }
2091  if ($element_type == 'fichinter') {
2092  $classpath = 'fichinter/class';
2093  $module='ficheinter';
2094  $subelement='fichinter';
2095  }
2096  if ($element_type == 'dolresource' || $element_type == 'resource') {
2097  $classpath = 'resource/class';
2098  $module='resource';
2099  $subelement='dolresource';
2100  }
2101  if ($element_type == 'propaldet') {
2102  $classpath = 'comm/propal/class';
2103  $module='propal';
2104  $subelement='propaleligne';
2105  }
2106  if ($element_type == 'order_supplier') {
2107  $classpath = 'fourn/class';
2108  $module='fournisseur';
2109  $subelement='commandefournisseur';
2110  $classfile='fournisseur.commande';
2111  }
2112  if ($element_type == 'invoice_supplier') {
2113  $classpath = 'fourn/class';
2114  $module='fournisseur';
2115  $subelement='facturefournisseur';
2116  $classfile='fournisseur.facture';
2117  }
2118 
2119  if (!isset($classfile)) $classfile = strtolower($subelement);
2120  if (!isset($classname)) $classname = ucfirst($subelement);
2121  if (!isset($classpath)) $classpath = $module.'/class';
2122 
2123  $element_properties = array(
2124  'module' => $module,
2125  'classpath' => $classpath,
2126  'element' => $element,
2127  'subelement' => $subelement,
2128  'classfile' => $classfile,
2129  'classname' => $classname
2130  );
2131  return $element_properties;
2132 }
2133 
2143 function fetchObjectByElement($element_id, $element_type, $element_ref='')
2144 {
2145  global $conf;
2146  global $db,$conf;
2147 
2148  $element_prop = getElementProperties($element_type);
2149  if (is_array($element_prop) && $conf->{$element_prop['module']}->enabled)
2150  {
2151  dol_include_once('/'.$element_prop['classpath'].'/'.$element_prop['classfile'].'.class.php');
2152 
2153  $objecttmp = new $element_prop['classname']($db);
2154  $ret = $objecttmp->fetch($element_id, $element_ref);
2155  if ($ret >= 0)
2156  {
2157  return $objecttmp;
2158  }
2159  }
2160  return 0;
2161 }
2162 
2163 
2173 function colorArrayToHex($arraycolor,$colorifnotfound='888888')
2174 {
2175  if (! is_array($arraycolor)) return $colorifnotfound;
2176  if (empty($arraycolor)) return $colorifnotfound;
2177  return sprintf("%02s",dechex($arraycolor[0])).sprintf("%02s",dechex($arraycolor[1])).sprintf("%02s",dechex($arraycolor[2]));
2178 }
2179 
2190 function colorStringToArray($stringcolor,$colorifnotfound=array(88,88,88))
2191 {
2192  if (is_array($stringcolor)) return $stringcolor; // If already into correct output format, we return as is
2193  $tmp=preg_match('/^#?([0-9a-fA-F][0-9a-fA-F])([0-9a-fA-F][0-9a-fA-F])([0-9a-fA-F][0-9a-fA-F])$/',$stringcolor,$reg);
2194  if (! $tmp)
2195  {
2196  $tmp=explode(',',$stringcolor);
2197  if (count($tmp) < 3) return $colorifnotfound;
2198  return $tmp;
2199  }
2200  return array(hexdec($reg[1]),hexdec($reg[2]),hexdec($reg[3]));
2201 }
2202 
2210 function cartesianArray(array $input)
2211 {
2212  // filter out empty values
2213  $input = array_filter($input);
2214 
2215  $result = array(array());
2216 
2217  foreach ($input as $key => $values) {
2218  $append = array();
2219 
2220  foreach($result as $product) {
2221  foreach($values as $item) {
2222  $product[$key] = $item;
2223  $append[] = $product;
2224  }
2225  }
2226 
2227  $result = $append;
2228  }
2229 
2230  return $result;
2231 }
2232 
2233 
2240 function getModuleDirForApiClass($module)
2241 {
2242  $moduledirforclass=$module;
2243  if ($moduledirforclass != 'api') $moduledirforclass = preg_replace('/api$/i','',$moduledirforclass);
2244 
2245  if ($module == 'contracts') {
2246  $moduledirforclass = 'contrat';
2247  }
2248  elseif (in_array($module, array('admin', 'login', 'setup', 'access', 'status', 'tools', 'documents'))) {
2249  $moduledirforclass = 'api';
2250  }
2251  elseif ($module == 'contact' || $module == 'contacts' || $module == 'customer' || $module == 'thirdparty' || $module == 'thirdparties') {
2252  $moduledirforclass = 'societe';
2253  }
2254  elseif ($module == 'propale' || $module == 'proposals') {
2255  $moduledirforclass = 'comm/propal';
2256  }
2257  elseif ($module == 'agenda' || $module == 'agendaevents') {
2258  $moduledirforclass = 'comm/action';
2259  }
2260  elseif ($module == 'adherent' || $module == 'members' || $module == 'memberstypes' || $module == 'subscriptions') {
2261  $moduledirforclass = 'adherents';
2262  }
2263  elseif ($module == 'banque' || $module == 'bankaccounts') {
2264  $moduledirforclass = 'compta/bank';
2265  }
2266  elseif ($module == 'category' || $module == 'categorie') {
2267  $moduledirforclass = 'categories';
2268  }
2269  elseif ($module == 'order' || $module == 'orders') {
2270  $moduledirforclass = 'commande';
2271  }
2272  elseif ($module == 'shipments') {
2273  $moduledirforclass = 'expedition';
2274  }
2275  elseif ($module == 'facture' || $module == 'invoice' || $module == 'invoices') {
2276  $moduledirforclass = 'compta/facture';
2277  }
2278  elseif ($module == 'products') {
2279  $moduledirforclass = 'product';
2280  }
2281  elseif ($module == 'project' || $module == 'projects' || $module == 'tasks') {
2282  $moduledirforclass = 'projet';
2283  }
2284  elseif ($module == 'task') {
2285  $moduledirforclass = 'projet';
2286  }
2287  elseif ($module == 'stock' || $module == 'stockmovements' || $module == 'warehouses') {
2288  $moduledirforclass = 'product/stock';
2289  }
2290  elseif ($module == 'supplierproposals' || $module == 'supplierproposal' || $module == 'supplier_proposal') {
2291  $moduledirforclass = 'supplier_proposal';
2292  }
2293  elseif ($module == 'fournisseur' || $module == 'supplierinvoices' || $module == 'supplierorders') {
2294  $moduledirforclass = 'fourn';
2295  }
2296  elseif ($module == 'expensereports') {
2297  $moduledirforclass = 'expensereport';
2298  }
2299  elseif ($module == 'users') {
2300  $moduledirforclass = 'user';
2301  }
2302  elseif ($module == 'ficheinter' || $module == 'interventions') {
2303  $moduledirforclass = 'fichinter';
2304  }
2305  elseif ($module == 'tickets') {
2306  $moduledirforclass = 'ticket';
2307  }
2308 
2309  return $moduledirforclass;
2310 }
2311 
2312 /*
2313  * Return 2 hexa code randomly
2314  *
2315  * @param $min int Between 0 and 255
2316  * @param $max int Between 0 and 255
2317  * @return String
2318  */
2319 function random_color_part($min=0,$max=255)
2320 {
2321  return str_pad( dechex( mt_rand( $min, $max) ), 2, '0', STR_PAD_LEFT);
2322 }
2323 
2324 /*
2325  * Return hexadecimal color randomly
2326  *
2327  * @param $min int Between 0 and 255
2328  * @param $max int Between 0 and 255
2329  * @return String
2330  */
2331 function random_color($min=0, $max=255)
2332 {
2333  return random_color_part($min, $max) . random_color_part($min, $max) . random_color_part($min, $max);
2334 }
array2table($data, $tableMarkup=1, $tableoptions='', $troptions='', $tdoptions='')
Return an html table from an array.
print
Draft customers invoices.
Definition: index.php:91
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.
if(! empty($conf->facture->enabled) && $user->rights->facture->lire) if(! empty($conf->fournisseur->enabled) && $user->rights->fournisseur->facture->lire) if(! empty($conf->don->enabled) && $user->rights->societe->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) && $user->rights->fournisseur->facture->lire) $resql
Social contributions to pay.
Definition: index.php:1053
getModuleDirForApiClass($module)
Get name of directory where the api_...class.php file is stored.
weight_convert($weight, &$from_unit, $to_unit)
Convertit une masse d&#39;une unite vers une autre unite.
cartesianArray(array $input)
Applies the Cartesian product algorithm to an array Source: http://stackoverflow.com/a/15973172.
dol_mktime($hour, $minute, $second, $month, $day, $year, $gm=false, $check=1)
Return a timestamp date built from detailed informations (by default a local PHP server timestamp) Re...
dol_print_reduction($reduction, $langs)
Returns formated reduction.
version_webserver()
Return web server version.
version_os()
Return OS version.
dol_print_object_info($object, $usetable=0)
Show informations on an object TODO Move this into html.formother.
Class to manage Dolibarr users.
Definition: user.class.php:41
dolGetModulesDirs($subdir='')
Return list of modules directories.
cleanCorruptedTree($db, $tabletocleantree, $fieldfkparent)
Clean corrupted tree (orphelins linked to a not existing parent), record linked to themself and child...
clean_url($url, $http=1)
Clean an url string.
dol_print_error($db='', $error='', $errors=null)
Affiche message erreur system avec toutes les informations pour faciliter le diagnostic et la remonte...
dol_buildlogin($lastname, $firstname)
Build a login from lastname, firstname.
check_value($mask, $value)
Check value.
colorStringToArray($stringcolor, $colorifnotfound=array(88, 88, 88))
Convert a string RGB value (&#39;FFFFFF&#39;, &#39;255,255,255&#39;) into an array RGB array(255,255,255).
isValidUrl($url, $http=0, $pass=0, $port=0, $path=0, $query=0, $anchor=0)
Url string validation <http[s]> :// [user[:pass]@] hostname [port] [/path] [?getquery] [anchor]...
dolAddEmailTrackId($email, $trackingid)
Return an email formatted to include a tracking id For example myemail@example.com becom myemail+trac...
hexbin($hexa)
Convert an hexadecimal string into a binary string.
fetchObjectByElement($element_id, $element_type, $element_ref='')
Fetch an object from its id and element_type Inclusion of classes is automatic.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='')
Write log message into outputs.
get_next_value($db, $mask, $table, $field, $where='', $objsoc='', $date='', $mode='next', $bentityon=true, $objuser=null, $forceentity=null)
Return last or next value for a mask (according to area we should not reset)
if(! function_exists('dol_getprefix')) dol_include_once($relpath, $classname='')
Make an include_once using default root and alternate root if it fails.
jsUnEscape($source)
Same function than javascript unescape() function but in PHP.
dol_getDefaultFormat(Translate $outputlangs=null)
Try to guess default paper format according to language into $langs.
Class to manage translations.
version_dolibarr()
Return Dolibarr version.
dol_print_file($langs, $filename, $searchalt=0)
Output content of a file $filename in version of current language (otherwise may use an alternate lan...
is_ip($ip)
This function evaluates a string that should be a valid IPv4 Note: For ip 169.254.0.0, it returns 0 with some PHP (5.6.24) and 2 with some minor patchs of PHP (5.6.25).
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:59
getServerTimeZoneInt($refgmtdate='now')
Return server timezone int.
Definition: date.lib.php:82
dol_string_unaccent($str)
Clean a string from all accent characters to be used as ref, login or by dol_sanitizeFileName.
dol_now($mode='gmt')
Return date for now.
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...
dol_set_user_param($db, $conf, &$user, $tab)
Save personnal parameter.
numero_semaine($time)
Retourne le numero de la semaine par rapport a une date.
version_php()
Return PHP version.
dol_print_date($time, $format='', $tzoutput='tzserver', $outputlangs='', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
isValidMailDomain($mail)
Return true if email has a domain name that can&#39;t be resolved.
dolGetElementUrl($objectid, $objecttype, $withpicto=0, $option='')
Return link url to an object.
array2tr($data, $troptions='', $tdoptions='')
Return lines of an html table from an array Used by array2table function only.
colorArrayToHex($arraycolor, $colorifnotfound='888888')
Convert an array with RGB value into hex RGB value.
dol_html_entity_decode($a, $b, $c='UTF-8')
Replace html_entity_decode functions to manage errors.
getListOfModels($db, $type, $maxfilenamelength=0)
Return list of activated modules usable for document generation.
get_string_between($string, $start, $end)
Get string between.
dolObfuscateEmail($mail, $replace="*", $nbreplace=8, $nbdisplaymail=4, $nbdisplaydomain=3, $displaytld=true)
Returns an email value with obfuscated parts.
binhex($bin, $pad=false, $upper=false)
Convert a binary data to string that represent hexadecimal value.
dol_string_nospecial($str, $newstr='_', $badcharstoreplace='')
Clean a string from all punctuation characters to use it as a ref or login.
getSoapParams()
Return array to use for SoapClient constructor.
isValidEmail($address, $acceptsupervisorkey=0)
Return true if email syntax is ok.
getElementProperties($element_type)
Get an array with properties of an element.
dol_strlen($string, $stringencoding='UTF-8')
Make a strlen call.