Completed
Push — master ( 64741e...904a1b )
by Maurício
09:11
created

db_operations.php (4 issues)

1
<?php
2
/* vim: set expandtab sw=4 ts=4 sts=4: */
3
/**
4
 * handles miscellaneous db operations:
5
 *  - move/rename
6
 *  - copy
7
 *  - changing collation
8
 *  - changing comment
9
 *  - adding tables
10
 *  - viewing PDF schemas
11
 *
12
 * @package PhpMyAdmin
13
 */
14
declare(strict_types=1);
15
16
use PhpMyAdmin\DatabaseInterface;
17
use PhpMyAdmin\Display\CreateTable;
18
use PhpMyAdmin\Message;
19
use PhpMyAdmin\Operations;
20
use PhpMyAdmin\Plugins;
21
use PhpMyAdmin\Plugins\Export\ExportSql;
22
use PhpMyAdmin\Relation;
23
use PhpMyAdmin\RelationCleanup;
24
use PhpMyAdmin\Response;
25
use PhpMyAdmin\Util;
26
27
/**
28
 * requirements
29
 */
30
require_once 'libraries/common.inc.php';
31
32
/**
33
 * functions implementation for this script
34
 */
35
require_once 'libraries/check_user_privileges.inc.php';
36
37
// add a javascript file for jQuery functions to handle Ajax actions
38
$response = Response::getInstance();
39
$header = $response->getHeader();
40
$scripts = $header->getScripts();
41
$scripts->addFile('db_operations.js');
42
43
$sql_query = '';
44
45
$relation = new Relation($GLOBALS['dbi']);
46
$operations = new Operations($GLOBALS['dbi'], $relation);
47
$relationCleanup = new RelationCleanup($GLOBALS['dbi'], $relation);
48
49
/**
50
 * Rename/move or copy database
51
 */
52
if (strlen($GLOBALS['db']) > 0
53
    && (! empty($_REQUEST['db_rename']) || ! empty($_REQUEST['db_copy']))
54
) {
55
    if (! empty($_REQUEST['db_rename'])) {
56
        $move = true;
57
    } else {
58
        $move = false;
59
    }
60
61
    if (! isset($_REQUEST['newname']) || strlen($_REQUEST['newname']) === 0) {
62
        $message = Message::error(__('The database name is empty!'));
63
    } else {
64
        // lower_case_table_names=1 `DB` becomes `db`
65
        if ($GLOBALS['dbi']->getLowerCaseNames() === '1') {
66
            $_REQUEST['newname'] = mb_strtolower(
67
                $_REQUEST['newname']
68
            );
69
        }
70
71
        if ($_REQUEST['newname'] === $_REQUEST['db']) {
72
            $message = Message::error(
73
                __('Cannot copy database to the same name. Change the name and try again.')
74
            );
75
        } else {
76
            $_error = false;
77
            if ($move || ! empty($_REQUEST['create_database_before_copying'])) {
78
                $operations->createDbBeforeCopy();
79
            }
80
81
            // here I don't use DELIMITER because it's not part of the
82
            // language; I have to send each statement one by one
83
84
            // to avoid selecting alternatively the current and new db
85
            // we would need to modify the CREATE definitions to qualify
86
            // the db name
87
            $operations->runProcedureAndFunctionDefinitions($GLOBALS['db']);
88
89
            // go back to current db, just in case
90
            $GLOBALS['dbi']->selectDb($GLOBALS['db']);
91
92
            $tables_full = $GLOBALS['dbi']->getTablesFull($GLOBALS['db']);
93
94
            // remove all foreign key constraints, otherwise we can get errors
95
            /* @var $export_sql_plugin ExportSql */
96
            $export_sql_plugin = Plugins::getPlugin(
97
                "export",
98
                "sql",
99
                'libraries/classes/Plugins/Export/',
100
                [
101
                    'single_table' => isset($single_table),
102
                    'export_type'  => 'database'
103
                ]
104
            );
105
106
            // create stand-in tables for views
107
            $views = $operations->getViewsAndCreateSqlViewStandIn(
108
                $tables_full,
109
                $export_sql_plugin,
110
                $GLOBALS['db']
111
            );
112
113
            // copy tables
114
            $sqlConstratints = $operations->copyTables(
115
                $tables_full,
116
                $move,
117
                $GLOBALS['db']
118
            );
119
120
            // handle the views
121
            if (! $_error) {
0 ignored issues
show
The condition $_error is always false.
Loading history...
122
                $operations->handleTheViews($views, $move, $GLOBALS['db']);
123
            }
124
            unset($views);
125
126
            // now that all tables exist, create all the accumulated constraints
127
            if (! $_error && count($sqlConstratints) > 0) {
0 ignored issues
show
The condition $_error is always false.
Loading history...
128
                $operations->createAllAccumulatedConstraints($sqlConstratints);
129
            }
130
            unset($sqlConstratints);
131
132
            if ($GLOBALS['dbi']->getVersion() >= 50100) {
133
                // here DELIMITER is not used because it's not part of the
134
                // language; each statement is sent one by one
135
136
                $operations->runEventDefinitionsForDb($GLOBALS['db']);
137
            }
138
139
            // go back to current db, just in case
140
            $GLOBALS['dbi']->selectDb($GLOBALS['db']);
141
142
            // Duplicate the bookmarks for this db (done once for each db)
143
            $operations->duplicateBookmarks($_error, $GLOBALS['db']);
144
145
            if (! $_error && $move) {
146
                if (isset($_REQUEST['adjust_privileges'])
147
                    && ! empty($_REQUEST['adjust_privileges'])
148
                ) {
149
                    $operations->adjustPrivilegesMoveDb($GLOBALS['db'], $_REQUEST['newname']);
150
                }
151
152
                /**
153
                 * cleanup pmadb stuff for this db
154
                 */
155
                $relationCleanup->database($GLOBALS['db']);
156
157
                // if someday the RENAME DATABASE reappears, do not DROP
158
                $local_query = 'DROP DATABASE '
159
                    . Util::backquote($GLOBALS['db']) . ';';
0 ignored issues
show
Are you sure PhpMyAdmin\Util::backquote($GLOBALS['db']) of type array|mixed|string can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

159
                    . /** @scrutinizer ignore-type */ Util::backquote($GLOBALS['db']) . ';';
Loading history...
160
                $sql_query .= "\n" . $local_query;
161
                $GLOBALS['dbi']->query($local_query);
162
163
                $message = Message::success(
164
                    __('Database %1$s has been renamed to %2$s.')
165
                );
166
                $message->addParam($GLOBALS['db']);
167
                $message->addParam($_REQUEST['newname']);
168
            } elseif (! $_error) {
169
                if (isset($_REQUEST['adjust_privileges'])
170
                    && ! empty($_REQUEST['adjust_privileges'])
171
                ) {
172
                    $operations->adjustPrivilegesCopyDb($GLOBALS['db'], $_REQUEST['newname']);
173
                }
174
175
                $message = Message::success(
176
                    __('Database %1$s has been copied to %2$s.')
177
                );
178
                $message->addParam($GLOBALS['db']);
179
                $message->addParam($_REQUEST['newname']);
180
            } else {
181
                $message = Message::error();
182
            }
183
            $reload     = true;
184
185
            /* Change database to be used */
186
            if (! $_error && $move) {
187
                $GLOBALS['db'] = $_REQUEST['newname'];
188
            } elseif (! $_error) {
189
                if (isset($_REQUEST['switch_to_new'])
190
                    && $_REQUEST['switch_to_new'] == 'true'
191
                ) {
192
                    $_SESSION['pma_switch_to_new'] = true;
193
                    $GLOBALS['db'] = $_REQUEST['newname'];
194
                } else {
195
                    $_SESSION['pma_switch_to_new'] = false;
196
                }
197
            }
198
        }
199
    }
200
201
    /**
202
     * Database has been successfully renamed/moved.  If in an Ajax request,
203
     * generate the output with {@link PhpMyAdmin\Response} and exit
204
     */
205
    if ($response->isAjax()) {
206
        $response->setRequestStatus($message->isSuccess());
207
        $response->addJSON('message', $message);
208
        $response->addJSON('newname', $_REQUEST['newname']);
209
        $response->addJSON(
210
            'sql_query',
211
            Util::getMessage(null, $sql_query)
212
        );
213
        $response->addJSON('db', $GLOBALS['db']);
214
        exit;
215
    }
216
}
217
218
/**
219
 * Settings for relations stuff
220
 */
221
$cfgRelation = $relation->getRelationsParam();
222
223
/**
224
 * Check if comments were updated
225
 * (must be done before displaying the menu tabs)
226
 */
227
if (isset($_REQUEST['comment'])) {
228
    $relation->setDbComment($GLOBALS['db'], $_REQUEST['comment']);
229
}
230
231
require 'libraries/db_common.inc.php';
232
$url_query .= '&amp;goto=db_operations.php';
233
234
// Gets the database structure
235
$sub_part = '_structure';
236
237
list(
238
    $tables,
239
    $num_tables,
240
    $total_num_tables,
241
    $sub_part,
242
    $is_show_stats,
243
    $db_is_system_schema,
244
    $tooltip_truename,
245
    $tooltip_aliasname,
246
    $pos
247
) = Util::getDbInfo($db, is_null($sub_part) ? '' : $sub_part);
0 ignored issues
show
The condition is_null($sub_part) is always false.
Loading history...
248
249
echo "\n";
250
251
if (isset($message)) {
252
    echo Util::getMessage($message, $sql_query);
253
    unset($message);
254
}
255
256
$_REQUEST['db_collation'] = $GLOBALS['dbi']->getDbCollation($GLOBALS['db']);
257
$is_information_schema = $GLOBALS['dbi']->isSystemSchema($GLOBALS['db']);
258
259
if (!$is_information_schema) {
260
    if ($cfgRelation['commwork']) {
261
        /**
262
         * database comment
263
         */
264
        $response->addHTML($operations->getHtmlForDatabaseComment($GLOBALS['db']));
265
    }
266
267
    $response->addHTML('<div>');
268
    $response->addHTML(CreateTable::getHtml($db));
269
    $response->addHTML('</div>');
270
271
    /**
272
     * rename database
273
     */
274
    if ($GLOBALS['db'] != 'mysql') {
275
        $response->addHTML($operations->getHtmlForRenameDatabase($GLOBALS['db']));
276
    }
277
278
    // Drop link if allowed
279
    // Don't even try to drop information_schema.
280
    // You won't be able to. Believe me. You won't.
281
    // Don't allow to easily drop mysql database, RFE #1327514.
282
    if (($GLOBALS['dbi']->isSuperuser() || $GLOBALS['cfg']['AllowUserDropDatabase'])
283
        && ! $db_is_system_schema
284
        && $GLOBALS['db'] != 'mysql'
285
    ) {
286
        $response->addHTML($operations->getHtmlForDropDatabaseLink($GLOBALS['db']));
287
    }
288
    /**
289
     * Copy database
290
     */
291
    $response->addHTML($operations->getHtmlForCopyDatabase($GLOBALS['db']));
292
293
    /**
294
     * Change database charset
295
     */
296
    $response->addHTML($operations->getHtmlForChangeDatabaseCharset($GLOBALS['db'], $table));
297
298
    if (! $cfgRelation['allworks']
299
        && $cfg['PmaNoRelation_DisableWarning'] == false
300
    ) {
301
        $message = Message::notice(
302
            __(
303
                'The phpMyAdmin configuration storage has been deactivated. ' .
304
                '%sFind out why%s.'
305
            )
306
        );
307
        $message->addParamHtml('<a href="./chk_rel.php' . $url_query . '">');
308
        $message->addParamHtml('</a>');
309
        /* Show error if user has configured something, notice elsewhere */
310
        if (!empty($cfg['Servers'][$server]['pmadb'])) {
311
            $message->isError(true);
312
        }
313
    } // end if
314
} // end if (!$is_information_schema)
315