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