dolibarr  21.0.0-alpha
import_csv.modules.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2006-2012 Laurent Destailleur <eldy@users.sourceforge.net>
3  * Copyright (C) 2009-2012 Regis Houssin <regis.houssin@inodbox.com>
4  * Copyright (C) 2012 Christophe Battarel <christophe.battarel@altairis.fr>
5  * Copyright (C) 2012-2016 Juanjo Menent <jmenent@2byte.es>
6  * Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program. If not, see <https://www.gnu.org/licenses/>.
20  * or see https://www.gnu.org/
21  */
22 
29 require_once DOL_DOCUMENT_ROOT.'/core/modules/import/modules_import.php';
30 
31 
35 class ImportCsv extends ModeleImports
36 {
40  public $db;
41 
45  public $id;
46 
51  public $version = 'dolibarr';
52 
53  public $label_lib; // Label of external lib used by driver
54 
55  public $version_lib; // Version of external lib used by driver
56 
57  public $separator;
58 
59  public $file; // Path of file
60 
61  public $handle; // Handle fichier
62 
63  public $cacheconvert = array(); // Array to cache list of value found after a conversion
64 
65  public $cachefieldtable = array(); // Array to cache list of value found into fields@tables
66 
67  public $nbinsert = 0; // # of insert done during the import
68 
69  public $nbupdate = 0; // # of update done during the import
70 
71  public $charset = '';
72 
73  public $col;
74 
75 
82  public function __construct($db, $datatoimport)
83  {
84  global $langs;
85 
86  parent::__construct();
87  $this->db = $db;
88 
89  $this->separator = (GETPOST('separator') ? GETPOST('separator') : getDolGlobalString('IMPORT_CSV_SEPARATOR_TO_USE', ','));
90  $this->enclosure = '"';
91  $this->escape = '"';
92 
93  $this->id = 'csv'; // Same value then xxx in file name export_xxx.modules.php
94  $this->label = 'Csv'; // Label of driver
95  $this->desc = $langs->trans("CSVFormatDesc", $this->separator, $this->enclosure, $this->escape);
96  $this->extension = 'csv'; // Extension for generated file by this driver
97  $this->picto = 'mime/other'; // Picto
98  $this->version = '1.34'; // Driver version
99  $this->phpmin = array(7, 0); // Minimum version of PHP required by module
100 
101  require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
102  if (versioncompare($this->phpmin, versionphparray()) > 0) {
103  dol_syslog("Module need a higher PHP version");
104  $this->error = "Module need a higher PHP version";
105  return;
106  }
107 
108  // If driver use an external library, put its name here
109  $this->label_lib = 'Dolibarr';
110  $this->version_lib = DOL_VERSION;
111 
112  $this->datatoimport = $datatoimport;
113  if (preg_match('/^societe_/', $datatoimport)) {
114  $this->thirdpartyobject = new Societe($this->db);
115  }
116  }
117 
118 
119  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
126  public function write_header_example($outputlangs)
127  {
128  // phpcs:enable
129  return '';
130  }
131 
132  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
140  public function write_title_example($outputlangs, $headerlinefields)
141  {
142  // phpcs:enable
143  $s = implode($this->separator, array_map('cleansep', $headerlinefields));
144  return $s."\n";
145  }
146 
147  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
155  public function write_record_example($outputlangs, $contentlinevalues)
156  {
157  // phpcs:enable
158  $s = implode($this->separator, array_map('cleansep', $contentlinevalues));
159  return $s."\n";
160  }
161 
162  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
169  public function write_footer_example($outputlangs)
170  {
171  // phpcs:enable
172  return '';
173  }
174 
175 
176  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
183  public function import_open_file($file)
184  {
185  // phpcs:enable
186  global $langs;
187  $ret = 1;
188 
189  dol_syslog(get_class($this)."::open_file file=".$file);
190 
191  ini_set('auto_detect_line_endings', 1); // For MAC compatibility
192 
193  $this->handle = fopen(dol_osencode($file), "r");
194  if (!$this->handle) {
195  $langs->load("errors");
196  $this->error = $langs->trans("ErrorFailToOpenFile", $file);
197  $ret = -1;
198  } else {
199  $this->file = $file;
200  }
201 
202  return $ret;
203  }
204 
205 
206  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
213  public function import_get_nb_of_lines($file)
214  {
215  // phpcs:enable
216  return dol_count_nb_of_line($file);
217  }
218 
219 
220  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
226  public function import_read_header()
227  {
228  // phpcs:enable
229  return 0;
230  }
231 
232 
233  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
239  public function import_read_record()
240  {
241  // phpcs:enable
242  global $conf;
243 
244  $arrayres = fgetcsv($this->handle, 100000, $this->separator, $this->enclosure, $this->escape);
245 
246  // End of file
247  if ($arrayres === false) {
248  return false;
249  }
250 
251  //var_dump($this->handle);
252  //var_dump($arrayres);exit;
253  $newarrayres = array();
254  if ($arrayres && is_array($arrayres)) {
255  foreach ($arrayres as $key => $val) {
256  if (getDolGlobalString('IMPORT_CSV_FORCE_CHARSET')) { // Forced charset
257  if (strtolower($conf->global->IMPORT_CSV_FORCE_CHARSET) == 'utf8') {
258  $newarrayres[$key]['val'] = $val;
259  $newarrayres[$key]['type'] = (dol_strlen($val) ? 1 : -1); // If empty we consider it's null
260  } else {
261  $newarrayres[$key]['val'] = mb_convert_encoding($val, 'UTF-8', 'ISO-8859-1');
262  $newarrayres[$key]['type'] = (dol_strlen($val) ? 1 : -1); // If empty we consider it's null
263  }
264  } else { // Autodetect format (UTF8 or ISO)
265  if (utf8_check($val)) {
266  $newarrayres[$key]['val'] = $val;
267  $newarrayres[$key]['type'] = (dol_strlen($val) ? 1 : -1); // If empty we consider it's null
268  } else {
269  $newarrayres[$key]['val'] = mb_convert_encoding($val, 'UTF-8', 'ISO-8859-1');
270  $newarrayres[$key]['type'] = (dol_strlen($val) ? 1 : -1); // If empty we consider it's null
271  }
272  }
273  }
274 
275  $this->col = count($newarrayres);
276  }
277 
278  return $newarrayres;
279  }
280 
281  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
287  public function import_close_file()
288  {
289  // phpcs:enable
290  fclose($this->handle);
291  return 0;
292  }
293 
294 
295  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
307  public function import_insert($arrayrecord, $array_match_file_to_database, $objimport, $maxfields, $importid, $updatekeys)
308  {
309  // phpcs:enable
310  global $langs, $conf, $user;
311  global $thirdparty_static; // Specific to thirdparty import
312  global $tablewithentity_cache; // Cache to avoid to call desc at each rows on tables
313 
314  $error = 0;
315  $warning = 0;
316  $this->errors = array();
317  $this->warnings = array();
318 
319  //dol_syslog("import_csv.modules maxfields=".$maxfields." importid=".$importid);
320 
321  //var_dump($array_match_file_to_database);
322  //var_dump($arrayrecord); exit;
323 
324  $array_match_database_to_file = array_flip($array_match_file_to_database);
325  $sort_array_match_file_to_database = $array_match_file_to_database;
326  ksort($sort_array_match_file_to_database);
327 
328  //var_dump($sort_array_match_file_to_database);
329 
330  if (count($arrayrecord) == 0 || (count($arrayrecord) == 1 && empty($arrayrecord[0]['val']))) {
331  //print 'W';
332  $this->warnings[$warning]['lib'] = $langs->trans('EmptyLine');
333  $this->warnings[$warning]['type'] = 'EMPTY';
334  $warning++;
335  } else {
336  $last_insert_id_array = array(); // store the last inserted auto_increment id for each table, so that dependent tables can be inserted with the appropriate id (eg: extrafields fk_object will be set with the last inserted object's id)
337  $updatedone = false;
338  $insertdone = false;
339  // For each table to insert, me make a separate insert
340  foreach ($objimport->array_import_tables[0] as $alias => $tablename) {
341  // Build sql request
342  $sql = '';
343  $listfields = array();
344  $listvalues = array();
345  $i = 0;
346  $errorforthistable = 0;
347 
348  // Define $tablewithentity_cache[$tablename] if not already defined
349  if (!isset($tablewithentity_cache[$tablename])) { // keep this test with "isset"
350  dol_syslog("Check if table ".$tablename." has an entity field");
351  $resql = $this->db->DDLDescTable($tablename, 'entity');
352  if ($resql) {
353  $obj = $this->db->fetch_object($resql);
354  if ($obj) {
355  $tablewithentity_cache[$tablename] = 1; // table contains entity field
356  } else {
357  $tablewithentity_cache[$tablename] = 0; // table does not contain entity field
358  }
359  } else {
360  dol_print_error($this->db);
361  }
362  } else {
363  //dol_syslog("Table ".$tablename." check for entity into cache is ".$tablewithentity_cache[$tablename]);
364  }
365 
366  // Define an array to convert fields ('c.ref', ...) into column index (1, ...)
367  $arrayfield = array();
368  foreach ($sort_array_match_file_to_database as $key => $val) {
369  $arrayfield[$val] = ($key - 1);
370  }
371 
372  // $arrayrecord start at key 0
373  // $sort_array_match_file_to_database start at key 1
374 
375  // Loop on each fields in the match array: $key = 1..n, $val=alias of field (s.nom)
376  foreach ($sort_array_match_file_to_database as $key => $val) {
377  $fieldalias = preg_replace('/\..*$/i', '', $val);
378  $fieldname = preg_replace('/^.*\./i', '', $val);
379 
380  if ($alias != $fieldalias) {
381  continue; // Not a field of current table
382  }
383 
384  if ($key <= $maxfields) {
385  // Set $newval with value to insert and set $listvalues with sql request part for insert
386  $newval = '';
387  if ($arrayrecord[($key - 1)]['type'] > 0) {
388  $newval = $arrayrecord[($key - 1)]['val']; // If type of field into input file is not empty string (so defined into input file), we get value
389  }
390 
391  //var_dump($newval);var_dump($val);
392  //var_dump($objimport->array_import_convertvalue[0][$val]);
393 
394  // Make some tests on $newval
395 
396  // Is it a required field ?
397  if (preg_match('/\*/', $objimport->array_import_fields[0][$val]) && ((string) $newval == '')) {
398  // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
399  $this->errors[$error]['lib'] = $langs->trans('ErrorMissingMandatoryValue', $key);
400  $this->errors[$error]['type'] = 'NOTNULL';
401  $errorforthistable++;
402  $error++;
403  } else {
404  // Test format only if field is not a missing mandatory field (field may be a value or empty but not mandatory)
405  // We convert field if required
406  if (!empty($objimport->array_import_convertvalue[0][$val])) {
407  //print 'Must convert '.$newval.' with rule '.join(',',$objimport->array_import_convertvalue[0][$val]).'. ';
408  if ($objimport->array_import_convertvalue[0][$val]['rule'] == 'fetchidfromcodeid'
409  || $objimport->array_import_convertvalue[0][$val]['rule'] == 'fetchidfromref'
410  || $objimport->array_import_convertvalue[0][$val]['rule'] == 'fetchidfromcodeorlabel'
411  ) {
412  // New val can be an id or ref. If it start with id: it is forced to id, if it start with ref: it is forced to ref. It not, we try to guess.
413  $isidorref = 'id';
414  if (!is_numeric($newval) && $newval != '' && !preg_match('/^id:/i', $newval)) {
415  $isidorref = 'ref';
416  }
417 
418  $newval = preg_replace('/^(id|ref):/i', '', $newval); // Remove id: or ref: that was used to force if field is id or ref
419  //print 'Newval is now "'.$newval.'" and is type '.$isidorref."<br>\n";
420 
421  if ($isidorref == 'ref') { // If value into input import file is a ref, we apply the function defined into descriptor
422  $file = (empty($objimport->array_import_convertvalue[0][$val]['classfile']) ? $objimport->array_import_convertvalue[0][$val]['file'] : $objimport->array_import_convertvalue[0][$val]['classfile']);
423  $class = $objimport->array_import_convertvalue[0][$val]['class'];
424  $method = $objimport->array_import_convertvalue[0][$val]['method'];
425  if ($this->cacheconvert[$file.'_'.$class.'_'.$method.'_'][$newval] != '') {
426  $newval = $this->cacheconvert[$file.'_'.$class.'_'.$method.'_'][$newval];
427  } else {
428  $resultload = dol_include_once($file);
429  if (empty($resultload)) {
430  dol_print_error(null, 'Error trying to call file='.$file.', class='.$class.', method='.$method);
431  break;
432  }
433  $classinstance = new $class($this->db);
434  if ($class == 'CGenericDic') {
435  $classinstance->element = $objimport->array_import_convertvalue[0][$val]['element'];
436  $classinstance->table_element = $objimport->array_import_convertvalue[0][$val]['table_element'];
437  }
438 
439  // Try the fetch from code or ref
440  $param_array = array('', $newval);
441  if ($class == 'AccountingAccount') {
442  //var_dump($arrayrecord[0]['val']);
443  /*include_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountancysystem.class.php';
444  $tmpchartofaccount = new AccountancySystem($this->db);
445  $tmpchartofaccount->fetch(getDolGlobalInt('CHARTOFACCOUNTS'));
446  //var_dump($tmpchartofaccount->ref.' - '.$arrayrecord[0]['val']);
447  if ((! (getDolGlobalInt('CHARTOFACCOUNTS') > 0)) || $tmpchartofaccount->ref != $arrayrecord[0]['val'])
448  {
449  $this->errors[$error]['lib']=$langs->trans('ErrorImportOfChartLimitedToCurrentChart', $tmpchartofaccount->ref);
450  $this->errors[$error]['type']='RESTRICTONCURRENCTCHART';
451  $errorforthistable++;
452  $error++;
453  }*/
454  $param_array = array('', $newval, 0, $arrayrecord[0]['val']); // Param to fetch parent from account, in chart.
455  }
456  if ($class == 'CActionComm') {
457  $param_array = array($newval); // CActionComm fetch method have same parameter for id and code
458  }
459  $result = call_user_func_array(array($classinstance, $method), $param_array);
460 
461  // If duplicate record found
462  if (!($classinstance->id != '') && $result == -2) {
463  $this->errors[$error]['lib'] = $langs->trans('ErrorMultipleRecordFoundFromRef', $newval);
464  $this->errors[$error]['type'] = 'FOREIGNKEY';
465  $errorforthistable++;
466  $error++;
467  }
468 
469  // If not found, try the fetch from label
470  if (!($classinstance->id != '') && $objimport->array_import_convertvalue[0][$val]['rule'] == 'fetchidfromcodeorlabel') {
471  $param_array = array('', '', $newval);
472  call_user_func_array(array($classinstance, $method), $param_array);
473  }
474  $this->cacheconvert[$file.'_'.$class.'_'.$method.'_'][$newval] = $classinstance->id;
475 
476  //print 'We have made a '.$class.'->'.$method.' to get id from code '.$newval.'. ';
477  if ($classinstance->id != '') { // id may be 0, it is a found value
478  $newval = $classinstance->id;
479  } elseif (! $error) {
480  if (!empty($objimport->array_import_convertvalue[0][$val]['dict'])) {
481  $this->errors[$error]['lib'] = $langs->trans('ErrorFieldValueNotIn', num2Alpha($key - 1), $newval, 'code', $langs->transnoentitiesnoconv($objimport->array_import_convertvalue[0][$val]['dict']));
482  } elseif (!empty($objimport->array_import_convertvalue[0][$val]['element'])) {
483  $this->errors[$error]['lib'] = $langs->trans('ErrorFieldRefNotIn', num2Alpha($key - 1), $newval, $langs->transnoentitiesnoconv($objimport->array_import_convertvalue[0][$val]['element']));
484  } else {
485  $this->errors[$error]['lib'] = 'ErrorBadDefinitionOfImportProfile';
486  }
487  $this->errors[$error]['type'] = 'FOREIGNKEY';
488  $errorforthistable++;
489  $error++;
490  }
491  }
492  }
493  } elseif ($objimport->array_import_convertvalue[0][$val]['rule'] == 'fetchidfromcodeandlabel') {
494  $isidorref = 'id';
495  if (!is_numeric($newval) && $newval != '' && !preg_match('/^id:/i', $newval)) {
496  $isidorref = 'ref';
497  }
498  $newval = preg_replace('/^(id|ref):/i', '', $newval);
499 
500  if ($isidorref == 'ref') {
501  $file = (empty($objimport->array_import_convertvalue[0][$val]['classfile']) ? $objimport->array_import_convertvalue[0][$val]['file'] : $objimport->array_import_convertvalue[0][$val]['classfile']);
502  $class = $objimport->array_import_convertvalue[0][$val]['class'];
503  $method = $objimport->array_import_convertvalue[0][$val]['method'];
504  $codefromfield = $objimport->array_import_convertvalue[0][$val]['codefromfield'];
505  $code = $arrayrecord[$arrayfield[$codefromfield]]['val'];
506  if ($this->cacheconvert[$file.'_'.$class.'_'.$method.'_'.$code][$newval] != '') {
507  $newval = $this->cacheconvert[$file.'_'.$class.'_'.$method.'_'.$code][$newval];
508  } else {
509  $resultload = dol_include_once($file);
510  if (empty($resultload)) {
511  dol_print_error(null, 'Error trying to call file='.$file.', class='.$class.', method='.$method.', code='.$code);
512  break;
513  }
514  $classinstance = new $class($this->db);
515  // Try the fetch from code and ref
516  $param_array = array('', $newval, $code);
517  call_user_func_array(array($classinstance, $method), $param_array);
518  $this->cacheconvert[$file.'_'.$class.'_'.$method.'_'.$code][$newval] = $classinstance->id;
519  if ($classinstance->id > 0) { // we found record
520  $newval = $classinstance->id;
521  } else {
522  if (!empty($objimport->array_import_convertvalue[0][$val]['dict'])) {
523  $this->errors[$error]['lib'] = $langs->trans('ErrorFieldValueNotIn', num2Alpha($key - 1), $newval, 'scale', $langs->transnoentitiesnoconv($objimport->array_import_convertvalue[0][$val]['dict']));
524  } else {
525  $this->errors[$error]['lib'] = 'ErrorFieldValueNotIn';
526  }
527  $this->errors[$error]['type'] = 'FOREIGNKEY';
528  $errorforthistable++;
529  $error++;
530  }
531  }
532  }
533  } elseif ($objimport->array_import_convertvalue[0][$val]['rule'] == 'zeroifnull') {
534  if (empty($newval)) {
535  $newval = '0';
536  }
537  } elseif ($objimport->array_import_convertvalue[0][$val]['rule'] == 'fetchidfromcodeunits' || $objimport->array_import_convertvalue[0][$val]['rule'] == 'fetchscalefromcodeunits') {
538  $file = (empty($objimport->array_import_convertvalue[0][$val]['classfile']) ? $objimport->array_import_convertvalue[0][$val]['file'] : $objimport->array_import_convertvalue[0][$val]['classfile']);
539  $class = $objimport->array_import_convertvalue[0][$val]['class'];
540  $method = $objimport->array_import_convertvalue[0][$val]['method'];
541  $units = $objimport->array_import_convertvalue[0][$val]['units'];
542  if ($this->cacheconvert[$file.'_'.$class.'_'.$method.'_'.$units][$newval] != '') {
543  $newval = $this->cacheconvert[$file.'_'.$class.'_'.$method.'_'.$units][$newval];
544  } else {
545  $resultload = dol_include_once($file);
546  if (empty($resultload)) {
547  dol_print_error(null, 'Error trying to call file='.$file.', class='.$class.', method='.$method.', units='.$units);
548  break;
549  }
550  $classinstance = new $class($this->db);
551  // Try the fetch from code or ref
552  call_user_func_array(array($classinstance, $method), array('', '', $newval, $units));
553  $scaleorid = (($objimport->array_import_convertvalue[0][$val]['rule'] == 'fetchidfromcodeunits') ? $classinstance->id : $classinstance->scale);
554  $this->cacheconvert[$file.'_'.$class.'_'.$method.'_'.$units][$newval] = $scaleorid;
555  //print 'We have made a '.$class.'->'.$method." to get a value from key '".$newval."' and we got '".$scaleorid."'.";exit;
556  if ($classinstance->id > 0) { // we found record
557  $newval = $scaleorid ? $scaleorid : 0;
558  } else {
559  if (!empty($objimport->array_import_convertvalue[0][$val]['dict'])) {
560  $this->errors[$error]['lib'] = $langs->trans('ErrorFieldValueNotIn', num2Alpha($key - 1), $newval, 'scale', $langs->transnoentitiesnoconv($objimport->array_import_convertvalue[0][$val]['dict']));
561  } else {
562  $this->errors[$error]['lib'] = 'ErrorFieldValueNotIn';
563  }
564  $this->errors[$error]['type'] = 'FOREIGNKEY';
565  $errorforthistable++;
566  $error++;
567  }
568  }
569  } elseif ($objimport->array_import_convertvalue[0][$val]['rule'] == 'getcustomercodeifauto') {
570  if (strtolower($newval) == 'auto') {
571  $this->thirdpartyobject->get_codeclient(0, 0);
572  $newval = $this->thirdpartyobject->code_client;
573  //print 'code_client='.$newval;
574  }
575  if (empty($newval)) {
576  $arrayrecord[($key - 1)]['type'] = -1; // If we get empty value, we will use "null"
577  }
578  } elseif ($objimport->array_import_convertvalue[0][$val]['rule'] == 'getsuppliercodeifauto') {
579  if (strtolower($newval) == 'auto') {
580  $this->thirdpartyobject->get_codefournisseur(0, 1);
581  $newval = $this->thirdpartyobject->code_fournisseur;
582  //print 'code_fournisseur='.$newval;
583  }
584  if (empty($newval)) {
585  $arrayrecord[($key - 1)]['type'] = -1; // If we get empty value, we will use "null"
586  }
587  } elseif ($objimport->array_import_convertvalue[0][$val]['rule'] == 'getcustomeraccountancycodeifauto') {
588  if (strtolower($newval) == 'auto') {
589  $this->thirdpartyobject->get_codecompta('customer');
590  $newval = $this->thirdpartyobject->code_compta;
591  //print 'code_compta='.$newval;
592  }
593  if (empty($newval)) {
594  $arrayrecord[($key - 1)]['type'] = -1; // If we get empty value, we will use "null"
595  }
596  } elseif ($objimport->array_import_convertvalue[0][$val]['rule'] == 'getsupplieraccountancycodeifauto') {
597  if (strtolower($newval) == 'auto') {
598  $this->thirdpartyobject->get_codecompta('supplier');
599  $newval = $this->thirdpartyobject->code_compta_fournisseur;
600  if (empty($newval)) {
601  $arrayrecord[($key - 1)]['type'] = -1; // If we get empty value, we will use "null"
602  }
603  //print 'code_compta_fournisseur='.$newval;
604  }
605  if (empty($newval)) {
606  $arrayrecord[($key - 1)]['type'] = -1; // If we get empty value, we will use "null"
607  }
608  } elseif ($objimport->array_import_convertvalue[0][$val]['rule'] == 'getrefifauto') {
609  if (strtolower($newval) == 'auto') {
610  $defaultref = '';
611 
612  $classModForNumber = $objimport->array_import_convertvalue[0][$val]['class'];
613  $pathModForNumber = $objimport->array_import_convertvalue[0][$val]['path'];
614 
615  if (!empty($classModForNumber) && !empty($pathModForNumber) && is_readable(DOL_DOCUMENT_ROOT.$pathModForNumber)) {
616  require_once DOL_DOCUMENT_ROOT.$pathModForNumber;
617  $modForNumber = new $classModForNumber();
618 
619  $tmpobject = null;
620  // Set the object with the date property when we can
621  if (!empty($objimport->array_import_convertvalue[0][$val]['classobject'])) {
622  $pathForObject = $objimport->array_import_convertvalue[0][$val]['pathobject'];
623  require_once DOL_DOCUMENT_ROOT.$pathForObject;
624  $tmpclassobject = $objimport->array_import_convertvalue[0][$val]['classobject'];
625  $tmpobject = new $tmpclassobject($this->db);
626  foreach ($arrayfield as $tmpkey => $tmpval) { // $arrayfield is array('c.ref'=>0, ...)
627  if (in_array($tmpkey, array('t.date', 'c.date_commande'))) {
628  $tmpobject->date = dol_stringtotime($arrayrecord[$arrayfield[$tmpkey]]['val'], 1);
629  }
630  }
631  }
632 
633  $defaultref = $modForNumber->getNextValue(null, $tmpobject);
634  }
635  if (is_numeric($defaultref) && $defaultref <= 0) { // If error
636  $defaultref = '';
637  }
638  $newval = $defaultref;
639  }
640  } elseif ($objimport->array_import_convertvalue[0][$val]['rule'] == 'compute') {
641  $file = (empty($objimport->array_import_convertvalue[0][$val]['classfile']) ? $objimport->array_import_convertvalue[0][$val]['file'] : $objimport->array_import_convertvalue[0][$val]['classfile']);
642  $class = $objimport->array_import_convertvalue[0][$val]['class'];
643  $method = $objimport->array_import_convertvalue[0][$val]['method'];
644  $resultload = dol_include_once($file);
645  if (empty($resultload)) {
646  dol_print_error(null, 'Error trying to call file='.$file.', class='.$class.', method='.$method);
647  break;
648  }
649  $classinstance = new $class($this->db);
650  $res = call_user_func_array(array($classinstance, $method), array(&$arrayrecord, $arrayfield, ($key - 1)));
651  if (empty($classinstance->error) && empty($classinstance->errors)) {
652  $newval = $res; // We get new value computed.
653  } else {
654  $this->errors[$error]['type'] = 'CLASSERROR';
655  $this->errors[$error]['lib'] = implode(
656  "\n",
657  array_merge([$classinstance->error], $classinstance->errors)
658  );
659  $errorforthistable++;
660  $error++;
661  }
662  } elseif ($objimport->array_import_convertvalue[0][$val]['rule'] == 'numeric') {
663  $newval = price2num($newval);
664  } elseif ($objimport->array_import_convertvalue[0][$val]['rule'] == 'accountingaccount') {
665  if (!getDolGlobalString('ACCOUNTING_MANAGE_ZERO')) {
666  $newval = rtrim(trim($newval), "0");
667  } else {
668  $newval = trim($newval);
669  }
670  }
671 
672  //print 'Val to use as insert is '.$newval.'<br>';
673  }
674 
675  // Test regexp
676  if (!empty($objimport->array_import_regex[0][$val]) && ($newval != '')) {
677  // If test regex string is "field@table" or "field@table:..." (means must exists into table ...)
678  $reg = array();
679  if (preg_match('/^(.+)@([^:]+)(:.+)?$/', $objimport->array_import_regex[0][$val], $reg)) {
680  $field = $reg[1];
681  $table = $reg[2];
682  $filter = !empty($reg[3]) ? substr($reg[3], 1) : '';
683 
684  $cachekey = $field.'@'.$table;
685  if (!empty($filter)) {
686  $cachekey .= ':'.$filter;
687  }
688 
689  // Load content of field@table into cache array
690  if (!is_array($this->cachefieldtable[$cachekey])) { // If content of field@table not already loaded into cache
691  $sql = "SELECT ".$field." as aliasfield FROM ".$table;
692  if (!empty($filter)) {
693  $sql .= ' WHERE '.$filter;
694  }
695 
696  $resql = $this->db->query($sql);
697  if ($resql) {
698  $num = $this->db->num_rows($resql);
699  $i = 0;
700  while ($i < $num) {
701  $obj = $this->db->fetch_object($resql);
702  if ($obj) {
703  $this->cachefieldtable[$cachekey][] = $obj->aliasfield;
704  }
705  $i++;
706  }
707  } else {
708  dol_print_error($this->db);
709  }
710  }
711 
712  // Now we check cache is not empty (should not) and key is into cache
713  if (!is_array($this->cachefieldtable[$cachekey]) || !in_array($newval, $this->cachefieldtable[$cachekey])) {
714  $tableforerror = $table;
715  if (!empty($filter)) {
716  $tableforerror .= ':'.$filter;
717  }
718  $this->errors[$error]['lib'] = $langs->transnoentitiesnoconv('ErrorFieldValueNotIn', num2Alpha($key - 1), $newval, $field, $tableforerror);
719  $this->errors[$error]['type'] = 'FOREIGNKEY';
720  $errorforthistable++;
721  $error++;
722  }
723  } elseif (!preg_match('/'.$objimport->array_import_regex[0][$val].'/i', $newval)) {
724  // If test is just a static regex
725  //if ($key == 19) print "xxx".$newval."zzz".$objimport->array_import_regex[0][$val]."<br>";
726  $this->errors[$error]['lib'] = $langs->transnoentitiesnoconv('ErrorWrongValueForField', num2Alpha($key - 1), $newval, $objimport->array_import_regex[0][$val]);
727  $this->errors[$error]['type'] = 'REGEX';
728  $errorforthistable++;
729  $error++;
730  }
731  }
732 
733  // Check HTML injection
734  $inj = testSqlAndScriptInject($newval, 0);
735  if ($inj) {
736  $this->errors[$error]['lib'] = $langs->transnoentitiesnoconv('ErrorHtmlInjectionForField', num2Alpha($key - 1), dol_trunc($newval, 100));
737  $this->errors[$error]['type'] = 'HTMLINJECTION';
738  $errorforthistable++;
739  $error++;
740  }
741 
742  // Other tests
743  // ...
744  }
745 
746  // Define $listfields and $listvalues to build the SQL request
747  if (isModEnabled("socialnetworks") && strpos($fieldname, "socialnetworks") !== false) {
748  if (!in_array("socialnetworks", $listfields)) {
749  $listfields[] = "socialnetworks";
750  $socialkey = array_search("socialnetworks", $listfields); // Return position of 'socialnetworks' key in array
751  $listvalues[$socialkey] = '';
752  }
753  //var_dump($newval); var_dump($arrayrecord[($key - 1)]['type']);
754  if (!empty($newval) && $arrayrecord[($key - 1)]['type'] > 0) {
755  $socialkey = array_search("socialnetworks", $listfields); // Return position of 'socialnetworks' key in array
756  //var_dump('sk='.$socialkey); // socialkey=19
757  $socialnetwork = explode("_", $fieldname)[1];
758  if (empty($listvalues[$socialkey]) || $listvalues[$socialkey] == "null") {
759  $json = new stdClass();
760  $json->$socialnetwork = $newval;
761  $listvalues[$socialkey] = json_encode($json);
762  } else {
763  $jsondata = $listvalues[$socialkey];
764  $json = json_decode($jsondata);
765  $json->$socialnetwork = $newval;
766  $listvalues[$socialkey] = json_encode($json);
767  }
768  }
769  } else {
770  $listfields[] = $fieldname;
771  // Note: arrayrecord (and 'type') is filled with ->import_read_record called by import.php page before calling import_insert
772  if (empty($newval) && $arrayrecord[($key - 1)]['type'] < 0) {
773  $listvalues[] = ($newval == '0' ? (int) $newval : "null");
774  } elseif (empty($newval) && $arrayrecord[($key - 1)]['type'] == 0) {
775  $listvalues[] = "''";
776  } else {
777  $listvalues[] = "'".$this->db->escape($newval)."'";
778  }
779  }
780  }
781  $i++;
782  }
783 
784  // We add hidden fields (but only if there is at least one field to add into table)
785  // We process here all the fields that were declared into the array $this->import_fieldshidden_array of the descriptor file.
786  // Previously we processed the ->import_fields_array.
787  if (!empty($listfields) && is_array($objimport->array_import_fieldshidden[0])) {
788  // Loop on each hidden fields to add them into listfields/listvalues
789  foreach ($objimport->array_import_fieldshidden[0] as $tmpkey => $tmpval) {
790  if (!preg_match('/^' . preg_quote($alias, '/') . '\./', $tmpkey)) {
791  continue; // Not a field of current table
792  }
793  $keyfield = preg_replace('/^' . preg_quote($alias, '/') . '\./', '', $tmpkey);
794 
795  if (in_array($keyfield, $listfields)) { // avoid duplicates in insert
796  continue;
797  } elseif ($tmpval == 'user->id') {
798  $listfields[] = $keyfield;
799  $listvalues[] = ((int) $user->id);
800  } elseif (preg_match('/^lastrowid-/', $tmpval)) {
801  $tmp = explode('-', $tmpval);
802  $lastinsertid = (isset($last_insert_id_array[$tmp[1]])) ? $last_insert_id_array[$tmp[1]] : 0;
803  $listfields[] = $keyfield;
804  $listvalues[] = (int) $lastinsertid;
805  //print $tmpkey."-".$tmpval."-".$listfields."-".$listvalues."<br>";exit;
806  } elseif (preg_match('/^const-/', $tmpval)) {
807  $tmp = explode('-', $tmpval, 2);
808  $listfields[] = $keyfield;
809  $listvalues[] = "'".$this->db->escape($tmp[1])."'";
810  } elseif (preg_match('/^rule-/', $tmpval)) {
811  $fieldname = $tmpkey;
812  if (!empty($objimport->array_import_convertvalue[0][$fieldname])) {
813  if ($objimport->array_import_convertvalue[0][$fieldname]['rule'] == 'compute') {
814  $file = (empty($objimport->array_import_convertvalue[0][$fieldname]['classfile']) ? $objimport->array_import_convertvalue[0][$fieldname]['file'] : $objimport->array_import_convertvalue[0][$fieldname]['classfile']);
815  $class = $objimport->array_import_convertvalue[0][$fieldname]['class'];
816  $method = $objimport->array_import_convertvalue[0][$fieldname]['method'];
817  $type = $objimport->array_import_convertvalue[0][$fieldname]['type'];
818  $resultload = dol_include_once($file);
819  if (empty($resultload)) {
820  dol_print_error(null, 'Error trying to call file=' . $file . ', class=' . $class . ', method=' . $method);
821  break;
822  }
823  $classinstance = new $class($this->db);
824  $res = call_user_func_array(array($classinstance, $method), array(&$arrayrecord, $arrayfield, ($key - 1)));
825  if (empty($classinstance->error) && empty($classinstance->errors)) {
826  $fieldArr = explode('.', $fieldname);
827  if (count($fieldArr) > 0) {
828  $fieldname = $fieldArr[1];
829  }
830 
831  // Set $listfields and $listvalues
832  $listfields[] = $fieldname;
833  if ($type == 'int') {
834  $listvalues[] = (int) $res;
835  } elseif ($type == 'double') {
836  $listvalues[] = (float) $res;
837  } else {
838  $listvalues[] = "'".$this->db->escape($res)."'";
839  }
840  } else {
841  $this->errors[$error]['type'] = 'CLASSERROR';
842  $this->errors[$error]['lib'] = implode(
843  "\n",
844  array_merge([$classinstance->error], $classinstance->errors)
845  );
846  $errorforthistable++;
847  $error++;
848  }
849  }
850  }
851  } else {
852  $this->errors[$error]['lib'] = 'Bad value of profile setup '.$tmpval.' for array_import_fieldshidden';
853  $this->errors[$error]['type'] = 'Import profile setup';
854  $error++;
855  }
856  }
857  }
858  //print 'listfields='.$listfields.'<br>listvalues='.$listvalues.'<br>';
859 
860  // If no error for this $alias/$tablename, we have a complete $listfields and $listvalues that are defined
861  // so we can try to make the insert or update now.
862  if (!$errorforthistable) {
863  //print "$alias/$tablename/$listfields/$listvalues<br>";
864  if (!empty($listfields)) {
865  $updatedone = false;
866  $insertdone = false;
867 
868  $is_table_category_link = false;
869  $fname = 'rowid';
870  if (strpos($tablename, '_categorie_') !== false) {
871  $is_table_category_link = true;
872  $fname = '*';
873  }
874 
875  if (!empty($updatekeys)) {
876  // We do SELECT to get the rowid, if we already have the rowid, it's to be used below for related tables (extrafields)
877 
878  if (empty($lastinsertid)) { // No insert done yet for a parent table
879  $sqlSelect = "SELECT ".$fname." FROM ".$tablename;
880  $data = array_combine($listfields, $listvalues);
881  $where = array(); // filters to forge SQL request
882  $filters = array(); // filters to forge output error message
883  foreach ($updatekeys as $key) {
884  $col = $objimport->array_import_updatekeys[0][$key];
885  $key = preg_replace('/^.*\./i', '', $key);
886  if (isModEnabled("socialnetworks") && strpos($key, "socialnetworks") !== false) {
887  $tmp = explode("_", $key);
888  $key = $tmp[0];
889  $socialnetwork = $tmp[1];
890  $jsondata = $data[$key];
891  $json = json_decode($jsondata);
892  $stringtosearch = json_encode($socialnetwork).':'.json_encode($json->$socialnetwork);
893  //var_dump($stringtosearch);
894  //var_dump($this->db->escape($stringtosearch)); // This provide a value for sql string (but not for a like)
895  $where[] = $key." LIKE '%".$this->db->escape($this->db->escapeforlike($stringtosearch))."%'";
896  $filters[] = $col." LIKE '%".$this->db->escape($this->db->escapeforlike($stringtosearch))."%'";
897  //var_dump($where[1]); // This provide a value for sql string inside a like
898  } else {
899  $where[] = $key.' = '.$data[$key];
900  $filters[] = $col.' = '.$data[$key];
901  }
902  }
903  if (!empty($tablewithentity_cache[$tablename])) {
904  $where[] = "entity IN (".getEntity($this->getElementFromTableWithPrefix($tablename)).")";
905  $filters[] = "entity IN (".getEntity($this->getElementFromTableWithPrefix($tablename)).")";
906  }
907  $sqlSelect .= " WHERE ".implode(' AND ', $where);
908 
909  $resql = $this->db->query($sqlSelect);
910  if ($resql) {
911  $num_rows = $this->db->num_rows($resql);
912  if ($num_rows == 1) {
913  $res = $this->db->fetch_object($resql);
914  $lastinsertid = $res->rowid;
915  if ($is_table_category_link) {
916  $lastinsertid = 'linktable';
917  } // used to apply update on tables like llx_categorie_product and avoid being blocked for all file content if at least one entry already exists
918  $last_insert_id_array[$tablename] = $lastinsertid;
919  } elseif ($num_rows > 1) {
920  $this->errors[$error]['lib'] = $langs->trans('MultipleRecordFoundWithTheseFilters', implode(', ', $filters));
921  $this->errors[$error]['type'] = 'SQL';
922  $error++;
923  } else {
924  // No record found with filters, insert will be tried below
925  }
926  } else {
927  //print 'E';
928  $this->errors[$error]['lib'] = $this->db->lasterror();
929  $this->errors[$error]['type'] = 'SQL';
930  $error++;
931  }
932  } else {
933  // We have a last INSERT ID (got by previous pass), so we check if we have a row referencing this foreign key.
934  // This is required when updating table with some extrafields. When inserting a record in parent table, we can make
935  // a direct insert into subtable extrafields, but when me wake an update, the insertid is defined and the child record
936  // may already exists. So we rescan the extrafield table to know if record exists or not for the rowid.
937  // Note: For extrafield tablename, we have in importfieldshidden_array an entry 'extra.fk_object'=>'lastrowid-tableparent' so $keyfield is 'fk_object'
938  $sqlSelect = "SELECT rowid FROM ".$tablename;
939 
940  if (empty($keyfield)) {
941  $keyfield = 'rowid';
942  }
943  $sqlSelect .= " WHERE ".$keyfield." = ".((int) $lastinsertid);
944 
945  if (!empty($tablewithentity_cache[$tablename])) {
946  $sqlSelect .= " AND entity IN (".getEntity($this->getElementFromTableWithPrefix($tablename)).")";
947  }
948 
949  $resql = $this->db->query($sqlSelect);
950  if ($resql) {
951  $res = $this->db->fetch_object($resql);
952  if ($this->db->num_rows($resql) == 1) {
953  // We have a row referencing this last foreign key, continue with UPDATE.
954  } else {
955  // No record found referencing this last foreign key,
956  // force $lastinsertid to 0 so we INSERT below.
957  $lastinsertid = 0;
958  }
959  } else {
960  //print 'E';
961  $this->errors[$error]['lib'] = $this->db->lasterror();
962  $this->errors[$error]['type'] = 'SQL';
963  $error++;
964  }
965  }
966 
967  if (!empty($lastinsertid)) {
968  // We db escape social network field because he isn't in field creation
969  if (in_array("socialnetworks", $listfields)) {
970  $socialkey = array_search("socialnetworks", $listfields);
971  $tmpsql = $listvalues[$socialkey];
972  $listvalues[$socialkey] = "'".$this->db->escape($tmpsql)."'";
973  }
974 
975  // Build SQL UPDATE request
976  $sqlstart = "UPDATE ".$tablename;
977 
978  $data = array_combine($listfields, $listvalues);
979  $set = array();
980  foreach ($data as $key => $val) {
981  $set[] = $key." = ".$val; // $val was escaped/sanitized previously
982  }
983  $sqlstart .= " SET ".implode(', ', $set).", import_key = '".$this->db->escape($importid)."'";
984 
985  if (empty($keyfield)) {
986  $keyfield = 'rowid';
987  }
988  $sqlend = " WHERE ".$keyfield." = ".((int) $lastinsertid);
989 
990  if ($is_table_category_link) {
991  '@phan-var-force string[] $where';
992  $sqlend = " WHERE " . implode(' AND ', $where);
993  }
994 
995  if (!empty($tablewithentity_cache[$tablename])) {
996  $sqlend .= " AND entity IN (".getEntity($this->getElementFromTableWithPrefix($tablename)).")";
997  }
998 
999  $sql = $sqlstart.$sqlend;
1000 
1001  // Run update request
1002  $resql = $this->db->query($sql);
1003  if ($resql) {
1004  // No error, update has been done. $this->db->db->affected_rows can be 0 if data hasn't changed
1005  $updatedone = true;
1006  } else {
1007  //print 'E';
1008  $this->errors[$error]['lib'] = $this->db->lasterror();
1009  $this->errors[$error]['type'] = 'SQL';
1010  $error++;
1011  }
1012  }
1013  }
1014 
1015  // Update not done, we do insert
1016  if (!$error && !$updatedone) {
1017  // We db escape social network field because he isn't in field creation
1018  if (in_array("socialnetworks", $listfields)) {
1019  $socialkey = array_search("socialnetworks", $listfields);
1020  $tmpsql = $listvalues[$socialkey];
1021  $listvalues[$socialkey] = "'".$this->db->escape($tmpsql)."'";
1022  }
1023 
1024  // Build SQL INSERT request
1025  $sqlstart = "INSERT INTO ".$tablename."(".implode(", ", $listfields).", import_key";
1026  $sqlend = ") VALUES(".implode(', ', $listvalues).", '".$this->db->escape($importid)."'";
1027  if (!empty($tablewithentity_cache[$tablename])) {
1028  $sqlstart .= ", entity";
1029  $sqlend .= ", ".$conf->entity;
1030  }
1031  if (!empty($objimport->array_import_tables_creator[0][$alias])) {
1032  $sqlstart .= ", ".$objimport->array_import_tables_creator[0][$alias];
1033  $sqlend .= ", ".$user->id;
1034  }
1035  $sql = $sqlstart.$sqlend.")";
1036  //dol_syslog("import_csv.modules", LOG_DEBUG);
1037 
1038  // Run insert request
1039  if ($sql) {
1040  $resql = $this->db->query($sql);
1041  if ($resql) {
1042  if (!$is_table_category_link) {
1043  $last_insert_id_array[$tablename] = $this->db->last_insert_id($tablename); // store the last inserted auto_increment id for each table, so that child tables can be inserted with the appropriate id. This must be done just after the INSERT request, else we risk losing the id (because another sql query will be issued somewhere in Dolibarr).
1044  }
1045  $insertdone = true;
1046  } else {
1047  //print 'E';
1048  $this->errors[$error]['lib'] = $this->db->lasterror();
1049  $this->errors[$error]['type'] = 'SQL';
1050  $error++;
1051  }
1052  }
1053  }
1054  }
1055  /*else
1056  {
1057  dol_print_error(null,'ErrorFieldListEmptyFor '.$alias."/".$tablename);
1058  }*/
1059  }
1060 
1061  if ($error) {
1062  break;
1063  }
1064  }
1065 
1066  if ($updatedone) {
1067  $this->nbupdate++;
1068  }
1069  if ($insertdone) {
1070  $this->nbinsert++;
1071  }
1072  }
1073 
1074  return 1;
1075  }
1076 }
1077 
1084 function cleansep($value)
1085 {
1086  return str_replace(array(',', ';'), '/', $value);
1087 }
versionphparray()
Return version PHP.
Definition: admin.lib.php:130
versioncompare($versionarray1, $versionarray2)
Compare 2 versions (stored into 2 arrays).
Definition: admin.lib.php:68
Class to import CSV files.
write_header_example($outputlangs)
Output header of an example file for this format.
import_get_nb_of_lines($file)
Return nb of records.
import_insert($arrayrecord, $array_match_file_to_database, $objimport, $maxfields, $importid, $updatekeys)
Insert a record into database.
__construct($db, $datatoimport)
Constructor.
import_read_record()
Return array of next record in input file.
write_record_example($outputlangs, $contentlinevalues)
Output record of an example file for this format.
write_footer_example($outputlangs)
Output footer of an example file for this format.
import_close_file()
Close file handle.
import_read_header()
Input header line from file.
write_title_example($outputlangs, $headerlinefields)
Output title line of an example file for this format.
import_open_file($file)
Open input file.
Parent class for import file readers.
getElementFromTableWithPrefix($tableNameWithPrefix)
Get element from table name with prefix.
Class to manage third parties objects (customers, suppliers, prospects...)
if(isModEnabled('invoice') && $user->hasRight('facture', 'lire')) if((isModEnabled('fournisseur') &&!getDolGlobalString('MAIN_USE_NEW_SUPPLIERMOD') && $user->hasRight("fournisseur", "facture", "lire"))||(isModEnabled('supplier_invoice') && $user->hasRight("supplier_invoice", "lire"))) if(isModEnabled('don') && $user->hasRight('don', 'lire')) if(isModEnabled('tax') && $user->hasRight('tax', 'charges', 'lire')) if(isModEnabled('invoice') &&isModEnabled('order') && $user->hasRight("commande", "lire") &&!getDolGlobalString('WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER')) $sql
Social contributions to pay.
Definition: index.php:751
dol_stringtotime($string, $gm=1)
Convert a string date into a GM Timestamps date Warning: YYYY-MM-DDTHH:MM:SS+02:00 (RFC3339) is not s...
Definition: date.lib.php:426
dol_count_nb_of_line($file)
Count number of lines in a file.
Definition: files.lib.php:602
dol_osencode($str)
Return a string encoded into OS filesystem encoding.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dol_strlen($string, $stringencoding='UTF-8')
Make a strlen call.
if(!function_exists('dol_getprefix')) dol_include_once($relpath, $classname='')
Make an include_once using default root and alternate root if it fails.
num2Alpha($n)
Return a numeric value into an Excel like column number.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
dol_trunc($string, $size=40, $trunc='right', $stringencoding='UTF-8', $nodot=0, $display=0)
Truncate a string to a particular length adding '…' if string larger than length.
getDolGlobalString($key, $default='')
Return dolibarr global constant string value.
isModEnabled($module)
Is Dolibarr module enabled.
utf8_check($str)
Check if a string is in UTF8.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
cleansep($value)
Clean a string from separator.
testSqlAndScriptInject($val, $type)
Security: WAF layer for SQL Injection and XSS Injection (scripts) protection (Filters on GET,...
Definition: main.inc.php:123
div float
Unit price before taxes.
Definition: style.css.php:963