import.php 91 KB

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