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