ExportCsv.class.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. <?php
  2. /* vim: set expandtab sw=4 ts=4 sts=4: */
  3. /**
  4. * CSV export code
  5. *
  6. * @package PhpMyAdmin-Export
  7. * @subpackage CSV
  8. */
  9. if (! defined('PHPMYADMIN')) {
  10. exit;
  11. }
  12. /* Get the export interface */
  13. require_once 'libraries/plugins/ExportPlugin.class.php';
  14. /**
  15. * Handles the export for the CSV format
  16. *
  17. * @package PhpMyAdmin-Export
  18. * @subpackage CSV
  19. */
  20. class ExportCsv extends ExportPlugin
  21. {
  22. /**
  23. * Constructor
  24. */
  25. public function __construct()
  26. {
  27. $this->setProperties();
  28. }
  29. /**
  30. * Sets the export CSV properties
  31. *
  32. * @return void
  33. */
  34. protected function setProperties()
  35. {
  36. $props = 'libraries/properties/';
  37. include_once "$props/plugins/ExportPluginProperties.class.php";
  38. include_once "$props/options/groups/OptionsPropertyRootGroup.class.php";
  39. include_once "$props/options/groups/OptionsPropertyMainGroup.class.php";
  40. include_once "$props/options/items/TextPropertyItem.class.php";
  41. include_once "$props/options/items/BoolPropertyItem.class.php";
  42. include_once "$props/options/items/HiddenPropertyItem.class.php";
  43. $exportPluginProperties = new ExportPluginProperties();
  44. $exportPluginProperties->setText('CSV');
  45. $exportPluginProperties->setExtension('csv');
  46. $exportPluginProperties->setMimeType('text/comma-separated-values');
  47. $exportPluginProperties->setOptionsText(__('Options'));
  48. // create the root group that will be the options field for
  49. // $exportPluginProperties
  50. // this will be shown as "Format specific options"
  51. $exportSpecificOptions = new OptionsPropertyRootGroup();
  52. $exportSpecificOptions->setName("Format Specific Options");
  53. // general options main group
  54. $generalOptions = new OptionsPropertyMainGroup();
  55. $generalOptions->setName("general_opts");
  56. // create leaf items and add them to the group
  57. $leaf = new TextPropertyItem();
  58. $leaf->setName("separator");
  59. $leaf->setText(__('Columns separated with:'));
  60. $generalOptions->addProperty($leaf);
  61. $leaf = new TextPropertyItem();
  62. $leaf->setName("enclosed");
  63. $leaf->setText(__('Columns enclosed with:'));
  64. $generalOptions->addProperty($leaf);
  65. $leaf = new TextPropertyItem();
  66. $leaf->setName("escaped");
  67. $leaf->setText(__('Columns escaped with:'));
  68. $generalOptions->addProperty($leaf);
  69. $leaf = new TextPropertyItem();
  70. $leaf->setName("terminated");
  71. $leaf->setText(__('Lines terminated with:'));
  72. $generalOptions->addProperty($leaf);
  73. $leaf = new TextPropertyItem();
  74. $leaf->setName('null');
  75. $leaf->setText(__('Replace NULL with:'));
  76. $generalOptions->addProperty($leaf);
  77. $leaf = new BoolPropertyItem();
  78. $leaf->setName('removeCRLF');
  79. $leaf->setText(
  80. __('Remove carriage return/line feed characters within columns')
  81. );
  82. $generalOptions->addProperty($leaf);
  83. $leaf = new BoolPropertyItem();
  84. $leaf->setName('columns');
  85. $leaf->setText(__('Put columns names in the first row'));
  86. $generalOptions->addProperty($leaf);
  87. $leaf = new HiddenPropertyItem();
  88. $leaf->setName('structure_or_data');
  89. $generalOptions->addProperty($leaf);
  90. // add the main group to the root group
  91. $exportSpecificOptions->addProperty($generalOptions);
  92. // set the options for the export plugin property item
  93. $exportPluginProperties->setOptions($exportSpecificOptions);
  94. $this->properties = $exportPluginProperties;
  95. }
  96. /**
  97. * This method is called when any PluginManager to which the observer
  98. * is attached calls PluginManager::notify()
  99. *
  100. * @param SplSubject $subject The PluginManager notifying the observer
  101. * of an update.
  102. *
  103. * @return void
  104. */
  105. public function update (SplSubject $subject)
  106. {
  107. }
  108. /**
  109. * Outputs export header
  110. *
  111. * @return bool Whether it succeeded
  112. */
  113. public function exportHeader ()
  114. {
  115. global $what, $csv_terminated, $csv_separator, $csv_enclosed, $csv_escaped;
  116. // Here we just prepare some values for export
  117. if ($what == 'excel') {
  118. $csv_terminated = "\015\012";
  119. switch($GLOBALS['excel_edition']) {
  120. case 'win':
  121. // as tested on Windows with Excel 2002 and Excel 2007
  122. $csv_separator = ';';
  123. break;
  124. case 'mac_excel2003':
  125. $csv_separator = ';';
  126. break;
  127. case 'mac_excel2008':
  128. $csv_separator = ',';
  129. break;
  130. }
  131. $csv_enclosed = '"';
  132. $csv_escaped = '"';
  133. if (isset($GLOBALS['excel_columns'])) {
  134. $GLOBALS['csv_columns'] = 'yes';
  135. }
  136. } else {
  137. if (empty($csv_terminated) || strtolower($csv_terminated) == 'auto') {
  138. $csv_terminated = $GLOBALS['crlf'];
  139. } else {
  140. $csv_terminated = str_replace('\\r', "\015", $csv_terminated);
  141. $csv_terminated = str_replace('\\n', "\012", $csv_terminated);
  142. $csv_terminated = str_replace('\\t', "\011", $csv_terminated);
  143. } // end if
  144. $csv_separator = str_replace('\\t', "\011", $csv_separator);
  145. }
  146. return true;
  147. }
  148. /**
  149. * Outputs export footer
  150. *
  151. * @return bool Whether it succeeded
  152. */
  153. public function exportFooter ()
  154. {
  155. return true;
  156. }
  157. /**
  158. * Outputs database header
  159. *
  160. * @param string $db Database name
  161. *
  162. * @return bool Whether it succeeded
  163. */
  164. public function exportDBHeader ($db)
  165. {
  166. return true;
  167. }
  168. /**
  169. * Outputs database footer
  170. *
  171. * @param string $db Database name
  172. *
  173. * @return bool Whether it succeeded
  174. */
  175. public function exportDBFooter ($db)
  176. {
  177. return true;
  178. }
  179. /**
  180. * Outputs CREATE DATABASE statement
  181. *
  182. * @param string $db Database name
  183. *
  184. * @return bool Whether it succeeded
  185. */
  186. public function exportDBCreate($db)
  187. {
  188. return true;
  189. }
  190. /**
  191. * Outputs the content of a table in CSV format
  192. *
  193. * @param string $db database name
  194. * @param string $table table name
  195. * @param string $crlf the end of line sequence
  196. * @param string $error_url the url to go back in case of error
  197. * @param string $sql_query SQL query for obtaining data
  198. *
  199. * @return bool Whether it succeeded
  200. */
  201. public function exportData($db, $table, $crlf, $error_url, $sql_query)
  202. {
  203. global $what, $csv_terminated, $csv_separator, $csv_enclosed, $csv_escaped;
  204. // Gets the data from the database
  205. $result = $GLOBALS['dbi']->query(
  206. $sql_query, null, PMA_DatabaseInterface::QUERY_UNBUFFERED
  207. );
  208. $fields_cnt = $GLOBALS['dbi']->numFields($result);
  209. // If required, get fields name at the first line
  210. if (isset($GLOBALS['csv_columns'])) {
  211. $schema_insert = '';
  212. for ($i = 0; $i < $fields_cnt; $i++) {
  213. if ($csv_enclosed == '') {
  214. $schema_insert .= stripslashes(
  215. $GLOBALS['dbi']->fieldName($result, $i)
  216. );
  217. } else {
  218. $schema_insert .= $csv_enclosed
  219. . str_replace(
  220. $csv_enclosed,
  221. $csv_escaped . $csv_enclosed,
  222. stripslashes($GLOBALS['dbi']->fieldName($result, $i))
  223. )
  224. . $csv_enclosed;
  225. }
  226. $schema_insert .= $csv_separator;
  227. } // end for
  228. $schema_insert = trim(substr($schema_insert, 0, -1));
  229. if (! PMA_exportOutputHandler($schema_insert . $csv_terminated)) {
  230. return false;
  231. }
  232. } // end if
  233. // Format the data
  234. while ($row = $GLOBALS['dbi']->fetchRow($result)) {
  235. $schema_insert = '';
  236. for ($j = 0; $j < $fields_cnt; $j++) {
  237. if (! isset($row[$j]) || is_null($row[$j])) {
  238. $schema_insert .= $GLOBALS[$what . '_null'];
  239. } elseif ($row[$j] == '0' || $row[$j] != '') {
  240. // always enclose fields
  241. if ($what == 'excel') {
  242. $row[$j] = preg_replace("/\015(\012)?/", "\012", $row[$j]);
  243. }
  244. // remove CRLF characters within field
  245. if (isset($GLOBALS[$what . '_removeCRLF'])
  246. && $GLOBALS[$what . '_removeCRLF']
  247. ) {
  248. $row[$j] = str_replace(
  249. "\n",
  250. "",
  251. str_replace(
  252. "\r",
  253. "",
  254. $row[$j]
  255. )
  256. );
  257. }
  258. if ($csv_enclosed == '') {
  259. $schema_insert .= $row[$j];
  260. } else {
  261. // also double the escape string if found in the data
  262. if ($csv_escaped != $csv_enclosed) {
  263. $schema_insert .= $csv_enclosed
  264. . str_replace(
  265. $csv_enclosed,
  266. $csv_escaped . $csv_enclosed,
  267. str_replace(
  268. $csv_escaped,
  269. $csv_escaped . $csv_escaped,
  270. $row[$j]
  271. )
  272. )
  273. . $csv_enclosed;
  274. } else {
  275. // avoid a problem when escape string equals enclose
  276. $schema_insert .= $csv_enclosed
  277. . str_replace(
  278. $csv_enclosed,
  279. $csv_escaped . $csv_enclosed,
  280. $row[$j]
  281. )
  282. . $csv_enclosed;
  283. }
  284. }
  285. } else {
  286. $schema_insert .= '';
  287. }
  288. if ($j < $fields_cnt-1) {
  289. $schema_insert .= $csv_separator;
  290. }
  291. } // end for
  292. if (! PMA_exportOutputHandler($schema_insert . $csv_terminated)) {
  293. return false;
  294. }
  295. } // end while
  296. $GLOBALS['dbi']->freeResult($result);
  297. return true;
  298. }
  299. }
  300. ?>