ajax.csvimport.php 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. <?php
  2. require_once('../application/application.inc.php');
  3. require_once('../application/webpage.class.inc.php');
  4. require_once('../application/ajaxwebpage.class.inc.php');
  5. require_once('../application/wizardhelper.class.inc.php');
  6. require_once('../application/ui.linkswidget.class.inc.php');
  7. require_once('../application/csvpage.class.inc.php');
  8. /**
  9. * Helper function to build the mapping drop-down list for a field
  10. */
  11. function GetMappingForField($sClassName, $sFieldName, $iFieldIndex, $bAdvancedMode = false)
  12. {
  13. $aChoices = array('' => Dict::S('UI:CSVImport:MappingSelectOne'));
  14. $aChoices[':none:'] = Dict::S('UI:CSVImport:MappingNotApplicable');
  15. if ($bAdvancedMode)
  16. {
  17. $aChoices['id'] = Dict::S('UI:CSVImport:idField');
  18. }
  19. foreach(MetaModel::ListAttributeDefs($sClassName) as $sAttCode => $oAttDef)
  20. {
  21. if ($oAttDef->IsExternalKey())
  22. {
  23. $aChoices[$sAttCode] = $oAttDef->GetLabel();
  24. // Get fields of the external class that are considered as reconciliation keys
  25. $sTargetClass = $oAttDef->GetTargetClass();
  26. foreach(MetaModel::ListAttributeDefs($sTargetClass) as $sTargetAttCode => $oTargetAttDef)
  27. {
  28. if (MetaModel::IsReconcKey($sTargetClass, $sTargetAttCode))
  29. {
  30. $aChoices[$sAttCode.'->'.$sTargetAttCode] = $oAttDef->GetLabel().'->'.$oTargetAttDef->GetLabel();
  31. }
  32. }
  33. }
  34. else if ($oAttDef->IsWritable())
  35. {
  36. $aChoices[$sAttCode] = $oAttDef->GetLabel();
  37. }
  38. }
  39. asort($aChoices);
  40. $sHtml = "<select id=\"mapping_{$iFieldIndex}\" name=\"field[$iFieldIndex]\">\n";
  41. foreach($aChoices as $sAttCode => $sLabel)
  42. {
  43. $sSelected = '';
  44. if ( ($sFieldName == $sAttCode) || ($sFieldName == $sLabel))
  45. {
  46. $sSelected = ' selected';
  47. }
  48. if ((!$bAdvancedMode) && ($sAttCode == ':none:') && ($sFieldName == 'id'))
  49. {
  50. $sSelected = ' selected';
  51. }
  52. $sHtml .= "<option value=\"$sAttCode\"$sSelected>$sLabel</option>\n";
  53. }
  54. $sHtml .= "</select>\n";
  55. return $sHtml;
  56. }
  57. require_once('../application/startup.inc.php');
  58. session_start();
  59. if (isset($_SESSION['auth_user']))
  60. {
  61. $sAuthUser = $_SESSION['auth_user'];
  62. $sAuthPwd = $_SESSION['auth_pwd'];
  63. // Attempt to login, fails silently
  64. UserRights::Login($sAuthUser, $sAuthPwd);
  65. }
  66. else
  67. {
  68. // No session information
  69. echo "<p>No session information</p>\n";
  70. }
  71. $oContext = new UserContext();
  72. $sOperation = utils::ReadParam('operation', '');
  73. switch($sOperation)
  74. {
  75. case 'parser_preview':
  76. $oPage = new ajax_page("");
  77. $oPage->no_cache();
  78. $sSeparator = utils::ReadParam('separator', ',');
  79. if ($sSeparator == 'tab') $sSeparator = "\t";
  80. $sTextQualifier = utils::ReadParam('qualifier', '"');
  81. $iLinesToSkip = utils::ReadParam('nb_lines_skipped', 0);
  82. $bFirstLineAsHeader = utils::ReadParam('header_line', true);
  83. $sData = stripslashes(utils::ReadParam('csvdata', true));
  84. $oCSVParser = new CSVParser($sData, $sSeparator, $sTextQualifier);
  85. $aData = $oCSVParser->ToArray($iLinesToSkip);
  86. $iTarget = count($aData);
  87. if ($iTarget == 0)
  88. {
  89. $oPage->p(Dict::S('UI:CSVImport:NoData'));
  90. }
  91. else
  92. {
  93. $sMaxLen = (strlen(''.$iTarget) < 3) ? 3 : strlen(''.$iTarget); // Pad line numbers to the appropriate number of chars, but at least 3
  94. $sFormat = '%0'.$sMaxLen.'d';
  95. $oPage->p("<h3>".Dict::S('UI:Title:DataPreview')."</h3>\n");
  96. $oPage->p("<div style=\"overflow-y:auto\">\n");
  97. $oPage->add("<table cellspacing=\"0\" style=\"overflow-y:auto\">");
  98. $iMaxIndex= 10; // Display maximum 10 lines for the preview
  99. $index = 1;
  100. foreach($aData as $aRow)
  101. {
  102. $sCSSClass = 'csv_row'.($index % 2);
  103. if ( ($bFirstLineAsHeader) && ($index == 1))
  104. {
  105. $oPage->add("<tr class=\"$sCSSClass\"><td style=\"border-left:#999 3px solid;padding-right:10px;padding-left:10px;\">".sprintf($sFormat, $index)."</td><th>");
  106. $oPage->add(implode('</th><th>', $aRow));
  107. $oPage->add("</th></tr>\n");
  108. $iNbCols = count($aRow);
  109. }
  110. else
  111. {
  112. if ($index == 1) $iNbCols = count($aRow);
  113. $oPage->add("<tr class=\"$sCSSClass\"><td style=\"border-left:#999 3px solid;padding-right:10px;padding-left:10px;\">".sprintf($sFormat, $index)."</td><td>");
  114. $oPage->add(implode('</td><td>', $aRow));
  115. $oPage->add("</td></tr>\n");
  116. }
  117. $index++;
  118. if ($index > $iMaxIndex) break;
  119. }
  120. $oPage->add("</table>\n");
  121. $oPage->add("</div>\n");
  122. if($iNbCols == 1)
  123. {
  124. $oPage->p('<img src="../images/error.png">&nbsp;'.Dict::S('UI:CSVImport:ErrorOnlyOneColumn'));
  125. }
  126. else
  127. {
  128. $oPage->p('&nbsp;');
  129. }
  130. }
  131. break;
  132. case 'display_mapping_form':
  133. $oPage = new ajax_page("");
  134. $oPage->no_cache();
  135. $sSeparator = utils::ReadParam('separator', ',');
  136. $sTextQualifier = utils::ReadParam('qualifier', '"');
  137. $iLinesToSkip = utils::ReadParam('nb_lines_skipped', 0);
  138. $bFirstLineAsHeader = utils::ReadParam('header_line', true);
  139. $sData = stripslashes(utils::ReadParam('csvdata', true));
  140. $sClassName = utils::ReadParam('class_name', '');
  141. $bAdvanced = utils::ReadParam('advanced', false);
  142. $oCSVParser = new CSVParser($sData, $sSeparator, $sTextQualifier);
  143. $aData = $oCSVParser->ToArray($iLinesToSkip);
  144. $iTarget = count($aData);
  145. if ($iTarget == 0)
  146. {
  147. $oPage->p(Dict::S('UI:CSVImport:NoData'));
  148. }
  149. else
  150. {
  151. $oPage->add("<table>");
  152. $index = 1;
  153. $aFirstLine = $aData[0]; // Use the first row to determine the number of columns
  154. $iStartLine = 0;
  155. $iNbColumns = count($aFirstLine);
  156. if ($bFirstLineAsHeader)
  157. { $iStartLine = 1;
  158. foreach($aFirstLine as $sField)
  159. {
  160. $aHeader[] = $sField;
  161. }
  162. }
  163. else
  164. {
  165. // Build some conventional name for the fields: field1...fieldn
  166. $index= 1;
  167. foreach($aFirstLine as $sField)
  168. {
  169. $aHeader[] = Dict::Format('UI:CSVImport:FieldName', $index);
  170. $index++;
  171. }
  172. }
  173. $oPage->add("<table>\n");
  174. $oPage->add('<tr>');
  175. $oPage->add('<th>'.Dict::S('UI:CSVImport:HeaderFields').'</th><th>'.Dict::S('UI:CSVImport:HeaderMappings').'</th><th>&nbsp;</th><th>'.Dict::S('UI:CSVImport:HeaderSearch').'</th><th>'.Dict::S('UI:CSVImport:DataLine1').'</th><th>'.Dict::S('UI:CSVImport:DataLine2').'</th>');
  176. $oPage->add('</tr>');
  177. foreach($aHeader as $sField)
  178. {
  179. $oPage->add('<tr>');
  180. $oPage->add("<th>$sField</th>");
  181. $oPage->add('<td>'.GetMappingForField($sClassName, $sField, $index, $bAdvanced).'</td>');
  182. $oPage->add('<td>&nbsp;</td>');
  183. $oPage->add('<td><input id="search_'.$index.'" type="checkbox" name="search_field['.$index.']" value="1" /></td>');
  184. $oPage->add('<td>'.(isset($aData[$iStartLine][$index-1]) ? htmlentities($aData[$iStartLine][$index-1], ENT_QUOTES, 'UTF-8') : '&nbsp;').'</td>');
  185. $oPage->add('<td>'.(isset($aData[$iStartLine+1][$index-1]) ? htmlentities($aData[$iStartLine+1][$index-1], ENT_QUOTES, 'UTF-8') : '&nbsp;').'</td>');
  186. $oPage->add('</tr>');
  187. $index++;
  188. }
  189. $oPage->add("</table>\n");
  190. $aReconciliationKeys = MetaModel::GetReconcKeys($sClassName);
  191. $sDefaultKeys = '"'.implode('", "',$aReconciliationKeys).'"';
  192. $oPage->add_ready_script(
  193. <<<EOF
  194. $('select[name^=field]').change( DoCheckMapping );
  195. aDefaultKeys = new Array($sDefaultKeys);
  196. DoCheckMapping();
  197. EOF
  198. );
  199. }
  200. break;
  201. case 'get_csv_template':
  202. $sClassName = utils::ReadParam('class_name');
  203. $oSearch = new DBObjectSearch($sClassName);
  204. $oSearch->AddCondition('id', 0); // Make sure we create an empty set
  205. $oSet = new CMDBObjectSet($oSearch);
  206. $sResult = cmdbAbstractObject::GetSetAsCSV($oSet);
  207. //$aCSV = explode("\n", $sCSV);
  208. // If there are more than one line, let's assume that the first line is a comment and skip it.
  209. //if (count($aCSV) > 1)
  210. //{
  211. // $sResult = $aCSV[0];
  212. //}
  213. //else
  214. //{
  215. // $sResult = $sCSV;
  216. //}
  217. $sClassDisplayName = MetaModel::GetName($sClassName);
  218. $sDisposition = utils::ReadParam('disposition', 'inline');
  219. if ($sDisposition == 'attachment')
  220. {
  221. $oPage = new CSVPage("");
  222. $oPage->add_header("Content-disposition: attachment; filename=\"{$sClassDisplayName}.csv\"");
  223. $oPage->no_cache();
  224. $oPage->add($sResult);
  225. }
  226. else
  227. {
  228. $oPage = new ajax_page("");
  229. $oPage->no_cache();
  230. $oPage->add('<p style="text-align:center"><a style="text-decoration:none" href="../pages/ajax.csvimport.php?operation=get_csv_template&disposition=attachment&class_name='.$sClassName.'"><img border="0" src="../images/csv.png"><br/>'.$sClassDisplayName.'.csv</a></p>');
  231. $oPage->add('<p><textarea rows="5" cols="100">'.$sResult.'</textarea></p>');
  232. }
  233. break;
  234. }
  235. $oPage->output();
  236. ?>