dolibarr 20.0.0
import_xlsx.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 MDW <mdeweerd@users.noreply.github.com>
7 * Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <https://www.gnu.org/licenses/>.
21 * or see https://www.gnu.org/
22 */
23
30use PhpOffice\PhpSpreadsheet\Reader\Xlsx;
31use PhpOffice\PhpSpreadsheet\Spreadsheet;
32use PhpOffice\PhpSpreadsheet\Style\Alignment;
33use PhpOffice\PhpSpreadsheet\Shared\Date;
34
35require_once DOL_DOCUMENT_ROOT . '/core/modules/import/modules_import.php';
36
37
42{
46 public $db;
47
51 public $id;
52
57 public $version = 'dolibarr';
58
59 public $label_lib; // Label of external lib used by driver
60
61 public $version_lib; // Version of external lib used by driver
62
63 public $separator;
64
65 public $file; // Path of file
66
67 public $handle; // Handle fichier
68
69 public $cacheconvert = array(); // Array to cache list of value found after a conversion
70
71 public $cachefieldtable = array(); // Array to cache list of value found into fields@tables
72
73 public $nbinsert = 0; // # of insert done during the import
74
75 public $nbupdate = 0; // # of update done during the import
76
77 public $workbook; // temporary import file
78
79 public $record; // current record
80
81 public $headers;
82
83
90 public function __construct($db, $datatoimport)
91 {
92 global $langs;
93
94 parent::__construct();
95 $this->db = $db;
96
97 // this is used as an extension from the example file code, so we have to put xlsx here !!!
98 $this->id = 'xlsx'; // Same value as xxx in file name export_xxx.modules.php
99 $this->label = 'Excel 2007'; // Label of driver
100 $this->desc = $langs->trans("Excel2007FormatDesc");
101 $this->extension = 'xlsx'; // Extension for generated file by this driver
102 $this->picto = 'mime/xls'; // Picto (This is not used by the example file code as Mime type, too bad ...)
103 $this->version = '1.0'; // Driver version
104 $this->phpmin = array(7, 1); // Minimum version of PHP required by module
105
106 require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
107 if (versioncompare($this->phpmin, versionphparray()) > 0) {
108 dol_syslog("Module need a higher PHP version");
109 $this->error = "Module need a higher PHP version";
110 return;
111 }
112
113 // If driver use an external library, put its name here
114 require_once DOL_DOCUMENT_ROOT.'/includes/phpoffice/phpspreadsheet/src/autoloader.php';
115 require_once DOL_DOCUMENT_ROOT.'/includes/Psr/autoloader.php';
116 require_once PHPEXCELNEW_PATH.'Spreadsheet.php';
117 $this->workbook = new Spreadsheet();
118
119 // If driver use an external library, put its name here
120 if (!class_exists('ZipArchive')) { // For Excel2007
121 $langs->load("errors");
122 $this->error = $langs->trans('ErrorPHPNeedModule', 'zip');
123 return;
124 }
125 $this->label_lib = 'PhpSpreadSheet';
126 $this->version_lib = '1.8.0';
127
128 $this->datatoimport = $datatoimport;
129 if (preg_match('/^societe_/', $datatoimport)) {
130 $this->thirdpartyobject = new Societe($this->db);
131 }
132 }
133
134
135 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
142 public function write_header_example($outputlangs)
143 {
144 // phpcs:enable
145 global $user, $conf, $langs, $file;
146 // create a temporary object, the final output will be generated in footer
147 $this->workbook->getProperties()->setCreator($user->getFullName($outputlangs) . ' - Dolibarr ' . DOL_VERSION);
148 $this->workbook->getProperties()->setTitle($outputlangs->trans("Import") . ' - ' . $file);
149 $this->workbook->getProperties()->setSubject($outputlangs->trans("Import") . ' - ' . $file);
150 $this->workbook->getProperties()->setDescription($outputlangs->trans("Import") . ' - ' . $file);
151
152 $this->workbook->setActiveSheetIndex(0);
153 $this->workbook->getActiveSheet()->setTitle($outputlangs->trans("Sheet"));
154 $this->workbook->getActiveSheet()->getDefaultRowDimension()->setRowHeight(16);
155
156 return '';
157 }
158
159 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
167 public function write_title_example($outputlangs, $headerlinefields)
168 {
169 // phpcs:enable
170 global $conf;
171 $this->workbook->getActiveSheet()->getStyle('1')->getFont()->setBold(true);
172 $this->workbook->getActiveSheet()->getStyle('1')->getAlignment()->setHorizontal(Alignment::HORIZONTAL_LEFT);
173
174 $col = 1;
175 foreach ($headerlinefields as $field) {
176 $this->workbook->getActiveSheet()->SetCellValueByColumnAndRow($col, 1, $outputlangs->transnoentities($field));
177 // set autowidth
178 //$this->workbook->getActiveSheet()->getColumnDimension($this->column2Letter($col + 1))->setAutoSize(true);
179 $col++;
180 }
181
182 return ''; // final output will be generated in footer
183 }
184
185 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
193 public function write_record_example($outputlangs, $contentlinevalues)
194 {
195 // phpcs:enable
196 $col = 1;
197 $row = 2;
198 foreach ($contentlinevalues as $cell) {
199 $this->workbook->getActiveSheet()->SetCellValueByColumnAndRow($col, $row, $cell);
200 $col++;
201 }
202
203 return ''; // final output will be generated in footer
204 }
205
206 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
213 public function write_footer_example($outputlangs)
214 {
215 // phpcs:enable
216 // return the file content as a string
217 $tempfile = tempnam(sys_get_temp_dir(), 'dol');
218 $objWriter = new PhpOffice\PhpSpreadsheet\Writer\Xlsx($this->workbook);
219 $objWriter->save($tempfile);
220 $this->workbook->disconnectWorksheets();
221 unset($this->workbook);
222
223 $content = file_get_contents($tempfile);
224 unlink($tempfile);
225 return $content;
226 }
227
228
229
230 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
237 public function import_open_file($file)
238 {
239 // phpcs:enable
240 global $langs;
241 $ret = 1;
242
243 dol_syslog(get_class($this) . "::open_file file=" . $file);
244
245 $reader = new Xlsx();
246 $this->workbook = $reader->load($file);
247 $this->record = 1;
248 $this->file = $file;
249
250 return $ret;
251 }
252
253
254 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
261 public function import_get_nb_of_lines($file)
262 {
263 // phpcs:enable
264 $reader = new Xlsx();
265 $this->workbook = $reader->load($file);
266
267 $rowcount = $this->workbook->getActiveSheet()->getHighestDataRow();
268
269 $this->workbook->disconnectWorksheets();
270 unset($this->workbook);
271
272 return $rowcount;
273 }
274
275
276 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
282 public function import_read_header()
283 {
284 // phpcs:enable
285 // This is not called by the import code !!!
286 $this->headers = array();
287 $xlsx = new Xlsx();
288 $info = $xlsx->listWorksheetinfo($this->file);
289 $countcolumns = $info[0]['totalColumns'];
290 for ($col = 1; $col <= $countcolumns; $col++) {
291 $this->headers[$col] = $this->workbook->getActiveSheet()->getCellByColumnAndRow($col, 1)->getValue();
292 }
293 return 0;
294 }
295
296
297 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
303 public function import_read_record()
304 {
305 // phpcs:enable
306 $rowcount = $this->workbook->getActiveSheet()->getHighestDataRow();
307 if ($this->record > $rowcount) {
308 return false;
309 }
310 $array = array();
311
312 $xlsx = new Xlsx();
313 $info = $xlsx->listWorksheetinfo($this->file);
314 $countcolumns = $info[0]['totalColumns'];
315
316 for ($col = 1; $col <= $countcolumns; $col++) {
317 $tmpcell = $this->workbook->getActiveSheet()->getCellByColumnAndRow($col, $this->record);
318
319 $val = $tmpcell->getValue();
320
321 if (Date::isDateTime($tmpcell)) {
322 // For date field, we use the standard date format string.
323 $dateValue = Date::excelToDateTimeObject($val);
324 $val = $dateValue->format('Y-m-d H:i:s');
325 }
326
327 $array[$col]['val'] = $val;
328 $array[$col]['type'] = (dol_strlen($val) ? 1 : -1); // If empty we consider it null
329 }
330 $this->record++;
331
332 unset($xlsx);
333
334 return $array;
335 }
336
337 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
343 public function import_close_file()
344 {
345 // phpcs:enable
346 $this->workbook->disconnectWorksheets();
347 unset($this->workbook);
348 return 0;
349 }
350
351
352 // What is this doing here ? it is common to all imports, is should be in the parent class
353 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
365 public function import_insert($arrayrecord, $array_match_file_to_database, $objimport, $maxfields, $importid, $updatekeys)
366 {
367 // phpcs:enable
368 global $langs, $conf, $user;
369 global $thirdparty_static; // Specific to thirdparty import
370 global $tablewithentity_cache; // Cache to avoid to call desc at each rows on tables
371
372 $error = 0;
373 $warning = 0;
374 $this->errors = array();
375 $this->warnings = array();
376
377 //dol_syslog("import_csv.modules maxfields=".$maxfields." importid=".$importid);
378
379 //var_dump($array_match_file_to_database);
380 //var_dump($arrayrecord); exit;
381
382 $array_match_database_to_file = array_flip($array_match_file_to_database);
383 $sort_array_match_file_to_database = $array_match_file_to_database;
384 ksort($sort_array_match_file_to_database);
385
386 //var_dump($sort_array_match_file_to_database);
387
388 if (count($arrayrecord) == 0 || (count($arrayrecord) == 1 && empty($arrayrecord[1]['val']))) {
389 //print 'W';
390 $this->warnings[$warning]['lib'] = $langs->trans('EmptyLine');
391 $this->warnings[$warning]['type'] = 'EMPTY';
392 $warning++;
393 } else {
394 $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)
395 $updatedone = false;
396 $insertdone = false;
397 // For each table to insert, me make a separate insert
398 foreach ($objimport->array_import_tables[0] as $alias => $tablename) {
399 // Build sql request
400 $sql = '';
401 $listfields = array();
402 $listvalues = array();
403 $i = 0;
404 $errorforthistable = 0;
405
406 // Define $tablewithentity_cache[$tablename] if not already defined
407 if (!isset($tablewithentity_cache[$tablename])) { // keep this test with "isset"
408 dol_syslog("Check if table " . $tablename . " has an entity field");
409 $resql = $this->db->DDLDescTable($tablename, 'entity');
410 if ($resql) {
411 $obj = $this->db->fetch_object($resql);
412 if ($obj) {
413 $tablewithentity_cache[$tablename] = 1; // table contains entity field
414 } else {
415 $tablewithentity_cache[$tablename] = 0; // table does not contain entity field
416 }
417 } else {
418 dol_print_error($this->db);
419 }
420 } else {
421 //dol_syslog("Table ".$tablename." check for entity into cache is ".$tablewithentity_cache[$tablename]);
422 }
423
424 // Define array to convert fields ('c.ref', ...) into column index (1, ...)
425 $arrayfield = array();
426 foreach ($sort_array_match_file_to_database as $key => $val) {
427 $arrayfield[$val] = ($key);
428 }
429
430 // $arrayrecord start at key 1
431 // $sort_array_match_file_to_database start at key 1
432
433 // Loop on each fields in the match array: $key = 1..n, $val=alias of field (s.nom)
434 foreach ($sort_array_match_file_to_database as $key => $val) {
435 $fieldalias = preg_replace('/\..*$/i', '', $val);
436 $fieldname = preg_replace('/^.*\./i', '', $val);
437
438 if ($alias != $fieldalias) {
439 continue; // Not a field of current table
440 }
441
442 if ($key <= $maxfields) {
443 // Set $newval with value to insert and set $listvalues with sql request part for insert
444 $newval = '';
445 if ($arrayrecord[($key)]['type'] > 0) {
446 $newval = $arrayrecord[($key)]['val']; // If type of field into input file is not empty string (so defined into input file), we get value
447 }
448
449 //var_dump($newval);var_dump($val);
450 //var_dump($objimport->array_import_convertvalue[0][$val]);
451
452 // Make some tests on $newval
453
454 // Is it a required field ?
455 if (preg_match('/\*/', $objimport->array_import_fields[0][$val]) && ((string) $newval == '')) {
456 $this->errors[$error]['lib'] = $langs->trans('ErrorMissingMandatoryValue', num2Alpha($key - 1));
457 $this->errors[$error]['type'] = 'NOTNULL';
458 $errorforthistable++;
459 $error++;
460 } else {
461 // Test format only if field is not a missing mandatory field (field may be a value or empty but not mandatory)
462 // We convert field if required
463 if (!empty($objimport->array_import_convertvalue[0][$val])) {
464 //print 'Must convert '.$newval.' with rule '.join(',',$objimport->array_import_convertvalue[0][$val]).'. ';
465 if ($objimport->array_import_convertvalue[0][$val]['rule'] == 'fetchidfromcodeid'
466 || $objimport->array_import_convertvalue[0][$val]['rule'] == 'fetchidfromref'
467 || $objimport->array_import_convertvalue[0][$val]['rule'] == 'fetchidfromcodeorlabel'
468 ) {
469 // 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.
470 $isidorref = 'id';
471 if (!is_numeric($newval) && $newval != '' && !preg_match('/^id:/i', $newval)) {
472 $isidorref = 'ref';
473 }
474 $newval = preg_replace('/^(id|ref):/i', '', $newval); // Remove id: or ref: that was used to force if field is id or ref
475 //print 'Newval is now "'.$newval.'" and is type '.$isidorref."<br>\n";
476
477 if ($isidorref == 'ref') { // If value into input import file is a ref, we apply the function defined into descriptor
478 $file = (empty($objimport->array_import_convertvalue[0][$val]['classfile']) ? $objimport->array_import_convertvalue[0][$val]['file'] : $objimport->array_import_convertvalue[0][$val]['classfile']);
479 $class = $objimport->array_import_convertvalue[0][$val]['class'];
480 $method = $objimport->array_import_convertvalue[0][$val]['method'];
481 if ($this->cacheconvert[$file . '_' . $class . '_' . $method . '_'][$newval] != '') {
482 $newval = $this->cacheconvert[$file . '_' . $class . '_' . $method . '_'][$newval];
483 } else {
484 $resultload = dol_include_once($file);
485 if (empty($resultload)) {
486 dol_print_error(null, 'Error trying to call file=' . $file . ', class=' . $class . ', method=' . $method);
487 break;
488 }
489 $classinstance = new $class($this->db);
490 if ($class == 'CGenericDic') {
491 $classinstance->element = $objimport->array_import_convertvalue[0][$val]['element'];
492 $classinstance->table_element = $objimport->array_import_convertvalue[0][$val]['table_element'];
493 }
494
495 // Try the fetch from code or ref
496 $param_array = array('', $newval);
497 if ($class == 'AccountingAccount') {
498 //var_dump($arrayrecord[0]['val']);
499 /*include_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountancysystem.class.php';
500 $tmpchartofaccount = new AccountancySystem($this->db);
501 $tmpchartofaccount->fetch(getDolGlobalInt('CHARTOFACCOUNTS'));
502 //var_dump($tmpchartofaccount->ref.' - '.$arrayrecord[0]['val']);
503 if ((! (getDolGlobalInt('CHARTOFACCOUNTS') > 0)) || $tmpchartofaccount->ref != $arrayrecord[0]['val'])
504 {
505 $this->errors[$error]['lib']=$langs->trans('ErrorImportOfChartLimitedToCurrentChart', $tmpchartofaccount->ref);
506 $this->errors[$error]['type']='RESTRICTONCURRENCTCHART';
507 $errorforthistable++;
508 $error++;
509 }*/
510 $param_array = array('', $newval, 0, $arrayrecord[0]['val']); // Param to fetch parent from account, in chart.
511 }
512
513 $result = call_user_func_array(array($classinstance, $method), $param_array);
514
515 // If duplicate record found
516 if (!($classinstance->id != '') && $result == -2) {
517 $this->errors[$error]['lib'] = $langs->trans('ErrorMultipleRecordFoundFromRef', $newval);
518 $this->errors[$error]['type'] = 'FOREIGNKEY';
519 $errorforthistable++;
520 $error++;
521 }
522
523 // If not found, try the fetch from label
524 if (!($classinstance->id != '') && $objimport->array_import_convertvalue[0][$val]['rule'] == 'fetchidfromcodeorlabel') {
525 $param_array = array('', '', $newval);
526 call_user_func_array(array($classinstance, $method), $param_array);
527 }
528 $this->cacheconvert[$file . '_' . $class . '_' . $method . '_'][$newval] = $classinstance->id;
529
530 //print 'We have made a '.$class.'->'.$method.' to get id from code '.$newval.'. ';
531 if ($classinstance->id != '') { // id may be 0, it is a found value
532 $newval = $classinstance->id;
533 } elseif (! $error) {
534 if (!empty($objimport->array_import_convertvalue[0][$val]['dict'])) {
535 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
536 $this->errors[$error]['lib'] = $langs->trans('ErrorFieldValueNotIn', $key, $newval, 'code', $langs->transnoentitiesnoconv($objimport->array_import_convertvalue[0][$val]['dict']));
537 } elseif (!empty($objimport->array_import_convertvalue[0][$val]['element'])) {
538 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
539 $this->errors[$error]['lib'] = $langs->trans('ErrorFieldRefNotIn', $key, $newval, $langs->transnoentitiesnoconv($objimport->array_import_convertvalue[0][$val]['element']));
540 } else {
541 $this->errors[$error]['lib'] = 'ErrorBadDefinitionOfImportProfile';
542 }
543 $this->errors[$error]['type'] = 'FOREIGNKEY';
544 $errorforthistable++;
545 $error++;
546 }
547 }
548 }
549 } elseif ($objimport->array_import_convertvalue[0][$val]['rule'] == 'fetchidfromcodeandlabel') {
550 $isidorref = 'id';
551 if (!is_numeric($newval) && $newval != '' && !preg_match('/^id:/i', $newval)) {
552 $isidorref = 'ref';
553 }
554 $newval = preg_replace('/^(id|ref):/i', '', $newval);
555
556 if ($isidorref == 'ref') {
557 $file = (empty($objimport->array_import_convertvalue[0][$val]['classfile']) ? $objimport->array_import_convertvalue[0][$val]['file'] : $objimport->array_import_convertvalue[0][$val]['classfile']);
558 $class = $objimport->array_import_convertvalue[0][$val]['class'];
559 $method = $objimport->array_import_convertvalue[0][$val]['method'];
560 $codefromfield = $objimport->array_import_convertvalue[0][$val]['codefromfield'];
561 $code = $arrayrecord[$arrayfield[$codefromfield]]['val'];
562 if ($this->cacheconvert[$file . '_' . $class . '_' . $method . '_' . $code][$newval] != '') {
563 $newval = $this->cacheconvert[$file . '_' . $class . '_' . $method . '_' . $code][$newval];
564 } else {
565 $resultload = dol_include_once($file);
566 if (empty($resultload)) {
567 dol_print_error(null, 'Error trying to call file=' . $file . ', class=' . $class . ', method=' . $method . ', code=' . $code);
568 break;
569 }
570 $classinstance = new $class($this->db);
571 // Try the fetch from code and ref
572 $param_array = array('', $newval, $code);
573 call_user_func_array(array($classinstance, $method), $param_array);
574 $this->cacheconvert[$file . '_' . $class . '_' . $method . '_' . $code][$newval] = $classinstance->id;
575 if ($classinstance->id > 0) { // we found record
576 $newval = $classinstance->id;
577 } else {
578 if (!empty($objimport->array_import_convertvalue[0][$val]['dict'])) {
579 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
580 $this->errors[$error]['lib'] = $langs->trans('ErrorFieldValueNotIn', $key, $newval, 'scale', $langs->transnoentitiesnoconv($objimport->array_import_convertvalue[0][$val]['dict']));
581 } else {
582 $this->errors[$error]['lib'] = 'ErrorFieldValueNotIn';
583 }
584 $this->errors[$error]['type'] = 'FOREIGNKEY';
585 $errorforthistable++;
586 $error++;
587 }
588 }
589 }
590 } elseif ($objimport->array_import_convertvalue[0][$val]['rule'] == 'zeroifnull') {
591 if (empty($newval)) {
592 $newval = '0';
593 }
594 } elseif ($objimport->array_import_convertvalue[0][$val]['rule'] == 'fetchidfromcodeunits' || $objimport->array_import_convertvalue[0][$val]['rule'] == 'fetchscalefromcodeunits') {
595 $file = (empty($objimport->array_import_convertvalue[0][$val]['classfile']) ? $objimport->array_import_convertvalue[0][$val]['file'] : $objimport->array_import_convertvalue[0][$val]['classfile']);
596 $class = $objimport->array_import_convertvalue[0][$val]['class'];
597 $method = $objimport->array_import_convertvalue[0][$val]['method'];
598 $units = $objimport->array_import_convertvalue[0][$val]['units'];
599 if ($this->cacheconvert[$file . '_' . $class . '_' . $method . '_' . $units][$newval] != '') {
600 $newval = $this->cacheconvert[$file . '_' . $class . '_' . $method . '_' . $units][$newval];
601 } else {
602 $resultload = dol_include_once($file);
603 if (empty($resultload)) {
604 dol_print_error(null, 'Error trying to call file=' . $file . ', class=' . $class . ', method=' . $method . ', units=' . $units);
605 break;
606 }
607 $classinstance = new $class($this->db);
608 // Try the fetch from code or ref
609 call_user_func_array(array($classinstance, $method), array('', '', $newval, $units));
610 $scaleorid = (($objimport->array_import_convertvalue[0][$val]['rule'] == 'fetchidfromcodeunits') ? $classinstance->id : $classinstance->scale);
611 $this->cacheconvert[$file . '_' . $class . '_' . $method . '_' . $units][$newval] = $scaleorid;
612 //print 'We have made a '.$class.'->'.$method." to get a value from key '".$newval."' and we got '".$scaleorid."'.";exit;
613 if ($classinstance->id > 0) { // we found record
614 $newval = $scaleorid ? $scaleorid : 0;
615 } else {
616 if (!empty($objimport->array_import_convertvalue[0][$val]['dict'])) {
617 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
618 $this->errors[$error]['lib'] = $langs->trans('ErrorFieldValueNotIn', $key, $newval, 'scale', $langs->transnoentitiesnoconv($objimport->array_import_convertvalue[0][$val]['dict']));
619 } else {
620 $this->errors[$error]['lib'] = 'ErrorFieldValueNotIn';
621 }
622 $this->errors[$error]['type'] = 'FOREIGNKEY';
623 $errorforthistable++;
624 $error++;
625 }
626 }
627 } elseif ($objimport->array_import_convertvalue[0][$val]['rule'] == 'getcustomercodeifauto') {
628 if (strtolower($newval) == 'auto') {
629 $this->thirdpartyobject->get_codeclient(0, 0);
630 $newval = $this->thirdpartyobject->code_client;
631 //print 'code_client='.$newval;
632 }
633 if (empty($newval)) {
634 $arrayrecord[($key)]['type'] = -1; // If we get empty value, we will use "null"
635 }
636 } elseif ($objimport->array_import_convertvalue[0][$val]['rule'] == 'getsuppliercodeifauto') {
637 if (strtolower($newval) == 'auto') {
638 $this->thirdpartyobject->get_codefournisseur(0, 1);
639 $newval = $this->thirdpartyobject->code_fournisseur;
640 //print 'code_fournisseur='.$newval;
641 }
642 if (empty($newval)) {
643 $arrayrecord[($key)]['type'] = -1; // If we get empty value, we will use "null"
644 }
645 } elseif ($objimport->array_import_convertvalue[0][$val]['rule'] == 'getcustomeraccountancycodeifauto') {
646 if (strtolower($newval) == 'auto') {
647 $this->thirdpartyobject->get_codecompta('customer');
648 $newval = $this->thirdpartyobject->code_compta;
649 //print 'code_compta='.$newval;
650 }
651 if (empty($newval)) {
652 $arrayrecord[($key)]['type'] = -1; // If we get empty value, we will use "null"
653 }
654 } elseif ($objimport->array_import_convertvalue[0][$val]['rule'] == 'getsupplieraccountancycodeifauto') {
655 if (strtolower($newval) == 'auto') {
656 $this->thirdpartyobject->get_codecompta('supplier');
657 $newval = $this->thirdpartyobject->code_compta_fournisseur;
658 if (empty($newval)) {
659 $arrayrecord[($key)]['type'] = -1; // If we get empty value, we will use "null"
660 }
661 //print 'code_compta_fournisseur='.$newval;
662 }
663 if (empty($newval)) {
664 $arrayrecord[($key)]['type'] = -1; // If we get empty value, we will use "null"
665 }
666 } elseif ($objimport->array_import_convertvalue[0][$val]['rule'] == 'getrefifauto') {
667 if (strtolower($newval) == 'auto') {
668 $defaultref = '';
669
670 $classModForNumber = $objimport->array_import_convertvalue[0][$val]['class'];
671 $pathModForNumber = $objimport->array_import_convertvalue[0][$val]['path'];
672
673 if (!empty($classModForNumber) && !empty($pathModForNumber) && is_readable(DOL_DOCUMENT_ROOT.$pathModForNumber)) {
674 require_once DOL_DOCUMENT_ROOT.$pathModForNumber;
675 $modForNumber = new $classModForNumber();
676
677 $tmpobject = null;
678 // Set the object with the date property when we can
679 if (!empty($objimport->array_import_convertvalue[0][$val]['classobject'])) {
680 $pathForObject = $objimport->array_import_convertvalue[0][$val]['pathobject'];
681 require_once DOL_DOCUMENT_ROOT.$pathForObject;
682 $tmpclassobject = $objimport->array_import_convertvalue[0][$val]['classobject'];
683 $tmpobject = new $tmpclassobject($this->db);
684 foreach ($arrayfield as $tmpkey => $tmpval) { // $arrayfield is array('c.ref'=>1, ...)
685 if (in_array($tmpkey, array('t.date', 'c.date_commande'))) {
686 $tmpobject->date = dol_stringtotime($arrayrecord[$arrayfield[$tmpkey]]['val'], 1);
687 }
688 }
689 }
690
691 $defaultref = $modForNumber->getNextValue(null, $tmpobject);
692 }
693 if (is_numeric($defaultref) && $defaultref <= 0) { // If error
694 $defaultref = '';
695 }
696 $newval = $defaultref;
697 }
698 } elseif ($objimport->array_import_convertvalue[0][$val]['rule'] == 'compute') {
699 $file = (empty($objimport->array_import_convertvalue[0][$val]['classfile']) ? $objimport->array_import_convertvalue[0][$val]['file'] : $objimport->array_import_convertvalue[0][$val]['classfile']);
700 $class = $objimport->array_import_convertvalue[0][$val]['class'];
701 $method = $objimport->array_import_convertvalue[0][$val]['method'];
702 $resultload = dol_include_once($file);
703 if (empty($resultload)) {
704 dol_print_error(null, 'Error trying to call file=' . $file . ', class=' . $class . ', method=' . $method);
705 break;
706 }
707 $classinstance = new $class($this->db);
708 $res = call_user_func_array(array($classinstance, $method), array(&$arrayrecord, $arrayfield, $key));
709 if (empty($classinstance->error) && empty($classinstance->errors)) {
710 $newval = $res; // We get new value computed.
711 } else {
712 $this->errors[$error]['type'] = 'CLASSERROR';
713 $this->errors[$error]['lib'] = implode(
714 "\n",
715 array_merge([$classinstance->error], $classinstance->errors)
716 );
717 $errorforthistable++;
718 $error++;
719 }
720 } elseif ($objimport->array_import_convertvalue[0][$val]['rule'] == 'numeric') {
721 $newval = price2num($newval);
722 } elseif ($objimport->array_import_convertvalue[0][$val]['rule'] == 'accountingaccount') {
723 if (!getDolGlobalString('ACCOUNTING_MANAGE_ZERO')) {
724 $newval = rtrim(trim($newval), "0");
725 } else {
726 $newval = trim($newval);
727 }
728 }
729
730 //print 'Val to use as insert is '.$newval.'<br>';
731 }
732
733 // Test regexp
734 if (!empty($objimport->array_import_regex[0][$val]) && ($newval != '')) {
735 // If test is "Must exist in a field@table or field@table:..."
736 $reg = array();
737 if (preg_match('/^(.+)@([^:]+)(:.+)?$/', $objimport->array_import_regex[0][$val], $reg)) {
738 $field = $reg[1];
739 $table = $reg[2];
740 $filter = !empty($reg[3]) ? substr($reg[3], 1) : '';
741
742 $cachekey = $field . '@' . $table;
743 if (!empty($filter)) {
744 $cachekey .= ':' . $filter;
745 }
746
747 // Load content of field@table into cache array
748 if (!is_array($this->cachefieldtable[$cachekey])) { // If content of field@table not already loaded into cache
749 $sql = "SELECT " . $field . " as aliasfield FROM " . $table;
750 if (!empty($filter)) {
751 $sql .= ' WHERE ' . $filter;
752 }
753
754 $resql = $this->db->query($sql);
755 if ($resql) {
756 $num = $this->db->num_rows($resql);
757 $i = 0;
758 while ($i < $num) {
759 $obj = $this->db->fetch_object($resql);
760 if ($obj) {
761 $this->cachefieldtable[$cachekey][] = $obj->aliasfield;
762 }
763 $i++;
764 }
765 } else {
766 dol_print_error($this->db);
767 }
768 }
769
770 // Now we check cache is not empty (should not) and key is into cache
771 if (!is_array($this->cachefieldtable[$cachekey]) || !in_array($newval, $this->cachefieldtable[$cachekey])) {
772 $tableforerror = $table;
773 if (!empty($filter)) {
774 $tableforerror .= ':' . $filter;
775 }
776 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
777 $this->errors[$error]['lib'] = $langs->transnoentitiesnoconv('ErrorFieldValueNotIn', $key, $newval, $field, $tableforerror);
778 $this->errors[$error]['type'] = 'FOREIGNKEY';
779 $errorforthistable++;
780 $error++;
781 }
782 } elseif (!preg_match('/' . $objimport->array_import_regex[0][$val] . '/i', $newval)) {
783 // If test is just a static regex
784 //if ($key == 19) print "xxx".$newval."zzz".$objimport->array_import_regex[0][$val]."<br>";
785 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
786 $this->errors[$error]['lib'] = $langs->transnoentitiesnoconv('ErrorWrongValueForField', $key, $newval, $objimport->array_import_regex[0][$val]);
787 $this->errors[$error]['type'] = 'REGEX';
788 $errorforthistable++;
789 $error++;
790 }
791 }
792
793 // Check HTML injection
794 $inj = testSqlAndScriptInject($newval, 0);
795 if ($inj) {
796 // @phan-suppress-next-line PhanPluginSuspiciousParamPosition
797 $this->errors[$error]['lib'] = $langs->transnoentitiesnoconv('ErrorHtmlInjectionForField', $key, dol_trunc($newval, 100));
798 $this->errors[$error]['type'] = 'HTMLINJECTION';
799 $errorforthistable++;
800 $error++;
801 }
802
803 // Other tests
804 // ...
805 }
806
807 // Define $listfields and $listvalues to build the SQL request
808 if (isModEnabled("socialnetworks") && strpos($fieldname, "socialnetworks") !== false) {
809 if (!in_array("socialnetworks", $listfields)) {
810 $listfields[] = "socialnetworks";
811 $socialkey = array_search("socialnetworks", $listfields); // Return position of 'socialnetworks' key in array. Example socialkey=19
812 $listvalues[$socialkey] = '';
813 }
814 if (!empty($newval) && $arrayrecord[($key)]['type'] > 0) {
815 $socialkey = array_search("socialnetworks", $listfields); // Return position of 'socialnetworks' key in array. Example socialkey=19
816 $socialnetwork = explode("_", $fieldname)[1];
817 if (empty($listvalues[$socialkey]) || $listvalues[$socialkey] == "null") {
818 $json = new stdClass();
819 $json->$socialnetwork = $newval;
820 $listvalues[$socialkey] = json_encode($json);
821 } else {
822 $jsondata = $listvalues[$socialkey];
823 $json = json_decode($jsondata);
824 $json->$socialnetwork = $newval;
825 $listvalues[$socialkey] = json_encode($json);
826 }
827 }
828 } else {
829 $listfields[] = $fieldname;
830
831 // Note: arrayrecord (and 'type') is filled with ->import_read_record called by import.php page before calling import_insert
832 if (empty($newval) && $arrayrecord[($key)]['type'] < 0) {
833 $listvalues[] = ($newval == '0' ? (int) $newval : "null");
834 } elseif (empty($newval) && $arrayrecord[($key)]['type'] == 0) {
835 $listvalues[] = "''";
836 } else {
837 $listvalues[] = "'".$this->db->escape($newval)."'";
838 }
839 }
840 }
841 $i++;
842 }
843
844 // We add hidden fields (but only if there is at least one field to add into table)
845 // We process here all the fields that were declared into the array $this->import_fieldshidden_array of the descriptor file.
846 // Previously we processed the ->import_fields_array.
847 if (!empty($listfields) && is_array($objimport->array_import_fieldshidden[0])) {
848 // Loop on each hidden fields to add them into listfields/listvalues
849 foreach ($objimport->array_import_fieldshidden[0] as $key => $val) {
850 if (!preg_match('/^' . preg_quote($alias, '/') . '\./', $key)) {
851 continue; // Not a field of current table
852 }
853 $keyfield = preg_replace('/^' . preg_quote($alias, '/') . '\./', '', $key);
854
855 if (in_array($keyfield, $listfields)) { // avoid duplicates in insert
856 continue;
857 } elseif ($val == 'user->id') {
858 $listfields[] = $keyfield;
859 $listvalues[] = ((int) $user->id);
860 } elseif (preg_match('/^lastrowid-/', $val)) {
861 $tmp = explode('-', $val);
862 $lastinsertid = (isset($last_insert_id_array[$tmp[1]])) ? $last_insert_id_array[$tmp[1]] : 0;
863 $listfields[] = $keyfield;
864 $listvalues[] = (int) $lastinsertid;
865 //print $key."-".$val."-".$listfields."-".$listvalues."<br>";exit;
866 } elseif (preg_match('/^const-/', $val)) {
867 $tmp = explode('-', $val, 2);
868 $listfields[] = $keyfield;
869 $listvalues[] = "'".$this->db->escape($tmp[1])."'";
870 } elseif (preg_match('/^rule-/', $val)) {
871 $fieldname = $key;
872 if (!empty($objimport->array_import_convertvalue[0][$fieldname])) {
873 if ($objimport->array_import_convertvalue[0][$fieldname]['rule'] == 'compute') {
874 $file = (empty($objimport->array_import_convertvalue[0][$fieldname]['classfile']) ? $objimport->array_import_convertvalue[0][$fieldname]['file'] : $objimport->array_import_convertvalue[0][$fieldname]['classfile']);
875 $class = $objimport->array_import_convertvalue[0][$fieldname]['class'];
876 $method = $objimport->array_import_convertvalue[0][$fieldname]['method'];
877 $type = $objimport->array_import_convertvalue[0][$fieldname]['type'];
878 $resultload = dol_include_once($file);
879 if (empty($resultload)) {
880 dol_print_error(null, 'Error trying to call file=' . $file . ', class=' . $class . ', method=' . $method);
881 break;
882 }
883 $classinstance = new $class($this->db);
884 $res = call_user_func_array(array($classinstance, $method), array(&$arrayrecord, $arrayfield, $key));
885 $fieldArr = explode('.', $fieldname);
886 if (count($fieldArr) > 0) {
887 $fieldname = $fieldArr[1];
888 }
889
890 // Set $listfields and $listvalues
891 $listfields[] = $fieldname;
892 if ($type == 'int') {
893 $listvalues[] = (int) $res;
894 } elseif ($type == 'double') {
895 $listvalues[] = (float) $res;
896 } else {
897 $listvalues[] = "'".$this->db->escape($res)."'";
898 }
899 } else {
900 $this->errors[$error]['type'] = 'CLASSERROR';
901 $this->errors[$error]['lib'] = implode(
902 "\n",
903 array_merge([$classinstance->error], $classinstance->errors)
904 );
905 $errorforthistable++;
906 $error++;
907 }
908 }
909 } else {
910 $this->errors[$error]['lib'] = 'Bad value of profile setup ' . $val . ' for array_import_fieldshidden';
911 $this->errors[$error]['type'] = 'Import profile setup';
912 $error++;
913 }
914 }
915 }
916 //print 'listfields='.$listfields.'<br>listvalues='.$listvalues.'<br>';
917
918 // If no error for this $alias/$tablename, we have a complete $listfields and $listvalues that are defined
919 // so we can try to make the insert or update now.
920 if (!$errorforthistable) {
921 //print "$alias/$tablename/$listfields/$listvalues<br>";
922 if (!empty($listfields)) {
923 $updatedone = false;
924 $insertdone = false;
925
926 $is_table_category_link = false;
927 $fname = 'rowid';
928 if (strpos($tablename, '_categorie_') !== false) {
929 $is_table_category_link = true;
930 $fname = '*';
931 }
932
933 if (!empty($updatekeys)) {
934 // We do SELECT to get the rowid, if we already have the rowid, it's to be used below for related tables (extrafields)
935
936 if (empty($lastinsertid)) { // No insert done yet for a parent table
937 $sqlSelect = "SELECT ".$fname." FROM " . $tablename;
938
939 $data = array_combine($listfields, $listvalues);
940
941 $where = array(); // filters to forge SQL request
942 // @phpstan-ignore-next-line
943 '@phan-var string[] $where';
944 $filters = array(); // filters to forge output error message
945 foreach ($updatekeys as $key) {
946 $col = $objimport->array_import_updatekeys[0][$key];
947 $key = preg_replace('/^.*\./i', '', $key);
948 if (isModEnabled("socialnetworks") && strpos($key, "socialnetworks") !== false) {
949 $tmp = explode("_", $key);
950 $key = $tmp[0];
951 $socialnetwork = $tmp[1];
952 $jsondata = $data[$key];
953 $json = json_decode($jsondata);
954 $stringtosearch = json_encode($socialnetwork).':'.json_encode($json->$socialnetwork);
955 //var_dump($stringtosearch);
956 //var_dump($this->db->escape($stringtosearch)); // This provide a value for sql string (but not for a like)
957 $where[] = $key." LIKE '%".$this->db->escape($this->db->escapeforlike($stringtosearch))."%'";
958 $filters[] = $col." LIKE '%".$this->db->escape($this->db->escapeforlike($stringtosearch))."%'";
959 //var_dump($where[1]); // This provide a value for sql string inside a like
960 } else {
961 $where[] = $key.' = '.$data[$key];
962 $filters[] = $col.' = '.$data[$key];
963 }
964 }
965 if (!empty($tablewithentity_cache[$tablename])) {
966 $where[] = "entity IN (".getEntity($this->getElementFromTableWithPrefix($tablename)).")";
967 $filters[] = "entity IN (".getEntity($this->getElementFromTableWithPrefix($tablename)).")";
968 }
969 $sqlSelect .= " WHERE " . implode(' AND ', $where);
970
971 $resql = $this->db->query($sqlSelect);
972 if ($resql) {
973 $num_rows = $this->db->num_rows($resql);
974 if ($num_rows == 1) {
975 $res = $this->db->fetch_object($resql);
976 $lastinsertid = $res->rowid;
977 if ($is_table_category_link) {
978 $lastinsertid = 'linktable';
979 } // 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
980 $last_insert_id_array[$tablename] = $lastinsertid;
981 } elseif ($num_rows > 1) {
982 $this->errors[$error]['lib'] = $langs->trans('MultipleRecordFoundWithTheseFilters', implode(', ', $filters));
983 $this->errors[$error]['type'] = 'SQL';
984 $error++;
985 } else {
986 // No record found with filters, insert will be tried below
987 }
988 } else {
989 //print 'E';
990 $this->errors[$error]['lib'] = $this->db->lasterror();
991 $this->errors[$error]['type'] = 'SQL';
992 $error++;
993 }
994 } else {
995 // We have a last INSERT ID (got by previous pass), so we check if we have a row referencing this foreign key.
996 // This is required when updating table with some extrafields. When inserting a record in parent table, we can make
997 // a direct insert into subtable extrafields, but when me wake an update, the insertid is defined and the child record
998 // may already exists. So we rescan the extrafield table to know if record exists or not for the rowid.
999 // Note: For extrafield tablename, we have in importfieldshidden_array an entry 'extra.fk_object'=>'lastrowid-tableparent' so $keyfield is 'fk_object'
1000 $sqlSelect = "SELECT rowid FROM " . $tablename;
1001
1002
1003 if (empty($keyfield)) {
1004 $keyfield = 'rowid';
1005 }
1006 $sqlSelect .= " WHERE ".$keyfield." = ".((int) $lastinsertid);
1007
1008 if (!empty($tablewithentity_cache[$tablename])) {
1009 $sqlSelect .= " AND entity IN (".getEntity($this->getElementFromTableWithPrefix($tablename)).")";
1010 }
1011
1012 $resql = $this->db->query($sqlSelect);
1013 if ($resql) {
1014 $res = $this->db->fetch_object($resql);
1015 if ($this->db->num_rows($resql) == 1) {
1016 // We have a row referencing this last foreign key, continue with UPDATE.
1017 } else {
1018 // No record found referencing this last foreign key,
1019 // force $lastinsertid to 0 so we INSERT below.
1020 $lastinsertid = 0;
1021 }
1022 } else {
1023 //print 'E';
1024 $this->errors[$error]['lib'] = $this->db->lasterror();
1025 $this->errors[$error]['type'] = 'SQL';
1026 $error++;
1027 }
1028 }
1029
1030 if (!empty($lastinsertid)) {
1031 // We db escape social network field because he isn't in field creation
1032 if (in_array("socialnetworks", $listfields)) {
1033 $socialkey = array_search("socialnetworks", $listfields);
1034 $tmpsql = $listvalues[$socialkey];
1035 $listvalues[$socialkey] = "'".$this->db->escape($tmpsql)."'";
1036 }
1037
1038 // Build SQL UPDATE request
1039 $sqlstart = "UPDATE " . $tablename;
1040
1041 $data = array_combine($listfields, $listvalues);
1042 $set = array();
1043 foreach ($data as $key => $val) {
1044 $set[] = $key." = ".$val; // $val was escaped/sanitized previously
1045 }
1046 $sqlstart .= " SET " . implode(', ', $set) . ", import_key = '" . $this->db->escape($importid) . "'";
1047
1048 if (empty($keyfield)) {
1049 $keyfield = 'rowid';
1050 }
1051 $sqlend = " WHERE " . $keyfield . " = ".((int) $lastinsertid);
1052
1053 if ($is_table_category_link) {
1054 '@phan-var-force string[] $where';
1055 $sqlend = " WHERE " . implode(' AND ', $where);
1056 }
1057
1058 if (!empty($tablewithentity_cache[$tablename])) {
1059 $sqlend .= " AND entity IN (".getEntity($this->getElementFromTableWithPrefix($tablename)).")";
1060 }
1061
1062 $sql = $sqlstart . $sqlend;
1063
1064 // Run update request
1065 $resql = $this->db->query($sql);
1066 if ($resql) {
1067 // No error, update has been done. $this->db->db->affected_rows can be 0 if data hasn't changed
1068 $updatedone = true;
1069 } else {
1070 //print 'E';
1071 $this->errors[$error]['lib'] = $this->db->lasterror();
1072 $this->errors[$error]['type'] = 'SQL';
1073 $error++;
1074 }
1075 }
1076 }
1077
1078 // Update not done, we do insert
1079 if (!$error && !$updatedone) {
1080 // We db escape social network field because he isn't in field creation
1081 if (in_array("socialnetworks", $listfields)) {
1082 $socialkey = array_search("socialnetworks", $listfields);
1083 $tmpsql = $listvalues[$socialkey];
1084 $listvalues[$socialkey] = "'".$this->db->escape($tmpsql)."'";
1085 }
1086
1087 // Build SQL INSERT request
1088 $sqlstart = "INSERT INTO " . $tablename . "(" . implode(", ", $listfields) . ", import_key";
1089 $sqlend = ") VALUES(" . implode(', ', $listvalues) . ", '" . $this->db->escape($importid) . "'";
1090 if (!empty($tablewithentity_cache[$tablename])) {
1091 $sqlstart .= ", entity";
1092 $sqlend .= ", " . $conf->entity;
1093 }
1094 if (!empty($objimport->array_import_tables_creator[0][$alias])) {
1095 $sqlstart .= ", " . $objimport->array_import_tables_creator[0][$alias];
1096 $sqlend .= ", " . $user->id;
1097 }
1098 $sql = $sqlstart . $sqlend . ")";
1099 //dol_syslog("import_xlsx.modules", LOG_DEBUG);
1100
1101 // Run insert request
1102 if ($sql) {
1103 $resql = $this->db->query($sql);
1104 if ($resql) {
1105 if (!$is_table_category_link) {
1106 $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).
1107 }
1108 $insertdone = true;
1109 } else {
1110 //print 'E';
1111 $this->errors[$error]['lib'] = $this->db->lasterror();
1112 $this->errors[$error]['type'] = 'SQL';
1113 $error++;
1114 }
1115 }
1116 }
1117 }
1118 /*else
1119 {
1120 dol_print_error(null,'ErrorFieldListEmptyFor '.$alias."/".$tablename);
1121 }*/
1122 }
1123
1124 if ($error) {
1125 break;
1126 }
1127 }
1128
1129 if ($updatedone) {
1130 $this->nbupdate++;
1131 }
1132 if ($insertdone) {
1133 $this->nbinsert++;
1134 }
1135 }
1136
1137 return 1;
1138 }
1139}
versionphparray()
Return version PHP.
versioncompare($versionarray1, $versionarray2)
Compare 2 versions (stored into 2 arrays).
Definition admin.lib.php:68
Class to import Excel files.
__construct($db, $datatoimport)
Constructor.
write_record_example($outputlangs, $contentlinevalues)
Output record of an example file for this format.
import_open_file($file)
Open input file.
import_insert($arrayrecord, $array_match_file_to_database, $objimport, $maxfields, $importid, $updatekeys)
Insert a record into database.
write_footer_example($outputlangs)
Output footer of an example file for this format.
import_read_header()
Input header line from file.
write_header_example($outputlangs)
Output header of an example file for this format.
import_read_record()
Return array of next record in input file.
write_title_example($outputlangs, $headerlinefields)
Output title line of an example file for this format.
import_get_nb_of_lines($file)
Return nb of records.
import_close_file()
Close file handle.
Parent class for import file readers.
getElementFromTableWithPrefix($tableNameWithPrefix)
Get element from table name with prefix.
Class to manage third parties objects (customers, suppliers, prospects...)
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:427
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.
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.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
testSqlAndScriptInject($val, $type)
Security: WAF layer for SQL Injection and XSS Injection (scripts) protection (Filters on GET,...
Definition main.inc.php:123