mirror of
https://github.com/Dolibarr/dolibarr.git
synced 2025-12-05 09:08:09 +01:00
2574 lines
95 KiB
PHP
2574 lines
95 KiB
PHP
<?php
|
|
/* Copyright (C) 2005-2016 Laurent Destailleur <eldy@users.sourceforge.net>
|
|
* Copyright (C) 2005-2009 Regis Houssin <regis.houssin@inodbox.com>
|
|
* Copyright (C) 2012 Christophe Battarel <christophe.battarel@altairis.fr>
|
|
* Copyright (C) 2022 Charlene Benke <charlene@patas-monkey.com>
|
|
* Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
|
|
* Copyright (C) 2024-2025 Frédéric France <frederic.france@free.fr>
|
|
*
|
|
* 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 <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
/**
|
|
* \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.'-'.dol_string_nohtmltag(dol_sanitizeFileName($_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' && $user->hasRight('import', 'run')) {
|
|
$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', 'Import', -1, 'upload');
|
|
|
|
print '<div class="opacitymedium">'.$langs->trans("SelectImportDataSet").'</div>';
|
|
|
|
|
|
// Define $nbmodulesnotautoenabled - TODO This code is at different places
|
|
$nbmodulesnotautoenabled = count($conf->modules);
|
|
$listofmodulesautoenabled = array('user', 'agenda', 'fckeditor', 'export', 'import');
|
|
foreach ($listofmodulesautoenabled as $moduleautoenable) {
|
|
if (in_array($moduleautoenable, $conf->modules)) {
|
|
$nbmodulesnotautoenabled--;
|
|
}
|
|
}
|
|
|
|
if ($user->admin && $nbmodulesnotautoenabled < getDolGlobalInt('MAIN_MIN_NB_ENABLED_MODULE_FOR_WARNING', 1)) { // If only minimal initial modules enabled
|
|
print info_admin($langs->trans("WarningOnlyProfilesOfActivatedModules").' '.$langs->trans("YouCanEnableModulesFrom"));
|
|
}
|
|
|
|
print '<br>';
|
|
|
|
// Show profile for import
|
|
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
|
|
print '<table class="noborder centpercent nomarginbottom">';
|
|
print '<tr class="liste_titre">';
|
|
print '<td>'.$langs->trans("Module").'</td>';
|
|
print '<td>'.$langs->trans("ImportableDatas").'</td>';
|
|
print '<td> </td>';
|
|
print '</tr>';
|
|
|
|
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 '<tr class="oddeven"><td class="tdoverflowmax200" title="'.dolPrintHTML($titleofmodule).'">';
|
|
// 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 '</td><td>';
|
|
$entity = preg_replace('/:.*$/', '', $objimport->array_import_icon[$key]);
|
|
$entityicon = strtolower(!empty($entitytoicon[$entity]) ? $entitytoicon[$entity] : $entity);
|
|
$label = $objimport->array_import_label[$key];
|
|
print '<div class="twolinesmax-normallineheight minwidth200onall">';
|
|
print img_object($objimport->array_import_module[$key]['module']->getName(), $entityicon, 'class="pictofixedwidth"');
|
|
print dolPrintHTML($label);
|
|
print '</div>';
|
|
print '</td><td style="text-align: right">';
|
|
if ($objimport->array_import_perms[$key]) {
|
|
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>';
|
|
} else {
|
|
print $langs->trans("NotEnoughPermissions");
|
|
}
|
|
print '</td></tr>';
|
|
}
|
|
} else {
|
|
print '<tr><td class="oddeven" colspan="3">'.$langs->trans("NoImportableData").'</td></tr>';
|
|
}
|
|
print '</table>';
|
|
print '</div>';
|
|
|
|
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', 'Import', -2, 'upload');
|
|
|
|
print '<div class="underbanner clearboth"></div>';
|
|
print '<div class="fichecenter">';
|
|
|
|
print '<table class="border tableforfield centpercent">';
|
|
|
|
// Module
|
|
print '<tr><td class="titlefieldcreate">'.$langs->trans("Module").'</td>';
|
|
print '<td>';
|
|
$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 '</td></tr>';
|
|
|
|
// Dataset to import
|
|
print '<tr><td>'.$langs->trans("DatasetToImport").'</td>';
|
|
print '<td>';
|
|
$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 '</td></tr>';
|
|
|
|
print '</table>';
|
|
print '</div>';
|
|
|
|
print dol_get_fiche_end();
|
|
|
|
print '<form name="userfile" action="'.$_SERVER["PHP_SELF"].'" enctype="multipart/form-data" METHOD="POST">';
|
|
print '<input type="hidden" name="token" value="'.newToken().'">';
|
|
|
|
print '<br>';
|
|
|
|
print '<span class="opacitymedium">';
|
|
$s = $langs->trans("ChooseFormatOfFileToImport", '{s1}');
|
|
$s = str_replace('{s1}', img_picto('', 'next'), $s);
|
|
print $s;
|
|
print '</span><br><br>';
|
|
|
|
print '<br>';
|
|
|
|
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
|
|
print '<table class="noborder centpercent" cellpadding="4">';
|
|
|
|
$filetoimport = '';
|
|
|
|
// Add format information and link to download example
|
|
print '<tr class="liste_titre"><td colspan="5">';
|
|
print $langs->trans("FileMustHaveOneOfFollowingFormat");
|
|
print '</td></tr>';
|
|
$list = $objmodelimport->listOfAvailableImportFormat($db);
|
|
foreach ($list as $key) {
|
|
print '<tr class="oddeven">';
|
|
print '<td width="16">'.img_picto_common($key, $objmodelimport->getPictoForKey($key)).'</td>';
|
|
$htmltext = $objmodelimport->getDriverDescForKey($key);
|
|
print '<td>'.$form->textwithpicto($objmodelimport->getDriverLabelForKey($key), $htmltext).'</td>';
|
|
print '<td style="text-align:center">';
|
|
if (empty($objmodelimport->drivererror[$key])) {
|
|
$filename = $langs->transnoentitiesnoconv("ExampleOfImportFile").'_'.$datatoimport.'.'.$key;
|
|
print '<a href="'.DOL_URL_ROOT.'/imports/emptyexample.php?format='.$key.$param.'&output=file&file='.urlencode($filename).'" target="_blank" rel="noopener noreferrer">';
|
|
print img_picto('', 'download', 'class="paddingright opacitymedium"');
|
|
print $langs->trans("DownloadEmptyExampleShort");
|
|
print '</a>';
|
|
print $form->textwithpicto('', $langs->trans("DownloadEmptyExample").'.<br>'.$langs->trans("StarAreMandatory"));
|
|
} else {
|
|
print dolPrintHTML($objmodelimport->drivererror[$key]);
|
|
}
|
|
print '</td>';
|
|
// Action button
|
|
print '<td style="text-align:right">';
|
|
if (empty($objmodelimport->drivererror[$key])) {
|
|
print '<a href="'.DOL_URL_ROOT.'/imports/import.php?step=3&format='.$key.$param.'">'.img_picto($langs->trans("SelectFormat"), 'next', 'class="fa-15"').'</a>';
|
|
}
|
|
print '</td>';
|
|
print '</tr>';
|
|
}
|
|
|
|
print '</table>';
|
|
print '</div>';
|
|
|
|
print '</form>';
|
|
}
|
|
|
|
|
|
// 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', 'Import', -2, 'upload');
|
|
|
|
/*
|
|
* 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 '<div class="underbanner clearboth"></div>';
|
|
print '<div class="fichecenter">';
|
|
|
|
print '<table class="border tableforfield centpercent">';
|
|
|
|
// Module
|
|
print '<tr><td class="titlefieldcreate">'.$langs->trans("Module").'</td>';
|
|
print '<td>';
|
|
$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 '</td></tr>';
|
|
|
|
// Lot de donnees a importer
|
|
print '<tr><td>'.$langs->trans("DatasetToImport").'</td>';
|
|
print '<td>';
|
|
$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 '</td></tr>';
|
|
|
|
print '</table>';
|
|
print '</div>';
|
|
|
|
print '<br>';
|
|
|
|
print load_fiche_titre($langs->trans("InformationOnSourceFile"), '', 'file-export');
|
|
|
|
print '<div class="underbanner clearboth"></div>';
|
|
print '<div class="fichecenter">';
|
|
print '<table width="100%" class="border tableforfield">';
|
|
|
|
// Source file format
|
|
print '<tr><td class="titlefieldcreate">'.$langs->trans("SourceFileFormat").'</td>';
|
|
print '<td class="nowraponall">';
|
|
$text = $objmodelimport->getDriverDescForKey($format);
|
|
// @phan-suppress-next-line PhanPluginSuspiciousParamPosition
|
|
print $form->textwithpicto($objmodelimport->getDriverLabelForKey($format), $text);
|
|
print '</td><td style="text-align:right" class="nowrap">';
|
|
$filename = $langs->transnoentitiesnoconv("ExampleOfImportFile").'_'.$datatoimport.'.'.$format;
|
|
print '<a href="'.DOL_URL_ROOT.'/imports/emptyexample.php?format='.$format.$param.'&output=file&file='.urlencode($filename).'" target="_blank" rel="noopener noreferrer">';
|
|
print img_picto('', 'download', 'class="paddingright opacitymedium"');
|
|
print $langs->trans("DownloadEmptyExampleShort");
|
|
print '</a>';
|
|
print $form->textwithpicto('', $langs->trans("DownloadEmptyExample").'.<br>'.$langs->trans("StarAreMandatory"));
|
|
print '</td></tr>';
|
|
|
|
print '</table>';
|
|
print '</div>';
|
|
|
|
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 '<br><br>';
|
|
|
|
print '<form name="userfile" action="'.$_SERVER["PHP_SELF"].'" enctype="multipart/form-data" method="POST">';
|
|
print '<input type="hidden" name="token" value="'.newToken().'">';
|
|
print '<input type="hidden" value="'.$step.'" name="step">';
|
|
print '<input type="hidden" value="'.dol_escape_htmltag($format).'" name="format">';
|
|
print '<input type="hidden" value="'.$excludefirstline.'" name="excludefirstline">';
|
|
print '<input type="hidden" value="'.$endatlinenb.'" name="endatlinenb">';
|
|
print '<input type="hidden" value="'.dol_escape_htmltag($separator).'" name="separator">';
|
|
print '<input type="hidden" value="'.dol_escape_htmltag($enclosure).'" name="enclosure">';
|
|
print '<input type="hidden" value="'.dol_escape_htmltag($datatoimport).'" name="datatoimport">';
|
|
|
|
print '<span class="opacitymedium">';
|
|
$s = $langs->trans("ChooseFileToImport", '{s1}');
|
|
$s = str_replace('{s1}', img_picto('', 'next'), $s);
|
|
print $s;
|
|
print '</span><br><br>';
|
|
|
|
$filetoimport = '';
|
|
|
|
// Input file name box
|
|
print '<div class="marginbottomonly">';
|
|
$maxfilesizearray = getMaxFileSizeArray();
|
|
$maxmin = $maxfilesizearray['maxmin'];
|
|
if ($maxmin > 0) {
|
|
print '<input type="hidden" name="MAX_FILE_SIZE" value="'.($maxmin * 1024).'">'; // MAX_FILE_SIZE must precede the field type=file
|
|
}
|
|
print '<input type="file" name="userfile" size="20" maxlength="80"> ';
|
|
$out = (!getDolGlobalString('MAIN_UPLOAD_DOC') ? ' disabled' : '');
|
|
print '<input type="submit" class="button small" value="'.$langs->trans("AddFile").'"'.$out.' name="sendit">';
|
|
$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 '</div>';
|
|
|
|
// Search available imports
|
|
$filearray = dol_dir_list($conf->import->dir_temp, 'files', 0, '', '', 'name', SORT_DESC);
|
|
if (count($filearray) > 0) {
|
|
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
|
|
print '<table class="noborder centpercent" width="100%" cellpadding="4">';
|
|
|
|
$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 '<tr class="oddeven">';
|
|
print '<td>';
|
|
print img_mime($file, '', 'pictofixedwidth');
|
|
print '<a data-ajax="false" href="'.DOL_URL_ROOT.'/document.php?modulepart='.$modulepart.'&file='.urlencode($relativepath).'&step=3'.$param.'" target="_blank" rel="noopener noreferrer">';
|
|
print $file;
|
|
print '</a>';
|
|
print '</td>';
|
|
// Affiche taille fichier
|
|
print '<td style="text-align:right">'.dol_print_size(dol_filesize($dir.'/'.$file)).'</td>';
|
|
// Affiche date fichier
|
|
print '<td style="text-align:right">'.dol_print_date(dol_filemtime($dir.'/'.$file), 'dayhour').'</td>';
|
|
// Del button
|
|
print '<td style="text-align:right"><a href="'.$_SERVER['PHP_SELF'].'?action=delete&token='.newToken().'&step=3'.$param.'&urlfile='.urlencode($relativepath);
|
|
print '">'.img_delete().'</a></td>';
|
|
// Action button
|
|
print '<td style="text-align:right">';
|
|
print '<a href="'.$_SERVER['PHP_SELF'].'?step=4'.$param.'&filetoimport='.urlencode($relativepath).'">'.img_picto($langs->trans("NewImport"), 'next', 'class="fa-15"').'</a>';
|
|
print '</td>';
|
|
print '</tr>';
|
|
}
|
|
|
|
print '</table>';
|
|
print '</div>';
|
|
}
|
|
|
|
print '</form>';
|
|
}
|
|
|
|
|
|
// 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<string,string> $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);
|
|
} else {
|
|
$fieldssource[$i]['example1'] = $langs->trans('Empty');
|
|
}
|
|
$fieldssource[$i]['imported'] = false;
|
|
$i++;
|
|
}
|
|
$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', 'Import', -2, 'upload');
|
|
|
|
print '<div class="underbanner clearboth"></div>';
|
|
print '<div class="fichecenter">';
|
|
|
|
print '<table class="centpercent border tableforfield">';
|
|
|
|
// Module
|
|
print '<tr><td class="titlefieldcreate">'.$langs->trans("Module").'</td>';
|
|
print '<td>';
|
|
$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 '</td></tr>';
|
|
|
|
// Lot de donnees a importer
|
|
print '<tr><td>'.$langs->trans("DatasetToImport").'</td>';
|
|
print '<td>';
|
|
$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 '</td></tr>';
|
|
|
|
print '</table>';
|
|
print '</div>';
|
|
|
|
print '<br>';
|
|
|
|
print load_fiche_titre($langs->trans("InformationOnSourceFile"), '', 'file-export');
|
|
|
|
print '<div class="underbanner clearboth"></div>';
|
|
print '<div class="fichecenter">';
|
|
print '<table width="100%" class="border tableforfield">';
|
|
|
|
// Source file format
|
|
print '<tr><td class="titlefieldcreate">'.$langs->trans("SourceFileFormat").'</td>';
|
|
print '<td class="nowraponall">';
|
|
$text = $objmodelimport->getDriverDescForKey($format);
|
|
// @phan-suppress-next-line PhanPluginSuspiciousParamPosition
|
|
print $form->textwithpicto($objmodelimport->getDriverLabelForKey($format), $text);
|
|
print '</td></tr>';
|
|
|
|
// Separator and enclosure
|
|
if ($model == 'csv') {
|
|
'@phan-var-force ImportCsv $obj';
|
|
print '<tr><td>'.$langs->trans("CsvOptions").'</td>';
|
|
print '<td>';
|
|
print '<form method="POST">';
|
|
print '<input type="hidden" name="token" value="'.newToken().'">';
|
|
print '<input type="hidden" value="'.$step.'" name="step">';
|
|
print '<input type="hidden" value="'.$format.'" name="format">';
|
|
print '<input type="hidden" value="'.$excludefirstline.'" name="excludefirstline">';
|
|
print '<input type="hidden" value="'.$endatlinenb.'" name="endatlinenb">';
|
|
print '<input type="hidden" value="'.$datatoimport.'" name="datatoimport">';
|
|
print '<input type="hidden" value="'.$filetoimport.'" name="filetoimport">';
|
|
print $langs->trans("Separator").' : ';
|
|
print '<input type="text" class="width25 center" name="separator" value="'.dol_escape_htmltag($separator).'"/>';
|
|
print ' '.$langs->trans("Enclosure").' : ';
|
|
print '<input type="text" class="width25 center" name="enclosure" value="'.dol_escape_htmltag($enclosure).'"/> ';
|
|
print '<input name="update" type="submit" value="'.$langs->trans('Update').'" class="button smallpaddingimp" />';
|
|
print '</form>';
|
|
print '</td></tr>';
|
|
}
|
|
|
|
// File to import
|
|
print '<tr><td>'.$langs->trans("FileToImport").'</td>';
|
|
print '<td>';
|
|
$modulepart = 'import';
|
|
$relativepath = GETPOST('filetoimport');
|
|
print '<a data-ajax="false" href="'.DOL_URL_ROOT.'/document.php?modulepart='.$modulepart.'&file='.urlencode($relativepath).'&step=4'.$param.'" target="_blank" rel="noopener noreferrer">';
|
|
print img_mime($file, '', 'pictofixedwidth');
|
|
print $filetoimport;
|
|
print img_picto($langs->trans("Download"), 'download', 'class="paddingleft opacitymedium"');
|
|
print '</a>';
|
|
print '</td></tr>';
|
|
|
|
print '</table>';
|
|
print '</div>';
|
|
|
|
print dol_get_fiche_end();
|
|
|
|
print '<br>'."\n";
|
|
|
|
|
|
// List of source fields
|
|
print '<!-- List of source fields -->'."\n";
|
|
print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
|
|
print '<input type="hidden" name="token" value="'.newToken().'">';
|
|
print '<input type="hidden" name="action" value="select_model">';
|
|
print '<input type="hidden" name="step" value="4">';
|
|
print '<input type="hidden" name="format" value="'.$format.'">';
|
|
print '<input type="hidden" name="datatoimport" value="'.$datatoimport.'">';
|
|
print '<input type="hidden" name="filetoimport" value="'.$filetoimport.'">';
|
|
print '<input type="hidden" name="excludefirstline" value="'.$excludefirstline.'">';
|
|
print '<input type="hidden" name="endatlinenb" value="'.$endatlinenb.'">';
|
|
print '<input type="hidden" name="separator" value="'.dol_escape_htmltag($separator).'">';
|
|
print '<input type="hidden" name="enclosure" value="'.dol_escape_htmltag($enclosure).'">';
|
|
|
|
// Import profile to use/load
|
|
print '<div class="marginbottomonly">';
|
|
print '<span class="opacitymedium">';
|
|
$s = $langs->trans("SelectImportFieldsSource", '{s1}');
|
|
$s = str_replace('{s1}', img_picto('', 'grip_title', '', 0, 0, 0, '', '', 0), $s);
|
|
print $s;
|
|
print '</span> ';
|
|
$htmlother->select_import_model((string) $importmodelid, 'importmodelid', $datatoimport, 1, $user->id);
|
|
print '<input type="submit" class="button smallpaddingimp reposition" value="'.$langs->trans("Select").'">';
|
|
print '</div>';
|
|
print '</form>';
|
|
|
|
// Title of array with fields
|
|
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
|
|
print '<table class="noborder centpercent">';
|
|
print '<tr class="liste_titre">';
|
|
print '<td>'.$langs->trans("FieldsInSourceFile").'</td>';
|
|
print '<td>'.$langs->trans("FieldsInTargetDatabase").'</td>';
|
|
print '</tr>';
|
|
|
|
//var_dump($array_match_file_to_database);
|
|
|
|
print '<tr valign="top"><td width="50%" class="nopaddingleftimp">';
|
|
|
|
$fieldsplaced = array();
|
|
$valforsourcefieldnb = array();
|
|
$listofkeys = array();
|
|
foreach ($array_match_file_to_database as $key => $val) {
|
|
$listofkeys[$key] = 1;
|
|
}
|
|
|
|
print "\n<!-- Box left container -->\n";
|
|
print '<div id="left" class="connectedSortable">'."\n";
|
|
|
|
// List of source fields
|
|
|
|
$lefti = 1;
|
|
foreach ($fieldssource as $key => $val) {
|
|
show_elem($fieldssource, $key, (string) $key); // key is field number in source file @phan-suppress-current-line PhanPluginSuspiciousParamPosition
|
|
$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 "</div>\n";
|
|
print "<!-- End box left container -->\n";
|
|
|
|
|
|
print '</td><td width="50%" class="nopaddingrightimp">';
|
|
|
|
// 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 '<table class="nobordernopadding centpercent tableimport">';
|
|
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;
|
|
}*/
|
|
//var_dump($line);
|
|
print '<tr style="height:'.$height.'" class="trimport oddevenimport">';
|
|
// 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', 'MyModule', ...
|
|
|
|
print '<td class="nowraponall hideonsmartphone" style="font-weight: normal">=> </td>';
|
|
print '<td class="nowraponall" style="font-weight: normal">';
|
|
|
|
$selectforline = '';
|
|
$selectforline .= '<select id="selectorderimport_'.($i + 1).'" class="targetselectchange minwidth300" name="select_'.($i + 1).'">';
|
|
$selectforline .= '<option value="-1"> </option>';
|
|
|
|
$j = 0;
|
|
$codeselectedarray = array();
|
|
foreach ($optionsall as $tmpcode => $tmpval) { // Loop on each entry to add into each combo list.
|
|
$label = '';
|
|
if (!empty($tmpval['picto'])) {
|
|
$label .= img_picto('', $tmpval['picto'], 'class="pictofixedwidth"');
|
|
}
|
|
$label .= $tmpval['required'] ? '<strong>' : '';
|
|
$label .= $tmpval['label'];
|
|
$label .= $tmpval['required'] ? '*</strong>' : '';
|
|
|
|
$tablealias = preg_replace('/(\..*)$/i', '', $tmpcode);
|
|
$tablename = !empty($objimport->array_import_tables[0][$tablealias]) ? $objimport->array_import_tables[0][$tablealias] : "";
|
|
|
|
$htmltext = '';
|
|
|
|
$filecolumn = ($i + 1);
|
|
// Source field info
|
|
if (empty($objimport->array_import_convertvalue[0][$tmpcode])) { // If source file does not need conversion
|
|
$filecolumntoshow = num2Alpha($i);
|
|
} else {
|
|
if ($objimport->array_import_convertvalue[0][$tmpcode]['rule'] == 'fetchidfromref') {
|
|
$htmltext .= $langs->trans("DataComeFromIdFoundFromRef", $langs->transnoentitiesnoconv($entitylang)).'<br>';
|
|
}
|
|
if ($objimport->array_import_convertvalue[0][$tmpcode]['rule'] == 'fetchidfromcodeid') {
|
|
$htmltext .= $langs->trans("DataComeFromIdFoundFromCodeId", $langs->transnoentitiesnoconv($objimport->array_import_convertvalue[0][$tmpcode]['dict'])).'<br>';
|
|
}
|
|
}
|
|
// Source required
|
|
$example = !empty($objimport->array_import_examplevalues[0][$tmpcode]) ? $objimport->array_import_examplevalues[0][$tmpcode] : "";
|
|
// Example
|
|
if (empty($objimport->array_import_convertvalue[0][$tmpcode])) { // If source file does not need conversion
|
|
if ($example) {
|
|
$htmltext .= $langs->trans("SourceExample").': <b>'.str_replace('"', '', $example).'</b><br>';
|
|
}
|
|
} else {
|
|
if ($objimport->array_import_convertvalue[0][$tmpcode]['rule'] == 'fetchidfromref') {
|
|
$htmltext .= $langs->trans("SourceExample").': <b>'.$langs->transnoentitiesnoconv("ExampleAnyRefFoundIntoElement", $entitylang).($example ? ' ('.$langs->transnoentitiesnoconv("Example").': '.str_replace('"', '', $example).')' : '').'</b><br>';
|
|
} elseif ($objimport->array_import_convertvalue[0][$tmpcode]['rule'] == 'fetchidfromcodeid') {
|
|
$htmltext .= $langs->trans("SourceExample").': <b>'.$langs->trans("ExampleAnyCodeOrIdFoundIntoDictionary", $langs->transnoentitiesnoconv($objimport->array_import_convertvalue[0][$tmpcode]['dict'])).($example ? ' ('.$langs->transnoentitiesnoconv("Example").': '.str_replace('"', '', $example).')' : '').'</b><br>';
|
|
} elseif ($example) {
|
|
$htmltext .= $langs->trans("SourceExample").': <b>'.str_replace('"', '', $example).'</b><br>';
|
|
}
|
|
}
|
|
// Format control rule
|
|
if (!empty($objimport->array_import_regex[0][$tmpcode])) {
|
|
$htmltext .= $langs->trans("FormatControlRule").': <b>'.str_replace('"', '', $objimport->array_import_regex[0][$tmpcode]).'</b><br>';
|
|
}
|
|
|
|
//var_dump($htmltext);
|
|
$htmltext .= $langs->trans("InformationOnTargetTables").': <b>'.$tablename."->".preg_replace('/^.*\./', '', $tmpcode)."</b>";
|
|
|
|
$labelhtml = $label.' '.$form->textwithpicto('', $htmltext, 1, 'help', '', 1);
|
|
|
|
$selectforline .= '<option value="'.$tmpcode.'"';
|
|
if ($modetoautofillmapping == 'orderoftargets') {
|
|
// 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.
|
|
if ($j == $i) {
|
|
$selectforline .= ' selected';
|
|
}
|
|
} elseif ($modetoautofillmapping == 'guess') {
|
|
// The mode where we try to guess which value to preselect from the name in first column of source file.
|
|
// $line['example1'] is the label of the column found on first line
|
|
$regs = array();
|
|
if (preg_match('/^(.+)\((.+\..+)\)$/', $line['example1'], $regs)) { // If text is "Label (x.abc)"
|
|
$tmpstring1 = $regs[1];
|
|
$tmpstring2 = $regs[2];
|
|
} else {
|
|
$tmpstring1 = $line['example1'];
|
|
$tmpstring2 = '';
|
|
}
|
|
$tmpstring1 = strtolower(dol_string_unaccent(str_replace('*', '', trim($tmpstring1))));
|
|
$tmpstring2 = strtolower(dol_string_unaccent(str_replace('*', '', trim($tmpstring2))));
|
|
|
|
// $tmpstring1 and $tmpstring2 are string from the input file title of column "Label (fieldname)".
|
|
// $tmpval is array of target fields read from the module import profile.
|
|
foreach ($tmpval['labelkeyarray'] as $tmpval2) {
|
|
$labeltarget = $langs->transnoentities($tmpval2);
|
|
//var_dump($tmpstring1.' - '.$tmpstring2.' - '.$tmpval['labelkey'].' - '.$tmpval['label'].' - '.$tmpval2.' - '.$labeltarget);
|
|
if ($tmpstring1 && ($tmpstring1 == $tmpcode || $tmpstring1 == strtolower($labeltarget)
|
|
|| $tmpstring1 == strtolower(dol_string_unaccent($labeltarget)) || $tmpstring1 == strtolower($tmpval2))) {
|
|
if (empty($codeselectedarray[$code])) {
|
|
$selectforline .= ' selected';
|
|
$codeselectedarray[$code] = 1;
|
|
break;
|
|
}
|
|
} elseif ($tmpstring2 && ($tmpstring2 == $tmpcode || $tmpstring2 == strtolower($labeltarget)
|
|
|| $tmpstring2 == strtolower(dol_string_unaccent($labeltarget)) || $tmpstring2 == strtolower($tmpval2))) {
|
|
if (empty($codeselectedarray[$code])) {
|
|
$selectforline .= ' selected';
|
|
$codeselectedarray[$code] = 1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
} elseif ($modetoautofillmapping == 'session' && !empty($_SESSION['dol_array_match_file_to_database_select'])) {
|
|
$tmpselectioninsession = dolExplodeIntoArray($_SESSION['dol_array_match_file_to_database_select'], ',', '=');
|
|
//var_dump($code);
|
|
if (!empty($tmpselectioninsession[(string) ($i + 1)]) && $tmpselectioninsession[(string) ($i + 1)] == $tmpcode) {
|
|
$selectforline .= ' selected';
|
|
}
|
|
$selectforline .= ' data-debug="'.$tmpcode.'-'.$code.'-'.$j.'-'.(!empty($tmpselectioninsession[(string) ($i + 1)]) ? $tmpselectioninsession[(string) ($i + 1)] : "").'"';
|
|
}
|
|
$selectforline .= ' data-html="'.dol_escape_htmltag($labelhtml).'"';
|
|
$selectforline .= '>';
|
|
$selectforline .= $label;
|
|
$selectforline .= '</options>';
|
|
$j++;
|
|
}
|
|
$selectforline .= '</select>';
|
|
$selectforline .= ajax_combobox('selectorderimport_'.($i + 1));
|
|
|
|
print $selectforline;
|
|
|
|
print '</td>';
|
|
|
|
// Tooltip at end of line
|
|
print '<td class="nowraponall" style="font-weight:normal; text-align:right">';
|
|
|
|
// Source field info
|
|
$htmltext = '<b><u>'.$langs->trans("FieldSource").'</u></b><br>';
|
|
$filecolumntoshow = num2Alpha($i);
|
|
$htmltext .= $langs->trans("DataComeFromFileFieldNb", $filecolumntoshow).'<br>';
|
|
|
|
print $form->textwithpicto('', $htmltext);
|
|
|
|
print '</td>';
|
|
print '</tr>';
|
|
$i++;
|
|
}
|
|
print '</table>';
|
|
|
|
print '</td></tr>';
|
|
|
|
// Lines for remark
|
|
print '<tr class="liste_titre"><td colspan="2">'.$langs->trans("Note").'</td></tr>';
|
|
print '<tr><td colspan="2"><div id="div-mandatory-target-fields-not-mapped"></div></td></tr>';
|
|
|
|
print '</table>';
|
|
print '</div>';
|
|
|
|
|
|
if (!empty($conf->use_javascript_ajax)) {
|
|
print '<script type="text/javascript">'."\n";
|
|
print 'var previousselectedvalueimport = "0";'."\n";
|
|
print 'var previousselectedlabelimport = "0";'."\n";
|
|
print 'var arrayofselectedvalues = [];'."\n";
|
|
print 'var arrayoftargetfields = [];'."\n";
|
|
print 'var arrayoftargetmandatoryfields = [];'."\n";
|
|
|
|
// Loop on $fieldstarget (seems sorted by 'position') to store php array into javascript array
|
|
$tmpi = 0;
|
|
foreach ($fieldstarget as $key => $val) {
|
|
print "arrayoftargetfields[".$tmpi."] = '".dol_escape_js($langs->trans($val['label']))."'; ";
|
|
if ($val['required']) {
|
|
print "arrayoftargetmandatoryfields[".$tmpi."] = '".dol_escape_js($key)."'; ";
|
|
}
|
|
$tmpi++;
|
|
}
|
|
print "\n";
|
|
|
|
print '$(document).ready(function () {'."\n";
|
|
|
|
print 'setOptionsToDisabled();'."\n";
|
|
print 'saveSelection();'."\n";
|
|
|
|
print '$(".targetselectchange").focus(function(){'."\n";
|
|
print ' previousselectedvalueimport = $(this).val();'."\n";
|
|
print ' previousselectedlabelimport = $(this).children("option:selected").text();'."\n";
|
|
print ' console.log("previousselectedvalueimport="+previousselectedvalueimport)'."\n";
|
|
print '})'."\n";
|
|
|
|
// Function to set the disabled flag
|
|
// - We set all option to "enabled"
|
|
// - Then we scan all combo to get the value currently selected and save them into the array arrayofselectedvalues
|
|
// - Then we set to disabled all fields that are selected
|
|
print 'function setOptionsToDisabled() {'."\n";
|
|
print ' console.log("Remove the disabled flag everywhere");'."\n";
|
|
print ' $("select.targetselectchange").not($( this )).find(\'option\').prop("disabled", false);'."\n"; // Enable all options
|
|
print ' arrayofselectedvalues = [];'."\n";
|
|
|
|
print ' $("select.targetselectchange").each(function(){'."\n";
|
|
print ' id = $(this).attr(\'id\')'."\n";
|
|
print ' value = $(this).val()'."\n";
|
|
print ' console.log("a selected value has been found for component "+id+" = "+value);'."\n";
|
|
print ' arrayofselectedvalues.push(value);'."\n";
|
|
print ' });'."\n";
|
|
|
|
print ' console.log("List of all selected values arrayofselectedvalues");'."\n";
|
|
print ' console.log(arrayofselectedvalues);'."\n";
|
|
print ' console.log("Set the option to disabled for every entry that is currently selected somewhere else (so into arrayofselectedvalues)");'."\n";
|
|
|
|
print ' $.each(arrayofselectedvalues, function(key, value) {'."\n"; // Loop on each selected value
|
|
print ' if (value != -1) {'."\n";
|
|
print ' console.log("Process key="+key+" value="+value+" to disable.");'."\n";
|
|
print ' $("select.targetselectchange").find(\'option[value="\'+value+\'"]:not(:selected)\').prop("disabled", true);'."\n"; // Set to disabled except if currently selected
|
|
print ' }'."\n";
|
|
print ' });'."\n";
|
|
print '}'."\n";
|
|
|
|
// Function to save the selection in database
|
|
print 'function saveSelection() {'."\n";
|
|
//print ' console.log(arrayofselectedvalues);'."\n";
|
|
print ' arrayselectedfields = [];'."\n";
|
|
print ' arrayselectedfields.push(0);'."\n";
|
|
|
|
print ' $.each( arrayofselectedvalues, function( key, value ) {'."\n";
|
|
print ' if (value != -1) {'."\n";
|
|
print ' arrayselectedfields.push(value);'."\n";
|
|
print ' } else {'."\n";
|
|
print ' arrayselectedfields.push(0);'."\n";
|
|
print ' }'."\n";
|
|
print ' });'."\n";
|
|
|
|
print " $.ajax({\n";
|
|
print " type: 'POST',\n";
|
|
print " dataType: 'json',\n";
|
|
print " url: '".dol_escape_js($_SERVER["PHP_SELF"])."?action=saveselectorder&token=".newToken()."',\n";
|
|
print " data: 'selectorder='+arrayselectedfields.toString(),\n";
|
|
print " success: function(){\n";
|
|
print " console.log('The selected fields have been saved into '+arrayselectedfields.toString());\n";
|
|
print " },\n";
|
|
print ' });'."\n";
|
|
|
|
// Now we loop on all target fields that are mandatory to show if they are not mapped yet.
|
|
print ' console.log("arrayselectedfields");';
|
|
print ' console.log(arrayselectedfields);';
|
|
print ' console.log("arrayoftargetmandatoryfields");';
|
|
print ' console.log(arrayoftargetmandatoryfields);';
|
|
print " listtoshow = '';";
|
|
print " nbelement = arrayoftargetmandatoryfields.length
|
|
for (let i = 0; i < nbelement; i++) {
|
|
if (arrayoftargetmandatoryfields[i] && ! arrayselectedfields.includes(arrayoftargetmandatoryfields[i])) {
|
|
console.log(arrayoftargetmandatoryfields[i]+' not mapped');
|
|
listtoshow = listtoshow + (listtoshow ? ', ' : '') + '<b>' + arrayoftargetfields[i] + '*</b>';
|
|
}
|
|
}
|
|
console.log(listtoshow);
|
|
if (listtoshow) {
|
|
listtoshow = '".dol_escape_js(img_warning($langs->trans("MandatoryTargetFieldsNotMapped")).' '.$langs->trans("MandatoryTargetFieldsNotMapped")).": ' + listtoshow;
|
|
$('#div-mandatory-target-fields-not-mapped').html(listtoshow);
|
|
} else {
|
|
$('#div-mandatory-target-fields-not-mapped').html('<span class=\"opacitymedium\">".dol_escape_js($langs->trans("AllTargetMandatoryFieldsAreMapped"))."</span>');
|
|
}
|
|
";
|
|
|
|
print '}'."\n";
|
|
|
|
// If we make a change on a selectbox
|
|
print '$(".targetselectchange").change(function(){'."\n";
|
|
print ' setOptionsToDisabled();'."\n";
|
|
|
|
print ' if(previousselectedlabelimport != "" && previousselectedvalueimport != -1) {'."\n";
|
|
print ' let valuetochange = $(this).val(); '."\n";
|
|
print ' $(".boxtdunused").each(function(){'."\n";
|
|
print ' if ($(this).text().includes(valuetochange)){'."\n";
|
|
print ' arraychild = $(this)[0].childNodes'."\n";
|
|
print ' arraytexttomodify = arraychild[0].textContent.split(" ")'."\n";
|
|
print ' arraytexttomodify[1] = previousselectedvalueimport '."\n";
|
|
print ' textmodified = arraytexttomodify.join(" ") '."\n";
|
|
print ' arraychild[0].textContent = textmodified'."\n";
|
|
print ' arraychild[1].innerHTML = previousselectedlabelimport'."\n";
|
|
print ' }'."\n";
|
|
print ' })'."\n";
|
|
print ' }'."\n";
|
|
print ' $(this).blur()'."\n";
|
|
|
|
print ' saveSelection()'."\n";
|
|
print '});'."\n";
|
|
|
|
print '})'."\n";
|
|
print '</script>'."\n";
|
|
}
|
|
|
|
/*
|
|
* Action bar
|
|
*/
|
|
print '<div class="tabsAction">';
|
|
|
|
if (count($array_match_file_to_database)) {
|
|
if ($mandatoryfieldshavesource) {
|
|
print '<a class="butAction saveorderselect" href="import.php?step=5'.$param.'&filetoimport='.urlencode($filetoimport).'">'.$langs->trans("NextStep").'</a>';
|
|
} else {
|
|
print '<a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->transnoentitiesnoconv("SomeMandatoryFieldHaveNoSource")).'">'.$langs->trans("NextStep").'</a>';
|
|
}
|
|
}
|
|
|
|
print '</div>';
|
|
|
|
|
|
// Area for profils import
|
|
if (count($array_match_file_to_database)) {
|
|
print '<br>'."\n";
|
|
print '<!-- Area to add new import profile -->'."\n";
|
|
print '<div class="marginbottomonly"><span class="opacitymedium">'.$langs->trans("SaveImportModel").'</span></div>';
|
|
|
|
print '<form class="nocellnopadd" action="'.$_SERVER["PHP_SELF"].'" method="post">';
|
|
print '<input type="hidden" name="token" value="'.newToken().'">';
|
|
print '<input type="hidden" name="action" value="add_import_model">';
|
|
print '<input type="hidden" name="step" value="'.$step.'">';
|
|
print '<input type="hidden" name="format" value="'.$format.'">';
|
|
print '<input type="hidden" name="datatoimport" value="'.$datatoimport.'">';
|
|
print '<input type="hidden" name="filetoimport" value="'.$filetoimport.'">';
|
|
print '<input type="hidden" name="hexa" value="'.$hexa.'">';
|
|
print '<input type="hidden" name="excludefirstline" value="'.$excludefirstline.'">';
|
|
print '<input type="hidden" name="endatlinenb" value="'.$endatlinenb.'">';
|
|
print '<input type="hidden" name="page_y" value="">';
|
|
print '<input type="hidden" value="'.dol_escape_htmltag($separator).'" name="separator">';
|
|
print '<input type="hidden" value="'.dol_escape_htmltag($enclosure).'" name="enclosure">';
|
|
|
|
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
|
|
print '<table summary="selectofimportprofil" class="noborder centpercent">';
|
|
print '<tr class="liste_titre">';
|
|
print '<td>'.$langs->trans("ImportModelName").'</td>';
|
|
print '<td>'.$langs->trans("Visibility").'</td>';
|
|
print '<td></td>';
|
|
print '</tr>';
|
|
|
|
$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 '<tr class="oddeven">';
|
|
print '<td><input name="import_name" class="minwidth300" value="'.$nameofimportprofile.'"></td>';
|
|
print '<td>';
|
|
$arrayvisibility = array('private' => $langs->trans("Private"), 'all' => $langs->trans("Everybody"));
|
|
print $form->selectarray('visibility', $arrayvisibility, 'private');
|
|
print '</td>';
|
|
print '<td class="right">';
|
|
print '<input type="submit" class="button smallpaddingimp reposition" value="'.$langs->trans("SaveImportProfile").'">';
|
|
print '</td></tr>';
|
|
|
|
// 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 '<tr class="oddeven"><td>';
|
|
print $obj->label;
|
|
print '</td>';
|
|
print '<td class="tdoverflowmax150">';
|
|
if (empty($obj->fk_user)) {
|
|
print $langs->trans("Everybody");
|
|
} else {
|
|
$tmpuser->fetch($obj->fk_user);
|
|
print $tmpuser->getNomUrl(-1);
|
|
}
|
|
print '</td>';
|
|
print '<td class="right">';
|
|
print '<a class="reposition" href="'.$_SERVER["PHP_SELF"].'?step='.$step.$param.'&action=deleteprof&token='.newToken().'&id='.$obj->rowid.'&filetoimport='.urlencode($filetoimport).'">';
|
|
print img_delete();
|
|
print '</a>';
|
|
print '</tr>';
|
|
$i++;
|
|
}
|
|
} else {
|
|
dol_print_error($db);
|
|
}
|
|
|
|
print '</table>';
|
|
print '</div>';
|
|
|
|
print '</form>';
|
|
}
|
|
}
|
|
|
|
// 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 '<form action="'.$_SERVER["PHP_SELF"].'?'.$param2.'" method="POST">';
|
|
print '<input type="hidden" name="token" value="'.newToken().'">';
|
|
print '<input type="hidden" name="step" value="5">'; // step 5
|
|
print '<input type="hidden" name="action" value="launchsimu">'; // step 5
|
|
|
|
print dol_get_fiche_head($head, 'step5', 'Import', -2, 'upload');
|
|
|
|
print '<div class="underbanner clearboth"></div>';
|
|
print '<div class="fichecenter">';
|
|
|
|
print '<table width="100%" class="border tableforfield">';
|
|
|
|
// Module
|
|
print '<tr><td class="titlefieldcreate">'.$langs->trans("Module").'</td>';
|
|
print '<td>';
|
|
$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 '</td></tr>';
|
|
|
|
// Lot de donnees a importer
|
|
print '<tr><td>'.$langs->trans("DatasetToImport").'</td>';
|
|
print '<td>';
|
|
$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 '</td></tr>';
|
|
|
|
print '</table>';
|
|
print '</div>';
|
|
|
|
print '<br>';
|
|
|
|
print load_fiche_titre($langs->trans("InformationOnSourceFile"), '', 'file-export');
|
|
|
|
print '<div class="underbanner clearboth"></div>';
|
|
print '<div class="fichecenter">';
|
|
print '<table width="100%" class="border tableforfield">';
|
|
|
|
// Source file format
|
|
print '<tr><td class="titlefieldcreate">'.$langs->trans("SourceFileFormat").'</td>';
|
|
print '<td class="nowraponall">';
|
|
$text = $objmodelimport->getDriverDescForKey($format);
|
|
// @phan-suppress-next-line PhanPluginSuspiciousParamPosition
|
|
print $form->textwithpicto($objmodelimport->getDriverLabelForKey($format), $text);
|
|
print '</td></tr>';
|
|
|
|
// Separator and enclosure
|
|
if ($model == 'csv') {
|
|
'@phan-var-force ImportCsv $obj';
|
|
print '<tr><td>'.$langs->trans("CsvOptions").'</td>';
|
|
print '<td>';
|
|
print $langs->trans("Separator").' : '.dol_escape_htmltag($separator);
|
|
print ' '.$langs->trans("Enclosure").' : '.dol_escape_htmltag($enclosure);
|
|
print '</td></tr>';
|
|
}
|
|
|
|
// File to import
|
|
print '<tr><td>'.$langs->trans("FileToImport").'</td>';
|
|
print '<td>';
|
|
$modulepart = 'import';
|
|
$relativepath = GETPOST('filetoimport');
|
|
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">';
|
|
print img_mime($file, '', 'pictofixedwidth');
|
|
print $filetoimport;
|
|
print img_picto($langs->trans("Download"), 'download', 'class="paddingleft opacitymedium"');
|
|
print '</a>';
|
|
print '</td></tr>';
|
|
|
|
// Total lines in source file
|
|
print '<tr><td>';
|
|
print $langs->trans("NbOfSourceLines");
|
|
print '</td><td>';
|
|
print $nboflines;
|
|
print '</td></tr>';
|
|
|
|
// Range of lines to import
|
|
print '<tr><td>';
|
|
print $langs->trans("ImportFromToLine");
|
|
print '</td><td>';
|
|
if ($action == 'launchsimu') {
|
|
print '<input type="number" class="maxwidth50 right" name="excludefirstlinebis" disabled="disabled" value="'.$excludefirstline.'">';
|
|
print '<input type="hidden" name="excludefirstline" value="'.$excludefirstline.'">';
|
|
} else {
|
|
print '<input type="number" class="maxwidth50 right" name="excludefirstline" value="'.$excludefirstline.'">';
|
|
print $form->textwithpicto("", $langs->trans("SetThisValueTo2ToExcludeFirstLine"));
|
|
}
|
|
print ' - ';
|
|
if ($action == 'launchsimu') {
|
|
print '<input type="text" class="maxwidth50" name="endatlinenbbis" disabled="disabled" value="'.$endatlinenb.'">';
|
|
print '<input type="hidden" name="endatlinenb" value="'.$endatlinenb.'">';
|
|
} else {
|
|
print '<input type="text" class="maxwidth50" name="endatlinenb" value="'.$endatlinenb.'">';
|
|
print $form->textwithpicto("", $langs->trans("KeepEmptyToGoToEndOfFile"));
|
|
}
|
|
if ($action == 'launchsimu') {
|
|
print ' <a href="'.$_SERVER["PHP_SELF"].'?step=5'.$param.'">'.$langs->trans("Modify").'</a>';
|
|
}
|
|
if ($excludefirstline == 2) {
|
|
print $form->textwithpicto("", $langs->trans("WarningFirstImportedLine", $excludefirstline), 1, 'warning', "warningexcludefirstline");
|
|
print '<script>
|
|
$( document ).ready(function() {
|
|
$("input[name=\'excludefirstline\']").on("change",function(){
|
|
if($(this).val() <= 1){
|
|
$(".warningexcludefirstline").hide();
|
|
}else{
|
|
$(".warningexcludefirstline").show();
|
|
}
|
|
})
|
|
});
|
|
</script>';
|
|
}
|
|
print '</td></tr>';
|
|
|
|
// Keys for data UPDATE (not INSERT of new data)
|
|
print '<tr><td>';
|
|
print $form->textwithpicto($langs->trans("KeysToUseForUpdates"), $langs->trans("SelectPrimaryColumnsForUpdateAttempt"));
|
|
print '</td><td>';
|
|
if ($action == 'launchsimu') {
|
|
if (count($updatekeys)) {
|
|
print $form->multiselectarray('updatekeysbis', $objimport->array_import_updatekeys[0], $updatekeys, 0, 0, '', 1, '80%', 'disabled');
|
|
} else {
|
|
print '<span class="opacitymedium">'.$langs->trans("NoUpdateAttempt").'</span> -';
|
|
}
|
|
foreach ($updatekeys as $val) {
|
|
print '<input type="hidden" name="updatekeys[]" value="'.$val.'">';
|
|
}
|
|
print ' <a href="'.$_SERVER["PHP_SELF"].'?step=5'.$param.'">'.$langs->trans("Modify").'</a>';
|
|
} 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 '<span class="opacitymedium">'.$langs->trans("UpdateNotYetSupportedForThisImport").'</span>';
|
|
}
|
|
}
|
|
/*echo '<pre>';
|
|
print_r($objimport->array_import_updatekeys);
|
|
echo '</pre>';*/
|
|
print '</td></tr>';
|
|
|
|
print '</table>';
|
|
print '</div>';
|
|
|
|
print '<br>';
|
|
|
|
print load_fiche_titre($langs->trans("InformationOnTargetTables"), '', 'file-import');
|
|
|
|
print '<div class="underbanner clearboth"></div>';
|
|
print '<div class="fichecenter">';
|
|
|
|
print '<table class="centpercent border tableforfield">';
|
|
|
|
// Tables imported
|
|
print '<tr><td class="titlefieldcreate">';
|
|
print $langs->trans("TablesTarget");
|
|
print '</td><td>';
|
|
$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.=' <a href="'.sprintf($helpbaseurl,$helppage).'">'.img_picto($langs->trans($mode == 'wiki' ? 'GoToWikiHelpPage': 'GoToHelpPage'),DOL_URL_ROOT.'/theme/common/helpdoc.png','',1).'</a>';
|
|
}*/
|
|
print $newval;
|
|
}
|
|
} else {
|
|
print $langs->trans("Error");
|
|
}
|
|
print '</td></tr>';
|
|
|
|
// Fields imported
|
|
print '<tr><td>';
|
|
print $langs->trans("FieldsTarget").'</td><td class="small">';
|
|
$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] = '<span class="nowrap">'.$langs->trans("Column").' '.num2Alpha((int) $code - 1).' -> '.$label.'</span>';
|
|
}
|
|
print count($listfields) ? (implode(', ', $listfields)) : $langs->trans("Error");
|
|
print '</td></tr>';
|
|
|
|
print '</table>';
|
|
print '</div>';
|
|
|
|
print dol_get_fiche_end();
|
|
|
|
|
|
if ($action != 'launchsimu') {
|
|
// Show import id
|
|
print '<br><span class="opacitymedium">';
|
|
print $langs->trans("NowClickToTestTheImport", $langs->transnoentitiesnoconv("RunSimulateImportFile")).'</span><br>';
|
|
print '<br>';
|
|
|
|
// Actions
|
|
print '<div class="center">';
|
|
if ($user->hasRight('import', 'run')) {
|
|
print '<input type="submit" class="butAction" value="'.$langs->trans("RunSimulateImportFile").'">';
|
|
} else {
|
|
print '<a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->transnoentitiesnoconv("NotEnoughPermissions")).'">'.$langs->trans("RunSimulateImportFile").'</a>';
|
|
}
|
|
print '</div>';
|
|
} else {
|
|
// Launch import
|
|
$arrayoferrors = array();
|
|
$arrayofwarnings = array();
|
|
$maxnboferrors = getDolGlobalInt('IMPORT_MAX_NB_OF_ERRORS', 50);
|
|
$maxnbofwarnings = getDolGlobalInt('IMPORT_MAX_NB_OF_WARNINGS', 50);
|
|
$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' => $langs->trans('ErrorFileLinesReachEOF', $nboflines, $sourcelinenb), '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("<br>", 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("<br>", array_merge([$hookmanager->error], $hookmanager->errors))
|
|
];
|
|
}
|
|
}
|
|
// 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 '<br>';
|
|
print '<div class="info">';
|
|
print '<div class=""><b>'.$langs->trans("ResultOfSimulationNoError").'</b></div>';
|
|
print $langs->trans("NbInsertSim", empty($obj->nbinsert) ? 0 : $obj->nbinsert).'<br>';
|
|
print $langs->trans("NbUpdateSim", empty($obj->nbupdate) ? 0 : $obj->nbupdate).'<br>';
|
|
print '</div>';
|
|
print '<br>';
|
|
} else {
|
|
print '<br>';
|
|
print '<div class="warning">';
|
|
print $langs->trans("NbOfLinesOK", $nbok).'...<br>';
|
|
print '</div>';
|
|
print '<br>';
|
|
}
|
|
|
|
// Show Errors
|
|
//var_dump($arrayoferrors);
|
|
if (count($arrayoferrors)) {
|
|
print img_error().' <b>'.$langs->trans("ErrorsOnXLines", count($arrayoferrors)).'</b><br>';
|
|
print '<table width="100%" class="border"><tr><td>';
|
|
foreach ($arrayoferrors as $key => $val) {
|
|
$nboferrors++;
|
|
if ($nboferrors > $maxnboferrors) {
|
|
print $langs->trans("TooMuchErrors", (count($arrayoferrors) - $nboferrors))."<br>";
|
|
break;
|
|
}
|
|
print '* '.$langs->trans("Line").' '.dol_escape_htmltag($key).'<br>';
|
|
foreach ($val as $i => $err) {
|
|
print ' > '.dol_escape_htmltag($err['lib']).'<br>';
|
|
}
|
|
}
|
|
print '</td></tr></table>';
|
|
print '<br>';
|
|
}
|
|
|
|
// Show Warnings
|
|
//var_dump($arrayoferrors);
|
|
if (count($arrayofwarnings)) {
|
|
print img_warning().' <b>'.$langs->trans("WarningsOnXLines", count($arrayofwarnings)).'</b><br>';
|
|
print '<table width="100%" class="border"><tr><td>';
|
|
foreach ($arrayofwarnings as $key => $val) {
|
|
$nbofwarnings++;
|
|
if ($nbofwarnings > $maxnbofwarnings) {
|
|
print $langs->trans("TooMuchWarnings", (count($arrayofwarnings) - $nbofwarnings))."<br>";
|
|
break;
|
|
}
|
|
print ' * '.$langs->trans("Line").' '.dol_escape_htmltag((string) $key).'<br>';
|
|
foreach ($val as $i => $err) {
|
|
print ' > '.dol_escape_htmltag($err['lib']).'<br>';
|
|
}
|
|
}
|
|
print '</td></tr></table>';
|
|
print '<br>';
|
|
}
|
|
|
|
// Show import id
|
|
$importid = dol_print_date(dol_now(), '%Y%m%d%H%M%S');
|
|
|
|
print '<div class="center">';
|
|
print '<span class="opacitymedium">'.$langs->trans("NowClickToRunTheImport", $langs->transnoentitiesnoconv("RunImportFile")).'</span><br>';
|
|
/*if (empty($nboferrors)) {
|
|
print $langs->trans("DataLoadedWithId", $importid).'<br>';
|
|
}*/
|
|
print '</div>';
|
|
|
|
print '<br>';
|
|
|
|
// Actions
|
|
print '<div class="center">';
|
|
if ($user->hasRight('import', 'run')) {
|
|
if (empty($nboferrors)) {
|
|
print '<a class="butAction" href="'.DOL_URL_ROOT.'/imports/import.php?leftmenu=import&step=6&importid='.$importid.$param.'">'.$langs->trans("RunImportFile").'</a>';
|
|
} else {
|
|
//print '<input type="submit" class="butAction" value="'.dol_escape_htmltag($langs->trans("RunSimulateImportFile")).'">';
|
|
|
|
print '<a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->transnoentitiesnoconv("CorrectErrorBeforeRunningImport")).'">'.$langs->trans("RunImportFile").'</a>';
|
|
}
|
|
} else {
|
|
print '<a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->transnoentitiesnoconv("NotEnoughPermissions")).'">'.$langs->trans("RunSimulateImportFile").'</a>';
|
|
|
|
print '<a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->transnoentitiesnoconv("NotEnoughPermissions")).'">'.$langs->trans("RunImportFile").'</a>';
|
|
}
|
|
print '</div>';
|
|
}
|
|
|
|
print '</form>';
|
|
}
|
|
|
|
|
|
// 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', 'Import', -1, 'upload');
|
|
|
|
print '<div class="underbanner clearboth"></div>';
|
|
print '<div class="fichecenter">';
|
|
|
|
print '<table width="100%" class="border">';
|
|
|
|
// Module
|
|
print '<tr><td class="titlefieldcreate">'.$langs->trans("Module").'</td>';
|
|
print '<td>';
|
|
$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 '</td></tr>';
|
|
|
|
// Lot de donnees a importer
|
|
print '<tr><td>'.$langs->trans("DatasetToImport").'</td>';
|
|
print '<td>';
|
|
$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 '</td></tr>';
|
|
|
|
print '</table>';
|
|
print '</div>';
|
|
|
|
print '<br>';
|
|
|
|
print load_fiche_titre($langs->trans("InformationOnSourceFile"), '', 'file-export');
|
|
|
|
print '<div class="underbanner clearboth"></div>';
|
|
print '<div class="fichecenter">';
|
|
print '<table width="100%" class="border tableforfield">';
|
|
|
|
// Source file format
|
|
print '<tr><td class="titlefieldcreate">'.$langs->trans("SourceFileFormat").'</td>';
|
|
print '<td class="nowraponall">';
|
|
$text = $objmodelimport->getDriverDescForKey($format);
|
|
// @phan-suppress-next-line PhanPluginSuspiciousParamPosition
|
|
print $form->textwithpicto($objmodelimport->getDriverLabelForKey($format), $text);
|
|
print '</td></tr>';
|
|
|
|
// Separator and enclosure
|
|
if ($model == 'csv') {
|
|
'@phan-var-force ImportCsv $obj';
|
|
print '<tr><td>'.$langs->trans("CsvOptions").'</td>';
|
|
print '<td>';
|
|
print $langs->trans("Separator").' : ';
|
|
print htmlentities($separator);
|
|
print ' '.$langs->trans("Enclosure").' : ';
|
|
print htmlentities($enclosure);
|
|
print '</td></tr>';
|
|
}
|
|
|
|
// File to import
|
|
print '<tr><td>'.$langs->trans("FileToImport").'</td>';
|
|
print '<td>';
|
|
$modulepart = 'import';
|
|
$relativepath = GETPOST('filetoimport');
|
|
print '<a data-ajax="false" href="'.DOL_URL_ROOT.'/document.php?modulepart='.$modulepart.'&file='.urlencode($relativepath).'&step=4'.$param.'" target="_blank" rel="noopener noreferrer">';
|
|
print img_mime($file, '', 'pictofixedwidth');
|
|
print $filetoimport;
|
|
print '</a>';
|
|
print '</td></tr>';
|
|
|
|
// Nb of fields
|
|
print '<tr><td>';
|
|
print $langs->trans("NbOfSourceLines");
|
|
print '</td><td>';
|
|
print $nboflines;
|
|
print '</td></tr>';
|
|
|
|
// Do not import first lines
|
|
print '<tr><td>';
|
|
print $langs->trans("ImportFromLine");
|
|
print '</td><td>';
|
|
print '<input type="text" size="4" name="excludefirstline" disabled="disabled" value="'.$excludefirstline.'">';
|
|
print '</td></tr>';
|
|
|
|
// Do not import end lines
|
|
print '<tr><td>';
|
|
print $langs->trans("EndAtLineNb");
|
|
print '</td><td>';
|
|
print '<input type="text" size="4" name="endatlinenb" disabled="disabled" value="'.$endatlinenb.'">';
|
|
print '</td></tr>';
|
|
|
|
print '</table>';
|
|
print '</div>';
|
|
|
|
print '<br>';
|
|
|
|
print '<b>'.$langs->trans("InformationOnTargetTables").'</b>';
|
|
print '<div class="underbanner clearboth"></div>';
|
|
print '<div class="fichecenter">';
|
|
print '<table class="border centpercent">';
|
|
|
|
// Tables imported
|
|
print '<tr><td width="25%">';
|
|
print $langs->trans("TablesTarget");
|
|
print '</td><td>';
|
|
$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.=' <a href="'.sprintf($helpbaseurl,$helppage).'">'.img_picto($langs->trans($mode == 'wiki' ? 'GoToWikiHelpPage': 'GoToHelpPage'),DOL_URL_ROOT.'/theme/common/helpdoc.png','',1).'</a>';
|
|
}*/
|
|
print $newval;
|
|
}
|
|
} else {
|
|
print $langs->trans("Error");
|
|
}
|
|
print '</td></tr>';
|
|
|
|
// Fields imported
|
|
print '<tr><td>';
|
|
print $langs->trans("FieldsTarget").'</td><td>';
|
|
$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 '</td></tr>';
|
|
|
|
print '</table>';
|
|
print '</div>';
|
|
|
|
// 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' => $langs->trans('ErrorFileLinesReachEOF', $nboflines, $sourcelinenb), '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("<br>", 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("<br>", 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 '<br>';
|
|
print '<div class="info">';
|
|
print $langs->trans("NbOfLinesImported", $nbok).'</b><br>';
|
|
print $langs->trans("NbInsert", empty($obj->nbinsert) ? 0 : $obj->nbinsert).'<br>';
|
|
print $langs->trans("NbUpdate", empty($obj->nbupdate) ? 0 : $obj->nbupdate).'<br>';
|
|
print '</div>';
|
|
print '<div class="center">';
|
|
print $langs->trans("FileWasImported", $importid).'<br>';
|
|
print '<span class="opacitymedium">'.$langs->trans("YouCanUseImportIdToFindRecord", $importid).'</span><br>';
|
|
print '</div>';
|
|
}
|
|
|
|
|
|
|
|
print '<br>';
|
|
|
|
// End of page
|
|
llxFooter();
|
|
$db->close();
|
|
|
|
|
|
/**
|
|
* Function to put the movable box of a source field
|
|
*
|
|
* @param array<int|string,array{label?:string,example1?:string,required?:bool,imported?:bool|int<0,1>,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<!-- Box_no-key start-->\n";
|
|
print '<div class="box boximport" style="padding:0;">'."\n";
|
|
print '<table summary="boxtable_no-key" class="centpercent nobordernopadding">'."\n";
|
|
} else {
|
|
print "\n\n<!-- Box ".$pos." start -->\n";
|
|
print '<div class="box boximport" style="padding: 0;" id="boxto_'.$pos.'">'."\n";
|
|
|
|
print '<table summary="boxtable'.$pos.'" class="nobordernopadding centpercent tableimport">'."\n";
|
|
}
|
|
|
|
if (($pos && $pos > count($fieldssource)) && (!isset($fieldssource[$pos]["imported"]))) { // No fields
|
|
/*
|
|
print '<tr style="height:'.$height.'" class="trimport oddevenimport">';
|
|
print '<td class="nocellnopadd" width="16" style="font-weight: normal">';
|
|
print '</td>';
|
|
print '<td style="font-weight: normal">';
|
|
print $langs->trans("NoFields");
|
|
print '</td>';
|
|
print '</tr>';
|
|
*/
|
|
} elseif ($key == 'none') { // Empty line
|
|
print '<tr style="height:'.$height.'" class="trimport oddevenimport">';
|
|
print '<td class="nocellnopadd" width="16" style="font-weight: normal">';
|
|
print ' ';
|
|
print '</td>';
|
|
print '<td style="font-weight: normal">';
|
|
print ' ';
|
|
print '</td>';
|
|
print '</tr>';
|
|
} else {
|
|
// Print field of source file
|
|
print '<tr style="height:'.$height.'" class="trimport oddevenimport">';
|
|
print '<td class="nocellnopadd" width="16" style="font-weight: normal">';
|
|
// 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 marginleftonly"');
|
|
print '</td>';
|
|
if (isset($fieldssource[$pos]['imported']) && $fieldssource[$pos]['imported'] == false) {
|
|
print '<td class="nowraponall boxtdunused" style="font-weight: normal">';
|
|
} else {
|
|
print '<td class="nowraponall tdoverflowmax500" style="font-weight: normal">';
|
|
}
|
|
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 '<br>'; }
|
|
print ' - ';
|
|
print '<i class="opacitymedium">'.dol_escape_htmltag($example).'</i>';
|
|
}
|
|
print '</td>';
|
|
print '</tr>';
|
|
}
|
|
|
|
print "</table>\n";
|
|
|
|
print "</div>\n";
|
|
print "<!-- Box end -->\n\n";
|
|
}
|
|
|
|
|
|
/**
|
|
* Return not used field number
|
|
*
|
|
* @param array<int,mixed|mixed[]> $fieldssource Array of field source
|
|
* @param array<int,mixed|mixed[]> $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<int|string,array{label?:string,example1?:string,required?:bool,imported?:bool|int<0,1>,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<int|string,array{label?:string,example1?:string,required?:bool,imported?:bool|int<0,1>,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;
|
|
}
|