ExportOdt.php 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809
  1. <?php
  2. /* vim: set expandtab sw=4 ts=4 sts=4: */
  3. /**
  4. * Set of functions used to build OpenDocument Text dumps of tables
  5. *
  6. * @package PhpMyAdmin-Export
  7. * @subpackage ODT
  8. */
  9. namespace PhpMyAdmin\Plugins\Export;
  10. use PhpMyAdmin\DatabaseInterface;
  11. use PhpMyAdmin\Export;
  12. use PhpMyAdmin\OpenDocument;
  13. use PhpMyAdmin\Plugins\ExportPlugin;
  14. use PhpMyAdmin\Properties\Plugins\ExportPluginProperties;
  15. use PhpMyAdmin\Properties\Options\Groups\OptionsPropertyMainGroup;
  16. use PhpMyAdmin\Properties\Options\Groups\OptionsPropertyRootGroup;
  17. use PhpMyAdmin\Properties\Options\Items\BoolPropertyItem;
  18. use PhpMyAdmin\Properties\Options\Items\RadioPropertyItem;
  19. use PhpMyAdmin\Properties\Options\Items\TextPropertyItem;
  20. use PhpMyAdmin\Relation;
  21. use PhpMyAdmin\Transformations;
  22. use PhpMyAdmin\Util;
  23. /**
  24. * Handles the export for the ODT class
  25. *
  26. * @package PhpMyAdmin-Export
  27. * @subpackage ODT
  28. */
  29. class ExportOdt extends ExportPlugin
  30. {
  31. /**
  32. * Constructor
  33. */
  34. public function __construct()
  35. {
  36. parent::__construct();
  37. $GLOBALS['odt_buffer'] = '';
  38. $this->setProperties();
  39. }
  40. /**
  41. * Sets the export ODT properties
  42. *
  43. * @return void
  44. */
  45. protected function setProperties()
  46. {
  47. global $plugin_param;
  48. $hide_structure = false;
  49. if ($plugin_param['export_type'] == 'table'
  50. && !$plugin_param['single_table']
  51. ) {
  52. $hide_structure = true;
  53. }
  54. $exportPluginProperties = new ExportPluginProperties();
  55. $exportPluginProperties->setText('OpenDocument Text');
  56. $exportPluginProperties->setExtension('odt');
  57. $exportPluginProperties->setMimeType(
  58. 'application/vnd.oasis.opendocument.text'
  59. );
  60. $exportPluginProperties->setForceFile(true);
  61. $exportPluginProperties->setOptionsText(__('Options'));
  62. // create the root group that will be the options field for
  63. // $exportPluginProperties
  64. // this will be shown as "Format specific options"
  65. $exportSpecificOptions = new OptionsPropertyRootGroup(
  66. "Format Specific Options"
  67. );
  68. // what to dump (structure/data/both) main group
  69. $dumpWhat = new OptionsPropertyMainGroup(
  70. "general_opts", __('Dump table')
  71. );
  72. // create primary items and add them to the group
  73. $leaf = new RadioPropertyItem("structure_or_data");
  74. $leaf->setValues(
  75. array(
  76. 'structure' => __('structure'),
  77. 'data' => __('data'),
  78. 'structure_and_data' => __('structure and data'),
  79. )
  80. );
  81. $dumpWhat->addProperty($leaf);
  82. // add the main group to the root group
  83. $exportSpecificOptions->addProperty($dumpWhat);
  84. // structure options main group
  85. if (!$hide_structure) {
  86. $structureOptions = new OptionsPropertyMainGroup(
  87. "structure", __('Object creation options')
  88. );
  89. $structureOptions->setForce('data');
  90. // create primary items and add them to the group
  91. if (!empty($GLOBALS['cfgRelation']['relation'])) {
  92. $leaf = new BoolPropertyItem(
  93. "relation",
  94. __('Display foreign key relationships')
  95. );
  96. $structureOptions->addProperty($leaf);
  97. }
  98. $leaf = new BoolPropertyItem(
  99. "comments",
  100. __('Display comments')
  101. );
  102. $structureOptions->addProperty($leaf);
  103. if (!empty($GLOBALS['cfgRelation']['mimework'])) {
  104. $leaf = new BoolPropertyItem(
  105. "mime",
  106. __('Display MIME types')
  107. );
  108. $structureOptions->addProperty($leaf);
  109. }
  110. // add the main group to the root group
  111. $exportSpecificOptions->addProperty($structureOptions);
  112. }
  113. // data options main group
  114. $dataOptions = new OptionsPropertyMainGroup(
  115. "data", __('Data dump options')
  116. );
  117. $dataOptions->setForce('structure');
  118. // create primary items and add them to the group
  119. $leaf = new BoolPropertyItem(
  120. "columns",
  121. __('Put columns names in the first row')
  122. );
  123. $dataOptions->addProperty($leaf);
  124. $leaf = new TextPropertyItem(
  125. 'null',
  126. __('Replace NULL with:')
  127. );
  128. $dataOptions->addProperty($leaf);
  129. // add the main group to the root group
  130. $exportSpecificOptions->addProperty($dataOptions);
  131. // set the options for the export plugin property item
  132. $exportPluginProperties->setOptions($exportSpecificOptions);
  133. $this->properties = $exportPluginProperties;
  134. }
  135. /**
  136. * Outputs export header
  137. *
  138. * @return bool Whether it succeeded
  139. */
  140. public function exportHeader()
  141. {
  142. $GLOBALS['odt_buffer'] .= '<?xml version="1.0" encoding="utf-8"?' . '>'
  143. . '<office:document-content '
  144. . OpenDocument::NS . ' office:version="1.0">'
  145. . '<office:body>'
  146. . '<office:text>';
  147. return true;
  148. }
  149. /**
  150. * Outputs export footer
  151. *
  152. * @return bool Whether it succeeded
  153. */
  154. public function exportFooter()
  155. {
  156. $GLOBALS['odt_buffer'] .= '</office:text>'
  157. . '</office:body>'
  158. . '</office:document-content>';
  159. if (!Export::outputHandler(
  160. OpenDocument::create(
  161. 'application/vnd.oasis.opendocument.text',
  162. $GLOBALS['odt_buffer']
  163. )
  164. )
  165. ) {
  166. return false;
  167. }
  168. return true;
  169. }
  170. /**
  171. * Outputs database header
  172. *
  173. * @param string $db Database name
  174. * @param string $db_alias Aliases of db
  175. *
  176. * @return bool Whether it succeeded
  177. */
  178. public function exportDBHeader($db, $db_alias = '')
  179. {
  180. if (empty($db_alias)) {
  181. $db_alias = $db;
  182. }
  183. $GLOBALS['odt_buffer']
  184. .= '<text:h text:outline-level="1" text:style-name="Heading_1"'
  185. . ' text:is-list-header="true">'
  186. . __('Database') . ' ' . htmlspecialchars($db_alias)
  187. . '</text:h>';
  188. return true;
  189. }
  190. /**
  191. * Outputs database footer
  192. *
  193. * @param string $db Database name
  194. *
  195. * @return bool Whether it succeeded
  196. */
  197. public function exportDBFooter($db)
  198. {
  199. return true;
  200. }
  201. /**
  202. * Outputs CREATE DATABASE statement
  203. *
  204. * @param string $db Database name
  205. * @param string $export_type 'server', 'database', 'table'
  206. * @param string $db_alias Aliases of db
  207. *
  208. * @return bool Whether it succeeded
  209. */
  210. public function exportDBCreate($db, $export_type, $db_alias = '')
  211. {
  212. return true;
  213. }
  214. /**
  215. * Outputs the content of a table in NHibernate format
  216. *
  217. * @param string $db database name
  218. * @param string $table table name
  219. * @param string $crlf the end of line sequence
  220. * @param string $error_url the url to go back in case of error
  221. * @param string $sql_query SQL query for obtaining data
  222. * @param array $aliases Aliases of db/table/columns
  223. *
  224. * @return bool Whether it succeeded
  225. */
  226. public function exportData(
  227. $db,
  228. $table,
  229. $crlf,
  230. $error_url,
  231. $sql_query,
  232. array $aliases = array()
  233. ) {
  234. global $what;
  235. $db_alias = $db;
  236. $table_alias = $table;
  237. $this->initAlias($aliases, $db_alias, $table_alias);
  238. // Gets the data from the database
  239. $result = $GLOBALS['dbi']->query(
  240. $sql_query,
  241. DatabaseInterface::CONNECT_USER,
  242. DatabaseInterface::QUERY_UNBUFFERED
  243. );
  244. $fields_cnt = $GLOBALS['dbi']->numFields($result);
  245. $fields_meta = $GLOBALS['dbi']->getFieldsMeta($result);
  246. $field_flags = array();
  247. for ($j = 0; $j < $fields_cnt; $j++) {
  248. $field_flags[$j] = $GLOBALS['dbi']->fieldFlags($result, $j);
  249. }
  250. $GLOBALS['odt_buffer']
  251. .= '<text:h text:outline-level="2" text:style-name="Heading_2"'
  252. . ' text:is-list-header="true">'
  253. . __('Dumping data for table') . ' ' . htmlspecialchars($table_alias)
  254. . '</text:h>'
  255. . '<table:table'
  256. . ' table:name="' . htmlspecialchars($table_alias) . '_structure">'
  257. . '<table:table-column'
  258. . ' table:number-columns-repeated="' . $fields_cnt . '"/>';
  259. // If required, get fields name at the first line
  260. if (isset($GLOBALS[$what . '_columns'])) {
  261. $GLOBALS['odt_buffer'] .= '<table:table-row>';
  262. for ($i = 0; $i < $fields_cnt; $i++) {
  263. $col_as = $GLOBALS['dbi']->fieldName($result, $i);
  264. if (!empty($aliases[$db]['tables'][$table]['columns'][$col_as])) {
  265. $col_as = $aliases[$db]['tables'][$table]['columns'][$col_as];
  266. }
  267. $GLOBALS['odt_buffer']
  268. .= '<table:table-cell office:value-type="string">'
  269. . '<text:p>'
  270. . htmlspecialchars(
  271. stripslashes($col_as)
  272. )
  273. . '</text:p>'
  274. . '</table:table-cell>';
  275. } // end for
  276. $GLOBALS['odt_buffer'] .= '</table:table-row>';
  277. } // end if
  278. // Format the data
  279. while ($row = $GLOBALS['dbi']->fetchRow($result)) {
  280. $GLOBALS['odt_buffer'] .= '<table:table-row>';
  281. for ($j = 0; $j < $fields_cnt; $j++) {
  282. if ($fields_meta[$j]->type === 'geometry') {
  283. // export GIS types as hex
  284. $row[$j] = '0x' . bin2hex($row[$j]);
  285. }
  286. if (!isset($row[$j]) || is_null($row[$j])) {
  287. $GLOBALS['odt_buffer']
  288. .= '<table:table-cell office:value-type="string">'
  289. . '<text:p>'
  290. . htmlspecialchars($GLOBALS[$what . '_null'])
  291. . '</text:p>'
  292. . '</table:table-cell>';
  293. } elseif (stristr($field_flags[$j], 'BINARY')
  294. && $fields_meta[$j]->blob
  295. ) {
  296. // ignore BLOB
  297. $GLOBALS['odt_buffer']
  298. .= '<table:table-cell office:value-type="string">'
  299. . '<text:p></text:p>'
  300. . '</table:table-cell>';
  301. } elseif ($fields_meta[$j]->numeric
  302. && $fields_meta[$j]->type != 'timestamp'
  303. && !$fields_meta[$j]->blob
  304. ) {
  305. $GLOBALS['odt_buffer']
  306. .= '<table:table-cell office:value-type="float"'
  307. . ' office:value="' . $row[$j] . '" >'
  308. . '<text:p>'
  309. . htmlspecialchars($row[$j])
  310. . '</text:p>'
  311. . '</table:table-cell>';
  312. } else {
  313. $GLOBALS['odt_buffer']
  314. .= '<table:table-cell office:value-type="string">'
  315. . '<text:p>'
  316. . htmlspecialchars($row[$j])
  317. . '</text:p>'
  318. . '</table:table-cell>';
  319. }
  320. } // end for
  321. $GLOBALS['odt_buffer'] .= '</table:table-row>';
  322. } // end while
  323. $GLOBALS['dbi']->freeResult($result);
  324. $GLOBALS['odt_buffer'] .= '</table:table>';
  325. return true;
  326. }
  327. /**
  328. * Returns a stand-in CREATE definition to resolve view dependencies
  329. *
  330. * @param string $db the database name
  331. * @param string $view the view name
  332. * @param string $crlf the end of line sequence
  333. * @param array $aliases Aliases of db/table/columns
  334. *
  335. * @return string resulting definition
  336. */
  337. public function getTableDefStandIn($db, $view, $crlf, $aliases = array())
  338. {
  339. $db_alias = $db;
  340. $view_alias = $view;
  341. $this->initAlias($aliases, $db_alias, $view_alias);
  342. /**
  343. * Gets fields properties
  344. */
  345. $GLOBALS['dbi']->selectDb($db);
  346. /**
  347. * Displays the table structure
  348. */
  349. $GLOBALS['odt_buffer']
  350. .= '<table:table table:name="'
  351. . htmlspecialchars($view_alias) . '_data">';
  352. $columns_cnt = 4;
  353. $GLOBALS['odt_buffer']
  354. .= '<table:table-column'
  355. . ' table:number-columns-repeated="' . $columns_cnt . '"/>';
  356. /* Header */
  357. $GLOBALS['odt_buffer'] .= '<table:table-row>'
  358. . '<table:table-cell office:value-type="string">'
  359. . '<text:p>' . __('Column') . '</text:p>'
  360. . '</table:table-cell>'
  361. . '<table:table-cell office:value-type="string">'
  362. . '<text:p>' . __('Type') . '</text:p>'
  363. . '</table:table-cell>'
  364. . '<table:table-cell office:value-type="string">'
  365. . '<text:p>' . __('Null') . '</text:p>'
  366. . '</table:table-cell>'
  367. . '<table:table-cell office:value-type="string">'
  368. . '<text:p>' . __('Default') . '</text:p>'
  369. . '</table:table-cell>'
  370. . '</table:table-row>';
  371. $columns = $GLOBALS['dbi']->getColumns($db, $view);
  372. foreach ($columns as $column) {
  373. $col_as = isset($column['Field']) ? $column['Field'] : null;
  374. if (!empty($aliases[$db]['tables'][$view]['columns'][$col_as])) {
  375. $col_as = $aliases[$db]['tables'][$view]['columns'][$col_as];
  376. }
  377. $GLOBALS['odt_buffer'] .= $this->formatOneColumnDefinition(
  378. $column,
  379. $col_as
  380. );
  381. $GLOBALS['odt_buffer'] .= '</table:table-row>';
  382. } // end foreach
  383. $GLOBALS['odt_buffer'] .= '</table:table>';
  384. return true;
  385. }
  386. /**
  387. * Returns $table's CREATE definition
  388. *
  389. * @param string $db the database name
  390. * @param string $table the table name
  391. * @param string $crlf the end of line sequence
  392. * @param string $error_url the url to go back in case of error
  393. * @param bool $do_relation whether to include relation comments
  394. * @param bool $do_comments whether to include the pmadb-style column
  395. * comments as comments in the structure;
  396. * this is deprecated but the parameter is
  397. * left here because export.php calls
  398. * PMA_exportStructure() also for other
  399. * @param bool $do_mime whether to include mime comments
  400. * @param bool $show_dates whether to include creation/update/check dates
  401. * @param bool $add_semicolon whether to add semicolon and end-of-line at
  402. * the end
  403. * @param bool $view whether we're handling a view
  404. * @param array $aliases Aliases of db/table/columns
  405. *
  406. * @return bool true
  407. */
  408. public function getTableDef(
  409. $db,
  410. $table,
  411. $crlf,
  412. $error_url,
  413. $do_relation,
  414. $do_comments,
  415. $do_mime,
  416. $show_dates = false,
  417. $add_semicolon = true,
  418. $view = false,
  419. array $aliases = array()
  420. ) {
  421. global $cfgRelation;
  422. $db_alias = $db;
  423. $table_alias = $table;
  424. $this->initAlias($aliases, $db_alias, $table_alias);
  425. /**
  426. * Gets fields properties
  427. */
  428. $GLOBALS['dbi']->selectDb($db);
  429. // Check if we can use Relations
  430. list($res_rel, $have_rel) = $this->relation->getRelationsAndStatus(
  431. $do_relation && !empty($cfgRelation['relation']),
  432. $db,
  433. $table
  434. );
  435. /**
  436. * Displays the table structure
  437. */
  438. $GLOBALS['odt_buffer'] .= '<table:table table:name="'
  439. . htmlspecialchars($table_alias) . '_structure">';
  440. $columns_cnt = 4;
  441. if ($do_relation && $have_rel) {
  442. $columns_cnt++;
  443. }
  444. if ($do_comments) {
  445. $columns_cnt++;
  446. }
  447. if ($do_mime && $cfgRelation['mimework']) {
  448. $columns_cnt++;
  449. }
  450. $GLOBALS['odt_buffer'] .= '<table:table-column'
  451. . ' table:number-columns-repeated="' . $columns_cnt . '"/>';
  452. /* Header */
  453. $GLOBALS['odt_buffer'] .= '<table:table-row>'
  454. . '<table:table-cell office:value-type="string">'
  455. . '<text:p>' . __('Column') . '</text:p>'
  456. . '</table:table-cell>'
  457. . '<table:table-cell office:value-type="string">'
  458. . '<text:p>' . __('Type') . '</text:p>'
  459. . '</table:table-cell>'
  460. . '<table:table-cell office:value-type="string">'
  461. . '<text:p>' . __('Null') . '</text:p>'
  462. . '</table:table-cell>'
  463. . '<table:table-cell office:value-type="string">'
  464. . '<text:p>' . __('Default') . '</text:p>'
  465. . '</table:table-cell>';
  466. if ($do_relation && $have_rel) {
  467. $GLOBALS['odt_buffer'] .= '<table:table-cell office:value-type="string">'
  468. . '<text:p>' . __('Links to') . '</text:p>'
  469. . '</table:table-cell>';
  470. }
  471. if ($do_comments) {
  472. $GLOBALS['odt_buffer'] .= '<table:table-cell office:value-type="string">'
  473. . '<text:p>' . __('Comments') . '</text:p>'
  474. . '</table:table-cell>';
  475. $comments = $this->relation->getComments($db, $table);
  476. }
  477. if ($do_mime && $cfgRelation['mimework']) {
  478. $GLOBALS['odt_buffer'] .= '<table:table-cell office:value-type="string">'
  479. . '<text:p>' . __('MIME type') . '</text:p>'
  480. . '</table:table-cell>';
  481. $mime_map = Transformations::getMIME($db, $table, true);
  482. }
  483. $GLOBALS['odt_buffer'] .= '</table:table-row>';
  484. $columns = $GLOBALS['dbi']->getColumns($db, $table);
  485. foreach ($columns as $column) {
  486. $col_as = $field_name = $column['Field'];
  487. if (!empty($aliases[$db]['tables'][$table]['columns'][$col_as])) {
  488. $col_as = $aliases[$db]['tables'][$table]['columns'][$col_as];
  489. }
  490. $GLOBALS['odt_buffer'] .= $this->formatOneColumnDefinition(
  491. $column,
  492. $col_as
  493. );
  494. if ($do_relation && $have_rel) {
  495. $foreigner = $this->relation->searchColumnInForeigners($res_rel, $field_name);
  496. if ($foreigner) {
  497. $rtable = $foreigner['foreign_table'];
  498. $rfield = $foreigner['foreign_field'];
  499. if (!empty($aliases[$db]['tables'][$rtable]['columns'][$rfield])
  500. ) {
  501. $rfield
  502. = $aliases[$db]['tables'][$rtable]['columns'][$rfield];
  503. }
  504. if (!empty($aliases[$db]['tables'][$rtable]['alias'])) {
  505. $rtable = $aliases[$db]['tables'][$rtable]['alias'];
  506. }
  507. $relation = htmlspecialchars($rtable . ' (' . $rfield . ')');
  508. $GLOBALS['odt_buffer']
  509. .= '<table:table-cell office:value-type="string">'
  510. . '<text:p>'
  511. . htmlspecialchars($relation)
  512. . '</text:p>'
  513. . '</table:table-cell>';
  514. }
  515. }
  516. if ($do_comments) {
  517. if (isset($comments[$field_name])) {
  518. $GLOBALS['odt_buffer']
  519. .= '<table:table-cell office:value-type="string">'
  520. . '<text:p>'
  521. . htmlspecialchars($comments[$field_name])
  522. . '</text:p>'
  523. . '</table:table-cell>';
  524. } else {
  525. $GLOBALS['odt_buffer']
  526. .= '<table:table-cell office:value-type="string">'
  527. . '<text:p></text:p>'
  528. . '</table:table-cell>';
  529. }
  530. }
  531. if ($do_mime && $cfgRelation['mimework']) {
  532. if (isset($mime_map[$field_name])) {
  533. $GLOBALS['odt_buffer']
  534. .= '<table:table-cell office:value-type="string">'
  535. . '<text:p>'
  536. . htmlspecialchars(
  537. str_replace('_', '/', $mime_map[$field_name]['mimetype'])
  538. )
  539. . '</text:p>'
  540. . '</table:table-cell>';
  541. } else {
  542. $GLOBALS['odt_buffer']
  543. .= '<table:table-cell office:value-type="string">'
  544. . '<text:p></text:p>'
  545. . '</table:table-cell>';
  546. }
  547. }
  548. $GLOBALS['odt_buffer'] .= '</table:table-row>';
  549. } // end foreach
  550. $GLOBALS['odt_buffer'] .= '</table:table>';
  551. return true;
  552. } // end of the '$this->getTableDef()' function
  553. /**
  554. * Outputs triggers
  555. *
  556. * @param string $db database name
  557. * @param string $table table name
  558. * @param array $aliases Aliases of db/table/columns
  559. *
  560. * @return bool true
  561. */
  562. protected function getTriggers($db, $table, array $aliases = array())
  563. {
  564. $db_alias = $db;
  565. $table_alias = $table;
  566. $this->initAlias($aliases, $db_alias, $table_alias);
  567. $GLOBALS['odt_buffer'] .= '<table:table'
  568. . ' table:name="' . htmlspecialchars($table_alias) . '_triggers">'
  569. . '<table:table-column'
  570. . ' table:number-columns-repeated="4"/>'
  571. . '<table:table-row>'
  572. . '<table:table-cell office:value-type="string">'
  573. . '<text:p>' . __('Name') . '</text:p>'
  574. . '</table:table-cell>'
  575. . '<table:table-cell office:value-type="string">'
  576. . '<text:p>' . __('Time') . '</text:p>'
  577. . '</table:table-cell>'
  578. . '<table:table-cell office:value-type="string">'
  579. . '<text:p>' . __('Event') . '</text:p>'
  580. . '</table:table-cell>'
  581. . '<table:table-cell office:value-type="string">'
  582. . '<text:p>' . __('Definition') . '</text:p>'
  583. . '</table:table-cell>'
  584. . '</table:table-row>';
  585. $triggers = $GLOBALS['dbi']->getTriggers($db, $table);
  586. foreach ($triggers as $trigger) {
  587. $GLOBALS['odt_buffer'] .= '<table:table-row>';
  588. $GLOBALS['odt_buffer'] .= '<table:table-cell office:value-type="string">'
  589. . '<text:p>'
  590. . htmlspecialchars($trigger['name'])
  591. . '</text:p>'
  592. . '</table:table-cell>';
  593. $GLOBALS['odt_buffer'] .= '<table:table-cell office:value-type="string">'
  594. . '<text:p>'
  595. . htmlspecialchars($trigger['action_timing'])
  596. . '</text:p>'
  597. . '</table:table-cell>';
  598. $GLOBALS['odt_buffer'] .= '<table:table-cell office:value-type="string">'
  599. . '<text:p>'
  600. . htmlspecialchars($trigger['event_manipulation'])
  601. . '</text:p>'
  602. . '</table:table-cell>';
  603. $GLOBALS['odt_buffer'] .= '<table:table-cell office:value-type="string">'
  604. . '<text:p>'
  605. . htmlspecialchars($trigger['definition'])
  606. . '</text:p>'
  607. . '</table:table-cell>';
  608. $GLOBALS['odt_buffer'] .= '</table:table-row>';
  609. }
  610. $GLOBALS['odt_buffer'] .= '</table:table>';
  611. return true;
  612. }
  613. /**
  614. * Outputs table's structure
  615. *
  616. * @param string $db database name
  617. * @param string $table table name
  618. * @param string $crlf the end of line sequence
  619. * @param string $error_url the url to go back in case of error
  620. * @param string $export_mode 'create_table', 'triggers', 'create_view',
  621. * 'stand_in'
  622. * @param string $export_type 'server', 'database', 'table'
  623. * @param bool $do_relation whether to include relation comments
  624. * @param bool $do_comments whether to include the pmadb-style column
  625. * comments as comments in the structure;
  626. * this is deprecated but the parameter is
  627. * left here because export.php calls
  628. * PMA_exportStructure() also for other
  629. * @param bool $do_mime whether to include mime comments
  630. * @param bool $dates whether to include creation/update/check dates
  631. * @param array $aliases Aliases of db/table/columns
  632. *
  633. * @return bool Whether it succeeded
  634. */
  635. public function exportStructure(
  636. $db,
  637. $table,
  638. $crlf,
  639. $error_url,
  640. $export_mode,
  641. $export_type,
  642. $do_relation = false,
  643. $do_comments = false,
  644. $do_mime = false,
  645. $dates = false,
  646. array $aliases = array()
  647. ) {
  648. $db_alias = $db;
  649. $table_alias = $table;
  650. $this->initAlias($aliases, $db_alias, $table_alias);
  651. switch ($export_mode) {
  652. case 'create_table':
  653. $GLOBALS['odt_buffer']
  654. .= '<text:h text:outline-level="2" text:style-name="Heading_2"'
  655. . ' text:is-list-header="true">'
  656. . __('Table structure for table') . ' ' .
  657. htmlspecialchars($table_alias)
  658. . '</text:h>';
  659. $this->getTableDef(
  660. $db,
  661. $table,
  662. $crlf,
  663. $error_url,
  664. $do_relation,
  665. $do_comments,
  666. $do_mime,
  667. $dates,
  668. true,
  669. false,
  670. $aliases
  671. );
  672. break;
  673. case 'triggers':
  674. $triggers = $GLOBALS['dbi']->getTriggers($db, $table, $aliases);
  675. if ($triggers) {
  676. $GLOBALS['odt_buffer']
  677. .= '<text:h text:outline-level="2" text:style-name="Heading_2"'
  678. . ' text:is-list-header="true">'
  679. . __('Triggers') . ' '
  680. . htmlspecialchars($table_alias)
  681. . '</text:h>';
  682. $this->getTriggers($db, $table);
  683. }
  684. break;
  685. case 'create_view':
  686. $GLOBALS['odt_buffer']
  687. .= '<text:h text:outline-level="2" text:style-name="Heading_2"'
  688. . ' text:is-list-header="true">'
  689. . __('Structure for view') . ' '
  690. . htmlspecialchars($table_alias)
  691. . '</text:h>';
  692. $this->getTableDef(
  693. $db,
  694. $table,
  695. $crlf,
  696. $error_url,
  697. $do_relation,
  698. $do_comments,
  699. $do_mime,
  700. $dates,
  701. true,
  702. true,
  703. $aliases
  704. );
  705. break;
  706. case 'stand_in':
  707. $GLOBALS['odt_buffer']
  708. .= '<text:h text:outline-level="2" text:style-name="Heading_2"'
  709. . ' text:is-list-header="true">'
  710. . __('Stand-in structure for view') . ' '
  711. . htmlspecialchars($table_alias)
  712. . '</text:h>';
  713. // export a stand-in definition to resolve view dependencies
  714. $this->getTableDefStandIn($db, $table, $crlf, $aliases);
  715. } // end switch
  716. return true;
  717. } // end of the '$this->exportStructure' function
  718. /**
  719. * Formats the definition for one column
  720. *
  721. * @param array $column info about this column
  722. * @param string $col_as column alias
  723. *
  724. * @return string Formatted column definition
  725. */
  726. protected function formatOneColumnDefinition($column, $col_as = '')
  727. {
  728. if (empty($col_as)) {
  729. $col_as = $column['Field'];
  730. }
  731. $definition = '<table:table-row>';
  732. $definition .= '<table:table-cell office:value-type="string">'
  733. . '<text:p>' . htmlspecialchars($col_as) . '</text:p>'
  734. . '</table:table-cell>';
  735. $extracted_columnspec
  736. = Util::extractColumnSpec($column['Type']);
  737. $type = htmlspecialchars($extracted_columnspec['print_type']);
  738. if (empty($type)) {
  739. $type = '&nbsp;';
  740. }
  741. $definition .= '<table:table-cell office:value-type="string">'
  742. . '<text:p>' . htmlspecialchars($type) . '</text:p>'
  743. . '</table:table-cell>';
  744. if (!isset($column['Default'])) {
  745. if ($column['Null'] != 'NO') {
  746. $column['Default'] = 'NULL';
  747. } else {
  748. $column['Default'] = '';
  749. }
  750. }
  751. $definition .= '<table:table-cell office:value-type="string">'
  752. . '<text:p>'
  753. . (($column['Null'] == '' || $column['Null'] == 'NO')
  754. ? __('No')
  755. : __('Yes'))
  756. . '</text:p>'
  757. . '</table:table-cell>';
  758. $definition .= '<table:table-cell office:value-type="string">'
  759. . '<text:p>' . htmlspecialchars($column['Default']) . '</text:p>'
  760. . '</table:table-cell>';
  761. return $definition;
  762. }
  763. }