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