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