diff --git a/libraries/plugins/ExportPlugin.class.php b/libraries/plugins/ExportPlugin.class.php index 62bc132715..1410234dd6 100644 --- a/libraries/plugins/ExportPlugin.class.php +++ b/libraries/plugins/ExportPlugin.class.php @@ -192,20 +192,6 @@ abstract class ExportPlugin extends PluginObserver ; } - /** - * Formats the definition for one column - * - * @param array $column info about this column - * @param array $unique_keys unique keys of the table - * - * @return string Formatted column definition - */ - protected function formatOneColumnDefinition( - $column, $unique_keys - ) { - ; - } - /** * Initializes the local variables with the global values. * These are variables that are used by all of the export plugins. diff --git a/libraries/plugins/export/ExportOdt.class.php b/libraries/plugins/export/ExportOdt.class.php new file mode 100644 index 0000000000..8d2f382c38 --- /dev/null +++ b/libraries/plugins/export/ExportOdt.class.php @@ -0,0 +1,797 @@ +initLocalVariables(); + + $this->setProperties(); + } + + /** + * Initialize the local variables that are used for export ODT + * + * @return void + */ + private function initLocalVariables() + { + global $what; + global $plugin_param; + global $cfgRelation; + $this->setWhat($what); + $this->setPluginParam($plugin_param); + $this->setCfgRelation($cfgRelation); + } + + /** + * Sets the export XML properties + * + * @return void + */ + protected function setProperties() + { + $plugin_param = $this->getPluginParam(); + $hide_structure = false; + if ($plugin_param['export_type'] == 'table' + && ! $plugin_param['single_table'] + ) { + $hide_structure = true; + } + + $this->properties = array( + 'text' => __('Open Document Text'), + 'extension' => 'odt', + 'mime_type' => 'application/vnd.oasis.opendocument.text', + 'force_file' => true, + 'options' => array(), + 'options_text' => __('Options') + ); + + /* what to dump (structure/data/both) */ + $this->properties['options'][] = array( + 'type' => 'begin_group', + 'text' => __('Dump table'), + 'name' => 'general_opts' + ); + $this->properties['options'][] = array( + 'type' => 'radio', + 'name' => 'structure_or_data', + 'values' => array( + 'structure' => __('structure'), + 'data' => __('data'), + 'structure_and_data' => __('structure and data') + ) + ); + $this->properties['options'][] = array( + 'type' => 'end_group' + ); + + /* Structure options */ + if (! $hide_structure) { + $this->properties['options'][] = array( + 'type' => 'begin_group', + 'name' => 'structure', + 'text' => __('Object creation options'), + 'force' => 'data' + ); + if (! empty($GLOBALS['cfgRelation']['relation'])) { + $this->properties['options'][] = array( + 'type' => 'bool', + 'name' => 'relation', + 'text' => __('Display foreign key relationships') + ); + } + $this->properties['options'][] = array( + 'type' => 'bool', + 'name' => 'comments', + 'text' => __('Display comments') + ); + if (! empty($GLOBALS['cfgRelation']['mimework'])) { + $this->properties['options'][] = array( + 'type' => 'bool', + 'name' => 'mime', + 'text' => __('Display MIME types') + ); + } + $this->properties['options'][] = array( + 'type' => 'end_group' + ); + } + + /* Data */ + $this->properties['options'][] = array( + 'type' => 'begin_group', + 'name' => 'data', + 'text' => __('Data dump options'), + 'force' => 'structure' + ); + $this->properties['options'][] = array( + 'type' => 'bool', + 'name' => 'columns', + 'text' => __('Put columns names in the first row') + ); + $this->properties['options'][] = array( + 'type' => 'text', + 'name' => 'null', + 'text' => __('Replace NULL with:') + ); + $this->properties['options'][] = array( + 'type' => 'end_group' + ); + } + + /** + * This method is called when any PluginManager to which the observer + * is attached calls PluginManager::notify() + * + * @param SplSubject $subject The PluginManager notifying the observer + * of an update. + * + * @return void + */ + public function update (SplSubject $subject) + { + } + + /** + * Outputs export header + * + * @return bool Whether it succeeded + */ + public function exportHeader () + { + // initialize the general export variables + $this->initExportCommonVariables(); + + $GLOBALS['odt_buffer'] .= '' + . '' + . '' + . ''; + return true; + } + + /** + * Outputs export footer + * + * @return bool Whether it succeeded + */ + public function exportFooter () + { + $GLOBALS['odt_buffer'] .= '' + . '' + . ''; + if (! PMA_exportOutputHandler( + PMA_createOpenDocument( + 'application/vnd.oasis.opendocument.text', + $GLOBALS['odt_buffer'] + ) + )) { + return false; + } + return true; + } + + /** + * Outputs database header + * + * @param string $db Database name + * + * @return bool Whether it succeeded + */ + public function exportDBHeader ($db) + { + $GLOBALS['odt_buffer'] .= + '' + . __('Database') . ' ' . htmlspecialchars($db) + . ''; + return true; + } + + /** + * Outputs database footer + * + * @param string $db Database name + * + * @return bool Whether it succeeded + */ + public function exportDBFooter ($db) + { + return true; + } + + /** + * Outputs CREATE DATABASE statement + * + * @param string $db Database name + * + * @return bool Whether it succeeded + */ + public function exportDBCreate($db) + { + return true; + } + /** + * Outputs the content of a table in NHibernate format + * + * @param string $db database name + * @param string $table table name + * @param string $crlf the end of line sequence + * @param string $error_url the url to go back in case of error + * @param string $sql_query SQL query for obtaining data + * + * @return bool Whether it succeeded + * + * @access public + */ + public function exportData($db, $table, $crlf, $error_url, $sql_query) + { + $what = $this->getWhat(); + + // Gets the data from the database + $result = PMA_DBI_query($sql_query, null, PMA_DBI_QUERY_UNBUFFERED); + $fields_cnt = PMA_DBI_num_fields($result); + $fields_meta = PMA_DBI_get_fields_meta($result); + $field_flags = array(); + for ($j = 0; $j < $fields_cnt; $j++) { + $field_flags[$j] = PMA_DBI_field_flags($result, $j); + } + + $GLOBALS['odt_buffer'] .= + '' + . __('Dumping data for table') . ' ' . htmlspecialchars($table) + . '' + . '' + . ''; + + // If required, get fields name at the first line + if (isset($GLOBALS[$what . '_columns'])) { + $GLOBALS['odt_buffer'] .= ''; + for ($i = 0; $i < $fields_cnt; $i++) { + $GLOBALS['odt_buffer'] .= + '' + . '' + . htmlspecialchars( + stripslashes(PMA_DBI_field_name($result, $i)) + ) + . '' + . ''; + } // end for + $GLOBALS['odt_buffer'] .= ''; + } // end if + + // Format the data + while ($row = PMA_DBI_fetch_row($result)) { + $GLOBALS['odt_buffer'] .= ''; + for ($j = 0; $j < $fields_cnt; $j++) { + if (! isset($row[$j]) || is_null($row[$j])) { + $GLOBALS['odt_buffer'] .= + '' + . '' + . htmlspecialchars($GLOBALS[$what . '_null']) + . '' + . ''; + } elseif (stristr($field_flags[$j], 'BINARY') + && $fields_meta[$j]->blob + ) { + // ignore BLOB + $GLOBALS['odt_buffer'] .= + '' + . '' + . ''; + } elseif ($fields_meta[$j]->numeric + && $fields_meta[$j]->type != 'timestamp' + && ! $fields_meta[$j]->blob + ) { + $GLOBALS['odt_buffer'] .= + '' + . '' + . htmlspecialchars($row[$j]) + . '' + . ''; + } else { + $GLOBALS['odt_buffer'] .= + '' + . '' + . htmlspecialchars($row[$j]) + . '' + . ''; + } + } // end for + $GLOBALS['odt_buffer'] .= ''; + } // end while + PMA_DBI_free_result($result); + + $GLOBALS['odt_buffer'] .= ''; + + return true; + } + + /** + * Returns a stand-in CREATE definition to resolve view dependencies + * + * @param string $db the database name + * @param string $view the view name + * @param string $crlf the end of line sequence + * + * @return bool true + */ + function getTableDefStandIn($db, $view, $crlf) + { + /** + * Gets fields properties + */ + PMA_DBI_select_db($db); + + /** + * Displays the table structure + */ + $GLOBALS['odt_buffer'] .= + ''; + $columns_cnt = 4; + $GLOBALS['odt_buffer'] .= + ''; + /* Header */ + $GLOBALS['odt_buffer'] .= '' + . '' + . '' . __('Column') . '' + . '' + . '' + . '' . __('Type') . '' + . '' + . '' + . '' . __('Null') . '' + . '' + . '' + . '' . __('Default') . '' + . '' + . ''; + + $columns = PMA_DBI_get_columns($db, $view); + foreach ($columns as $column) { + $GLOBALS['odt_buffer'] .= $this->formatOneColumnDefinition($column); + $GLOBALS['odt_buffer'] .= ''; + } // end foreach + + $GLOBALS['odt_buffer'] .= ''; + return true; + } + + /** + * Returns $table's CREATE definition + * + * @param string $db the database name + * @param string $table the table name + * @param string $crlf the end of line sequence + * @param string $error_url the url to go back in case of error + * @param bool $do_relation whether to include relation comments + * @param bool $do_comments whether to include the pmadb-style column + * comments as comments in the structure; + * this is deprecated but the parameter is + * left here because export.php calls + * PMA_exportStructure() also for other + * @param bool $do_mime whether to include mime comments + * @param bool $show_dates whether to include creation/update/check dates + * @param bool $add_semicolon whether to add semicolon and end-of-line at + * the end + * @param bool $view whether we're handling a view + */ + public function getTableDef( + $db, + $table, + $crlf, + $error_url, + $do_relation, + $do_comments, + $do_mime, + $show_dates = false, + $add_semicolon = true, + $view = false + ) { + $cfgRelation = $this->getCfgRelation(); + + /** + * Gets fields properties + */ + PMA_DBI_select_db($db); + + // Check if we can use Relations + if ($do_relation && ! empty($cfgRelation['relation'])) { + // Find which tables are related with the current one and write it in + // an array + $res_rel = PMA_getForeigners($db, $table); + + if ($res_rel && count($res_rel) > 0) { + $have_rel = true; + } else { + $have_rel = false; + } + } else { + $have_rel = false; + } // end if + + /** + * Displays the table structure + */ + $GLOBALS['odt_buffer'] .= ''; + $columns_cnt = 4; + if ($do_relation && $have_rel) { + $columns_cnt++; + } + if ($do_comments) { + $columns_cnt++; + } + if ($do_mime && $cfgRelation['mimework']) { + $columns_cnt++; + } + $GLOBALS['odt_buffer'] .= ''; + /* Header */ + $GLOBALS['odt_buffer'] .= '' + . '' + . '' . __('Column') . '' + . '' + . '' + . '' . __('Type') . '' + . '' + . '' + . '' . __('Null') . '' + . '' + . '' + . '' . __('Default') . '' + . ''; + if ($do_relation && $have_rel) { + $GLOBALS['odt_buffer'] .= '' + . '' . __('Links to') . '' + . ''; + } + if ($do_comments) { + $GLOBALS['odt_buffer'] .= '' + . '' . __('Comments') . '' + . ''; + $comments = PMA_getComments($db, $table); + } + if ($do_mime && $cfgRelation['mimework']) { + $GLOBALS['odt_buffer'] .= '' + . '' . __('MIME type') . '' + . ''; + $mime_map = PMA_getMIME($db, $table, true); + } + $GLOBALS['odt_buffer'] .= ''; + + $columns = PMA_DBI_get_columns($db, $table); + foreach ($columns as $column) { + $field_name = $column['Field']; + $GLOBALS['odt_buffer'] .= $this->formatOneColumnDefinition($column); + + if ($do_relation && $have_rel) { + if (isset($res_rel[$field_name])) { + $GLOBALS['odt_buffer'] .= + '' + . '' + . htmlspecialchars( + $res_rel[$field_name]['foreign_table'] + . ' (' . $res_rel[$field_name]['foreign_field'] . ')' + ) + . '' + . ''; + } + } + if ($do_comments) { + if (isset($comments[$field_name])) { + $GLOBALS['odt_buffer'] .= + '' + . '' + . htmlspecialchars($comments[$field_name]) + . '' + . ''; + } else { + $GLOBALS['odt_buffer'] .= + '' + . '' + . ''; + } + } + if ($do_mime && $cfgRelation['mimework']) { + if (isset($mime_map[$field_name])) { + $GLOBALS['odt_buffer'] .= + '' + . '' + . htmlspecialchars( + str_replace('_', '/', $mime_map[$field_name]['mimetype']) + ) + . '' + . ''; + } else { + $GLOBALS['odt_buffer'] .= + '' + . '' + . ''; + } + } + $GLOBALS['odt_buffer'] .= ''; + } // end foreach + + $GLOBALS['odt_buffer'] .= ''; + return true; + } // end of the '$this->getTableDef()' function + + /** + * Outputs triggers + * + * @param string $db database name + * @param string $table table name + * + * @return bool true + */ + function getTriggers($db, $table) + { + $GLOBALS['odt_buffer'] .= '' + . '' + . '' + . '' + . '' . __('Name') . '' + . '' + . '' + . '' . __('Time') . '' + . '' + . '' + . '' . __('Event') . '' + . '' + . '' + . '' . __('Definition') . '' + . '' + . ''; + + $triggers = PMA_DBI_get_triggers($db, $table); + + foreach ($triggers as $trigger) { + $GLOBALS['odt_buffer'] .= ''; + $GLOBALS['odt_buffer'] .= '' + . '' + . htmlspecialchars($trigger['name']) + . '' + . ''; + $GLOBALS['odt_buffer'] .= '' + . '' + . htmlspecialchars($trigger['action_timing']) + . '' + . ''; + $GLOBALS['odt_buffer'] .= '' + . '' + . htmlspecialchars($trigger['event_manipulation']) + . '' + . ''; + $GLOBALS['odt_buffer'] .= '' + . '' + . htmlspecialchars($trigger['definition']) + . '' + . ''; + $GLOBALS['odt_buffer'] .= ''; + } + + $GLOBALS['odt_buffer'] .= ''; + return true; + } + + /** + * Outputs table's structure + * + * @param string $db database name + * @param string $table table name + * @param string $crlf the end of line sequence + * @param string $error_url the url to go back in case of error + * @param string $export_mode 'create_table', 'triggers', 'create_view', + * 'stand_in' + * @param string $export_type 'server', 'database', 'table' + * @param bool $do_relation whether to include relation comments + * @param bool $do_comments whether to include the pmadb-style column + * comments as comments in the structure; + * this is deprecated but the parameter is + * left here because export.php calls + * PMA_exportStructure() also for other + * @param bool $do_mime whether to include mime comments + * @param bool $dates whether to include creation/update/check dates + * + * @return bool Whether it succeeded + */ + function exportStructure( + $db, + $table, + $crlf, + $error_url, + $export_mode, + $export_type, + $do_relation = false, + $do_comments = false, + $do_mime = false, + $dates = false + ) { + switch($export_mode) { + case 'create_table': + $GLOBALS['odt_buffer'] .= + '' + . __('Table structure for table') . ' ' . + htmlspecialchars($table) + . ''; + $this->getTableDef( + $db, $table, $crlf, $error_url, $do_relation, $do_comments, + $do_mime, $dates + ); + break; + case 'triggers': + $triggers = PMA_DBI_get_triggers($db, $table); + if ($triggers) { + $GLOBALS['odt_buffer'] .= + '' + . __('Triggers') . ' ' + . htmlspecialchars($table) + . ''; + $this->getTriggers($db, $table); + } + break; + case 'create_view': + $GLOBALS['odt_buffer'] .= + '' + . __('Structure for view') . ' ' + . htmlspecialchars($table) + . ''; + $this->getTableDef( + $db, $table, $crlf, $error_url, $do_relation, $do_comments, + $do_mime, $dates, true, true + ); + break; + case 'stand_in': + $GLOBALS['odt_buffer'] .= + '' + . __('Stand-in structure for view') . ' ' + . htmlspecialchars($table) + . ''; + // export a stand-in definition to resolve view dependencies + $this->getTableDefStandIn($db, $table, $crlf); + } // end switch + + return true; + } // end of the '$this->exportStructure' function + + /** + * Formats the definition for one column + * + * @param array $column info about this column + * + * @return string Formatted column definition + */ + protected function formatOneColumnDefinition($column) + { + $field_name = $column['Field']; + $definition = ''; + $definition .= '' + . '' . htmlspecialchars($field_name) . '' + . ''; + + $extracted_columnspec = PMA_extractColumnSpec($column['Type']); + $type = htmlspecialchars($extracted_columnspec['print_type']); + if (empty($type)) { + $type = ' '; + } + + $definition .= '' + . '' . htmlspecialchars($type) . '' + . ''; + if (! isset($column['Default'])) { + if ($column['Null'] != 'NO') { + $column['Default'] = 'NULL'; + } else { + $column['Default'] = ''; + } + } else { + $column['Default'] = $column['Default']; + } + $definition .= '' + . '' + . (($column['Null'] == '' || $column['Null'] == 'NO') + ? __('No') + : __('Yes')) + . '' + . ''; + $definition .= '' + . '' . htmlspecialchars($column['Default']) . '' + . ''; + return $definition; + } + + + /* ~~~~~~~~~~~~~~~~~~~~ Getters and Setters ~~~~~~~~~~~~~~~~~~~~ */ + + + public function getWhat() + { + return $this->_what; + } + + public function setWhat($what) + { + $this->_what = $what; + } + + public function getPluginParam() + { + return $this->_pluginParam; + } + + private function setPluginParam($pluginParam) + { + $this->_pluginParam = $pluginParam; + } + + public function getCfgRelation() + { + return $this->_cfgRelation; + } + + private function setCfgRelation($cfgRelation) + { + $this->_cfgRelation = $cfgRelation; + } +} +?> \ No newline at end of file