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