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