dolibarr  16.0.1
import.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2005-2016 Laurent Destailleur <eldy@users.sourceforge.net>
3  * Copyright (C) 2005-2009 Regis Houssin <regis.houssin@inodbox.com>
4  * Copyright (C) 2012 Christophe Battarel <christophe.battarel@altairis.fr>
5  * Copyright (C) 2022 Charlene Benke <charlene@patas-monkey.com>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program. If not, see <https://www.gnu.org/licenses/>.
19  */
20 
27 require_once '../main.inc.php';
28 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
29 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php';
30 require_once DOL_DOCUMENT_ROOT.'/imports/class/import.class.php';
31 require_once DOL_DOCUMENT_ROOT.'/core/modules/import/modules_import.php';
32 require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
33 require_once DOL_DOCUMENT_ROOT.'/core/lib/images.lib.php';
34 require_once DOL_DOCUMENT_ROOT.'/core/lib/import.lib.php';
35 
36 // Load translation files required by the page
37 $langs->loadLangs(array('exports', 'compta', 'errors'));
38 
39 // Security check
40 $result = restrictedArea($user, 'import');
41 
42 // Map icons, array duplicated in export.php, was not synchronized, TODO put it somewhere only once
43 $entitytoicon = array(
44  'invoice' => 'bill',
45  'invoice_line' => 'bill',
46  'order' => 'order',
47  'order_line' => 'order',
48  'propal' => 'propal',
49  'propal_line' => 'propal',
50  'intervention' => 'intervention',
51  'inter_line' => 'intervention',
52  'member' => 'user',
53  'member_type' => 'group',
54  'subscription' => 'payment',
55  'payment' => 'payment',
56  'tax' => 'bill',
57  'tax_type' => 'generic',
58  'other' => 'generic',
59  'account' => 'account',
60  'product' => 'product',
61  'virtualproduct'=>'product',
62  'subproduct' => 'product',
63  'product_supplier_ref' => 'product',
64  'stock' => 'stock',
65  'warehouse' => 'stock',
66  'batch' => 'stock',
67  'stockbatch' => 'stock',
68  'category' => 'category',
69  'shipment' => 'sending',
70  'shipment_line'=> 'sending',
71  'reception'=> 'sending',
72  'reception_line'=> 'sending',
73  'expensereport'=> 'trip',
74  'expensereport_line'=> 'trip',
75  'holiday' => 'holiday',
76  'contract_line' => 'contract',
77  'translation' => 'generic',
78  'bomm' => 'bom',
79  'bomline' => 'bom'
80 );
81 
82 // Translation code, array duplicated in export.php, was not synchronized, TODO put it somewhere only once
83 $entitytolang = array(
84  'user' => 'User',
85  'company' => 'Company',
86  'contact' => 'Contact',
87  'invoice' => 'Bill',
88  'invoice_line' => 'InvoiceLine',
89  'order' => 'Order',
90  'order_line' => 'OrderLine',
91  'propal' => 'Proposal',
92  'propal_line' => 'ProposalLine',
93  'intervention' => 'Intervention',
94  'inter_line' => 'InterLine',
95  'member' => 'Member',
96  'member_type' => 'MemberType',
97  'subscription' => 'Subscription',
98  'tax' => 'SocialContribution',
99  'tax_type' => 'DictionarySocialContributions',
100  'account' => 'BankTransactions',
101  'payment' => 'Payment',
102  'product' => 'Product',
103  'virtualproduct' => 'AssociatedProducts',
104  'subproduct' => 'SubProduct',
105  'product_supplier_ref' => 'SupplierPrices',
106  'service' => 'Service',
107  'stock' => 'Stock',
108  'movement' => 'StockMovement',
109  'batch' => 'Batch',
110  'stockbatch' => 'StockDetailPerBatch',
111  'warehouse' => 'Warehouse',
112  'category' => 'Category',
113  'other' => 'Other',
114  'trip' => 'TripsAndExpenses',
115  'shipment' => 'Shipments',
116  'shipment_line'=> 'ShipmentLine',
117  'project' => 'Projects',
118  'projecttask' => 'Tasks',
119  'task_time' => 'TaskTimeSpent',
120  'action' => 'Event',
121  'expensereport'=> 'ExpenseReport',
122  'expensereport_line'=> 'ExpenseReportLine',
123  'holiday' => 'TitreRequestCP',
124  'contract' => 'Contract',
125  'contract_line'=> 'ContractLine',
126  'translation' => 'Translation',
127  'bom' => 'BOM',
128  'bomline' => 'BOMLine'
129 );
130 
131 $datatoimport = GETPOST('datatoimport');
132 $format = GETPOST('format');
133 $filetoimport = GETPOST('filetoimport');
134 $action = GETPOST('action', 'alpha');
135 $confirm = GETPOST('confirm', 'alpha');
136 $step = (GETPOST('step') ? GETPOST('step') : 1);
137 $import_name = GETPOST('import_name');
138 $hexa = GETPOST('hexa');
139 $importmodelid = GETPOST('importmodelid', 'int');
140 $excludefirstline = (GETPOST('excludefirstline') ? GETPOST('excludefirstline') : 2);
141 $endatlinenb = (GETPOST('endatlinenb') ? GETPOST('endatlinenb') : '');
142 $updatekeys = (GETPOST('updatekeys', 'array') ? GETPOST('updatekeys', 'array') : array());
143 $separator = (GETPOST('separator', 'alphanohtml') ? GETPOST('separator', 'alphanohtml', 3) : '');
144 $enclosure = (GETPOST('enclosure', 'nohtml') ? GETPOST('enclosure', 'nohtml') : '"'); // We must use 'nohtml' and not 'alphanohtml' because we must accept "
145 $separator_used = str_replace('\t', "\t", $separator);
146 
147 $objimport = new Import($db);
148 $objimport->load_arrays($user, ($step == 1 ? '' : $datatoimport));
149 
150 $objmodelimport = new ModeleImports();
151 
152 $form = new Form($db);
153 $htmlother = new FormOther($db);
154 $formfile = new FormFile($db);
155 
156 // Init $array_match_file_to_database from _SESSION
157 if (empty($array_match_file_to_database)) {
158  $serialized_array_match_file_to_database = isset($_SESSION["dol_array_match_file_to_database_select"]) ? $_SESSION["dol_array_match_file_to_database_select"] : '';
159  $array_match_file_to_database = array();
160  $fieldsarray = explode(',', $serialized_array_match_file_to_database);
161  foreach ($fieldsarray as $elem) {
162  $tabelem = explode('=', $elem, 2);
163  $key = $tabelem[0];
164  $val = (isset($tabelem[1]) ? $tabelem[1] : '');
165  if ($key && $val) {
166  $array_match_file_to_database[$key] = $val;
167  }
168  }
169 }
170 
171 
172 /*
173  * Actions
174  */
175 
176 /*
177 if ($action=='downfield' || $action=='upfield')
178 {
179  $pos=$array_match_file_to_database[$_GET["field"]];
180  if ($action=='downfield') $newpos=$pos+1;
181  if ($action=='upfield') $newpos=$pos-1;
182  // Recherche code avec qui switcher
183  $newcode="";
184  foreach($array_match_file_to_database as $code=>$value)
185  {
186  if ($value == $newpos)
187  {
188  $newcode=$code;
189  break;
190  }
191  }
192  //print("Switch pos=$pos (code=".$_GET["field"].") and newpos=$newpos (code=$newcode)");
193  if ($newcode) // Si newcode trouve (protection contre resoumission de page)
194  {
195  $array_match_file_to_database[$_GET["field"]]=$newpos;
196  $array_match_file_to_database[$newcode]=$pos;
197  $_SESSION["dol_array_match_file_to_database"]=$serialized_array_match_file_to_database;
198  }
199 }
200 */
201 if ($action == 'builddoc') {
202  // Build import file
203  $result = $objimport->build_file($user, GETPOST('model', 'alpha'), $datatoimport, $array_match_file_to_database);
204  if ($result < 0) {
205  setEventMessages($objimport->error, $objimport->errors, 'errors');
206  } else {
207  setEventMessages($langs->trans("FileSuccessfullyBuilt"), null, 'mesgs');
208  }
209 }
210 
211 if ($action == 'deleteprof') {
212  if (GETPOST("id", 'int')) {
213  $objimport->fetch(GETPOST("id", 'int'));
214  $result = $objimport->delete($user);
215  }
216 }
217 
218 // Save import config to database
219 if ($action == 'add_import_model') {
220  if ($import_name) {
221  // Set save string
222  $hexa = '';
223  foreach ($array_match_file_to_database as $key => $val) {
224  if ($hexa) {
225  $hexa .= ',';
226  }
227  $hexa .= $key.'='.$val;
228  }
229 
230  $objimport->model_name = $import_name;
231  $objimport->datatoimport = $datatoimport;
232  $objimport->hexa = $hexa;
233  $objimport->fk_user = (GETPOST('visibility', 'aZ09') == 'all' ? 0 : $user->id);
234 
235  $result = $objimport->create($user);
236  if ($result >= 0) {
237  setEventMessages($langs->trans("ImportModelSaved", $objimport->model_name), null, 'mesgs');
238  $import_name = '';
239  } else {
240  $langs->load("errors");
241  if ($objimport->errno == 'DB_ERROR_RECORD_ALREADY_EXISTS') {
242  setEventMessages($langs->trans("ErrorImportDuplicateProfil"), null, 'errors');
243  } else {
244  setEventMessages($objimport->error, null, 'errors');
245  }
246  }
247  } else {
248  setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("ImportModelName")), null, 'errors');
249  }
250 }
251 
252 if ($step == 3 && $datatoimport) {
253  if (GETPOST('sendit') && !empty($conf->global->MAIN_UPLOAD_DOC)) {
254  dol_mkdir($conf->import->dir_temp);
255  $nowyearmonth = dol_print_date(dol_now(), '%Y%m%d%H%M%S');
256 
257  $fullpath = $conf->import->dir_temp."/".$nowyearmonth.'-'.$_FILES['userfile']['name'];
258  if (dol_move_uploaded_file($_FILES['userfile']['tmp_name'], $fullpath, 1) > 0) {
259  dol_syslog("File ".$fullpath." was added for import");
260  } else {
261  $langs->load("errors");
262  setEventMessages($langs->trans("ErrorFailedToSaveFile"), null, 'errors');
263  }
264  }
265 
266  // Delete file
267  if ($action == 'confirm_deletefile' && $confirm == 'yes') {
268  $langs->load("other");
269 
270  $param = '&datatoimport='.urlencode($datatoimport).'&format='.urlencode($format);
271  if ($excludefirstline) {
272  $param .= '&excludefirstline='.urlencode($excludefirstline);
273  }
274  if ($endatlinenb) {
275  $param .= '&endatlinenb='.urlencode($endatlinenb);
276  }
277 
278  $file = $conf->import->dir_temp.'/'.GETPOST('urlfile'); // Do not use urldecode here ($_GET and $_REQUEST are already decoded by PHP).
279  $ret = dol_delete_file($file);
280  if ($ret) {
281  setEventMessages($langs->trans("FileWasRemoved", GETPOST('urlfile')), null, 'mesgs');
282  } else {
283  setEventMessages($langs->trans("ErrorFailToDeleteFile", GETPOST('urlfile')), null, 'errors');
284  }
285  Header('Location: '.$_SERVER["PHP_SELF"].'?step='.$step.$param);
286  exit;
287  }
288 }
289 
290 if ($step == 4 && $action == 'select_model') {
291  // Reinit match arrays
292  $_SESSION["dol_array_match_file_to_database"] = '';
293  $serialized_array_match_file_to_database = '';
294  $array_match_file_to_database = array();
295 
296  // Load model from $importmodelid and set $array_match_file_to_database
297  // and $_SESSION["dol_array_match_file_to_database"]
298  $result = $objimport->fetch($importmodelid);
299  if ($result > 0) {
300  $serialized_array_match_file_to_database = $objimport->hexa;
301  $fieldsarray = explode(',', $serialized_array_match_file_to_database);
302  foreach ($fieldsarray as $elem) {
303  $tabelem = explode('=', $elem);
304  $key = $tabelem[0];
305  $val = $tabelem[1];
306  if ($key && $val) {
307  $array_match_file_to_database[$key] = $val;
308  }
309  }
310  $_SESSION["dol_array_match_file_to_database"] = $serialized_array_match_file_to_database;
311  $_SESSION['dol_array_match_file_to_database_select'] = $_SESSION["dol_array_match_file_to_database"];
312  }
313 }
314 if ($action == 'saveselectorder') {
315  // Enregistrement de la position des champs
316  $serialized_array_match_file_to_database = '';
317  dol_syslog("selectorder=".GETPOST('selectorder'), LOG_DEBUG);
318  $selectorder = explode(",", GETPOST('selectorder'));
319  $fieldtarget = $fieldstarget = $objimport->array_import_fields[0];
320  foreach ($selectorder as $key => $code) {
321  $serialized_array_match_file_to_database .= $key.'='.$code;
322  $serialized_array_match_file_to_database .= ',';
323  }
324  $serialized_array_match_file_to_database = substr($serialized_array_match_file_to_database, 0, -1);
325  dol_syslog('dol_array_match_file_to_database_select='.$serialized_array_match_file_to_database);
326  $_SESSION["dol_array_match_file_to_database_select"] = $serialized_array_match_file_to_database;
327  echo "{}";
328  exit(0);
329 }
330 
331 
332 
333 /*
334  * View
335  */
336 
337 
338 $help_url = 'EN:Module_Imports_En|FR:Module_Imports|ES:M&oacute;dulo_Importaciones';
339 
340 
341 // STEP 1: Page to select dataset to import
342 if ($step == 1 || !$datatoimport) {
343  // Clean saved file-database matching
344  $serialized_array_match_file_to_database = '';
345  $array_match_file_to_database = array();
346  $_SESSION["dol_array_match_file_to_database"] = '';
347  $_SESSION["dol_array_match_file_to_database_select"] = '';
348 
349  $param = '';
350  if ($excludefirstline) {
351  $param .= '&excludefirstline='.urlencode($excludefirstline);
352  }
353  if ($endatlinenb) {
354  $param .= '&endatlinenb='.urlencode($endatlinenb);
355  }
356  if ($separator) {
357  $param .= '&separator='.urlencode($separator);
358  }
359  if ($enclosure) {
360  $param .= '&enclosure='.urlencode($enclosure);
361  }
362 
363  llxHeader('', $langs->trans("NewImport"), $help_url);
364 
365  $head = import_prepare_head($param, 1);
366 
367  print dol_get_fiche_head($head, 'step1', '', -1);
368 
369  print '<div class="opacitymedium">'.$langs->trans("SelectImportDataSet").'</div><br>';
370 
371  // Affiche les modules d'imports
372  print '<div class="div-table-responsive-no-min">'; // You can use div-table-responsive-no-min if you dont need reserved height for your table
373  print '<table class="noborder centpercent">';
374  print '<tr class="liste_titre">';
375  print '<td>'.$langs->trans("Module").'</td>';
376  print '<td>'.$langs->trans("ImportableDatas").'</td>';
377  print '<td>&nbsp;</td>';
378  print '</tr>';
379 
380  if (count($objimport->array_import_module)) {
381  $sortedarrayofmodules = dol_sort_array($objimport->array_import_module, 'position_of_profile', 'asc', 0, 0, 1);
382  foreach ($sortedarrayofmodules as $key => $value) {
383  //var_dump($key.' '.$value['position_of_profile'].' '.$value['import_code'].' '.$objimport->array_import_module[$key]['module']->getName().' '.$objimport->array_import_code[$key]);
384  print '<tr class="oddeven"><td>';
385  $titleofmodule = $objimport->array_import_module[$key]['module']->getName();
386  // Special cas for import common to module/services
387  if (in_array($objimport->array_import_code[$key], array('produit_supplierprices', 'produit_multiprice', 'produit_languages'))) {
388  $titleofmodule = $langs->trans("ProductOrService");
389  }
390  print $titleofmodule;
391  print '</td><td>';
392  $entity = preg_replace('/:.*$/', '', $objimport->array_import_icon[$key]);
393  $entityicon = strtolower(!empty($entitytoicon[$entity]) ? $entitytoicon[$entity] : $entity);
394  print img_object($objimport->array_import_module[$key]['module']->getName(), $entityicon).' ';
395  print $objimport->array_import_label[$key];
396  print '</td><td style="text-align: right">';
397  if ($objimport->array_import_perms[$key]) {
398  print '<a href="'.DOL_URL_ROOT.'/imports/import.php?step=2&datatoimport='.$objimport->array_import_code[$key].$param.'">'.img_picto($langs->trans("NewImport"), 'next', 'class="fa-15"').'</a>';
399  } else {
400  print $langs->trans("NotEnoughPermissions");
401  }
402  print '</td></tr>';
403  }
404  } else {
405  print '<tr><td class="oddeven" colspan="3">'.$langs->trans("NoImportableData").'</td></tr>';
406  }
407  print '</table>';
408  print '</div>';
409 
410  print dol_get_fiche_end();
411 }
412 
413 
414 // STEP 2: Page to select input format file
415 if ($step == 2 && $datatoimport) {
416  $param = '&datatoimport='.urlencode($datatoimport);
417  if ($excludefirstline) {
418  $param .= '&excludefirstline='.urlencode($excludefirstline);
419  }
420  if ($endatlinenb) {
421  $param .= '&endatlinenb='.urlencode($endatlinenb);
422  }
423  if ($separator) {
424  $param .= '&separator='.urlencode($separator);
425  }
426  if ($enclosure) {
427  $param .= '&enclosure='.urlencode($enclosure);
428  }
429 
430  llxHeader('', $langs->trans("NewImport"), $help_url);
431 
432  $head = import_prepare_head($param, 2);
433 
434  print dol_get_fiche_head($head, 'step2', '', -2);
435 
436  print '<div class="underbanner clearboth"></div>';
437  print '<div class="fichecenter">';
438 
439  print '<table class="border tableforfield centpercent">';
440 
441  // Module
442  print '<tr><td class="titlefieldcreate">'.$langs->trans("Module").'</td>';
443  print '<td>';
444  $titleofmodule = $objimport->array_import_module[0]['module']->getName();
445  // Special cas for import common to module/services
446  if (in_array($objimport->array_import_code[0], array('produit_supplierprices', 'produit_multiprice', 'produit_languages'))) {
447  $titleofmodule = $langs->trans("ProductOrService");
448  }
449  print $titleofmodule;
450  print '</td></tr>';
451 
452  // Dataset to import
453  print '<tr><td>'.$langs->trans("DatasetToImport").'</td>';
454  print '<td>';
455  $entity = preg_replace('/:.*$/', '', $objimport->array_import_icon[0]);
456  $entityicon = strtolower(!empty($entitytoicon[$entity]) ? $entitytoicon[$entity] : $entity);
457  print img_object($objimport->array_import_module[0]['module']->getName(), $entityicon).' ';
458  print $objimport->array_import_label[0];
459  print '</td></tr>';
460 
461  print '</table>';
462  print '</div>';
463 
464  print dol_get_fiche_end();
465 
466  print '<form name="userfile" action="'.$_SERVER["PHP_SELF"].'" enctype="multipart/form-data" METHOD="POST">';
467  print '<input type="hidden" name="token" value="'.newToken().'">';
468 
469  print '<br>';
470 
471  print '<span class="opacitymedium">';
472  $s = $langs->trans("ChooseFormatOfFileToImport", '{s1}');
473  $s = str_replace('{s1}', img_picto('', 'next'), $s);
474  print $s;
475  print '</span><br><br>';
476 
477  print '<br>';
478 
479  print '<div class="div-table-responsive-no-min">'; // You can use div-table-responsive-no-min if you dont need reserved height for your table
480  print '<table class="noborder centpercent" cellpadding="4">';
481 
482  $filetoimport = '';
483 
484  // Add format informations and link to download example
485  print '<tr class="liste_titre"><td colspan="5">';
486  print $langs->trans("FileMustHaveOneOfFollowingFormat");
487  print '</td></tr>';
488  $list = $objmodelimport->liste_modeles($db);
489  foreach ($list as $key) {
490  print '<tr class="oddeven">';
491  print '<td width="16">'.img_picto_common($key, $objmodelimport->getPictoForKey($key)).'</td>';
492  $text = $objmodelimport->getDriverDescForKey($key);
493  print '<td>'.$form->textwithpicto($objmodelimport->getDriverLabelForKey($key), $text).'</td>';
494  print '<td style="text-align:center">';
495  print '<a href="'.DOL_URL_ROOT.'/imports/emptyexample.php?format='.$key.$param.'" target="_blank" rel="noopener noreferrer">';
496  print img_picto('', 'download', 'class="paddingright opacitymedium"');
497  print $langs->trans("DownloadEmptyExampleShort");
498  print '</a>';
499  print $form->textwithpicto('', $langs->trans("DownloadEmptyExample").'.<br>'.$langs->trans("StarAreMandatory"));
500  print '</td>';
501  // Action button
502  print '<td style="text-align:right">';
503  print '<a href="'.DOL_URL_ROOT.'/imports/import.php?step=3&format='.$key.$param.'">'.img_picto($langs->trans("SelectFormat"), 'next', 'class="fa-15"').'</a>';
504  print '</td>';
505  print '</tr>';
506  }
507 
508  print '</table>';
509  print '</div>';
510 
511  print '</form>';
512 }
513 
514 
515 // STEP 3: Page to select file
516 if ($step == 3 && $datatoimport) {
517  $param = '&datatoimport='.urlencode($datatoimport).'&format='.urlencode($format);
518  if ($excludefirstline) {
519  $param .= '&excludefirstline='.urlencode($excludefirstline);
520  }
521  if ($endatlinenb) {
522  $param .= '&endatlinenb='.urlencode($endatlinenb);
523  }
524  if ($separator) {
525  $param .= '&separator='.urlencode($separator);
526  }
527  if ($enclosure) {
528  $param .= '&enclosure='.urlencode($enclosure);
529  }
530 
531  $list = $objmodelimport->liste_modeles($db);
532 
533  llxHeader('', $langs->trans("NewImport"), $help_url);
534 
535  $head = import_prepare_head($param, 3);
536 
537  print dol_get_fiche_head($head, 'step3', '', -2);
538 
539  /*
540  * Confirm delete file
541  */
542  if ($action == 'delete') {
543  print $form->formconfirm($_SERVER["PHP_SELF"].'?urlfile='.urlencode(GETPOST('urlfile')).'&step=3'.$param, $langs->trans('DeleteFile'), $langs->trans('ConfirmDeleteFile'), 'confirm_deletefile', '', 0, 1);
544  }
545 
546  print '<div class="underbanner clearboth"></div>';
547  print '<div class="fichecenter">';
548 
549  print '<table class="border tableforfield centpercent">';
550 
551  // Module
552  print '<tr><td class="titlefieldcreate">'.$langs->trans("Module").'</td>';
553  print '<td>';
554  $titleofmodule = $objimport->array_import_module[0]['module']->getName();
555  // Special cas for import common to module/services
556  if (in_array($objimport->array_import_code[0], array('produit_supplierprices', 'produit_multiprice', 'produit_languages'))) {
557  $titleofmodule = $langs->trans("ProductOrService");
558  }
559  print $titleofmodule;
560  print '</td></tr>';
561 
562  // Lot de donnees a importer
563  print '<tr><td>'.$langs->trans("DatasetToImport").'</td>';
564  print '<td>';
565  $entity = preg_replace('/:.*$/', '', $objimport->array_import_icon[0]);
566  $entityicon = strtolower(!empty($entitytoicon[$entity]) ? $entitytoicon[$entity] : $entity);
567  print img_object($objimport->array_import_module[0]['module']->getName(), $entityicon).' ';
568  print $objimport->array_import_label[0];
569  print '</td></tr>';
570 
571  print '</table>';
572  print '</div>';
573 
574  print load_fiche_titre($langs->trans("InformationOnSourceFile"), '', 'file-export');
575 
576  print '<div class="underbanner clearboth"></div>';
577  print '<div class="fichecenter">';
578  print '<table width="100%" class="border tableforfield">';
579 
580  // Source file format
581  print '<tr><td class="titlefieldcreate">'.$langs->trans("SourceFileFormat").'</td>';
582  print '<td class="nowraponall">';
583  $text = $objmodelimport->getDriverDescForKey($format);
584  print $form->textwithpicto($objmodelimport->getDriverLabelForKey($format), $text);
585  print '</td><td style="text-align:right" class="nowrap">';
586  print '<a href="'.DOL_URL_ROOT.'/imports/emptyexample.php?format='.$format.$param.'" target="_blank" rel="noopener noreferrer">';
587  print img_picto('', 'download', 'class="paddingright opacitymedium"');
588  print $langs->trans("DownloadEmptyExampleShort");
589  print '</a>';
590  print $form->textwithpicto('', $langs->trans("DownloadEmptyExample").'.<br>'.$langs->trans("StarAreMandatory"));
591  print '</td></tr>';
592 
593  print '</table>';
594  print '</div>';
595 
596  print dol_get_fiche_end();
597 
598 
599  if ($format == 'xlsx' && !class_exists('XMLWriter')) {
600  $langs->load("install");
601  print info_admin($langs->trans("ErrorPHPDoesNotSupport", 'php-xml'), 0, 0, 1, 'error');
602  }
603 
604 
605  print '<br><br>';
606 
607  print '<form name="userfile" action="'.$_SERVER["PHP_SELF"].'" enctype="multipart/form-data" method="POST">';
608  print '<input type="hidden" name="token" value="'.newToken().'">';
609  print '<input type="hidden" value="'.$step.'" name="step">';
610  print '<input type="hidden" value="'.dol_escape_htmltag($format).'" name="format">';
611  print '<input type="hidden" value="'.$excludefirstline.'" name="excludefirstline">';
612  print '<input type="hidden" value="'.$endatlinenb.'" name="endatlinenb">';
613  print '<input type="hidden" value="'.dol_escape_htmltag($separator).'" name="separator">';
614  print '<input type="hidden" value="'.dol_escape_htmltag($enclosure).'" name="enclosure">';
615  print '<input type="hidden" value="'.dol_escape_htmltag($datatoimport).'" name="datatoimport">';
616 
617  print '<span class="opacitymedium">';
618  $s = $langs->trans("ChooseFileToImport", '{s1}');
619  $s = str_replace('{s1}', img_picto('', 'next'), $s);
620  print $s;
621  print '</span><br><br>';
622 
623  $filetoimport = '';
624 
625  // Input file name box
626  print '<div class="marginbottomonly">';
627  $maxfilesizearray = getMaxFileSizeArray();
628  $maxmin = $maxfilesizearray['maxmin'];
629  if ($maxmin > 0) {
630  print '<input type="hidden" name="MAX_FILE_SIZE" value="'.($maxmin * 1024).'">'; // MAX_FILE_SIZE must precede the field type=file
631  }
632  print '<input type="file" name="userfile" size="20" maxlength="80"> &nbsp; &nbsp; ';
633  $out = (empty($conf->global->MAIN_UPLOAD_DOC) ? ' disabled' : '');
634  print '<input type="submit" class="button small" value="'.$langs->trans("AddFile").'"'.$out.' name="sendit">';
635  $out = '';
636  if (!empty($conf->global->MAIN_UPLOAD_DOC)) {
637  $max = $conf->global->MAIN_UPLOAD_DOC; // In Kb
638  $maxphp = @ini_get('upload_max_filesize'); // In unknown
639  if (preg_match('/k$/i', $maxphp)) {
640  $maxphp = (int) substr($maxphp, 0, -1) * 1;
641  }
642  if (preg_match('/m$/i', $maxphp)) {
643  $maxphp = (int) substr($maxphp, 0, -1) * 1024;
644  }
645  if (preg_match('/g$/i', $maxphp)) {
646  $maxphp = (int) substr($maxphp, 0, -1) * 1024 * 1024;
647  }
648  if (preg_match('/t$/i', $maxphp)) {
649  $maxphp = (int) substr($maxphp, 0, -1) * 1024 * 1024 * 1024;
650  }
651  $maxphp2 = @ini_get('post_max_size'); // In unknown
652  if (preg_match('/k$/i', $maxphp2)) {
653  $maxphp2 = (int) substr($maxphp2, 0, -1) * 1;
654  }
655  if (preg_match('/m$/i', $maxphp2)) {
656  $maxphp2 = (int) substr($maxphp2, 0, -1) * 1024;
657  }
658  if (preg_match('/g$/i', $maxphp2)) {
659  $maxphp2 = (int) substr($maxphp2, 0, -1) * 1024 * 1024;
660  }
661  if (preg_match('/t$/i', $maxphp2)) {
662  $maxphp2 = (int) substr($maxphp2, 0, -1) * 1024 * 1024 * 1024;
663  }
664  // Now $max and $maxphp and $maxphp2 are in Kb
665  $maxmin = $max;
666  $maxphptoshow = $maxphptoshowparam = '';
667  if ($maxphp > 0) {
668  $maxmin = min($max, $maxphp);
669  $maxphptoshow = $maxphp;
670  $maxphptoshowparam = 'upload_max_filesize';
671  }
672  if ($maxphp2 > 0) {
673  $maxmin = min($max, $maxphp2);
674  if ($maxphp2 < $maxphp) {
675  $maxphptoshow = $maxphp2;
676  $maxphptoshowparam = 'post_max_size';
677  }
678  }
679 
680  $langs->load('other');
681  $out .= ' ';
682  $out .= info_admin($langs->trans("ThisLimitIsDefinedInSetup", $max, $maxphptoshow), 1);
683  } else {
684  $out .= ' ('.$langs->trans("UploadDisabled").')';
685  }
686  print $out;
687  print '</div>';
688 
689  // Search available imports
690  $filearray = dol_dir_list($conf->import->dir_temp, 'files', 0, '', '', 'name', SORT_DESC);
691  if (count($filearray) > 0) {
692  print '<div class="div-table-responsive-no-min">'; // You can use div-table-responsive-no-min if you dont need reserved height for your table
693  print '<table class="noborder centpercent" width="100%" cellpadding="4">';
694 
695  $dir = $conf->import->dir_temp;
696 
697  // Search available files to import
698  $i = 0;
699  foreach ($filearray as $key => $val) {
700  $file = $val['name'];
701 
702  // readdir return value in ISO and we want UTF8 in memory
703  if (!utf8_check($file)) {
704  $file = utf8_encode($file);
705  }
706 
707  if (preg_match('/^\./', $file)) {
708  continue;
709  }
710 
711  $modulepart = 'import';
712  $urlsource = $_SERVER["PHP_SELF"].'?step='.$step.$param.'&filetoimport='.urlencode($filetoimport);
713  $relativepath = $file;
714 
715  print '<tr class="oddeven">';
716  print '<td>';
717  print img_mime($file, '', 'pictofixedwidth');
718  print '<a data-ajax="false" href="'.DOL_URL_ROOT.'/document.php?modulepart='.$modulepart.'&file='.urlencode($relativepath).'&step=3'.$param.'" target="_blank" rel="noopener noreferrer">';
719  print $file;
720  print '</a>';
721  print '</td>';
722  // Affiche taille fichier
723  print '<td style="text-align:right">'.dol_print_size(dol_filesize($dir.'/'.$file)).'</td>';
724  // Affiche date fichier
725  print '<td style="text-align:right">'.dol_print_date(dol_filemtime($dir.'/'.$file), 'dayhour').'</td>';
726  // Del button
727  print '<td style="text-align:right"><a href="'.$_SERVER['PHP_SELF'].'?action=delete&token='.newToken().'&step=3'.$param.'&urlfile='.urlencode($relativepath);
728  print '">'.img_delete().'</a></td>';
729  // Action button
730  print '<td style="text-align:right">';
731  print '<a href="'.$_SERVER['PHP_SELF'].'?step=4'.$param.'&filetoimport='.urlencode($relativepath).'">'.img_picto($langs->trans("NewImport"), 'next', 'class="fa-15"').'</a>';
732  print '</td>';
733  print '</tr>';
734  }
735 
736  print '</table>';
737  print '</div>';
738  }
739 
740  print '</form>';
741 }
742 
743 
744 // STEP 4: Page to make matching between source file and database fields
745 if ($step == 4 && $datatoimport) {
746  //var_dump($_SESSION["dol_array_match_file_to_database_select"]);
747  $serialized_array_match_file_to_database = isset($_SESSION["dol_array_match_file_to_database_select"]) ? $_SESSION["dol_array_match_file_to_database_select"] : '';
748  $fieldsarray = explode(',', $serialized_array_match_file_to_database);
749  $array_match_file_to_database = array(); // Same than $fieldsarray but with mapped value only (col1 => 's.fielda', col2 => 's.fieldb'...)
750  foreach ($fieldsarray as $elem) {
751  $tabelem = explode('=', $elem, 2);
752  $key = $tabelem[0];
753  $val = (isset($tabelem[1]) ? $tabelem[1] : '');
754  if ($key && $val) {
755  $array_match_file_to_database[$key] = $val;
756  }
757  }
758 
759  //var_dump($serialized_array_match_file_to_database);
760  //var_dump($fieldsarray);
761  //var_dump($array_match_file_to_database);
762 
763  $model = $format;
764  $list = $objmodelimport->liste_modeles($db);
765 
766  if (empty($separator)) {
767  $separator = (empty($conf->global->IMPORT_CSV_SEPARATOR_TO_USE) ? ',' : $conf->global->IMPORT_CSV_SEPARATOR_TO_USE);
768  }
769 
770  // The separator has been defined, if it is a unique char, we check it is valid by reading the source file
771  if ($model == 'csv' && strlen($separator) == 1 && !GETPOSTISSET('separator')) {
772  // Count the char in first line of file.
773  $fh = fopen($conf->import->dir_temp.'/'.$filetoimport, 'r');
774  if ($fh) {
775  $sline = fgets($fh, 1000000);
776  fclose($fh);
777  $nboccurence = substr_count($sline, $separator);
778  $nboccurencea = substr_count($sline, ',');
779  $nboccurenceb = substr_count($sline, ';');
780  //var_dump($nboccurence." ".$nboccurencea." ".$nboccurenceb);exit;
781  if ($nboccurence == 0) {
782  if ($nboccurencea > 2) {
783  $separator = ',';
784  } elseif ($nboccurenceb > 2) {
785  $separator = ';';
786  }
787  }
788  }
789  }
790 
791  // The value to use
792  $separator_used = str_replace('\t', "\t", $separator);
793 
794  // Create classe to use for import
795  $dir = DOL_DOCUMENT_ROOT."/core/modules/import/";
796  $file = "import_".$model.".modules.php";
797  $classname = "Import".ucfirst($model);
798  require_once $dir.$file;
799  $obj = new $classname($db, $datatoimport);
800  if ($model == 'csv') {
801  $obj->separator = $separator_used;
802  $obj->enclosure = $enclosure;
803  }
804  if ($model == 'xlsx') {
805  if (!preg_match('/\.xlsx$/i', $filetoimport)) {
806  $langs->load("errors");
807  $param = '&datatoimport='.$datatoimport.'&format='.$format;
808  setEventMessages($langs->trans("ErrorFileMustHaveFormat", $model), null, 'errors');
809  header("Location: ".$_SERVER["PHP_SELF"].'?step=3'.$param.'&filetoimport='.urlencode($relativepath));
810  exit;
811  }
812  }
813 
814  if (GETPOST('update')) {
815  $array_match_file_to_database = array();
816  }
817 
818  // Load source fields in input file
819  $fieldssource = array();
820  $result = $obj->import_open_file($conf->import->dir_temp.'/'.$filetoimport, $langs);
821  if ($result >= 0) {
822  // Read first line
823  $arrayrecord = $obj->import_read_record();
824  // Put into array fieldssource starting with 1.
825  $i = 1;
826  foreach ($arrayrecord as $key => $val) {
827  if ($val["type"] != -1) {
828  $fieldssource[$i]['example1'] = dol_trunc($val['val'], 128);
829  $i++;
830  }
831  }
832  $obj->import_close_file();
833  }
834 
835  // Load targets fields in database
836  $fieldstarget = $objimport->array_import_fields[0];
837  $minpos = min(count($fieldssource), count($fieldstarget));
838  //var_dump($array_match_file_to_database);
839 
840 
841  $initialloadofstep4 = false;
842  if (empty($_SESSION['dol_array_match_file_to_database_select'])) {
843  $initialloadofstep4 = true;
844  }
845 
846  // Is it a first time in page (if yes, we must initialize array_match_file_to_database)
847  if (count($array_match_file_to_database) == 0) {
848  // This is first input in screen, we need to define
849  // $array_match_file_to_database
850  // $serialized_array_match_file_to_database
851  // $_SESSION["dol_array_match_file_to_database"]
852  $pos = 1;
853  $num = count($fieldssource);
854  while ($pos <= $num) {
855  if ($num >= 1 && $pos <= $num) {
856  $posbis = 1;
857  foreach ($fieldstarget as $key => $val) {
858  if ($posbis < $pos) {
859  $posbis++;
860  continue;
861  }
862  // We found the key of targets that is at position pos
863  $array_match_file_to_database[$pos] = $key;
864  break;
865  }
866  }
867  $pos++;
868  }
869  }
870  $array_match_database_to_file = array_flip($array_match_file_to_database);
871  //var_dump($array_match_database_to_file);
872  //var_dump($_SESSION["dol_array_match_file_to_database_select"]);
873 
874  $fieldstarget_tmp = array();
875  $arraykeysfieldtarget = array_keys($fieldstarget);
876  $position = 0;
877  foreach ($fieldstarget as $key => $label) {
878  $isrequired = preg_match('/\*$/', $label);
879  if (!empty($isrequired)) {
880  $newlabel = substr($label, 0, -1);
881  $fieldstarget_tmp[$key] = array("label"=>$newlabel, "required"=>true);
882  } else {
883  $fieldstarget_tmp[$key] = array("label"=>$label, "required"=>false);
884  }
885  if (!empty($array_match_database_to_file[$key])) {
886  $fieldstarget_tmp[$key]["imported"] = true;
887  $fieldstarget_tmp[$key]["position"] = $array_match_database_to_file[$key]-1;
888  $keytoswap = $key;
889  while (!empty($array_match_database_to_file[$keytoswap])) {
890  if ($position+1 > $array_match_database_to_file[$keytoswap]) {
891  $keytoswapwith = $array_match_database_to_file[$keytoswap]-1;
892  $tmp = [$keytoswap=>$fieldstarget_tmp[$keytoswap]];
893  unset($fieldstarget_tmp[$keytoswap]);
894  $fieldstarget_tmp = arrayInsert($fieldstarget_tmp, $keytoswapwith, $tmp);
895  $keytoswapwith = $arraykeysfieldtarget[$array_match_database_to_file[$keytoswap]-1];
896  $tmp = $fieldstarget_tmp[$keytoswapwith];
897  unset($fieldstarget_tmp[$keytoswapwith]);
898  $fieldstarget_tmp[$keytoswapwith] = $tmp;
899  $keytoswap = $keytoswapwith;
900  } else {
901  break;
902  }
903  }
904  } else {
905  $fieldstarget_tmp[$key]["imported"] = false;
906  }
907  $position++;
908  }
909  $fieldstarget = $fieldstarget_tmp;
910 
911  //print $serialized_array_match_file_to_database;
912  //print $_SESSION["dol_array_match_file_to_database"];
913  //print $_SESSION["dol_array_match_file_to_database_select"];
914  //var_dump($array_match_file_to_database);exit;
915 
916  // Now $array_match_file_to_database contains fieldnb(1,2,3...)=>fielddatabase(key in $array_match_file_to_database)
917 
918  $param = '&format='.$format.'&datatoimport='.urlencode($datatoimport).'&filetoimport='.urlencode($filetoimport);
919  if ($excludefirstline) {
920  $param .= '&excludefirstline='.urlencode($excludefirstline);
921  }
922  if ($endatlinenb) {
923  $param .= '&endatlinenb='.urlencode($endatlinenb);
924  }
925  if ($separator) {
926  $param .= '&separator='.urlencode($separator);
927  }
928  if ($enclosure) {
929  $param .= '&enclosure='.urlencode($enclosure);
930  }
931 
932  llxHeader('', $langs->trans("NewImport"), $help_url);
933 
934  $head = import_prepare_head($param, 4);
935 
936  print dol_get_fiche_head($head, 'step4', '', -2);
937 
938  print '<div class="underbanner clearboth"></div>';
939  print '<div class="fichecenter">';
940 
941  print '<table class="centpercent border tableforfield">';
942 
943  // Module
944  print '<tr><td class="titlefieldcreate">'.$langs->trans("Module").'</td>';
945  print '<td>';
946  $titleofmodule = $objimport->array_import_module[0]['module']->getName();
947  // Special cas for import common to module/services
948  if (in_array($objimport->array_import_code[0], array('produit_supplierprices', 'produit_multiprice', 'produit_languages'))) {
949  $titleofmodule = $langs->trans("ProductOrService");
950  }
951  print $titleofmodule;
952  print '</td></tr>';
953 
954  // Lot de donnees a importer
955  print '<tr><td>'.$langs->trans("DatasetToImport").'</td>';
956  print '<td>';
957  $entity = preg_replace('/:.*$/', '', $objimport->array_import_icon[0]);
958  $entityicon = strtolower(!empty($entitytoicon[$entity]) ? $entitytoicon[$entity] : $entity);
959  print img_object($objimport->array_import_module[0]['module']->getName(), $entityicon).' ';
960  print $objimport->array_import_label[0];
961  print '</td></tr>';
962 
963  print '</table>';
964  print '</div>';
965 
966  print load_fiche_titre($langs->trans("InformationOnSourceFile"), '', 'file-export');
967 
968  print '<div class="underbanner clearboth"></div>';
969  print '<div class="fichecenter">';
970  print '<table width="100%" class="border tableforfield">';
971 
972  // Source file format
973  print '<tr><td class="titlefieldcreate">'.$langs->trans("SourceFileFormat").'</td>';
974  print '<td>';
975  $text = $objmodelimport->getDriverDescForKey($format);
976  print $form->textwithpicto($objmodelimport->getDriverLabelForKey($format), $text);
977  print '</td></tr>';
978 
979  // Separator and enclosure
980  if ($model == 'csv') {
981  print '<tr><td>'.$langs->trans("CsvOptions").'</td>';
982  print '<td>';
983  print '<form method="POST">';
984  print '<input type="hidden" name="token" value="'.newToken().'">';
985  print '<input type="hidden" value="'.$step.'" name="step">';
986  print '<input type="hidden" value="'.$format.'" name="format">';
987  print '<input type="hidden" value="'.$excludefirstline.'" name="excludefirstline">';
988  print '<input type="hidden" value="'.$endatlinenb.'" name="endatlinenb">';
989  print '<input type="hidden" value="'.$datatoimport.'" name="datatoimport">';
990  print '<input type="hidden" value="'.$filetoimport.'" name="filetoimport">';
991  print $langs->trans("Separator").' : ';
992  print '<input type="text" class="width25 center" name="separator" value="'.dol_escape_htmltag($separator).'"/>';
993  print '&nbsp;&nbsp;&nbsp;&nbsp;'.$langs->trans("Enclosure").' : ';
994  print '<input type="text" class="width25 center" name="enclosure" value="'.dol_escape_htmltag($enclosure).'"/> ';
995  print '<input name="update" type="submit" value="'.$langs->trans('Update').'" class="button smallpaddingimp" />';
996  print '</form>';
997  print '</td></tr>';
998  }
999 
1000  // File to import
1001  print '<tr><td>'.$langs->trans("FileToImport").'</td>';
1002  print '<td>';
1003  $modulepart = 'import';
1004  $relativepath = GETPOST('filetoimport');
1005  print '<a data-ajax="false" href="'.DOL_URL_ROOT.'/document.php?modulepart='.$modulepart.'&file='.urlencode($relativepath).'&step=4'.$param.'" target="_blank" rel="noopener noreferrer">';
1006  print img_mime($file, '', 'pictofixedwidth');
1007  print $filetoimport;
1008  print img_picto($langs->trans("Download"), 'download', 'class="paddingleft opacitymedium"');
1009  print '</a>';
1010  print '</td></tr>';
1011 
1012  print '</table>';
1013  print '</div>';
1014 
1015  print dol_get_fiche_end();
1016 
1017  print '<br>'."\n";
1018 
1019 
1020  // List of source fields
1021  print '<!-- List of source fields -->'."\n";
1022  print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
1023  print '<input type="hidden" name="token" value="'.newToken().'">';
1024  print '<input type="hidden" name="action" value="select_model">';
1025  print '<input type="hidden" name="step" value="4">';
1026  print '<input type="hidden" name="format" value="'.$format.'">';
1027  print '<input type="hidden" name="datatoimport" value="'.$datatoimport.'">';
1028  print '<input type="hidden" name="filetoimport" value="'.$filetoimport.'">';
1029  print '<input type="hidden" name="excludefirstline" value="'.$excludefirstline.'">';
1030  print '<input type="hidden" name="endatlinenb" value="'.$endatlinenb.'">';
1031  print '<input type="hidden" name="separator" value="'.dol_escape_htmltag($separator).'">';
1032  print '<input type="hidden" name="enclosure" value="'.dol_escape_htmltag($enclosure).'">';
1033 
1034  // Import profile to use/load
1035  print '<div class="marginbottomonly">';
1036  print '<span class="opacitymedium">';
1037  $s = $langs->trans("SelectImportFieldsSource", '{s1}');
1038  $s = str_replace('{s1}', img_picto('', 'grip_title', '', false, 0, 0, '', '', 0), $s);
1039  print $s;
1040  print '</span> ';
1041  $htmlother->select_import_model($importmodelid, 'importmodelid', $datatoimport, 1, $user->id);
1042  print '<input type="submit" class="button small reposition" value="'.$langs->trans("Select").'">';
1043  print '</div>';
1044  print '</form>';
1045 
1046  // Title of array with fields
1047  print '<div class="div-table-responsive-no-min">'; // You can use div-table-responsive-no-min if you dont need reserved height for your table
1048  print '<table class="noborder centpercent">';
1049  print '<tr class="liste_titre">';
1050  print '<td>'.$langs->trans("FieldsInSourceFile").'</td>';
1051  print '<td>'.$langs->trans("FieldsInTargetDatabase").'</td>';
1052  print '</tr>';
1053 
1054  //var_dump($array_match_file_to_database);
1055 
1056  print '<tr valign="top"><td width="50%" class="nopaddingleftimp">';
1057 
1058  $fieldsplaced = array();
1059  $valforsourcefieldnb = array();
1060  $listofkeys = array();
1061  foreach ($array_match_file_to_database as $key => $val) {
1062  $listofkeys[$key] = 1;
1063  }
1064 
1065  print "\n<!-- Box left container -->\n";
1066  print '<div id="left" class="connectedSortable">'."\n";
1067 
1068  // List of source fields
1069  $var = false;
1070  $lefti = 1;
1071  foreach ($fieldssource as $key => $val) {
1072  show_elem($fieldssource, $key, $val, $var); // key is field number in source file
1073  $listofkeys[$key] = 1;
1074  $fieldsplaced[$key] = 1;
1075  $valforsourcefieldnb[$lefti] = $key;
1076  $lefti++;
1077 
1078  if ($lefti > count($fieldstarget)) {
1079  break; // Other fields are in the not imported area
1080  }
1081  }
1082  //var_dump($valforsourcefieldnb);
1083 
1084  print "</div>\n";
1085  print "<!-- End box left container -->\n";
1086 
1087 
1088  print '</td><td width="50%" class="nopaddingrightimp">';
1089 
1090  // Set the list of all possible target fields in Dolibarr.
1091  $optionsall = array();
1092  foreach ($fieldstarget as $code => $line) {
1093  //var_dump($line);
1094 
1095  $tmparray = explode('|', $line["label"]); // If label of field is several translation keys separated with |
1096  $labeltoshow = '';
1097  foreach ($tmparray as $tmpkey => $tmpval) {
1098  $labeltoshow .= ($labeltoshow ? ' '.$langs->trans('or').' ' : '').$langs->transnoentities($tmpval);
1099  }
1100  $optionsall[$code] = array('labelkey'=>$line['label'], 'labelkeyarray'=>$tmparray, 'label'=>$labeltoshow, 'required'=>(empty($line["required"]) ? 0 : 1), 'position'=>!empty($line['position']) ? $line['position'] : 0);
1101  // TODO Get type from a new array into module descriptor.
1102  //$picto = 'email';
1103  $picto = '';
1104  if ($picto) {
1105  $optionsall[$code]['picto'] = $picto;
1106  }
1107  }
1108  // $optionsall is an array of all possible target fields. key=>array('label'=>..., 'xxx')
1109 
1110  $height = '32px'; //needs px for css height attribute below
1111  $i = 0;
1112  $mandatoryfieldshavesource = true;
1113 
1114  //var_dump($fieldstarget);
1115  //var_dump($optionsall);
1116  //exit;
1117 
1118  //var_dump($_SESSION['dol_array_match_file_to_database']);
1119  //var_dump($_SESSION['dol_array_match_file_to_database_select']);
1120  //exit;
1121  //var_dump($optionsall);
1122  //var_dump($fieldssource);
1123  //var_dump($fieldstarget);
1124 
1125  $modetoautofillmapping = 'session'; // Use setup in session
1126  if ($initialloadofstep4) {
1127  $modetoautofillmapping = 'guess';
1128  }
1129  //var_dump($modetoautofillmapping);
1130 
1131  print '<table class="nobordernopadding centpercent tableimport">';
1132  foreach ($fieldssource as $code => $line) { // $fieldssource is an array code=column num, line=content on first line for column in source file.
1133  if ($i == $minpos) {
1134  break;
1135  }
1136  print '<tr style="height:'.$height.'" class="trimport oddevenimport">';
1137  $entity = (!empty($objimport->array_import_entities[0][$code]) ? $objimport->array_import_entities[0][$code] : $objimport->array_import_icon[0]);
1138 
1139  $entityicon = !empty($entitytoicon[$entity]) ? $entitytoicon[$entity] : $entity; // $entityicon must string name of picto of the field like 'project', 'company', 'contact', 'modulename', ...
1140  $entitylang = $entitytolang[$entity] ? $entitytolang[$entity] : $objimport->array_import_label[0]; // $entitylang must be a translation key to describe object the field is related to, like 'Company', 'Contact', 'MyModyle', ...
1141 
1142  //print '<td class="nowraponall" style="font-weight: normal">=> '.img_object('', $entityicon).' '.$langs->trans($entitylang).'</td>';
1143  print '<td class="nowraponall" style="font-weight: normal">=> </td>';
1144  print '<td class="nowraponall" style="font-weight: normal">';
1145 
1146  //var_dump($_SESSION['dol_array_match_file_to_database_select']);
1147  //var_dump($_SESSION['dol_array_match_file_to_database']);
1148 
1149  $selectforline = '';
1150  $selectforline .= '<select id="selectorderimport_'.($i+1).'" class="targetselectchange minwidth300" name="select_'.($i+1).'">';
1151  if (!empty($line["imported"])) {
1152  $selectforline .= '<option value="-1">&nbsp;</option>';
1153  } else {
1154  $selectforline .= '<option selected="" value="-1">&nbsp;</option>';
1155  }
1156 
1157  $j = 0;
1158  $codeselectedarray = array();
1159  foreach ($optionsall as $tmpcode => $tmpval) { // Loop on each entry to add into each combo list.
1160  $label = '';
1161  if (!empty($tmpval['picto'])) {
1162  $label .= img_picto('', $tmpval['picto'], 'class="pictofixedwidth"');
1163  }
1164  $label .= $tmpval['required'] ? '<strong>' : '';
1165  $label .= $tmpval['label'];
1166  $label .= $tmpval['required'] ? '*</strong>' : '';
1167 
1168  $tablealias = preg_replace('/(\..*)$/i', '', $tmpcode);
1169  $tablename = !empty($objimport->array_import_tables[0][$tablealias]) ? $objimport->array_import_tables[0][$tablealias] : "";
1170 
1171  $htmltext = '';
1172 
1173  $filecolumn = ($i + 1);
1174  // Source field info
1175  if (empty($objimport->array_import_convertvalue[0][$tmpcode])) { // If source file does not need convertion
1176  $filecolumntoshow = num2Alpha($i);
1177  } else {
1178  if ($objimport->array_import_convertvalue[0][$tmpcode]['rule'] == 'fetchidfromref') {
1179  $htmltext .= $langs->trans("DataComeFromIdFoundFromRef", $langs->transnoentitiesnoconv($entitylang)).'<br>';
1180  }
1181  if ($objimport->array_import_convertvalue[0][$tmpcode]['rule'] == 'fetchidfromcodeid') {
1182  $htmltext .= $langs->trans("DataComeFromIdFoundFromCodeId", $langs->transnoentitiesnoconv($objimport->array_import_convertvalue[0][$tmpcode]['dict'])).'<br>';
1183  }
1184  }
1185  // Source required
1186  $example = !empty($objimport->array_import_examplevalues[0][$tmpcode])?$objimport->array_import_examplevalues[0][$tmpcode]:"";
1187  // Example
1188  if (empty($objimport->array_import_convertvalue[0][$tmpcode])) { // If source file does not need convertion
1189  if ($example) {
1190  $htmltext .= $langs->trans("SourceExample").': <b>'.str_replace('"', '', $example).'</b><br>';
1191  }
1192  } else {
1193  if ($objimport->array_import_convertvalue[0][$tmpcode]['rule'] == 'fetchidfromref') {
1194  $htmltext .= $langs->trans("SourceExample").': <b>'.$langs->transnoentitiesnoconv("ExampleAnyRefFoundIntoElement", $entitylang).($example ? ' ('.$langs->transnoentitiesnoconv("Example").': '.str_replace('"', '', $example).')' : '').'</b><br>';
1195  } elseif ($objimport->array_import_convertvalue[0][$tmpcode]['rule'] == 'fetchidfromcodeid') {
1196  $htmltext .= $langs->trans("SourceExample").': <b>'.$langs->trans("ExampleAnyCodeOrIdFoundIntoDictionary", $langs->transnoentitiesnoconv($objimport->array_import_convertvalue[0][$tmpcode]['dict'])).($example ? ' ('.$langs->transnoentitiesnoconv("Example").': '.str_replace('"', '', $example).')' : '').'</b><br>';
1197  } elseif ($example) {
1198  $htmltext .= $langs->trans("SourceExample").': <b>'.str_replace('"', '', $example).'</b><br>';
1199  }
1200  }
1201  // Format control rule
1202  if (!empty($objimport->array_import_regex[0][$tmpcode])) {
1203  $htmltext .= $langs->trans("FormatControlRule").': <b>'.str_replace('"', '', $objimport->array_import_regex[0][$tmpcode]).'</b><br>';
1204  }
1205 
1206  //var_dump($htmltext);
1207  $htmltext .= $langs->trans("InformationOnTargetTables").': &nbsp; <b>'.$tablename."->".preg_replace('/^.*\./', '', $tmpcode)."</b>";
1208 
1209  $labelhtml = $label.' '.$form->textwithpicto('', $htmltext, 1, 'help', '', 1);
1210 
1211  $selectforline .= '<option value="'.$tmpcode.'"';
1212  if ($modetoautofillmapping == 'orderoftargets') {
1213  // The mode where we fill the preselected value of combo one by one in order of available targets fields in the declaration in descriptor file.
1214  if ($j == $i) {
1215  $selectforline .= ' selected';
1216  }
1217  } elseif ($modetoautofillmapping == 'guess') {
1218  // The mode where we try to guess which value to preselect from the name in first column of source file.
1219  // $line['example1'] is the label of the column found on first line
1220  $regs = array();
1221  if (preg_match('/^(.+)\((.+\..+)\)$/', $line['example1'], $regs)) { // If text is "Label (x.abc)"
1222  $tmpstring1 = $regs[1];
1223  $tmpstring2 = $regs[2];
1224  } else {
1225  $tmpstring1 = $line['example1'];
1226  $tmpstring2 = '';
1227  }
1228  $tmpstring1 = strtolower(str_replace('*', '', trim($tmpstring1)));
1229  $tmpstring2 = strtolower(str_replace('*', '', trim($tmpstring2)));
1230 
1231  // $tmpstring1 and $tmpstring2 are string from input file.
1232  foreach ($tmpval['labelkeyarray'] as $tmpval2) {
1233  $labeltarget = $langs->transnoentities($tmpval2);
1234  //var_dump($tmpstring1.' - '.$tmpstring2.' - '.$tmpval['labelkey'].' - '.$tmpval['label'].' - '.$tmpval2.' - '.$labeltarget);
1235  if ($tmpstring1 && ($tmpstring1 == $tmpcode || $tmpstring1 == strtolower($labeltarget)
1236  || $tmpstring1 == strtolower(dol_string_unaccent($labeltarget)) || $tmpstring1 == strtolower($tmpval2))) {
1237  if (empty($codeselectedarray[$code])) {
1238  $selectforline .= ' selected';
1239  $codeselectedarray[$code] = 1;
1240  break;
1241  }
1242  } elseif ($tmpstring2 && ($tmpstring2 == $tmpcode || $tmpstring2 == strtolower($labeltarget)
1243  || $tmpstring2 == strtolower(dol_string_unaccent($labeltarget)) || $tmpstring2 == strtolower($tmpval2))) {
1244  if (empty($codeselectedarray[$code])) {
1245  $selectforline .= ' selected';
1246  $codeselectedarray[$code] = 1;
1247  break;
1248  }
1249  }
1250  }
1251  } elseif ($modetoautofillmapping == 'session' && !empty($_SESSION['dol_array_match_file_to_database_select'])) {
1252  $tmpselectioninsession = dolExplodeIntoArray($_SESSION['dol_array_match_file_to_database_select'], ',', '=');
1253  //var_dump($code);
1254  if (!empty($tmpselectioninsession[($i+1)]) && $tmpselectioninsession[($i+1)] == $tmpcode) {
1255  $selectforline .= ' selected';
1256  }
1257  $selectforline .= ' data-debug="'.$tmpcode.'-'.$code.'-'.$j.'-'.(!empty($tmpselectioninsession[($i+1)]) ? $tmpselectioninsession[($i+1)] : "").'"';
1258  }
1259  $selectforline .= ' data-html="'.dol_escape_htmltag($labelhtml).'"';
1260  $selectforline .= '>';
1261  $selectforline .= $label;
1262  $selectforline .= '</options>';
1263  $j++;
1264  }
1265  $selectforline .= '</select>';
1266  $selectforline .= ajax_combobox('selectorderimport_'.($i+1));
1267 
1268  print $selectforline;
1269 
1270  print '</td>';
1271 
1272  // Tooltip at end of line
1273  print '<td class="nowraponall" style="font-weight:normal; text-align:right">';
1274 
1275  // Source field info
1276  $htmltext = '<b><u>'.$langs->trans("FieldSource").'</u></b><br>';
1277  $filecolumntoshow = num2Alpha($i);
1278  $htmltext .= $langs->trans("DataComeFromFileFieldNb", $filecolumntoshow).'<br>';
1279 
1280  print $form->textwithpicto('', $htmltext);
1281 
1282  print '</td>';
1283  print '</tr>';
1284  $i++;
1285  }
1286  print '</table>';
1287 
1288  print '</td></tr>';
1289 
1290  // Lines for remark
1291  print '<tr class="liste_titre"><td colspan="2">'.$langs->trans("Note").'</td></tr>';
1292  print '<tr><td colspan="2"><div id="div-mandatory-target-fields-not-mapped"></div></td></tr>';
1293 
1294  print '</table>';
1295  print '</div>';
1296 
1297 
1298  if (!empty($conf->use_javascript_ajax)) {
1299  print '<script type="text/javascript">'."\n";
1300  print 'var previousselectedvalueimport = "0";'."\n";
1301  print 'var previousselectedlabelimport = "0";'."\n";
1302  print 'var arrayofselectedvalues = [];'."\n";
1303  print 'var arrayoftargetfields = [];'."\n";
1304  print 'var arrayoftargetmandatoryfields = [];'."\n";
1305 
1306  // Loop on $fieldstarget (seems sorted by 'position') to store php array into javascript array
1307  $tmpi = 0;
1308  foreach ($fieldstarget as $key => $val) {
1309  print "arrayoftargetfields[".$tmpi."] = '".dol_escape_js($langs->trans($val['label']))."'; ";
1310  if ($val['required']) {
1311  print "arrayoftargetmandatoryfields[".$tmpi."] = '".dol_escape_js($key)."'; ";
1312  }
1313  $tmpi++;
1314  }
1315  print "\n";
1316 
1317  print '$(document).ready(function () {'."\n";
1318 
1319  print 'setOptionsToDisabled();'."\n";
1320  print 'saveSelection();'."\n";
1321 
1322  print '$(".targetselectchange").focus(function(){'."\n";
1323  print ' previousselectedvalueimport = $(this).val();'."\n";
1324  print ' previousselectedlabelimport = $(this).children("option:selected").text();'."\n";
1325  print ' console.log("previousselectedvalueimport="+previousselectedvalueimport)'."\n";
1326  print '})'."\n";
1327 
1328  // Function to set the disabled flag
1329  // - We set all option to "enabled"
1330  // - Then we scan all combo to get the value currently selected and save them into the array arrayofselectedvalues
1331  // - Then we set to disabled all fields that are selected
1332  print 'function setOptionsToDisabled() {'."\n";
1333  print ' console.log("Remove the disabled flag everywhere");'."\n";
1334  print ' $("select.targetselectchange").not($( this )).find(\'option\').prop("disabled", false);'."\n"; // Enable all options
1335  print ' arrayofselectedvalues = [];'."\n";
1336 
1337  print ' $("select.targetselectchange").each(function(){'."\n";
1338  print ' id = $(this).attr(\'id\')'."\n";
1339  print ' value = $(this).val()'."\n";
1340  print ' console.log("a selected value has been found for component "+id+" = "+value);'."\n";
1341  print ' arrayofselectedvalues.push(value);'."\n";
1342  print ' });'."\n";
1343 
1344  print ' console.log("List of all selected values arrayofselectedvalues");'."\n";
1345  print ' console.log(arrayofselectedvalues);'."\n";
1346  print ' console.log("Set the option to disabled for every entry that is currently selected somewhere else (so into arrayofselectedvalues)");'."\n";
1347 
1348  print ' $.each(arrayofselectedvalues, function(key, value) {'."\n"; // Loop on each selected value
1349  print ' if (value != -1) {'."\n";
1350  print ' console.log("Process key="+key+" value="+value+" to disable.");'."\n";
1351  print ' $("select.targetselectchange").find(\'option[value="\'+value+\'"]:not(:selected)\').prop("disabled", true);'."\n"; // Set to disabled except if currently selected
1352  print ' }'."\n";
1353  print ' });'."\n";
1354  print '};'."\n";
1355 
1356  // Function to save the selection in database
1357  print 'function saveSelection() {'."\n";
1358  //print ' console.log(arrayofselectedvalues);'."\n";
1359  print ' arrayselectedfields = [];'."\n";
1360  print ' arrayselectedfields.push(0);'."\n";
1361 
1362  print ' $.each( arrayofselectedvalues, function( key, value ) {'."\n";
1363  print ' if (value != -1) {'."\n";
1364  print ' arrayselectedfields.push(value);'."\n";
1365  print ' } else {'."\n";
1366  print ' arrayselectedfields.push(0);'."\n";
1367  print ' }'."\n";
1368  print ' });'."\n";
1369 
1370  print " $.ajax({\n";
1371  print " type: 'POST',\n";
1372  print " dataType: 'json',\n";
1373  print " url: '".dol_escape_js($_SERVER["PHP_SELF"])."?action=saveselectorder&token=".newToken()."',\n";
1374  print " data: 'selectorder='+arrayselectedfields.toString(),\n";
1375  print " success: function(){\n";
1376  print " console.log('The selected fields have been saved into '+arrayselectedfields.toString());\n";
1377  print " },\n";
1378  print ' });'."\n";
1379 
1380  // Now we loop on all target fields that are mandatory to show if they are not mapped yet.
1381  print ' console.log("arrayselectedfields");';
1382  print ' console.log(arrayselectedfields);';
1383  print ' console.log("arrayoftargetmandatoryfields");';
1384  print ' console.log(arrayoftargetmandatoryfields);';
1385  print " listtoshow = '';";
1386  print " nbelement = arrayoftargetmandatoryfields.length
1387  for (let i = 0; i < nbelement; i++) {
1388  if (arrayoftargetmandatoryfields[i] && ! arrayselectedfields.includes(arrayoftargetmandatoryfields[i])) {
1389  console.log(arrayoftargetmandatoryfields[i]+' not mapped');
1390  listtoshow = listtoshow + (listtoshow ? ', ' : '') + '<b>' + arrayoftargetfields[i] + '*</b>';
1391  }
1392  }
1393  console.log(listtoshow);
1394  if (listtoshow) {
1395  listtoshow = '".dol_escape_js(img_warning($langs->trans("MandatoryTargetFieldsNotMapped")).' '.$langs->trans("MandatoryTargetFieldsNotMapped")).": ' + listtoshow;
1396  $('#div-mandatory-target-fields-not-mapped').html(listtoshow);
1397  } else {
1398  $('#div-mandatory-target-fields-not-mapped').html('<span class=\"opacitymedium\">".dol_escape_js($langs->trans("AllTargetMandatoryFieldsAreMapped"))."</span>');
1399  }
1400  ";
1401 
1402  print '};'."\n";
1403 
1404  // If we make a change on a selectbox
1405  print '$(".targetselectchange").change(function(){'."\n";
1406  print ' setOptionsToDisabled();'."\n";
1407 
1408  print ' if(previousselectedlabelimport != "" && previousselectedvalueimport != -1) {'."\n";
1409  print ' let valuetochange = $(this).val(); '."\n";
1410  print ' $(".boxtdunused").each(function(){'."\n";
1411  print ' if ($(this).text().includes(valuetochange)){'."\n";
1412  print ' arraychild = $(this)[0].childNodes'."\n";
1413  print ' arraytexttomodify = arraychild[0].textContent.split(" ")'."\n";
1414  print ' arraytexttomodify[1] = previousselectedvalueimport '."\n";
1415  print ' textmodified = arraytexttomodify.join(" ") '."\n";
1416  print ' arraychild[0].textContent = textmodified'."\n";
1417  print ' arraychild[1].innerHTML = previousselectedlabelimport'."\n";
1418  print ' }'."\n";
1419  print ' })'."\n";
1420  print ' }'."\n";
1421  print ' $(this).blur()'."\n";
1422 
1423  print ' saveSelection()'."\n";
1424  print '});'."\n";
1425 
1426  print '})'."\n";
1427  print '</script>'."\n";
1428  }
1429 
1430  /*
1431  * Action bar
1432  */
1433  print '<div class="tabsAction">';
1434 
1435  if (count($array_match_file_to_database)) {
1436  if ($mandatoryfieldshavesource) {
1437  print '<a class="butAction saveorderselect" href="import.php?step=5'.$param.'&filetoimport='.urlencode($filetoimport).'">'.$langs->trans("NextStep").'</a>';
1438  } else {
1439  print '<a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->transnoentitiesnoconv("SomeMandatoryFieldHaveNoSource")).'">'.$langs->trans("NextStep").'</a>';
1440  }
1441  }
1442 
1443  print '</div>';
1444 
1445 
1446  // Area for profils import
1447  if (count($array_match_file_to_database)) {
1448  print '<br>'."\n";
1449  print '<!-- Area to add new import profile -->'."\n";
1450  print '<div class="marginbottomonly"><span class="opacitymedium">'.$langs->trans("SaveImportModel").'</span></div>';
1451 
1452  print '<form class="nocellnopadd" action="'.$_SERVER["PHP_SELF"].'" method="post">';
1453  print '<input type="hidden" name="token" value="'.newToken().'">';
1454  print '<input type="hidden" name="action" value="add_import_model">';
1455  print '<input type="hidden" name="step" value="'.$step.'">';
1456  print '<input type="hidden" name="format" value="'.$format.'">';
1457  print '<input type="hidden" name="datatoimport" value="'.$datatoimport.'">';
1458  print '<input type="hidden" name="filetoimport" value="'.$filetoimport.'">';
1459  print '<input type="hidden" name="hexa" value="'.$hexa.'">';
1460  print '<input type="hidden" name="excludefirstline" value="'.$excludefirstline.'">';
1461  print '<input type="hidden" name="endatlinenb" value="'.$endatlinenb.'">';
1462  print '<input type="hidden" name="page_y" value="">';
1463  print '<input type="hidden" value="'.dol_escape_htmltag($separator).'" name="separator">';
1464  print '<input type="hidden" value="'.dol_escape_htmltag($enclosure).'" name="enclosure">';
1465 
1466  print '<div class="div-table-responsive-no-min">'; // You can use div-table-responsive-no-min if you dont need reserved height for your table
1467  print '<table summary="selectofimportprofil" class="noborder centpercent">';
1468  print '<tr class="liste_titre">';
1469  print '<td>'.$langs->trans("ImportModelName").'</td>';
1470  print '<td>'.$langs->trans("Visibility").'</td>';
1471  print '<td></td>';
1472  print '</tr>';
1473 
1474  $nameofimportprofile = str_replace(' ', '-', $langs->trans("ImportProfile").' '.$titleofmodule.' '.dol_print_date(dol_now('gmt'), 'dayxcard'));
1475  if (GETPOST('import_name')) { // If we have submited a form, we take value used fot the update try
1476  $nameofimportprofile = $import_name;
1477  }
1478 
1479  print '<tr class="oddeven">';
1480  print '<td><input name="import_name" class="minwidth300" value="'.$nameofimportprofile.'"></td>';
1481  print '<td>';
1482  $arrayvisibility = array('private'=>$langs->trans("Private"), 'all'=>$langs->trans("Everybody"));
1483  print $form->selectarray('visibility', $arrayvisibility, 'private');
1484  print '</td>';
1485  print '<td class="right">';
1486  print '<input type="submit" class="button smallpaddingimp reposition" value="'.$langs->trans("SaveImportProfile").'">';
1487  print '</td></tr>';
1488 
1489  // List of existing import profils
1490  $sql = "SELECT rowid, label, fk_user, entity";
1491  $sql .= " FROM ".MAIN_DB_PREFIX."import_model";
1492  $sql .= " WHERE type = '".$db->escape($datatoimport)."'";
1493  if (empty($conf->global->EXPORTS_SHARE_MODELS)) { // EXPORTS_SHARE_MODELS means all templates are visible, whatever is owner.
1494  $sql .= " AND fk_user IN (0, ".((int) $user->id).")";
1495  }
1496  $sql .= " ORDER BY rowid";
1497 
1498  $resql = $db->query($sql);
1499  if ($resql) {
1500  $num = $db->num_rows($resql);
1501 
1502  $tmpuser = new user($db);
1503 
1504  $i = 0;
1505  while ($i < $num) {
1506  $obj = $db->fetch_object($resql);
1507 
1508  print '<tr class="oddeven"><td>';
1509  print $obj->label;
1510  print '</td>';
1511  print '<td>';
1512  if (empty($obj->fk_user)) {
1513  print $langs->trans("Everybody");
1514  } else {
1515  $tmpuser->fetch($obj->fk_user);
1516  print $tmpuser->getNomUrl(-1);
1517  }
1518  print '</td>';
1519  print '<td class="right">';
1520  print '<a class="reposition" href="'.$_SERVER["PHP_SELF"].'?step='.$step.$param.'&action=deleteprof&token='.newToken().'&id='.$obj->rowid.'&filetoimport='.urlencode($filetoimport).'">';
1521  print img_delete();
1522  print '</a>';
1523  print '</tr>';
1524  $i++;
1525  }
1526  } else {
1527  dol_print_error($db);
1528  }
1529 
1530  print '</table>';
1531  print '</div>';
1532 
1533  print '</form>';
1534  }
1535 }
1536 
1537 // STEP 5: Summary of choices and launch simulation
1538 if ($step == 5 && $datatoimport) {
1539  $max_execution_time_for_importexport = (empty($conf->global->IMPORT_MAX_EXECUTION_TIME) ? 300 : $conf->global->IMPORT_MAX_EXECUTION_TIME); // 5mn if not defined
1540  $max_time = @ini_get("max_execution_time");
1541  if ($max_time && $max_time < $max_execution_time_for_importexport) {
1542  dol_syslog("max_execution_time=".$max_time." is lower than max_execution_time_for_importexport=".$max_execution_time_for_importexport.". We try to increase it dynamically.");
1543  @ini_set("max_execution_time", $max_execution_time_for_importexport); // This work only if safe mode is off. also web servers has timeout of 300
1544  }
1545 
1546  $model = $format;
1547  $list = $objmodelimport->liste_modeles($db);
1548 
1549  // Create classe to use for import
1550  $dir = DOL_DOCUMENT_ROOT."/core/modules/import/";
1551  $file = "import_".$model.".modules.php";
1552  $classname = "Import".ucfirst($model);
1553  require_once $dir.$file;
1554  $obj = new $classname($db, $datatoimport);
1555  if ($model == 'csv') {
1556  $obj->separator = $separator_used;
1557  $obj->enclosure = $enclosure;
1558  }
1559 
1560  // Load source fields in input file
1561  $fieldssource = array();
1562  $result = $obj->import_open_file($conf->import->dir_temp.'/'.$filetoimport, $langs);
1563 
1564  if ($result >= 0) {
1565  // Read first line
1566  $arrayrecord = $obj->import_read_record();
1567  // Put into array fieldssource starting with 1.
1568  $i = 1;
1569  foreach ($arrayrecord as $key => $val) {
1570  $fieldssource[$i]['example1'] = dol_trunc($val['val'], 24);
1571  $i++;
1572  }
1573  $obj->import_close_file();
1574  }
1575 
1576  $nboflines = $obj->import_get_nb_of_lines($conf->import->dir_temp.'/'.$filetoimport);
1577 
1578  $param = '&leftmenu=import&format='.urlencode($format).'&datatoimport='.urlencode($datatoimport).'&filetoimport='.urlencode($filetoimport).'&nboflines='.urlencode($nboflines).'&separator='.urlencode($separator).'&enclosure='.urlencode($enclosure);
1579  $param2 = $param; // $param2 = $param without excludefirstline and endatlinenb
1580  if ($excludefirstline) {
1581  $param .= '&excludefirstline='.urlencode($excludefirstline);
1582  }
1583  if ($endatlinenb) {
1584  $param .= '&endatlinenb='.urlencode($endatlinenb);
1585  }
1586  if (!empty($updatekeys)) {
1587  $param .= '&updatekeys[]='.implode('&updatekeys[]=', $updatekeys);
1588  }
1589 
1590  llxHeader('', $langs->trans("NewImport"), 'EN:Module_Imports_En|FR:Module_Imports|ES:M&oacute;dulo_Importaciones');
1591 
1592  $head = import_prepare_head($param, 5);
1593 
1594 
1595  print '<form action="'.$_SERVER["PHP_SELF"].'?'.$param2.'" method="POST">';
1596  print '<input type="hidden" name="token" value="'.newToken().'">';
1597  print '<input type="hidden" name="step" value="5">'; // step 5
1598  print '<input type="hidden" name="action" value="launchsimu">'; // step 5
1599 
1600  print dol_get_fiche_head($head, 'step5', '', -2);
1601 
1602  print '<div class="underbanner clearboth"></div>';
1603  print '<div class="fichecenter">';
1604 
1605  print '<table width="100%" class="border tableforfield">';
1606 
1607  // Module
1608  print '<tr><td class="titlefieldcreate">'.$langs->trans("Module").'</td>';
1609  print '<td>';
1610  $titleofmodule = $objimport->array_import_module[0]['module']->getName();
1611  // Special cas for import common to module/services
1612  if (in_array($objimport->array_import_code[0], array('produit_supplierprices', 'produit_multiprice', 'produit_languages'))) {
1613  $titleofmodule = $langs->trans("ProductOrService");
1614  }
1615  print $titleofmodule;
1616  print '</td></tr>';
1617 
1618  // Lot de donnees a importer
1619  print '<tr><td>'.$langs->trans("DatasetToImport").'</td>';
1620  print '<td>';
1621  $entity = preg_replace('/:.*$/', '', $objimport->array_import_icon[0]);
1622  $entityicon = strtolower(!empty($entitytoicon[$entity]) ? $entitytoicon[$entity] : $entity);
1623  print img_object($objimport->array_import_module[0]['module']->getName(), $entityicon).' ';
1624  print $objimport->array_import_label[0];
1625  print '</td></tr>';
1626 
1627  print '</table>';
1628  print '</div>';
1629 
1630  print load_fiche_titre($langs->trans("InformationOnSourceFile"), '', 'file-export');
1631 
1632  print '<div class="underbanner clearboth"></div>';
1633  print '<div class="fichecenter">';
1634  print '<table width="100%" class="border tableforfield">';
1635 
1636  // Source file format
1637  print '<tr><td class="titlefieldcreate">'.$langs->trans("SourceFileFormat").'</td>';
1638  print '<td>';
1639  $text = $objmodelimport->getDriverDescForKey($format);
1640  print $form->textwithpicto($objmodelimport->getDriverLabelForKey($format), $text);
1641  print '</td></tr>';
1642 
1643  // Separator and enclosure
1644  if ($model == 'csv') {
1645  print '<tr><td>'.$langs->trans("CsvOptions").'</td>';
1646  print '<td>';
1647  print $langs->trans("Separator").' : '.dol_escape_htmltag($separator);
1648  print '&nbsp;&nbsp;&nbsp;&nbsp;'.$langs->trans("Enclosure").' : '.dol_escape_htmltag($enclosure);
1649  print '</td></tr>';
1650  }
1651 
1652  // File to import
1653  print '<tr><td>'.$langs->trans("FileToImport").'</td>';
1654  print '<td>';
1655  $modulepart = 'import';
1656  $relativepath = GETPOST('filetoimport');
1657  print '<a data-ajax="false" href="'.DOL_URL_ROOT.'/document.php?modulepart='.$modulepart.'&file='.urlencode($relativepath).'&step=4'.$param.'" target="_blank" rel="noopener noreferrer">';
1658  print img_mime($file, '', 'pictofixedwidth');
1659  print $filetoimport;
1660  print img_picto($langs->trans("Download"), 'download', 'class="paddingleft opacitymedium"');
1661  print '</a>';
1662  print '</td></tr>';
1663 
1664  // Total lines in source file
1665  print '<tr><td>';
1666  print $langs->trans("NbOfSourceLines");
1667  print '</td><td>';
1668  print $nboflines;
1669  print '</td></tr>';
1670 
1671  // Range of lines to import
1672  print '<tr><td>';
1673  print $langs->trans("ImportFromToLine");
1674  print '</td><td>';
1675  if ($action == 'launchsimu') {
1676  print '<input type="number" class="maxwidth50 right" name="excludefirstlinebis" disabled="disabled" value="'.$excludefirstline.'">';
1677  print '<input type="hidden" name="excludefirstline" value="'.$excludefirstline.'">';
1678  } else {
1679  print '<input type="number" class="maxwidth50 right" name="excludefirstline" value="'.$excludefirstline.'">';
1680  print $form->textwithpicto("", $langs->trans("SetThisValueTo2ToExcludeFirstLine"));
1681  }
1682  print ' - ';
1683  if ($action == 'launchsimu') {
1684  print '<input type="text" class="maxwidth50" name="endatlinenbbis" disabled="disabled" value="'.$endatlinenb.'">';
1685  print '<input type="hidden" name="endatlinenb" value="'.$endatlinenb.'">';
1686  } else {
1687  print '<input type="text" class="maxwidth50" name="endatlinenb" value="'.$endatlinenb.'">';
1688  print $form->textwithpicto("", $langs->trans("KeepEmptyToGoToEndOfFile"));
1689  }
1690  if ($action == 'launchsimu') {
1691  print ' &nbsp; <a href="'.$_SERVER["PHP_SELF"].'?step=5'.$param.'">'.$langs->trans("Modify").'</a>';
1692  }
1693  if ($excludefirstline == 2) {
1694  print $form->textwithpicto("", $langs->trans("WarningFirstImportedLine", $excludefirstline), 1, 'warning', "warningexcludefirstline");
1695  print '<script>
1696  $( document ).ready(function() {
1697  $("input[name=\'excludefirstline\']").on("change",function(){
1698  if($(this).val() <= 1){
1699  $(".warningexcludefirstline").hide();
1700  }else{
1701  $(".warningexcludefirstline").show();
1702  }
1703  })
1704  });
1705  </script>';
1706  }
1707  print '</td></tr>';
1708 
1709  // Keys for data UPDATE (not INSERT of new data)
1710  print '<tr><td>';
1711  print $form->textwithpicto($langs->trans("KeysToUseForUpdates"), $langs->trans("SelectPrimaryColumnsForUpdateAttempt"));
1712  print '</td><td>';
1713  if ($action == 'launchsimu') {
1714  if (count($updatekeys)) {
1715  print $form->multiselectarray('updatekeysbis', $objimport->array_import_updatekeys[0], $updatekeys, 0, 0, '', 1, '80%', 'disabled');
1716  } else {
1717  print '<span class="opacitymedium">'.$langs->trans("NoUpdateAttempt").'</span> &nbsp; -';
1718  }
1719  foreach ($updatekeys as $val) {
1720  print '<input type="hidden" name="updatekeys[]" value="'.$val.'">';
1721  }
1722  print ' &nbsp; <a href="'.$_SERVER["PHP_SELF"].'?step=5'.$param.'">'.$langs->trans("Modify").'</a>';
1723  } else {
1724  if (is_array($objimport->array_import_updatekeys[0]) && count($objimport->array_import_updatekeys[0])) { //TODO dropdown UL is created inside nested SPANS
1725  print $form->multiselectarray('updatekeys', $objimport->array_import_updatekeys[0], $updatekeys, 0, 0, '', 1, '80%');
1726  //print $form->textwithpicto("", $langs->trans("SelectPrimaryColumnsForUpdateAttempt"));
1727  } else {
1728  print '<span class="opacitymedium">'.$langs->trans("UpdateNotYetSupportedForThisImport").'</span>';
1729  }
1730  }
1731  /*echo '<pre>';
1732  print_r($objimport->array_import_updatekeys);
1733  echo '</pre>';*/
1734  print '</td></tr>';
1735 
1736  print '</table>';
1737  print '</div>';
1738 
1739 
1740  print load_fiche_titre($langs->trans("InformationOnTargetTables"), '', 'file-import');
1741 
1742  print '<div class="underbanner clearboth"></div>';
1743  print '<div class="fichecenter">';
1744 
1745  print '<table width="100%" class="border tableforfield">';
1746 
1747  // Tables imported
1748  print '<tr><td class="titlefieldcreate">';
1749  print $langs->trans("TablesTarget");
1750  print '</td><td>';
1751  $listtables = array();
1752  $sort_array_match_file_to_database = $array_match_file_to_database;
1753  foreach ($array_match_file_to_database as $code => $label) {
1754  //var_dump($fieldssource);
1755  if ($code > count($fieldssource)) {
1756  continue;
1757  }
1758  //print $code.'-'.$label;
1759  $alias = preg_replace('/(\..*)$/i', '', $label);
1760  $listtables[$alias] = $objimport->array_import_tables[0][$alias];
1761  }
1762  if (count($listtables)) {
1763  $newval = '';
1764  //ksort($listtables);
1765  foreach ($listtables as $val) {
1766  if ($newval) {
1767  print ', ';
1768  }
1769  $newval = $val;
1770  // Link to Dolibarr wiki pages
1771  /*$helppagename='EN:Table_'.$newval;
1772  if ($helppagename && empty($conf->global->MAIN_HELP_DISABLELINK))
1773  {
1774  // Get helpbaseurl, helppage and mode from helppagename and langs
1775  $arrayres=getHelpParamFor($helppagename,$langs);
1776  $helpbaseurl=$arrayres['helpbaseurl'];
1777  $helppage=$arrayres['helppage'];
1778  $mode=$arrayres['mode'];
1779  $newval.=' <a href="'.sprintf($helpbaseurl,$helppage).'">'.img_picto($langs->trans($mode == 'wiki' ? 'GoToWikiHelpPage': 'GoToHelpPage'),DOL_URL_ROOT.'/theme/common/helpdoc.png','',1).'</a>';
1780  }*/
1781  print $newval;
1782  }
1783  } else {
1784  print $langs->trans("Error");
1785  }
1786  print '</td></tr>';
1787 
1788  // Fields imported
1789  print '<tr><td>';
1790  print $langs->trans("FieldsTarget").'</td><td>';
1791  $listfields = array();
1792  $i = 0;
1793  //print 'fieldsource='.$fieldssource;
1794  $sort_array_match_file_to_database = $array_match_file_to_database;
1795  ksort($sort_array_match_file_to_database);
1796  //var_dump($sort_array_match_file_to_database);
1797  foreach ($sort_array_match_file_to_database as $code => $label) {
1798  $i++;
1799  //var_dump($fieldssource);
1800  if ($code > count($fieldssource)) {
1801  continue;
1802  }
1803  //print $code.'-'.$label;
1804  $alias = preg_replace('/(\..*)$/i', '', $label);
1805  $listfields[$i] = '<span class="nowrap">'.$langs->trans("Column").' '.num2Alpha($code - 1).' -> '.$label.'</span>';
1806  }
1807  print count($listfields) ? (join(', ', $listfields)) : $langs->trans("Error");
1808  print '</td></tr>';
1809 
1810  print '</table>';
1811  print '</div>';
1812 
1813  print dol_get_fiche_end();
1814 
1815 
1816  if ($action != 'launchsimu') {
1817  // Show import id
1818  print '<br><span class="opacitymedium">';
1819  print $langs->trans("NowClickToTestTheImport", $langs->transnoentitiesnoconv("RunSimulateImportFile")).'</span><br>';
1820  print '<br>';
1821 
1822  // Actions
1823  print '<div class="center">';
1824  if ($user->rights->import->run) {
1825  print '<input type="submit" class="butAction" value="'.$langs->trans("RunSimulateImportFile").'">';
1826  } else {
1827  print '<a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->transnoentitiesnoconv("NotEnoughPermissions")).'">'.$langs->trans("RunSimulateImportFile").'</a>';
1828  }
1829  print '</div>';
1830  } else {
1831  // Launch import
1832  $arrayoferrors = array();
1833  $arrayofwarnings = array();
1834  $maxnboferrors = empty($conf->global->IMPORT_MAX_NB_OF_ERRORS) ? 50 : $conf->global->IMPORT_MAX_NB_OF_ERRORS;
1835  $maxnbofwarnings = empty($conf->global->IMPORT_MAX_NB_OF_WARNINGS) ? 50 : $conf->global->IMPORT_MAX_NB_OF_WARNINGS;
1836  $nboferrors = 0;
1837  $nbofwarnings = 0;
1838 
1839  $importid = dol_print_date(dol_now(), '%Y%m%d%H%M%S');
1840 
1841  //var_dump($array_match_file_to_database);
1842 
1843  $db->begin();
1844 
1845  // Open input file
1846  $nbok = 0;
1847  $pathfile = $conf->import->dir_temp.'/'.$filetoimport;
1848  $result = $obj->import_open_file($pathfile, $langs);
1849  if ($result > 0) {
1850  global $tablewithentity_cache;
1851  $tablewithentity_cache = array();
1852  $sourcelinenb = 0; $endoffile = 0;
1853 
1854  // Loop on each input file record
1855  while (($sourcelinenb < $nboflines) && !$endoffile) {
1856  $sourcelinenb++;
1857  // Read line and store it into $arrayrecord
1858  //dol_syslog("line ".$sourcelinenb.' - '.$nboflines.' - '.$excludefirstline.' - '.$endatlinenb);
1859  $arrayrecord = $obj->import_read_record();
1860  if ($arrayrecord === false) {
1861  $arrayofwarnings[$sourcelinenb][0] = array('lib'=>'File has '.$nboflines.' lines. However we reach end of file after record '.$sourcelinenb.'. This may occurs when some records are split onto several lines. Ensure the complete string is delimited correctly when there is a separator character in the text string.', 'type'=>'EOF_RECORD_ON_SEVERAL_LINES');
1862  $endoffile++;
1863  continue;
1864  }
1865  if ($excludefirstline && ($sourcelinenb < $excludefirstline)) {
1866  continue;
1867  }
1868  if ($endatlinenb && ($sourcelinenb > $endatlinenb)) {
1869  break;
1870  }
1871 
1872  // Run import
1873  $result = $obj->import_insert($arrayrecord, $array_match_file_to_database, $objimport, count($fieldssource), $importid, $updatekeys);
1874 
1875  if (count($obj->errors)) {
1876  $arrayoferrors[$sourcelinenb] = $obj->errors;
1877  }
1878  if (count($obj->warnings)) {
1879  $arrayofwarnings[$sourcelinenb] = $obj->warnings;
1880  }
1881  if (!count($obj->errors) && !count($obj->warnings)) {
1882  $nbok++;
1883  }
1884  }
1885  // Close file
1886  $obj->import_close_file();
1887  } else {
1888  print $langs->trans("ErrorFailedToOpenFile", $pathfile);
1889  }
1890 
1891  $error = 0;
1892 
1893  // Run the sql after import if defined
1894  //var_dump($objimport->array_import_run_sql_after[0]);
1895  if (!empty($objimport->array_import_run_sql_after[0]) && is_array($objimport->array_import_run_sql_after[0])) {
1896  $i = 0;
1897  foreach ($objimport->array_import_run_sql_after[0] as $sqlafterimport) {
1898  $i++;
1899  $resqlafterimport = $db->query($sqlafterimport);
1900  if (!$resqlafterimport) {
1901  $arrayoferrors['none'][] = array('lib'=>$langs->trans("Error running final request: ".$sqlafterimport));
1902  $error++;
1903  }
1904  }
1905  }
1906 
1907  $db->rollback(); // We force rollback because this was just a simulation.
1908 
1909  // Show OK
1910  if (!count($arrayoferrors) && !count($arrayofwarnings)) {
1911  print '<br>';
1912  print '<div class="info">';
1913  print '<div class=""><b>'.$langs->trans("ResultOfSimulationNoError").'</b></div>';
1914  print $langs->trans("NbInsert", empty($obj->nbinsert) ? 0 : $obj->nbinsert).'<br>';
1915  print $langs->trans("NbUpdate", empty($obj->nbupdate) ? 0 : $obj->nbupdate).'<br>';
1916  print '</div>';
1917  print '<br>';
1918  } else {
1919  print '<br>';
1920  print '<div class="warning">';
1921  print $langs->trans("NbOfLinesOK", $nbok).'...<br>';
1922  print '</div>';
1923  print '<br>';
1924  }
1925 
1926  // Show Errors
1927  //var_dump($arrayoferrors);
1928  if (count($arrayoferrors)) {
1929  print img_error().' <b>'.$langs->trans("ErrorsOnXLines", count($arrayoferrors)).'</b><br>';
1930  print '<table width="100%" class="border"><tr><td>';
1931  foreach ($arrayoferrors as $key => $val) {
1932  $nboferrors++;
1933  if ($nboferrors > $maxnboferrors) {
1934  print $langs->trans("TooMuchErrors", (count($arrayoferrors) - $nboferrors))."<br>";
1935  break;
1936  }
1937  print '* '.$langs->trans("Line").' '.dol_escape_htmltag($key).'<br>';
1938  foreach ($val as $i => $err) {
1939  print ' &nbsp; &nbsp; > '.dol_escape_htmltag($err['lib']).'<br>';
1940  }
1941  }
1942  print '</td></tr></table>';
1943  print '<br>';
1944  }
1945 
1946  // Show Warnings
1947  //var_dump($arrayoferrors);
1948  if (count($arrayofwarnings)) {
1949  print img_warning().' <b>'.$langs->trans("WarningsOnXLines", count($arrayofwarnings)).'</b><br>';
1950  print '<table width="100%" class="border"><tr><td>';
1951  foreach ($arrayofwarnings as $key => $val) {
1952  $nbofwarnings++;
1953  if ($nbofwarnings > $maxnbofwarnings) {
1954  print $langs->trans("TooMuchWarnings", (count($arrayofwarnings) - $nbofwarnings))."<br>";
1955  break;
1956  }
1957  print ' * '.$langs->trans("Line").' '.dol_escape_htmltag($key).'<br>';
1958  foreach ($val as $i => $err) {
1959  print ' &nbsp; &nbsp; > '.dol_escape_htmltag($err['lib']).'<br>';
1960  }
1961  }
1962  print '</td></tr></table>';
1963  print '<br>';
1964  }
1965 
1966  // Show import id
1967  $importid = dol_print_date(dol_now(), '%Y%m%d%H%M%S');
1968 
1969  print '<div class="center">';
1970  print '<span class="opacitymedium">'.$langs->trans("NowClickToRunTheImport", $langs->transnoentitiesnoconv("RunImportFile")).'</span><br>';
1971  /*if (empty($nboferrors)) {
1972  print $langs->trans("DataLoadedWithId", $importid).'<br>';
1973  }*/
1974  print '</div>';
1975 
1976  print '<br>';
1977 
1978  // Actions
1979  print '<div class="center">';
1980  if ($user->rights->import->run) {
1981  if (empty($nboferrors)) {
1982  print '<a class="butAction" href="'.DOL_URL_ROOT.'/imports/import.php?leftmenu=import&step=6&importid='.$importid.$param.'">'.$langs->trans("RunImportFile").'</a>';
1983  } else {
1984  //print '<input type="submit" class="butAction" value="'.dol_escape_htmltag($langs->trans("RunSimulateImportFile")).'">';
1985 
1986  print '<a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->transnoentitiesnoconv("CorrectErrorBeforeRunningImport")).'">'.$langs->trans("RunImportFile").'</a>';
1987  }
1988  } else {
1989  print '<a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->transnoentitiesnoconv("NotEnoughPermissions")).'">'.$langs->trans("RunSimulateImportFile").'</a>';
1990 
1991  print '<a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->transnoentitiesnoconv("NotEnoughPermissions")).'">'.$langs->trans("RunImportFile").'</a>';
1992  }
1993  print '</div>';
1994  }
1995 
1996  print '</form>';
1997 }
1998 
1999 
2000 // STEP 6: Real import
2001 if ($step == 6 && $datatoimport) {
2002  $max_execution_time_for_importexport = (empty($conf->global->IMPORT_MAX_EXECUTION_TIME) ? 300 : $conf->global->IMPORT_MAX_EXECUTION_TIME); // 5mn if not defined
2003  $max_time = @ini_get("max_execution_time");
2004  if ($max_time && $max_time < $max_execution_time_for_importexport) {
2005  dol_syslog("max_execution_time=".$max_time." is lower than max_execution_time_for_importexport=".$max_execution_time_for_importexport.". We try to increase it dynamically.");
2006  @ini_set("max_execution_time", $max_execution_time_for_importexport); // This work only if safe mode is off. also web servers has timeout of 300
2007  }
2008 
2009  $model = $format;
2010  $list = $objmodelimport->liste_modeles($db);
2011  $importid = GETPOST("importid", 'alphanohtml');
2012 
2013 
2014  // Create classe to use for import
2015  $dir = DOL_DOCUMENT_ROOT."/core/modules/import/";
2016  $file = "import_".$model.".modules.php";
2017  $classname = "Import".ucfirst($model);
2018  require_once $dir.$file;
2019  $obj = new $classname($db, $datatoimport);
2020  if ($model == 'csv') {
2021  $obj->separator = $separator_used;
2022  $obj->enclosure = $enclosure;
2023  }
2024 
2025  // Load source fields in input file
2026  $fieldssource = array();
2027  $result = $obj->import_open_file($conf->import->dir_temp.'/'.$filetoimport, $langs);
2028  if ($result >= 0) {
2029  // Read first line
2030  $arrayrecord = $obj->import_read_record();
2031  // Put into array fieldssource starting with 1.
2032  $i = 1;
2033  foreach ($arrayrecord as $key => $val) {
2034  $fieldssource[$i]['example1'] = dol_trunc($val['val'], 24);
2035  $i++;
2036  }
2037  $obj->import_close_file();
2038  }
2039 
2040  $nboflines = (!empty($_GET["nboflines"]) ? $_GET["nboflines"] : dol_count_nb_of_line($conf->import->dir_temp.'/'.$filetoimport));
2041 
2042  $param = '&format='.$format.'&datatoimport='.urlencode($datatoimport).'&filetoimport='.urlencode($filetoimport).'&nboflines='.urlencode($nboflines);
2043  if ($excludefirstline) {
2044  $param .= '&excludefirstline='.urlencode($excludefirstline);
2045  }
2046  if ($endatlinenb) {
2047  $param .= '&endatlinenb='.urlencode($endatlinenb);
2048  }
2049  if ($separator) {
2050  $param .= '&separator='.urlencode($separator);
2051  }
2052  if ($enclosure) {
2053  $param .= '&enclosure='.urlencode($enclosure);
2054  }
2055 
2056  llxHeader('', $langs->trans("NewImport"), 'EN:Module_Imports_En|FR:Module_Imports|ES:M&oacute;dulo_Importaciones');
2057 
2058  $head = import_prepare_head($param, 6);
2059 
2060  print dol_get_fiche_head($head, 'step6', '', -1);
2061 
2062  print '<div class="underbanner clearboth"></div>';
2063  print '<div class="fichecenter">';
2064 
2065  print '<table width="100%" class="border">';
2066 
2067  // Module
2068  print '<tr><td class="titlefieldcreate">'.$langs->trans("Module").'</td>';
2069  print '<td>';
2070  $titleofmodule = $objimport->array_import_module[0]['module']->getName();
2071  // Special cas for import common to module/services
2072  if (in_array($objimport->array_import_code[0], array('produit_supplierprices', 'produit_multiprice', 'produit_languages'))) {
2073  $titleofmodule = $langs->trans("ProductOrService");
2074  }
2075  print $titleofmodule;
2076  print '</td></tr>';
2077 
2078  // Lot de donnees a importer
2079  print '<tr><td>'.$langs->trans("DatasetToImport").'</td>';
2080  print '<td>';
2081  $entity = preg_replace('/:.*$/', '', $objimport->array_import_icon[0]);
2082  $entityicon = strtolower(!empty($entitytoicon[$entity]) ? $entitytoicon[$entity] : $entity);
2083  print img_object($objimport->array_import_module[0]['module']->getName(), $entityicon).' ';
2084  print $objimport->array_import_label[0];
2085  print '</td></tr>';
2086 
2087  print '</table>';
2088  print '</div>';
2089 
2090  print load_fiche_titre($langs->trans("InformationOnSourceFile"), '', 'file-export');
2091 
2092  print '<div class="underbanner clearboth"></div>';
2093  print '<div class="fichecenter">';
2094  print '<table width="100%" class="border">';
2095 
2096  // Source file format
2097  print '<tr><td class="titlefieldcreate">'.$langs->trans("SourceFileFormat").'</td>';
2098  print '<td>';
2099  $text = $objmodelimport->getDriverDescForKey($format);
2100  print $form->textwithpicto($objmodelimport->getDriverLabelForKey($format), $text);
2101  print '</td></tr>';
2102 
2103  // Separator and enclosure
2104  if ($model == 'csv') {
2105  print '<tr><td>'.$langs->trans("CsvOptions").'</td>';
2106  print '<td>';
2107  print $langs->trans("Separator").' : ';
2108  print htmlentities($separator);
2109  print '&nbsp;&nbsp;&nbsp;&nbsp;'.$langs->trans("Enclosure").' : ';
2110  print htmlentities($enclosure);
2111  print '</td></tr>';
2112  }
2113 
2114  // File to import
2115  print '<tr><td>'.$langs->trans("FileToImport").'</td>';
2116  print '<td>';
2117  $modulepart = 'import';
2118  $relativepath = GETPOST('filetoimport');
2119  print '<a data-ajax="false" href="'.DOL_URL_ROOT.'/document.php?modulepart='.$modulepart.'&file='.urlencode($relativepath).'&step=4'.$param.'" target="_blank" rel="noopener noreferrer">';
2120  print img_mime($file, '', 'pictofixedwidth');
2121  print $filetoimport;
2122  print '</a>';
2123  print '</td></tr>';
2124 
2125  // Nb of fields
2126  print '<tr><td>';
2127  print $langs->trans("NbOfSourceLines");
2128  print '</td><td>';
2129  print $nboflines;
2130  print '</td></tr>';
2131 
2132  // Do not import first lines
2133  print '<tr><td>';
2134  print $langs->trans("ImportFromLine");
2135  print '</td><td>';
2136  print '<input type="text" size="4" name="excludefirstline" disabled="disabled" value="'.$excludefirstline.'">';
2137  print '</td></tr>';
2138 
2139  // Do not import end lines
2140  print '<tr><td>';
2141  print $langs->trans("EndAtLineNb");
2142  print '</td><td>';
2143  print '<input type="text" size="4" name="endatlinenb" disabled="disabled" value="'.$endatlinenb.'">';
2144  print '</td></tr>';
2145 
2146  print '</table>';
2147  print '</div>';
2148 
2149  print '<br>';
2150 
2151  print '<b>'.$langs->trans("InformationOnTargetTables").'</b>';
2152  print '<div class="underbanner clearboth"></div>';
2153  print '<div class="fichecenter">';
2154  print '<table class="border centpercent">';
2155 
2156  // Tables imported
2157  print '<tr><td width="25%">';
2158  print $langs->trans("TablesTarget");
2159  print '</td><td>';
2160  $listtables = array();
2161  foreach ($array_match_file_to_database as $code => $label) {
2162  //var_dump($fieldssource);
2163  if ($code > count($fieldssource)) {
2164  continue;
2165  }
2166  //print $code.'-'.$label;
2167  $alias = preg_replace('/(\..*)$/i', '', $label);
2168  $listtables[$alias] = $objimport->array_import_tables[0][$alias];
2169  }
2170  if (count($listtables)) {
2171  $newval = '';
2172  foreach ($listtables as $val) {
2173  if ($newval) {
2174  print ', ';
2175  }
2176  $newval = $val;
2177  // Link to Dolibarr wiki pages
2178  /*$helppagename='EN:Table_'.$newval;
2179  if ($helppagename && empty($conf->global->MAIN_HELP_DISABLELINK))
2180  {
2181  // Get helpbaseurl, helppage and mode from helppagename and langs
2182  $arrayres=getHelpParamFor($helppagename,$langs);
2183  $helpbaseurl=$arrayres['helpbaseurl'];
2184  $helppage=$arrayres['helppage'];
2185  $mode=$arrayres['mode'];
2186  $newval.=' <a href="'.sprintf($helpbaseurl,$helppage).'">'.img_picto($langs->trans($mode == 'wiki' ? 'GoToWikiHelpPage': 'GoToHelpPage'),DOL_URL_ROOT.'/theme/common/helpdoc.png','',1).'</a>';
2187  }*/
2188  print $newval;
2189  }
2190  } else {
2191  print $langs->trans("Error");
2192  }
2193  print '</td></tr>';
2194 
2195  // Fields imported
2196  print '<tr><td>';
2197  print $langs->trans("FieldsTarget").'</td><td>';
2198  $listfields = array();
2199  $i = 0;
2200  $sort_array_match_file_to_database = $array_match_file_to_database;
2201  ksort($sort_array_match_file_to_database);
2202  //var_dump($sort_array_match_file_to_database);
2203  foreach ($sort_array_match_file_to_database as $code => $label) {
2204  $i++;
2205  //var_dump($fieldssource);
2206  if ($code > count($fieldssource)) {
2207  continue;
2208  }
2209  //print $code.'-'.$label;
2210  $alias = preg_replace('/(\..*)$/i', '', $label);
2211  $listfields[$i] = $langs->trans("Field").' '.$code.'->'.$label;
2212  }
2213  print count($listfields) ? (join(', ', $listfields)) : $langs->trans("Error");
2214  print '</td></tr>';
2215 
2216  print '</table>';
2217  print '</div>';
2218 
2219  // Launch import
2220  $arrayoferrors = array();
2221  $arrayofwarnings = array();
2222  $maxnboferrors = empty($conf->global->IMPORT_MAX_NB_OF_ERRORS) ? 50 : $conf->global->IMPORT_MAX_NB_OF_ERRORS;
2223  $maxnbofwarnings = empty($conf->global->IMPORT_MAX_NB_OF_WARNINGS) ? 50 : $conf->global->IMPORT_MAX_NB_OF_WARNINGS;
2224  $nboferrors = 0;
2225  $nbofwarnings = 0;
2226 
2227  $importid = dol_print_date(dol_now(), '%Y%m%d%H%M%S');
2228 
2229  //var_dump($array_match_file_to_database);
2230 
2231  $db->begin();
2232 
2233  // Open input file
2234  $nbok = 0;
2235  $pathfile = $conf->import->dir_temp.'/'.$filetoimport;
2236  $result = $obj->import_open_file($pathfile, $langs);
2237  if ($result > 0) {
2238  global $tablewithentity_cache;
2239  $tablewithentity_cache = array();
2240  $sourcelinenb = 0; $endoffile = 0;
2241 
2242  while ($sourcelinenb < $nboflines && !$endoffile) {
2243  $sourcelinenb++;
2244  $arrayrecord = $obj->import_read_record();
2245  if ($arrayrecord === false) {
2246  $arrayofwarnings[$sourcelinenb][0] = array('lib'=>'File has '.$nboflines.' lines. However we reach end of file after record '.$sourcelinenb.'. This may occurs when some records are split onto several lines.', 'type'=>'EOF_RECORD_ON_SEVERAL_LINES');
2247  $endoffile++;
2248  continue;
2249  }
2250  if ($excludefirstline && ($sourcelinenb < $excludefirstline)) {
2251  continue;
2252  }
2253  if ($endatlinenb && ($sourcelinenb > $endatlinenb)) {
2254  break;
2255  }
2256 
2257  // Run import
2258  $result = $obj->import_insert($arrayrecord, $array_match_file_to_database, $objimport, count($fieldssource), $importid, $updatekeys);
2259 
2260  if (count($obj->errors)) {
2261  $arrayoferrors[$sourcelinenb] = $obj->errors;
2262  }
2263  if (count($obj->warnings)) {
2264  $arrayofwarnings[$sourcelinenb] = $obj->warnings;
2265  }
2266  if (!count($obj->errors) && !count($obj->warnings)) {
2267  $nbok++;
2268  }
2269  }
2270  // Close file
2271  $obj->import_close_file();
2272  } else {
2273  print $langs->trans("ErrorFailedToOpenFile", $pathfile);
2274  }
2275 
2276  if (count($arrayoferrors) > 0) {
2277  $db->rollback(); // We force rollback because this was errors.
2278  } else {
2279  $error = 0;
2280 
2281  // Run the sql after import if defined
2282  //var_dump($objimport->array_import_run_sql_after[0]);
2283  if (!empty($objimport->array_import_run_sql_after[0]) && is_array($objimport->array_import_run_sql_after[0])) {
2284  $i = 0;
2285  foreach ($objimport->array_import_run_sql_after[0] as $sqlafterimport) {
2286  $i++;
2287  $resqlafterimport = $db->query($sqlafterimport);
2288  if (!$resqlafterimport) {
2289  $arrayoferrors['none'][] = array('lib'=>$langs->trans("Error running final request: ".$sqlafterimport));
2290  $error++;
2291  }
2292  }
2293  }
2294 
2295  if (!$error) {
2296  $db->commit(); // We can commit if no errors.
2297  } else {
2298  $db->rollback();
2299  }
2300  }
2301 
2302  print dol_get_fiche_end();
2303 
2304 
2305  // Show result
2306  print '<br>';
2307  print '<div class="info">';
2308  print $langs->trans("NbOfLinesImported", $nbok).'</b><br>';
2309  print $langs->trans("NbInsert", empty($obj->nbinsert) ? 0 : $obj->nbinsert).'<br>';
2310  print $langs->trans("NbUpdate", empty($obj->nbupdate) ? 0 : $obj->nbupdate).'<br>';
2311  print '</div>';
2312  print '<div class="center">';
2313  print $langs->trans("FileWasImported", $importid).'<br>';
2314  print '<span class="opacitymedium">'.$langs->trans("YouCanUseImportIdToFindRecord", $importid).'</span><br>';
2315  print '</div>';
2316 }
2317 
2318 
2319 
2320 print '<br>';
2321 
2322 // End of page
2323 llxFooter();
2324 $db->close();
2325 
2326 
2337 function show_elem($fieldssource, $pos, $key, $var, $nostyle = '')
2338 {
2339  global $langs;
2340 
2341  $height = '32px';
2342 
2343  if ($key == 'none') {
2344  //stop multiple duplicate ids with no number
2345  print "\n\n<!-- Box_no-key start-->\n";
2346  print '<div class="box boximport" style="padding:0;">'."\n";
2347  print '<table summary="boxtable_no-key" class="centpercent nobordernopadding">'."\n";
2348  } else {
2349  print "\n\n<!-- Box ".$pos." start -->\n";
2350  print '<div class="box boximport" style="padding: 0;" id="boxto_'.$pos.'">'."\n";
2351 
2352  print '<table summary="boxtable'.$pos.'" class="nobordernopadding centpercent tableimport">'."\n";
2353  }
2354 
2355  if (($pos && $pos > count($fieldssource)) && (!isset($fieldssource[$pos]["imported"]))) { // No fields
2356  /*
2357  print '<tr style="height:'.$height.'" class="trimport oddevenimport">';
2358  print '<td class="nocellnopadding" width="16" style="font-weight: normal">';
2359  print '</td>';
2360  print '<td style="font-weight: normal">';
2361  print $langs->trans("NoFields");
2362  print '</td>';
2363  print '</tr>';
2364  */
2365  } elseif ($key == 'none') { // Empty line
2366  print '<tr style="height:'.$height.'" class="trimport oddevenimport">';
2367  print '<td class="nocellnopadding" width="16" style="font-weight: normal">';
2368  print '&nbsp;';
2369  print '</td>';
2370  print '<td style="font-weight: normal">';
2371  print '&nbsp;';
2372  print '</td>';
2373  print '</tr>';
2374  } else {
2375  // Print field of source file
2376  print '<tr style="height:'.$height.'" class="trimport oddevenimport">';
2377  print '<td class="nocellnopadding" width="16" style="font-weight: normal">';
2378  // The image must have the class 'boxhandle' beause it's value used in DOM draggable objects to define the area used to catch the full object
2379  //print img_picto($langs->trans("MoveField", $pos), 'grip_title', 'class="boxhandle" style="cursor:move;"');
2380  print img_picto($langs->trans("Column").' '.num2Alpha($pos - 1), 'file', 'class="pictofixedwith"');
2381  print '</td>';
2382  if (isset($fieldssource[$pos]['imported']) && $fieldssource[$pos]['imported'] == false) {
2383  print '<td class="nowraponall boxtdunused" style="font-weight: normal">';
2384  } else {
2385  print '<td class="nowraponall" style="font-weight: normal">';
2386  }
2387  print $langs->trans("Column").' '.num2Alpha($pos - 1).' (#'.$pos.')';
2388  if (empty($fieldssource[$pos]['example1'])) {
2389  $example = $fieldssource[$pos]['label'];
2390  } else {
2391  $example = $fieldssource[$pos]['example1'];
2392  }
2393  if ($example) {
2394  if (!utf8_check($example)) {
2395  $example = utf8_encode($example);
2396  }
2397  print ' - ';
2398  //print '<span class="opacitymedium hideonsmartphone">'.$langs->trans("ExampleOnFirstLine").': </span>';
2399  print '<i class="opacitymedium">'.$example.'</i>';
2400  }
2401  print '</td>';
2402  print '</tr>';
2403  }
2404 
2405  print "</table>\n";
2406 
2407  print "</div>\n";
2408  print "<!-- Box end -->\n\n";
2409 }
2410 
2411 
2419 function getnewkey(&$fieldssource, &$listofkey)
2420 {
2421  $i = count($fieldssource) + 1;
2422  // Max number of key
2423  $maxkey = 0;
2424  foreach ($listofkey as $key => $val) {
2425  $maxkey = max($maxkey, $key);
2426  }
2427  // Found next empty key
2428  while ($i <= $maxkey) {
2429  if (empty($listofkey[$i])) {
2430  break;
2431  } else {
2432  $i++;
2433  }
2434  }
2435 
2436  $listofkey[$i] = 1;
2437  return $i;
2438 }
2447 function arrayInsert($array, $position, $insertArray)
2448 {
2449  $ret = [];
2450 
2451  if ($position == count($array)) {
2452  $ret = $array + $insertArray;
2453  } else {
2454  $i = 0;
2455  foreach ($array as $key => $value) {
2456  if ($position == $i++) {
2457  $ret += $insertArray;
2458  }
2459 
2460  $ret[$key] = $value;
2461  }
2462  }
2463 
2464  return $ret;
2465 }
GETPOST($paramname, $check= 'alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
getMaxFileSizeArray()
Return the max allowed for file upload.
if($cancel &&!$id) if($action== 'add'&&!$cancel) if($action== 'delete') if($id) $form
Actions.
Definition: card.php:142
dol_mkdir($dir, $dataroot= '', $newmask= '')
Creation of a directory (this can create recursive subdir)
getnewkey(&$fieldssource, &$listofkey)
Return not used field number.
Definition: import.php:2419
Class to manage imports.
dol_escape_js($stringtoescape, $mode=0, $noescapebackslashn=0)
Returns text escaped for inclusion into javascript code.
dol_now($mode= 'auto')
Return date for now.
arrayInsert($array, $position, $insertArray)
Return array with element inserted in it at position $position.
Definition: import.php:2447
if(!defined('NOREQUIRESOC')) if(!defined('NOREQUIRETRAN')) if(!defined('NOCSRFCHECK')) if(!defined('NOTOKENRENEWAL')) if(!defined('NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined('NOREQUIREAJAX')) llxHeader()
Empty header.
Definition: wrapper.php:59
import_prepare_head($param, $maxstep=0)
Function to return list of tabs for import pages.
Definition: import.lib.php:36
dol_filesize($pathoffile)
Return size of a file.
Definition: files.lib.php:580
num2Alpha($n)
Return a numeric value into an Excel like column number.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags= '', $escapeonlyhtmltags=0)
Returns text escaped for inclusion in HTML alt or title tags, or into values of HTML input fields...
show_elem($fieldssource, $pos, $key, $var, $nostyle= '')
Function to put the movable box of a source field.
Definition: import.php:2337
if(GETPOST('button_removefilter_x', 'alpha')||GETPOST('button_removefilter.x', 'alpha')||GETPOST('button_removefilter', 'alpha')) if(GETPOST('button_search_x', 'alpha')||GETPOST('button_search.x', 'alpha')||GETPOST('button_search', 'alpha')) if($action=="save"&&empty($cancel)) $help_url
View.
Definition: agenda.php:116
img_mime($file, $titlealt= '', $morecss= '')
Show MIME img of a file.
img_warning($titlealt= 'default', $moreatt= '', $morecss= 'pictowarning')
Show warning logo.
setEventMessages($mesg, $mesgs, $style= 'mesgs', $messagekey= '')
Set event messages in dol_events session object.
img_error($titlealt= 'default')
Show error logo.
Class to manage generation of HTML components Only common components must be here.
GETPOSTISSET($paramname)
Return true if we are in a context of submitting the parameter $paramname from a POST of a form...
info_admin($text, $infoonimgalt=0, $nodiv=0, $admin= '1', $morecss= 'hideonsmartphone', $textfordropdown= '')
Show information for admin users or standard users.
load_fiche_titre($titre, $morehtmlright= '', $picto= 'generic', $pictoisfullpath=0, $id= '', $morecssontable= '', $morehtmlcenter= '')
Load a title with picto.
img_picto($titlealt, $picto, $moreatt= '', $pictoisfullpath=false, $srconly=0, $notitle=0, $alt= '', $morecss= '', $marginleftonlyshort=2)
Show picto whatever it&#39;s its name (generic function)
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename= '', $restricttologhandler= '', $logcontext=null)
Write log message into outputs.
Classe permettant la generation de composants html autre Only common components are here...
img_object($titlealt, $picto, $moreatt= '', $pictoisfullpath=false, $srconly=0, $notitle=0)
Show a picto called object_picto (generic function)
$conf db user
Definition: repair.php:123
dol_dir_list($path, $types="all", $recursive=0, $filter="", $excludefilter=null, $sortcriteria="name", $sortorder=SORT_ASC, $mode=0, $nohook=0, $relativename="", $donotfollowsymlinks=0)
Scan a directory and return a list of files/directories.
Definition: files.lib.php:60
dol_string_unaccent($str)
Clean a string from all accent characters to be used as ref, login or by dol_sanitizeFileName.
utf8_check($str)
Check if a string is in UTF8.
dol_count_nb_of_line($file)
Count number of lines in a file.
Definition: files.lib.php:549
Class to offer components to list and upload files.
dol_move_uploaded_file($src_file, $dest_file, $allowoverwrite, $disablevirusscan=0, $uploaderrorcode=0, $nohook=0, $varfiles= 'addedfile', $upload_dir= '')
Make control on an uploaded file from an GUI page and move it to final destination.
Definition: files.lib.php:1091
ajax_combobox($htmlname, $events=array(), $minLengthToAutocomplete=0, $forcefocus=0, $widthTypeOfAutocomplete= 'resolve', $idforemptyvalue= '-1')
Convert a html select field into an ajax combobox.
Definition: ajax.lib.php:429
restrictedArea($user, $features, $objectid=0, $tableandshare= '', $feature2= '', $dbt_keyfield= 'fk_soc', $dbt_select= 'rowid', $isdraft=0, $mode=0)
Check permissions of a user to show a page and an object.
if(isModEnabled('facture')&&!empty($user->rights->facture->lire)) if((isModEnabled('fournisseur')&&empty($conf->global->MAIN_USE_NEW_SUPPLIERMOD)&&$user->rights->fournisseur->facture->lire)||(isModEnabled('supplier_invoice')&&$user->rights->supplier_invoice->lire)) if(isModEnabled('don')&&!empty($user->rights->don->lire)) if(isModEnabled('tax')&&!empty($user->rights->tax->charges->lire)) if(isModEnabled('facture')&&isModEnabled('commande')&&$user->rights->commande->lire &&empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) $resql
Social contributions to pay.
Definition: index.php:742
dolExplodeIntoArray($string, $delimiter= ';', $kv= '=')
Split a string with 2 keys into key array.
Parent class for import file readers.
dol_sort_array(&$array, $index, $order= 'asc', $natsort=0, $case_sensitive=0, $keepindex=0)
Advanced sort array by second index function, which produces ascending (default) or descending output...
dol_get_fiche_head($links=array(), $active= '', $title= '', $notab=0, $picto= '', $pictoisfullpath=0, $morehtmlright= '', $morecss= '', $limittoshow=0, $moretabssuffix= '')
Show tabs of a record.
dol_print_date($time, $format= '', $tzoutput= 'auto', $outputlangs= '', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
dol_filemtime($pathoffile)
Return time of a file.
Definition: files.lib.php:592
dol_print_error($db= '', $error= '', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
newToken()
Return the value of token currently saved into session with name &#39;newtoken&#39;.
dol_get_fiche_end($notab=0)
Return tab footer of a card.
dol_trunc($string, $size=40, $trunc= 'right', $stringencoding= 'UTF-8', $nodot=0, $display=0)
Truncate a string to a particular length adding &#39;…&#39; if string larger than length. ...
llxFooter()
Empty footer.
Definition: wrapper.php:73
img_delete($titlealt= 'default', $other= 'class="pictodelete"', $morecss= '')
Show delete logo.
dol_delete_file($file, $disableglob=0, $nophperrors=0, $nohook=0, $object=null, $allowdotdot=false, $indexdatabase=1, $nolog=0)
Remove a file or several files with a mask.
Definition: files.lib.php:1230