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