dolibarr  16.0.5
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 the source fields from input file into variable $arrayrecord
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 
825  // Create array $fieldssource starting with 1 with values found of first line.
826  $i = 1;
827  foreach ($arrayrecord as $key => $val) {
828  if ($val["type"] != -1) {
829  $fieldssource[$i]['example1'] = dol_trunc($val['val'], 128);
830  $i++;
831  } else {
832  $fieldssource[$i]['example1'] = $langs->trans('Empty');
833  $i++;
834  }
835  }
836  $obj->import_close_file();
837  }
838 
839  // Load targets fields in database
840  $fieldstarget = $objimport->array_import_fields[0];
841  $minpos = min(count($fieldssource), count($fieldstarget));
842  //var_dump($array_match_file_to_database);
843 
844 
845  $initialloadofstep4 = false;
846  if (empty($_SESSION['dol_array_match_file_to_database_select'])) {
847  $initialloadofstep4 = true;
848  }
849 
850  // Is it a first time in page (if yes, we must initialize array_match_file_to_database)
851  if (count($array_match_file_to_database) == 0) {
852  // This is first input in screen, we need to define
853  // $array_match_file_to_database
854  // $serialized_array_match_file_to_database
855  // $_SESSION["dol_array_match_file_to_database"]
856  $pos = 1;
857  $num = count($fieldssource);
858  while ($pos <= $num) {
859  if ($num >= 1 && $pos <= $num) {
860  $posbis = 1;
861  foreach ($fieldstarget as $key => $val) {
862  if ($posbis < $pos) {
863  $posbis++;
864  continue;
865  }
866  // We found the key of targets that is at position pos
867  $array_match_file_to_database[$pos] = $key;
868  break;
869  }
870  }
871  $pos++;
872  }
873  }
874  $array_match_database_to_file = array_flip($array_match_file_to_database);
875  //var_dump($array_match_database_to_file);
876  //var_dump($_SESSION["dol_array_match_file_to_database_select"]);
877 
878  $fieldstarget_tmp = array();
879  $arraykeysfieldtarget = array_keys($fieldstarget);
880  $position = 0;
881  foreach ($fieldstarget as $key => $label) {
882  $isrequired = preg_match('/\*$/', $label);
883  if (!empty($isrequired)) {
884  $newlabel = substr($label, 0, -1);
885  $fieldstarget_tmp[$key] = array("label"=>$newlabel, "required"=>true);
886  } else {
887  $fieldstarget_tmp[$key] = array("label"=>$label, "required"=>false);
888  }
889  if (!empty($array_match_database_to_file[$key])) {
890  $fieldstarget_tmp[$key]["imported"] = true;
891  $fieldstarget_tmp[$key]["position"] = $array_match_database_to_file[$key]-1;
892  $keytoswap = $key;
893  while (!empty($array_match_database_to_file[$keytoswap])) {
894  if ($position+1 > $array_match_database_to_file[$keytoswap]) {
895  $keytoswapwith = $array_match_database_to_file[$keytoswap]-1;
896  $tmp = [$keytoswap=>$fieldstarget_tmp[$keytoswap]];
897  unset($fieldstarget_tmp[$keytoswap]);
898  $fieldstarget_tmp = arrayInsert($fieldstarget_tmp, $keytoswapwith, $tmp);
899  $keytoswapwith = $arraykeysfieldtarget[$array_match_database_to_file[$keytoswap]-1];
900  $tmp = $fieldstarget_tmp[$keytoswapwith];
901  unset($fieldstarget_tmp[$keytoswapwith]);
902  $fieldstarget_tmp[$keytoswapwith] = $tmp;
903  $keytoswap = $keytoswapwith;
904  } else {
905  break;
906  }
907  }
908  } else {
909  $fieldstarget_tmp[$key]["imported"] = false;
910  }
911  $position++;
912  }
913  $fieldstarget = $fieldstarget_tmp;
914 
915  //print $serialized_array_match_file_to_database;
916  //print $_SESSION["dol_array_match_file_to_database"];
917  //print $_SESSION["dol_array_match_file_to_database_select"];
918  //var_dump($array_match_file_to_database);exit;
919 
920  // Now $array_match_file_to_database contains fieldnb(1,2,3...)=>fielddatabase(key in $array_match_file_to_database)
921 
922  $param = '&format='.$format.'&datatoimport='.urlencode($datatoimport).'&filetoimport='.urlencode($filetoimport);
923  if ($excludefirstline) {
924  $param .= '&excludefirstline='.urlencode($excludefirstline);
925  }
926  if ($endatlinenb) {
927  $param .= '&endatlinenb='.urlencode($endatlinenb);
928  }
929  if ($separator) {
930  $param .= '&separator='.urlencode($separator);
931  }
932  if ($enclosure) {
933  $param .= '&enclosure='.urlencode($enclosure);
934  }
935 
936  llxHeader('', $langs->trans("NewImport"), $help_url);
937 
938  $head = import_prepare_head($param, 4);
939 
940  print dol_get_fiche_head($head, 'step4', '', -2);
941 
942  print '<div class="underbanner clearboth"></div>';
943  print '<div class="fichecenter">';
944 
945  print '<table class="centpercent border tableforfield">';
946 
947  // Module
948  print '<tr><td class="titlefieldcreate">'.$langs->trans("Module").'</td>';
949  print '<td>';
950  $titleofmodule = $objimport->array_import_module[0]['module']->getName();
951  // Special cas for import common to module/services
952  if (in_array($objimport->array_import_code[0], array('produit_supplierprices', 'produit_multiprice', 'produit_languages'))) {
953  $titleofmodule = $langs->trans("ProductOrService");
954  }
955  print $titleofmodule;
956  print '</td></tr>';
957 
958  // Lot de donnees a importer
959  print '<tr><td>'.$langs->trans("DatasetToImport").'</td>';
960  print '<td>';
961  $entity = preg_replace('/:.*$/', '', $objimport->array_import_icon[0]);
962  $entityicon = strtolower(!empty($entitytoicon[$entity]) ? $entitytoicon[$entity] : $entity);
963  print img_object($objimport->array_import_module[0]['module']->getName(), $entityicon).' ';
964  print $objimport->array_import_label[0];
965  print '</td></tr>';
966 
967  print '</table>';
968  print '</div>';
969 
970  print load_fiche_titre($langs->trans("InformationOnSourceFile"), '', 'file-export');
971 
972  print '<div class="underbanner clearboth"></div>';
973  print '<div class="fichecenter">';
974  print '<table width="100%" class="border tableforfield">';
975 
976  // Source file format
977  print '<tr><td class="titlefieldcreate">'.$langs->trans("SourceFileFormat").'</td>';
978  print '<td>';
979  $text = $objmodelimport->getDriverDescForKey($format);
980  print $form->textwithpicto($objmodelimport->getDriverLabelForKey($format), $text);
981  print '</td></tr>';
982 
983  // Separator and enclosure
984  if ($model == 'csv') {
985  print '<tr><td>'.$langs->trans("CsvOptions").'</td>';
986  print '<td>';
987  print '<form method="POST">';
988  print '<input type="hidden" name="token" value="'.newToken().'">';
989  print '<input type="hidden" value="'.$step.'" name="step">';
990  print '<input type="hidden" value="'.$format.'" name="format">';
991  print '<input type="hidden" value="'.$excludefirstline.'" name="excludefirstline">';
992  print '<input type="hidden" value="'.$endatlinenb.'" name="endatlinenb">';
993  print '<input type="hidden" value="'.$datatoimport.'" name="datatoimport">';
994  print '<input type="hidden" value="'.$filetoimport.'" name="filetoimport">';
995  print $langs->trans("Separator").' : ';
996  print '<input type="text" class="width25 center" name="separator" value="'.dol_escape_htmltag($separator).'"/>';
997  print '&nbsp;&nbsp;&nbsp;&nbsp;'.$langs->trans("Enclosure").' : ';
998  print '<input type="text" class="width25 center" name="enclosure" value="'.dol_escape_htmltag($enclosure).'"/> ';
999  print '<input name="update" type="submit" value="'.$langs->trans('Update').'" class="button smallpaddingimp" />';
1000  print '</form>';
1001  print '</td></tr>';
1002  }
1003 
1004  // File to import
1005  print '<tr><td>'.$langs->trans("FileToImport").'</td>';
1006  print '<td>';
1007  $modulepart = 'import';
1008  $relativepath = GETPOST('filetoimport');
1009  print '<a data-ajax="false" href="'.DOL_URL_ROOT.'/document.php?modulepart='.$modulepart.'&file='.urlencode($relativepath).'&step=4'.$param.'" target="_blank" rel="noopener noreferrer">';
1010  print img_mime($file, '', 'pictofixedwidth');
1011  print $filetoimport;
1012  print img_picto($langs->trans("Download"), 'download', 'class="paddingleft opacitymedium"');
1013  print '</a>';
1014  print '</td></tr>';
1015 
1016  print '</table>';
1017  print '</div>';
1018 
1019  print dol_get_fiche_end();
1020 
1021  print '<br>'."\n";
1022 
1023 
1024  // List of source fields
1025  print '<!-- List of source fields -->'."\n";
1026  print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
1027  print '<input type="hidden" name="token" value="'.newToken().'">';
1028  print '<input type="hidden" name="action" value="select_model">';
1029  print '<input type="hidden" name="step" value="4">';
1030  print '<input type="hidden" name="format" value="'.$format.'">';
1031  print '<input type="hidden" name="datatoimport" value="'.$datatoimport.'">';
1032  print '<input type="hidden" name="filetoimport" value="'.$filetoimport.'">';
1033  print '<input type="hidden" name="excludefirstline" value="'.$excludefirstline.'">';
1034  print '<input type="hidden" name="endatlinenb" value="'.$endatlinenb.'">';
1035  print '<input type="hidden" name="separator" value="'.dol_escape_htmltag($separator).'">';
1036  print '<input type="hidden" name="enclosure" value="'.dol_escape_htmltag($enclosure).'">';
1037 
1038  // Import profile to use/load
1039  print '<div class="marginbottomonly">';
1040  print '<span class="opacitymedium">';
1041  $s = $langs->trans("SelectImportFieldsSource", '{s1}');
1042  $s = str_replace('{s1}', img_picto('', 'grip_title', '', false, 0, 0, '', '', 0), $s);
1043  print $s;
1044  print '</span> ';
1045  $htmlother->select_import_model($importmodelid, 'importmodelid', $datatoimport, 1, $user->id);
1046  print '<input type="submit" class="button small reposition" value="'.$langs->trans("Select").'">';
1047  print '</div>';
1048  print '</form>';
1049 
1050  // Title of array with fields
1051  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
1052  print '<table class="noborder centpercent">';
1053  print '<tr class="liste_titre">';
1054  print '<td>'.$langs->trans("FieldsInSourceFile").'</td>';
1055  print '<td>'.$langs->trans("FieldsInTargetDatabase").'</td>';
1056  print '</tr>';
1057 
1058  //var_dump($array_match_file_to_database);
1059 
1060  print '<tr valign="top"><td width="50%" class="nopaddingleftimp">';
1061 
1062  $fieldsplaced = array();
1063  $valforsourcefieldnb = array();
1064  $listofkeys = array();
1065  foreach ($array_match_file_to_database as $key => $val) {
1066  $listofkeys[$key] = 1;
1067  }
1068 
1069  print "\n<!-- Box left container -->\n";
1070  print '<div id="left" class="connectedSortable">'."\n";
1071 
1072  // List of source fields
1073  $var = false;
1074  $lefti = 1;
1075  foreach ($fieldssource as $key => $val) {
1076  show_elem($fieldssource, $key, $val, $var); // key is field number in source file
1077  $listofkeys[$key] = 1;
1078  $fieldsplaced[$key] = 1;
1079  $valforsourcefieldnb[$lefti] = $key;
1080  $lefti++;
1081 
1082  /*if ($lefti > count($fieldstarget)) {
1083  break; // Other fields are in the not imported area
1084  }*/
1085  }
1086  //var_dump($valforsourcefieldnb);
1087 
1088  print "</div>\n";
1089  print "<!-- End box left container -->\n";
1090 
1091 
1092  print '</td><td width="50%" class="nopaddingrightimp">';
1093 
1094  // Set the list of all possible target fields in Dolibarr.
1095  $optionsall = array();
1096  foreach ($fieldstarget as $code => $line) {
1097  //var_dump($line);
1098 
1099  $tmparray = explode('|', $line["label"]); // If label of field is several translation keys separated with |
1100  $labeltoshow = '';
1101  foreach ($tmparray as $tmpkey => $tmpval) {
1102  $labeltoshow .= ($labeltoshow ? ' '.$langs->trans('or').' ' : '').$langs->transnoentities($tmpval);
1103  }
1104  $optionsall[$code] = array('labelkey'=>$line['label'], 'labelkeyarray'=>$tmparray, 'label'=>$labeltoshow, 'required'=>(empty($line["required"]) ? 0 : 1), 'position'=>!empty($line['position']) ? $line['position'] : 0);
1105  // TODO Get type from a new array into module descriptor.
1106  //$picto = 'email';
1107  $picto = '';
1108  if ($picto) {
1109  $optionsall[$code]['picto'] = $picto;
1110  }
1111  }
1112  // $optionsall is an array of all possible target fields. key=>array('label'=>..., 'xxx')
1113 
1114  $height = '32px'; //needs px for css height attribute below
1115  $i = 0;
1116  $mandatoryfieldshavesource = true;
1117 
1118  //var_dump($fieldstarget);
1119  //var_dump($optionsall);
1120  //exit;
1121 
1122  //var_dump($_SESSION['dol_array_match_file_to_database']);
1123  //var_dump($_SESSION['dol_array_match_file_to_database_select']);
1124  //exit;
1125  //var_dump($optionsall);
1126  //var_dump($fieldssource);
1127  //var_dump($fieldstarget);
1128 
1129  $modetoautofillmapping = 'session'; // Use setup in session
1130  if ($initialloadofstep4) {
1131  $modetoautofillmapping = 'guess';
1132  }
1133  //var_dump($modetoautofillmapping);
1134 
1135  print '<table class="nobordernopadding centpercent tableimport">';
1136  foreach ($fieldssource as $code => $line) { // $fieldssource is an array code=column num, line=content on first line for column in source file.
1137  /*if ($i == $minpos) {
1138  break;
1139  }*/
1140  print '<tr style="height:'.$height.'" class="trimport oddevenimport">';
1141  $entity = (!empty($objimport->array_import_entities[0][$code]) ? $objimport->array_import_entities[0][$code] : $objimport->array_import_icon[0]);
1142 
1143  $entityicon = !empty($entitytoicon[$entity]) ? $entitytoicon[$entity] : $entity; // $entityicon must string name of picto of the field like 'project', 'company', 'contact', 'modulename', ...
1144  $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', ...
1145 
1146  //print '<td class="nowraponall" style="font-weight: normal">=> '.img_object('', $entityicon).' '.$langs->trans($entitylang).'</td>';
1147  print '<td class="nowraponall" style="font-weight: normal">=> </td>';
1148  print '<td class="nowraponall" style="font-weight: normal">';
1149 
1150  //var_dump($_SESSION['dol_array_match_file_to_database_select']);
1151  //var_dump($_SESSION['dol_array_match_file_to_database']);
1152 
1153  $selectforline = '';
1154  $selectforline .= '<select id="selectorderimport_'.($i+1).'" class="targetselectchange minwidth300" name="select_'.($i+1).'">';
1155  if (!empty($line["imported"])) {
1156  $selectforline .= '<option value="-1">&nbsp;</option>';
1157  } else {
1158  $selectforline .= '<option selected="" value="-1">&nbsp;</option>';
1159  }
1160 
1161  $j = 0;
1162  $codeselectedarray = array();
1163  foreach ($optionsall as $tmpcode => $tmpval) { // Loop on each entry to add into each combo list.
1164  $label = '';
1165  if (!empty($tmpval['picto'])) {
1166  $label .= img_picto('', $tmpval['picto'], 'class="pictofixedwidth"');
1167  }
1168  $label .= $tmpval['required'] ? '<strong>' : '';
1169  $label .= $tmpval['label'];
1170  $label .= $tmpval['required'] ? '*</strong>' : '';
1171 
1172  $tablealias = preg_replace('/(\..*)$/i', '', $tmpcode);
1173  $tablename = !empty($objimport->array_import_tables[0][$tablealias]) ? $objimport->array_import_tables[0][$tablealias] : "";
1174 
1175  $htmltext = '';
1176 
1177  $filecolumn = ($i + 1);
1178  // Source field info
1179  if (empty($objimport->array_import_convertvalue[0][$tmpcode])) { // If source file does not need convertion
1180  $filecolumntoshow = num2Alpha($i);
1181  } else {
1182  if ($objimport->array_import_convertvalue[0][$tmpcode]['rule'] == 'fetchidfromref') {
1183  $htmltext .= $langs->trans("DataComeFromIdFoundFromRef", $langs->transnoentitiesnoconv($entitylang)).'<br>';
1184  }
1185  if ($objimport->array_import_convertvalue[0][$tmpcode]['rule'] == 'fetchidfromcodeid') {
1186  $htmltext .= $langs->trans("DataComeFromIdFoundFromCodeId", $langs->transnoentitiesnoconv($objimport->array_import_convertvalue[0][$tmpcode]['dict'])).'<br>';
1187  }
1188  }
1189  // Source required
1190  $example = !empty($objimport->array_import_examplevalues[0][$tmpcode])?$objimport->array_import_examplevalues[0][$tmpcode]:"";
1191  // Example
1192  if (empty($objimport->array_import_convertvalue[0][$tmpcode])) { // If source file does not need convertion
1193  if ($example) {
1194  $htmltext .= $langs->trans("SourceExample").': <b>'.str_replace('"', '', $example).'</b><br>';
1195  }
1196  } else {
1197  if ($objimport->array_import_convertvalue[0][$tmpcode]['rule'] == 'fetchidfromref') {
1198  $htmltext .= $langs->trans("SourceExample").': <b>'.$langs->transnoentitiesnoconv("ExampleAnyRefFoundIntoElement", $entitylang).($example ? ' ('.$langs->transnoentitiesnoconv("Example").': '.str_replace('"', '', $example).')' : '').'</b><br>';
1199  } elseif ($objimport->array_import_convertvalue[0][$tmpcode]['rule'] == 'fetchidfromcodeid') {
1200  $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>';
1201  } elseif ($example) {
1202  $htmltext .= $langs->trans("SourceExample").': <b>'.str_replace('"', '', $example).'</b><br>';
1203  }
1204  }
1205  // Format control rule
1206  if (!empty($objimport->array_import_regex[0][$tmpcode])) {
1207  $htmltext .= $langs->trans("FormatControlRule").': <b>'.str_replace('"', '', $objimport->array_import_regex[0][$tmpcode]).'</b><br>';
1208  }
1209 
1210  //var_dump($htmltext);
1211  $htmltext .= $langs->trans("InformationOnTargetTables").': &nbsp; <b>'.$tablename."->".preg_replace('/^.*\./', '', $tmpcode)."</b>";
1212 
1213  $labelhtml = $label.' '.$form->textwithpicto('', $htmltext, 1, 'help', '', 1);
1214 
1215  $selectforline .= '<option value="'.$tmpcode.'"';
1216  if ($modetoautofillmapping == 'orderoftargets') {
1217  // 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.
1218  if ($j == $i) {
1219  $selectforline .= ' selected';
1220  }
1221  } elseif ($modetoautofillmapping == 'guess') {
1222  // The mode where we try to guess which value to preselect from the name in first column of source file.
1223  // $line['example1'] is the label of the column found on first line
1224  $regs = array();
1225  if (preg_match('/^(.+)\((.+\..+)\)$/', $line['example1'], $regs)) { // If text is "Label (x.abc)"
1226  $tmpstring1 = $regs[1];
1227  $tmpstring2 = $regs[2];
1228  } else {
1229  $tmpstring1 = $line['example1'];
1230  $tmpstring2 = '';
1231  }
1232  $tmpstring1 = strtolower(str_replace('*', '', trim($tmpstring1)));
1233  $tmpstring2 = strtolower(str_replace('*', '', trim($tmpstring2)));
1234 
1235  // $tmpstring1 and $tmpstring2 are string from input file.
1236  foreach ($tmpval['labelkeyarray'] as $tmpval2) {
1237  $labeltarget = $langs->transnoentities($tmpval2);
1238  //var_dump($tmpstring1.' - '.$tmpstring2.' - '.$tmpval['labelkey'].' - '.$tmpval['label'].' - '.$tmpval2.' - '.$labeltarget);
1239  if ($tmpstring1 && ($tmpstring1 == $tmpcode || $tmpstring1 == strtolower($labeltarget)
1240  || $tmpstring1 == strtolower(dol_string_unaccent($labeltarget)) || $tmpstring1 == strtolower($tmpval2))) {
1241  if (empty($codeselectedarray[$code])) {
1242  $selectforline .= ' selected';
1243  $codeselectedarray[$code] = 1;
1244  break;
1245  }
1246  } elseif ($tmpstring2 && ($tmpstring2 == $tmpcode || $tmpstring2 == strtolower($labeltarget)
1247  || $tmpstring2 == strtolower(dol_string_unaccent($labeltarget)) || $tmpstring2 == strtolower($tmpval2))) {
1248  if (empty($codeselectedarray[$code])) {
1249  $selectforline .= ' selected';
1250  $codeselectedarray[$code] = 1;
1251  break;
1252  }
1253  }
1254  }
1255  } elseif ($modetoautofillmapping == 'session' && !empty($_SESSION['dol_array_match_file_to_database_select'])) {
1256  $tmpselectioninsession = dolExplodeIntoArray($_SESSION['dol_array_match_file_to_database_select'], ',', '=');
1257  //var_dump($code);
1258  if (!empty($tmpselectioninsession[($i+1)]) && $tmpselectioninsession[($i+1)] == $tmpcode) {
1259  $selectforline .= ' selected';
1260  }
1261  $selectforline .= ' data-debug="'.$tmpcode.'-'.$code.'-'.$j.'-'.(!empty($tmpselectioninsession[($i+1)]) ? $tmpselectioninsession[($i+1)] : "").'"';
1262  }
1263  $selectforline .= ' data-html="'.dol_escape_htmltag($labelhtml).'"';
1264  $selectforline .= '>';
1265  $selectforline .= $label;
1266  $selectforline .= '</options>';
1267  $j++;
1268  }
1269  $selectforline .= '</select>';
1270  $selectforline .= ajax_combobox('selectorderimport_'.($i+1));
1271 
1272  print $selectforline;
1273 
1274  print '</td>';
1275 
1276  // Tooltip at end of line
1277  print '<td class="nowraponall" style="font-weight:normal; text-align:right">';
1278 
1279  // Source field info
1280  $htmltext = '<b><u>'.$langs->trans("FieldSource").'</u></b><br>';
1281  $filecolumntoshow = num2Alpha($i);
1282  $htmltext .= $langs->trans("DataComeFromFileFieldNb", $filecolumntoshow).'<br>';
1283 
1284  print $form->textwithpicto('', $htmltext);
1285 
1286  print '</td>';
1287  print '</tr>';
1288  $i++;
1289  }
1290  print '</table>';
1291 
1292  print '</td></tr>';
1293 
1294  // Lines for remark
1295  print '<tr class="liste_titre"><td colspan="2">'.$langs->trans("Note").'</td></tr>';
1296  print '<tr><td colspan="2"><div id="div-mandatory-target-fields-not-mapped"></div></td></tr>';
1297 
1298  print '</table>';
1299  print '</div>';
1300 
1301 
1302  if (!empty($conf->use_javascript_ajax)) {
1303  print '<script type="text/javascript">'."\n";
1304  print 'var previousselectedvalueimport = "0";'."\n";
1305  print 'var previousselectedlabelimport = "0";'."\n";
1306  print 'var arrayofselectedvalues = [];'."\n";
1307  print 'var arrayoftargetfields = [];'."\n";
1308  print 'var arrayoftargetmandatoryfields = [];'."\n";
1309 
1310  // Loop on $fieldstarget (seems sorted by 'position') to store php array into javascript array
1311  $tmpi = 0;
1312  foreach ($fieldstarget as $key => $val) {
1313  print "arrayoftargetfields[".$tmpi."] = '".dol_escape_js($langs->trans($val['label']))."'; ";
1314  if ($val['required']) {
1315  print "arrayoftargetmandatoryfields[".$tmpi."] = '".dol_escape_js($key)."'; ";
1316  }
1317  $tmpi++;
1318  }
1319  print "\n";
1320 
1321  print '$(document).ready(function () {'."\n";
1322 
1323  print 'setOptionsToDisabled();'."\n";
1324  print 'saveSelection();'."\n";
1325 
1326  print '$(".targetselectchange").focus(function(){'."\n";
1327  print ' previousselectedvalueimport = $(this).val();'."\n";
1328  print ' previousselectedlabelimport = $(this).children("option:selected").text();'."\n";
1329  print ' console.log("previousselectedvalueimport="+previousselectedvalueimport)'."\n";
1330  print '})'."\n";
1331 
1332  // Function to set the disabled flag
1333  // - We set all option to "enabled"
1334  // - Then we scan all combo to get the value currently selected and save them into the array arrayofselectedvalues
1335  // - Then we set to disabled all fields that are selected
1336  print 'function setOptionsToDisabled() {'."\n";
1337  print ' console.log("Remove the disabled flag everywhere");'."\n";
1338  print ' $("select.targetselectchange").not($( this )).find(\'option\').prop("disabled", false);'."\n"; // Enable all options
1339  print ' arrayofselectedvalues = [];'."\n";
1340 
1341  print ' $("select.targetselectchange").each(function(){'."\n";
1342  print ' id = $(this).attr(\'id\')'."\n";
1343  print ' value = $(this).val()'."\n";
1344  print ' console.log("a selected value has been found for component "+id+" = "+value);'."\n";
1345  print ' arrayofselectedvalues.push(value);'."\n";
1346  print ' });'."\n";
1347 
1348  print ' console.log("List of all selected values arrayofselectedvalues");'."\n";
1349  print ' console.log(arrayofselectedvalues);'."\n";
1350  print ' console.log("Set the option to disabled for every entry that is currently selected somewhere else (so into arrayofselectedvalues)");'."\n";
1351 
1352  print ' $.each(arrayofselectedvalues, function(key, value) {'."\n"; // Loop on each selected value
1353  print ' if (value != -1) {'."\n";
1354  print ' console.log("Process key="+key+" value="+value+" to disable.");'."\n";
1355  print ' $("select.targetselectchange").find(\'option[value="\'+value+\'"]:not(:selected)\').prop("disabled", true);'."\n"; // Set to disabled except if currently selected
1356  print ' }'."\n";
1357  print ' });'."\n";
1358  print '};'."\n";
1359 
1360  // Function to save the selection in database
1361  print 'function saveSelection() {'."\n";
1362  //print ' console.log(arrayofselectedvalues);'."\n";
1363  print ' arrayselectedfields = [];'."\n";
1364  print ' arrayselectedfields.push(0);'."\n";
1365 
1366  print ' $.each( arrayofselectedvalues, function( key, value ) {'."\n";
1367  print ' if (value != -1) {'."\n";
1368  print ' arrayselectedfields.push(value);'."\n";
1369  print ' } else {'."\n";
1370  print ' arrayselectedfields.push(0);'."\n";
1371  print ' }'."\n";
1372  print ' });'."\n";
1373 
1374  print " $.ajax({\n";
1375  print " type: 'POST',\n";
1376  print " dataType: 'json',\n";
1377  print " url: '".dol_escape_js($_SERVER["PHP_SELF"])."?action=saveselectorder&token=".newToken()."',\n";
1378  print " data: 'selectorder='+arrayselectedfields.toString(),\n";
1379  print " success: function(){\n";
1380  print " console.log('The selected fields have been saved into '+arrayselectedfields.toString());\n";
1381  print " },\n";
1382  print ' });'."\n";
1383 
1384  // Now we loop on all target fields that are mandatory to show if they are not mapped yet.
1385  print ' console.log("arrayselectedfields");';
1386  print ' console.log(arrayselectedfields);';
1387  print ' console.log("arrayoftargetmandatoryfields");';
1388  print ' console.log(arrayoftargetmandatoryfields);';
1389  print " listtoshow = '';";
1390  print " nbelement = arrayoftargetmandatoryfields.length
1391  for (let i = 0; i < nbelement; i++) {
1392  if (arrayoftargetmandatoryfields[i] && ! arrayselectedfields.includes(arrayoftargetmandatoryfields[i])) {
1393  console.log(arrayoftargetmandatoryfields[i]+' not mapped');
1394  listtoshow = listtoshow + (listtoshow ? ', ' : '') + '<b>' + arrayoftargetfields[i] + '*</b>';
1395  }
1396  }
1397  console.log(listtoshow);
1398  if (listtoshow) {
1399  listtoshow = '".dol_escape_js(img_warning($langs->trans("MandatoryTargetFieldsNotMapped")).' '.$langs->trans("MandatoryTargetFieldsNotMapped")).": ' + listtoshow;
1400  $('#div-mandatory-target-fields-not-mapped').html(listtoshow);
1401  } else {
1402  $('#div-mandatory-target-fields-not-mapped').html('<span class=\"opacitymedium\">".dol_escape_js($langs->trans("AllTargetMandatoryFieldsAreMapped"))."</span>');
1403  }
1404  ";
1405 
1406  print '};'."\n";
1407 
1408  // If we make a change on a selectbox
1409  print '$(".targetselectchange").change(function(){'."\n";
1410  print ' setOptionsToDisabled();'."\n";
1411 
1412  print ' if(previousselectedlabelimport != "" && previousselectedvalueimport != -1) {'."\n";
1413  print ' let valuetochange = $(this).val(); '."\n";
1414  print ' $(".boxtdunused").each(function(){'."\n";
1415  print ' if ($(this).text().includes(valuetochange)){'."\n";
1416  print ' arraychild = $(this)[0].childNodes'."\n";
1417  print ' arraytexttomodify = arraychild[0].textContent.split(" ")'."\n";
1418  print ' arraytexttomodify[1] = previousselectedvalueimport '."\n";
1419  print ' textmodified = arraytexttomodify.join(" ") '."\n";
1420  print ' arraychild[0].textContent = textmodified'."\n";
1421  print ' arraychild[1].innerHTML = previousselectedlabelimport'."\n";
1422  print ' }'."\n";
1423  print ' })'."\n";
1424  print ' }'."\n";
1425  print ' $(this).blur()'."\n";
1426 
1427  print ' saveSelection()'."\n";
1428  print '});'."\n";
1429 
1430  print '})'."\n";
1431  print '</script>'."\n";
1432  }
1433 
1434  /*
1435  * Action bar
1436  */
1437  print '<div class="tabsAction">';
1438 
1439  if (count($array_match_file_to_database)) {
1440  if ($mandatoryfieldshavesource) {
1441  print '<a class="butAction saveorderselect" href="import.php?step=5'.$param.'&filetoimport='.urlencode($filetoimport).'">'.$langs->trans("NextStep").'</a>';
1442  } else {
1443  print '<a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->transnoentitiesnoconv("SomeMandatoryFieldHaveNoSource")).'">'.$langs->trans("NextStep").'</a>';
1444  }
1445  }
1446 
1447  print '</div>';
1448 
1449 
1450  // Area for profils import
1451  if (count($array_match_file_to_database)) {
1452  print '<br>'."\n";
1453  print '<!-- Area to add new import profile -->'."\n";
1454  print '<div class="marginbottomonly"><span class="opacitymedium">'.$langs->trans("SaveImportModel").'</span></div>';
1455 
1456  print '<form class="nocellnopadd" action="'.$_SERVER["PHP_SELF"].'" method="post">';
1457  print '<input type="hidden" name="token" value="'.newToken().'">';
1458  print '<input type="hidden" name="action" value="add_import_model">';
1459  print '<input type="hidden" name="step" value="'.$step.'">';
1460  print '<input type="hidden" name="format" value="'.$format.'">';
1461  print '<input type="hidden" name="datatoimport" value="'.$datatoimport.'">';
1462  print '<input type="hidden" name="filetoimport" value="'.$filetoimport.'">';
1463  print '<input type="hidden" name="hexa" value="'.$hexa.'">';
1464  print '<input type="hidden" name="excludefirstline" value="'.$excludefirstline.'">';
1465  print '<input type="hidden" name="endatlinenb" value="'.$endatlinenb.'">';
1466  print '<input type="hidden" name="page_y" value="">';
1467  print '<input type="hidden" value="'.dol_escape_htmltag($separator).'" name="separator">';
1468  print '<input type="hidden" value="'.dol_escape_htmltag($enclosure).'" name="enclosure">';
1469 
1470  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
1471  print '<table summary="selectofimportprofil" class="noborder centpercent">';
1472  print '<tr class="liste_titre">';
1473  print '<td>'.$langs->trans("ImportModelName").'</td>';
1474  print '<td>'.$langs->trans("Visibility").'</td>';
1475  print '<td></td>';
1476  print '</tr>';
1477 
1478  $nameofimportprofile = str_replace(' ', '-', $langs->trans("ImportProfile").' '.$titleofmodule.' '.dol_print_date(dol_now('gmt'), 'dayxcard'));
1479  if (GETPOST('import_name')) { // If we have submited a form, we take value used fot the update try
1480  $nameofimportprofile = $import_name;
1481  }
1482 
1483  print '<tr class="oddeven">';
1484  print '<td><input name="import_name" class="minwidth300" value="'.$nameofimportprofile.'"></td>';
1485  print '<td>';
1486  $arrayvisibility = array('private'=>$langs->trans("Private"), 'all'=>$langs->trans("Everybody"));
1487  print $form->selectarray('visibility', $arrayvisibility, 'private');
1488  print '</td>';
1489  print '<td class="right">';
1490  print '<input type="submit" class="button smallpaddingimp reposition" value="'.$langs->trans("SaveImportProfile").'">';
1491  print '</td></tr>';
1492 
1493  // List of existing import profils
1494  $sql = "SELECT rowid, label, fk_user, entity";
1495  $sql .= " FROM ".MAIN_DB_PREFIX."import_model";
1496  $sql .= " WHERE type = '".$db->escape($datatoimport)."'";
1497  if (empty($conf->global->EXPORTS_SHARE_MODELS)) { // EXPORTS_SHARE_MODELS means all templates are visible, whatever is owner.
1498  $sql .= " AND fk_user IN (0, ".((int) $user->id).")";
1499  }
1500  $sql .= " ORDER BY rowid";
1501 
1502  $resql = $db->query($sql);
1503  if ($resql) {
1504  $num = $db->num_rows($resql);
1505 
1506  $tmpuser = new user($db);
1507 
1508  $i = 0;
1509  while ($i < $num) {
1510  $obj = $db->fetch_object($resql);
1511 
1512  print '<tr class="oddeven"><td>';
1513  print $obj->label;
1514  print '</td>';
1515  print '<td>';
1516  if (empty($obj->fk_user)) {
1517  print $langs->trans("Everybody");
1518  } else {
1519  $tmpuser->fetch($obj->fk_user);
1520  print $tmpuser->getNomUrl(-1);
1521  }
1522  print '</td>';
1523  print '<td class="right">';
1524  print '<a class="reposition" href="'.$_SERVER["PHP_SELF"].'?step='.$step.$param.'&action=deleteprof&token='.newToken().'&id='.$obj->rowid.'&filetoimport='.urlencode($filetoimport).'">';
1525  print img_delete();
1526  print '</a>';
1527  print '</tr>';
1528  $i++;
1529  }
1530  } else {
1531  dol_print_error($db);
1532  }
1533 
1534  print '</table>';
1535  print '</div>';
1536 
1537  print '</form>';
1538  }
1539 }
1540 
1541 // STEP 5: Summary of choices and launch simulation
1542 if ($step == 5 && $datatoimport) {
1543  $max_execution_time_for_importexport = (empty($conf->global->IMPORT_MAX_EXECUTION_TIME) ? 300 : $conf->global->IMPORT_MAX_EXECUTION_TIME); // 5mn if not defined
1544  $max_time = @ini_get("max_execution_time");
1545  if ($max_time && $max_time < $max_execution_time_for_importexport) {
1546  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.");
1547  @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
1548  }
1549 
1550  $model = $format;
1551  $list = $objmodelimport->liste_modeles($db);
1552 
1553  // Create classe to use for import
1554  $dir = DOL_DOCUMENT_ROOT."/core/modules/import/";
1555  $file = "import_".$model.".modules.php";
1556  $classname = "Import".ucfirst($model);
1557  require_once $dir.$file;
1558  $obj = new $classname($db, $datatoimport);
1559  if ($model == 'csv') {
1560  $obj->separator = $separator_used;
1561  $obj->enclosure = $enclosure;
1562  }
1563 
1564  // Load source fields in input file
1565  $fieldssource = array();
1566  $result = $obj->import_open_file($conf->import->dir_temp.'/'.$filetoimport, $langs);
1567 
1568  if ($result >= 0) {
1569  // Read first line
1570  $arrayrecord = $obj->import_read_record();
1571  // Put into array fieldssource starting with 1.
1572  $i = 1;
1573  foreach ($arrayrecord as $key => $val) {
1574  $fieldssource[$i]['example1'] = dol_trunc($val['val'], 24);
1575  $i++;
1576  }
1577  $obj->import_close_file();
1578  }
1579 
1580  $nboflines = $obj->import_get_nb_of_lines($conf->import->dir_temp.'/'.$filetoimport);
1581 
1582  $param = '&leftmenu=import&format='.urlencode($format).'&datatoimport='.urlencode($datatoimport).'&filetoimport='.urlencode($filetoimport).'&nboflines='.urlencode($nboflines).'&separator='.urlencode($separator).'&enclosure='.urlencode($enclosure);
1583  $param2 = $param; // $param2 = $param without excludefirstline and endatlinenb
1584  if ($excludefirstline) {
1585  $param .= '&excludefirstline='.urlencode($excludefirstline);
1586  }
1587  if ($endatlinenb) {
1588  $param .= '&endatlinenb='.urlencode($endatlinenb);
1589  }
1590  if (!empty($updatekeys)) {
1591  $param .= '&updatekeys[]='.implode('&updatekeys[]=', $updatekeys);
1592  }
1593 
1594  llxHeader('', $langs->trans("NewImport"), 'EN:Module_Imports_En|FR:Module_Imports|ES:M&oacute;dulo_Importaciones');
1595 
1596  $head = import_prepare_head($param, 5);
1597 
1598 
1599  print '<form action="'.$_SERVER["PHP_SELF"].'?'.$param2.'" method="POST">';
1600  print '<input type="hidden" name="token" value="'.newToken().'">';
1601  print '<input type="hidden" name="step" value="5">'; // step 5
1602  print '<input type="hidden" name="action" value="launchsimu">'; // step 5
1603 
1604  print dol_get_fiche_head($head, 'step5', '', -2);
1605 
1606  print '<div class="underbanner clearboth"></div>';
1607  print '<div class="fichecenter">';
1608 
1609  print '<table width="100%" class="border tableforfield">';
1610 
1611  // Module
1612  print '<tr><td class="titlefieldcreate">'.$langs->trans("Module").'</td>';
1613  print '<td>';
1614  $titleofmodule = $objimport->array_import_module[0]['module']->getName();
1615  // Special cas for import common to module/services
1616  if (in_array($objimport->array_import_code[0], array('produit_supplierprices', 'produit_multiprice', 'produit_languages'))) {
1617  $titleofmodule = $langs->trans("ProductOrService");
1618  }
1619  print $titleofmodule;
1620  print '</td></tr>';
1621 
1622  // Lot de donnees a importer
1623  print '<tr><td>'.$langs->trans("DatasetToImport").'</td>';
1624  print '<td>';
1625  $entity = preg_replace('/:.*$/', '', $objimport->array_import_icon[0]);
1626  $entityicon = strtolower(!empty($entitytoicon[$entity]) ? $entitytoicon[$entity] : $entity);
1627  print img_object($objimport->array_import_module[0]['module']->getName(), $entityicon).' ';
1628  print $objimport->array_import_label[0];
1629  print '</td></tr>';
1630 
1631  print '</table>';
1632  print '</div>';
1633 
1634  print load_fiche_titre($langs->trans("InformationOnSourceFile"), '', 'file-export');
1635 
1636  print '<div class="underbanner clearboth"></div>';
1637  print '<div class="fichecenter">';
1638  print '<table width="100%" class="border tableforfield">';
1639 
1640  // Source file format
1641  print '<tr><td class="titlefieldcreate">'.$langs->trans("SourceFileFormat").'</td>';
1642  print '<td>';
1643  $text = $objmodelimport->getDriverDescForKey($format);
1644  print $form->textwithpicto($objmodelimport->getDriverLabelForKey($format), $text);
1645  print '</td></tr>';
1646 
1647  // Separator and enclosure
1648  if ($model == 'csv') {
1649  print '<tr><td>'.$langs->trans("CsvOptions").'</td>';
1650  print '<td>';
1651  print $langs->trans("Separator").' : '.dol_escape_htmltag($separator);
1652  print '&nbsp;&nbsp;&nbsp;&nbsp;'.$langs->trans("Enclosure").' : '.dol_escape_htmltag($enclosure);
1653  print '</td></tr>';
1654  }
1655 
1656  // File to import
1657  print '<tr><td>'.$langs->trans("FileToImport").'</td>';
1658  print '<td>';
1659  $modulepart = 'import';
1660  $relativepath = GETPOST('filetoimport');
1661  print '<a data-ajax="false" href="'.DOL_URL_ROOT.'/document.php?modulepart='.$modulepart.'&file='.urlencode($relativepath).'&step=4'.$param.'" target="_blank" rel="noopener noreferrer">';
1662  print img_mime($file, '', 'pictofixedwidth');
1663  print $filetoimport;
1664  print img_picto($langs->trans("Download"), 'download', 'class="paddingleft opacitymedium"');
1665  print '</a>';
1666  print '</td></tr>';
1667 
1668  // Total lines in source file
1669  print '<tr><td>';
1670  print $langs->trans("NbOfSourceLines");
1671  print '</td><td>';
1672  print $nboflines;
1673  print '</td></tr>';
1674 
1675  // Range of lines to import
1676  print '<tr><td>';
1677  print $langs->trans("ImportFromToLine");
1678  print '</td><td>';
1679  if ($action == 'launchsimu') {
1680  print '<input type="number" class="maxwidth50 right" name="excludefirstlinebis" disabled="disabled" value="'.$excludefirstline.'">';
1681  print '<input type="hidden" name="excludefirstline" value="'.$excludefirstline.'">';
1682  } else {
1683  print '<input type="number" class="maxwidth50 right" name="excludefirstline" value="'.$excludefirstline.'">';
1684  print $form->textwithpicto("", $langs->trans("SetThisValueTo2ToExcludeFirstLine"));
1685  }
1686  print ' - ';
1687  if ($action == 'launchsimu') {
1688  print '<input type="text" class="maxwidth50" name="endatlinenbbis" disabled="disabled" value="'.$endatlinenb.'">';
1689  print '<input type="hidden" name="endatlinenb" value="'.$endatlinenb.'">';
1690  } else {
1691  print '<input type="text" class="maxwidth50" name="endatlinenb" value="'.$endatlinenb.'">';
1692  print $form->textwithpicto("", $langs->trans("KeepEmptyToGoToEndOfFile"));
1693  }
1694  if ($action == 'launchsimu') {
1695  print ' &nbsp; <a href="'.$_SERVER["PHP_SELF"].'?step=5'.$param.'">'.$langs->trans("Modify").'</a>';
1696  }
1697  if ($excludefirstline == 2) {
1698  print $form->textwithpicto("", $langs->trans("WarningFirstImportedLine", $excludefirstline), 1, 'warning', "warningexcludefirstline");
1699  print '<script>
1700  $( document ).ready(function() {
1701  $("input[name=\'excludefirstline\']").on("change",function(){
1702  if($(this).val() <= 1){
1703  $(".warningexcludefirstline").hide();
1704  }else{
1705  $(".warningexcludefirstline").show();
1706  }
1707  })
1708  });
1709  </script>';
1710  }
1711  print '</td></tr>';
1712 
1713  // Keys for data UPDATE (not INSERT of new data)
1714  print '<tr><td>';
1715  print $form->textwithpicto($langs->trans("KeysToUseForUpdates"), $langs->trans("SelectPrimaryColumnsForUpdateAttempt"));
1716  print '</td><td>';
1717  if ($action == 'launchsimu') {
1718  if (count($updatekeys)) {
1719  print $form->multiselectarray('updatekeysbis', $objimport->array_import_updatekeys[0], $updatekeys, 0, 0, '', 1, '80%', 'disabled');
1720  } else {
1721  print '<span class="opacitymedium">'.$langs->trans("NoUpdateAttempt").'</span> &nbsp; -';
1722  }
1723  foreach ($updatekeys as $val) {
1724  print '<input type="hidden" name="updatekeys[]" value="'.$val.'">';
1725  }
1726  print ' &nbsp; <a href="'.$_SERVER["PHP_SELF"].'?step=5'.$param.'">'.$langs->trans("Modify").'</a>';
1727  } else {
1728  if (is_array($objimport->array_import_updatekeys[0]) && count($objimport->array_import_updatekeys[0])) { //TODO dropdown UL is created inside nested SPANS
1729  print $form->multiselectarray('updatekeys', $objimport->array_import_updatekeys[0], $updatekeys, 0, 0, '', 1, '80%');
1730  //print $form->textwithpicto("", $langs->trans("SelectPrimaryColumnsForUpdateAttempt"));
1731  } else {
1732  print '<span class="opacitymedium">'.$langs->trans("UpdateNotYetSupportedForThisImport").'</span>';
1733  }
1734  }
1735  /*echo '<pre>';
1736  print_r($objimport->array_import_updatekeys);
1737  echo '</pre>';*/
1738  print '</td></tr>';
1739 
1740  print '</table>';
1741  print '</div>';
1742 
1743 
1744  print load_fiche_titre($langs->trans("InformationOnTargetTables"), '', 'file-import');
1745 
1746  print '<div class="underbanner clearboth"></div>';
1747  print '<div class="fichecenter">';
1748 
1749  print '<table width="100%" class="border tableforfield">';
1750 
1751  // Tables imported
1752  print '<tr><td class="titlefieldcreate">';
1753  print $langs->trans("TablesTarget");
1754  print '</td><td>';
1755  $listtables = array();
1756  $sort_array_match_file_to_database = $array_match_file_to_database;
1757  foreach ($array_match_file_to_database as $code => $label) {
1758  //var_dump($fieldssource);
1759  if ($code > count($fieldssource)) {
1760  continue;
1761  }
1762  //print $code.'-'.$label;
1763  $alias = preg_replace('/(\..*)$/i', '', $label);
1764  $listtables[$alias] = $objimport->array_import_tables[0][$alias];
1765  }
1766  if (count($listtables)) {
1767  $newval = '';
1768  //ksort($listtables);
1769  foreach ($listtables as $val) {
1770  if ($newval) {
1771  print ', ';
1772  }
1773  $newval = $val;
1774  // Link to Dolibarr wiki pages
1775  /*$helppagename='EN:Table_'.$newval;
1776  if ($helppagename && empty($conf->global->MAIN_HELP_DISABLELINK))
1777  {
1778  // Get helpbaseurl, helppage and mode from helppagename and langs
1779  $arrayres=getHelpParamFor($helppagename,$langs);
1780  $helpbaseurl=$arrayres['helpbaseurl'];
1781  $helppage=$arrayres['helppage'];
1782  $mode=$arrayres['mode'];
1783  $newval.=' <a href="'.sprintf($helpbaseurl,$helppage).'">'.img_picto($langs->trans($mode == 'wiki' ? 'GoToWikiHelpPage': 'GoToHelpPage'),DOL_URL_ROOT.'/theme/common/helpdoc.png','',1).'</a>';
1784  }*/
1785  print $newval;
1786  }
1787  } else {
1788  print $langs->trans("Error");
1789  }
1790  print '</td></tr>';
1791 
1792  // Fields imported
1793  print '<tr><td>';
1794  print $langs->trans("FieldsTarget").'</td><td>';
1795  $listfields = array();
1796  $i = 0;
1797  //print 'fieldsource='.$fieldssource;
1798  $sort_array_match_file_to_database = $array_match_file_to_database;
1799  ksort($sort_array_match_file_to_database);
1800  //var_dump($sort_array_match_file_to_database);
1801  foreach ($sort_array_match_file_to_database as $code => $label) {
1802  $i++;
1803  //var_dump($fieldssource);
1804  if ($code > count($fieldssource)) {
1805  continue;
1806  }
1807  //print $code.'-'.$label;
1808  $alias = preg_replace('/(\..*)$/i', '', $label);
1809  $listfields[$i] = '<span class="nowrap">'.$langs->trans("Column").' '.num2Alpha($code - 1).' -> '.$label.'</span>';
1810  }
1811  print count($listfields) ? (join(', ', $listfields)) : $langs->trans("Error");
1812  print '</td></tr>';
1813 
1814  print '</table>';
1815  print '</div>';
1816 
1817  print dol_get_fiche_end();
1818 
1819 
1820  if ($action != 'launchsimu') {
1821  // Show import id
1822  print '<br><span class="opacitymedium">';
1823  print $langs->trans("NowClickToTestTheImport", $langs->transnoentitiesnoconv("RunSimulateImportFile")).'</span><br>';
1824  print '<br>';
1825 
1826  // Actions
1827  print '<div class="center">';
1828  if ($user->rights->import->run) {
1829  print '<input type="submit" class="butAction" value="'.$langs->trans("RunSimulateImportFile").'">';
1830  } else {
1831  print '<a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->transnoentitiesnoconv("NotEnoughPermissions")).'">'.$langs->trans("RunSimulateImportFile").'</a>';
1832  }
1833  print '</div>';
1834  } else {
1835  // Launch import
1836  $arrayoferrors = array();
1837  $arrayofwarnings = array();
1838  $maxnboferrors = empty($conf->global->IMPORT_MAX_NB_OF_ERRORS) ? 50 : $conf->global->IMPORT_MAX_NB_OF_ERRORS;
1839  $maxnbofwarnings = empty($conf->global->IMPORT_MAX_NB_OF_WARNINGS) ? 50 : $conf->global->IMPORT_MAX_NB_OF_WARNINGS;
1840  $nboferrors = 0;
1841  $nbofwarnings = 0;
1842 
1843  $importid = dol_print_date(dol_now(), '%Y%m%d%H%M%S');
1844 
1845  //var_dump($array_match_file_to_database);
1846 
1847  $db->begin();
1848 
1849  // Open input file
1850  $nbok = 0;
1851  $pathfile = $conf->import->dir_temp.'/'.$filetoimport;
1852  $result = $obj->import_open_file($pathfile, $langs);
1853  if ($result > 0) {
1854  global $tablewithentity_cache;
1855  $tablewithentity_cache = array();
1856  $sourcelinenb = 0; $endoffile = 0;
1857 
1858  // Loop on each input file record
1859  while (($sourcelinenb < $nboflines) && !$endoffile) {
1860  $sourcelinenb++;
1861  // Read line and store it into $arrayrecord
1862  //dol_syslog("line ".$sourcelinenb.' - '.$nboflines.' - '.$excludefirstline.' - '.$endatlinenb);
1863  $arrayrecord = $obj->import_read_record();
1864  if ($arrayrecord === false) {
1865  $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');
1866  $endoffile++;
1867  continue;
1868  }
1869  if ($excludefirstline && ($sourcelinenb < $excludefirstline)) {
1870  continue;
1871  }
1872  if ($endatlinenb && ($sourcelinenb > $endatlinenb)) {
1873  break;
1874  }
1875 
1876  // Run import
1877  $result = $obj->import_insert($arrayrecord, $array_match_file_to_database, $objimport, count($fieldssource), $importid, $updatekeys);
1878 
1879  if (count($obj->errors)) {
1880  $arrayoferrors[$sourcelinenb] = $obj->errors;
1881  }
1882  if (count($obj->warnings)) {
1883  $arrayofwarnings[$sourcelinenb] = $obj->warnings;
1884  }
1885  if (!count($obj->errors) && !count($obj->warnings)) {
1886  $nbok++;
1887  }
1888  }
1889  // Close file
1890  $obj->import_close_file();
1891  } else {
1892  print $langs->trans("ErrorFailedToOpenFile", $pathfile);
1893  }
1894 
1895  $error = 0;
1896 
1897  // Run the sql after import if defined
1898  //var_dump($objimport->array_import_run_sql_after[0]);
1899  if (!empty($objimport->array_import_run_sql_after[0]) && is_array($objimport->array_import_run_sql_after[0])) {
1900  $i = 0;
1901  foreach ($objimport->array_import_run_sql_after[0] as $sqlafterimport) {
1902  $i++;
1903  $resqlafterimport = $db->query($sqlafterimport);
1904  if (!$resqlafterimport) {
1905  $arrayoferrors['none'][] = array('lib'=>$langs->trans("Error running final request: ".$sqlafterimport));
1906  $error++;
1907  }
1908  }
1909  }
1910 
1911  $db->rollback(); // We force rollback because this was just a simulation.
1912 
1913  // Show OK
1914  if (!count($arrayoferrors) && !count($arrayofwarnings)) {
1915  print '<br>';
1916  print '<div class="info">';
1917  print '<div class=""><b>'.$langs->trans("ResultOfSimulationNoError").'</b></div>';
1918  print $langs->trans("NbInsert", empty($obj->nbinsert) ? 0 : $obj->nbinsert).'<br>';
1919  print $langs->trans("NbUpdate", empty($obj->nbupdate) ? 0 : $obj->nbupdate).'<br>';
1920  print '</div>';
1921  print '<br>';
1922  } else {
1923  print '<br>';
1924  print '<div class="warning">';
1925  print $langs->trans("NbOfLinesOK", $nbok).'...<br>';
1926  print '</div>';
1927  print '<br>';
1928  }
1929 
1930  // Show Errors
1931  //var_dump($arrayoferrors);
1932  if (count($arrayoferrors)) {
1933  print img_error().' <b>'.$langs->trans("ErrorsOnXLines", count($arrayoferrors)).'</b><br>';
1934  print '<table width="100%" class="border"><tr><td>';
1935  foreach ($arrayoferrors as $key => $val) {
1936  $nboferrors++;
1937  if ($nboferrors > $maxnboferrors) {
1938  print $langs->trans("TooMuchErrors", (count($arrayoferrors) - $nboferrors))."<br>";
1939  break;
1940  }
1941  print '* '.$langs->trans("Line").' '.dol_escape_htmltag($key).'<br>';
1942  foreach ($val as $i => $err) {
1943  print ' &nbsp; &nbsp; > '.dol_escape_htmltag($err['lib']).'<br>';
1944  }
1945  }
1946  print '</td></tr></table>';
1947  print '<br>';
1948  }
1949 
1950  // Show Warnings
1951  //var_dump($arrayoferrors);
1952  if (count($arrayofwarnings)) {
1953  print img_warning().' <b>'.$langs->trans("WarningsOnXLines", count($arrayofwarnings)).'</b><br>';
1954  print '<table width="100%" class="border"><tr><td>';
1955  foreach ($arrayofwarnings as $key => $val) {
1956  $nbofwarnings++;
1957  if ($nbofwarnings > $maxnbofwarnings) {
1958  print $langs->trans("TooMuchWarnings", (count($arrayofwarnings) - $nbofwarnings))."<br>";
1959  break;
1960  }
1961  print ' * '.$langs->trans("Line").' '.dol_escape_htmltag($key).'<br>';
1962  foreach ($val as $i => $err) {
1963  print ' &nbsp; &nbsp; > '.dol_escape_htmltag($err['lib']).'<br>';
1964  }
1965  }
1966  print '</td></tr></table>';
1967  print '<br>';
1968  }
1969 
1970  // Show import id
1971  $importid = dol_print_date(dol_now(), '%Y%m%d%H%M%S');
1972 
1973  print '<div class="center">';
1974  print '<span class="opacitymedium">'.$langs->trans("NowClickToRunTheImport", $langs->transnoentitiesnoconv("RunImportFile")).'</span><br>';
1975  /*if (empty($nboferrors)) {
1976  print $langs->trans("DataLoadedWithId", $importid).'<br>';
1977  }*/
1978  print '</div>';
1979 
1980  print '<br>';
1981 
1982  // Actions
1983  print '<div class="center">';
1984  if ($user->rights->import->run) {
1985  if (empty($nboferrors)) {
1986  print '<a class="butAction" href="'.DOL_URL_ROOT.'/imports/import.php?leftmenu=import&step=6&importid='.$importid.$param.'">'.$langs->trans("RunImportFile").'</a>';
1987  } else {
1988  //print '<input type="submit" class="butAction" value="'.dol_escape_htmltag($langs->trans("RunSimulateImportFile")).'">';
1989 
1990  print '<a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->transnoentitiesnoconv("CorrectErrorBeforeRunningImport")).'">'.$langs->trans("RunImportFile").'</a>';
1991  }
1992  } else {
1993  print '<a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->transnoentitiesnoconv("NotEnoughPermissions")).'">'.$langs->trans("RunSimulateImportFile").'</a>';
1994 
1995  print '<a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->transnoentitiesnoconv("NotEnoughPermissions")).'">'.$langs->trans("RunImportFile").'</a>';
1996  }
1997  print '</div>';
1998  }
1999 
2000  print '</form>';
2001 }
2002 
2003 
2004 // STEP 6: Real import
2005 if ($step == 6 && $datatoimport) {
2006  $max_execution_time_for_importexport = (empty($conf->global->IMPORT_MAX_EXECUTION_TIME) ? 300 : $conf->global->IMPORT_MAX_EXECUTION_TIME); // 5mn if not defined
2007  $max_time = @ini_get("max_execution_time");
2008  if ($max_time && $max_time < $max_execution_time_for_importexport) {
2009  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.");
2010  @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
2011  }
2012 
2013  $model = $format;
2014  $list = $objmodelimport->liste_modeles($db);
2015  $importid = GETPOST("importid", 'alphanohtml');
2016 
2017 
2018  // Create classe to use for import
2019  $dir = DOL_DOCUMENT_ROOT."/core/modules/import/";
2020  $file = "import_".$model.".modules.php";
2021  $classname = "Import".ucfirst($model);
2022  require_once $dir.$file;
2023  $obj = new $classname($db, $datatoimport);
2024  if ($model == 'csv') {
2025  $obj->separator = $separator_used;
2026  $obj->enclosure = $enclosure;
2027  }
2028 
2029  // Load source fields in input file
2030  $fieldssource = array();
2031  $result = $obj->import_open_file($conf->import->dir_temp.'/'.$filetoimport, $langs);
2032  if ($result >= 0) {
2033  // Read first line
2034  $arrayrecord = $obj->import_read_record();
2035  // Put into array fieldssource starting with 1.
2036  $i = 1;
2037  foreach ($arrayrecord as $key => $val) {
2038  $fieldssource[$i]['example1'] = dol_trunc($val['val'], 24);
2039  $i++;
2040  }
2041  $obj->import_close_file();
2042  }
2043 
2044  $nboflines = (!empty($_GET["nboflines"]) ? $_GET["nboflines"] : dol_count_nb_of_line($conf->import->dir_temp.'/'.$filetoimport));
2045 
2046  $param = '&format='.$format.'&datatoimport='.urlencode($datatoimport).'&filetoimport='.urlencode($filetoimport).'&nboflines='.urlencode($nboflines);
2047  if ($excludefirstline) {
2048  $param .= '&excludefirstline='.urlencode($excludefirstline);
2049  }
2050  if ($endatlinenb) {
2051  $param .= '&endatlinenb='.urlencode($endatlinenb);
2052  }
2053  if ($separator) {
2054  $param .= '&separator='.urlencode($separator);
2055  }
2056  if ($enclosure) {
2057  $param .= '&enclosure='.urlencode($enclosure);
2058  }
2059 
2060  llxHeader('', $langs->trans("NewImport"), 'EN:Module_Imports_En|FR:Module_Imports|ES:M&oacute;dulo_Importaciones');
2061 
2062  $head = import_prepare_head($param, 6);
2063 
2064  print dol_get_fiche_head($head, 'step6', '', -1);
2065 
2066  print '<div class="underbanner clearboth"></div>';
2067  print '<div class="fichecenter">';
2068 
2069  print '<table width="100%" class="border">';
2070 
2071  // Module
2072  print '<tr><td class="titlefieldcreate">'.$langs->trans("Module").'</td>';
2073  print '<td>';
2074  $titleofmodule = $objimport->array_import_module[0]['module']->getName();
2075  // Special cas for import common to module/services
2076  if (in_array($objimport->array_import_code[0], array('produit_supplierprices', 'produit_multiprice', 'produit_languages'))) {
2077  $titleofmodule = $langs->trans("ProductOrService");
2078  }
2079  print $titleofmodule;
2080  print '</td></tr>';
2081 
2082  // Lot de donnees a importer
2083  print '<tr><td>'.$langs->trans("DatasetToImport").'</td>';
2084  print '<td>';
2085  $entity = preg_replace('/:.*$/', '', $objimport->array_import_icon[0]);
2086  $entityicon = strtolower(!empty($entitytoicon[$entity]) ? $entitytoicon[$entity] : $entity);
2087  print img_object($objimport->array_import_module[0]['module']->getName(), $entityicon).' ';
2088  print $objimport->array_import_label[0];
2089  print '</td></tr>';
2090 
2091  print '</table>';
2092  print '</div>';
2093 
2094  print load_fiche_titre($langs->trans("InformationOnSourceFile"), '', 'file-export');
2095 
2096  print '<div class="underbanner clearboth"></div>';
2097  print '<div class="fichecenter">';
2098  print '<table width="100%" class="border">';
2099 
2100  // Source file format
2101  print '<tr><td class="titlefieldcreate">'.$langs->trans("SourceFileFormat").'</td>';
2102  print '<td>';
2103  $text = $objmodelimport->getDriverDescForKey($format);
2104  print $form->textwithpicto($objmodelimport->getDriverLabelForKey($format), $text);
2105  print '</td></tr>';
2106 
2107  // Separator and enclosure
2108  if ($model == 'csv') {
2109  print '<tr><td>'.$langs->trans("CsvOptions").'</td>';
2110  print '<td>';
2111  print $langs->trans("Separator").' : ';
2112  print htmlentities($separator);
2113  print '&nbsp;&nbsp;&nbsp;&nbsp;'.$langs->trans("Enclosure").' : ';
2114  print htmlentities($enclosure);
2115  print '</td></tr>';
2116  }
2117 
2118  // File to import
2119  print '<tr><td>'.$langs->trans("FileToImport").'</td>';
2120  print '<td>';
2121  $modulepart = 'import';
2122  $relativepath = GETPOST('filetoimport');
2123  print '<a data-ajax="false" href="'.DOL_URL_ROOT.'/document.php?modulepart='.$modulepart.'&file='.urlencode($relativepath).'&step=4'.$param.'" target="_blank" rel="noopener noreferrer">';
2124  print img_mime($file, '', 'pictofixedwidth');
2125  print $filetoimport;
2126  print '</a>';
2127  print '</td></tr>';
2128 
2129  // Nb of fields
2130  print '<tr><td>';
2131  print $langs->trans("NbOfSourceLines");
2132  print '</td><td>';
2133  print $nboflines;
2134  print '</td></tr>';
2135 
2136  // Do not import first lines
2137  print '<tr><td>';
2138  print $langs->trans("ImportFromLine");
2139  print '</td><td>';
2140  print '<input type="text" size="4" name="excludefirstline" disabled="disabled" value="'.$excludefirstline.'">';
2141  print '</td></tr>';
2142 
2143  // Do not import end lines
2144  print '<tr><td>';
2145  print $langs->trans("EndAtLineNb");
2146  print '</td><td>';
2147  print '<input type="text" size="4" name="endatlinenb" disabled="disabled" value="'.$endatlinenb.'">';
2148  print '</td></tr>';
2149 
2150  print '</table>';
2151  print '</div>';
2152 
2153  print '<br>';
2154 
2155  print '<b>'.$langs->trans("InformationOnTargetTables").'</b>';
2156  print '<div class="underbanner clearboth"></div>';
2157  print '<div class="fichecenter">';
2158  print '<table class="border centpercent">';
2159 
2160  // Tables imported
2161  print '<tr><td width="25%">';
2162  print $langs->trans("TablesTarget");
2163  print '</td><td>';
2164  $listtables = array();
2165  foreach ($array_match_file_to_database as $code => $label) {
2166  //var_dump($fieldssource);
2167  if ($code > count($fieldssource)) {
2168  continue;
2169  }
2170  //print $code.'-'.$label;
2171  $alias = preg_replace('/(\..*)$/i', '', $label);
2172  $listtables[$alias] = $objimport->array_import_tables[0][$alias];
2173  }
2174  if (count($listtables)) {
2175  $newval = '';
2176  foreach ($listtables as $val) {
2177  if ($newval) {
2178  print ', ';
2179  }
2180  $newval = $val;
2181  // Link to Dolibarr wiki pages
2182  /*$helppagename='EN:Table_'.$newval;
2183  if ($helppagename && empty($conf->global->MAIN_HELP_DISABLELINK))
2184  {
2185  // Get helpbaseurl, helppage and mode from helppagename and langs
2186  $arrayres=getHelpParamFor($helppagename,$langs);
2187  $helpbaseurl=$arrayres['helpbaseurl'];
2188  $helppage=$arrayres['helppage'];
2189  $mode=$arrayres['mode'];
2190  $newval.=' <a href="'.sprintf($helpbaseurl,$helppage).'">'.img_picto($langs->trans($mode == 'wiki' ? 'GoToWikiHelpPage': 'GoToHelpPage'),DOL_URL_ROOT.'/theme/common/helpdoc.png','',1).'</a>';
2191  }*/
2192  print $newval;
2193  }
2194  } else {
2195  print $langs->trans("Error");
2196  }
2197  print '</td></tr>';
2198 
2199  // Fields imported
2200  print '<tr><td>';
2201  print $langs->trans("FieldsTarget").'</td><td>';
2202  $listfields = array();
2203  $i = 0;
2204  $sort_array_match_file_to_database = $array_match_file_to_database;
2205  ksort($sort_array_match_file_to_database);
2206  //var_dump($sort_array_match_file_to_database);
2207  foreach ($sort_array_match_file_to_database as $code => $label) {
2208  $i++;
2209  //var_dump($fieldssource);
2210  if ($code > count($fieldssource)) {
2211  continue;
2212  }
2213  //print $code.'-'.$label;
2214  $alias = preg_replace('/(\..*)$/i', '', $label);
2215  $listfields[$i] = $langs->trans("Field").' '.$code.'->'.$label;
2216  }
2217  print count($listfields) ? (join(', ', $listfields)) : $langs->trans("Error");
2218  print '</td></tr>';
2219 
2220  print '</table>';
2221  print '</div>';
2222 
2223  // Launch import
2224  $arrayoferrors = array();
2225  $arrayofwarnings = array();
2226  $maxnboferrors = empty($conf->global->IMPORT_MAX_NB_OF_ERRORS) ? 50 : $conf->global->IMPORT_MAX_NB_OF_ERRORS;
2227  $maxnbofwarnings = empty($conf->global->IMPORT_MAX_NB_OF_WARNINGS) ? 50 : $conf->global->IMPORT_MAX_NB_OF_WARNINGS;
2228  $nboferrors = 0;
2229  $nbofwarnings = 0;
2230 
2231  $importid = dol_print_date(dol_now(), '%Y%m%d%H%M%S');
2232 
2233  //var_dump($array_match_file_to_database);
2234 
2235  $db->begin();
2236 
2237  // Open input file
2238  $nbok = 0;
2239  $pathfile = $conf->import->dir_temp.'/'.$filetoimport;
2240  $result = $obj->import_open_file($pathfile, $langs);
2241  if ($result > 0) {
2242  global $tablewithentity_cache;
2243  $tablewithentity_cache = array();
2244  $sourcelinenb = 0; $endoffile = 0;
2245 
2246  while ($sourcelinenb < $nboflines && !$endoffile) {
2247  $sourcelinenb++;
2248  $arrayrecord = $obj->import_read_record();
2249  if ($arrayrecord === false) {
2250  $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');
2251  $endoffile++;
2252  continue;
2253  }
2254  if ($excludefirstline && ($sourcelinenb < $excludefirstline)) {
2255  continue;
2256  }
2257  if ($endatlinenb && ($sourcelinenb > $endatlinenb)) {
2258  break;
2259  }
2260 
2261  // Run import
2262  $result = $obj->import_insert($arrayrecord, $array_match_file_to_database, $objimport, count($fieldssource), $importid, $updatekeys);
2263 
2264  if (count($obj->errors)) {
2265  $arrayoferrors[$sourcelinenb] = $obj->errors;
2266  }
2267  if (count($obj->warnings)) {
2268  $arrayofwarnings[$sourcelinenb] = $obj->warnings;
2269  }
2270  if (!count($obj->errors) && !count($obj->warnings)) {
2271  $nbok++;
2272  }
2273  }
2274  // Close file
2275  $obj->import_close_file();
2276  } else {
2277  print $langs->trans("ErrorFailedToOpenFile", $pathfile);
2278  }
2279 
2280  if (count($arrayoferrors) > 0) {
2281  $db->rollback(); // We force rollback because this was errors.
2282  } else {
2283  $error = 0;
2284 
2285  // Run the sql after import if defined
2286  //var_dump($objimport->array_import_run_sql_after[0]);
2287  if (!empty($objimport->array_import_run_sql_after[0]) && is_array($objimport->array_import_run_sql_after[0])) {
2288  $i = 0;
2289  foreach ($objimport->array_import_run_sql_after[0] as $sqlafterimport) {
2290  $i++;
2291  $resqlafterimport = $db->query($sqlafterimport);
2292  if (!$resqlafterimport) {
2293  $arrayoferrors['none'][] = array('lib'=>$langs->trans("Error running final request: ".$sqlafterimport));
2294  $error++;
2295  }
2296  }
2297  }
2298 
2299  if (!$error) {
2300  $db->commit(); // We can commit if no errors.
2301  } else {
2302  $db->rollback();
2303  }
2304  }
2305 
2306  print dol_get_fiche_end();
2307 
2308 
2309  // Show result
2310  print '<br>';
2311  print '<div class="info">';
2312  print $langs->trans("NbOfLinesImported", $nbok).'</b><br>';
2313  print $langs->trans("NbInsert", empty($obj->nbinsert) ? 0 : $obj->nbinsert).'<br>';
2314  print $langs->trans("NbUpdate", empty($obj->nbupdate) ? 0 : $obj->nbupdate).'<br>';
2315  print '</div>';
2316  print '<div class="center">';
2317  print $langs->trans("FileWasImported", $importid).'<br>';
2318  print '<span class="opacitymedium">'.$langs->trans("YouCanUseImportIdToFindRecord", $importid).'</span><br>';
2319  print '</div>';
2320 }
2321 
2322 
2323 
2324 print '<br>';
2325 
2326 // End of page
2327 llxFooter();
2328 $db->close();
2329 
2330 
2341 function show_elem($fieldssource, $pos, $key, $var, $nostyle = '')
2342 {
2343  global $langs;
2344 
2345  $height = '32px';
2346 
2347  if ($key == 'none') {
2348  //stop multiple duplicate ids with no number
2349  print "\n\n<!-- Box_no-key start-->\n";
2350  print '<div class="box boximport" style="padding:0;">'."\n";
2351  print '<table summary="boxtable_no-key" class="centpercent nobordernopadding">'."\n";
2352  } else {
2353  print "\n\n<!-- Box ".$pos." start -->\n";
2354  print '<div class="box boximport" style="padding: 0;" id="boxto_'.$pos.'">'."\n";
2355 
2356  print '<table summary="boxtable'.$pos.'" class="nobordernopadding centpercent tableimport">'."\n";
2357  }
2358 
2359  if (($pos && $pos > count($fieldssource)) && (!isset($fieldssource[$pos]["imported"]))) { // No fields
2360  /*
2361  print '<tr style="height:'.$height.'" class="trimport oddevenimport">';
2362  print '<td class="nocellnopadding" width="16" style="font-weight: normal">';
2363  print '</td>';
2364  print '<td style="font-weight: normal">';
2365  print $langs->trans("NoFields");
2366  print '</td>';
2367  print '</tr>';
2368  */
2369  } elseif ($key == 'none') { // Empty line
2370  print '<tr style="height:'.$height.'" class="trimport oddevenimport">';
2371  print '<td class="nocellnopadding" width="16" style="font-weight: normal">';
2372  print '&nbsp;';
2373  print '</td>';
2374  print '<td style="font-weight: normal">';
2375  print '&nbsp;';
2376  print '</td>';
2377  print '</tr>';
2378  } else {
2379  // Print field of source file
2380  print '<tr style="height:'.$height.'" class="trimport oddevenimport">';
2381  print '<td class="nocellnopadding" width="16" style="font-weight: normal">';
2382  // 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
2383  //print img_picto($langs->trans("MoveField", $pos), 'grip_title', 'class="boxhandle" style="cursor:move;"');
2384  print img_picto($langs->trans("Column").' '.num2Alpha($pos - 1), 'file', 'class="pictofixedwith"');
2385  print '</td>';
2386  if (isset($fieldssource[$pos]['imported']) && $fieldssource[$pos]['imported'] == false) {
2387  print '<td class="nowraponall boxtdunused" style="font-weight: normal">';
2388  } else {
2389  print '<td class="nowraponall" style="font-weight: normal">';
2390  }
2391  print $langs->trans("Column").' '.num2Alpha($pos - 1).' (#'.$pos.')';
2392  if (empty($fieldssource[$pos]['example1'])) {
2393  $example = $fieldssource[$pos]['label'];
2394  } else {
2395  $example = $fieldssource[$pos]['example1'];
2396  }
2397  if ($example) {
2398  if (!utf8_check($example)) {
2399  $example = utf8_encode($example);
2400  }
2401  print ' - ';
2402  //print '<span class="opacitymedium hideonsmartphone">'.$langs->trans("ExampleOnFirstLine").': </span>';
2403  print '<i class="opacitymedium">'.$example.'</i>';
2404  }
2405  print '</td>';
2406  print '</tr>';
2407  }
2408 
2409  print "</table>\n";
2410 
2411  print "</div>\n";
2412  print "<!-- Box end -->\n\n";
2413 }
2414 
2415 
2423 function getnewkey(&$fieldssource, &$listofkey)
2424 {
2425  $i = count($fieldssource) + 1;
2426  // Max number of key
2427  $maxkey = 0;
2428  foreach ($listofkey as $key => $val) {
2429  $maxkey = max($maxkey, $key);
2430  }
2431  // Found next empty key
2432  while ($i <= $maxkey) {
2433  if (empty($listofkey[$i])) {
2434  break;
2435  } else {
2436  $i++;
2437  }
2438  }
2439 
2440  $listofkey[$i] = 1;
2441  return $i;
2442 }
2451 function arrayInsert($array, $position, $insertArray)
2452 {
2453  $ret = [];
2454 
2455  if ($position == count($array)) {
2456  $ret = $array + $insertArray;
2457  } else {
2458  $i = 0;
2459  foreach ($array as $key => $value) {
2460  if ($position == $i++) {
2461  $ret += $insertArray;
2462  }
2463 
2464  $ret[$key] = $value;
2465  }
2466  }
2467 
2468  return $ret;
2469 }
ajax_combobox
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:438
dol_escape_htmltag
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.
Definition: functions.lib.php:1468
dol_trunc
dol_trunc($string, $size=40, $trunc='right', $stringencoding='UTF-8', $nodot=0, $display=0)
Truncate a string to a particular length adding '…' if string larger than length.
Definition: functions.lib.php:3805
restrictedArea
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.
Definition: security.lib.php:234
llxFooter
llxFooter()
Empty footer.
Definition: wrapper.php:73
img_error
img_error($titlealt='default')
Show error logo.
Definition: functions.lib.php:4539
dol_count_nb_of_line
dol_count_nb_of_line($file)
Count number of lines in a file.
Definition: files.lib.php:550
dol_filemtime
dol_filemtime($pathoffile)
Return time of a file.
Definition: files.lib.php:593
load_fiche_titre
load_fiche_titre($titre, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='')
Load a title with picto.
Definition: functions.lib.php:5204
GETPOST
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
Definition: functions.lib.php:484
dol_print_error
dol_print_error($db='', $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
Definition: functions.lib.php:4844
dol_sort_array
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...
Definition: functions.lib.php:8385
Import
Class to manage imports.
Definition: import.class.php:30
img_warning
img_warning($titlealt='default', $moreatt='', $morecss='pictowarning')
Show warning logo.
Definition: functions.lib.php:4521
$form
if($cancel &&! $id) if($action=='add' &&! $cancel) if($action=='delete') if($id) $form
Actions.
Definition: card.php:142
dol_dir_list
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
FormOther
Classe permettant la generation de composants html autre Only common components are here.
Definition: html.formother.class.php:39
$help_url
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
dol_print_date
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs='', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
Definition: functions.lib.php:2514
dolExplodeIntoArray
dolExplodeIntoArray($string, $delimiter=';', $kv='=')
Split a string with 2 keys into key array.
Definition: functions.lib.php:9354
img_picto
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
Show picto whatever it's its name (generic function)
Definition: functions.lib.php:3880
utf8_check
utf8_check($str)
Check if a string is in UTF8.
Definition: functions.lib.php:8438
dol_delete_file
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:1231
import_prepare_head
import_prepare_head($param, $maxstep=0)
Function to return list of tabs for import pages.
Definition: import.lib.php:36
getMaxFileSizeArray
getMaxFileSizeArray()
Return the max allowed for file upload.
Definition: security.lib.php:993
img_delete
img_delete($titlealt='default', $other='class="pictodelete"', $morecss='')
Show delete logo.
Definition: functions.lib.php:4429
dol_move_uploaded_file
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:1092
arrayInsert
arrayInsert($array, $position, $insertArray)
Return array with element inserted in it at position $position.
Definition: import.php:2451
dol_escape_js
dol_escape_js($stringtoescape, $mode=0, $noescapebackslashn=0)
Returns text escaped for inclusion into javascript code.
Definition: functions.lib.php:1423
FormFile
Class to offer components to list and upload files.
Definition: html.formfile.class.php:36
num2Alpha
num2Alpha($n)
Return a numeric value into an Excel like column number.
Definition: functions.lib.php:236
dol_string_unaccent
dol_string_unaccent($str)
Clean a string from all accent characters to be used as ref, login or by dol_sanitizeFileName.
Definition: functions.lib.php:1309
ModeleImports
Parent class for import file readers.
Definition: modules_import.php:31
show_elem
show_elem($fieldssource, $pos, $key, $var, $nostyle='')
Function to put the movable box of a source field.
Definition: import.php:2341
getnewkey
getnewkey(&$fieldssource, &$listofkey)
Return not used field number.
Definition: import.php:2423
dol_syslog
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
Definition: functions.lib.php:1603
dol_get_fiche_head
dol_get_fiche_head($links=array(), $active='', $title='', $notab=0, $picto='', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limittoshow=0, $moretabssuffix='')
Show tabs of a record.
Definition: functions.lib.php:1822
info_admin
info_admin($text, $infoonimgalt=0, $nodiv=0, $admin='1', $morecss='hideonsmartphone', $textfordropdown='')
Show information for admin users or standard users.
Definition: functions.lib.php:4800
newToken
newToken()
Return the value of token currently saved into session with name 'newtoken'.
Definition: functions.lib.php:10878
dol_get_fiche_end
dol_get_fiche_end($notab=0)
Return tab footer of a card.
Definition: functions.lib.php:2018
GETPOSTISSET
GETPOSTISSET($paramname)
Return true if we are in a context of submitting the parameter $paramname from a POST of a form.
Definition: functions.lib.php:386
dol_filesize
dol_filesize($pathoffile)
Return size of a file.
Definition: files.lib.php:581
img_mime
img_mime($file, $titlealt='', $morecss='')
Show MIME img of a file.
Definition: functions.lib.php:4726
Form
Class to manage generation of HTML components Only common components must be here.
Definition: html.form.class.php:52
img_object
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0)
Show a picto called object_picto (generic function)
Definition: functions.lib.php:4211
dol_now
dol_now($mode='auto')
Return date for now.
Definition: functions.lib.php:2845
$resql
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
setEventMessages
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='')
Set event messages in dol_events session object.
Definition: functions.lib.php:8137
user
$conf db user
Definition: repair.php:123
dol_mkdir
dol_mkdir($dir, $dataroot='', $newmask='')
Creation of a directory (this can create recursive subdir)
Definition: functions.lib.php:6603
llxHeader
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