import.php 93 KB

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