ajax.csvimport.php 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. <?php
  2. // Copyright (C) 2010 Combodo SARL
  3. //
  4. // This program is free software; you can redistribute it and/or modify
  5. // it under the terms of the GNU General Public License as published by
  6. // the Free Software Foundation; version 3 of the License.
  7. //
  8. // This program is distributed in the hope that it will be useful,
  9. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. // GNU General Public License for more details.
  12. //
  13. // You should have received a copy of the GNU General Public License
  14. // along with this program; if not, write to the Free Software
  15. // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  16. /**
  17. * Specific to the interactive csv import
  18. *
  19. * @author Erwan Taloc <erwan.taloc@combodo.com>
  20. * @author Romain Quetiez <romain.quetiez@combodo.com>
  21. * @author Denis Flaven <denis.flaven@combodo.com>
  22. * @license http://www.opensource.org/licenses/gpl-3.0.html LGPL
  23. */
  24. require_once('../application/application.inc.php');
  25. require_once('../application/webpage.class.inc.php');
  26. require_once('../application/ajaxwebpage.class.inc.php');
  27. require_once('../application/wizardhelper.class.inc.php');
  28. require_once('../application/ui.linkswidget.class.inc.php');
  29. require_once('../application/csvpage.class.inc.php');
  30. /**
  31. * Helper function to build the mapping drop-down list for a field
  32. */
  33. function GetMappingForField($sClassName, $sFieldName, $iFieldIndex, $bAdvancedMode = false)
  34. {
  35. $aChoices = array('' => Dict::S('UI:CSVImport:MappingSelectOne'));
  36. $aChoices[':none:'] = Dict::S('UI:CSVImport:MappingNotApplicable');
  37. if ($bAdvancedMode)
  38. {
  39. $aChoices['id'] = Dict::S('UI:CSVImport:idField');
  40. }
  41. foreach(MetaModel::ListAttributeDefs($sClassName) as $sAttCode => $oAttDef)
  42. {
  43. if ($oAttDef->IsExternalKey())
  44. {
  45. $aChoices[$sAttCode] = $oAttDef->GetLabel();
  46. // Get fields of the external class that are considered as reconciliation keys
  47. $sTargetClass = $oAttDef->GetTargetClass();
  48. foreach(MetaModel::ListAttributeDefs($sTargetClass) as $sTargetAttCode => $oTargetAttDef)
  49. {
  50. if (MetaModel::IsReconcKey($sTargetClass, $sTargetAttCode))
  51. {
  52. $aChoices[$sAttCode.'->'.$sTargetAttCode] = $oAttDef->GetLabel().'->'.$oTargetAttDef->GetLabel();
  53. }
  54. }
  55. }
  56. else if ($oAttDef->IsWritable())
  57. {
  58. $aChoices[$sAttCode] = $oAttDef->GetLabel();
  59. }
  60. }
  61. asort($aChoices);
  62. $sHtml = "<select id=\"mapping_{$iFieldIndex}\" name=\"field[$iFieldIndex]\">\n";
  63. foreach($aChoices as $sAttCode => $sLabel)
  64. {
  65. $sSelected = '';
  66. if ( ($sFieldName == $sAttCode) || ($sFieldName == $sLabel))
  67. {
  68. $sSelected = ' selected';
  69. }
  70. if ((!$bAdvancedMode) && ($sAttCode == ':none:') && ($sFieldName == 'id'))
  71. {
  72. $sSelected = ' selected';
  73. }
  74. $sHtml .= "<option value=\"$sAttCode\"$sSelected>$sLabel</option>\n";
  75. }
  76. $sHtml .= "</select>\n";
  77. return $sHtml;
  78. }
  79. require_once('../application/startup.inc.php');
  80. session_start();
  81. if (isset($_SESSION['auth_user']))
  82. {
  83. $sAuthUser = $_SESSION['auth_user'];
  84. $sAuthPwd = $_SESSION['auth_pwd'];
  85. // Attempt to login, fails silently
  86. UserRights::Login($sAuthUser, $sAuthPwd);
  87. }
  88. else
  89. {
  90. // No session information
  91. echo "<p>No session information</p>\n";
  92. }
  93. $oContext = new UserContext();
  94. $sOperation = utils::ReadParam('operation', '');
  95. switch($sOperation)
  96. {
  97. case 'parser_preview':
  98. $oPage = new ajax_page("");
  99. $oPage->no_cache();
  100. $sSeparator = utils::ReadParam('separator', ',');
  101. if ($sSeparator == 'tab') $sSeparator = "\t";
  102. $sTextQualifier = utils::ReadParam('qualifier', '"');
  103. $iLinesToSkip = utils::ReadParam('nb_lines_skipped', 0);
  104. $bFirstLineAsHeader = utils::ReadParam('header_line', true);
  105. $sData = stripslashes(utils::ReadParam('csvdata', true));
  106. $oCSVParser = new CSVParser($sData, $sSeparator, $sTextQualifier);
  107. $aData = $oCSVParser->ToArray($iLinesToSkip);
  108. $iTarget = count($aData);
  109. if ($iTarget == 0)
  110. {
  111. $oPage->p(Dict::S('UI:CSVImport:NoData'));
  112. }
  113. else
  114. {
  115. $sMaxLen = (strlen(''.$iTarget) < 3) ? 3 : strlen(''.$iTarget); // Pad line numbers to the appropriate number of chars, but at least 3
  116. $sFormat = '%0'.$sMaxLen.'d';
  117. $oPage->p("<h3>".Dict::S('UI:Title:DataPreview')."</h3>\n");
  118. $oPage->p("<div style=\"overflow-y:auto\">\n");
  119. $oPage->add("<table cellspacing=\"0\" style=\"overflow-y:auto\">");
  120. $iMaxIndex= 10; // Display maximum 10 lines for the preview
  121. $index = 1;
  122. foreach($aData as $aRow)
  123. {
  124. $sCSSClass = 'csv_row'.($index % 2);
  125. if ( ($bFirstLineAsHeader) && ($index == 1))
  126. {
  127. $oPage->add("<tr class=\"$sCSSClass\"><td style=\"border-left:#999 3px solid;padding-right:10px;padding-left:10px;\">".sprintf($sFormat, $index)."</td><th>");
  128. $oPage->add(implode('</th><th>', $aRow));
  129. $oPage->add("</th></tr>\n");
  130. $iNbCols = count($aRow);
  131. }
  132. else
  133. {
  134. if ($index == 1) $iNbCols = count($aRow);
  135. $oPage->add("<tr class=\"$sCSSClass\"><td style=\"border-left:#999 3px solid;padding-right:10px;padding-left:10px;\">".sprintf($sFormat, $index)."</td><td>");
  136. $oPage->add(implode('</td><td>', $aRow));
  137. $oPage->add("</td></tr>\n");
  138. }
  139. $index++;
  140. if ($index > $iMaxIndex) break;
  141. }
  142. $oPage->add("</table>\n");
  143. $oPage->add("</div>\n");
  144. if($iNbCols == 1)
  145. {
  146. $oPage->p('<img src="../images/error.png">&nbsp;'.Dict::S('UI:CSVImport:ErrorOnlyOneColumn'));
  147. }
  148. else
  149. {
  150. $oPage->p('&nbsp;');
  151. }
  152. }
  153. break;
  154. case 'display_mapping_form':
  155. $oPage = new ajax_page("");
  156. $oPage->no_cache();
  157. $sSeparator = utils::ReadParam('separator', ',');
  158. $sTextQualifier = utils::ReadParam('qualifier', '"');
  159. $iLinesToSkip = utils::ReadParam('nb_lines_skipped', 0);
  160. $bFirstLineAsHeader = utils::ReadParam('header_line', true);
  161. $sData = stripslashes(utils::ReadParam('csvdata', true));
  162. $sClassName = utils::ReadParam('class_name', '');
  163. $bAdvanced = utils::ReadParam('advanced', false);
  164. $oCSVParser = new CSVParser($sData, $sSeparator, $sTextQualifier);
  165. $aData = $oCSVParser->ToArray($iLinesToSkip);
  166. $iTarget = count($aData);
  167. if ($iTarget == 0)
  168. {
  169. $oPage->p(Dict::S('UI:CSVImport:NoData'));
  170. }
  171. else
  172. {
  173. $oPage->add("<table>");
  174. $index = 1;
  175. $aFirstLine = $aData[0]; // Use the first row to determine the number of columns
  176. $iStartLine = 0;
  177. $iNbColumns = count($aFirstLine);
  178. if ($bFirstLineAsHeader)
  179. { $iStartLine = 1;
  180. foreach($aFirstLine as $sField)
  181. {
  182. $aHeader[] = $sField;
  183. }
  184. }
  185. else
  186. {
  187. // Build some conventional name for the fields: field1...fieldn
  188. $index= 1;
  189. foreach($aFirstLine as $sField)
  190. {
  191. $aHeader[] = Dict::Format('UI:CSVImport:FieldName', $index);
  192. $index++;
  193. }
  194. }
  195. $oPage->add("<table>\n");
  196. $oPage->add('<tr>');
  197. $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>');
  198. $oPage->add('</tr>');
  199. foreach($aHeader as $sField)
  200. {
  201. $oPage->add('<tr>');
  202. $oPage->add("<th>$sField</th>");
  203. $oPage->add('<td>'.GetMappingForField($sClassName, $sField, $index, $bAdvanced).'</td>');
  204. $oPage->add('<td>&nbsp;</td>');
  205. $oPage->add('<td><input id="search_'.$index.'" type="checkbox" name="search_field['.$index.']" value="1" /></td>');
  206. $oPage->add('<td>'.(isset($aData[$iStartLine][$index-1]) ? htmlentities($aData[$iStartLine][$index-1], ENT_QUOTES, 'UTF-8') : '&nbsp;').'</td>');
  207. $oPage->add('<td>'.(isset($aData[$iStartLine+1][$index-1]) ? htmlentities($aData[$iStartLine+1][$index-1], ENT_QUOTES, 'UTF-8') : '&nbsp;').'</td>');
  208. $oPage->add('</tr>');
  209. $index++;
  210. }
  211. $oPage->add("</table>\n");
  212. $aReconciliationKeys = MetaModel::GetReconcKeys($sClassName);
  213. $sDefaultKeys = '"'.implode('", "',$aReconciliationKeys).'"';
  214. $oPage->add_ready_script(
  215. <<<EOF
  216. $('select[name^=field]').change( DoCheckMapping );
  217. aDefaultKeys = new Array($sDefaultKeys);
  218. DoCheckMapping();
  219. EOF
  220. );
  221. }
  222. break;
  223. case 'get_csv_template':
  224. $sClassName = utils::ReadParam('class_name');
  225. $oSearch = new DBObjectSearch($sClassName);
  226. $oSearch->AddCondition('id', 0); // Make sure we create an empty set
  227. $oSet = new CMDBObjectSet($oSearch);
  228. $sResult = cmdbAbstractObject::GetSetAsCSV($oSet);
  229. //$aCSV = explode("\n", $sCSV);
  230. // If there are more than one line, let's assume that the first line is a comment and skip it.
  231. //if (count($aCSV) > 1)
  232. //{
  233. // $sResult = $aCSV[0];
  234. //}
  235. //else
  236. //{
  237. // $sResult = $sCSV;
  238. //}
  239. $sClassDisplayName = MetaModel::GetName($sClassName);
  240. $sDisposition = utils::ReadParam('disposition', 'inline');
  241. if ($sDisposition == 'attachment')
  242. {
  243. $oPage = new CSVPage("");
  244. $oPage->add_header("Content-disposition: attachment; filename=\"{$sClassDisplayName}.csv\"");
  245. $oPage->no_cache();
  246. $oPage->add($sResult);
  247. }
  248. else
  249. {
  250. $oPage = new ajax_page("");
  251. $oPage->no_cache();
  252. $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>');
  253. $oPage->add('<p><textarea rows="5" cols="100">'.$sResult.'</textarea></p>');
  254. }
  255. break;
  256. }
  257. $oPage->output();
  258. ?>