Merge pull request #14901 from mauriciofauth/server_databases

Refactor ServerDatabasesController

Refactors PhpMyAdmin\Controllers\Server\ServerDatabasesController.

- Renames variables and methods to camelCase format.
- Moves request and response handling back to server_databases.php.
- Groups all HTML into templates/server/databases/index.twig.
- Improves unit tests.
This commit is contained in:
Maurício Meneghini Fauth 2019-01-26 16:25:10 -03:00 committed by GitHub
commit e972b3edbc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 724 additions and 871 deletions

View File

@ -1,6 +1,5 @@
<?php
/* vim: set expandtab sw=4 ts=4 sts=4: */
/**
* Holds the PhpMyAdmin\Controllers\Server\ServerDatabasesController
*
@ -11,11 +10,9 @@ declare(strict_types=1);
namespace PhpMyAdmin\Controllers\Server;
use PhpMyAdmin\Charsets;
use PhpMyAdmin\CheckUserPrivileges;
use PhpMyAdmin\Controllers\Controller;
use PhpMyAdmin\DatabaseInterface;
use PhpMyAdmin\Message;
use PhpMyAdmin\Response;
use PhpMyAdmin\Url;
use PhpMyAdmin\Util;
@ -29,234 +26,234 @@ class ServerDatabasesController extends Controller
/**
* @var array array of database details
*/
private $_databases;
private $databases = [];
/**
* @var int number of databases
*/
private $_database_count;
private $databaseCount = 0;
/**
* @var string sort by column
*/
private $_sort_by;
private $sortBy;
/**
* @var string sort order of databases
*/
private $_sort_order;
private $sortOrder;
/**
* @var boolean whether to show database statistics
*/
private $_dbstats;
private $hasStatistics;
/**
* @var int position in list navigation
*/
private $_pos;
private $position;
/**
* Index action
*
* @return void
* @param array $params Request parameters
*
* @return string HTML
*/
public function indexAction()
public function indexAction(array $params): string
{
$checkUserPrivileges = new CheckUserPrivileges($this->dbi);
$checkUserPrivileges->getPrivileges();
$response = Response::getInstance();
if (isset($_POST['drop_selected_dbs'])
&& $response->isAjax()
&& ($this->dbi->isSuperuser() || $GLOBALS['cfg']['AllowUserDropDatabase'])
) {
$this->dropDatabasesAction();
return;
}
global $cfg, $server, $dblist, $is_create_db_priv;
global $replication_info, $db_to_create, $pmaThemeImage, $text_dir;
include_once ROOT_PATH . 'libraries/replication.inc.php';
if (isset($_POST['new_db'])
&& $response->isAjax()
) {
$this->createDatabaseAction();
return;
}
include_once ROOT_PATH . 'libraries/server_common.inc.php';
$header = $this->response->getHeader();
$scripts = $header->getScripts();
$scripts->addFile('server_databases.js');
$this->_setSortDetails();
$this->_dbstats = empty($_REQUEST['dbstats']) ? false : true;
$this->_pos = empty($_REQUEST['pos']) ? 0 : (int) $_REQUEST['pos'];
$this->setSortDetails($params['sort_by'], $params['sort_order']);
$this->hasStatistics = ! empty($params['statistics']);
$this->position = ! empty($params['pos']) ? (int) $params['pos'] : 0;
/**
* Gets the databases list
*/
if ($GLOBALS['server'] > 0) {
$this->_databases = $this->dbi->getDatabasesFull(
if ($server > 0) {
$this->databases = $this->dbi->getDatabasesFull(
null,
$this->_dbstats,
$this->hasStatistics,
DatabaseInterface::CONNECT_USER,
$this->_sort_by,
$this->_sort_order,
$this->_pos,
$this->sortBy,
$this->sortOrder,
$this->position,
true
);
$this->_database_count = count($GLOBALS['dblist']->databases);
} else {
$this->_database_count = 0;
$this->databaseCount = count($dblist->databases);
}
$_url_params = [
'pos' => $this->_pos,
'dbstats' => $this->_dbstats,
'sort_by' => $this->_sort_by,
'sort_order' => $this->_sort_order,
$urlParams = [
'statistics' => $this->hasStatistics,
'pos' => $this->position,
'sort_by' => $this->sortBy,
'sort_order' => $this->sortOrder,
];
$column_order = null;
$first_database = null;
$databases = $this->getDatabases($replication_types ?? []);
if ($this->_database_count > 0 && ! empty($this->_databases)) {
$first_database = reset($this->_databases);
// table col order
$column_order = $this->_getColumnOrder();
$databases = $this->_getHtmlForDatabases($replication_types);
$collationDropdownBox = '';
if ($cfg['ShowCreateDb'] && $is_create_db_priv) {
$collationDropdownBox = Charsets::getCollationDropdownBox(
$this->dbi,
$cfg['Server']['DisableIS'],
'db_collation',
null,
$this->dbi->getServerCollation(),
true
);
}
$this->response->addHTML($this->template->render('server/databases/index', [
'show_create_db' => $GLOBALS['cfg']['ShowCreateDb'],
'is_create_db_priv' => $GLOBALS['is_create_db_priv'],
'dbstats' => $this->_dbstats,
'db_to_create' => $GLOBALS['db_to_create'],
'databases' => isset($databases) ? $databases : null,
'dbi' => $this->dbi,
'disable_is' => $GLOBALS['cfg']['Server']['DisableIS'],
'database_count' => $this->_database_count,
'pos' => $this->_pos,
'url_params' => $_url_params,
'max_db_list' => $GLOBALS['cfg']['MaxDbList'],
'sort_by' => $this->_sort_by,
'sort_order' => $this->_sort_order,
'column_order' => $column_order,
'first_database' => $first_database,
'master_replication' => $GLOBALS['replication_info']['master']['status'],
'slave_replication' => $GLOBALS['replication_info']['slave']['status'],
'is_superuser' => $this->dbi->isSuperuser(),
'allow_user_drop_database' => $GLOBALS['cfg']['AllowUserDropDatabase'],
]));
$headerStatistics = $this->getStatisticsColumns();
return $this->template->render('server/databases/index', [
'is_create_database_shown' => $cfg['ShowCreateDb'],
'has_create_database_privileges' => $is_create_db_priv,
'has_statistics' => $this->hasStatistics,
'database_to_create' => $db_to_create,
'databases' => $databases['databases'],
'total_statistics' => $databases['total_statistics'],
'header_statistics' => $headerStatistics,
'collation_dropdown_box' => $collationDropdownBox,
'database_count' => $this->databaseCount,
'pos' => $this->position,
'url_params' => $urlParams,
'max_db_list' => $cfg['MaxDbList'],
'has_master_replication' => $replication_info['master']['status'],
'has_slave_replication' => $replication_info['slave']['status'],
'is_drop_allowed' => $this->dbi->isSuperuser() || $cfg['AllowUserDropDatabase'],
'default_tab_database' => $cfg['DefaultTabDatabase'],
'pma_theme_image' => $pmaThemeImage,
'text_dir' => $text_dir,
]);
}
/**
* Handles creating a new database
*
* @return void
* @param array $params Request parameters
*
* @return array JSON
*/
public function createDatabaseAction()
public function createDatabaseAction(array $params): array
{
global $cfg, $db;
/**
* Builds and executes the db creation sql query
*/
$sql_query = 'CREATE DATABASE ' . Util::backquote($_POST['new_db']);
if (! empty($_POST['db_collation'])) {
list($db_charset) = explode('_', $_POST['db_collation']);
$sqlQuery = 'CREATE DATABASE ' . Util::backquote($params['new_db']);
if (! empty($params['db_collation'])) {
list($databaseCharset) = explode('_', $params['db_collation']);
$charsets = Charsets::getMySQLCharsets(
$this->dbi,
$GLOBALS['cfg']['Server']['DisableIS']
$cfg['Server']['DisableIS']
);
$collations = Charsets::getMySQLCollations(
$this->dbi,
$GLOBALS['cfg']['Server']['DisableIS']
$cfg['Server']['DisableIS']
);
if (in_array($db_charset, $charsets)
&& in_array($_POST['db_collation'], $collations[$db_charset])
if (in_array($databaseCharset, $charsets)
&& in_array($params['db_collation'], $collations[$databaseCharset])
) {
$sql_query .= ' DEFAULT'
. Util::getCharsetQueryPart($_POST['db_collation']);
$sqlQuery .= ' DEFAULT'
. Util::getCharsetQueryPart($params['db_collation']);
}
}
$sql_query .= ';';
$sqlQuery .= ';';
$result = $this->dbi->tryQuery($sql_query);
$result = $this->dbi->tryQuery($sqlQuery);
if (! $result) {
// avoid displaying the not-created db name in header or navi panel
$GLOBALS['db'] = '';
$db = '';
$message = Message::rawError($this->dbi->getError());
$json = ['message' => $message];
$this->response->setRequestStatus(false);
$this->response->addJSON('message', $message);
} else {
$GLOBALS['db'] = $_POST['new_db'];
$db = $params['new_db'];
$message = Message::success(__('Database %1$s has been created.'));
$message->addParam($_POST['new_db']);
$this->response->addJSON('message', $message);
$this->response->addJSON(
'sql_query',
Util::getMessage(null, $sql_query, 'success')
);
$message->addParam($params['new_db']);
$this->response->addJSON(
'url_query',
Util::getScriptNameForOption(
$GLOBALS['cfg']['DefaultTabDatabase'],
$json = [
'message' => $message,
'sql_query' => Util::getMessage(null, $sqlQuery, 'success'),
'url_query' => Util::getScriptNameForOption(
$cfg['DefaultTabDatabase'],
'database'
)
. Url::getCommon(['db' => $_POST['new_db']])
);
) . Url::getCommon(['db' => $params['new_db']]),
];
}
return $json;
}
/**
* Handles dropping multiple databases
*
* @return void
* @param array $params Request parameters
*
* @return array JSON
*/
public function dropDatabasesAction()
public function dropDatabasesAction(array $params): array
{
if (! isset($_POST['selected_dbs'])) {
global $submit_mult, $mult_btn, $selected;
if (! isset($params['selected_dbs'])) {
$message = Message::error(__('No databases selected.'));
} else {
$action = 'server_databases.php';
$err_url = $action . Url::getCommon();
$GLOBALS['submit_mult'] = 'drop_db';
$GLOBALS['mult_btn'] = __('Yes');
$submit_mult = 'drop_db';
$mult_btn = __('Yes');
include ROOT_PATH . 'libraries/mult_submits.inc.php';
if (empty($message)) { // no error message
$number_of_databases = count($selected);
$numberOfDatabases = count($selected);
$message = Message::success(
_ngettext(
'%1$d database has been dropped successfully.',
'%1$d databases have been dropped successfully.',
$number_of_databases
$numberOfDatabases
)
);
$message->addParam($number_of_databases);
$message->addParam($numberOfDatabases);
}
}
$json = [];
if ($message instanceof Message) {
$json = ['message' => $message];
$this->response->setRequestStatus($message->isSuccess());
$this->response->addJSON('message', $message);
}
return $json;
}
/**
* Extracts parameters $sort_order and $sort_by
* Extracts parameters sort order and sort by
*
* @param string|null $sortBy sort by
* @param string|null $sortOrder sort order
*
* @return void
*/
private function _setSortDetails()
private function setSortDetails(?string $sortBy, ?string $sortOrder): void
{
if (empty($_REQUEST['sort_by'])) {
$this->_sort_by = 'SCHEMA_NAME';
if (empty($sortBy)) {
$this->sortBy = 'SCHEMA_NAME';
} else {
$sort_by_whitelist = [
$sortByWhitelist = [
'SCHEMA_NAME',
'DEFAULT_COLLATION_NAME',
'SCHEMA_TABLES',
@ -266,262 +263,135 @@ class ServerDatabasesController extends Controller
'SCHEMA_LENGTH',
'SCHEMA_DATA_FREE',
];
if (in_array($_REQUEST['sort_by'], $sort_by_whitelist)) {
$this->_sort_by = $_REQUEST['sort_by'];
} else {
$this->_sort_by = 'SCHEMA_NAME';
$this->sortBy = 'SCHEMA_NAME';
if (in_array($sortBy, $sortByWhitelist)) {
$this->sortBy = $sortBy;
}
}
if (isset($_REQUEST['sort_order'])
&& mb_strtolower($_REQUEST['sort_order']) == 'desc'
$this->sortOrder = 'asc';
if (isset($sortOrder)
&& mb_strtolower($sortOrder) === 'desc'
) {
$this->_sort_order = 'desc';
} else {
$this->_sort_order = 'asc';
$this->sortOrder = 'desc';
}
}
/**
* Returns the html for Database List
* Returns database list
*
* @param array $replication_types replication types
*
* @return string
*/
private function _getHtmlForDatabases(array $replication_types)
{
$first_database = reset($this->_databases);
// table col order
$column_order = $this->_getColumnOrder();
$dbColumnOrders = [];
// calculate aggregate stats to display in footer
foreach ($this->_databases as $current) {
$dbColumnOrders[$current['SCHEMA_NAME']] = $this->_getColumnOrder();
foreach ($column_order as $stat_name => $stat) {
if (array_key_exists($stat_name, $current)
&& is_numeric($stat['footer'])
) {
$column_order[$stat_name]['footer'] += $current[$stat_name];
$dbColumnOrders[$current['SCHEMA_NAME']][$stat_name]['footer'] = $current[$stat_name];
}
}
}
$values = [];
$units = [];
foreach ($column_order as $stat_name => $stat) {
if (array_key_exists($stat_name, $first_database)) {
if ($stat['format'] == 'byte') {
$byte_format = Util::formatByteDown($stat['footer'], 3, 1);
$values[$stat_name] = $byte_format[0];
$units[$stat_name] = $byte_format[1];
} elseif ($stat['format'] == 'number') {
$values[$stat_name] = Util::formatNumber($stat['footer'], 0);
} else {
$values[$stat_name] = htmlentities($stat['footer'], 0);
}
}
}
$_url_params = [
'pos' => $this->_pos,
'dbstats' => $this->_dbstats,
'sort_by' => $this->_sort_by,
'sort_order' => $this->_sort_order,
];
$html = $this->_getHtmlForTableBody($dbColumnOrders, $replication_types);
$html .= $this->template->render('server/databases/databases_footer', [
'column_order' => $column_order,
'first_database' => $first_database,
'master_replication' => $GLOBALS['replication_info']['master']['status'],
'slave_replication' => $GLOBALS['replication_info']['slave']['status'],
'database_count' => $this->_database_count,
'is_superuser' => $this->dbi->isSuperuser(),
'allow_user_drop_database' => $GLOBALS['cfg']['AllowUserDropDatabase'],
'pma_theme_image' => $GLOBALS['pmaThemeImage'],
'text_dir' => $GLOBALS['text_dir'],
'dbstats' => $this->_dbstats,
'values' => $values,
'units' => $units,
]);
return $html;
}
/**
* Prepares the $column_order array
* @param array $replicationTypes replication types
*
* @return array
*/
private function _getColumnOrder()
private function getDatabases(array $replicationTypes): array
{
$column_order = [];
$column_order['DEFAULT_COLLATION_NAME'] = [
'disp_name' => __('Collation'),
'description_function' => [
Charsets::class,
'getCollationDescr',
],
'format' => 'string',
'footer' => '',
];
$column_order['SCHEMA_TABLES'] = [
'disp_name' => __('Tables'),
'format' => 'number',
'footer' => 0,
];
$column_order['SCHEMA_TABLE_ROWS'] = [
'disp_name' => __('Rows'),
'format' => 'number',
'footer' => 0,
];
$column_order['SCHEMA_DATA_LENGTH'] = [
'disp_name' => __('Data'),
'format' => 'byte',
'footer' => 0,
];
$column_order['SCHEMA_INDEX_LENGTH'] = [
'disp_name' => __('Indexes'),
'format' => 'byte',
'footer' => 0,
];
$column_order['SCHEMA_LENGTH'] = [
'disp_name' => __('Total'),
'format' => 'byte',
'footer' => 0,
];
$column_order['SCHEMA_DATA_FREE'] = [
'disp_name' => __('Overhead'),
'format' => 'byte',
'footer' => 0,
];
global $replication_info;
return $column_order;
}
/**
* Returns the html for Database List
*
* @param array $dbColumnOrders databases column order
* @param array $replicationTypes replication types
*
* @return string
*/
private function _getHtmlForTableBody(array $dbColumnOrders, array $replicationTypes)
{
$html = '<tbody>' . "\n";
foreach ($this->_databases as $current) {
$tr_class = ' db-row';
if ($this->dbi->isSystemSchema($current['SCHEMA_NAME'], true)) {
$tr_class .= ' noclick';
}
$generated_html = $this->_buildHtmlForDb(
$current,
$dbColumnOrders[$current['SCHEMA_NAME']],
$replicationTypes,
$GLOBALS['replication_info'],
$tr_class
);
$html .= $generated_html;
} // end foreach ($this->_databases as $key => $current)
$html .= '</tbody>';
return $html;
}
/**
* Builds the HTML for one database to display in the list
* of databases from server_databases.php
*
* @param array $current current database
* @param array $column_order column order
* @param array $replication_types replication types
* @param array $replication_info replication info
* @param string $tr_class HTMl class for the row
*
* @return string
*/
public function _buildHtmlForDb(
array $current,
array $column_order,
array $replication_types,
array $replication_info,
$tr_class = ''
) {
$master_replication = $slave_replication = '';
foreach ($replication_types as $type) {
if ($replication_info[$type]['status']) {
$out = '';
$key = array_search(
$current["SCHEMA_NAME"],
$replication_info[$type]['Ignore_DB']
);
if (strlen((string) $key) > 0) {
$out = Util::getIcon(
's_cancel',
__('Not replicated')
);
} else {
$databases = [];
$totalStatistics = $this->getStatisticsColumns();
foreach ($this->databases as $database) {
$replication = [
'master' => [
'status' => $replication_info['master']['status'],
],
'slave' => [
'status' => $replication_info['slave']['status'],
],
];
foreach ($replicationTypes as $type) {
if ($replication_info[$type]['status']) {
$key = array_search(
$current["SCHEMA_NAME"],
$replication_info[$type]['Do_DB']
$database["SCHEMA_NAME"],
$replication_info[$type]['Ignore_DB']
);
if (strlen((string) $key) > 0
|| count($replication_info[$type]['Do_DB']) == 0
) {
// if ($key != null) did not work for index "0"
$out = Util::getIcon(
's_success',
__('Replicated')
if (strlen((string) $key) > 0) {
$replication[$type]['is_replicated'] = false;
} else {
$key = array_search(
$database["SCHEMA_NAME"],
$replication_info[$type]['Do_DB']
);
if (strlen((string) $key) > 0
|| count($replication_info[$type]['Do_DB']) == 0
) {
// if ($key != null) did not work for index "0"
$replication[$type]['is_replicated'] = true;
}
}
}
}
if ($type == 'master') {
$master_replication = $out;
} elseif ($type == 'slave') {
$slave_replication = $out;
$statistics = $this->getStatisticsColumns();
if ($this->hasStatistics) {
foreach (array_keys($statistics) as $key) {
$statistics[$key]['raw'] = $database[$key] ?? null;
$totalStatistics[$key]['raw'] += (int) $database[$key] ?? 0;
}
}
$databases[] = [
'name' => $database['SCHEMA_NAME'],
'collation' => [
'name' => $database['DEFAULT_COLLATION_NAME'],
'description' => Charsets::getCollationDescr(
$database['DEFAULT_COLLATION_NAME']
),
],
'statistics' => $statistics,
'replication' => $replication,
'is_system_schema' => $this->dbi->isSystemSchema(
$database['SCHEMA_NAME'],
true
),
];
}
$values = [];
$units = [];
foreach ($column_order as $stat_name => $stat) {
if (array_key_exists($stat_name, $current)) {
if ($stat['format'] == 'byte') {
$byte_format = Util::formatByteDown($stat['footer'], 3, 1);
$values[$stat_name] = $byte_format[0];
$units[$stat_name] = $byte_format[1];
} elseif ($stat['format'] == 'number') {
$values[$stat_name] = Util::formatNumber($stat['footer'], 0);
} else {
$values[$stat_name] = htmlentities($stat['footer'], 0);
}
}
}
return [
'databases' => $databases,
'total_statistics' => $totalStatistics,
];
}
return $this->template->render('server/databases/table_row', [
'current' => $current,
'tr_class' => $tr_class,
'column_order' => $column_order,
'master_replication_status' => $GLOBALS['replication_info']['master']['status'],
'master_replication' => $master_replication,
'slave_replication_status' => $GLOBALS['replication_info']['slave']['status'],
'slave_replication' => $slave_replication,
'is_superuser' => $this->dbi->isSuperuser(),
'allow_user_drop_database' => $GLOBALS['cfg']['AllowUserDropDatabase'],
'is_system_schema' => $this->dbi->isSystemSchema($current['SCHEMA_NAME'], true),
'default_tab_database' => $GLOBALS['cfg']['DefaultTabDatabase'],
'values' => $values,
'units' => $units,
]);
/**
* Prepares the statistics columns
*
* @return array
*/
private function getStatisticsColumns(): array
{
return [
'SCHEMA_TABLES' => [
'title' => __('Tables'),
'format' => 'number',
'raw' => 0,
],
'SCHEMA_TABLE_ROWS' => [
'title' => __('Rows'),
'format' => 'number',
'raw' => 0,
],
'SCHEMA_DATA_LENGTH' => [
'title' => __('Data'),
'format' => 'byte',
'raw' => 0,
],
'SCHEMA_INDEX_LENGTH' => [
'title' => __('Indexes'),
'format' => 'byte',
'raw' => 0,
],
'SCHEMA_LENGTH' => [
'title' => __('Total'),
'format' => 'byte',
'raw' => 0,
],
'SCHEMA_DATA_FREE' => [
'title' => __('Overhead'),
'format' => 'byte',
'raw' => 0,
],
];
}
}

View File

@ -24,7 +24,6 @@ parameters:
- '#GisGeomTestCase::\$object#'
- '#Undefined variable: \$array#'
- '#Undefined variable: \$(cfg|db|table|url_query|text_dir|server|pmaThemeImage|action|sql_query|lang|export_type|err_url|collation_connection|filename_template|transform_key|cn|goto|partitionDetails|token_mismatch|auth_plugin|username|hostname|display_query|where_clause)#'#Others
- '#Undefined variable: \$(replication_types|selected)#'#Controllers/Server/ServerDatabasesController.php
- '#Undefined variable: \$(dir|error_header|error_message)#'#error.inc.php
- '#Undefined variable: \$_PMA_RTE#'#rte/rte_main.inc.php
- '#Undefined variable: \$(unsaved_values|is_upload)#'#tbl_change.php
@ -40,7 +39,6 @@ parameters:
- '#Variable \$time might not be defined#'#DatabaseInterface.php
- '#Variable \$contentPath in isset\(\) always exists and is not nullable#'#DatabaseInterface.php
- '#Variable \$server_info might not be defined#'#DatabaseInterface.php
# - '#Variable \$single_table always exists and is not nullable#'#Display/ExportTest.php
- '#Function mysqli_get_client_info invoked with 0 parameters, 1 required#'#libraries/classes/Dbi/DbiMysqli.php
- '#Variable \$default_fk_check_value might not be defined#'#libraries/mult_submits.inc.php
- '#Variable \$http_response_header in isset\(\) always exists and is not nullable#'

View File

@ -7,6 +7,7 @@
*/
declare(strict_types=1);
use PhpMyAdmin\CheckUserPrivileges;
use PhpMyAdmin\Controllers\Server\ServerDatabasesController;
use PhpMyAdmin\Di\Container;
use PhpMyAdmin\Response;
@ -33,4 +34,37 @@ $controller = $container->get(
'ServerDatabasesController',
[]
);
$controller->indexAction();
/** @var Response $response */
$response = $container->get('response');
$checkUserPrivileges = new CheckUserPrivileges($GLOBALS['dbi']);
$checkUserPrivileges->getPrivileges();
if (isset($_POST['drop_selected_dbs'])
&& $response->isAjax()
&& ($GLOBALS['dbi']->isSuperuser() || $GLOBALS['cfg']['AllowUserDropDatabase'])
) {
$response->addJSON($controller->dropDatabasesAction([
'drop_selected_dbs' => $_POST['drop_selected_dbs'],
'selected_dbs' => $_POST['selected_dbs'] ?? null,
]));
} elseif (isset($_POST['new_db'])
&& $response->isAjax()
) {
$response->addJSON($controller->createDatabaseAction([
'new_db' => $_POST['new_db'],
'db_collation' => $_POST['db_collation'] ?? null,
]));
} else {
$header = $response->getHeader();
$scripts = $header->getScripts();
$scripts->addFile('server_databases.js');
$response->addHTML($controller->indexAction([
'statistics' => $_REQUEST['statistics'] ?? null,
'pos' => $_REQUEST['pos'] ?? null,
'sort_by' => $_REQUEST['sort_by'] ?? null,
'sort_order' => $_REQUEST['sort_order'] ?? null,
]));
}

View File

@ -1,71 +0,0 @@
<tfoot>
<tr>
{% if is_superuser or allow_user_drop_database %}
<th></th>
{% endif %}
<th>
{% trans 'Total' %}: <span id="filter-rows-count">
{{- database_count -}}
</span>
</th>
{% for stat_name, stat in column_order if stat_name in first_database|keys %}
<th class="value">
{% if stat['description_function'] is defined %}
<dfn title="{{ get_collation_descr(stat['footer']) }}">
{{ values[stat_name] }}
</dfn>
{% else %}
{{ values[stat_name] }}
{% endif %}
</th>
{% if stat['format'] is same as('byte') %}
<th class="unit">{{ units[stat_name] }}</th>
{% endif %}
{% endfor %}
{% if master_replication %}
<th></th>
{% endif %}
{% if slave_replication %}
<th></th>
{% endif %}
<th></th>
</tr>
</tfoot>
</table>
</div>
{# Footer buttons #}
{% if is_superuser or allow_user_drop_database %}
{% include 'select_all.twig' with {
'pma_theme_image': pma_theme_image,
'text_dir': text_dir,
'form_name': 'dbStatsForm'
} only %}
{{ get_button_or_image(
'',
'mult_submit ajax',
'Drop'|trans,
'b_deltbl'
) }}
{% endif %}
{# Enable statistics #}
{% if dbstats is empty %}
{{ 'Note: Enabling the database statistics here might cause heavy traffic between the web server and the MySQL server.'|trans|notice }}
{% set content %}
<strong>{% trans 'Enable statistics' %}</strong>
{% endset %}
{% set items = [{
'content': content,
'class': 'li_switch_dbstats',
'url': {
'href': 'server_databases.php' ~ get_common({'dbstats': '1'}),
'title': 'Enable statistics'|trans
}
}] %}
{% include 'list/unordered.twig' with {'items': items} only %}
{% endif %}
</form>
</div>

View File

@ -1,123 +1,317 @@
{# Displays the sub-page heading #}
{% include 'server/sub_page_header.twig' with {
'type': dbstats ? 'database_statistics' : 'databases'
} only %}
<h2>
{{ get_image('s_db') }}
{% if has_statistics %}
{% trans 'Databases statistics' %}
{% else %}
{% trans 'Databases' %}
{% endif %}
</h2>
{# Displays For Create database #}
{% if show_create_db %}
<ul>
<li id="li_create_database" class="no_bullets">
{% if is_create_db_priv %}
<form method="post" action="server_databases.php" id="create_database_form" class="ajax">
<p><strong>
<label for="text_create_db">
{{ get_image('b_newdb') }}
{% trans 'Create database' %}
</label>
{{ show_mysql_docu('CREATE_DATABASE') }}
</strong></p>
{% if is_create_database_shown %}
<ul>
<li id="li_create_database" class="no_bullets">
{% if has_create_database_privileges %}
<form method="post" action="server_databases.php" id="create_database_form" class="ajax">
<p>
<strong>
<label for="text_create_db">
{{ get_image('b_newdb') }}
{% trans 'Create database' %}
</label>
{{ show_mysql_docu('CREATE_DATABASE') }}
</strong>
</p>
{{ get_hidden_inputs('', '', 5) }}
<input type="hidden" name="reload" value="1">
{% if dbstats is not empty %}
<input type="hidden" name="dbstats" value="1">
{{ get_hidden_inputs('', '', 5) }}
<input type="hidden" name="reload" value="1">
{% if has_statistics %}
<input type="hidden" name="statistics" value="1">
{% endif %}
<input type="text" name="new_db" maxlength="64" class="textfield" value="
{{- database_to_create }}" id="text_create_db" placeholder="
{%- trans 'Database name' %}" required>
{{ collation_dropdown_box|raw }}
<input id="buttonGo" class="btn btn-primary" type="submit" value="{% trans 'Create' %}">
</form>
{% else %}
<p>
<strong>
{{ get_image('b_newdb') }}
{% trans 'Create database' %}
{{ show_mysql_docu('CREATE_DATABASE') }}
</strong>
</p>
<span class="noPrivileges">
{{ get_image('s_error', '', {
'hspace': 2,
'border': 0,
'align': 'middle'
}) }}
{% trans 'No privileges to create databases' %}
</span>
{% endif %}
</li>
</ul>
{% endif %}
{% if database_count > 0 %}
{% include 'filter.twig' with {'filter_value': ''} only %}
<div id="tableslistcontainer">
{{ get_list_navigator(
database_count,
pos,
url_params,
'server_databases.php',
'frame_content',
max_db_list
) }}
<form class="ajax" action="server_databases.php" method="post" name="dbStatsForm" id="dbStatsForm">
{{ get_hidden_inputs(url_params) }}
<div class="responsivetable">
<table id="tabledatabases" class="data">
<thead>
<tr>
{% if is_drop_allowed %}
<th></th>
{% endif %}
<th>
<a href="server_databases.php{{ get_common(url_params|merge({
'sort_by': 'SCHEMA_NAME',
'sort_order': url_params.sort_by == 'SCHEMA_NAME'
and url_params.sort_order == 'asc' ? 'desc' : 'asc'
})) }}">
{% trans 'Database' %}
{% if url_params.sort_by == 'SCHEMA_NAME' %}
{% if url_params.sort_order == 'asc' %}
{{ get_image('s_asc', 'Ascending'|trans) }}
{% else %}
{{ get_image('s_desc', 'Descending'|trans) }}
{% endif %}
{% endif %}
</a>
</th>
<input type="text" name="new_db" value="{{ db_to_create }}"
maxlength="64" class="textfield" id="text_create_db" required
placeholder="{% trans 'Database name' %}">
{{ get_collation_dropdown_box(
dbi,
disable_is,
'db_collation',
null,
server_collation,
true
) }}
<input id="buttonGo" class="btn btn-primary" type="submit" value="{% trans 'Create' %}">
</form>
{% else %}
{# db creation no privileges message #}
<p><strong>
{{ get_image('b_newdb') }}
{% trans 'Create database' %}
{{ show_mysql_docu('CREATE_DATABASE') }}
</strong></p>
<th>
<a href="server_databases.php{{ get_common(url_params|merge({
'sort_by': 'DEFAULT_COLLATION_NAME',
'sort_order': url_params.sort_by == 'DEFAULT_COLLATION_NAME'
and url_params.sort_order == 'asc' ? 'desc' : 'asc'
})) }}">
{% trans 'Collation' %}
{% if url_params.sort_by == 'DEFAULT_COLLATION_NAME' %}
{% if url_params.sort_order == 'asc' %}
{{ get_image('s_asc', 'Ascending'|trans) }}
{% else %}
{{ get_image('s_desc', 'Descending'|trans) }}
{% endif %}
{% endif %}
</a>
</th>
<span class="noPrivileges">
{{ get_image(
's_error',
'',
{'hspace': 2, 'border': 0, 'align': 'middle'}
) }}
{% trans 'No Privileges' %}
{% if has_statistics %}
{% for name, statistic in header_statistics %}
<th{{ statistic.format == 'byte' ? ' colspan="2"' }}>
<a href="server_databases.php{{ get_common(url_params|merge({
'sort_by': name,
'sort_order': url_params.sort_by == name
and url_params.sort_order == 'asc' ? 'desc' : 'asc'
})) }}">
{{ statistic.title }}
{% if url_params.sort_by == name %}
{% if url_params.sort_order == 'asc' %}
{{ get_image('s_asc', 'Ascending'|trans) }}
{% else %}
{{ get_image('s_desc', 'Descending'|trans) }}
{% endif %}
{% endif %}
</a>
</th>
{% endfor %}
{% endif %}
{% if has_master_replication %}
<th>{% trans 'Master replication' %}</th>
{% endif %}
{% if has_slave_replication %}
<th>{% trans 'Slave replication' %}</th>
{% endif %}
<th>{% trans 'Action' %}</th>
</tr>
</thead>
<tbody>
{% for database in databases %}
<tr class="db-row{{ database.is_system_schema ? ' noclick' }}" data-filter-row="{{ database.name|upper }}">
{% if is_drop_allowed %}
<td class="tool">
<input type="checkbox" name="selected_dbs[]" class="checkall" title="
{{- database.name }}" value="
{{- database.name }}"
{{- database.is_system_schema ? ' disabled' }}>
</td>
{% endif %}
<td class="name">
<a href="{{ get_script_name_for_option(default_tab_database, 'database') }}
{{- get_common({'db': database.name}) }}" title="
{{- "Jump to database '%s'"|trans|format(database.name) }}">
{{ database.name }}
</a>
</td>
<td class="value">
<dfn title="{{ database.collation.description }}">
{{ database.collation.name }}
</dfn>
</td>
{% if has_statistics %}
{% for statistic in database.statistics %}
{% if statistic.format is same as('byte') %}
{% set value = format_byte_down(statistic.raw, 3, 1) %}
<td class="value">
<data value="{{ statistic.raw }}" title="{{ statistic.raw }}">
{{ value[0] }}
</data>
</td>
<td class="unit">{{ value[1] }}</td>
{% else %}
<td class="value">
<data value="{{ statistic.raw }}" title="{{ statistic.raw }}">
{{ format_number(statistic.raw, 0) }}
</data>
</td>
{% endif %}
{% endfor %}
{% endif %}
{% if database.replication.master.status %}
{% if database.replication.master.is_replicated %}
<td class="tool center">
{{ get_icon('s_success', 'Replicated'|trans) }}
</td>
{% else %}
<td class="tool center">
{{ get_icon('s_cancel', 'Not replicated'|trans) }}
</td>
{% endif %}
{% endif %}
{% if database.replication.slave.status %}
{% if database.replication.slave.is_replicated %}
<td class="tool center">
{{ get_icon('s_success', 'Replicated'|trans) }}
</td>
{% else %}
<td class="tool center">
{{ get_icon('s_cancel', 'Not replicated'|trans) }}
</td>
{% endif %}
{% endif %}
<td class="tool">
<a class="server_databases" data="
{{- database.name|js_format }}" href="server_privileges.php
{{- get_common({
'db': database.name,
'checkprivsdb': database.name
}) }}" title="
{{- 'Check privileges for database "%s".'|trans|format(database.name) }}">
{{ get_icon('s_rights', 'Check privileges'|trans) }}
</a>
</td>
</tr>
{% endfor %}
</tbody>
<tfoot>
<tr>
<th colspan="{{ is_drop_allowed ? '3' : '2' }}">
{% trans 'Total:' %}
<span id="filter-rows-count">
{% trans %}
{{ count }} database
{% plural database_count %}
{{ count }} databases
{% endtrans %}
</span>
{% endif %}
</li>
</ul>
{% endif %}
</th>
{% include 'filter.twig' with {'filter_value': ''} only %}
{% if has_statistics %}
{% for statistic in total_statistics %}
{% if statistic.format is same as('byte') %}
{% set value = format_byte_down(statistic.raw, 3, 1) %}
<th class="value">
<data value="{{ statistic.raw }}" title="{{ statistic.raw }}">
{{ value[0] }}
</data>
</th>
<th class="unit">{{ value[1] }}</th>
{% else %}
<th class="value">
<data value="{{ statistic.raw }}" title="{{ statistic.raw }}">
{{ format_number(statistic.raw, 0) }}
</data>
</th>
{% endif %}
{% endfor %}
{% endif %}
{# Displays the table #}
{% if databases is not null %}
<div id="tableslistcontainer">
{{ get_list_navigator(
database_count,
pos,
url_params,
'server_databases.php',
'frame_content',
max_db_list
{% if has_master_replication %}
<th></th>
{% endif %}
{% if has_slave_replication %}
<th></th>
{% endif %}
<th></th>
</tr>
</tfoot>
</table>
</div>
{# Footer buttons #}
{% if is_drop_allowed %}
{% include 'select_all.twig' with {
'pma_theme_image': pma_theme_image,
'text_dir': text_dir,
'form_name': 'dbStatsForm'
} only %}
{{ get_button_or_image(
'',
'mult_submit ajax',
'Drop'|trans,
'b_deltbl'
) }}
<form class="ajax" action="server_databases.php" method="post" name="dbStatsForm" id="dbStatsForm">
{{ get_hidden_inputs(url_params) }}
{% set url_params = url_params|merge({
'sort_by': 'SCHEMA_NAME',
'sort_order': sort_by == 'SCHEMA_NAME' and sort_order == 'asc' ? 'desc' : 'asc'
}) %}
<div class="responsivetable">
<table id="tabledatabases" class="data">
<thead>
<tr>
{% if is_superuser or allow_user_drop_database %}
<th></th>
{% endif %}
<th>
<a href="server_databases.php{{ get_common(url_params) }}">
{% trans 'Database' %}
{{ sort_by == 'SCHEMA_NAME' ? get_image(
's_' ~ sort_order,
sort_order == 'asc' ? 'Ascending'|trans : 'Descending'|trans
) }}
</a>
</th>
{% for stat_name, stat in column_order if stat_name in first_database|keys %}
{% set url_params = url_params|merge({
'sort_by': stat_name,
'sort_order': sort_by == stat_name and sort_order == 'desc' ? 'asc' : 'desc'
}) %}
{% endif %}
<th{{ stat['format'] is same as('byte') ? ' colspan="2"' }}>
<a href="server_databases.php{{ get_common(url_params) }}">
{{ stat['disp_name'] }}
{{ sort_by == stat_name ? get_image(
's_' ~ sort_order,
sort_order == 'asc' ? 'Ascending'|trans : 'Descending'|trans
) }}
</a>
</th>
{% endfor %}
{% if master_replication %}
<th>{% trans 'Master replication' %}</th>
{% endif %}
{% if slave_replication %}
<th>{% trans 'Slave replication' %}</th>
{% endif %}
<th>{% trans 'Action' %}</th>
</tr>
</thead>
{{ databases|raw }}
{# Enable statistics #}
{% if not has_statistics %}
{{ 'Note: Enabling the database statistics here might cause heavy traffic between the web server and the MySQL server.'|trans|notice }}
{% set content %}
<strong>{% trans 'Enable statistics' %}</strong>
{% endset %}
{% set items = [{
'content': content,
'class': 'li_switch_dbstats',
'url': {
'href': 'server_databases.php' ~ get_common({'statistics': '1'}),
'title': 'Enable statistics'|trans
}
}] %}
{% include 'list/unordered.twig' with {'items': items} only %}
{% endif %}
</form>
</div>
{% else %}
<p>{% trans 'No databases' %}</p>
<p>{{ 'No databases'|trans|notice }}</p>
{% endif %}

View File

@ -1,55 +0,0 @@
<tr{% if tr_class %} class="{{ tr_class }}"{% endif %} data-filter-row="{{ current['SCHEMA_NAME']|upper }}">
{% if is_superuser or allow_user_drop_database %}
<td class="tool">
<input type="checkbox" name="selected_dbs[]" class="checkall" title="
{{- current['SCHEMA_NAME'] }}" value="
{{- current['SCHEMA_NAME'] }}"
{%- if is_system_schema %} disabled="disabled"{% endif %}>
</td>
{% endif %}
<td class="name">
<a href="{{ get_script_name_for_option(default_tab_database, 'database') }}
{{- get_common({'db': current['SCHEMA_NAME']}) }}" title="
{{- "Jump to database '%s'"|trans|format(current['SCHEMA_NAME']|e) }}">
{{ current['SCHEMA_NAME'] }}
</a>
</td>
{% for stat_name, stat in column_order if stat_name in current|keys %}
<td class="value">
{% if stat['description_function'] is defined %}
<dfn title="{{ get_collation_descr(current[stat_name]) }}">
{{ current[stat_name] }}
</dfn>
{% else %}
{{ current[stat_name] }}
{% endif %}
</td>
{% if stat['format'] is same as('byte') %}
<td class="unit">{{ units[stat_name] }}</td>
{% endif %}
{% endfor %}
{% if master_replication_status %}
<td class="tool center">
{{ master_replication|raw }}
</td>
{% endif %}
{% if slave_replication_status %}
<td class="tool center">
{{ slave_replication|raw }}
</td>
{% endif %}
<td class="tool">
<a class="server_databases" data="
{{- current['SCHEMA_NAME']|js_format }}" href="server_privileges.php
{{- get_common({
'db': current['SCHEMA_NAME'],
'checkprivsdb': current['SCHEMA_NAME']
}) }}" title="
{{- 'Check privileges for database "%s".'|trans|format(current['SCHEMA_NAME']|e) }}">
{{ get_icon('s_rights', 'Check privileges'|trans) }}
</a>
</td>
</tr>

View File

@ -24,14 +24,6 @@
'image': 's_replication',
'text': 'Replication'|trans
},
'database_statistics': {
'image': 's_db',
'text': 'Databases statistics'|trans
},
'databases': {
'image': 's_db',
'text': 'Databases'|trans
},
'privileges': {
'image': 'b_usrlist',
'text': 'Privileges'|trans

View File

@ -9,301 +9,192 @@ declare(strict_types=1);
namespace PhpMyAdmin\Tests\Controllers\Server;
use PhpMyAdmin\Charsets;
use PhpMyAdmin\Config;
use PhpMyAdmin\Di\Container;
use PhpMyAdmin\Tests\PmaTestCase;
use PhpMyAdmin\Tests\Stubs\Response as ResponseStub;
use ReflectionClass;
use PhpMyAdmin\Controllers\Server\ServerDatabasesController;
use PhpMyAdmin\DatabaseInterface;
use PhpMyAdmin\Message;
use PhpMyAdmin\Response;
use PHPUnit\Framework\TestCase;
/**
* Tests for ServerDatabasesController class
*
* @package PhpMyAdmin-test
*/
class ServerDatabasesControllerTest extends PmaTestCase
class ServerDatabasesControllerTest extends TestCase
{
/**
* Prepares environment for the test.
*
* @return void
*/
protected function setUp()
protected function setUp(): void
{
//$_REQUEST
$_REQUEST['log'] = "index1";
$_REQUEST['pos'] = 3;
//$GLOBALS
$GLOBALS['PMA_Config'] = new Config();
$GLOBALS['PMA_Config']->enableBc();
$GLOBALS['db'] = 'db';
$GLOBALS['table'] = "table";
$GLOBALS['replication_info']['master']['status'] = false;
$GLOBALS['replication_info']['slave']['status'] = false;
$GLOBALS['pmaThemeImage'] = 'image';
$GLOBALS['text_dir'] = "text_dir";
$GLOBALS['server'] = 1;
$GLOBALS['db'] = 'pma_test';
$GLOBALS['table'] = '';
$GLOBALS['PMA_PHP_SELF'] = 'index.php';
$GLOBALS['cfg']['Server']['DisableIS'] = false;
//$_SESSION
$GLOBALS['server'] = 1;
$container = Container::getDefaultContainer();
$container->set('dbi', $GLOBALS['dbi']);
$response = new ResponseStub();
$container->set('PhpMyAdmin\Response', $response);
$container->alias('response', 'PhpMyAdmin\Response');
$GLOBALS['pmaThemeImage'] = 'image';
$GLOBALS['text_dir'] = "text_dir";
}
/**
* Tests for _getHtmlForDatabases
*
* @return void
* @group medium
*/
public function testGetHtmlForDatabase()
public function testIndexAction(): void
{
$class = new ReflectionClass('\PhpMyAdmin\Controllers\Server\ServerDatabasesController');
$method = $class->getMethod('_getHtmlForDatabases');
$method->setAccessible(true);
global $cfg, $dblist, $is_create_db_priv;
$container = Container::getDefaultContainer();
$container->factory('PhpMyAdmin\Controllers\Server\ServerDatabasesController');
$container->alias(
'ServerDatabasesController',
'PhpMyAdmin\Controllers\Server\ServerDatabasesController'
);
$ctrl = $container->get('ServerDatabasesController');
//Call the test function
$databases = [
["SCHEMA_NAME" => "pma_bookmark"],
["SCHEMA_NAME" => "information_schema"],
["SCHEMA_NAME" => "mysql"],
["SCHEMA_NAME" => "performance_schema"],
["SCHEMA_NAME" => "phpmyadmin"],
];
$property = $class->getProperty('_databases');
$property->setAccessible(true);
$property->setValue($ctrl, $databases);
$property = $class->getProperty('_database_count');
$property->setAccessible(true);
$property->setValue($ctrl, 5);
$property = $class->getProperty('_pos');
$property->setAccessible(true);
$property->setValue($ctrl, 0);
$property = $class->getProperty('_dbstats');
$property->setAccessible(true);
$property->setValue($ctrl, false);
$property = $class->getProperty('_sort_by');
$property->setAccessible(true);
$property->setValue($ctrl, 'SCHEMA_NAME');
$property = $class->getProperty('_sort_order');
$property->setAccessible(true);
$property->setValue($ctrl, 'asc');
$replication_types = [
"master",
"slave",
];
$html = $method->invoke($ctrl, $replication_types);
//validate 3: PMA_getHtmlForColumnOrderWithSort
$this->assertContains(
'<a href="server_databases.php',
$html
);
//validate 4: PMA_getHtmlAndColumnOrderForDatabaseList
$this->assertRegExp(
'/title="pma_bookmark"[[:space:]]*value="pma_bookmark"/',
$html
);
$this->assertRegExp(
'/title="information_schema"[[:space:]]*value="information_schema"/',
$html
);
$this->assertRegExp(
'/title="performance_schema"[[:space:]]*value="performance_schema"/',
$html
);
$this->assertRegExp(
'/title="phpmyadmin"[[:space:]]*value="phpmyadmin"/',
$html
);
//validate 5: table footer
$this->assertContains(
'Total: <span id="filter-rows-count">5</span>',
$html
);
//validate 6: footer buttons
$this->assertContains(
'Check all',
$html
);
//validate 7: enable statistics
$this->assertContains(
'Note: Enabling the database statistics here might cause heavy traffic',
$html
);
$this->assertContains(
'Enable statistics',
$html
);
}
/**
* Tests for _setSortDetails()
*
* @return void
*/
public function testSetSortDetails()
{
$class = new ReflectionClass('\PhpMyAdmin\Controllers\Server\ServerDatabasesController');
$method = $class->getMethod('_setSortDetails');
$method->setAccessible(true);
$propertySortBy = $class->getProperty('_sort_by');
$propertySortBy->setAccessible(true);
$propertySortOrder = $class->getProperty('_sort_order');
$propertySortOrder->setAccessible(true);
$container = Container::getDefaultContainer();
$container->factory('PhpMyAdmin\Controllers\Server\ServerDatabasesController');
$container->alias(
'ServerDatabasesController',
'PhpMyAdmin\Controllers\Server\ServerDatabasesController'
);
$ctrl = $container->get('ServerDatabasesController');
//$_REQUEST['sort_by'] and $_REQUEST['sort_order'] are empty
$method->invoke($ctrl, ["master", "slave"]);
$this->assertEquals(
'SCHEMA_NAME',
$propertySortBy->getValue($ctrl)
);
$this->assertEquals(
'asc',
$propertySortOrder->getValue($ctrl)
);
$container = Container::getDefaultContainer();
$container->factory('PhpMyAdmin\Controllers\Server\ServerDatabasesController');
$container->alias(
'ServerDatabasesController',
'PhpMyAdmin\Controllers\Server\ServerDatabasesController'
);
$ctrl = $container->get('ServerDatabasesController');
// $_REQUEST['sort_by'] = 'DEFAULT_COLLATION_NAME'
// and $_REQUEST['sort_order'] is not 'desc'
$_REQUEST['sort_by'] = 'DEFAULT_COLLATION_NAME';
$_REQUEST['sort_order'] = 'abc';
$method->invoke($ctrl);
$this->assertEquals(
'DEFAULT_COLLATION_NAME',
$propertySortBy->getValue($ctrl)
);
$this->assertEquals(
'asc',
$propertySortOrder->getValue($ctrl)
);
$container = Container::getDefaultContainer();
$container->factory('PhpMyAdmin\Controllers\Server\ServerDatabasesController');
$container->alias(
'ServerDatabasesController',
'PhpMyAdmin\Controllers\Server\ServerDatabasesController'
);
$ctrl = $container->get('ServerDatabasesController');
// $_REQUEST['sort_by'] = 'DEFAULT_COLLATION_NAME'
// and $_REQUEST['sort_order'] is 'desc'
$_REQUEST['sort_by'] = 'DEFAULT_COLLATION_NAME';
$_REQUEST['sort_order'] = 'desc';
$method->invoke($ctrl);
$this->assertEquals(
'DEFAULT_COLLATION_NAME',
$propertySortBy->getValue($ctrl)
);
$this->assertEquals(
'desc',
$propertySortOrder->getValue($ctrl)
);
}
/**
* Tests for _getColumnOrder()
*
* @return void
*/
public function testGetColumnOrder()
{
$class = new ReflectionClass('\PhpMyAdmin\Controllers\Server\ServerDatabasesController');
$method = $class->getMethod('_getColumnOrder');
$method->setAccessible(true);
$container = Container::getDefaultContainer();
$container->factory('PhpMyAdmin\Controllers\Server\ServerDatabasesController');
$container->alias(
'ServerDatabasesController',
'PhpMyAdmin\Controllers\Server\ServerDatabasesController'
);
$ctrl = $container->get('ServerDatabasesController');
$this->assertEquals(
[
'DEFAULT_COLLATION_NAME' => [
'disp_name' => __('Collation'),
'description_function' => [
Charsets::class,
'getCollationDescr',
],
'format' => 'string',
'footer' => ''
],
'SCHEMA_TABLES' => [
'disp_name' => __('Tables'),
'format' => 'number',
'footer' => 0,
],
'SCHEMA_TABLE_ROWS' => [
'disp_name' => __('Rows'),
'format' => 'number',
'footer' => 0,
],
'SCHEMA_DATA_LENGTH' => [
'disp_name' => __('Data'),
'format' => 'byte',
'footer' => 0,
],
'SCHEMA_INDEX_LENGTH' => [
'disp_name' => __('Indexes'),
'format' => 'byte',
'footer' => 0,
],
'SCHEMA_LENGTH' => [
'disp_name' => __('Total'),
'format' => 'byte',
'footer' => 0,
],
'SCHEMA_DATA_FREE' => [
'disp_name' => __('Overhead'),
'format' => 'byte',
'footer' => 0,
]
'DEFAULT_COLLATION_NAME' => 'utf8_general_ci',
'SCHEMA_TABLES' => '23',
'SCHEMA_TABLE_ROWS' => '47274',
'SCHEMA_DATA_LENGTH' => '4358144',
'SCHEMA_INDEX_LENGTH' => '2392064',
'SCHEMA_LENGTH' => '6750208',
'SCHEMA_DATA_FREE' => '0',
'SCHEMA_NAME' => 'sakila',
],
$method->invoke($ctrl)
[
'DEFAULT_COLLATION_NAME' => 'utf8mb4_general_ci',
'SCHEMA_TABLES' => '8',
'SCHEMA_TABLE_ROWS' => '3912174',
'SCHEMA_DATA_LENGTH' => '148111360',
'SCHEMA_INDEX_LENGTH' => '5816320',
'SCHEMA_LENGTH' => '153927680',
'SCHEMA_DATA_FREE' => '0',
'SCHEMA_NAME' => 'employees',
],
];
$dblist = new \stdClass();
$dblist->databases = $databases;
$dbi = $this->getMockBuilder(DatabaseInterface::class)
->disableOriginalConstructor()
->getMock();
$dbi->method('getDatabasesFull')
->willReturn($databases);
$controller = new ServerDatabasesController(
Response::getInstance(),
$dbi
);
$actual = $controller->indexAction([
'statistics' => null,
'pos' => null,
'sort_by' => null,
'sort_order' => null,
]);
$this->assertContains('data-filter-row="SAKILA"', $actual);
$this->assertContains('sakila', $actual);
$this->assertContains('utf8_general_ci', $actual);
$this->assertContains('title="Unicode, case-insensitive"', $actual);
$this->assertContains('data-filter-row="SAKILA"', $actual);
$this->assertContains('sakila', $actual);
$this->assertContains('utf8mb4_general_ci', $actual);
$this->assertContains('title="Unicode (UCA 4.0.0), case-insensitive"', $actual);
$this->assertContains('2 databases', $actual);
$this->assertContains('name="pos" value="0"', $actual);
$this->assertContains('name="sort_by" value="SCHEMA_NAME"', $actual);
$this->assertContains('name="sort_order" value="asc"', $actual);
$this->assertContains(__('Enable statistics'), $actual);
$this->assertContains(__('No privileges to create databases'), $actual);
$this->assertNotContains(__('Indexes'), $actual);
$cfg['ShowCreateDb'] = true;
$is_create_db_priv = true;
$actual = $controller->indexAction([
'statistics' => '1',
'pos' => null,
'sort_by' => 'SCHEMA_TABLES',
'sort_order' => 'desc',
]);
$this->assertNotContains(__('Enable statistics'), $actual);
$this->assertContains(__('Indexes'), $actual);
$this->assertContains('name="sort_by" value="SCHEMA_TABLES"', $actual);
$this->assertContains('name="sort_order" value="desc"', $actual);
$this->assertContains('name="statistics" value="1"', $actual);
$this->assertContains('title="3912174"', $actual);
$this->assertContains('3,912,174', $actual);
$this->assertContains('title="4358144"', $actual);
$this->assertContains('4.2', $actual);
$this->assertContains('MiB', $actual);
$this->assertContains('name="db_collation"', $actual);
}
/**
* @return void
*/
public function testCreateDatabaseAction()
{
$dbi = $this->getMockBuilder(DatabaseInterface::class)
->disableOriginalConstructor()
->getMock();
$dbi->method('getError')
->willReturn('CreateDatabaseError');
$controller = new ServerDatabasesController(
Response::getInstance(),
$dbi
);
$actual = $controller->createDatabaseAction([
'new_db' => 'pma_test',
'db_collation' => null,
]);
$this->assertArrayHasKey('message', $actual);
$this->assertInstanceOf(Message::class, $actual['message']);
$this->assertContains('<div class="error">', $actual['message']->getDisplay());
$this->assertContains('CreateDatabaseError', $actual['message']->getDisplay());
$dbi->method('tryQuery')
->willReturn(true);
$actual = $controller->createDatabaseAction([
'new_db' => 'pma_test',
'db_collation' => 'utf8_general_ci',
]);
$this->assertArrayHasKey('message', $actual);
$this->assertInstanceOf(Message::class, $actual['message']);
$this->assertContains('<div class="success">', $actual['message']->getDisplay());
$this->assertContains(
sprintf(__('Database %1$s has been created.'), 'pma_test'),
$actual['message']->getDisplay()
);
}
/**
* @return void
*/
public function testDropDatabasesAction()
{
$dbi = $this->getMockBuilder(DatabaseInterface::class)
->disableOriginalConstructor()
->getMock();
$controller = new ServerDatabasesController(
Response::getInstance(),
$dbi
);
$actual = $controller->dropDatabasesAction([
'drop_selected_dbs' => true,
'selected_dbs' => null,
]);
$this->assertArrayHasKey('message', $actual);
$this->assertInstanceOf(Message::class, $actual['message']);
$this->assertContains('<div class="error">', $actual['message']->getDisplay());
$this->assertContains(__('No databases selected.'), $actual['message']->getDisplay());
}
}