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