* Copyright (C) 2005-2009 Regis Houssin * Copyright (C) 2012 Christophe Battarel * Copyright (C) 2022 Charlene Benke * Copyright (C) 2024 MDW * Copyright (C) 2024 Frédéric France * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ /** * \file htdocs/imports/import.php * \ingroup import * \brief Pages of import Wizard */ require_once '../main.inc.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php'; require_once DOL_DOCUMENT_ROOT.'/imports/class/import.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/modules/import/modules_import.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/images.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/import.lib.php'; /** * @var Conf $conf * @var DoliDB $db * @var HookManager $hookmanager * @var Translate $langs * @var User $user */ // Load translation files required by the page $langs->loadLangs(array('exports', 'compta', 'errors', 'projects', 'admin')); // Initialize a technical object to manage hooks of page. Note that conf->hooks_modules contains an array of hook context $hookmanager->initHooks(array('imports')); // Security check $result = restrictedArea($user, 'import'); // Map icons, array duplicated in export.php, was not synchronized, TODO put it somewhere only once $entitytoicon = array( 'invoice' => 'bill', 'invoice_line' => 'bill', 'order' => 'order', 'order_line' => 'order', 'propal' => 'propal', 'propal_line' => 'propal', 'intervention' => 'intervention', 'inter_line' => 'intervention', 'member' => 'user', 'member_type' => 'group', 'subscription' => 'payment', 'payment' => 'payment', 'tax' => 'bill', 'tax_type' => 'generic', 'other' => 'generic', 'account' => 'account', 'product' => 'product', 'virtualproduct' => 'product', 'subproduct' => 'product', 'product_supplier_ref' => 'product', 'stock' => 'stock', 'warehouse' => 'stock', 'batch' => 'stock', 'stockbatch' => 'stock', 'category' => 'category', 'shipment' => 'sending', 'shipment_line' => 'sending', 'reception' => 'sending', 'reception_line' => 'sending', 'expensereport' => 'trip', 'expensereport_line' => 'trip', 'holiday' => 'holiday', 'contract_line' => 'contract', 'translation' => 'generic', 'bomm' => 'bom', 'bomline' => 'bom' ); // Translation code, array duplicated in export.php, was not synchronized, TODO put it somewhere only once $entitytolang = array( 'user' => 'User', 'company' => 'Company', 'contact' => 'Contact', 'invoice' => 'Bill', 'invoice_line' => 'InvoiceLine', 'order' => 'Order', 'order_line' => 'OrderLine', 'propal' => 'Proposal', 'propal_line' => 'ProposalLine', 'intervention' => 'Intervention', 'inter_line' => 'InterLine', 'member' => 'Member', 'member_type' => 'MemberType', 'subscription' => 'Subscription', 'tax' => 'SocialContribution', 'tax_type' => 'DictionarySocialContributions', 'account' => 'BankTransactions', 'payment' => 'Payment', 'product' => 'Product', 'virtualproduct' => 'AssociatedProducts', 'subproduct' => 'SubProduct', 'product_supplier_ref' => 'SupplierPrices', 'service' => 'Service', 'stock' => 'Stock', 'movement' => 'StockMovement', 'batch' => 'Batch', 'stockbatch' => 'StockDetailPerBatch', 'warehouse' => 'Warehouse', 'category' => 'Category', 'other' => 'Other', 'trip' => 'TripsAndExpenses', 'shipment' => 'Shipments', 'shipment_line' => 'ShipmentLine', 'project' => 'Projects', 'projecttask' => 'Tasks', 'task_time' => 'TaskTimeSpent', 'action' => 'Event', 'expensereport' => 'ExpenseReport', 'expensereport_line' => 'ExpenseReportLine', 'holiday' => 'TitreRequestCP', 'contract' => 'Contract', 'contract_line' => 'ContractLine', 'translation' => 'Translation', 'bom' => 'BOM', 'bomline' => 'BOMLine' ); $datatoimport = GETPOST('datatoimport'); $format = GETPOST('format'); $filetoimport = GETPOST('filetoimport'); $action = GETPOST('action', 'alpha'); $confirm = GETPOST('confirm', 'alpha'); $step = (GETPOST('step') ? GETPOST('step') : 1); $import_name = GETPOST('import_name'); $hexa = GETPOST('hexa'); $importmodelid = GETPOSTINT('importmodelid'); $excludefirstline = (GETPOST('excludefirstline') ? GETPOST('excludefirstline') : 2); $endatlinenb = (GETPOST('endatlinenb') ? GETPOST('endatlinenb') : ''); $updatekeys = (GETPOST('updatekeys', 'array') ? GETPOST('updatekeys', 'array') : array()); $separator = (GETPOST('separator', 'nohtml') ? GETPOST('separator', 'nohtml', 3) : ''); $enclosure = (GETPOST('enclosure', 'nohtml') ? GETPOST('enclosure', 'nohtml') : '"'); // We must use 'nohtml' and not 'alphanohtml' because we must accept " $charset = GETPOST('charset', 'aZ09'); $separator_used = str_replace('\t', "\t", $separator); $relativepath = ''; $objimport = new Import($db); $objimport->load_arrays($user, ($step == 1 ? '' : $datatoimport)); if (empty($updatekeys) && !empty($objimport->array_import_preselected_updatekeys[0])) { $updatekeys = $objimport->array_import_preselected_updatekeys[0]; } $objmodelimport = new ModeleImports(); $form = new Form($db); $htmlother = new FormOther($db); $formfile = new FormFile($db); // Init $array_match_file_to_database from _SESSION if (empty($array_match_file_to_database)) { $serialized_array_match_file_to_database = isset($_SESSION["dol_array_match_file_to_database_select"]) ? $_SESSION["dol_array_match_file_to_database_select"] : ''; $array_match_file_to_database = array(); $fieldsarray = explode(',', $serialized_array_match_file_to_database); foreach ($fieldsarray as $elem) { $tabelem = explode('=', $elem, 2); $key = $tabelem[0]; $val = (isset($tabelem[1]) ? $tabelem[1] : ''); if ($key && $val) { $array_match_file_to_database[$key] = $val; } } } /* * Actions */ if ($action == 'deleteprof' && $user->hasRight('import', 'run')) { if (GETPOSTINT("id")) { $objimport->fetch(GETPOSTINT("id")); $result = $objimport->delete($user); } } // Save import config to database if ($action == 'add_import_model' && $user->hasRight('import', 'run')) { if ($import_name) { // Set save string $hexa = ''; foreach ($array_match_file_to_database as $key => $val) { if ($hexa) { $hexa .= ','; } $hexa .= $key.'='.$val; } $objimport->model_name = $import_name; $objimport->datatoimport = $datatoimport; $objimport->hexa = $hexa; $objimport->fk_user = (GETPOST('visibility', 'aZ09') == 'all' ? 0 : $user->id); $result = $objimport->create($user); if ($result >= 0) { setEventMessages($langs->trans("ImportModelSaved", $objimport->model_name), null, 'mesgs'); $import_name = ''; } else { $langs->load("errors"); if ($objimport->errno == 'DB_ERROR_RECORD_ALREADY_EXISTS') { setEventMessages($langs->trans("ErrorImportDuplicateProfil"), null, 'errors'); } else { setEventMessages($objimport->error, null, 'errors'); } } } else { setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("ImportModelName")), null, 'errors'); } } if ($step == 3 && $datatoimport) { if (GETPOST('sendit') && getDolGlobalString('MAIN_UPLOAD_DOC')) { dol_mkdir($conf->import->dir_temp); $nowyearmonth = dol_print_date(dol_now(), '%Y%m%d%H%M%S'); $fullpath = $conf->import->dir_temp."/".$nowyearmonth.'-'.$_FILES['userfile']['name']; if (dol_move_uploaded_file($_FILES['userfile']['tmp_name'], $fullpath, 1) > 0) { dol_syslog("File ".$fullpath." was added for import"); } else { $langs->load("errors"); setEventMessages($langs->trans("ErrorFailedToSaveFile"), null, 'errors'); } } // Delete file if ($action == 'confirm_deletefile' && $confirm == 'yes') { $langs->load("other"); $param = '&datatoimport='.urlencode($datatoimport).'&format='.urlencode($format); if ($excludefirstline) { $param .= '&excludefirstline='.urlencode($excludefirstline); } if ($endatlinenb) { $param .= '&endatlinenb='.urlencode($endatlinenb); } $file = $conf->import->dir_temp.'/'.GETPOST('urlfile'); $ret = dol_delete_file($file); if ($ret) { setEventMessages($langs->trans("FileWasRemoved", GETPOST('urlfile')), null, 'mesgs'); } else { setEventMessages($langs->trans("ErrorFailToDeleteFile", GETPOST('urlfile')), null, 'errors'); } header('Location: '.$_SERVER["PHP_SELF"].'?step='.$step.$param); exit; } } if ($step == 4 && $action == 'select_model' && $user->hasRight('import', 'run')) { // Reinit match arrays $_SESSION["dol_array_match_file_to_database"] = ''; $serialized_array_match_file_to_database = ''; $array_match_file_to_database = array(); // Load model from $importmodelid and set $array_match_file_to_database // and $_SESSION["dol_array_match_file_to_database"] $result = $objimport->fetch($importmodelid); if ($result > 0) { $serialized_array_match_file_to_database = $objimport->hexa; $fieldsarray = explode(',', $serialized_array_match_file_to_database); foreach ($fieldsarray as $elem) { $tabelem = explode('=', $elem); $key = $tabelem[0]; $val = $tabelem[1]; if ($key && $val) { $array_match_file_to_database[$key] = $val; } } $_SESSION["dol_array_match_file_to_database"] = $serialized_array_match_file_to_database; $_SESSION['dol_array_match_file_to_database_select'] = $_SESSION["dol_array_match_file_to_database"]; } } if ($action == 'saveselectorder' && $user->hasRight('import', 'run')) { // Enregistrement de la position des champs $serialized_array_match_file_to_database = ''; dol_syslog("selectorder=".GETPOST('selectorder'), LOG_DEBUG); $selectorder = explode(",", GETPOST('selectorder')); $fieldtarget = $fieldstarget = $objimport->array_import_fields[0]; foreach ($selectorder as $key => $code) { $serialized_array_match_file_to_database .= $key.'='.$code; $serialized_array_match_file_to_database .= ','; } $serialized_array_match_file_to_database = substr($serialized_array_match_file_to_database, 0, -1); dol_syslog('dol_array_match_file_to_database_select='.$serialized_array_match_file_to_database); $_SESSION["dol_array_match_file_to_database_select"] = $serialized_array_match_file_to_database; echo "{}"; exit(0); } /* * View */ $help_url = 'EN:Module_Imports_En|FR:Module_Imports|ES:Módulo_Importaciones'; // STEP 1: Page to select dataset to import if ($step == 1 || !$datatoimport) { // Clean saved file-database matching $serialized_array_match_file_to_database = ''; $array_match_file_to_database = array(); $_SESSION["dol_array_match_file_to_database"] = ''; $_SESSION["dol_array_match_file_to_database_select"] = ''; $param = ''; if ($excludefirstline) { $param .= '&excludefirstline='.urlencode($excludefirstline); } if ($endatlinenb) { $param .= '&endatlinenb='.urlencode($endatlinenb); } if ($separator) { $param .= '&separator='.urlencode($separator); } if ($enclosure) { $param .= '&enclosure='.urlencode($enclosure); } llxHeader('', $langs->trans("NewImport"), $help_url); $head = import_prepare_head($param, 1); print dol_get_fiche_head($head, 'step1', '', -1); print '
'.$langs->trans("SelectImportDataSet").'

'; // Affiche les modules d'imports print '
'; // You can use div-table-responsive-no-min if you don't need reserved height for your table print ''; print ''; print ''; print ''; print ''; print ''; if (count($objimport->array_import_module)) { $sortedarrayofmodules = dol_sort_array($objimport->array_import_module, 'position_of_profile', 'asc', 0, 0, 1); foreach ($sortedarrayofmodules as $key => $value) { //var_dump($key.' '.$value['position_of_profile'].' '.$value['import_code'].' '.$objimport->array_import_module[$key]['module']->getName().' '.$objimport->array_import_code[$key]); $titleofmodule = $objimport->array_import_module[$key]['module']->getName(); print ''; } } else { print ''; } print '
'.$langs->trans("Module").''.$langs->trans("ImportableDatas").' 
'; // Special case for import common to module/services if (in_array($objimport->array_import_code[$key], array('produit_supplierprices', 'produit_multiprice', 'produit_languages'))) { $titleofmodule = $langs->trans("ProductOrService"); } print dolPrintHTML($titleofmodule); print ''; $entity = preg_replace('/:.*$/', '', $objimport->array_import_icon[$key]); $entityicon = strtolower(!empty($entitytoicon[$entity]) ? $entitytoicon[$entity] : $entity); $label = $objimport->array_import_label[$key]; print '
'; print img_object($objimport->array_import_module[$key]['module']->getName(), $entityicon, 'class="pictofixedwidth"'); print dolPrintHTML($label); print '
'; print '
'; if ($objimport->array_import_perms[$key]) { print ''.img_picto($langs->trans("NewImport"), 'next', 'class="fa-15"').''; } else { print $langs->trans("NotEnoughPermissions"); } print '
'.$langs->trans("NoImportableData").'
'; print '
'; print dol_get_fiche_end(); } // STEP 2: Page to select input format file if ($step == 2 && $datatoimport) { $param = '&datatoimport='.urlencode($datatoimport); if ($excludefirstline) { $param .= '&excludefirstline='.urlencode($excludefirstline); } if ($endatlinenb) { $param .= '&endatlinenb='.urlencode($endatlinenb); } if ($separator) { $param .= '&separator='.urlencode($separator); } if ($enclosure) { $param .= '&enclosure='.urlencode($enclosure); } llxHeader('', $langs->trans("NewImport"), $help_url); $head = import_prepare_head($param, 2); print dol_get_fiche_head($head, 'step2', '', -2); print '
'; print '
'; print ''; // Module print ''; print ''; // Dataset to import print ''; print ''; print '
'.$langs->trans("Module").''; $titleofmodule = $objimport->array_import_module[0]['module']->getName(); // Special case for import common to module/services if (in_array($objimport->array_import_code[0], array('produit_supplierprices', 'produit_multiprice', 'produit_languages'))) { $titleofmodule = $langs->trans("ProductOrService"); } print $titleofmodule; print '
'.$langs->trans("DatasetToImport").''; $entity = preg_replace('/:.*$/', '', $objimport->array_import_icon[0]); $entityicon = strtolower(!empty($entitytoicon[$entity]) ? $entitytoicon[$entity] : $entity); print img_object($objimport->array_import_module[0]['module']->getName(), $entityicon).' '; print $objimport->array_import_label[0]; print '
'; print '
'; print dol_get_fiche_end(); print '
'; print ''; print '
'; print ''; $s = $langs->trans("ChooseFormatOfFileToImport", '{s1}'); $s = str_replace('{s1}', img_picto('', 'next'), $s); print $s; print '

'; print '
'; print '
'; // You can use div-table-responsive-no-min if you don't need reserved height for your table print ''; $filetoimport = ''; // Add format information and link to download example print ''; $list = $objmodelimport->listOfAvailableImportFormat($db); foreach ($list as $key) { print ''; print ''; $htmltext = $objmodelimport->getDriverDescForKey($key); print ''; print ''; // Action button print ''; print ''; } print '
'; print $langs->trans("FileMustHaveOneOfFollowingFormat"); print '
'.img_picto_common($key, $objmodelimport->getPictoForKey($key)).''.$form->textwithpicto($objmodelimport->getDriverLabelForKey($key), $htmltext).''; if (empty($objmodelimport->drivererror[$key])) { $filename = $langs->transnoentitiesnoconv("ExampleOfImportFile").'_'.$datatoimport.'.'.$key; print ''; print img_picto('', 'download', 'class="paddingright opacitymedium"'); print $langs->trans("DownloadEmptyExampleShort"); print ''; print $form->textwithpicto('', $langs->trans("DownloadEmptyExample").'.
'.$langs->trans("StarAreMandatory")); } else { print dolPrintHTML($objmodelimport->drivererror[$key]); } print '
'; if (empty($objmodelimport->drivererror[$key])) { print ''.img_picto($langs->trans("SelectFormat"), 'next', 'class="fa-15"').''; } print '
'; print '
'; print '
'; } // STEP 3: Page to select file if ($step == 3 && $datatoimport) { $param = '&datatoimport='.urlencode($datatoimport).'&format='.urlencode($format); if ($excludefirstline) { $param .= '&excludefirstline='.urlencode($excludefirstline); } if ($endatlinenb) { $param .= '&endatlinenb='.urlencode($endatlinenb); } if ($separator) { $param .= '&separator='.urlencode($separator); } if ($enclosure) { $param .= '&enclosure='.urlencode($enclosure); } $list = $objmodelimport->listOfAvailableImportFormat($db); llxHeader('', $langs->trans("NewImport"), $help_url); $head = import_prepare_head($param, 3); print dol_get_fiche_head($head, 'step3', '', -2); /* * Confirm delete file */ if ($action == 'delete') { print $form->formconfirm($_SERVER["PHP_SELF"].'?urlfile='.urlencode(GETPOST('urlfile')).'&step=3'.$param, $langs->trans('DeleteFile'), $langs->trans('ConfirmDeleteFile'), 'confirm_deletefile', '', 0, 1); } print '
'; print '
'; print ''; // Module print ''; print ''; // Lot de donnees a importer print ''; print ''; print '
'.$langs->trans("Module").''; $titleofmodule = $objimport->array_import_module[0]['module']->getName(); // Special case for import common to module/services if (in_array($objimport->array_import_code[0], array('produit_supplierprices', 'produit_multiprice', 'produit_languages'))) { $titleofmodule = $langs->trans("ProductOrService"); } print $titleofmodule; print '
'.$langs->trans("DatasetToImport").''; $entity = preg_replace('/:.*$/', '', $objimport->array_import_icon[0]); $entityicon = strtolower(!empty($entitytoicon[$entity]) ? $entitytoicon[$entity] : $entity); print img_object($objimport->array_import_module[0]['module']->getName(), $entityicon).' '; print $objimport->array_import_label[0]; print '
'; print '
'; print load_fiche_titre($langs->trans("InformationOnSourceFile"), '', 'file-export'); print '
'; print '
'; print ''; // Source file format print ''; print ''; print '
'.$langs->trans("SourceFileFormat").''; $text = $objmodelimport->getDriverDescForKey($format); // @phan-suppress-next-line PhanPluginSuspiciousParamPosition print $form->textwithpicto($objmodelimport->getDriverLabelForKey($format), $text); print ''; $filename = $langs->transnoentitiesnoconv("ExampleOfImportFile").'_'.$datatoimport.'.'.$format; print ''; print img_picto('', 'download', 'class="paddingright opacitymedium"'); print $langs->trans("DownloadEmptyExampleShort"); print ''; print $form->textwithpicto('', $langs->trans("DownloadEmptyExample").'.
'.$langs->trans("StarAreMandatory")); print '
'; print '
'; print dol_get_fiche_end(); if ($format == 'xlsx' && !class_exists('XMLWriter')) { $langs->load("install"); print info_admin($langs->trans("ErrorPHPDoesNotSupport", 'php-xml'), 0, 0, '1', 'error'); } print '

'; print '
'; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; $s = $langs->trans("ChooseFileToImport", '{s1}'); $s = str_replace('{s1}', img_picto('', 'next'), $s); print $s; print '

'; $filetoimport = ''; // Input file name box print '
'; $maxfilesizearray = getMaxFileSizeArray(); $maxmin = $maxfilesizearray['maxmin']; if ($maxmin > 0) { print ''; // MAX_FILE_SIZE must precede the field type=file } print '     '; $out = (!getDolGlobalString('MAIN_UPLOAD_DOC') ? ' disabled' : ''); print ''; $out = ''; if (getDolGlobalString('MAIN_UPLOAD_DOC')) { $max = getDolGlobalString('MAIN_UPLOAD_DOC'); // In Kb $maxphp = @ini_get('upload_max_filesize'); // In unknown if (preg_match('/k$/i', $maxphp)) { $maxphp = (int) substr($maxphp, 0, -1); } if (preg_match('/m$/i', $maxphp)) { $maxphp = (int) substr($maxphp, 0, -1) * 1024; } if (preg_match('/g$/i', $maxphp)) { $maxphp = (int) substr($maxphp, 0, -1) * 1024 * 1024; } if (preg_match('/t$/i', $maxphp)) { $maxphp = (int) substr($maxphp, 0, -1) * 1024 * 1024 * 1024; } $maxphp2 = @ini_get('post_max_size'); // In unknown if (preg_match('/k$/i', $maxphp2)) { $maxphp2 = (int) substr($maxphp2, 0, -1); } if (preg_match('/m$/i', $maxphp2)) { $maxphp2 = (int) substr($maxphp2, 0, -1) * 1024; } if (preg_match('/g$/i', $maxphp2)) { $maxphp2 = (int) substr($maxphp2, 0, -1) * 1024 * 1024; } if (preg_match('/t$/i', $maxphp2)) { $maxphp2 = (int) substr($maxphp2, 0, -1) * 1024 * 1024 * 1024; } // Now $max and $maxphp and $maxphp2 are in Kb $maxmin = $max; $maxphptoshow = $maxphptoshowparam = ''; if ($maxphp > 0) { $maxmin = min($max, $maxphp); $maxphptoshow = $maxphp; $maxphptoshowparam = 'upload_max_filesize'; } if ($maxphp2 > 0) { $maxmin = min($max, $maxphp2); if ($maxphp2 < $maxphp) { $maxphptoshow = $maxphp2; $maxphptoshowparam = 'post_max_size'; } } $langs->load('other'); $out .= ' '; $out .= info_admin($langs->trans("ThisLimitIsDefinedInSetup", $max, $maxphptoshow), 1); } else { $out .= ' ('.$langs->trans("UploadDisabled").')'; } print $out; print '
'; // Search available imports $filearray = dol_dir_list($conf->import->dir_temp, 'files', 0, '', '', 'name', SORT_DESC); if (count($filearray) > 0) { print '
'; // You can use div-table-responsive-no-min if you don't need reserved height for your table print ''; $dir = $conf->import->dir_temp; // Search available files to import $i = 0; foreach ($filearray as $key => $val) { $file = $val['name']; // readdir return value in ISO and we want UTF8 in memory if (!utf8_check($file)) { $file = mb_convert_encoding($file, 'UTF-8', 'ISO-8859-1'); } if (preg_match('/^\./', $file)) { continue; } $modulepart = 'import'; $urlsource = $_SERVER["PHP_SELF"].'?step='.$step.$param.'&filetoimport='.urlencode($filetoimport); $relativepath = $file; print ''; print ''; // Affiche taille fichier print ''; // Affiche date fichier print ''; // Del button print ''; // Action button print ''; print ''; } print '
'; print img_mime($file, '', 'pictofixedwidth'); print ''; print $file; print ''; print ''.dol_print_size(dol_filesize($dir.'/'.$file)).''.dol_print_date(dol_filemtime($dir.'/'.$file), 'dayhour').''.img_delete().''; print ''.img_picto($langs->trans("NewImport"), 'next', 'class="fa-15"').''; print '
'; print '
'; } print '
'; } // STEP 4: Page to make matching between source file and database fields if ($step == 4 && $datatoimport) { //var_dump($_SESSION["dol_array_match_file_to_database_select"]); $serialized_array_match_file_to_database = isset($_SESSION["dol_array_match_file_to_database_select"]) ? $_SESSION["dol_array_match_file_to_database_select"] : ''; $fieldsarray = explode(',', $serialized_array_match_file_to_database); $array_match_file_to_database = array(); // Same than $fieldsarray but with mapped value only (col1 => 's.fielda', col2 => 's.fieldb'...) foreach ($fieldsarray as $elem) { $tabelem = explode('=', $elem, 2); $key = $tabelem[0]; $val = (isset($tabelem[1]) ? $tabelem[1] : ''); if ($key && $val) { $array_match_file_to_database[$key] = $val; } } //var_dump($serialized_array_match_file_to_database); //var_dump($fieldsarray); //var_dump($array_match_file_to_database); $model = $format; $list = $objmodelimport->listOfAvailableImportFormat($db); if (empty($separator)) { $separator = (!getDolGlobalString('IMPORT_CSV_SEPARATOR_TO_USE') ? ',' : $conf->global->IMPORT_CSV_SEPARATOR_TO_USE); } // The separator has been defined, if it is a unique char, we check it is valid by reading the source file if ($model == 'csv' && strlen($separator) == 1 && !GETPOSTISSET('separator')) { '@phan-var-force ImportCsv $obj'; // Count the char in first line of file. $fh = fopen($conf->import->dir_temp.'/'.$filetoimport, 'r'); if ($fh) { $sline = fgets($fh, 1000000); fclose($fh); $nboccurence = substr_count($sline, $separator); $nboccurencea = substr_count($sline, ','); $nboccurenceb = substr_count($sline, ';'); //var_dump($nboccurence." ".$nboccurencea." ".$nboccurenceb);exit; if ($nboccurence == 0) { if ($nboccurencea > 2) { $separator = ','; } elseif ($nboccurenceb > 2) { $separator = ';'; } } } } // The value to use $separator_used = str_replace('\t', "\t", $separator); // Create class to use for import $dir = DOL_DOCUMENT_ROOT."/core/modules/import/"; $file = "import_".$model.".modules.php"; $classname = "Import".ucfirst($model); require_once $dir.$file; $obj = new $classname($db, $datatoimport); '@phan-var-force ModeleImports $obj'; if (!empty($obj->error)) { $langs->load("errors"); $param = '&datatoimport='.$datatoimport.'&format='.$format; setEventMessages($obj->error, null, 'errors'); header("Location: ".$_SERVER["PHP_SELF"].'?step=3'.$param.'&filetoimport='.urlencode($relativepath)); exit; } if ($model == 'csv') { '@phan-var-force ImportCsv $obj'; $obj->separator = $separator_used; $obj->enclosure = $enclosure; $obj->charset = ''; } if ($model == 'xlsx') { '@phan-var-force ImportXlsx $obj'; if (!preg_match('/\.xlsx$/i', $filetoimport)) { $langs->load("errors"); $param = '&datatoimport='.$datatoimport.'&format='.$format; setEventMessages($langs->trans("ErrorFileMustHaveFormat", $model), null, 'errors'); header("Location: ".$_SERVER["PHP_SELF"].'?step=3'.$param.'&filetoimport='.urlencode($relativepath)); exit; } } if (GETPOST('update')) { $array_match_file_to_database = array(); } // Load the source fields from input file into variable $arrayrecord $fieldssource = array(); /** @var array $fieldssource */ $result = $obj->import_open_file($conf->import->dir_temp.'/'.$filetoimport); if ($result >= 0) { // Read first line $arrayrecord = $obj->import_read_record(); // Create array $fieldssource starting with 1 with values found of first line. $i = 1; foreach ($arrayrecord as $key => $val) { if ($val["type"] != -1) { $fieldssource[$i]['example1'] = dol_trunc($val['val'], 128); $i++; } else { $fieldssource[$i]['example1'] = $langs->trans('Empty'); $i++; } $fieldssource[$i]['imported'] = 0; } $obj->import_close_file(); } // Load targets fields in database $fieldstarget = $objimport->array_import_fields[0]; $minpos = min(count($fieldssource), count($fieldstarget)); //var_dump($array_match_file_to_database); $initialloadofstep4 = false; if (empty($_SESSION['dol_array_match_file_to_database_select'])) { $initialloadofstep4 = true; } // Is it a first time in page (if yes, we must initialize array_match_file_to_database) if (count($array_match_file_to_database) == 0) { // This is first input in screen, we need to define // $array_match_file_to_database // $serialized_array_match_file_to_database // $_SESSION["dol_array_match_file_to_database"] $pos = 1; $num = count($fieldssource); while ($pos <= $num) { if ($num >= 1 && $pos <= $num) { $posbis = 1; foreach ($fieldstarget as $key => $val) { if ($posbis < $pos) { $posbis++; continue; } // We found the key of targets that is at position pos $array_match_file_to_database[$pos] = $key; break; } } $pos++; } } $array_match_database_to_file = array_flip($array_match_file_to_database); //var_dump($array_match_database_to_file); //var_dump($_SESSION["dol_array_match_file_to_database_select"]); $fieldstarget_tmp = array(); $arraykeysfieldtarget = array_keys($fieldstarget); $position = 0; foreach ($fieldstarget as $key => $label) { $isrequired = preg_match('/\*$/', $label); if (!empty($isrequired)) { $newlabel = substr($label, 0, -1); $fieldstarget_tmp[$key] = array("label" => $newlabel, "required" => true); } else { $fieldstarget_tmp[$key] = array("label" => $label, "required" => false); } if (!empty($array_match_database_to_file[$key])) { $fieldstarget_tmp[$key]["imported"] = true; $fieldstarget_tmp[$key]["position"] = (int) $array_match_database_to_file[$key] - 1; $keytoswap = $key; while (!empty($array_match_database_to_file[$keytoswap])) { if ($position + 1 > $array_match_database_to_file[$keytoswap]) { $keytoswapwith = $array_match_database_to_file[$keytoswap] - 1; $tmp = [$keytoswap => $fieldstarget_tmp[$keytoswap]]; unset($fieldstarget_tmp[$keytoswap]); $fieldstarget_tmp = arrayInsert($fieldstarget_tmp, $keytoswapwith, $tmp); $keytoswapwith = $arraykeysfieldtarget[$array_match_database_to_file[$keytoswap] - 1]; $tmp = $fieldstarget_tmp[$keytoswapwith]; unset($fieldstarget_tmp[$keytoswapwith]); $fieldstarget_tmp[$keytoswapwith] = $tmp; $keytoswap = $keytoswapwith; } else { break; } } } else { $fieldstarget_tmp[$key]["imported"] = false; } $position++; } $fieldstarget = $fieldstarget_tmp; //print $serialized_array_match_file_to_database; //print $_SESSION["dol_array_match_file_to_database"]; //print $_SESSION["dol_array_match_file_to_database_select"]; //var_dump($array_match_file_to_database);exit; // Now $array_match_file_to_database contains fieldnb(1,2,3...)=>fielddatabase(key in $array_match_file_to_database) $param = '&format='.$format.'&datatoimport='.urlencode($datatoimport).'&filetoimport='.urlencode($filetoimport); if ($excludefirstline) { $param .= '&excludefirstline='.urlencode($excludefirstline); } if ($endatlinenb) { $param .= '&endatlinenb='.urlencode($endatlinenb); } if ($separator) { $param .= '&separator='.urlencode($separator); } if ($enclosure) { $param .= '&enclosure='.urlencode($enclosure); } llxHeader('', $langs->trans("NewImport"), $help_url); $head = import_prepare_head($param, 4); print dol_get_fiche_head($head, 'step4', '', -2); print '
'; print '
'; print ''; // Module print ''; print ''; // Lot de donnees a importer print ''; print ''; print '
'.$langs->trans("Module").''; $titleofmodule = $objimport->array_import_module[0]['module']->getName(); // Special case for import common to module/services if (in_array($objimport->array_import_code[0], array('produit_supplierprices', 'produit_multiprice', 'produit_languages'))) { $titleofmodule = $langs->trans("ProductOrService"); } print $titleofmodule; print '
'.$langs->trans("DatasetToImport").''; $entity = preg_replace('/:.*$/', '', $objimport->array_import_icon[0]); $entityicon = strtolower(!empty($entitytoicon[$entity]) ? $entitytoicon[$entity] : $entity); print img_object($objimport->array_import_module[0]['module']->getName(), $entityicon).' '; print $objimport->array_import_label[0]; print '
'; print '
'; print load_fiche_titre($langs->trans("InformationOnSourceFile"), '', 'file-export'); print '
'; print '
'; print ''; // Source file format print ''; print ''; // Separator and enclosure if ($model == 'csv') { '@phan-var-force ImportCsv $obj'; print ''; print ''; } // File to import print ''; print ''; print '
'.$langs->trans("SourceFileFormat").''; $text = $objmodelimport->getDriverDescForKey($format); // @phan-suppress-next-line PhanPluginSuspiciousParamPosition print $form->textwithpicto($objmodelimport->getDriverLabelForKey($format), $text); print '
'.$langs->trans("CsvOptions").''; print '
'; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print $langs->trans("Separator").' : '; print ''; print '    '.$langs->trans("Enclosure").' : '; print ' '; print ''; print '
'; print '
'.$langs->trans("FileToImport").''; $modulepart = 'import'; $relativepath = GETPOST('filetoimport'); print ''; print img_mime($file, '', 'pictofixedwidth'); print $filetoimport; print img_picto($langs->trans("Download"), 'download', 'class="paddingleft opacitymedium"'); print ''; print '
'; print '
'; print dol_get_fiche_end(); print '
'."\n"; // List of source fields print ''."\n"; print '
'; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; // Import profile to use/load print '
'; print ''; $s = $langs->trans("SelectImportFieldsSource", '{s1}'); $s = str_replace('{s1}', img_picto('', 'grip_title', '', 0, 0, 0, '', '', 0), $s); print $s; print ' '; $htmlother->select_import_model($importmodelid, 'importmodelid', $datatoimport, 1, $user->id); print ''; print '
'; print '
'; // Title of array with fields print '
'; // You can use div-table-responsive-no-min if you don't need reserved height for your table print ''; print ''; print ''; print ''; print ''; //var_dump($array_match_file_to_database); print ''; // Lines for remark print ''; print ''; print '
'.$langs->trans("FieldsInSourceFile").''.$langs->trans("FieldsInTargetDatabase").'
'; $fieldsplaced = array(); $valforsourcefieldnb = array(); $listofkeys = array(); foreach ($array_match_file_to_database as $key => $val) { $listofkeys[$key] = 1; } print "\n\n"; print '
'."\n"; // List of source fields $lefti = 1; foreach ($fieldssource as $key => $val) { // @phan-suppress-next-line PhanPluginSuspiciousParamPosition show_elem($fieldssource, $key, $val); // key is field number in source file $listofkeys[$key] = 1; $fieldsplaced[$key] = 1; $valforsourcefieldnb[$lefti] = $key; $lefti++; /*if ($lefti > count($fieldstarget)) { break; // Other fields are in the not imported area }*/ } //var_dump($valforsourcefieldnb); print "
\n"; print "\n"; print '
'; // Set the list of all possible target fields in Dolibarr. $optionsall = array(); foreach ($fieldstarget as $code => $line) { $tmparray = explode('|', $line["label"]); // If label of field is several translation keys separated with | $labeltoshow = ''; foreach ($tmparray as $tmpkey => $tmpval) { $labeltoshow .= ($labeltoshow ? ' '.$langs->trans('or').' ' : '').$langs->transnoentities($tmpval); } // TODO Get type from a new array into module descriptor. // $picto = 'email'; $picto = ''; $optionsall[$code] = array( 'labelkey' => $line['label'], 'labelkeyarray' => $tmparray, 'label' => $labeltoshow, 'required' => (empty($line["required"]) ? 0 : 1), 'position' => (!empty($line['position']) ? $line['position'] : 0), 'picto' => $picto, ); } // $optionsall is an array of all possible target fields. key=>array('label'=>..., 'xxx') $height = '32px'; //needs px for css height attribute below $i = 0; $mandatoryfieldshavesource = true; //var_dump($fieldstarget); //var_dump($optionsall); //exit; //var_dump($_SESSION['dol_array_match_file_to_database']); //var_dump($_SESSION['dol_array_match_file_to_database_select']); //exit; //var_dump($optionsall); //var_dump($fieldssource); //var_dump($fieldstarget); $modetoautofillmapping = 'session'; // Use setup in session if ($initialloadofstep4) { $modetoautofillmapping = 'guess'; } //var_dump($modetoautofillmapping); print ''; foreach ($fieldssource as $code => $line) { // $fieldssource is an array code=column num, line=content on first line for column in source file. /*if ($i == $minpos) { break; }*/ print ''; // Note: $code is int, but index should be fieldname? -> @phan-suppress-next-line PhanTypeMismatchDimFetch $entity = (!empty($objimport->array_import_entities[0][$code]) ? $objimport->array_import_entities[0][$code] : $objimport->array_import_icon[0]); $entityicon = !empty($entitytoicon[$entity]) ? $entitytoicon[$entity] : $entity; // $entityicon must string name of picto of the field like 'project', 'company', 'contact', 'modulename', ... $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', 'MyModyle', ... print ''; print ''; // Tooltip at end of line print ''; print ''; $i++; } print '
=> '; $selectforline = ''; $selectforline .= ''; $selectforline .= ajax_combobox('selectorderimport_'.($i + 1)); print $selectforline; print ''; // Source field info $htmltext = ''.$langs->trans("FieldSource").'
'; $filecolumntoshow = num2Alpha($i); $htmltext .= $langs->trans("DataComeFromFileFieldNb", $filecolumntoshow).'
'; print $form->textwithpicto('', $htmltext); print '
'; print '
'.$langs->trans("Note").'
'; print '
'; if (!empty($conf->use_javascript_ajax)) { print ''."\n"; } /* * Action bar */ print '
'; if (count($array_match_file_to_database)) { if ($mandatoryfieldshavesource) { print ''.$langs->trans("NextStep").''; } else { print ''.$langs->trans("NextStep").''; } } print '
'; // Area for profils import if (count($array_match_file_to_database)) { print '
'."\n"; print ''."\n"; print '
'.$langs->trans("SaveImportModel").'
'; print '
'; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print '
'; // You can use div-table-responsive-no-min if you don't need reserved height for your table print ''; print ''; print ''; print ''; print ''; print ''; $nameofimportprofile = str_replace(' ', '-', $langs->trans("ImportProfile").' '.$titleofmodule.' '.dol_print_date(dol_now('gmt'), 'dayxcard')); if (GETPOST('import_name')) { // If we have submitted a form, we take value used for the update try $nameofimportprofile = $import_name; } print ''; print ''; print ''; print ''; // List of existing import profils $sql = "SELECT rowid, label, fk_user, entity"; $sql .= " FROM ".MAIN_DB_PREFIX."import_model"; $sql .= " WHERE type = '".$db->escape($datatoimport)."'"; if (!getDolGlobalString('EXPORTS_SHARE_MODELS')) { // EXPORTS_SHARE_MODELS means all templates are visible, whatever is owner. $sql .= " AND fk_user IN (0, ".((int) $user->id).")"; } $sql .= " ORDER BY rowid"; $resql = $db->query($sql); if ($resql) { $num = $db->num_rows($resql); $tmpuser = new User($db); $i = 0; while ($i < $num) { $obj = $db->fetch_object($resql); print ''; print ''; print ''; $i++; } } else { dol_print_error($db); } print '
'.$langs->trans("ImportModelName").''.$langs->trans("Visibility").'
'; $arrayvisibility = array('private' => $langs->trans("Private"), 'all' => $langs->trans("Everybody")); print $form->selectarray('visibility', $arrayvisibility, 'private'); print ''; print ''; print '
'; print $obj->label; print ''; if (empty($obj->fk_user)) { print $langs->trans("Everybody"); } else { $tmpuser->fetch($obj->fk_user); print $tmpuser->getNomUrl(-1); } print ''; print 'rowid.'&filetoimport='.urlencode($filetoimport).'">'; print img_delete(); print ''; print '
'; print '
'; print '
'; } } // STEP 5: Summary of choices and launch simulation if ($step == 5 && $datatoimport) { $max_execution_time_for_importexport = getDolGlobalInt('IMPORT_MAX_EXECUTION_TIME', 300); // 5mn if not defined $max_time = @ini_get("max_execution_time"); if ($max_time && $max_time < $max_execution_time_for_importexport) { 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."); @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 } $model = $format; $list = $objmodelimport->listOfAvailableImportFormat($db); // Create class to use for import $dir = DOL_DOCUMENT_ROOT."/core/modules/import/"; $file = "import_".$model.".modules.php"; $classname = "Import".ucfirst($model); require_once $dir.$file; $obj = new $classname($db, $datatoimport); '@phan-var-force ModeleImports $obj'; if ($model == 'csv') { '@phan-var-force ImportCsv $obj'; $obj->separator = $separator_used; $obj->enclosure = $enclosure; } // Load source fields in input file $fieldssource = array(); $result = $obj->import_open_file($conf->import->dir_temp.'/'.$filetoimport); if ($result >= 0) { // Read first line $arrayrecord = $obj->import_read_record(); // Put into array fieldssource starting with 1. $i = 1; foreach ($arrayrecord as $key => $val) { $fieldssource[$i]['example1'] = dol_trunc($val['val'], 24); $i++; } $obj->import_close_file(); } $nboflines = $obj->import_get_nb_of_lines($conf->import->dir_temp.'/'.$filetoimport); $param = '&leftmenu=import&format='.urlencode($format).'&datatoimport='.urlencode($datatoimport).'&filetoimport='.urlencode($filetoimport).'&nboflines='.((int) $nboflines).'&separator='.urlencode($separator).'&enclosure='.urlencode($enclosure); $param2 = $param; // $param2 = $param without excludefirstline and endatlinenb if ($excludefirstline) { $param .= '&excludefirstline='.urlencode($excludefirstline); } if ($endatlinenb) { $param .= '&endatlinenb='.urlencode($endatlinenb); } if (!empty($updatekeys)) { $param .= '&updatekeys[]='.implode('&updatekeys[]=', $updatekeys); } llxHeader('', $langs->trans("NewImport"), $help_url); $head = import_prepare_head($param, 5); print '
'; print ''; print ''; // step 5 print ''; // step 5 print dol_get_fiche_head($head, 'step5', '', -2); print '
'; print '
'; print ''; // Module print ''; print ''; // Lot de donnees a importer print ''; print ''; print '
'.$langs->trans("Module").''; $titleofmodule = $objimport->array_import_module[0]['module']->getName(); // Special case for import common to module/services if (in_array($objimport->array_import_code[0], array('produit_supplierprices', 'produit_multiprice', 'produit_languages'))) { $titleofmodule = $langs->trans("ProductOrService"); } print $titleofmodule; print '
'.$langs->trans("DatasetToImport").''; $entity = preg_replace('/:.*$/', '', $objimport->array_import_icon[0]); $entityicon = strtolower(!empty($entitytoicon[$entity]) ? $entitytoicon[$entity] : $entity); print img_object($objimport->array_import_module[0]['module']->getName(), $entityicon).' '; print $objimport->array_import_label[0]; print '
'; print '
'; print load_fiche_titre($langs->trans("InformationOnSourceFile"), '', 'file-export'); print '
'; print '
'; print ''; // Source file format print ''; print ''; // Separator and enclosure if ($model == 'csv') { '@phan-var-force ImportCsv $obj'; print ''; print ''; } // File to import print ''; print ''; // Total lines in source file print ''; // Range of lines to import print ''; // Keys for data UPDATE (not INSERT of new data) print ''; print '
'.$langs->trans("SourceFileFormat").''; $text = $objmodelimport->getDriverDescForKey($format); // @phan-suppress-next-line PhanPluginSuspiciousParamPosition print $form->textwithpicto($objmodelimport->getDriverLabelForKey($format), $text); print '
'.$langs->trans("CsvOptions").''; print $langs->trans("Separator").' : '.dol_escape_htmltag($separator); print '    '.$langs->trans("Enclosure").' : '.dol_escape_htmltag($enclosure); print '
'.$langs->trans("FileToImport").''; $modulepart = 'import'; $relativepath = GETPOST('filetoimport'); print ''; print img_mime($file, '', 'pictofixedwidth'); print $filetoimport; print img_picto($langs->trans("Download"), 'download', 'class="paddingleft opacitymedium"'); print ''; print '
'; print $langs->trans("NbOfSourceLines"); print ''; print $nboflines; print '
'; print $langs->trans("ImportFromToLine"); print ''; if ($action == 'launchsimu') { print ''; print ''; } else { print ''; print $form->textwithpicto("", $langs->trans("SetThisValueTo2ToExcludeFirstLine")); } print ' - '; if ($action == 'launchsimu') { print ''; print ''; } else { print ''; print $form->textwithpicto("", $langs->trans("KeepEmptyToGoToEndOfFile")); } if ($action == 'launchsimu') { print '   '.$langs->trans("Modify").''; } if ($excludefirstline == 2) { print $form->textwithpicto("", $langs->trans("WarningFirstImportedLine", $excludefirstline), 1, 'warning', "warningexcludefirstline"); print ''; } print '
'; print $form->textwithpicto($langs->trans("KeysToUseForUpdates"), $langs->trans("SelectPrimaryColumnsForUpdateAttempt")); print ''; if ($action == 'launchsimu') { if (count($updatekeys)) { print $form->multiselectarray('updatekeysbis', $objimport->array_import_updatekeys[0], $updatekeys, 0, 0, '', 1, '80%', 'disabled'); } else { print ''.$langs->trans("NoUpdateAttempt").'   -'; } foreach ($updatekeys as $val) { print ''; } print '   '.$langs->trans("Modify").''; } else { if (is_array($objimport->array_import_updatekeys[0]) && count($objimport->array_import_updatekeys[0])) { //TODO dropdown UL is created inside nested SPANS print $form->multiselectarray('updatekeys', $objimport->array_import_updatekeys[0], $updatekeys, 0, 0, '', 1, '80%'); //print $form->textwithpicto("", $langs->trans("SelectPrimaryColumnsForUpdateAttempt")); } else { print ''.$langs->trans("UpdateNotYetSupportedForThisImport").''; } } /*echo '
';
	print_r($objimport->array_import_updatekeys);
	echo '
';*/ print '
'; print '
'; print load_fiche_titre($langs->trans("InformationOnTargetTables"), '', 'file-import'); print '
'; print '
'; print ''; // Tables imported print ''; // Fields imported print ''; print '
'; print $langs->trans("TablesTarget"); print ''; $listtables = array(); $sort_array_match_file_to_database = $array_match_file_to_database; foreach ($array_match_file_to_database as $code => $label) { //var_dump($fieldssource); if ($code > count($fieldssource)) { continue; } //print $code.'-'.$label; $alias = preg_replace('/(\..*)$/i', '', $label); $listtables[$alias] = $objimport->array_import_tables[0][$alias]; } if (count($listtables)) { $newval = ''; //ksort($listtables); foreach ($listtables as $val) { if ($newval) { print ', '; } $newval = $val; // Link to Dolibarr wiki pages /*$helppagename='EN:Table_'.$newval; if ($helppagename && empty($conf->global->MAIN_HELP_DISABLELINK)) { // Get helpbaseurl, helppage and mode from helppagename and langs $arrayres=getHelpParamFor($helppagename,$langs); $helpbaseurl=$arrayres['helpbaseurl']; $helppage=$arrayres['helppage']; $mode=$arrayres['mode']; $newval.=' '.img_picto($langs->trans($mode == 'wiki' ? 'GoToWikiHelpPage': 'GoToHelpPage'),DOL_URL_ROOT.'/theme/common/helpdoc.png','',1).''; }*/ print $newval; } } else { print $langs->trans("Error"); } print '
'; print $langs->trans("FieldsTarget").''; $listfields = array(); $i = 0; //print 'fieldsource='.$fieldssource; $sort_array_match_file_to_database = $array_match_file_to_database; ksort($sort_array_match_file_to_database); //var_dump($sort_array_match_file_to_database); foreach ($sort_array_match_file_to_database as $code => $label) { $i++; //var_dump($fieldssource); if ($code > count($fieldssource)) { continue; } //print $code.'-'.$label; $alias = preg_replace('/(\..*)$/i', '', $label); $listfields[$i] = ''.$langs->trans("Column").' '.num2Alpha((int) $code - 1).' -> '.$label.''; } print count($listfields) ? (implode(', ', $listfields)) : $langs->trans("Error"); print '
'; print '
'; print dol_get_fiche_end(); if ($action != 'launchsimu') { // Show import id print '
'; print $langs->trans("NowClickToTestTheImport", $langs->transnoentitiesnoconv("RunSimulateImportFile")).'
'; print '
'; // Actions print '
'; if ($user->hasRight('import', 'run')) { print ''; } else { print ''.$langs->trans("RunSimulateImportFile").''; } print '
'; } else { // Launch import $arrayoferrors = array(); $arrayofwarnings = array(); $maxnboferrors = !getDolGlobalString('IMPORT_MAX_NB_OF_ERRORS') ? 50 : $conf->global->IMPORT_MAX_NB_OF_ERRORS; $maxnbofwarnings = !getDolGlobalString('IMPORT_MAX_NB_OF_WARNINGS') ? 50 : $conf->global->IMPORT_MAX_NB_OF_WARNINGS; $nboferrors = 0; $nbofwarnings = 0; $importid = dol_print_date(dol_now(), '%Y%m%d%H%M%S'); //var_dump($array_match_file_to_database); $db->begin(); // Open input file $nbok = 0; $pathfile = $conf->import->dir_temp.'/'.$filetoimport; $result = $obj->import_open_file($pathfile); if ($result > 0) { global $tablewithentity_cache; $tablewithentity_cache = array(); $sourcelinenb = 0; $endoffile = 0; // Loop on each input file record while (($sourcelinenb < $nboflines) && !$endoffile) { $sourcelinenb++; // Read line and store it into $arrayrecord //dol_syslog("line ".$sourcelinenb.' - '.$nboflines.' - '.$excludefirstline.' - '.$endatlinenb); $arrayrecord = $obj->import_read_record(); if ($arrayrecord === false) { $arrayofwarnings[$sourcelinenb][0] = array('lib' => 'File has '.$nboflines.' lines. However we reach the end of file or an empty line at record '.$sourcelinenb.'. This may occurs when some records are split onto several lines and not correctly delimited by the "Char delimiter", or if there is line with no data on all fields.', 'type' => 'EOF_RECORD_ON_SEVERAL_LINES'); $endoffile++; continue; } if ($excludefirstline && ($sourcelinenb < $excludefirstline)) { continue; } if ($endatlinenb && ($sourcelinenb > $endatlinenb)) { break; } $parameters = array( 'step' => $step, 'datatoimport' => $datatoimport, 'obj' => &$obj, 'arrayrecord' => $arrayrecord, 'array_match_file_to_database' => $array_match_file_to_database, 'objimport' => $objimport, 'fieldssource' => $fieldssource, 'importid' => $importid, 'updatekeys' => $updatekeys, 'arrayoferrors' => &$arrayoferrors, 'arrayofwarnings' => &$arrayofwarnings, 'nbok' => &$nbok, ); $reshook = $hookmanager->executeHooks('ImportInsert', $parameters); if ($reshook < 0) { $arrayoferrors[$sourcelinenb][] = [ 'lib' => implode("
", array_merge([$hookmanager->error], $hookmanager->errors)) ]; } if (empty($reshook)) { // Run import $result = $obj->import_insert($arrayrecord, $array_match_file_to_database, $objimport, count($fieldssource), $importid, $updatekeys); if (count($obj->errors)) { $arrayoferrors[$sourcelinenb] = $obj->errors; } if (count($obj->warnings)) { $arrayofwarnings[$sourcelinenb] = $obj->warnings; } if (!count($obj->errors) && !count($obj->warnings)) { $nbok++; } } } // Close file $obj->import_close_file(); } else { print $langs->trans("ErrorFailedToOpenFile", $pathfile); } $error = 0; // Run the sql after import if defined //var_dump($objimport->array_import_run_sql_after[0]); if (!empty($objimport->array_import_run_sql_after[0]) && is_array($objimport->array_import_run_sql_after[0])) { $i = 0; foreach ($objimport->array_import_run_sql_after[0] as $sqlafterimport) { $i++; $resqlafterimport = $db->query($sqlafterimport); if (!$resqlafterimport) { $arrayoferrors['none'][] = array('lib' => $langs->trans("Error running final request: ".$sqlafterimport)); $error++; } } } $db->rollback(); // We force rollback because this was just a simulation. // Show OK if (!count($arrayoferrors) && !count($arrayofwarnings)) { print '
'; print '
'; print '
'.$langs->trans("ResultOfSimulationNoError").'
'; print $langs->trans("NbInsertSim", empty($obj->nbinsert) ? 0 : $obj->nbinsert).'
'; print $langs->trans("NbUpdateSim", empty($obj->nbupdate) ? 0 : $obj->nbupdate).'
'; print '
'; print '
'; } else { print '
'; print '
'; print $langs->trans("NbOfLinesOK", $nbok).'...
'; print '
'; print '
'; } // Show Errors //var_dump($arrayoferrors); if (count($arrayoferrors)) { print img_error().' '.$langs->trans("ErrorsOnXLines", count($arrayoferrors)).'
'; print '
'; foreach ($arrayoferrors as $key => $val) { $nboferrors++; if ($nboferrors > $maxnboferrors) { print $langs->trans("TooMuchErrors", (count($arrayoferrors) - $nboferrors))."
"; break; } print '* '.$langs->trans("Line").' '.dol_escape_htmltag($key).'
'; foreach ($val as $i => $err) { print '     > '.dol_escape_htmltag($err['lib']).'
'; } } print '
'; print '
'; } // Show Warnings //var_dump($arrayoferrors); if (count($arrayofwarnings)) { print img_warning().' '.$langs->trans("WarningsOnXLines", count($arrayofwarnings)).'
'; print '
'; foreach ($arrayofwarnings as $key => $val) { $nbofwarnings++; if ($nbofwarnings > $maxnbofwarnings) { print $langs->trans("TooMuchWarnings", (count($arrayofwarnings) - $nbofwarnings))."
"; break; } print ' * '.$langs->trans("Line").' '.dol_escape_htmltag((string) $key).'
'; foreach ($val as $i => $err) { print '     > '.dol_escape_htmltag($err['lib']).'
'; } } print '
'; print '
'; } // Show import id $importid = dol_print_date(dol_now(), '%Y%m%d%H%M%S'); print '
'; print ''.$langs->trans("NowClickToRunTheImport", $langs->transnoentitiesnoconv("RunImportFile")).'
'; /*if (empty($nboferrors)) { print $langs->trans("DataLoadedWithId", $importid).'
'; }*/ print '
'; print '
'; // Actions print '
'; if ($user->hasRight('import', 'run')) { if (empty($nboferrors)) { print ''.$langs->trans("RunImportFile").''; } else { //print ''; print ''.$langs->trans("RunImportFile").''; } } else { print ''.$langs->trans("RunSimulateImportFile").''; print ''.$langs->trans("RunImportFile").''; } print '
'; } print '
'; } // STEP 6: Real import if ($step == 6 && $datatoimport) { $max_execution_time_for_importexport = getDolGlobalInt('IMPORT_MAX_EXECUTION_TIME', 300); // 5mn if not defined $max_time = @ini_get("max_execution_time"); if ($max_time && $max_time < $max_execution_time_for_importexport) { 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."); @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 } $model = $format; $list = $objmodelimport->listOfAvailableImportFormat($db); $importid = GETPOST("importid", 'alphanohtml'); // Create class to use for import $dir = DOL_DOCUMENT_ROOT."/core/modules/import/"; $file = "import_".$model.".modules.php"; $classname = "Import".ucfirst($model); require_once $dir.$file; $obj = new $classname($db, $datatoimport); '@phan-var-force ModeleImports $obj'; if ($model == 'csv') { '@phan-var-force ImportCsv $obj'; $obj->separator = $separator_used; $obj->enclosure = $enclosure; } // Load source fields in input file $fieldssource = array(); $result = $obj->import_open_file($conf->import->dir_temp.'/'.$filetoimport); if ($result >= 0) { // Read first line $arrayrecord = $obj->import_read_record(); // Put into array fieldssource starting with 1. $i = 1; foreach ($arrayrecord as $key => $val) { $fieldssource[$i]['example1'] = dol_trunc($val['val'], 24); $i++; } $obj->import_close_file(); } $nboflines = (GETPOSTISSET("nboflines") ? GETPOSTINT("nboflines") : dol_count_nb_of_line($conf->import->dir_temp.'/'.$filetoimport)); $param = '&format='.$format.'&datatoimport='.urlencode($datatoimport).'&filetoimport='.urlencode($filetoimport).'&nboflines='.((int) $nboflines); if ($excludefirstline) { $param .= '&excludefirstline='.urlencode($excludefirstline); } if ($endatlinenb) { $param .= '&endatlinenb='.urlencode($endatlinenb); } if ($separator) { $param .= '&separator='.urlencode($separator); } if ($enclosure) { $param .= '&enclosure='.urlencode($enclosure); } llxHeader('', $langs->trans("NewImport"), $help_url); $head = import_prepare_head($param, 6); print dol_get_fiche_head($head, 'step6', '', -1); print '
'; print '
'; print ''; // Module print ''; print ''; // Lot de donnees a importer print ''; print ''; print '
'.$langs->trans("Module").''; $titleofmodule = $objimport->array_import_module[0]['module']->getName(); // Special case for import common to module/services if (in_array($objimport->array_import_code[0], array('produit_supplierprices', 'produit_multiprice', 'produit_languages'))) { $titleofmodule = $langs->trans("ProductOrService"); } print $titleofmodule; print '
'.$langs->trans("DatasetToImport").''; $entity = preg_replace('/:.*$/', '', $objimport->array_import_icon[0]); $entityicon = strtolower(!empty($entitytoicon[$entity]) ? $entitytoicon[$entity] : $entity); print img_object($objimport->array_import_module[0]['module']->getName(), $entityicon).' '; print $objimport->array_import_label[0]; print '
'; print '
'; print load_fiche_titre($langs->trans("InformationOnSourceFile"), '', 'file-export'); print '
'; print '
'; print ''; // Source file format print ''; print ''; // Separator and enclosure if ($model == 'csv') { '@phan-var-force ImportCsv $obj'; print ''; print ''; } // File to import print ''; print ''; // Nb of fields print ''; // Do not import first lines print ''; // Do not import end lines print ''; print '
'.$langs->trans("SourceFileFormat").''; $text = $objmodelimport->getDriverDescForKey($format); // @phan-suppress-next-line PhanPluginSuspiciousParamPosition print $form->textwithpicto($objmodelimport->getDriverLabelForKey($format), $text); print '
'.$langs->trans("CsvOptions").''; print $langs->trans("Separator").' : '; print htmlentities($separator); print '    '.$langs->trans("Enclosure").' : '; print htmlentities($enclosure); print '
'.$langs->trans("FileToImport").''; $modulepart = 'import'; $relativepath = GETPOST('filetoimport'); print ''; print img_mime($file, '', 'pictofixedwidth'); print $filetoimport; print ''; print '
'; print $langs->trans("NbOfSourceLines"); print ''; print $nboflines; print '
'; print $langs->trans("ImportFromLine"); print ''; print ''; print '
'; print $langs->trans("EndAtLineNb"); print ''; print ''; print '
'; print '
'; print '
'; print ''.$langs->trans("InformationOnTargetTables").''; print '
'; print '
'; print ''; // Tables imported print ''; // Fields imported print ''; print '
'; print $langs->trans("TablesTarget"); print ''; $listtables = array(); foreach ($array_match_file_to_database as $code => $label) { //var_dump($fieldssource); if ($code > count($fieldssource)) { continue; } //print $code.'-'.$label; $alias = preg_replace('/(\..*)$/i', '', $label); $listtables[$alias] = $objimport->array_import_tables[0][$alias]; } if (count($listtables)) { $newval = ''; foreach ($listtables as $val) { if ($newval) { print ', '; } $newval = $val; // Link to Dolibarr wiki pages /*$helppagename='EN:Table_'.$newval; if ($helppagename && empty($conf->global->MAIN_HELP_DISABLELINK)) { // Get helpbaseurl, helppage and mode from helppagename and langs $arrayres=getHelpParamFor($helppagename,$langs); $helpbaseurl=$arrayres['helpbaseurl']; $helppage=$arrayres['helppage']; $mode=$arrayres['mode']; $newval.=' '.img_picto($langs->trans($mode == 'wiki' ? 'GoToWikiHelpPage': 'GoToHelpPage'),DOL_URL_ROOT.'/theme/common/helpdoc.png','',1).''; }*/ print $newval; } } else { print $langs->trans("Error"); } print '
'; print $langs->trans("FieldsTarget").''; $listfields = array(); $i = 0; $sort_array_match_file_to_database = $array_match_file_to_database; ksort($sort_array_match_file_to_database); //var_dump($sort_array_match_file_to_database); foreach ($sort_array_match_file_to_database as $code => $label) { $i++; //var_dump($fieldssource); if ($code > count($fieldssource)) { continue; } //print $code.'-'.$label; $alias = preg_replace('/(\..*)$/i', '', $label); $listfields[$i] = $langs->trans("Field").' '.$code.'->'.$label; } print count($listfields) ? (implode(', ', $listfields)) : $langs->trans("Error"); print '
'; print '
'; // Launch import $arrayoferrors = array(); $arrayofwarnings = array(); $maxnboferrors = !getDolGlobalString('IMPORT_MAX_NB_OF_ERRORS') ? 50 : $conf->global->IMPORT_MAX_NB_OF_ERRORS; $maxnbofwarnings = !getDolGlobalString('IMPORT_MAX_NB_OF_WARNINGS') ? 50 : $conf->global->IMPORT_MAX_NB_OF_WARNINGS; $nboferrors = 0; $nbofwarnings = 0; $importid = dol_print_date(dol_now(), '%Y%m%d%H%M%S'); //var_dump($array_match_file_to_database); $db->begin(); // Open input file $nbok = 0; $pathfile = $conf->import->dir_temp.'/'.$filetoimport; $result = $obj->import_open_file($pathfile); if ($result > 0) { global $tablewithentity_cache; $tablewithentity_cache = array(); $sourcelinenb = 0; $endoffile = 0; while ($sourcelinenb < $nboflines && !$endoffile) { $sourcelinenb++; $arrayrecord = $obj->import_read_record(); if ($arrayrecord === false) { $arrayofwarnings[$sourcelinenb][0] = array('lib' => 'File has '.$nboflines.' lines. However we reach the end of file or an empty line at record '.$sourcelinenb.'. This may occurs when some records are split onto several lines and not correctly delimited by the "Char delimiter", or if there is line with no data on all fields.', 'type' => 'EOF_RECORD_ON_SEVERAL_LINES'); $endoffile++; continue; } if ($excludefirstline && ($sourcelinenb < $excludefirstline)) { continue; } if ($endatlinenb && ($sourcelinenb > $endatlinenb)) { break; } $parameters = array( 'step' => $step, 'datatoimport' => $datatoimport, 'obj' => &$obj, 'arrayrecord' => $arrayrecord, 'array_match_file_to_database' => $array_match_file_to_database, 'objimport' => $objimport, 'fieldssource' => $fieldssource, 'importid' => $importid, 'updatekeys' => $updatekeys, 'arrayoferrors' => &$arrayoferrors, 'arrayofwarnings' => &$arrayofwarnings, 'nbok' => &$nbok, ); $reshook = $hookmanager->executeHooks('ImportInsert', $parameters); if ($reshook < 0) { $arrayoferrors[$sourcelinenb][] = [ 'lib' => implode("
", array_merge([$hookmanager->error], $hookmanager->errors)) ]; } if (empty($reshook)) { // Run import $result = $obj->import_insert($arrayrecord, $array_match_file_to_database, $objimport, count($fieldssource), $importid, $updatekeys); if (count($obj->errors)) { $arrayoferrors[$sourcelinenb] = $obj->errors; } if (count($obj->warnings)) { $arrayofwarnings[$sourcelinenb] = $obj->warnings; } if (!count($obj->errors) && !count($obj->warnings)) { $nbok++; } } $reshook = $hookmanager->executeHooks('AfterImportInsert', $parameters); if ($reshook < 0) { $arrayoferrors[$sourcelinenb][] = [ 'lib' => implode("
", array_merge([$hookmanager->error], $hookmanager->errors)) ]; } } // Close file $obj->import_close_file(); } else { print $langs->trans("ErrorFailedToOpenFile", $pathfile); } if (count($arrayoferrors) > 0) { $db->rollback(); // We force rollback because this was errors. } else { $error = 0; // Run the sql after import if defined //var_dump($objimport->array_import_run_sql_after[0]); if (!empty($objimport->array_import_run_sql_after[0]) && is_array($objimport->array_import_run_sql_after[0])) { $i = 0; foreach ($objimport->array_import_run_sql_after[0] as $sqlafterimport) { $i++; $resqlafterimport = $db->query($sqlafterimport); if (!$resqlafterimport) { $arrayoferrors['none'][] = array('lib' => $langs->trans("Error running final request: ".$sqlafterimport)); $error++; } } } if (!$error) { $db->commit(); // We can commit if no errors. } else { $db->rollback(); } } print dol_get_fiche_end(); // Show result print '
'; print '
'; print $langs->trans("NbOfLinesImported", $nbok).'
'; print $langs->trans("NbInsert", empty($obj->nbinsert) ? 0 : $obj->nbinsert).'
'; print $langs->trans("NbUpdate", empty($obj->nbupdate) ? 0 : $obj->nbupdate).'
'; print '
'; print '
'; print $langs->trans("FileWasImported", $importid).'
'; print ''.$langs->trans("YouCanUseImportIdToFindRecord", $importid).'
'; print '
'; } print '
'; // End of page llxFooter(); $db->close(); /** * Function to put the movable box of a source field * * @param array,position?:int}> $fieldssource List of source fields * @param int $pos Pos * @param string $key Key * @return void */ function show_elem($fieldssource, $pos, $key) { global $conf, $langs; $height = '32px'; if ($key == 'none') { //stop multiple duplicate ids with no number print "\n\n\n"; print '
'."\n"; print ''."\n"; } else { print "\n\n\n"; print '
'."\n"; print '
'."\n"; } if (($pos && $pos > count($fieldssource)) && (!isset($fieldssource[$pos]["imported"]))) { // No fields /* print ''; print ''; print ''; print ''; */ } elseif ($key == 'none') { // Empty line print ''; print ''; print ''; print ''; } else { // Print field of source file print ''; print ''; if (isset($fieldssource[$pos]['imported']) && $fieldssource[$pos]['imported'] == false) { print ''; print ''; } print "
'; print ''; print $langs->trans("NoFields"); print '
'; print ' '; print ''; print ' '; print '
'; // 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 //print img_picto($langs->trans("MoveField", $pos), 'grip_title', 'class="boxhandle" style="cursor:move;"'); print img_picto($langs->trans("Column").' '.num2Alpha($pos - 1), 'file', 'class="pictofixedwidth"'); print ''; } else { print ''; } print $langs->trans("Column").' '.num2Alpha($pos - 1).' (#'.$pos.')'; if (empty($fieldssource[$pos]['example1'])) { $example = $fieldssource[$pos]['label']; } else { $example = $fieldssource[$pos]['example1']; } if ($example) { if (!utf8_check($example)) { $example = mb_convert_encoding($example, 'UTF-8', 'ISO-8859-1'); } // if (!empty($conf->dol_optimize_smallscreen)) { //print '
'; } print ' - '; print ''.dol_escape_htmltag($example).''; } print '
\n"; print "
\n"; print "\n\n"; } /** * Return not used field number * * @param array $fieldssource Array of field source * @param array $listofkey Array of keys * @return int */ function getnewkey(&$fieldssource, &$listofkey) { $i = count($fieldssource) + 1; // Max number of key $maxkey = 0; foreach ($listofkey as $key => $val) { $maxkey = max($maxkey, $key); } // Found next empty key while ($i <= $maxkey) { if (empty($listofkey[$i])) { break; } else { $i++; } } $listofkey[$i] = 1; return $i; } /** * Return array with element inserted in it at position $position * * @param array,position?:int}> $array Array of field source * @param int $position key of position to insert to * @param array{label?:string,example1?:string,required?:bool,imported?:bool|int<0,1>,position?:int} $insertArray Array to insert * @return array,position?:int}> */ function arrayInsert($array, $position, $insertArray) { $ret = []; if ($position == count($array)) { $ret = $array + $insertArray; } else { $i = 0; foreach ($array as $key => $value) { if ($position == $i++) { $ret += $insertArray; } $ret[$key] = $value; } } return $ret; }