MultSubmits.php 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628
  1. <?php
  2. /* vim: set expandtab sw=4 ts=4 sts=4: */
  3. /**
  4. * Holds the PhpMyAdmin\MultSubmits class
  5. *
  6. * @usedby mult_submits.inc.php
  7. *
  8. * @package PhpMyAdmin
  9. */
  10. namespace PhpMyAdmin;
  11. use PhpMyAdmin\Operations;
  12. use PhpMyAdmin\RelationCleanup;
  13. use PhpMyAdmin\Sql;
  14. use PhpMyAdmin\Table;
  15. use PhpMyAdmin\Transformations;
  16. use PhpMyAdmin\Url;
  17. use PhpMyAdmin\Util;
  18. /**
  19. * Functions for multi submit forms
  20. *
  21. * @package PhpMyAdmin
  22. */
  23. class MultSubmits
  24. {
  25. /**
  26. * Gets url params
  27. *
  28. * @param string $what mult submit type
  29. * @param bool $reload is reload
  30. * @param string $action action type
  31. * @param string $db database name
  32. * @param string $table table name
  33. * @param array $selected selected rows(table,db)
  34. * @param array|null $views table views
  35. * @param string $originalSqlQuery original sql query
  36. * @param string $originalUrlQuery original url query
  37. *
  38. * @return array
  39. */
  40. public function getUrlParams(
  41. $what,
  42. $reload,
  43. $action,
  44. $db,
  45. $table,
  46. array $selected,
  47. $views,
  48. $originalSqlQuery,
  49. $originalUrlQuery
  50. ) {
  51. $urlParams = [
  52. 'query_type' => $what,
  53. 'reload' => (! empty($reload) ? 1 : 0),
  54. ];
  55. if (mb_strpos(' ' . $action, 'db_') == 1) {
  56. $urlParams['db']= $db;
  57. } elseif (mb_strpos(' ' . $action, 'tbl_') == 1
  58. || $what == 'row_delete'
  59. ) {
  60. $urlParams['db'] = $db;
  61. $urlParams['table'] = $table;
  62. }
  63. foreach ($selected as $selectedValue) {
  64. if ($what == 'row_delete') {
  65. $urlParams['selected'][] = 'DELETE FROM '
  66. . Util::backquote($table)
  67. . ' WHERE ' . $selectedValue . ' LIMIT 1;';
  68. } else {
  69. $urlParams['selected'][] = $selectedValue;
  70. }
  71. }
  72. if ($what == 'drop_tbl' && !empty($views)) {
  73. foreach ($views as $current) {
  74. $urlParams['views'][] = $current;
  75. }
  76. }
  77. if ($what == 'row_delete') {
  78. $urlParams['original_sql_query'] = $originalSqlQuery;
  79. if (! empty($originalUrlQuery)) {
  80. $urlParams['original_url_query'] = $originalUrlQuery;
  81. }
  82. }
  83. return $urlParams;
  84. }
  85. /**
  86. * Builds or execute queries for multiple elements, depending on $queryType
  87. *
  88. * @param string $queryType query type
  89. * @param array $selected selected tables
  90. * @param string $db db name
  91. * @param string $table table name
  92. * @param array|null $views table views
  93. * @param string $primary table primary
  94. * @param string $fromPrefix from prefix original
  95. * @param string $toPrefix to prefix original
  96. *
  97. * @return array
  98. */
  99. public function buildOrExecuteQuery(
  100. $queryType,
  101. array $selected,
  102. $db,
  103. $table,
  104. $views,
  105. $primary,
  106. $fromPrefix,
  107. $toPrefix
  108. ) {
  109. $rebuildDatabaseList = false;
  110. $reload = null;
  111. $aQuery = null;
  112. $sqlQuery = '';
  113. $sqlQueryViews = null;
  114. // whether to run query after each pass
  115. $runParts = false;
  116. // whether to execute the query at the end (to display results)
  117. $executeQueryLater = false;
  118. $result = null;
  119. if ($queryType == 'drop_tbl') {
  120. $sqlQueryViews = '';
  121. }
  122. $selectedCount = count($selected);
  123. $deletes = false;
  124. $copyTable = false;
  125. for ($i = 0; $i < $selectedCount; $i++) {
  126. switch ($queryType) {
  127. case 'row_delete':
  128. $deletes = true;
  129. $aQuery = $selected[$i];
  130. $runParts = true;
  131. break;
  132. case 'drop_db':
  133. RelationCleanup::database($selected[$i]);
  134. $aQuery = 'DROP DATABASE '
  135. . Util::backquote($selected[$i]);
  136. $reload = 1;
  137. $runParts = true;
  138. $rebuildDatabaseList = true;
  139. break;
  140. case 'drop_tbl':
  141. RelationCleanup::table($db, $selected[$i]);
  142. $current = $selected[$i];
  143. if (!empty($views) && in_array($current, $views)) {
  144. $sqlQueryViews .= (empty($sqlQueryViews) ? 'DROP VIEW ' : ', ')
  145. . Util::backquote($current);
  146. } else {
  147. $sqlQuery .= (empty($sqlQuery) ? 'DROP TABLE ' : ', ')
  148. . Util::backquote($current);
  149. }
  150. $reload = 1;
  151. break;
  152. case 'check_tbl':
  153. $sqlQuery .= (empty($sqlQuery) ? 'CHECK TABLE ' : ', ')
  154. . Util::backquote($selected[$i]);
  155. $executeQueryLater = true;
  156. break;
  157. case 'optimize_tbl':
  158. $sqlQuery .= (empty($sqlQuery) ? 'OPTIMIZE TABLE ' : ', ')
  159. . Util::backquote($selected[$i]);
  160. $executeQueryLater = true;
  161. break;
  162. case 'analyze_tbl':
  163. $sqlQuery .= (empty($sqlQuery) ? 'ANALYZE TABLE ' : ', ')
  164. . Util::backquote($selected[$i]);
  165. $executeQueryLater = true;
  166. break;
  167. case 'checksum_tbl':
  168. $sqlQuery .= (empty($sqlQuery) ? 'CHECKSUM TABLE ' : ', ')
  169. . Util::backquote($selected[$i]);
  170. $executeQueryLater = true;
  171. break;
  172. case 'repair_tbl':
  173. $sqlQuery .= (empty($sqlQuery) ? 'REPAIR TABLE ' : ', ')
  174. . Util::backquote($selected[$i]);
  175. $executeQueryLater = true;
  176. break;
  177. case 'empty_tbl':
  178. $deletes = true;
  179. $aQuery = 'TRUNCATE ';
  180. $aQuery .= Util::backquote($selected[$i]);
  181. $runParts = true;
  182. break;
  183. case 'drop_fld':
  184. RelationCleanup::column($db, $table, $selected[$i]);
  185. $sqlQuery .= (empty($sqlQuery)
  186. ? 'ALTER TABLE ' . Util::backquote($table)
  187. : ',')
  188. . ' DROP ' . Util::backquote($selected[$i])
  189. . (($i == $selectedCount - 1) ? ';' : '');
  190. break;
  191. case 'primary_fld':
  192. $sqlQuery .= (empty($sqlQuery)
  193. ? 'ALTER TABLE ' . Util::backquote($table)
  194. . (empty($primary)
  195. ? ''
  196. : ' DROP PRIMARY KEY,') . ' ADD PRIMARY KEY( '
  197. : ', ')
  198. . Util::backquote($selected[$i])
  199. . (($i == $selectedCount - 1) ? ');' : '');
  200. break;
  201. case 'index_fld':
  202. $sqlQuery .= (empty($sqlQuery)
  203. ? 'ALTER TABLE ' . Util::backquote($table)
  204. . ' ADD INDEX( '
  205. : ', ')
  206. . Util::backquote($selected[$i])
  207. . (($i == $selectedCount - 1) ? ');' : '');
  208. break;
  209. case 'unique_fld':
  210. $sqlQuery .= (empty($sqlQuery)
  211. ? 'ALTER TABLE ' . Util::backquote($table)
  212. . ' ADD UNIQUE( '
  213. : ', ')
  214. . Util::backquote($selected[$i])
  215. . (($i == $selectedCount - 1) ? ');' : '');
  216. break;
  217. case 'spatial_fld':
  218. $sqlQuery .= (empty($sqlQuery)
  219. ? 'ALTER TABLE ' . Util::backquote($table)
  220. . ' ADD SPATIAL( '
  221. : ', ')
  222. . Util::backquote($selected[$i])
  223. . (($i == $selectedCount - 1) ? ');' : '');
  224. break;
  225. case 'fulltext_fld':
  226. $sqlQuery .= (empty($sqlQuery)
  227. ? 'ALTER TABLE ' . Util::backquote($table)
  228. . ' ADD FULLTEXT( '
  229. : ', ')
  230. . Util::backquote($selected[$i])
  231. . (($i == $selectedCount - 1) ? ');' : '');
  232. break;
  233. case 'add_prefix_tbl':
  234. $newTableName = $_POST['add_prefix'] . $selected[$i];
  235. // ADD PREFIX TO TABLE NAME
  236. $aQuery = 'ALTER TABLE '
  237. . Util::backquote($selected[$i])
  238. . ' RENAME '
  239. . Util::backquote($newTableName);
  240. $runParts = true;
  241. break;
  242. case 'replace_prefix_tbl':
  243. $current = $selected[$i];
  244. $subFromPrefix = mb_substr(
  245. $current,
  246. 0,
  247. mb_strlen($fromPrefix)
  248. );
  249. if ($subFromPrefix == $fromPrefix) {
  250. $newTableName = $toPrefix
  251. . mb_substr(
  252. $current,
  253. mb_strlen($fromPrefix)
  254. );
  255. } else {
  256. $newTableName = $current;
  257. }
  258. // CHANGE PREFIX PATTERN
  259. $aQuery = 'ALTER TABLE '
  260. . Util::backquote($selected[$i])
  261. . ' RENAME '
  262. . Util::backquote($newTableName);
  263. $runParts = true;
  264. break;
  265. case 'copy_tbl_change_prefix':
  266. $runParts = true;
  267. $copyTable = true;
  268. $current = $selected[$i];
  269. $newTableName = $toPrefix .
  270. mb_substr($current, mb_strlen($fromPrefix));
  271. // COPY TABLE AND CHANGE PREFIX PATTERN
  272. Table::moveCopy(
  273. $db,
  274. $current,
  275. $db,
  276. $newTableName,
  277. 'data',
  278. false,
  279. 'one_table'
  280. );
  281. break;
  282. case 'copy_tbl':
  283. $runParts = true;
  284. $copyTable = true;
  285. Table::moveCopy(
  286. $db,
  287. $selected[$i],
  288. $_POST['target_db'],
  289. $selected[$i],
  290. $_POST['what'],
  291. false,
  292. 'one_table'
  293. );
  294. if (isset($_POST['adjust_privileges']) && !empty($_POST['adjust_privileges'])) {
  295. $operations = new Operations();
  296. $operations->adjustPrivilegesCopyTable(
  297. $db,
  298. $selected[$i],
  299. $_POST['target_db'],
  300. $selected[$i]
  301. );
  302. }
  303. break;
  304. } // end switch
  305. // All "DROP TABLE", "DROP FIELD", "OPTIMIZE TABLE" and "REPAIR TABLE"
  306. // statements will be run at once below
  307. if ($runParts && !$copyTable) {
  308. $sqlQuery .= $aQuery . ';' . "\n";
  309. if ($queryType != 'drop_db') {
  310. $GLOBALS['dbi']->selectDb($db);
  311. }
  312. $result = $GLOBALS['dbi']->query($aQuery);
  313. if ($queryType == 'drop_db') {
  314. Transformations::clear($selected[$i]);
  315. } elseif ($queryType == 'drop_tbl') {
  316. Transformations::clear($db, $selected[$i]);
  317. } elseif ($queryType == 'drop_fld') {
  318. Transformations::clear($db, $table, $selected[$i]);
  319. }
  320. } // end if
  321. } // end for
  322. if ($deletes && ! empty($_REQUEST['pos'])) {
  323. $sql = new Sql();
  324. $_REQUEST['pos'] = $sql->calculatePosForLastPage(
  325. $db,
  326. $table,
  327. isset($_REQUEST['pos']) ? $_REQUEST['pos'] : null
  328. );
  329. }
  330. return [
  331. $result,
  332. $rebuildDatabaseList,
  333. $reload,
  334. $runParts,
  335. $executeQueryLater,
  336. $sqlQuery,
  337. $sqlQueryViews
  338. ];
  339. }
  340. /**
  341. * Gets HTML for copy tables form
  342. *
  343. * @param string $action action type
  344. * @param array $urlParams URL params
  345. *
  346. * @return string
  347. */
  348. public function getHtmlForCopyMultipleTables($action, array $urlParams)
  349. {
  350. $html = '<form id="ajax_form" action="' . $action . '" method="post">';
  351. $html .= Url::getHiddenInputs($urlParams);
  352. $html .= '<fieldset class = "input">';
  353. $databasesList = $GLOBALS['dblist']->databases;
  354. foreach ($databasesList as $key => $databaseName) {
  355. if ($databaseName == $GLOBALS['db']) {
  356. $databasesList->offsetUnset($key);
  357. break;
  358. }
  359. }
  360. $html .= '<strong><label for="db_name_dropdown">' . __('Database') . ':</label></strong>';
  361. $html .= '<select id="db_name_dropdown" class="halfWidth" name="target_db" >'
  362. . $databasesList->getHtmlOptions(true, false)
  363. . '</select>';
  364. $html .= '<br><br>';
  365. $html .= '<strong><label>' . __('Options') . ':</label></strong><br>';
  366. $html .= '<input type="radio" id ="what_structure" value="structure" name="what"/>';
  367. $html .= '<label for="what_structure">' . __('Structure only') . '</label><br>';
  368. $html .= '<input type="radio" id ="what_data" value="data" name="what" checked="checked"/>';
  369. $html .= '<label for="what_data">' . __('Structure and data') . '</label><br>';
  370. $html .= '<input type="radio" id ="what_dataonly" value="dataonly" name="what"/>';
  371. $html .= '<label for="what_dataonly">' . __('Data only') . '</label><br><br>';
  372. $html .= '<input type="checkbox" id="checkbox_drop" value="true" name="drop_if_exists"/>';
  373. $html .= '<label for="checkbox_drop">' . __('Add DROP TABLE') . '</label><br>';
  374. $html .= '<input type="checkbox" id="checkbox_auto_increment_cp" value="1" name="sql_auto_increment"/>';
  375. $html .= '<label for="checkbox_auto_increment_cp">' . __('Add AUTO INCREMENT value') . '</label><br>';
  376. $html .= '<input type="checkbox" id="checkbox_constraints" value="1" name="sql_auto_increment" checked="checked"/>';
  377. $html .= '<label for="checkbox_constraints">' . __('Add constraints') . '</label><br><br>';
  378. $html .= '<input name="adjust_privileges" value="1" id="checkbox_adjust_privileges" checked="checked" type="checkbox"/>';
  379. $html .= '<label for="checkbox_adjust_privileges">' . __('Adjust privileges') . '<a href="./doc/html/faq.html#faq6-39" target="documentation"><img src="themes/dot.gif" title="Documentation" alt="Documentation" class="icon ic_b_help"></a></label>';
  380. $html .= '</fieldset>';
  381. $html .= '<input type="hidden" name="mult_btn" value="' . __('Yes') . '" />';
  382. $html .= '</form>';
  383. return $html;
  384. }
  385. /**
  386. * Gets HTML for replace_prefix_tbl or copy_tbl_change_prefix
  387. *
  388. * @param string $action action type
  389. * @param array $urlParams URL params
  390. *
  391. * @return string
  392. */
  393. public function getHtmlForReplacePrefixTable($action, array $urlParams)
  394. {
  395. $html = '<form id="ajax_form" action="' . $action . '" method="post">';
  396. $html .= Url::getHiddenInputs($urlParams);
  397. $html .= '<fieldset class = "input">';
  398. $html .= '<table>';
  399. $html .= '<tr>';
  400. $html .= '<td>' . __('From') . '</td>';
  401. $html .= '<td>';
  402. $html .= '<input type="text" name="from_prefix" id="initialPrefix" />';
  403. $html .= '</td>';
  404. $html .= '</tr>';
  405. $html .= '<tr>';
  406. $html .= '<td>' . __('To') . '</td>';
  407. $html .= '<td>';
  408. $html .= '<input type="text" name="to_prefix" id="newPrefix" />';
  409. $html .= '</td>';
  410. $html .= '</tr>';
  411. $html .= '</table>';
  412. $html .= '</fieldset>';
  413. $html .= '<input type="hidden" name="mult_btn" value="' . __('Yes') . '" />';
  414. $html .= '</form>';
  415. return $html;
  416. }
  417. /**
  418. * Gets HTML for add_prefix_tbl
  419. *
  420. * @param string $action action type
  421. * @param array $urlParams URL params
  422. *
  423. * @return string
  424. */
  425. public function getHtmlForAddPrefixTable($action, array $urlParams)
  426. {
  427. $html = '<form id="ajax_form" action="' . $action . '" method="post">';
  428. $html .= Url::getHiddenInputs($urlParams);
  429. $html .= '<fieldset class = "input">';
  430. $html .= '<table>';
  431. $html .= '<tr>';
  432. $html .= '<td>' . __('Add prefix') . '</td>';
  433. $html .= '<td>';
  434. $html .= '<input type="text" name="add_prefix" id="txtPrefix" />';
  435. $html .= '</td>';
  436. $html .= '</tr>';
  437. $html .= '<tr>';
  438. $html .= '</table>';
  439. $html .= '</fieldset>';
  440. $html .= '<input type="hidden" name="mult_btn" value="' . __('Yes') . '" />';
  441. $html .= '</form>';
  442. return $html;
  443. }
  444. /**
  445. * Gets HTML for other mult_submits actions
  446. *
  447. * @param string $what mult_submit type
  448. * @param string $action action type
  449. * @param array $urlParams URL params
  450. * @param string $fullQuery full sql query string
  451. *
  452. * @return string
  453. */
  454. public function getHtmlForOtherActions($what, $action, array $urlParams, $fullQuery)
  455. {
  456. $html = '<form action="' . $action . '" method="post">';
  457. $html .= Url::getHiddenInputs($urlParams);
  458. $html .= '<fieldset class="confirmation">';
  459. $html .= '<legend>';
  460. if ($what == 'drop_db') {
  461. $html .= __('You are about to DESTROY a complete database!') . ' ';
  462. }
  463. $html .= __('Do you really want to execute the following query?');
  464. $html .= '</legend>';
  465. $html .= '<code>' . $fullQuery . '</code>';
  466. $html .= '</fieldset>';
  467. $html .= '<fieldset class="tblFooters">';
  468. // Display option to disable foreign key checks while dropping tables
  469. if ($what === 'drop_tbl' || $what === 'empty_tbl' || $what === 'row_delete') {
  470. $html .= '<div id="foreignkeychk">';
  471. $html .= Util::getFKCheckbox();
  472. $html .= '</div>';
  473. }
  474. $html .= '<input id="buttonYes" type="submit" name="mult_btn" value="'
  475. . __('Yes') . '" />';
  476. $html .= '<input id="buttonNo" type="submit" name="mult_btn" value="'
  477. . __('No') . '" />';
  478. $html .= '</fieldset>';
  479. $html .= '</form>';
  480. return $html;
  481. }
  482. /**
  483. * Get query string from Selected
  484. *
  485. * @param string $what mult_submit type
  486. * @param string $table table name
  487. * @param array $selected the selected columns
  488. * @param array $views table views
  489. *
  490. * @return array
  491. */
  492. public function getQueryFromSelected($what, $table, array $selected, array $views)
  493. {
  494. $reload = false;
  495. $fullQueryViews = null;
  496. $fullQuery = '';
  497. if ($what == 'drop_tbl') {
  498. $fullQueryViews = '';
  499. }
  500. $selectedCount = count($selected);
  501. $i = 0;
  502. foreach ($selected as $selectedValue) {
  503. switch ($what) {
  504. case 'row_delete':
  505. $fullQuery .= 'DELETE FROM '
  506. . Util::backquote(htmlspecialchars($table))
  507. // Do not append a "LIMIT 1" clause here
  508. // (it's not binlog friendly).
  509. // We don't need the clause because the calling panel permits
  510. // this feature only when there is a unique index.
  511. . ' WHERE ' . htmlspecialchars($selectedValue)
  512. . ';<br />';
  513. break;
  514. case 'drop_db':
  515. $fullQuery .= 'DROP DATABASE '
  516. . Util::backquote(htmlspecialchars($selectedValue))
  517. . ';<br />';
  518. $reload = true;
  519. break;
  520. case 'drop_tbl':
  521. $current = $selectedValue;
  522. if (!empty($views) && in_array($current, $views)) {
  523. $fullQueryViews .= (empty($fullQueryViews) ? 'DROP VIEW ' : ', ')
  524. . Util::backquote(htmlspecialchars($current));
  525. } else {
  526. $fullQuery .= (empty($fullQuery) ? 'DROP TABLE ' : ', ')
  527. . Util::backquote(htmlspecialchars($current));
  528. }
  529. break;
  530. case 'empty_tbl':
  531. $fullQuery .= 'TRUNCATE ';
  532. $fullQuery .= Util::backquote(htmlspecialchars($selectedValue))
  533. . ';<br />';
  534. break;
  535. case 'primary_fld':
  536. if ($fullQuery == '') {
  537. $fullQuery .= 'ALTER TABLE '
  538. . Util::backquote(htmlspecialchars($table))
  539. . '<br />&nbsp;&nbsp;DROP PRIMARY KEY,'
  540. . '<br />&nbsp;&nbsp; ADD PRIMARY KEY('
  541. . '<br />&nbsp;&nbsp;&nbsp;&nbsp; '
  542. . Util::backquote(htmlspecialchars($selectedValue))
  543. . ',';
  544. } else {
  545. $fullQuery .= '<br />&nbsp;&nbsp;&nbsp;&nbsp; '
  546. . Util::backquote(htmlspecialchars($selectedValue))
  547. . ',';
  548. }
  549. if ($i == $selectedCount - 1) {
  550. $fullQuery = preg_replace('@,$@', ');<br />', $fullQuery);
  551. }
  552. break;
  553. case 'drop_fld':
  554. if ($fullQuery == '') {
  555. $fullQuery .= 'ALTER TABLE '
  556. . Util::backquote(htmlspecialchars($table));
  557. }
  558. $fullQuery .= '<br />&nbsp;&nbsp;DROP '
  559. . Util::backquote(htmlspecialchars($selectedValue))
  560. . ',';
  561. if ($i == $selectedCount - 1) {
  562. $fullQuery = preg_replace('@,$@', ';<br />', $fullQuery);
  563. }
  564. break;
  565. } // end switch
  566. $i++;
  567. }
  568. if ($what == 'drop_tbl') {
  569. if (!empty($fullQuery)) {
  570. $fullQuery .= ';<br />' . "\n";
  571. }
  572. if (!empty($fullQueryViews)) {
  573. $fullQuery .= $fullQueryViews . ';<br />' . "\n";
  574. }
  575. unset($fullQueryViews);
  576. }
  577. $fullQueryViews = isset($fullQueryViews) ? $fullQueryViews : null;
  578. return [$fullQuery, $reload, $fullQueryViews];
  579. }
  580. }