dolibarr 19.0.4
import.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2005-2016 Laurent Destailleur <eldy@users.sourceforge.net>
3 * Copyright (C) 2005-2009 Regis Houssin <regis.houssin@inodbox.com>
4 * Copyright (C) 2012 Christophe Battarel <christophe.battarel@altairis.fr>
5 * Copyright (C) 2022 Charlene Benke <charlene@patas-monkey.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
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 $reshook = $hookmanager->executeHooks('AfterImportInsert', $parameters);
1929 if ($reshook < 0) {
1930 $arrayoferrors[$sourcelinenb][] = [
1931 'lib' => implode("<br>", array_merge([$hookmanager->error], $hookmanager->errors))
1932 ];
1933 }
1934 }
1935 // Close file
1936 $obj->import_close_file();
1937 } else {
1938 print $langs->trans("ErrorFailedToOpenFile", $pathfile);
1939 }
1940
1941 $error = 0;
1942
1943 // Run the sql after import if defined
1944 //var_dump($objimport->array_import_run_sql_after[0]);
1945 if (!empty($objimport->array_import_run_sql_after[0]) && is_array($objimport->array_import_run_sql_after[0])) {
1946 $i = 0;
1947 foreach ($objimport->array_import_run_sql_after[0] as $sqlafterimport) {
1948 $i++;
1949 $resqlafterimport = $db->query($sqlafterimport);
1950 if (!$resqlafterimport) {
1951 $arrayoferrors['none'][] = array('lib'=>$langs->trans("Error running final request: ".$sqlafterimport));
1952 $error++;
1953 }
1954 }
1955 }
1956
1957 $db->rollback(); // We force rollback because this was just a simulation.
1958
1959 // Show OK
1960 if (!count($arrayoferrors) && !count($arrayofwarnings)) {
1961 print '<br>';
1962 print '<div class="info">';
1963 print '<div class=""><b>'.$langs->trans("ResultOfSimulationNoError").'</b></div>';
1964 print $langs->trans("NbInsertSim", empty($obj->nbinsert) ? 0 : $obj->nbinsert).'<br>';
1965 print $langs->trans("NbUpdateSim", empty($obj->nbupdate) ? 0 : $obj->nbupdate).'<br>';
1966 print '</div>';
1967 print '<br>';
1968 } else {
1969 print '<br>';
1970 print '<div class="warning">';
1971 print $langs->trans("NbOfLinesOK", $nbok).'...<br>';
1972 print '</div>';
1973 print '<br>';
1974 }
1975
1976 // Show Errors
1977 //var_dump($arrayoferrors);
1978 if (count($arrayoferrors)) {
1979 print img_error().' <b>'.$langs->trans("ErrorsOnXLines", count($arrayoferrors)).'</b><br>';
1980 print '<table width="100%" class="border"><tr><td>';
1981 foreach ($arrayoferrors as $key => $val) {
1982 $nboferrors++;
1983 if ($nboferrors > $maxnboferrors) {
1984 print $langs->trans("TooMuchErrors", (count($arrayoferrors) - $nboferrors))."<br>";
1985 break;
1986 }
1987 print '* '.$langs->trans("Line").' '.dol_escape_htmltag($key).'<br>';
1988 foreach ($val as $i => $err) {
1989 print ' &nbsp; &nbsp; > '.dol_escape_htmltag($err['lib']).'<br>';
1990 }
1991 }
1992 print '</td></tr></table>';
1993 print '<br>';
1994 }
1995
1996 // Show Warnings
1997 //var_dump($arrayoferrors);
1998 if (count($arrayofwarnings)) {
1999 print img_warning().' <b>'.$langs->trans("WarningsOnXLines", count($arrayofwarnings)).'</b><br>';
2000 print '<table width="100%" class="border"><tr><td>';
2001 foreach ($arrayofwarnings as $key => $val) {
2002 $nbofwarnings++;
2003 if ($nbofwarnings > $maxnbofwarnings) {
2004 print $langs->trans("TooMuchWarnings", (count($arrayofwarnings) - $nbofwarnings))."<br>";
2005 break;
2006 }
2007 print ' * '.$langs->trans("Line").' '.dol_escape_htmltag($key).'<br>';
2008 foreach ($val as $i => $err) {
2009 print ' &nbsp; &nbsp; > '.dol_escape_htmltag($err['lib']).'<br>';
2010 }
2011 }
2012 print '</td></tr></table>';
2013 print '<br>';
2014 }
2015
2016 // Show import id
2017 $importid = dol_print_date(dol_now(), '%Y%m%d%H%M%S');
2018
2019 print '<div class="center">';
2020 print '<span class="opacitymedium">'.$langs->trans("NowClickToRunTheImport", $langs->transnoentitiesnoconv("RunImportFile")).'</span><br>';
2021 /*if (empty($nboferrors)) {
2022 print $langs->trans("DataLoadedWithId", $importid).'<br>';
2023 }*/
2024 print '</div>';
2025
2026 print '<br>';
2027
2028 // Actions
2029 print '<div class="center">';
2030 if ($user->hasRight('import', 'run')) {
2031 if (empty($nboferrors)) {
2032 print '<a class="butAction" href="'.DOL_URL_ROOT.'/imports/import.php?leftmenu=import&step=6&importid='.$importid.$param.'">'.$langs->trans("RunImportFile").'</a>';
2033 } else {
2034 //print '<input type="submit" class="butAction" value="'.dol_escape_htmltag($langs->trans("RunSimulateImportFile")).'">';
2035
2036 print '<a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->transnoentitiesnoconv("CorrectErrorBeforeRunningImport")).'">'.$langs->trans("RunImportFile").'</a>';
2037 }
2038 } else {
2039 print '<a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->transnoentitiesnoconv("NotEnoughPermissions")).'">'.$langs->trans("RunSimulateImportFile").'</a>';
2040
2041 print '<a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->transnoentitiesnoconv("NotEnoughPermissions")).'">'.$langs->trans("RunImportFile").'</a>';
2042 }
2043 print '</div>';
2044 }
2045
2046 print '</form>';
2047}
2048
2049
2050// STEP 6: Real import
2051if ($step == 6 && $datatoimport) {
2052 $max_execution_time_for_importexport = (!getDolGlobalString('IMPORT_MAX_EXECUTION_TIME') ? 300 : $conf->global->IMPORT_MAX_EXECUTION_TIME); // 5mn if not defined
2053 $max_time = @ini_get("max_execution_time");
2054 if ($max_time && $max_time < $max_execution_time_for_importexport) {
2055 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.");
2056 @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
2057 }
2058
2059 $model = $format;
2060 $list = $objmodelimport->listOfAvailableImportFormat($db);
2061 $importid = GETPOST("importid", 'alphanohtml');
2062
2063
2064 // Create classe to use for import
2065 $dir = DOL_DOCUMENT_ROOT."/core/modules/import/";
2066 $file = "import_".$model.".modules.php";
2067 $classname = "Import".ucfirst($model);
2068 require_once $dir.$file;
2069 $obj = new $classname($db, $datatoimport);
2070 if ($model == 'csv') {
2071 $obj->separator = $separator_used;
2072 $obj->enclosure = $enclosure;
2073 }
2074
2075 // Load source fields in input file
2076 $fieldssource = array();
2077 $result = $obj->import_open_file($conf->import->dir_temp.'/'.$filetoimport, $langs);
2078 if ($result >= 0) {
2079 // Read first line
2080 $arrayrecord = $obj->import_read_record();
2081 // Put into array fieldssource starting with 1.
2082 $i = 1;
2083 foreach ($arrayrecord as $key => $val) {
2084 $fieldssource[$i]['example1'] = dol_trunc($val['val'], 24);
2085 $i++;
2086 }
2087 $obj->import_close_file();
2088 }
2089
2090 $nboflines = (!empty($_GET["nboflines"]) ? $_GET["nboflines"] : dol_count_nb_of_line($conf->import->dir_temp.'/'.$filetoimport));
2091
2092 $param = '&format='.$format.'&datatoimport='.urlencode($datatoimport).'&filetoimport='.urlencode($filetoimport).'&nboflines='.urlencode($nboflines);
2093 if ($excludefirstline) {
2094 $param .= '&excludefirstline='.urlencode($excludefirstline);
2095 }
2096 if ($endatlinenb) {
2097 $param .= '&endatlinenb='.urlencode($endatlinenb);
2098 }
2099 if ($separator) {
2100 $param .= '&separator='.urlencode($separator);
2101 }
2102 if ($enclosure) {
2103 $param .= '&enclosure='.urlencode($enclosure);
2104 }
2105
2106 llxHeader('', $langs->trans("NewImport"), $help_url);
2107
2108 $head = import_prepare_head($param, 6);
2109
2110 print dol_get_fiche_head($head, 'step6', '', -1);
2111
2112 print '<div class="underbanner clearboth"></div>';
2113 print '<div class="fichecenter">';
2114
2115 print '<table width="100%" class="border">';
2116
2117 // Module
2118 print '<tr><td class="titlefieldcreate">'.$langs->trans("Module").'</td>';
2119 print '<td>';
2120 $titleofmodule = $objimport->array_import_module[0]['module']->getName();
2121 // Special cas for import common to module/services
2122 if (in_array($objimport->array_import_code[0], array('produit_supplierprices', 'produit_multiprice', 'produit_languages'))) {
2123 $titleofmodule = $langs->trans("ProductOrService");
2124 }
2125 print $titleofmodule;
2126 print '</td></tr>';
2127
2128 // Lot de donnees a importer
2129 print '<tr><td>'.$langs->trans("DatasetToImport").'</td>';
2130 print '<td>';
2131 $entity = preg_replace('/:.*$/', '', $objimport->array_import_icon[0]);
2132 $entityicon = strtolower(!empty($entitytoicon[$entity]) ? $entitytoicon[$entity] : $entity);
2133 print img_object($objimport->array_import_module[0]['module']->getName(), $entityicon).' ';
2134 print $objimport->array_import_label[0];
2135 print '</td></tr>';
2136
2137 print '</table>';
2138 print '</div>';
2139
2140 print load_fiche_titre($langs->trans("InformationOnSourceFile"), '', 'file-export');
2141
2142 print '<div class="underbanner clearboth"></div>';
2143 print '<div class="fichecenter">';
2144 print '<table width="100%" class="border">';
2145
2146 // Source file format
2147 print '<tr><td class="titlefieldcreate">'.$langs->trans("SourceFileFormat").'</td>';
2148 print '<td>';
2149 $text = $objmodelimport->getDriverDescForKey($format);
2150 print $form->textwithpicto($objmodelimport->getDriverLabelForKey($format), $text);
2151 print '</td></tr>';
2152
2153 // Separator and enclosure
2154 if ($model == 'csv') {
2155 print '<tr><td>'.$langs->trans("CsvOptions").'</td>';
2156 print '<td>';
2157 print $langs->trans("Separator").' : ';
2158 print htmlentities($separator);
2159 print '&nbsp;&nbsp;&nbsp;&nbsp;'.$langs->trans("Enclosure").' : ';
2160 print htmlentities($enclosure);
2161 print '</td></tr>';
2162 }
2163
2164 // File to import
2165 print '<tr><td>'.$langs->trans("FileToImport").'</td>';
2166 print '<td>';
2167 $modulepart = 'import';
2168 $relativepath = GETPOST('filetoimport');
2169 print '<a data-ajax="false" href="'.DOL_URL_ROOT.'/document.php?modulepart='.$modulepart.'&file='.urlencode($relativepath).'&step=4'.$param.'" target="_blank" rel="noopener noreferrer">';
2170 print img_mime($file, '', 'pictofixedwidth');
2171 print $filetoimport;
2172 print '</a>';
2173 print '</td></tr>';
2174
2175 // Nb of fields
2176 print '<tr><td>';
2177 print $langs->trans("NbOfSourceLines");
2178 print '</td><td>';
2179 print $nboflines;
2180 print '</td></tr>';
2181
2182 // Do not import first lines
2183 print '<tr><td>';
2184 print $langs->trans("ImportFromLine");
2185 print '</td><td>';
2186 print '<input type="text" size="4" name="excludefirstline" disabled="disabled" value="'.$excludefirstline.'">';
2187 print '</td></tr>';
2188
2189 // Do not import end lines
2190 print '<tr><td>';
2191 print $langs->trans("EndAtLineNb");
2192 print '</td><td>';
2193 print '<input type="text" size="4" name="endatlinenb" disabled="disabled" value="'.$endatlinenb.'">';
2194 print '</td></tr>';
2195
2196 print '</table>';
2197 print '</div>';
2198
2199 print '<br>';
2200
2201 print '<b>'.$langs->trans("InformationOnTargetTables").'</b>';
2202 print '<div class="underbanner clearboth"></div>';
2203 print '<div class="fichecenter">';
2204 print '<table class="border centpercent">';
2205
2206 // Tables imported
2207 print '<tr><td width="25%">';
2208 print $langs->trans("TablesTarget");
2209 print '</td><td>';
2210 $listtables = array();
2211 foreach ($array_match_file_to_database as $code => $label) {
2212 //var_dump($fieldssource);
2213 if ($code > count($fieldssource)) {
2214 continue;
2215 }
2216 //print $code.'-'.$label;
2217 $alias = preg_replace('/(\..*)$/i', '', $label);
2218 $listtables[$alias] = $objimport->array_import_tables[0][$alias];
2219 }
2220 if (count($listtables)) {
2221 $newval = '';
2222 foreach ($listtables as $val) {
2223 if ($newval) {
2224 print ', ';
2225 }
2226 $newval = $val;
2227 // Link to Dolibarr wiki pages
2228 /*$helppagename='EN:Table_'.$newval;
2229 if ($helppagename && empty($conf->global->MAIN_HELP_DISABLELINK))
2230 {
2231 // Get helpbaseurl, helppage and mode from helppagename and langs
2232 $arrayres=getHelpParamFor($helppagename,$langs);
2233 $helpbaseurl=$arrayres['helpbaseurl'];
2234 $helppage=$arrayres['helppage'];
2235 $mode=$arrayres['mode'];
2236 $newval.=' <a href="'.sprintf($helpbaseurl,$helppage).'">'.img_picto($langs->trans($mode == 'wiki' ? 'GoToWikiHelpPage': 'GoToHelpPage'),DOL_URL_ROOT.'/theme/common/helpdoc.png','',1).'</a>';
2237 }*/
2238 print $newval;
2239 }
2240 } else {
2241 print $langs->trans("Error");
2242 }
2243 print '</td></tr>';
2244
2245 // Fields imported
2246 print '<tr><td>';
2247 print $langs->trans("FieldsTarget").'</td><td>';
2248 $listfields = array();
2249 $i = 0;
2250 $sort_array_match_file_to_database = $array_match_file_to_database;
2251 ksort($sort_array_match_file_to_database);
2252 //var_dump($sort_array_match_file_to_database);
2253 foreach ($sort_array_match_file_to_database as $code => $label) {
2254 $i++;
2255 //var_dump($fieldssource);
2256 if ($code > count($fieldssource)) {
2257 continue;
2258 }
2259 //print $code.'-'.$label;
2260 $alias = preg_replace('/(\..*)$/i', '', $label);
2261 $listfields[$i] = $langs->trans("Field").' '.$code.'->'.$label;
2262 }
2263 print count($listfields) ? (join(', ', $listfields)) : $langs->trans("Error");
2264 print '</td></tr>';
2265
2266 print '</table>';
2267 print '</div>';
2268
2269 // Launch import
2270 $arrayoferrors = array();
2271 $arrayofwarnings = array();
2272 $maxnboferrors = !getDolGlobalString('IMPORT_MAX_NB_OF_ERRORS') ? 50 : $conf->global->IMPORT_MAX_NB_OF_ERRORS;
2273 $maxnbofwarnings = !getDolGlobalString('IMPORT_MAX_NB_OF_WARNINGS') ? 50 : $conf->global->IMPORT_MAX_NB_OF_WARNINGS;
2274 $nboferrors = 0;
2275 $nbofwarnings = 0;
2276
2277 $importid = dol_print_date(dol_now(), '%Y%m%d%H%M%S');
2278
2279 //var_dump($array_match_file_to_database);
2280
2281 $db->begin();
2282
2283 // Open input file
2284 $nbok = 0;
2285 $pathfile = $conf->import->dir_temp.'/'.$filetoimport;
2286 $result = $obj->import_open_file($pathfile, $langs);
2287 if ($result > 0) {
2288 global $tablewithentity_cache;
2289 $tablewithentity_cache = array();
2290 $sourcelinenb = 0;
2291 $endoffile = 0;
2292
2293 while ($sourcelinenb < $nboflines && !$endoffile) {
2294 $sourcelinenb++;
2295 $arrayrecord = $obj->import_read_record();
2296 if ($arrayrecord === false) {
2297 $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');
2298 $endoffile++;
2299 continue;
2300 }
2301 if ($excludefirstline && ($sourcelinenb < $excludefirstline)) {
2302 continue;
2303 }
2304 if ($endatlinenb && ($sourcelinenb > $endatlinenb)) {
2305 break;
2306 }
2307
2308 $parameters = array(
2309 'step' => $step,
2310 'datatoimport' => $datatoimport,
2311 'obj' => &$obj,
2312 'arrayrecord' => $arrayrecord,
2313 'array_match_file_to_database' => $array_match_file_to_database,
2314 'objimport' => $objimport,
2315 'fieldssource' => $fieldssource,
2316 'importid' => $importid,
2317 'updatekeys' => $updatekeys,
2318 'arrayoferrors' => &$arrayoferrors,
2319 'arrayofwarnings' => &$arrayofwarnings,
2320 'nbok' => &$nbok,
2321 );
2322
2323 $reshook = $hookmanager->executeHooks('ImportInsert', $parameters);
2324 if ($reshook < 0) {
2325 $arrayoferrors[$sourcelinenb][] = [
2326 'lib' => implode("<br>", array_merge([$hookmanager->error], $hookmanager->errors))
2327 ];
2328 }
2329
2330 if (empty($reshook)) {
2331 // Run import
2332 $result = $obj->import_insert($arrayrecord, $array_match_file_to_database, $objimport, count($fieldssource), $importid, $updatekeys);
2333
2334 if (count($obj->errors)) {
2335 $arrayoferrors[$sourcelinenb] = $obj->errors;
2336 }
2337 if (count($obj->warnings)) {
2338 $arrayofwarnings[$sourcelinenb] = $obj->warnings;
2339 }
2340
2341 if (!count($obj->errors) && !count($obj->warnings)) {
2342 $nbok++;
2343 }
2344 }
2345
2346 $reshook = $hookmanager->executeHooks('AfterImportInsert', $parameters);
2347 if ($reshook < 0) {
2348 $arrayoferrors[$sourcelinenb][] = [
2349 'lib' => implode("<br>", array_merge([$hookmanager->error], $hookmanager->errors))
2350 ];
2351 }
2352 }
2353 // Close file
2354 $obj->import_close_file();
2355 } else {
2356 print $langs->trans("ErrorFailedToOpenFile", $pathfile);
2357 }
2358
2359 if (count($arrayoferrors) > 0) {
2360 $db->rollback(); // We force rollback because this was errors.
2361 } else {
2362 $error = 0;
2363
2364 // Run the sql after import if defined
2365 //var_dump($objimport->array_import_run_sql_after[0]);
2366 if (!empty($objimport->array_import_run_sql_after[0]) && is_array($objimport->array_import_run_sql_after[0])) {
2367 $i = 0;
2368 foreach ($objimport->array_import_run_sql_after[0] as $sqlafterimport) {
2369 $i++;
2370 $resqlafterimport = $db->query($sqlafterimport);
2371 if (!$resqlafterimport) {
2372 $arrayoferrors['none'][] = array('lib'=>$langs->trans("Error running final request: ".$sqlafterimport));
2373 $error++;
2374 }
2375 }
2376 }
2377
2378 if (!$error) {
2379 $db->commit(); // We can commit if no errors.
2380 } else {
2381 $db->rollback();
2382 }
2383 }
2384
2385 print dol_get_fiche_end();
2386
2387
2388 // Show result
2389 print '<br>';
2390 print '<div class="info">';
2391 print $langs->trans("NbOfLinesImported", $nbok).'</b><br>';
2392 print $langs->trans("NbInsert", empty($obj->nbinsert) ? 0 : $obj->nbinsert).'<br>';
2393 print $langs->trans("NbUpdate", empty($obj->nbupdate) ? 0 : $obj->nbupdate).'<br>';
2394 print '</div>';
2395 print '<div class="center">';
2396 print $langs->trans("FileWasImported", $importid).'<br>';
2397 print '<span class="opacitymedium">'.$langs->trans("YouCanUseImportIdToFindRecord", $importid).'</span><br>';
2398 print '</div>';
2399}
2400
2401
2402
2403print '<br>';
2404
2405// End of page
2406llxFooter();
2407$db->close();
2408
2409
2420function show_elem($fieldssource, $pos, $key, $var, $nostyle = '')
2421{
2422 global $conf, $langs;
2423
2424 $height = '32px';
2425
2426 if ($key == 'none') {
2427 //stop multiple duplicate ids with no number
2428 print "\n\n<!-- Box_no-key start-->\n";
2429 print '<div class="box boximport" style="padding:0;">'."\n";
2430 print '<table summary="boxtable_no-key" class="centpercent nobordernopadding">'."\n";
2431 } else {
2432 print "\n\n<!-- Box ".$pos." start -->\n";
2433 print '<div class="box boximport" style="padding: 0;" id="boxto_'.$pos.'">'."\n";
2434
2435 print '<table summary="boxtable'.$pos.'" class="nobordernopadding centpercent tableimport">'."\n";
2436 }
2437
2438 if (($pos && $pos > count($fieldssource)) && (!isset($fieldssource[$pos]["imported"]))) { // No fields
2439 /*
2440 print '<tr style="height:'.$height.'" class="trimport oddevenimport">';
2441 print '<td class="nocellnopadding" width="16" style="font-weight: normal">';
2442 print '</td>';
2443 print '<td style="font-weight: normal">';
2444 print $langs->trans("NoFields");
2445 print '</td>';
2446 print '</tr>';
2447 */
2448 } elseif ($key == 'none') { // Empty line
2449 print '<tr style="height:'.$height.'" class="trimport oddevenimport">';
2450 print '<td class="nocellnopadding" width="16" style="font-weight: normal">';
2451 print '&nbsp;';
2452 print '</td>';
2453 print '<td style="font-weight: normal">';
2454 print '&nbsp;';
2455 print '</td>';
2456 print '</tr>';
2457 } else {
2458 // Print field of source file
2459 print '<tr style="height:'.$height.'" class="trimport oddevenimport">';
2460 print '<td class="nocellnopadding" width="16" style="font-weight: normal">';
2461 // 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
2462 //print img_picto($langs->trans("MoveField", $pos), 'grip_title', 'class="boxhandle" style="cursor:move;"');
2463 print img_picto($langs->trans("Column").' '.num2Alpha($pos - 1), 'file', 'class="pictofixedwith"');
2464 print '</td>';
2465 if (isset($fieldssource[$pos]['imported']) && $fieldssource[$pos]['imported'] == false) {
2466 print '<td class="nowraponall boxtdunused" style="font-weight: normal">';
2467 } else {
2468 print '<td class="nowraponall tdoverflowmax500" style="font-weight: normal">';
2469 }
2470 print $langs->trans("Column").' '.num2Alpha($pos - 1).' (#'.$pos.')';
2471 if (empty($fieldssource[$pos]['example1'])) {
2472 $example = $fieldssource[$pos]['label'];
2473 } else {
2474 $example = $fieldssource[$pos]['example1'];
2475 }
2476 if ($example) {
2477 if (!utf8_check($example)) {
2478 $example = mb_convert_encoding($example, 'UTF-8', 'ISO-8859-1');
2479 }
2480 if (!empty($conf->dol_optimize_smallscreen)) {
2481 //print '<br>';
2482 print ' - ';
2483 } else {
2484 print ' - ';
2485 }
2486 print '<i class="opacitymedium">'.dol_escape_htmltag($example).'</i>';
2487 }
2488 print '</td>';
2489 print '</tr>';
2490 }
2491
2492 print "</table>\n";
2493
2494 print "</div>\n";
2495 print "<!-- Box end -->\n\n";
2496}
2497
2498
2506function getnewkey(&$fieldssource, &$listofkey)
2507{
2508 $i = count($fieldssource) + 1;
2509 // Max number of key
2510 $maxkey = 0;
2511 foreach ($listofkey as $key => $val) {
2512 $maxkey = max($maxkey, $key);
2513 }
2514 // Found next empty key
2515 while ($i <= $maxkey) {
2516 if (empty($listofkey[$i])) {
2517 break;
2518 } else {
2519 $i++;
2520 }
2521 }
2522
2523 $listofkey[$i] = 1;
2524 return $i;
2525}
2534function arrayInsert($array, $position, $insertArray)
2535{
2536 $ret = [];
2537
2538 if ($position == count($array)) {
2539 $ret = $array + $insertArray;
2540 } else {
2541 $i = 0;
2542 foreach ($array as $key => $value) {
2543 if ($position == $i++) {
2544 $ret += $insertArray;
2545 }
2546
2547 $ret[$key] = $value;
2548 }
2549 }
2550
2551 return $ret;
2552}
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:455
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:2506
arrayInsert($array, $position, $insertArray)
Return array with element inserted in it at position $position.
Definition import.php:2534
show_elem($fieldssource, $pos, $key, $var, $nostyle='')
Function to put the movable box of a source field.
Definition import.php:2420
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.