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