ExportMediawiki.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  1. <?php
  2. /**
  3. * Set of functions used to build MediaWiki dumps of tables
  4. */
  5. declare(strict_types=1);
  6. namespace PhpMyAdmin\Plugins\Export;
  7. use PhpMyAdmin\DatabaseInterface;
  8. use PhpMyAdmin\Plugins\ExportPlugin;
  9. use PhpMyAdmin\Properties\Options\Groups\OptionsPropertyMainGroup;
  10. use PhpMyAdmin\Properties\Options\Groups\OptionsPropertyRootGroup;
  11. use PhpMyAdmin\Properties\Options\Groups\OptionsPropertySubgroup;
  12. use PhpMyAdmin\Properties\Options\Items\BoolPropertyItem;
  13. use PhpMyAdmin\Properties\Options\Items\RadioPropertyItem;
  14. use PhpMyAdmin\Properties\Plugins\ExportPluginProperties;
  15. use PhpMyAdmin\Util;
  16. use function __;
  17. use function array_values;
  18. use function count;
  19. use function htmlspecialchars;
  20. use function str_repeat;
  21. /**
  22. * Handles the export for the MediaWiki class
  23. */
  24. class ExportMediawiki extends ExportPlugin
  25. {
  26. /**
  27. * @psalm-return non-empty-lowercase-string
  28. */
  29. public function getName(): string
  30. {
  31. return 'mediawiki';
  32. }
  33. protected function setProperties(): ExportPluginProperties
  34. {
  35. $exportPluginProperties = new ExportPluginProperties();
  36. $exportPluginProperties->setText('MediaWiki Table');
  37. $exportPluginProperties->setExtension('mediawiki');
  38. $exportPluginProperties->setMimeType('text/plain');
  39. $exportPluginProperties->setOptionsText(__('Options'));
  40. // create the root group that will be the options field for
  41. // $exportPluginProperties
  42. // this will be shown as "Format specific options"
  43. $exportSpecificOptions = new OptionsPropertyRootGroup('Format Specific Options');
  44. // general options main group
  45. $generalOptions = new OptionsPropertyMainGroup(
  46. 'general_opts',
  47. __('Dump table')
  48. );
  49. // what to dump (structure/data/both)
  50. $subgroup = new OptionsPropertySubgroup(
  51. 'dump_table',
  52. __('Dump table')
  53. );
  54. $leaf = new RadioPropertyItem('structure_or_data');
  55. $leaf->setValues(
  56. [
  57. 'structure' => __('structure'),
  58. 'data' => __('data'),
  59. 'structure_and_data' => __('structure and data'),
  60. ]
  61. );
  62. $subgroup->setSubgroupHeader($leaf);
  63. $generalOptions->addProperty($subgroup);
  64. // export table name
  65. $leaf = new BoolPropertyItem(
  66. 'caption',
  67. __('Export table names')
  68. );
  69. $generalOptions->addProperty($leaf);
  70. // export table headers
  71. $leaf = new BoolPropertyItem(
  72. 'headers',
  73. __('Export table headers')
  74. );
  75. $generalOptions->addProperty($leaf);
  76. //add the main group to the root group
  77. $exportSpecificOptions->addProperty($generalOptions);
  78. // set the options for the export plugin property item
  79. $exportPluginProperties->setOptions($exportSpecificOptions);
  80. return $exportPluginProperties;
  81. }
  82. /**
  83. * Outputs export header
  84. */
  85. public function exportHeader(): bool
  86. {
  87. return true;
  88. }
  89. /**
  90. * Outputs export footer
  91. */
  92. public function exportFooter(): bool
  93. {
  94. return true;
  95. }
  96. /**
  97. * Outputs database header
  98. *
  99. * @param string $db Database name
  100. * @param string $dbAlias Alias of db
  101. */
  102. public function exportDBHeader($db, $dbAlias = ''): bool
  103. {
  104. return true;
  105. }
  106. /**
  107. * Outputs database footer
  108. *
  109. * @param string $db Database name
  110. */
  111. public function exportDBFooter($db): bool
  112. {
  113. return true;
  114. }
  115. /**
  116. * Outputs CREATE DATABASE statement
  117. *
  118. * @param string $db Database name
  119. * @param string $exportType 'server', 'database', 'table'
  120. * @param string $dbAlias Aliases of db
  121. */
  122. public function exportDBCreate($db, $exportType, $dbAlias = ''): bool
  123. {
  124. return true;
  125. }
  126. /**
  127. * Outputs table's structure
  128. *
  129. * @param string $db database name
  130. * @param string $table table name
  131. * @param string $crlf the end of line sequence
  132. * @param string $errorUrl the url to go back in case of error
  133. * @param string $exportMode 'create_table','triggers','create_view',
  134. * 'stand_in'
  135. * @param string $exportType 'server', 'database', 'table'
  136. * @param bool $do_relation whether to include relation comments
  137. * @param bool $do_comments whether to include the pmadb-style column
  138. * comments as comments in the structure; this is
  139. * deprecated but the parameter is left here
  140. * because /export calls exportStructure()
  141. * also for other export types which use this
  142. * parameter
  143. * @param bool $do_mime whether to include mime comments
  144. * @param bool $dates whether to include creation/update/check dates
  145. * @param array $aliases Aliases of db/table/columns
  146. */
  147. public function exportStructure(
  148. $db,
  149. $table,
  150. $crlf,
  151. $errorUrl,
  152. $exportMode,
  153. $exportType,
  154. $do_relation = false,
  155. $do_comments = false,
  156. $do_mime = false,
  157. $dates = false,
  158. array $aliases = []
  159. ): bool {
  160. global $dbi;
  161. $db_alias = $db;
  162. $table_alias = $table;
  163. $this->initAlias($aliases, $db_alias, $table_alias);
  164. $output = '';
  165. switch ($exportMode) {
  166. case 'create_table':
  167. $columns = $dbi->getColumns($db, $table);
  168. $columns = array_values($columns);
  169. $row_cnt = count($columns);
  170. // Print structure comment
  171. $output = $this->exportComment(
  172. 'Table structure for '
  173. . Util::backquote($table_alias)
  174. );
  175. // Begin the table construction
  176. $output .= '{| class="wikitable" style="text-align:center;"'
  177. . $this->exportCRLF();
  178. // Add the table name
  179. if (isset($GLOBALS['mediawiki_caption'])) {
  180. $output .= "|+'''" . $table_alias . "'''" . $this->exportCRLF();
  181. }
  182. // Add the table headers
  183. if (isset($GLOBALS['mediawiki_headers'])) {
  184. $output .= '|- style="background:#ffdead;"' . $this->exportCRLF();
  185. $output .= '! style="background:#ffffff" | '
  186. . $this->exportCRLF();
  187. for ($i = 0; $i < $row_cnt; ++$i) {
  188. $col_as = $columns[$i]['Field'];
  189. if (! empty($aliases[$db]['tables'][$table]['columns'][$col_as])) {
  190. $col_as = $aliases[$db]['tables'][$table]['columns'][$col_as];
  191. }
  192. $output .= ' | ' . $col_as . $this->exportCRLF();
  193. }
  194. }
  195. // Add the table structure
  196. $output .= '|-' . $this->exportCRLF();
  197. $output .= '! Type' . $this->exportCRLF();
  198. for ($i = 0; $i < $row_cnt; ++$i) {
  199. $output .= ' | ' . $columns[$i]['Type'] . $this->exportCRLF();
  200. }
  201. $output .= '|-' . $this->exportCRLF();
  202. $output .= '! Null' . $this->exportCRLF();
  203. for ($i = 0; $i < $row_cnt; ++$i) {
  204. $output .= ' | ' . $columns[$i]['Null'] . $this->exportCRLF();
  205. }
  206. $output .= '|-' . $this->exportCRLF();
  207. $output .= '! Default' . $this->exportCRLF();
  208. for ($i = 0; $i < $row_cnt; ++$i) {
  209. $output .= ' | ' . $columns[$i]['Default'] . $this->exportCRLF();
  210. }
  211. $output .= '|-' . $this->exportCRLF();
  212. $output .= '! Extra' . $this->exportCRLF();
  213. for ($i = 0; $i < $row_cnt; ++$i) {
  214. $output .= ' | ' . $columns[$i]['Extra'] . $this->exportCRLF();
  215. }
  216. $output .= '|}' . str_repeat($this->exportCRLF(), 2);
  217. break;
  218. }
  219. return $this->export->outputHandler($output);
  220. }
  221. /**
  222. * Outputs the content of a table in MediaWiki format
  223. *
  224. * @param string $db database name
  225. * @param string $table table name
  226. * @param string $crlf the end of line sequence
  227. * @param string $errorUrl the url to go back in case of error
  228. * @param string $sqlQuery SQL query for obtaining data
  229. * @param array $aliases Aliases of db/table/columns
  230. */
  231. public function exportData(
  232. $db,
  233. $table,
  234. $crlf,
  235. $errorUrl,
  236. $sqlQuery,
  237. array $aliases = []
  238. ): bool {
  239. global $dbi;
  240. $db_alias = $db;
  241. $table_alias = $table;
  242. $this->initAlias($aliases, $db_alias, $table_alias);
  243. // Print data comment
  244. $output = $this->exportComment(
  245. $table_alias != ''
  246. ? 'Table data for ' . Util::backquote($table_alias)
  247. : 'Query results'
  248. );
  249. // Begin the table construction
  250. // Use the "wikitable" class for style
  251. // Use the "sortable" class for allowing tables to be sorted by column
  252. $output .= '{| class="wikitable sortable" style="text-align:center;"'
  253. . $this->exportCRLF();
  254. // Add the table name
  255. if (isset($GLOBALS['mediawiki_caption'])) {
  256. $output .= "|+'''" . $table_alias . "'''" . $this->exportCRLF();
  257. }
  258. // Add the table headers
  259. if (isset($GLOBALS['mediawiki_headers'])) {
  260. // Get column names
  261. $column_names = $dbi->getColumnNames($db, $table);
  262. // Add column names as table headers
  263. if ($column_names !== []) {
  264. // Use '|-' for separating rows
  265. $output .= '|-' . $this->exportCRLF();
  266. // Use '!' for separating table headers
  267. foreach ($column_names as $column) {
  268. if (! empty($aliases[$db]['tables'][$table]['columns'][$column])) {
  269. $column = $aliases[$db]['tables'][$table]['columns'][$column];
  270. }
  271. $output .= ' ! ' . $column . '' . $this->exportCRLF();
  272. }
  273. }
  274. }
  275. // Get the table data from the database
  276. $result = $dbi->query($sqlQuery, DatabaseInterface::CONNECT_USER, DatabaseInterface::QUERY_UNBUFFERED);
  277. $fields_cnt = $result->numFields();
  278. while ($row = $result->fetchRow()) {
  279. $output .= '|-' . $this->exportCRLF();
  280. // Use '|' for separating table columns
  281. for ($i = 0; $i < $fields_cnt; ++$i) {
  282. $output .= ' | ' . $row[$i] . '' . $this->exportCRLF();
  283. }
  284. }
  285. // End table construction
  286. $output .= '|}' . str_repeat($this->exportCRLF(), 2);
  287. return $this->export->outputHandler($output);
  288. }
  289. /**
  290. * Outputs result raw query in MediaWiki format
  291. *
  292. * @param string $errorUrl the url to go back in case of error
  293. * @param string|null $db the database where the query is executed
  294. * @param string $sqlQuery the rawquery to output
  295. * @param string $crlf the end of line sequence
  296. */
  297. public function exportRawQuery(string $errorUrl, ?string $db, string $sqlQuery, string $crlf): bool
  298. {
  299. global $dbi;
  300. if ($db !== null) {
  301. $dbi->selectDb($db);
  302. }
  303. return $this->exportData($db ?? '', '', $crlf, $errorUrl, $sqlQuery);
  304. }
  305. /**
  306. * Outputs comments containing info about the exported tables
  307. *
  308. * @param string $text Text of comment
  309. *
  310. * @return string The formatted comment
  311. */
  312. private function exportComment($text = '')
  313. {
  314. // see https://www.mediawiki.org/wiki/Help:Formatting
  315. $comment = $this->exportCRLF();
  316. $comment .= '<!--' . $this->exportCRLF();
  317. $comment .= htmlspecialchars($text) . $this->exportCRLF();
  318. $comment .= '-->' . str_repeat($this->exportCRLF(), 2);
  319. return $comment;
  320. }
  321. /**
  322. * Outputs CRLF
  323. *
  324. * @return string CRLF
  325. */
  326. private function exportCRLF()
  327. {
  328. // The CRLF expected by the mediawiki format is "\n"
  329. return "\n";
  330. }
  331. }