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