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