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