aboutsummaryrefslogtreecommitdiff
path: root/srcs/phpmyadmin/libraries/classes/Operations.php
diff options
context:
space:
mode:
Diffstat (limited to 'srcs/phpmyadmin/libraries/classes/Operations.php')
-rw-r--r--srcs/phpmyadmin/libraries/classes/Operations.php2263
1 files changed, 2263 insertions, 0 deletions
diff --git a/srcs/phpmyadmin/libraries/classes/Operations.php b/srcs/phpmyadmin/libraries/classes/Operations.php
new file mode 100644
index 0000000..7cedd17
--- /dev/null
+++ b/srcs/phpmyadmin/libraries/classes/Operations.php
@@ -0,0 +1,2263 @@
+<?php
+/* vim: set expandtab sw=4 ts=4 sts=4: */
+/**
+ * Holds the PhpMyAdmin\Operations class
+ *
+ * @package PhpMyAdmin
+ */
+declare(strict_types=1);
+
+namespace PhpMyAdmin;
+
+use PhpMyAdmin\Charsets\Charset;
+use PhpMyAdmin\Charsets\Collation;
+use PhpMyAdmin\Engines\Innodb;
+use PhpMyAdmin\Plugins\Export\ExportSql;
+
+/**
+ * Set of functions with the operations section in phpMyAdmin
+ *
+ * @package PhpMyAdmin
+ */
+class Operations
+{
+ /**
+ * @var Relation
+ */
+ private $relation;
+
+ /**
+ * @var DatabaseInterface
+ */
+ private $dbi;
+
+ /**
+ * Operations constructor.
+ *
+ * @param DatabaseInterface $dbi DatabaseInterface object
+ * @param Relation $relation Relation object
+ */
+ public function __construct(DatabaseInterface $dbi, Relation $relation)
+ {
+ $this->dbi = $dbi;
+ $this->relation = $relation;
+ }
+
+ /**
+ * Get HTML output for database comment
+ *
+ * @param string $db database name
+ *
+ * @return string
+ */
+ public function getHtmlForDatabaseComment($db)
+ {
+ $html_output = '<div>'
+ . '<form method="post" action="db_operations.php" id="formDatabaseComment">'
+ . Url::getHiddenInputs($db)
+ . '<fieldset>'
+ . '<legend>';
+ if (Util::showIcons('ActionLinksMode')) {
+ $html_output .= Util::getImage('b_comment') . '&nbsp;';
+ }
+ $html_output .= __('Database comment');
+ $html_output .= '</legend>';
+ $html_output .= '<input type="text" name="comment" '
+ . 'class="textfield"'
+ . 'value="' . htmlspecialchars($this->relation->getDbComment($db)) . '">'
+ . '</fieldset>';
+ $html_output .= '<fieldset class="tblFooters">'
+ . '<input class="btn btn-primary" type="submit" value="' . __('Go') . '">'
+ . '</fieldset>'
+ . '</form>'
+ . '</div>';
+
+ return $html_output;
+ }
+
+ /**
+ * Get HTML output for rename database
+ *
+ * @param string $db database name
+ * @param string $db_collation dataset collation
+ *
+ * @return string
+ */
+ public function getHtmlForRenameDatabase($db, $db_collation)
+ {
+ $html_output = '<div>'
+ . '<form id="rename_db_form" '
+ . 'class="ajax" '
+ . 'method="post" action="db_operations.php" '
+ . 'onsubmit="return Functions.emptyCheckTheField(this, \'newname\')">';
+ if ($db_collation !== null) {
+ $html_output .= '<input type="hidden" name="db_collation" '
+ . 'value="' . $db_collation
+ . '">' . "\n";
+ }
+ $html_output .= '<input type="hidden" name="what" value="data">'
+ . '<input type="hidden" name="db_rename" value="true">'
+ . Url::getHiddenInputs($db)
+ . '<fieldset>'
+ . '<legend>';
+
+ if (Util::showIcons('ActionLinksMode')) {
+ $html_output .= Util::getImage('b_edit') . '&nbsp;';
+ }
+ $html_output .= __('Rename database to')
+ . '</legend>';
+
+ $html_output .= '<input id="new_db_name" type="text" name="newname" '
+ . 'maxlength="64" class="textfield" required="required">';
+ $html_output .= '<br>';
+
+ if ($GLOBALS['db_priv'] && $GLOBALS['table_priv']
+ && $GLOBALS['col_priv'] && $GLOBALS['proc_priv']
+ && $GLOBALS['is_reload_priv']
+ ) {
+ $html_output .= '<input type="checkbox" name="adjust_privileges" '
+ . 'value="1" id="checkbox_adjust_privileges" checked="checked">';
+ } else {
+ $html_output .= '<input type="checkbox" name="adjust_privileges" '
+ . 'value="1" id="checkbox_adjust_privileges" title="' . __(
+ 'You don\'t have sufficient privileges to perform this '
+ . 'operation; Please refer to the documentation for more details'
+ )
+ . '" disabled>';
+ }
+
+ $html_output .= '<label for="checkbox_adjust_privileges">'
+ . __('Adjust privileges') . Util::showDocu('faq', 'faq6-39')
+ . '</label><br>';
+
+ $html_output .= ''
+ . '</fieldset>'
+ . '<fieldset class="tblFooters">'
+ . '<input id="rename_db_input" class="btn btn-primary" type="submit" value="' . __('Go') . '">'
+ . '</fieldset>'
+ . '</form>'
+ . '</div>';
+
+ return $html_output;
+ }
+
+ /**
+ * Get HTML for database drop link
+ *
+ * @param string $db database name
+ *
+ * @return string
+ */
+ public function getHtmlForDropDatabaseLink($db)
+ {
+ $this_sql_query = 'DROP DATABASE ' . Util::backquote($db);
+ $this_url_params = [
+ 'sql_query' => $this_sql_query,
+ 'back' => 'db_operations.php',
+ 'goto' => 'index.php',
+ 'reload' => '1',
+ 'purge' => '1',
+ 'message_to_show' => sprintf(
+ __('Database %s has been dropped.'),
+ htmlspecialchars(Util::backquote($db))
+ ),
+ 'db' => null,
+ ];
+
+ $html_output = '<div>'
+ . '<fieldset class="caution">';
+ $html_output .= '<legend>';
+ if (Util::showIcons('ActionLinksMode')) {
+ $html_output .= Util::getImage('b_deltbl') . '&nbsp';
+ }
+ $html_output .= __('Remove database')
+ . '</legend>';
+ $html_output .= '<ul>';
+ $html_output .= $this->getDeleteDataOrTablelink(
+ $this_url_params,
+ 'DROP_DATABASE',
+ __('Drop the database (DROP)'),
+ 'drop_db_anchor'
+ );
+ $html_output .= '</ul></fieldset>'
+ . '</div>';
+
+ return $html_output;
+ }
+
+ /**
+ * Get HTML snippet for copy database
+ *
+ * @param string $db database name
+ * @param string $db_collation dataset collation
+ *
+ * @return string
+ */
+ public function getHtmlForCopyDatabase($db, $db_collation)
+ {
+ $drop_clause = 'DROP TABLE / DROP VIEW';
+ $choices = [
+ 'structure' => __('Structure only'),
+ 'data' => __('Structure and data'),
+ 'dataonly' => __('Data only'),
+ ];
+
+ $pma_switch_to_new = isset($_SESSION['pma_switch_to_new']) && $_SESSION['pma_switch_to_new'];
+
+ $html_output = '<div>';
+ $html_output .= '<form id="copy_db_form" '
+ . 'class="ajax" '
+ . 'method="post" action="db_operations.php" '
+ . 'onsubmit="return Functions.emptyCheckTheField(this, \'newname\')">';
+
+ if ($db_collation !== null) {
+ $html_output .= '<input type="hidden" name="db_collation" '
+ . 'value="' . $db_collation . '">' . "\n";
+ }
+ $html_output .= '<input type="hidden" name="db_copy" value="true">' . "\n"
+ . Url::getHiddenInputs($db);
+ $html_output .= '<fieldset>'
+ . '<legend>';
+
+ if (Util::showIcons('ActionLinksMode')) {
+ $html_output .= Util::getImage('b_edit') . '&nbsp';
+ }
+ $html_output .= __('Copy database to')
+ . '</legend>'
+ . '<input type="text" maxlength="64" name="newname" '
+ . 'class="textfield" required="required"><br>'
+ . Util::getRadioFields(
+ 'what',
+ $choices,
+ 'data',
+ true
+ );
+ $html_output .= '<br>';
+ $html_output .= '<input type="checkbox" name="create_database_before_copying" '
+ . 'value="1" id="checkbox_create_database_before_copying"'
+ . 'checked="checked">';
+ $html_output .= '<label for="checkbox_create_database_before_copying">'
+ . __('CREATE DATABASE before copying') . '</label><br>';
+ $html_output .= '<input type="checkbox" name="drop_if_exists" value="true"'
+ . 'id="checkbox_drop">';
+ $html_output .= '<label for="checkbox_drop">'
+ . sprintf(__('Add %s'), $drop_clause)
+ . '</label><br>';
+ $html_output .= '<input type="checkbox" name="sql_auto_increment" value="1" '
+ . 'checked="checked" id="checkbox_auto_increment">';
+ $html_output .= '<label for="checkbox_auto_increment">'
+ . __('Add AUTO_INCREMENT value') . '</label><br>';
+ $html_output .= '<input type="checkbox" name="add_constraints" value="1"'
+ . 'id="checkbox_constraints" checked="checked">';
+ $html_output .= '<label for="checkbox_constraints">'
+ . __('Add constraints') . '</label><br>';
+ $html_output .= '<br>';
+
+ if ($GLOBALS['db_priv'] && $GLOBALS['table_priv']
+ && $GLOBALS['col_priv'] && $GLOBALS['proc_priv']
+ && $GLOBALS['is_reload_priv']
+ ) {
+ $html_output .= '<input type="checkbox" name="adjust_privileges" '
+ . 'value="1" id="checkbox_privileges" checked="checked">';
+ } else {
+ $html_output .= '<input type="checkbox" name="adjust_privileges" '
+ . 'value="1" id="checkbox_privileges" title="' . __(
+ 'You don\'t have sufficient privileges to perform this '
+ . 'operation; Please refer to the documentation for more details'
+ )
+ . '" disabled>';
+ }
+ $html_output .= '<label for="checkbox_privileges">'
+ . __('Adjust privileges') . Util::showDocu('faq', 'faq6-39')
+ . '</label><br>';
+
+ $html_output .= '<input type="checkbox" name="switch_to_new" value="true"'
+ . 'id="checkbox_switch"'
+ . ($pma_switch_to_new ? ' checked="checked"' : '') . '>';
+ $html_output .= '<label for="checkbox_switch">'
+ . __('Switch to copied database') . '</label>'
+ . '</fieldset>';
+ $html_output .= '<fieldset class="tblFooters">'
+ . '<input class="btn btn-primary" type="submit" name="submit_copy" value="' . __('Go') . '">'
+ . '</fieldset>'
+ . '</form>'
+ . '</div>';
+
+ return $html_output;
+ }
+
+ /**
+ * Get HTML snippet for change database charset
+ *
+ * @param string $db database name
+ * @param string $db_collation dataset collation
+ *
+ * @return string
+ */
+ public function getHtmlForChangeDatabaseCharset($db, $db_collation)
+ {
+ $html_output = '<div>'
+ . '<form id="change_db_charset_form" ';
+ $html_output .= 'class="ajax" ';
+ $html_output .= 'method="post" action="db_operations.php">';
+
+ $html_output .= Url::getHiddenInputs($db);
+
+ $html_output .= '<fieldset>' . "\n"
+ . ' <legend>';
+ if (Util::showIcons('ActionLinksMode')) {
+ $html_output .= Util::getImage('s_asci') . '&nbsp';
+ }
+ $html_output .= '<label for="select_db_collation">' . __('Collation')
+ . '</label>' . "\n"
+ . '</legend>' . "\n";
+ $html_output .= '<select lang="en" dir="ltr" name="db_collation" id="select_db_collation">' . "\n";
+ $html_output .= '<option value=""></option>' . "\n";
+
+ $charsets = Charsets::getCharsets($this->dbi, $GLOBALS['cfg']['Server']['DisableIS']);
+ $collations = Charsets::getCollations($this->dbi, $GLOBALS['cfg']['Server']['DisableIS']);
+ /** @var Charset $charset */
+ foreach ($charsets as $charset) {
+ $html_output .= '<optgroup label="' . $charset->getName()
+ . '" title="' . $charset->getDescription() . '">' . "\n";
+ /** @var Collation $collation */
+ foreach ($collations[$charset->getName()] as $collation) {
+ $html_output .= '<option value="' . $collation->getName()
+ . '" title="' . $collation->getDescription() . '"'
+ . ($db_collation == $collation->getName() ? ' selected' : '') . '>'
+ . $collation->getName() . '</option>' . "\n";
+ }
+ $html_output .= '</optgroup>' . "\n";
+ }
+ $html_output .= '</select>' . "\n";
+ $html_output .= '<br>'
+ . '<input type="checkbox" name="change_all_tables_collations"'
+ . 'id="checkbox_change_all_tables_collations">'
+ . '<label for="checkbox_change_all_tables_collations">'
+ . __('Change all tables collations')
+ . '</label>'
+ . '<br>'
+ . '<span id="span_change_all_tables_columns_collations"><input type="checkbox" name="change_all_tables_columns_collations"'
+ . 'id="checkbox_change_all_tables_columns_collations">'
+ . '<label for="checkbox_change_all_tables_columns_collations">'
+ . __('Change all tables columns collations')
+ . '</label></span>'
+ . '</fieldset>'
+ . '<fieldset class="tblFooters">'
+ . '<input class="btn btn-primary" type="submit" name="submitcollation"'
+ . ' value="' . __('Go') . '">' . "\n"
+ . '</fieldset>' . "\n"
+ . '</form></div>' . "\n";
+
+ return $html_output;
+ }
+
+ /**
+ * Run the Procedure definitions and function definitions
+ *
+ * to avoid selecting alternatively the current and new db
+ * we would need to modify the CREATE definitions to qualify
+ * the db name
+ *
+ * @param string $db database name
+ *
+ * @return void
+ */
+ public function runProcedureAndFunctionDefinitions($db)
+ {
+ $procedure_names = $this->dbi->getProceduresOrFunctions($db, 'PROCEDURE');
+ if ($procedure_names) {
+ foreach ($procedure_names as $procedure_name) {
+ $this->dbi->selectDb($db);
+ $tmp_query = $this->dbi->getDefinition(
+ $db,
+ 'PROCEDURE',
+ $procedure_name
+ );
+ if ($tmp_query !== null) {
+ // collect for later display
+ $GLOBALS['sql_query'] .= "\n" . $tmp_query;
+ $this->dbi->selectDb($_POST['newname']);
+ $this->dbi->query($tmp_query);
+ }
+ }
+ }
+
+ $function_names = $this->dbi->getProceduresOrFunctions($db, 'FUNCTION');
+ if ($function_names) {
+ foreach ($function_names as $function_name) {
+ $this->dbi->selectDb($db);
+ $tmp_query = $this->dbi->getDefinition(
+ $db,
+ 'FUNCTION',
+ $function_name
+ );
+ if ($tmp_query !== null) {
+ // collect for later display
+ $GLOBALS['sql_query'] .= "\n" . $tmp_query;
+ $this->dbi->selectDb($_POST['newname']);
+ $this->dbi->query($tmp_query);
+ }
+ }
+ }
+ }
+
+ /**
+ * Create database before copy
+ *
+ * @return void
+ */
+ public function createDbBeforeCopy()
+ {
+ $local_query = 'CREATE DATABASE IF NOT EXISTS '
+ . Util::backquote($_POST['newname']);
+ if (isset($_POST['db_collation'])) {
+ $local_query .= ' DEFAULT'
+ . Util::getCharsetQueryPart($_POST['db_collation']);
+ }
+ $local_query .= ';';
+ $GLOBALS['sql_query'] .= $local_query;
+
+ // save the original db name because Tracker.php which
+ // may be called under $this->dbi->query() changes $GLOBALS['db']
+ // for some statements, one of which being CREATE DATABASE
+ $original_db = $GLOBALS['db'];
+ $this->dbi->query($local_query);
+ $GLOBALS['db'] = $original_db;
+
+ // Set the SQL mode to NO_AUTO_VALUE_ON_ZERO to prevent MySQL from creating
+ // export statements it cannot import
+ $sql_set_mode = "SET SQL_MODE='NO_AUTO_VALUE_ON_ZERO'";
+ $this->dbi->query($sql_set_mode);
+
+ // rebuild the database list because Table::moveCopy
+ // checks in this list if the target db exists
+ $GLOBALS['dblist']->databases->build();
+ }
+
+ /**
+ * Get views as an array and create SQL view stand-in
+ *
+ * @param array $tables_full array of all tables in given db or dbs
+ * @param ExportSql $export_sql_plugin export plugin instance
+ * @param string $db database name
+ *
+ * @return array
+ */
+ public function getViewsAndCreateSqlViewStandIn(
+ array $tables_full,
+ $export_sql_plugin,
+ $db
+ ) {
+ $views = [];
+ foreach ($tables_full as $each_table => $tmp) {
+ // to be able to rename a db containing views,
+ // first all the views are collected and a stand-in is created
+ // the real views are created after the tables
+ if ($this->dbi->getTable($db, (string) $each_table)->isView()) {
+ // If view exists, and 'add drop view' is selected: Drop it!
+ if ($_POST['what'] != 'nocopy'
+ && isset($_POST['drop_if_exists'])
+ && $_POST['drop_if_exists'] == 'true'
+ ) {
+ $drop_query = 'DROP VIEW IF EXISTS '
+ . Util::backquote($_POST['newname']) . '.'
+ . Util::backquote($each_table);
+ $this->dbi->query($drop_query);
+
+ $GLOBALS['sql_query'] .= "\n" . $drop_query . ';';
+ }
+
+ $views[] = $each_table;
+ // Create stand-in definition to resolve view dependencies
+ $sql_view_standin = $export_sql_plugin->getTableDefStandIn(
+ $db,
+ $each_table,
+ "\n"
+ );
+ $this->dbi->selectDb($_POST['newname']);
+ $this->dbi->query($sql_view_standin);
+ $GLOBALS['sql_query'] .= "\n" . $sql_view_standin;
+ }
+ }
+ return $views;
+ }
+
+ /**
+ * Get sql query for copy/rename table and boolean for whether copy/rename or not
+ *
+ * @param array $tables_full array of all tables in given db or dbs
+ * @param boolean $move whether database name is empty or not
+ * @param string $db database name
+ *
+ * @return array SQL queries for the constraints
+ */
+ public function copyTables(array $tables_full, $move, $db)
+ {
+ $sqlContraints = [];
+ foreach ($tables_full as $each_table => $tmp) {
+ // skip the views; we have created stand-in definitions
+ if ($this->dbi->getTable($db, (string) $each_table)->isView()) {
+ continue;
+ }
+
+ // value of $what for this table only
+ $this_what = $_POST['what'];
+
+ // do not copy the data from a Merge table
+ // note: on the calling FORM, 'data' means 'structure and data'
+ if ($this->dbi->getTable($db, (string) $each_table)->isMerge()) {
+ if ($this_what == 'data') {
+ $this_what = 'structure';
+ }
+ if ($this_what == 'dataonly') {
+ $this_what = 'nocopy';
+ }
+ }
+
+ if ($this_what != 'nocopy') {
+ // keep the triggers from the original db+table
+ // (third param is empty because delimiters are only intended
+ // for importing via the mysql client or our Import feature)
+ $triggers = $this->dbi->getTriggers($db, (string) $each_table, '');
+
+ if (! Table::moveCopy(
+ $db,
+ $each_table,
+ $_POST['newname'],
+ $each_table,
+ (isset($this_what) ? $this_what : 'data'),
+ $move,
+ 'db_copy'
+ )) {
+ $GLOBALS['_error'] = true;
+ break;
+ }
+ // apply the triggers to the destination db+table
+ if ($triggers) {
+ $this->dbi->selectDb($_POST['newname']);
+ foreach ($triggers as $trigger) {
+ $this->dbi->query($trigger['create']);
+ $GLOBALS['sql_query'] .= "\n" . $trigger['create'] . ';';
+ }
+ }
+
+ // this does not apply to a rename operation
+ if (isset($_POST['add_constraints'])
+ && ! empty($GLOBALS['sql_constraints_query'])
+ ) {
+ $sqlContraints[] = $GLOBALS['sql_constraints_query'];
+ unset($GLOBALS['sql_constraints_query']);
+ }
+ }
+ }
+ return $sqlContraints;
+ }
+
+ /**
+ * Run the EVENT definition for selected database
+ *
+ * to avoid selecting alternatively the current and new db
+ * we would need to modify the CREATE definitions to qualify
+ * the db name
+ *
+ * @param string $db database name
+ *
+ * @return void
+ */
+ public function runEventDefinitionsForDb($db)
+ {
+ $event_names = $this->dbi->fetchResult(
+ 'SELECT EVENT_NAME FROM information_schema.EVENTS WHERE EVENT_SCHEMA= \''
+ . $this->dbi->escapeString($db) . '\';'
+ );
+ if ($event_names) {
+ foreach ($event_names as $event_name) {
+ $this->dbi->selectDb($db);
+ $tmp_query = $this->dbi->getDefinition($db, 'EVENT', $event_name);
+ // collect for later display
+ $GLOBALS['sql_query'] .= "\n" . $tmp_query;
+ $this->dbi->selectDb($_POST['newname']);
+ $this->dbi->query($tmp_query);
+ }
+ }
+ }
+
+ /**
+ * Handle the views, return the boolean value whether table rename/copy or not
+ *
+ * @param array $views views as an array
+ * @param boolean $move whether database name is empty or not
+ * @param string $db database name
+ *
+ * @return void
+ */
+ public function handleTheViews(array $views, $move, $db)
+ {
+ // temporarily force to add DROP IF EXIST to CREATE VIEW query,
+ // to remove stand-in VIEW that was created earlier
+ // ( $_POST['drop_if_exists'] is used in moveCopy() )
+ if (isset($_POST['drop_if_exists'])) {
+ $temp_drop_if_exists = $_POST['drop_if_exists'];
+ }
+
+ $_POST['drop_if_exists'] = 'true';
+ foreach ($views as $view) {
+ $copying_succeeded = Table::moveCopy(
+ $db,
+ $view,
+ $_POST['newname'],
+ $view,
+ 'structure',
+ $move,
+ 'db_copy'
+ );
+ if (! $copying_succeeded) {
+ $GLOBALS['_error'] = true;
+ break;
+ }
+ }
+ unset($_POST['drop_if_exists']);
+
+ if (isset($temp_drop_if_exists)) {
+ // restore previous value
+ $_POST['drop_if_exists'] = $temp_drop_if_exists;
+ }
+ }
+
+ /**
+ * Adjust the privileges after Renaming the db
+ *
+ * @param string $oldDb Database name before renaming
+ * @param string $newname New Database name requested
+ *
+ * @return void
+ */
+ public function adjustPrivilegesMoveDb($oldDb, $newname)
+ {
+ if ($GLOBALS['db_priv'] && $GLOBALS['table_priv']
+ && $GLOBALS['col_priv'] && $GLOBALS['proc_priv']
+ && $GLOBALS['is_reload_priv']
+ ) {
+ $this->dbi->selectDb('mysql');
+ $newname = str_replace("_", "\_", $newname);
+ $oldDb = str_replace("_", "\_", $oldDb);
+
+ // For Db specific privileges
+ $query_db_specific = 'UPDATE ' . Util::backquote('db')
+ . 'SET Db = \'' . $this->dbi->escapeString($newname)
+ . '\' where Db = \'' . $this->dbi->escapeString($oldDb) . '\';';
+ $this->dbi->query($query_db_specific);
+
+ // For table specific privileges
+ $query_table_specific = 'UPDATE ' . Util::backquote('tables_priv')
+ . 'SET Db = \'' . $this->dbi->escapeString($newname)
+ . '\' where Db = \'' . $this->dbi->escapeString($oldDb) . '\';';
+ $this->dbi->query($query_table_specific);
+
+ // For column specific privileges
+ $query_col_specific = 'UPDATE ' . Util::backquote('columns_priv')
+ . 'SET Db = \'' . $this->dbi->escapeString($newname)
+ . '\' where Db = \'' . $this->dbi->escapeString($oldDb) . '\';';
+ $this->dbi->query($query_col_specific);
+
+ // For procedures specific privileges
+ $query_proc_specific = 'UPDATE ' . Util::backquote('procs_priv')
+ . 'SET Db = \'' . $this->dbi->escapeString($newname)
+ . '\' where Db = \'' . $this->dbi->escapeString($oldDb) . '\';';
+ $this->dbi->query($query_proc_specific);
+
+ // Finally FLUSH the new privileges
+ $flush_query = "FLUSH PRIVILEGES;";
+ $this->dbi->query($flush_query);
+ }
+ }
+
+ /**
+ * Adjust the privileges after Copying the db
+ *
+ * @param string $oldDb Database name before copying
+ * @param string $newname New Database name requested
+ *
+ * @return void
+ */
+ public function adjustPrivilegesCopyDb($oldDb, $newname)
+ {
+ if ($GLOBALS['db_priv'] && $GLOBALS['table_priv']
+ && $GLOBALS['col_priv'] && $GLOBALS['proc_priv']
+ && $GLOBALS['is_reload_priv']
+ ) {
+ $this->dbi->selectDb('mysql');
+ $newname = str_replace("_", "\_", $newname);
+ $oldDb = str_replace("_", "\_", $oldDb);
+
+ $query_db_specific_old = 'SELECT * FROM '
+ . Util::backquote('db') . ' WHERE '
+ . 'Db = "' . $oldDb . '";';
+
+ $old_privs_db = $this->dbi->fetchResult($query_db_specific_old, 0);
+
+ foreach ($old_privs_db as $old_priv) {
+ $newDb_db_privs_query = 'INSERT INTO ' . Util::backquote('db')
+ . ' VALUES("' . $old_priv[0] . '", "' . $newname . '"';
+ for ($i = 2; $i < count($old_priv); $i++) {
+ $newDb_db_privs_query .= ', "' . $old_priv[$i] . '"';
+ }
+ $newDb_db_privs_query .= ')';
+
+ $this->dbi->query($newDb_db_privs_query);
+ }
+
+ // For Table Specific privileges
+ $query_table_specific_old = 'SELECT * FROM '
+ . Util::backquote('tables_priv') . ' WHERE '
+ . 'Db = "' . $oldDb . '";';
+
+ $old_privs_table = $this->dbi->fetchResult(
+ $query_table_specific_old,
+ 0
+ );
+
+ foreach ($old_privs_table as $old_priv) {
+ $newDb_table_privs_query = 'INSERT INTO ' . Util::backquote(
+ 'tables_priv'
+ ) . ' VALUES("' . $old_priv[0] . '", "' . $newname . '", "'
+ . $old_priv[2] . '", "' . $old_priv[3] . '", "' . $old_priv[4]
+ . '", "' . $old_priv[5] . '", "' . $old_priv[6] . '", "'
+ . $old_priv[7] . '");';
+
+ $this->dbi->query($newDb_table_privs_query);
+ }
+
+ // For Column Specific privileges
+ $query_col_specific_old = 'SELECT * FROM '
+ . Util::backquote('columns_priv') . ' WHERE '
+ . 'Db = "' . $oldDb . '";';
+
+ $old_privs_col = $this->dbi->fetchResult(
+ $query_col_specific_old,
+ 0
+ );
+
+ foreach ($old_privs_col as $old_priv) {
+ $newDb_col_privs_query = 'INSERT INTO ' . Util::backquote(
+ 'columns_priv'
+ ) . ' VALUES("' . $old_priv[0] . '", "' . $newname . '", "'
+ . $old_priv[2] . '", "' . $old_priv[3] . '", "' . $old_priv[4]
+ . '", "' . $old_priv[5] . '", "' . $old_priv[6] . '");';
+
+ $this->dbi->query($newDb_col_privs_query);
+ }
+
+ // For Procedure Specific privileges
+ $query_proc_specific_old = 'SELECT * FROM '
+ . Util::backquote('procs_priv') . ' WHERE '
+ . 'Db = "' . $oldDb . '";';
+
+ $old_privs_proc = $this->dbi->fetchResult(
+ $query_proc_specific_old,
+ 0
+ );
+
+ foreach ($old_privs_proc as $old_priv) {
+ $newDb_proc_privs_query = 'INSERT INTO ' . Util::backquote(
+ 'procs_priv'
+ ) . ' VALUES("' . $old_priv[0] . '", "' . $newname . '", "'
+ . $old_priv[2] . '", "' . $old_priv[3] . '", "' . $old_priv[4]
+ . '", "' . $old_priv[5] . '", "' . $old_priv[6] . '", "'
+ . $old_priv[7] . '");';
+
+ $this->dbi->query($newDb_proc_privs_query);
+ }
+
+ // Finally FLUSH the new privileges
+ $flush_query = "FLUSH PRIVILEGES;";
+ $this->dbi->query($flush_query);
+ }
+ }
+
+ /**
+ * Create all accumulated constraints
+ *
+ * @param array $sqlConstratints array of sql constraints for the database
+ *
+ * @return void
+ */
+ public function createAllAccumulatedConstraints(array $sqlConstratints)
+ {
+ $this->dbi->selectDb($_POST['newname']);
+ foreach ($sqlConstratints as $one_query) {
+ $this->dbi->query($one_query);
+ // and prepare to display them
+ $GLOBALS['sql_query'] .= "\n" . $one_query;
+ }
+ }
+
+ /**
+ * Duplicate the bookmarks for the db (done once for each db)
+ *
+ * @param boolean $_error whether table rename/copy or not
+ * @param string $db database name
+ *
+ * @return void
+ */
+ public function duplicateBookmarks($_error, $db)
+ {
+ if (! $_error && $db != $_POST['newname']) {
+ $get_fields = [
+ 'user',
+ 'label',
+ 'query',
+ ];
+ $where_fields = ['dbase' => $db];
+ $new_fields = ['dbase' => $_POST['newname']];
+ Table::duplicateInfo(
+ 'bookmarkwork',
+ 'bookmark',
+ $get_fields,
+ $where_fields,
+ $new_fields
+ );
+ }
+ }
+
+ /**
+ * Get the HTML snippet for order the table
+ *
+ * @param array $columns columns array
+ *
+ * @return string
+ */
+ public function getHtmlForOrderTheTable(array $columns)
+ {
+ $html_output = '<div>';
+ $html_output .= '<form method="post" id="alterTableOrderby" '
+ . 'action="tbl_operations.php">';
+ $html_output .= Url::getHiddenInputs(
+ $GLOBALS['db'],
+ $GLOBALS['table']
+ );
+ $html_output .= '<fieldset id="fieldset_table_order">'
+ . '<legend>' . __('Alter table order by') . '</legend>'
+ . '<select name="order_field">';
+
+ foreach ($columns as $fieldname) {
+ $html_output .= '<option '
+ . 'value="' . htmlspecialchars($fieldname['Field']) . '">'
+ . htmlspecialchars($fieldname['Field']) . '</option>' . "\n";
+ }
+ $html_output .= '</select> ' . __('(singly)') . ' '
+ . '<br>'
+ . '<input id="order_order_asc" name="order_order"'
+ . ' type="radio" value="asc" checked="checked">'
+ . '<label for="order_order_asc">' . __('Ascending') . '</label>'
+ . '<input id="order_order_desc" name="order_order"'
+ . ' type="radio" value="desc">'
+ . '<label for="order_order_desc">' . __('Descending') . '</label>'
+ . '</fieldset>'
+ . '<fieldset class="tblFooters">'
+ . '<input type="hidden" name="submitorderby" value="1">'
+ . '<input class="btn btn-primary" type="submit" value="' . __('Go') . '">'
+ . '</fieldset>'
+ . '</form>'
+ . '</div>';
+
+ return $html_output;
+ }
+
+ /**
+ * Get the HTML snippet for move table
+ *
+ * @return string
+ */
+ public function getHtmlForMoveTable()
+ {
+ $html_output = '<div>';
+ $html_output .= '<form method="post" action="tbl_operations.php"'
+ . ' id="moveTableForm" class="ajax"'
+ . ' onsubmit="return Functions.emptyCheckTheField(this, \'new_name\')">'
+ . Url::getHiddenInputs($GLOBALS['db'], $GLOBALS['table']);
+
+ $html_output .= '<input type="hidden" name="reload" value="1">'
+ . '<input type="hidden" name="what" value="data">'
+ . '<fieldset id="fieldset_table_rename">';
+
+ $html_output .= '<legend>' . __('Move table to (database<b>.</b>table)')
+ . '</legend>';
+
+ if (count($GLOBALS['dblist']->databases) > $GLOBALS['cfg']['MaxDbList']) {
+ $html_output .= '<input type="text" maxlength="100" '
+ . 'name="target_db" value="' . htmlspecialchars($GLOBALS['db'])
+ . '">';
+ } else {
+ $html_output .= '<select class="halfWidth" name="target_db">'
+ . $GLOBALS['dblist']->databases->getHtmlOptions(true, false)
+ . '</select>';
+ }
+ $html_output .= '&nbsp;<strong>.</strong>&nbsp;';
+ $html_output .= '<input class="halfWidth" type="text" name="new_name"'
+ . ' maxlength="64" required="required" '
+ . 'value="' . htmlspecialchars($GLOBALS['table']) . '"><br>';
+
+ // starting with MySQL 5.0.24, SHOW CREATE TABLE includes the AUTO_INCREMENT
+ // next value but users can decide if they want it or not for the operation
+
+ $html_output .= '<input type="checkbox" name="sql_auto_increment" '
+ . 'value="1" id="checkbox_auto_increment_mv" checked="checked">'
+ . '<label for="checkbox_auto_increment_mv">'
+ . __('Add AUTO_INCREMENT value')
+ . '</label><br>';
+
+ if ($GLOBALS['table_priv'] && $GLOBALS['col_priv']
+ && $GLOBALS['is_reload_priv']
+ ) {
+ $html_output .= '<input type="checkbox" name="adjust_privileges" '
+ . 'value="1" id="checkbox_privileges_tables_move" '
+ . 'checked="checked">';
+ } else {
+ $html_output .= '<input type="checkbox" name="adjust_privileges" '
+ . 'value="1" id="checkbox_privileges_tables_move" title="' . __(
+ 'You don\'t have sufficient privileges to perform this '
+ . 'operation; Please refer to the documentation for more details'
+ )
+ . '" disabled>';
+ }
+ $html_output .= '<label for="checkbox_privileges_tables_move">'
+ . __('Adjust privileges') . Util::showDocu('faq', 'faq6-39')
+ . '</label><br>';
+
+ $html_output .= '</fieldset><fieldset class="tblFooters">'
+ . '<input class="btn btn-primary" type="submit" name="submit_move" value="' . __('Go') . '">'
+ . '</fieldset>'
+ . '</form>'
+ . '</div>';
+
+ return $html_output;
+ }
+
+ /**
+ * Get the HTML div for Table option
+ *
+ * @param Table $pma_table Table object
+ * @param string $com