diff options
-rw-r--r-- | db_designer.php | 44 | ||||
-rw-r--r-- | libraries/classes/PmdCommon.php | 775 | ||||
-rw-r--r-- | libraries/pmd_common.php | 773 | ||||
-rw-r--r-- | schema_export.php | 2 | ||||
-rw-r--r-- | test/classes/PmdCommonTest.php (renamed from test/libraries/PMA_PMD_common_test.php) | 58 |
5 files changed, 827 insertions, 825 deletions
diff --git a/db_designer.php b/db_designer.php index ceb4f89ed6..0db302be72 100644 --- a/db_designer.php +++ b/db_designer.php @@ -6,10 +6,10 @@ * @package PhpMyAdmin-Designer */ use PhpMyAdmin\Database\Designer; +use PhpMyAdmin\PmdCommon; use PhpMyAdmin\Response; require_once 'libraries/common.inc.php'; -require_once 'libraries/pmd_common.php'; $response = Response::getInstance(); @@ -26,11 +26,11 @@ if (isset($_REQUEST['dialog'])) { $GLOBALS['db'], $_REQUEST['selected_page'] ); } else if ($_REQUEST['dialog'] == 'add_table') { - $script_display_field = PMA_getTablesInfo(); + $script_display_field = PmdCommon::getTablesInfo(); $required = $GLOBALS['db'] . '.' . $GLOBALS['table']; - $tab_column = PMA_getColumnsInfo(); - $tables_all_keys = PMA_getAllKeys(); - $tables_pk_or_unique_keys = PMA_getPKOrUniqueKeys(); + $tab_column = PmdCommon::getColumnsInfo(); + $tables_all_keys = PmdCommon::getAllKeys(); + $tables_pk_or_unique_keys = PmdCommon::getPkOrUniqueKeys(); $req_key = array_search($required, $GLOBALS['PMD']['TABLE_NAME']); @@ -56,24 +56,24 @@ if (isset($_REQUEST['dialog'])) { if (isset($_REQUEST['operation'])) { if ($_REQUEST['operation'] == 'deletePage') { - $success = PMA_deletePage($_REQUEST['selected_page']); + $success = PmdCommon::deletePage($_REQUEST['selected_page']); $response->setRequestStatus($success); } elseif ($_REQUEST['operation'] == 'savePage') { if ($_REQUEST['save_page'] == 'same') { $page = $_REQUEST['selected_page']; } else { // new - $page = PMA_createNewPage($_REQUEST['selected_value'], $GLOBALS['db']); + $page = PmdCommon::createNewPage($_REQUEST['selected_value'], $GLOBALS['db']); $response->addJSON('id', $page); } - $success = PMA_saveTablePositions($page); + $success = PmdCommon::saveTablePositions($page); $response->setRequestStatus($success); } elseif ($_REQUEST['operation'] == 'setDisplayField') { - PMA_saveDisplayField( + PmdCommon::saveDisplayField( $_REQUEST['db'], $_REQUEST['table'], $_REQUEST['field'] ); $response->setRequestStatus(true); } elseif ($_REQUEST['operation'] == 'addNewRelation') { - list($success, $message) = PMA_addNewRelation( + list($success, $message) = PmdCommon::addNewRelation( $_REQUEST['db'], $_REQUEST['T1'], $_REQUEST['F1'], @@ -87,7 +87,7 @@ if (isset($_REQUEST['operation'])) { $response->setRequestStatus($success); $response->addJSON('message', $message); } elseif ($_REQUEST['operation'] == 'removeRelation') { - list($success, $message) = PMA_removeRelation( + list($success, $message) = PmdCommon::removeRelation( $_REQUEST['T1'], $_REQUEST['F1'], $_REQUEST['T2'], @@ -96,7 +96,7 @@ if (isset($_REQUEST['operation'])) { $response->setRequestStatus($success); $response->addJSON('message', $message); } elseif ($_REQUEST['operation'] == 'save_setting_value') { - $success = PMA_saveDesignerSetting($_REQUEST['index'], $_REQUEST['value']); + $success = PmdCommon::saveDesignerSetting($_REQUEST['index'], $_REQUEST['value']); $response->setRequestStatus($success); } @@ -105,30 +105,30 @@ if (isset($_REQUEST['operation'])) { require 'libraries/db_common.inc.php'; -$script_display_field = PMA_getTablesInfo(); -$tab_column = PMA_getColumnsInfo(); -$script_tables = PMA_getScriptTabs(); -$tables_pk_or_unique_keys = PMA_getPKOrUniqueKeys(); -$tables_all_keys = PMA_getAllKeys(); +$script_display_field = PmdCommon::getTablesInfo(); +$tab_column = PmdCommon::getColumnsInfo(); +$script_tables = PmdCommon::getScriptTabs(); +$tables_pk_or_unique_keys = PmdCommon::getPkOrUniqueKeys(); +$tables_all_keys = PmdCommon::getAllKeys(); $classes_side_menu = Designer::returnClassNamesFromMenuButtons(); $display_page = -1; $selected_page = null; if (isset($_REQUEST['query'])) { - $display_page = PMA_getDefaultPage($_REQUEST['db']); + $display_page = PmdCommon::getDefaultPage($_REQUEST['db']); } else { if (! empty($_REQUEST['page'])) { $display_page = $_REQUEST['page']; } else { - $display_page = PMA_getLoadingPage($_REQUEST['db']); + $display_page = PmdCommon::getLoadingPage($_REQUEST['db']); } } if ($display_page != -1) { - $selected_page = PMA_getPageName($display_page); + $selected_page = PmdCommon::getPageName($display_page); } -$tab_pos = PMA_getTablePositions($display_page); -$script_contr = PMA_getScriptContr(); +$tab_pos = PmdCommon::getTablePositions($display_page); +$script_contr = PmdCommon::getScriptContr(); $params = array('lang' => $GLOBALS['lang']); if (isset($_GET['db'])) { diff --git a/libraries/classes/PmdCommon.php b/libraries/classes/PmdCommon.php new file mode 100644 index 0000000000..3422918d90 --- /dev/null +++ b/libraries/classes/PmdCommon.php @@ -0,0 +1,775 @@ +<?php +/* vim: set expandtab sw=4 ts=4 sts=4: */ +/** + * Common functions for Designer + * + * @package PhpMyAdmin-Designer + */ +namespace PhpMyAdmin; + +use PhpMyAdmin\DatabaseInterface; +use PhpMyAdmin\Index; +use PhpMyAdmin\Relation; +use PhpMyAdmin\Table; +use PhpMyAdmin\Util; + +/** + * PhpMyAdmin\PmdCommon class + * + * @package PhpMyAdmin-Designer + */ +class PmdCommon +{ + /** + * Retrieves table info and stores it in $GLOBALS['PMD'] + * + * @return array with table info + */ + public static function getTablesInfo() + { + $retval = array(); + + $GLOBALS['PMD']['TABLE_NAME'] = array();// that foreach no error + $GLOBALS['PMD']['OWNER'] = array(); + $GLOBALS['PMD']['TABLE_NAME_SMALL'] = array(); + + $tables = $GLOBALS['dbi']->getTablesFull($GLOBALS['db']); + // seems to be needed later + $GLOBALS['dbi']->selectDb($GLOBALS['db']); + $i = 0; + foreach ($tables as $one_table) { + $GLOBALS['PMD']['TABLE_NAME'][$i] + = $GLOBALS['db'] . "." . $one_table['TABLE_NAME']; + $GLOBALS['PMD']['OWNER'][$i] = $GLOBALS['db']; + $GLOBALS['PMD']['TABLE_NAME_SMALL'][$i] = htmlspecialchars( + $one_table['TABLE_NAME'], ENT_QUOTES + ); + + $GLOBALS['PMD_URL']['TABLE_NAME'][$i] + = $GLOBALS['db'] . "." . $one_table['TABLE_NAME']; + $GLOBALS['PMD_URL']['OWNER'][$i] = $GLOBALS['db']; + $GLOBALS['PMD_URL']['TABLE_NAME_SMALL'][$i] + = $one_table['TABLE_NAME']; + + $GLOBALS['PMD_OUT']['TABLE_NAME'][$i] = htmlspecialchars( + $GLOBALS['db'] . "." . $one_table['TABLE_NAME'], ENT_QUOTES + ); + $GLOBALS['PMD_OUT']['OWNER'][$i] = htmlspecialchars( + $GLOBALS['db'], ENT_QUOTES + ); + $GLOBALS['PMD_OUT']['TABLE_NAME_SMALL'][$i] = htmlspecialchars( + $one_table['TABLE_NAME'], ENT_QUOTES + ); + + $GLOBALS['PMD']['TABLE_TYPE'][$i] = mb_strtoupper( + $one_table['ENGINE'] + ); + + $DF = Relation::getDisplayField($GLOBALS['db'], $one_table['TABLE_NAME']); + if ($DF != '') { + $retval[$GLOBALS['PMD_URL']["TABLE_NAME_SMALL"][$i]] = $DF; + } + + $i++; + } + + return $retval; + } + + /** + * Retrieves table column info + * + * @return array table column nfo + */ + public static function getColumnsInfo() + { + $GLOBALS['dbi']->selectDb($GLOBALS['db']); + $tab_column = array(); + for ($i = 0, $cnt = count($GLOBALS['PMD']["TABLE_NAME"]); $i < $cnt; $i++) { + $fields_rs = $GLOBALS['dbi']->query( + $GLOBALS['dbi']->getColumnsSql( + $GLOBALS['db'], + $GLOBALS['PMD_URL']["TABLE_NAME_SMALL"][$i], + null, + true + ), + null, + DatabaseInterface::QUERY_STORE + ); + $tbl_name_i = $GLOBALS['PMD']['TABLE_NAME'][$i]; + $j = 0; + while ($row = $GLOBALS['dbi']->fetchAssoc($fields_rs)) { + $tab_column[$tbl_name_i]['COLUMN_ID'][$j] = $j; + $tab_column[$tbl_name_i]['COLUMN_NAME'][$j] = $row['Field']; + $tab_column[$tbl_name_i]['TYPE'][$j] = $row['Type']; + $tab_column[$tbl_name_i]['NULLABLE'][$j] = $row['Null']; + $j++; + } + } + return $tab_column; + } + + /** + * Returns JavaScript code for initializing vars + * + * @return string JavaScript code + */ + public static function getScriptContr() + { + $GLOBALS['dbi']->selectDb($GLOBALS['db']); + $con = array(); + $con["C_NAME"] = array(); + $i = 0; + $alltab_rs = $GLOBALS['dbi']->query( + 'SHOW TABLES FROM ' . Util::backquote($GLOBALS['db']), + null, + DatabaseInterface::QUERY_STORE + ); + while ($val = @$GLOBALS['dbi']->fetchRow($alltab_rs)) { + $row = Relation::getForeigners($GLOBALS['db'], $val[0], '', 'internal'); + + if ($row !== false) { + foreach ($row as $field => $value) { + $con['C_NAME'][$i] = ''; + $con['DTN'][$i] = urlencode($GLOBALS['db'] . "." . $val[0]); + $con['DCN'][$i] = urlencode($field); + $con['STN'][$i] = urlencode( + $value['foreign_db'] . "." . $value['foreign_table'] + ); + $con['SCN'][$i] = urlencode($value['foreign_field']); + $i++; + } + } + $row = Relation::getForeigners($GLOBALS['db'], $val[0], '', 'foreign'); + + if ($row !== false) { + foreach ($row['foreign_keys_data'] as $one_key) { + foreach ($one_key['index_list'] as $index => $one_field) { + $con['C_NAME'][$i] = $one_key['constraint']; + $con['DTN'][$i] = urlencode($GLOBALS['db'] . "." . $val[0]); + $con['DCN'][$i] = urlencode($one_field); + $con['STN'][$i] = urlencode( + (isset($one_key['ref_db_name']) ? + $one_key['ref_db_name'] : $GLOBALS['db']) + . "." . $one_key['ref_table_name'] + ); + $con['SCN'][$i] = urlencode($one_key['ref_index_list'][$index]); + $i++; + } + } + } + } + + $ti = 0; + $retval = array(); + for ($i = 0, $cnt = count($con["C_NAME"]); $i < $cnt; $i++) { + $c_name_i = $con['C_NAME'][$i]; + $dtn_i = $con['DTN'][$i]; + $retval[$ti] = array(); + $retval[$ti][$c_name_i] = array(); + if (in_array($dtn_i, $GLOBALS['PMD_URL']["TABLE_NAME"]) + && in_array($con['STN'][$i], $GLOBALS['PMD_URL']["TABLE_NAME"]) + ) { + $retval[$ti][$c_name_i][$dtn_i] = array(); + $retval[$ti][$c_name_i][$dtn_i][$con['DCN'][$i]] = array( + 0 => $con['STN'][$i], + 1 => $con['SCN'][$i] + ); + } + $ti++; + } + return $retval; + } + + /** + * Returns UNIQUE and PRIMARY indices + * + * @return array unique or primary indices + */ + public static function getPkOrUniqueKeys() + { + return self::getAllKeys(true); + } + + /** + * Returns all indices + * + * @param bool $unique_only whether to include only unique ones + * + * @return array indices + */ + public static function getAllKeys($unique_only = false) + { + $keys = array(); + + foreach ($GLOBALS['PMD']['TABLE_NAME_SMALL'] as $I => $table) { + $schema = $GLOBALS['PMD']['OWNER'][$I]; + // for now, take into account only the first index segment + foreach (Index::getFromTable($table, $schema) as $index) { + if ($unique_only && ! $index->isUnique()) { + continue; + } + $columns = $index->getColumns(); + foreach ($columns as $column_name => $dummy) { + $keys[$schema . '.' . $table . '.' . $column_name] = 1; + } + } + } + return $keys; + } + + /** + * Return script to create j_tab and h_tab arrays + * + * @return string + */ + public static function getScriptTabs() + { + $retval = array( + 'j_tabs' => array(), + 'h_tabs' => array() + ); + + for ($i = 0, $cnt = count($GLOBALS['PMD']['TABLE_NAME']); $i < $cnt; $i++) { + $j = 0; + if (Util::isForeignKeySupported($GLOBALS['PMD']['TABLE_TYPE'][$i])) { + $j = 1; + } + $retval['j_tabs'][$GLOBALS['PMD_URL']['TABLE_NAME'][$i]] = $j; + $retval['h_tabs'][$GLOBALS['PMD_URL']['TABLE_NAME'][$i]] = 1; + } + return $retval; + } + + /** + * Returns table positions of a given pdf page + * + * @param int $pg pdf page id + * + * @return array of table positions + */ + public static function getTablePositions($pg) + { + $cfgRelation = Relation::getRelationsParam(); + if (! $cfgRelation['pdfwork']) { + return null; + } + + $query = " + SELECT CONCAT_WS('.', `db_name`, `table_name`) AS `name`, + `x` AS `X`, + `y` AS `Y`, + 1 AS `V`, + 1 AS `H` + FROM " . Util::backquote($cfgRelation['db']) + . "." . Util::backquote($cfgRelation['table_coords']) . " + WHERE pdf_page_number = " . intval($pg); + + $tab_pos = $GLOBALS['dbi']->fetchResult( + $query, + 'name', + null, + $GLOBALS['controllink'], + DatabaseInterface::QUERY_STORE + ); + return $tab_pos; + } + + /** + * Returns page name of a given pdf page + * + * @param int $pg pdf page id + * + * @return String table name + */ + public static function getPageName($pg) + { + $cfgRelation = Relation::getRelationsParam(); + if (! $cfgRelation['pdfwork']) { + return null; + } + + $query = "SELECT `page_descr`" + . " FROM " . Util::backquote($cfgRelation['db']) + . "." . Util::backquote($cfgRelation['pdf_pages']) + . " WHERE " . Util::backquote('page_nr') . " = " . intval($pg); + $page_name = $GLOBALS['dbi']->fetchResult( + $query, + null, + null, + $GLOBALS['controllink'], + DatabaseInterface::QUERY_STORE + ); + return count($page_name) ? $page_name[0] : null; + } + + /** + * Deletes a given pdf page and its corresponding coordinates + * + * @param int $pg page id + * + * @return boolean success/failure + */ + public static function deletePage($pg) + { + $cfgRelation = Relation::getRelationsParam(); + if (! $cfgRelation['pdfwork']) { + return false; + } + + $query = "DELETE FROM " . Util::backquote($cfgRelation['db']) + . "." . Util::backquote($cfgRelation['table_coords']) + . " WHERE " . Util::backquote('pdf_page_number') . " = " . intval($pg); + $success = Relation::queryAsControlUser( + $query, true, DatabaseInterface::QUERY_STORE + ); + + if ($success) { + $query = "DELETE FROM " . Util::backquote($cfgRelation['db']) + . "." . Util::backquote($cfgRelation['pdf_pages']) + . " WHERE " . Util::backquote('page_nr') . " = " . intval($pg); + $success = Relation::queryAsControlUser( + $query, true, DatabaseInterface::QUERY_STORE + ); + } + + return (boolean) $success; + } + + /** + * Returns the id of the default pdf page of the database. + * Default page is the one which has the same name as the database. + * + * @param string $db database + * + * @return int id of the default pdf page for the database + */ + public static function getDefaultPage($db) + { + $cfgRelation = Relation::getRelationsParam(); + if (! $cfgRelation['pdfwork']) { + return null; + } + + $query = "SELECT `page_nr`" + . " FROM " . Util::backquote($cfgRelation['db']) + . "." . Util::backquote($cfgRelation['pdf_pages']) + . " WHERE `db_name` = '" . $GLOBALS['dbi']->escapeString($db) . "'" + . " AND `page_descr` = '" . $GLOBALS['dbi']->escapeString($db) . "'"; + + $default_page_no = $GLOBALS['dbi']->fetchResult( + $query, + null, + null, + $GLOBALS['controllink'], + DatabaseInterface::QUERY_STORE + ); + + if (count($default_page_no)) { + return intval($default_page_no[0]); + } + return -1; + } + + /** + * Get the id of the page to load. If a default page exists it will be returned. + * If no such exists, returns the id of the first page of the database. + * + * @param string $db database + * + * @return int id of the page to load + */ + public static function getLoadingPage($db) + { + $cfgRelation = Relation::getRelationsParam(); + if (! $cfgRelation['pdfwork']) { + return null; + } + + $page_no = -1; + + $default_page_no = self::getDefaultPage($db); + if ($default_page_no != -1) { + $page_no = $default_page_no; + } else { + $query = "SELECT MIN(`page_nr`)" + . " FROM " . Util::backquote($cfgRelation['db']) + . "." . Util::backquote($cfgRelation['pdf_pages']) + . " WHERE `db_name` = '" . $GLOBALS['dbi']->escapeString($db) . "'"; + + $min_page_no = $GLOBALS['dbi']->fetchResult( + $query, + null, + null, + $GLOBALS['controllink'], + DatabaseInterface::QUERY_STORE + ); + if (count($min_page_no[0])) { + $page_no = $min_page_no[0]; + } + } + return intval($page_no); + } + + /** + * Creates a new page and returns its auto-incrementing id + * + * @param string $pageName name of the page + * @param string $db name of the database + * + * @return int|null + */ + public static function createNewPage($pageName, $db) + { + $cfgRelation = Relation::getRelationsParam(); + if ($cfgRelation['pdfwork']) { + $pageNumber = Relation::createPage( + $pageName, + $cfgRelation, + $db + ); + return $pageNumber; + } + return null; + } + + /** + * Saves positions of table(s) of a given pdf page + * + * @param int $pg pdf page id + * + * @return boolean success/failure + */ + public static function saveTablePositions($pg) + { + $cfgRelation = Relation::getRelationsParam(); + if (! $cfgRelation['pdfwork']) { + return false; + } + + $query = "DELETE FROM " + . Util::backquote($GLOBALS['cfgRelation']['db']) + . "." . Util::backquote( + $GLOBALS['cfgRelation']['table_coords'] + ) + . " WHERE `db_name` = '" . $GLOBALS['dbi']->escapeString($_REQUEST['db']) + . "'" + . " AND `pdf_page_number` = '" . $GLOBALS['dbi']->escapeString($pg) + . "'"; + + $res = Relation::queryAsControlUser( + $query, + true, + DatabaseInterface::QUERY_STORE + ); + + if (!$res) { + return (boolean)$res; + } + + foreach ($_REQUEST['t_h'] as $key => $value) { + list($DB, $TAB) = explode(".", $key); + if (!$value) { + continue; + } + + $query = "INSERT INTO " + . Util::backquote($GLOBALS['cfgRelation']['db']) . "." + . Util::backquote($GLOBALS['cfgRelation']['table_coords']) + . " (`db_name`, `table_name`, `pdf_page_number`, `x`, `y`)" + . " VALUES (" + . "'" . $GLOBALS['dbi']->escapeString($DB) . "', " + . "'" . $GLOBALS['dbi']->escapeString($TAB) . "', " + . "'" . $GLOBALS['dbi']->escapeString($pg) . "', " + . "'" . $GLOBALS['dbi']->escapeString($_REQUEST['t_x'][$key]) . "', " + . "'" . $GLOBALS['dbi']->escapeString($_REQUEST['t_y'][$key]) . "')"; + + $res = Relation::queryAsControlUser( + $query, true, DatabaseInterface::QUERY_STORE + ); + } + + return (boolean) $res; + } + + /** + * Saves the display field for a table. + * + * @param string $db database name + * @param string $table table name + * @param string $field display field name + * + * @return boolean + */ + public static function saveDisplayField($db, $table, $field) + { + $cfgRelation = Relation::getRelationsParam(); + if (!$cfgRelation['displaywork']) { + return false; + } + + $upd_query = new Table($table, $db, $GLOBALS['dbi']); + $upd_query->updateDisplayField($field, $cfgRelation); + + return true; + } + + /** + * Adds a new foreign relation + * + * @param string $db database name + * @param string $T1 foreign table + * @param string $F1 foreign field + * @param string $T2 master table + * @param string $F2 master field + * @param string $on_delete on delete action + * @param string $on_update on update action + * + * @return array array of success/failure and message + */ + public static function addNewRelation($db, $T1, $F1, $T2, $F2, $on_delete, $on_update, $DB1, $DB2) + { + $tables = $GLOBALS['dbi']->getTablesFull($DB1, $T1); + $type_T1 = mb_strtoupper($tables[$T1]['ENGINE']); + $tables = $GLOBALS['dbi']->getTablesFull($DB2, $T2); + $type_T2 = mb_strtoupper($tables[$T2]['ENGINE']); + + // native foreign key + if (Util::isForeignKeySupported($type_T1) + && Util::isForeignKeySupported($type_T2) + && $type_T1 == $type_T2 + ) { + // relation exists? + $existrel_foreign = Relation::getForeigners($DB2, $T2, '', 'foreign'); + $foreigner = Relation::searchColumnInForeigners($existrel_foreign, $F2); + if ($foreigner + && isset($foreigner['constraint']) + ) { + return array(false, __('Error: relationship already exists.')); + } + // note: in InnoDB, the index does not requires to be on a PRIMARY + // or UNIQUE key + // improve: check all other requirements for InnoDB relations + $result = $GLOBALS['dbi']->query( + 'SHOW INDEX FROM ' . Util::backquote($DB1) + . '.' . Util::backquote($T1) . ';' + ); + + // will be use to emphasis prim. keys in the table view + $index_array1 = array(); + while ($row = $GLOBALS['dbi']->fetchAssoc($result)) { + $index_array1[$row['Column_name']] = 1; + } + $GLOBALS['dbi']->freeResult($result); + + $result = $GLOBALS['dbi']->query( + 'SHOW INDEX FROM ' . Util::backquote($DB2) + . '.' . Util::backquote($T2) . ';' + ); + // will be used to emphasis prim. keys in the table view + $index_array2 = array(); + while ($row = $GLOBALS['dbi']->fetchAssoc($result)) { + $index_array2[$row['Column_name']] = 1; + } + $GLOBALS['dbi']->freeResult($result); + + if (! empty($index_array1[$F1]) && ! empty($index_array2[$F2])) { + $upd_query = 'ALTER TABLE ' . Util::backquote($DB2) + . '.' . Util::backquote($T2) + . ' ADD FOREIGN KEY (' + . Util::backquote($F2) . ')' + . ' REFERENCES ' + . Util::backquote($DB1) . '.' + . Util::backquote($T1) . '(' + . Util::backquote($F1) . ')'; + + if ($on_delete != 'nix') { + $upd_query .= ' ON DELETE ' . $on_delete; + } + if ($on_update != 'nix') { + $upd_query .= ' ON UPDATE ' . $on_update; + } + $upd_query .= ';'; + if ($GLOBALS['dbi']->tryQuery($upd_query)) { + return array(true, __('FOREIGN KEY relationship has been added.')); + } + + $error = $GLOBALS['dbi']->getError(); + return array( + false, + __('Error: FOREIGN KEY relationship could not be added!') + . "<br/>" . $error + ); + } + + return array(false, __('Error: Missing index on column(s).')); + } + + // internal (pmadb) relation + if ($GLOBALS['cfgRelation']['relwork'] == false) { + return array(false, __('Error: Relational features are disabled!')); + } + + // no need to recheck if the keys are primary or unique at this point, + // this was checked on the interface part + + $q = "INSERT INTO " + . Util::backquote($GLOBALS['cfgRelation']['db']) + . "." + . Util::backquote($GLOBALS['cfgRelation']['relation']) + . "(master_db, master_table, master_field, " + . "foreign_db, foreign_table, foreign_field)" + . " values(" + . "'" . $GLOBALS['dbi']->escapeString($DB2) . "', " + . "'" . $GLOBALS['dbi']->escapeString($T2) . "', " + . "'" . $GLOBALS['dbi']->escapeString($F2) . "', " + . "'" . $GLOBALS['dbi']->escapeString($DB1) . "', " + . "'" . $GLOBALS['dbi']->escapeString($T1) . "', " + . "'" . $GLOBALS['dbi']->escapeString($F1) . "')"; + + if (Relation::queryAsControlUser($q, false, DatabaseInterface::QUERY_STORE) + ) { + return array(true, __('Internal relationship has been added.')); + } + + $error = $GLOBALS['dbi']->getError($GLOBALS['controllink']); + return array( + false, + __('Error: Internal relationship could not be added!') + . "<br/>" . $error + ); + } + + /** + * Removes a foreign relation + * + * @param string $T1 foreign db.table + * @param string $F1 foreign field + * @param string $T2 master db.table + * @param string $F2 master field + * + * @return array array of success/failure and message + */ + public static function removeRelation($T1, $F1, $T2, $F2) + { + list($DB1, $T1) = explode(".", $T1); + list($DB2, $T2) = explode(".", $T2); + + $tables = $GLOBALS['dbi']->getTablesFull($DB1, $T1); + $type_T1 = mb_strtoupper($tables[$T1]['ENGINE']); + $tables = $GLOBALS['dbi']->getTablesFull($DB2, $T2); + $type_T2 = mb_strtoupper($tables[$T2]['ENGINE']); + + if (Util::isForeignKeySupported($type_T1) + && Util::isForeignKeySupported($type_T2) + && $type_T1 == $type_T2 + ) { + // InnoDB + $existrel_foreign = Relation::getForeigners($DB2, $T2, '', 'foreign'); + $foreigner = Relation::searchColumnInForeigners($existrel_foreign, $F2); + + if (isset($foreigner['constraint'])) { + $upd_query = 'ALTER TABLE ' . Util::backquote($DB2) + . '.' . Util::backquote($T2) . ' DROP FOREIGN KEY ' + . Util::backquote($foreigner['constraint']) . ';'; + if ($GLOBALS['dbi']->query($upd_query)) { + return array(true, __('FOREIGN KEY relationship has been removed.')); + } + + $error = $GLOBALS['dbi']->getError(); + return array( + false, + __('Error: FOREIGN KEY relationship could not be removed!') + . "<br/>" . $error + ); + } + } + + // internal relations + $delete_query = "DELETE FROM " + . Util::backquote($GLOBALS['cfgRelation']['db']) . "." + . $GLOBALS['cfgRelation']['relation'] . " WHERE " + . "master_db = '" . $GLOBALS['dbi']->escapeString($DB2) . "'" + . " AND master_table = '" . $GLOBALS['dbi']->escapeString($T2) . "'" + . " AND master_field = '" . $GLOBALS['dbi']->escapeString($F2) . "'" + . " AND foreign_db = '" . $GLOBALS['dbi']->escapeString($DB1) . "'" + . " AND foreign_table = '" . $GLOBALS['dbi']->escapeString($T1) . "'" + . " AND foreign_field = '" . $GLOBALS['dbi']->escapeString($F1) . "'"; + + $result = Relation::queryAsControlUser( + $delete_query, + false, + DatabaseInterface::QUERY_STORE + ); + + if (!$result) { + $error = $GLOBALS['dbi']->getError($GLOBALS['controllink']); + return array( + false, + __('Error: Internal relationship could not be removed!') . "<br/>" . $error + ); + } + + return array(true, __('Internal relationship has been removed.')); + } + + /** + * Save value for a designer setting + * + * @param string $index setting + * @param string $value value + * + * @return bool whether the operation succeeded + */ + public static function saveDesignerSetting($index, $value) + { + $cfgRelation = Relation::getRelationsParam(); + $cfgDesigner = array( + 'user' => $GLOBALS['cfg']['Server']['user'], + 'db' => $cfgRelation['db'], + 'table' => $cfgRelation['designer_settings'] + ); + + $success = true; + if ($GLOBALS['cfgRelation']['designersettingswork']) { + + $orig_data_query = "SELECT settings_data" + . " FROM " . Util::backquote($cfgDesigner['db']) + . "." . Util::backquote($cfgDesigner['table']) + . " WHERE username = '" + . $GLOBALS['dbi']->escapeString($cfgDesigner['user']) . "';"; + + $orig_data = $GLOBALS['dbi']->fetchSingleRow( + $orig_data_query, 'ASSOC', $GLOBALS['controllink'] + ); + + if (! empty($orig_data)) { + $orig_data = json_decode($orig_data['settings_data'], true); + $orig_data[$index] = $value; + $orig_data = json_encode($orig_data); + + $save_query = "UPDATE " + . Util::backquote($cfgDesigner['db']) + . "." . Util::backquote($cfgDesigner['table']) + . " SET settings_data = '" . $orig_data . "'" + . " WHERE username = '" + . $GLOBALS['dbi']->escapeString($cfgDesigner['user']) . "';"; + + $success = Relation::queryAsControlUser($save_query); + } else { + $save_data = array($index => $value); + + $query = "INSERT INTO " + . Util::backquote($cfgDesigner['db']) + . "." . Util::backquote($cfgDesigner['table']) + . " (username, settings_data)" + . " VALUES('" . $cfgDesigner['user'] . "'," + . " '" . json_encode($save_data) . "');"; + + $success = Relation::queryAsControlUser($query); + } + } + + return (bool) $success; + } +} diff --git a/libraries/pmd_common.php b/libraries/pmd_common.php deleted file mode 100644 index 078b824f47..0000000000 --- a/libraries/pmd_common.php +++ /dev/null @@ -1,773 +0,0 @@ -<?php -/* vim: set expandtab sw=4 ts=4 sts=4: */ -/** - * Common functions for Designer - * - * @package PhpMyAdmin-Designer - */ -use PhpMyAdmin\Relation; -use PhpMyAdmin\Table; - -/** - * Block attempts to directly run this script - */ -if (! defined('PHPMYADMIN')) { - exit; -} - -$GLOBALS['PMD']['STYLE'] = 'default'; - -$cfgRelation = Relation::getRelationsParam(); - -/** - * Retrieves table info and stores it in $GLOBALS['PMD'] - * - * @return array with table info - */ -function PMA_getTablesInfo() -{ - $retval = array(); - - $GLOBALS['PMD']['TABLE_NAME'] = array();// that foreach no error - $GLOBALS['PMD']['OWNER'] = array(); - $GLOBALS['PMD']['TABLE_NAME_SMALL'] = array(); - - $tables = $GLOBALS['dbi']->getTablesFull($GLOBALS['db']); - // seems to be needed later - $GLOBALS['dbi']->selectDb($GLOBALS['db']); - $i = 0; - foreach ($tables as $one_table) { - $GLOBALS['PMD']['TABLE_NAME'][$i] - = $GLOBALS['db'] . "." . $one_table['TABLE_NAME']; - $GLOBALS['PMD']['OWNER'][$i] = $GLOBALS['db']; - $GLOBALS['PMD']['TABLE_NAME_SMALL'][$i] = htmlspecialchars( - $one_table['TABLE_NAME'], ENT_QUOTES - ); - - $GLOBALS['PMD_URL']['TABLE_NAME'][$i] - = $GLOBALS['db'] . "." . $one_table['TABLE_NAME']; - $GLOBALS['PMD_URL']['OWNER'][$i] = $GLOBALS['db']; - $GLOBALS['PMD_URL']['TABLE_NAME_SMALL'][$i] - = $one_table['TABLE_NAME']; - - $GLOBALS['PMD_OUT']['TABLE_NAME'][$i] = htmlspecialchars( - $GLOBALS['db'] . "." . $one_table['TABLE_NAME'], ENT_QUOTES - ); - $GLOBALS['PMD_OUT']['OWNER'][$i] = htmlspecialchars( - $GLOBALS['db'], ENT_QUOTES - ); - $GLOBALS['PMD_OUT']['TABLE_NAME_SMALL'][$i] = htmlspecialchars( - $one_table['TABLE_NAME'], ENT_QUOTES - ); - - $GLOBALS['PMD']['TABLE_TYPE'][$i] = mb_strtoupper( - $one_table['ENGINE'] - ); - - $DF = Relation::getDisplayField($GLOBALS['db'], $one_table['TABLE_NAME']); - if ($DF != '') { - $retval[$GLOBALS['PMD_URL']["TABLE_NAME_SMALL"][$i]] = $DF; - } - - $i++; - } - - return $retval; -} - -/** - * Retrieves table column info - * - * @return array table column nfo - */ -function PMA_getColumnsInfo() -{ - $GLOBALS['dbi']->selectDb($GLOBALS['db']); - $tab_column = array(); - for ($i = 0, $cnt = count($GLOBALS['PMD']["TABLE_NAME"]); $i < $cnt; $i++) { - $fields_rs = $GLOBALS['dbi']->query( - $GLOBALS['dbi']->getColumnsSql( - $GLOBALS['db'], - $GLOBALS['PMD_URL']["TABLE_NAME_SMALL"][$i], - null, - true - ), - null, - PhpMyAdmin\DatabaseInterface::QUERY_STORE - ); - $tbl_name_i = $GLOBALS['PMD']['TABLE_NAME'][$i]; - $j = 0; - while ($row = $GLOBALS['dbi']->fetchAssoc($fields_rs)) { - $tab_column[$tbl_name_i]['COLUMN_ID'][$j] = $j; - $tab_column[$tbl_name_i]['COLUMN_NAME'][$j] = $row['Field']; - $tab_column[$tbl_name_i]['TYPE'][$j] = $row['Type']; - $tab_column[$tbl_name_i]['NULLABLE'][$j] = $row['Null']; - $j++; - } - } - return $tab_column; -} - -/** - * Returns JavaScript code for initializing vars - * - * @return string JavaScript code - */ -function PMA_getScriptContr() -{ - $GLOBALS['dbi']->selectDb($GLOBALS['db']); - $con = array(); - $con["C_NAME"] = array(); - $i = 0; - $alltab_rs = $GLOBALS['dbi']->query( - 'SHOW TABLES FROM ' . PhpMyAdmin\Util::backquote($GLOBALS['db']), - null, - PhpMyAdmin\DatabaseInterface::QUERY_STORE - ); - while ($val = @$GLOBALS['dbi']->fetchRow($alltab_rs)) { - $row = Relation::getForeigners($GLOBALS['db'], $val[0], '', 'internal'); - - if ($row !== false) { - foreach ($row as $field => $value) { - $con['C_NAME'][$i] = ''; - $con['DTN'][$i] = urlencode($GLOBALS['db'] . "." . $val[0]); - $con['DCN'][$i] = urlencode($field); - $con['STN'][$i] = urlencode( - $value['foreign_db'] . "." . $value['foreign_table'] - ); - $con['SCN'][$i] = urlencode($value['foreign_field']); - $i++; - } - } - $row = Relation::getForeigners($GLOBALS['db'], $val[0], '', 'foreign'); - - if ($row !== false) { - foreach ($row['foreign_keys_data'] as $one_key) { - foreach ($one_key['index_list'] as $index => $one_field) { - $con['C_NAME'][$i] = $one_key['constraint']; - $con['DTN'][$i] = urlencode($GLOBALS['db'] . "." . $val[0]); - $con['DCN'][$i] = urlencode($one_field); - $con['STN'][$i] = urlencode( - (isset($one_key['ref_db_name']) ? - $one_key['ref_db_name'] : $GLOBALS['db']) - . "." . $one_key['ref_table_name'] - ); - $con['SCN'][$i] = urlencode($one_key['ref_index_list'][$index]); - $i++; - } - } - } - } - - $ti = 0; - $retval = array(); - for ($i = 0, $cnt = count($con["C_NAME"]); $i < $cnt; $i++) { - $c_name_i = $con['C_NAME'][$i]; - $dtn_i = $con['DTN'][$i]; - $retval[$ti] = array(); - $retval[$ti][$c_name_i] = array(); - if (in_array($dtn_i, $GLOBALS['PMD_URL']["TABLE_NAME"]) - && in_array($con['STN'][$i], $GLOBALS['PMD_URL']["TABLE_NAME"]) - ) { - $retval[$ti][$c_name_i][$dtn_i] = array(); - $retval[$ti][$c_name_i][$dtn_i][$con['DCN'][$i]] = array( - 0 => $con['STN'][$i], - 1 => $con['SCN'][$i] - ); - } - $ti++; - } - return $retval; -} - -/** - * Returns UNIQUE and PRIMARY indices - * - * @return array unique or primary indices - */ -function PMA_getPKOrUniqueKeys() -{ - return PMA_getAllKeys(true); -} - -/** - * Returns all indices - * - * @param bool $unique_only whether to include only unique ones - * - * @return array indices - */ -function PMA_getAllKeys($unique_only = false) -{ - $keys = array(); - - foreach ($GLOBALS['PMD']['TABLE_NAME_SMALL'] as $I => $table) { - $schema = $GLOBALS['PMD']['OWNER'][$I]; - // for now, take into account only the first index segment - foreach (PhpMyAdmin\Index::getFromTable($table, $schema) as $index) { - if ($unique_only && ! $index->isUnique()) { - continue; - } - $columns = $index->getColumns(); - foreach ($columns as $column_name => $dummy) { - $keys[$schema . '.' . $table . '.' . $column_name] = 1; - } - } - } - return $keys; -} - -/** - * Return script to create j_tab and h_tab arrays - * - * @return string - */ -function PMA_getScriptTabs() -{ - $retval = array( - 'j_tabs' => array(), - 'h_tabs' => array() - ); - - for ($i = 0, $cnt = count($GLOBALS['PMD']['TABLE_NAME']); $i < $cnt; $i++) { - $j = 0; - if (PhpMyAdmin\Util::isForeignKeySupported($GLOBALS['PMD']['TABLE_TYPE'][$i])) { - $j = 1; - } - $retval['j_tabs'][$GLOBALS['PMD_URL']['TABLE_NAME'][$i]] = $j; - $retval['h_tabs'][$GLOBALS['PMD_URL']['TABLE_NAME'][$i]] = 1; - } - return $retval; -} - -/** - * Returns table positions of a given pdf page - * - * @param int $pg pdf page id - * - * @return array of table positions - */ -function PMA_getTablePositions($pg) -{ - $cfgRelation = Relation::getRelationsParam(); - if (! $cfgRelation['pdfwork']) { - return null; - } - - $query = " - SELECT CONCAT_WS('.', `db_name`, `table_name`) AS `name`, - `x` AS `X`, - `y` AS `Y`, - 1 AS `V`, - 1 AS `H` - FROM " . PhpMyAdmin\Util::backquote($cfgRelation['db']) - . "." . PhpMyAdmin\Util::backquote($cfgRelation['table_coords']) . " - WHERE pdf_page_number = " . intval($pg); - - $tab_pos = $GLOBALS['dbi']->fetchResult( - $query, - 'name', - null, - $GLOBALS['controllink'], - PhpMyAdmin\DatabaseInterface::QUERY_STORE - ); - return $tab_pos; -} - -/** - * Returns page name of a given pdf page - * - * @param int $pg pdf page id - * - * @return String table name - */ -function PMA_getPageName($pg) -{ - $cfgRelation = Relation::getRelationsParam(); - if (! $cfgRelation['pdfwork']) { - return null; - } - - $query = "SELECT `page_descr`" - . " FROM " . PhpMyAdmin\Util::backquote($cfgRelation['db']) - . "." . PhpMyAdmin\Util::backquote($cfgRelation['pdf_pages']) - . " WHERE " . PhpMyAdmin\Util::backquote('page_nr') . " = " . intval($pg); - $page_name = $GLOBALS['dbi']->fetchResult( - $query, - null, - null, - $GLOBALS['controllink'], - PhpMyAdmin\DatabaseInterface::QUERY_STORE - ); - return count($page_name) ? $page_name[0] : null; -} - -/** - * Deletes a given pdf page and its corresponding coordinates - * - * @param int $pg page id - * - * @return boolean success/failure - */ -function PMA_deletePage($pg) -{ - $cfgRelation = Relation::getRelationsParam(); - if (! $cfgRelation['pdfwork']) { - return false; - } - - $query = "DELETE FROM " . PhpMyAdmin\Util::backquote($cfgRelation['db']) - . "." . PhpMyAdmin\Util::backquote($cfgRelation['table_coords']) - . " WHERE " . PhpMyAdmin\Util::backquote('pdf_page_number') . " = " . intval($pg); - $success = Relation::queryAsControlUser( - $query, true, PhpMyAdmin\DatabaseInterface::QUERY_STORE - ); - - if ($success) { - $query = "DELETE FROM " . PhpMyAdmin\Util::backquote($cfgRelation['db']) - . "." . PhpMyAdmin\Util::backquote($cfgRelation['pdf_pages']) - . " WHERE " . PhpMyAdmin\Util::backquote('page_nr') . " = " . intval($pg); - $success = Relation::queryAsControlUser( - $query, true, PhpMyAdmin\DatabaseInterface::QUERY_STORE - ); - } - - return (boolean) $success; -} - -/** - * Returns the id of the default pdf page of the database. - * Default page is the one which has the same name as the database. - * - * @param string $db database - * - * @return int id of the default pdf page for the database - */ -function PMA_getDefaultPage($db) -{ - $cfgRelation = Relation::getRelationsParam(); - if (! $cfgRelation['pdfwork']) { - return null; - } - - $query = "SELECT `page_nr`" - . " FROM " . PhpMyAdmin\Util::backquote($cfgRelation['db']) - . "." . PhpMyAdmin\Util::backquote($cfgRelation['pdf_pages']) - . " WHERE `db_name` = '" . $GLOBALS['dbi']->escapeString($db) . "'" - . " AND `page_descr` = '" . $GLOBALS['dbi']->escapeString($db) . "'"; - - $default_page_no = $GLOBALS['dbi']->fetchResult( - $query, - null, - null, - $GLOBALS['controllink'], - PhpMyAdmin\DatabaseInterface::QUERY_STORE - ); - - if (count($default_page_no)) { - return intval($default_page_no[0]); - } - return -1; -} - -/** - * Get the id of the page to load. If a default page exists it will be returned. - * If no such exists, returns the id of the first page of the database. - * - * @param string $db database - * - * @return int id of the page to load - */ -function PMA_getLoadingPage($db) -{ - $cfgRelation = Relation::getRelationsParam(); - if (! $cfgRelation['pdfwork']) { - return null; - } - - $page_no = -1; - - $default_page_no = PMA_getDefaultPage($db); - if ($default_page_no != -1) { - $page_no = $default_page_no; - } else { - $query = "SELECT MIN(`page_nr`)" - . " FROM " . PhpMyAdmin\Util::backquote($cfgRelation['db']) - . "." . PhpMyAdmin\Util::backquote($cfgRelation['pdf_pages']) - . " WHERE `db_name` = '" . $GLOBALS['dbi']->escapeString($db) . "'"; - - $min_page_no = $GLOBALS['dbi']->fetchResult( - $query, - null, - null, - $GLOBALS['controllink'], - PhpMyAdmin\DatabaseInterface::QUERY_STORE - ); - if (count($min_page_no[0])) { - $page_no = $min_page_no[0]; - } - } - return intval($page_no); -} - -/** - * Creates a new page and returns its auto-incrementing id - * - * @param string $pageName name of the page - * @param string $db name of the database - * - * @return int|null - */ -function PMA_createNewPage($pageName, $db) -{ - $cfgRelation = Relation::getRelationsParam(); - if ($cfgRelation['pdfwork']) { - $pageNumber = Relation::createPage( - $pageName, - $cfgRelation, - $db - ); - return $pageNumber; - } - return null; -} - -/** - * Saves positions of table(s) of a given pdf page - * - * @param int $pg pdf page id - * - * @return boolean success/failure - */ -function PMA_saveTablePositions($pg) -{ - $cfgRelation = Relation::getRelationsParam(); - if (! $cfgRelation['pdfwork']) { - return false; - } - - $query = "DELETE FROM " - . PhpMyAdmin\Util::backquote($GLOBALS['cfgRelation']['db']) - . "." . PhpMyAdmin\Util::backquote( - $GLOBALS['cfgRelation']['table_coords'] - ) - . " WHERE `db_name` = '" . $GLOBALS['dbi']->escapeString($_REQUEST['db']) - . "'" - . " AND `pdf_page_number` = '" . $GLOBALS['dbi']->escapeString($pg) - . "'"; - - $res = Relation::queryAsControlUser( - $query, - true, - PhpMyAdmin\DatabaseInterface::QUERY_STORE - ); - - if (!$res) { - return (boolean)$res; - } - - foreach ($_REQUEST['t_h'] as $key => $value) { - list($DB, $TAB) = explode(".", $key); - if (!$value) { - continue; - } - - $query = "INSERT INTO " - . PhpMyAdmin\Util::backquote($GLOBALS['cfgRelation']['db']) . "." - . PhpMyAdmin\Util::backquote($GLOBALS['cfgRelation']['table_coords']) - . " (`db_name`, `table_name`, `pdf_page_number`, `x`, `y`)" - . " VALUES (" - . "'" . $GLOBALS['dbi']->escapeString($DB) . "', " - . "'" . $GLOBALS['dbi']->escapeString($TAB) . "', " - . "'" . $GLOBALS['dbi']->escapeString($pg) . "', " - . "'" . $GLOBALS['dbi']->escapeString($_REQUEST['t_x'][$key]) . "', " - . "'" . $GLOBALS['dbi']->escapeString($_REQUEST['t_y'][$key]) . "')"; - - $res = Relation::queryAsControlUser( - $query, true, PhpMyAdmin\DatabaseInterface::QUERY_STORE - ); - } - - return (boolean) $res; -} - -/** - * Saves the display field for a table. - * - * @param string $db database name - * @param string $table table name - * @param string $field display field name - * - * @return boolean - */ -function PMA_saveDisplayField($db, $table, $field) -{ - $cfgRelation = Relation::getRelationsParam(); - if (!$cfgRelation['displaywork']) { - return false; - } - - $upd_query = new Table($table, $db, $GLOBALS['dbi']); - $upd_query->updateDisplayField($field, $cfgRelation); - - return true; -} - -/** - * Adds a new foreign relation - * - * @param string $db database name - * @param string $T1 foreign table - * @param string $F1 foreign field - * @param string $T2 master table - * @param string $F2 master field - * @param string $on_delete on delete action - * @param string $on_update on update action - * - * @return array array of success/failure and message - */ -function PMA_addNewRelation($db, $T1, $F1, $T2, $F2, $on_delete, $on_update, $DB1, $DB2) -{ - $tables = $GLOBALS['dbi']->getTablesFull($DB1, $T1); - $type_T1 = mb_strtoupper($tables[$T1]['ENGINE']); - $tables = $GLOBALS['dbi']->getTablesFull($DB2, $T2); - $type_T2 = mb_strtoupper($tables[$T2]['ENGINE']); - - // native foreign key - if (PhpMyAdmin\Util::isForeignKeySupported($type_T1) - && PhpMyAdmin\Util::isForeignKeySupported($type_T2) - && $type_T1 == $type_T2 - ) { - // relation exists? - $existrel_foreign = Relation::getForeigners($DB2, $T2, '', 'foreign'); - $foreigner = Relation::searchColumnInForeigners($existrel_foreign, $F2); - if ($foreigner - && isset($foreigner['constraint']) - ) { - return array(false, __('Error: relationship already exists.')); - } - // note: in InnoDB, the index does not requires to be on a PRIMARY - // or UNIQUE key - // improve: check all other requirements for InnoDB relations - $result = $GLOBALS['dbi']->query( - 'SHOW INDEX FROM ' . PhpMyAdmin\Util::backquote($DB1) - . '.' . PhpMyAdmin\Util::backquote($T1) . ';' - ); - - // will be use to emphasis prim. keys in the table view - $index_array1 = array(); - while ($row = $GLOBALS['dbi']->fetchAssoc($result)) { - $index_array1[$row['Column_name']] = 1; - } - $GLOBALS['dbi']->freeResult($result); - - $result = $GLOBALS['dbi']->query( - 'SHOW INDEX FROM ' . PhpMyAdmin\Util::backquote($DB2) - . '.' . PhpMyAdmin\Util::backquote($T2) . ';' - ); - // will be used to emphasis prim. keys in the table view - $index_array2 = array(); - while ($row = $GLOBALS['dbi']->fetchAssoc($result)) { - $index_array2[$row['Column_name']] = 1; - } - $GLOBALS['dbi']->freeResult($result); - - if (! empty($index_array1[$F1]) && ! empty($index_array2[$F2])) { - $upd_query = 'ALTER TABLE ' . PhpMyAdmin\Util::backquote($DB2) - . '.' . PhpMyAdmin\Util::backquote($T2) - . ' ADD FOREIGN KEY (' - . PhpMyAdmin\Util::backquote($F2) . ')' - . ' REFERENCES ' - . PhpMyAdmin\Util::backquote($DB1) . '.' - . PhpMyAdmin\Util::backquote($T1) . '(' - . PhpMyAdmin\Util::backquote($F1) . ')'; - - if ($on_delete != 'nix') { - $upd_query .= ' ON DELETE ' . $on_delete; - } - if ($on_update != 'nix') { - $upd_query .= ' ON UPDATE ' . $on_update; - } - $upd_query .= ';'; - if ($GLOBALS['dbi']->tryQuery($upd_query)) { - return array(true, __('FOREIGN KEY relationship has been added.')); - } - - $error = $GLOBALS['dbi']->getError(); - return array( - false, - __('Error: FOREIGN KEY relationship could not be added!') - . "<br/>" . $error - ); - } - - return array(false, __('Error: Missing index on column(s).')); - } - - // internal (pmadb) relation - if ($GLOBALS['cfgRelation']['relwork'] == false) { - return array(false, __('Error: Relational features are disabled!')); - } - - // no need to recheck if the keys are primary or unique at this point, - // this was checked on the interface part - - $q = "INSERT INTO " - . PhpMyAdmin\Util::backquote($GLOBALS['cfgRelation']['db']) - . "." - . PhpMyAdmin\Util::backquote($GLOBALS['cfgRelation']['relation']) - . "(master_db, master_table, master_field, " - . "foreign_db, foreign_table, foreign_field)" - . " values(" - . "'" . $GLOBALS['dbi']->escapeString($DB2) . "', " - . "'" . $GLOBALS['dbi']->escapeString($T2) . "', " - . "'" . $GLOBALS['dbi']->escapeString($F2) . "', " - . "'" . $GLOBALS['dbi']->escapeString($DB1) . "', " - . "'" . $GLOBALS['dbi']->escapeString($T1) . "', " - . "'" . $GLOBALS['dbi']->escapeString($F1) . "')"; - - if (Relation::queryAsControlUser($q, false, PhpMyAdmin\DatabaseInterface::QUERY_STORE) - ) { - return array(true, __('Internal relationship has been added.')); - } - - $error = $GLOBALS['dbi']->getError($GLOBALS['controllink']); - return array( - false, - __('Error: Internal relationship could not be added!') - . "<br/>" . $error - ); -} - -/** - * Removes a foreign relation - * - * @param string $T1 foreign db.table - * @param string $F1 foreign field - * @param string $T2 master db.table - * @param string $F2 master field - * - * @return array array of success/failure and message - */ -function PMA_removeRelation($T1, $F1, $T2, $F2) -{ - list($DB1, $T1) = explode(".", $T1); - list($DB2, $T2) = explode(".", $T2); - - $tables = $GLOBALS['dbi']->getTablesFull($DB1, $T1); - $type_T1 = mb_strtoupper($tables[$T1]['ENGINE']); - $tables = $GLOBALS['dbi']->getTablesFull($DB2, $T2); - $type_T2 = mb_strtoupper($tables[$T2]['ENGINE']); - - if (PhpMyAdmin\Util::isForeignKeySupported($type_T1) - && PhpMyAdmin\Util::isForeignKeySupported($type_T2) - && $type_T1 == $type_T2 - ) { - // InnoDB - $existrel_foreign = Relation::getForeigners($DB2, $T2, '', 'foreign'); - $foreigner = Relation::searchColumnInForeigners($existrel_foreign, $F2); - - if (isset($foreigner['constraint'])) { - $upd_query = 'ALTER TABLE ' . PhpMyAdmin\Util::backquote($DB2) - . '.' . PhpMyAdmin\Util::backquote($T2) . ' DROP FOREIGN KEY ' - . PhpMyAdmin\Util::backquote($foreigner['constraint']) . ';'; - if ($GLOBALS['dbi']->query($upd_query)) { - return array(true, __('FOREIGN KEY relationship has been removed.')); - } - - $error = $GLOBALS['dbi']->getError(); - return array( - false, - __('Error: FOREIGN KEY relationship could not be removed!') - . "<br/>" . $error - ); - } - } - - // internal relations - $delete_query = "DELETE FROM " - . PhpMyAdmin\Util::backquote($GLOBALS['cfgRelation']['db']) . "." - . $GLOBALS['cfgRelation']['relation'] . " WHERE " - . "master_db = '" . $GLOBALS['dbi']->escapeString($DB2) . "'" - . " AND master_table = '" . $GLOBALS['dbi']->escapeString($T2) . "'" - . " AND master_field = '" . $GLOBALS['dbi']->escapeString($F2) . "'" - . " AND foreign_db = '" . $GLOBALS['dbi']->escapeString($DB1) . "'" - . " AND foreign_table = '" . $GLOBALS['dbi']->escapeString($T1) . "'" - . " AND foreign_field = '" . $GLOBALS['dbi']->escapeString($F1) . "'"; - - $result = Relation::queryAsControlUser( - $delete_query, - false, - PhpMyAdmin\DatabaseInterface::QUERY_STORE - ); - - if (!$result) { - $error = $GLOBALS['dbi']->getError($GLOBALS['controllink']); - return array( - false, - __('Error: Internal relationship could not be removed!') . "<br/>" . $error - ); - } - - return array(true, __('Internal relationship has been removed.')); -} - -/** - * Save value for a designer setting - * - * @param string $index setting - * @param string $value value - * - * @return bool whether the operation succeeded - */ -function PMA_saveDesignerSetting($index, $value) -{ - $cfgRelation = Relation::getRelationsParam(); - $cfgDesigner = array( - 'user' => $GLOBALS['cfg']['Server']['user'], - 'db' => $cfgRelation['db'], - 'table' => $cfgRelation['designer_settings'] - ); - - $success = true; - if ($GLOBALS['cfgRelation']['designersettingswork']) { - - $orig_data_query = "SELECT settings_data" - . " FROM " . PhpMyAdmin\Util::backquote($cfgDesigner['db']) - . "." . PhpMyAdmin\Util::backquote($cfgDesigner['table']) - . " WHERE username = '" - . $GLOBALS['dbi']->escapeString($cfgDesigner['user']) . "';"; - - $orig_data = $GLOBALS['dbi']->fetchSingleRow( - $orig_data_query, 'ASSOC', $GLOBALS['controllink'] - ); - - if (! empty($orig_data)) { - $orig_data = json_decode($orig_data['settings_data'], true); - $orig_data[$index] = $value; - $orig_data = json_encode($orig_data); - - $save_query = "UPDATE " - . PhpMyAdmin\Util::backquote($cfgDesigner['db']) - . "." . PhpMyAdmin\Util::backquote($cfgDesigner['table']) - . " SET settings_data = '" . $orig_data . "'" - . " WHERE username = '" - . $GLOBALS['dbi']->escapeString($cfgDesigner['user']) . "';"; - - $success = Relation::queryAsControlUser($save_query); - } else { - $save_data = array($index => $value); - - $query = "INSERT INTO " - . PhpMyAdmin\Util::backquote($cfgDesigner['db']) - . "." . PhpMyAdmin\Util::backquote($cfgDesigner['table']) - . " (username, settings_data)" - . " VALUES('" . $cfgDesigner['user'] . "'," - . " '" . json_encode($save_data) . "');"; - - $success = Relation::queryAsControlUser($query); - } - } - - return (bool) $success; -} diff --git a/schema_export.php b/schema_export.php index 936cc0c263..fd5d2d13ce 100644 --- a/schema_export.php +++ b/schema_export.php @@ -22,8 +22,6 @@ require_once 'libraries/common.inc.php'; */ $cfgRelation = Relation::getRelationsParam(); -require_once 'libraries/pmd_common.php'; - if (! isset($_REQUEST['export_type'])) { PhpMyAdmin\Util::checkParameters(array('export_type')); } diff --git a/test/libraries/PMA_PMD_common_test.php b/test/classes/PmdCommonTest.php index 0a6fac8dbd..ff2771a29d 100644 --- a/test/libraries/PMA_PMD_common_test.php +++ b/test/classes/PmdCommonTest.php @@ -1,17 +1,22 @@ <?php /** - * Tests for libraries/pmd_common.php + * Tests for PhpMyAdmin\PmdCommon * * @package PhpMyAdmin-test */ +namespace PhpMyAdmin\Tests; +use PhpMyAdmin\DatabaseInterface; +use PhpMyAdmin\PmdCommon; +use PhpMyAdmin\Relation; +use PHPUnit_Framework_TestCase as TestCase; /** - * Tests for libraries/pmd_common.php + * Tests for PhpMyAdmin\PmdCommon * * @package PhpMyAdmin-test */ -class PMA_PMD_CommonTest extends PHPUnit_Framework_TestCase +class PmdCommonTest extends TestCase { /** * Setup for test cases @@ -33,13 +38,10 @@ class PMA_PMD_CommonTest extends PHPUnit_Framework_TestCase ) ) ); - - include_once 'libraries/pmd_common.php'; } - /** - * Test for PMA_getTablePositions() + * Test for PmdCommon::getTablePositions() * * @return void */ @@ -57,25 +59,25 @@ class PMA_PMD_CommonTest extends PHPUnit_Framework_TestCase ->method('fetchResult') ->with( " - SELECT CONCAT_WS('.', `db_name`, `table_name`) AS `name`, - `x` AS `X`, - `y` AS `Y`, - 1 AS `V`, - 1 AS `H` - FROM `pmadb`.`table_coords` - WHERE pdf_page_number = " . $pg, + SELECT CONCAT_WS('.', `db_name`, `table_name`) AS `name`, + `x` AS `X`, + `y` AS `Y`, + 1 AS `V`, + 1 AS `H` + FROM `pmadb`.`table_coords` + WHERE pdf_page_number = " . $pg, 'name', null, 2, - PhpMyAdmin\DatabaseInterface::QUERY_STORE + DatabaseInterface::QUERY_STORE ); $GLOBALS['dbi'] = $dbi; - PMA_getTablePositions($pg); + PmdCommon::getTablePositions($pg); } /** - * Test for PMA_getPageName() + * Test for PmdCommon::getPageName() * * @return void */ @@ -98,18 +100,18 @@ class PMA_PMD_CommonTest extends PHPUnit_Framework_TestCase null, null, 2, - PhpMyAdmin\DatabaseInterface::QUERY_STORE + DatabaseInterface::QUERY_STORE ) ->will($this->returnValue(array($pageName))); $GLOBALS['dbi'] = $dbi; - $result = PMA_getPageName($pg); + $result = PmdCommon::getPageName($pg); $this->assertEquals($pageName, $result); } /** - * Test for PMA_deletePage() + * Test for PmdCommon::deletePage() * * @return void */ @@ -132,7 +134,7 @@ class PMA_PMD_CommonTest extends PHPUnit_Framework_TestCase $GLOBALS['dbi'] = $dbi; - $result = PMA_deletePage($pg); + $result = PmdCommon::deletePage($pg); $this->assertEquals(true, $result); } @@ -160,7 +162,7 @@ class PMA_PMD_CommonTest extends PHPUnit_Framework_TestCase null, null, 2, - PhpMyAdmin\DatabaseInterface::QUERY_STORE + DatabaseInterface::QUERY_STORE ) ->will($this->returnValue(array($default_pg))); $dbi->expects($this->any())->method('escapeString') @@ -168,7 +170,7 @@ class PMA_PMD_CommonTest extends PHPUnit_Framework_TestCase $GLOBALS['dbi'] = $dbi; - $result = PMA_getDefaultPage($db); + $result = PmdCommon::getDefaultPage($db); $this->assertEquals($default_pg, $result); } @@ -194,7 +196,7 @@ class PMA_PMD_CommonTest extends PHPUnit_Framework_TestCase null, null, 2, - PhpMyAdmin\DatabaseInterface::QUERY_STORE + DatabaseInterface::QUERY_STORE ) ->will($this->returnValue(array())); $dbi->expects($this->any())->method('escapeString') @@ -202,7 +204,7 @@ class PMA_PMD_CommonTest extends PHPUnit_Framework_TestCase $GLOBALS['dbi'] = $dbi; - $result = PMA_getDefaultPage($db); + $result = PmdCommon::getDefaultPage($db); $this->assertEquals(-1, $result); } @@ -229,7 +231,7 @@ class PMA_PMD_CommonTest extends PHPUnit_Framework_TestCase null, null, 2, - PhpMyAdmin\DatabaseInterface::QUERY_STORE + DatabaseInterface::QUERY_STORE ) ->will($this->returnValue(array($default_pg))); $dbi->expects($this->any())->method('escapeString') @@ -237,7 +239,7 @@ class PMA_PMD_CommonTest extends PHPUnit_Framework_TestCase $GLOBALS['dbi'] = $dbi; - $result = PMA_getLoadingPage($db); + $result = PmdCommon::getLoadingPage($db); $this->assertEquals($default_pg, $result); } @@ -266,7 +268,7 @@ class PMA_PMD_CommonTest extends PHPUnit_Framework_TestCase $GLOBALS['dbi'] = $dbi; - $result = PMA_getLoadingPage($db); + $result = PmdCommon::getLoadingPage($db); $this->assertEquals($first_pg, $result); } } |