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