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