aboutsummaryrefslogtreecommitdiff
path: root/srcs/phpmyadmin/libraries/classes/Controllers/Server
diff options
context:
space:
mode:
Diffstat (limited to 'srcs/phpmyadmin/libraries/classes/Controllers/Server')
-rw-r--r--srcs/phpmyadmin/libraries/classes/Controllers/Server/BinlogController.php149
-rw-r--r--srcs/phpmyadmin/libraries/classes/Controllers/Server/CollationsController.php100
-rw-r--r--srcs/phpmyadmin/libraries/classes/Controllers/Server/DatabasesController.php424
-rw-r--r--srcs/phpmyadmin/libraries/classes/Controllers/Server/EnginesController.php69
-rw-r--r--srcs/phpmyadmin/libraries/classes/Controllers/Server/PluginsController.php77
-rw-r--r--srcs/phpmyadmin/libraries/classes/Controllers/Server/ReplicationController.php72
-rw-r--r--srcs/phpmyadmin/libraries/classes/Controllers/Server/SqlController.php34
-rw-r--r--srcs/phpmyadmin/libraries/classes/Controllers/Server/Status/AbstractController.php42
-rw-r--r--srcs/phpmyadmin/libraries/classes/Controllers/Server/Status/AdvisorController.php60
-rw-r--r--srcs/phpmyadmin/libraries/classes/Controllers/Server/Status/MonitorController.php146
-rw-r--r--srcs/phpmyadmin/libraries/classes/Controllers/Server/Status/ProcessesController.php240
-rw-r--r--srcs/phpmyadmin/libraries/classes/Controllers/Server/Status/QueriesController.php75
-rw-r--r--srcs/phpmyadmin/libraries/classes/Controllers/Server/Status/StatusController.php260
-rw-r--r--srcs/phpmyadmin/libraries/classes/Controllers/Server/Status/VariablesController.php639
-rw-r--r--srcs/phpmyadmin/libraries/classes/Controllers/Server/VariablesController.php238
15 files changed, 2625 insertions, 0 deletions
diff --git a/srcs/phpmyadmin/libraries/classes/Controllers/Server/BinlogController.php b/srcs/phpmyadmin/libraries/classes/Controllers/Server/BinlogController.php
new file mode 100644
index 0000000..859559c
--- /dev/null
+++ b/srcs/phpmyadmin/libraries/classes/Controllers/Server/BinlogController.php
@@ -0,0 +1,149 @@
+<?php
+/* vim: set expandtab sw=4 ts=4 sts=4: */
+/**
+ * Holds the PhpMyAdmin\Controllers\Server\BinlogController
+ *
+ * @package PhpMyAdmin\Controllers
+ */
+declare(strict_types=1);
+
+namespace PhpMyAdmin\Controllers\Server;
+
+use PhpMyAdmin\Controllers\AbstractController;
+use PhpMyAdmin\DatabaseInterface;
+use PhpMyAdmin\Message;
+use PhpMyAdmin\Response;
+use PhpMyAdmin\Template;
+use PhpMyAdmin\Util;
+
+/**
+ * Handles viewing binary logs
+ *
+ * @package PhpMyAdmin\Controllers
+ */
+class BinlogController extends AbstractController
+{
+ /**
+ * array binary log files
+ */
+ protected $binaryLogs;
+
+ /**
+ * Constructs BinlogController
+ *
+ * @param Response $response Response object
+ * @param DatabaseInterface $dbi DatabaseInterface object
+ * @param Template $template Template object
+ */
+ public function __construct($response, $dbi, Template $template)
+ {
+ parent::__construct($response, $dbi, $template);
+ $this->binaryLogs = $this->dbi->fetchResult(
+ 'SHOW MASTER LOGS',
+ 'Log_name',
+ null,
+ DatabaseInterface::CONNECT_USER,
+ DatabaseInterface::QUERY_STORE
+ );
+ }
+
+ /**
+ * Index action
+ *
+ * @param array $params Request params
+ *
+ * @return string
+ */
+ public function indexAction(array $params): string
+ {
+ global $cfg, $pmaThemeImage;
+
+ include_once ROOT_PATH . 'libraries/server_common.inc.php';
+
+ $position = ! empty($params['pos']) ? (int) $params['pos'] : 0;
+
+ $urlParams = [];
+ if (isset($params['log'])
+ && array_key_exists($params['log'], $this->binaryLogs)
+ ) {
+ $urlParams['log'] = $params['log'];
+ }
+
+ $isFullQuery = false;
+ if (! empty($params['is_full_query'])) {
+ $isFullQuery = true;
+ $urlParams['is_full_query'] = 1;
+ }
+
+ $sqlQuery = $this->getSqlQuery(
+ $params['log'] ?? '',
+ $position,
+ (int) $cfg['MaxRows']
+ );
+ $result = $this->dbi->query($sqlQuery);
+
+ $numRows = 0;
+ if (isset($result) && $result) {
+ $numRows = $this->dbi->numRows($result);
+ }
+
+ $previousParams = $urlParams;
+ $fullQueriesParams = $urlParams;
+ $nextParams = $urlParams;
+ if ($position > 0) {
+ $fullQueriesParams['pos'] = $position;
+ if ($position > $cfg['MaxRows']) {
+ $previousParams['pos'] = $position - $cfg['MaxRows'];
+ }
+ }
+ $fullQueriesParams['is_full_query'] = 1;
+ if ($isFullQuery) {
+ unset($fullQueriesParams['is_full_query']);
+ }
+ if ($numRows >= $cfg['MaxRows']) {
+ $nextParams['pos'] = $position + $cfg['MaxRows'];
+ }
+
+ $values = [];
+ while ($value = $this->dbi->fetchAssoc($result)) {
+ $values[] = $value;
+ }
+
+ return $this->template->render('server/binlog/index', [
+ 'url_params' => $urlParams,
+ 'binary_logs' => $this->binaryLogs,
+ 'log' => $params['log'],
+ 'sql_message' => Util::getMessage(Message::success(), $sqlQuery),
+ 'values' => $values,
+ 'has_previous' => $position > 0,
+ 'has_next' => $numRows >= $cfg['MaxRows'],
+ 'previous_params' => $previousParams,
+ 'full_queries_params' => $fullQueriesParams,
+ 'next_params' => $nextParams,
+ 'has_icons' => Util::showIcons('TableNavigationLinksMode'),
+ 'is_full_query' => $isFullQuery,
+ 'image_path' => $pmaThemeImage,
+ ]);
+ }
+
+ /**
+ * @param string $log Binary log file name
+ * @param int $position Position to display
+ * @param int $maxRows Maximum number of rows
+ *
+ * @return string
+ */
+ private function getSqlQuery(
+ string $log,
+ int $position,
+ int $maxRows
+ ): string {
+ $sqlQuery = 'SHOW BINLOG EVENTS';
+ if (! empty($log)) {
+ $sqlQuery .= ' IN \'' . $log . '\'';
+ }
+ $sqlQuery .= ' LIMIT ' . $position . ', ' . $maxRows;
+
+ return $sqlQuery;
+ }
+}
diff --git a/srcs/phpmyadmin/libraries/classes/Controllers/Server/CollationsController.php b/srcs/phpmyadmin/libraries/classes/Controllers/Server/CollationsController.php
new file mode 100644
index 0000000..2d806e8
--- /dev/null
+++ b/srcs/phpmyadmin/libraries/classes/Controllers/Server/CollationsController.php
@@ -0,0 +1,100 @@
+<?php
+/* vim: set expandtab sw=4 ts=4 sts=4: */
+/**
+ * Holds the PhpMyAdmin\Controllers\Server\CollationsController
+ *
+ * @package PhpMyAdmin\Controllers
+ */
+declare(strict_types=1);
+
+namespace PhpMyAdmin\Controllers\Server;
+
+use PhpMyAdmin\Charsets;
+use PhpMyAdmin\Charsets\Charset;
+use PhpMyAdmin\Charsets\Collation;
+use PhpMyAdmin\Controllers\AbstractController;
+use PhpMyAdmin\DatabaseInterface;
+use PhpMyAdmin\Response;
+use PhpMyAdmin\Template;
+
+/**
+ * Handles viewing character sets and collations
+ *
+ * @package PhpMyAdmin\Controllers
+ */
+class CollationsController extends AbstractController
+{
+ /**
+ * @var array|null
+ */
+ private $charsets;
+
+ /**
+ * @var array|null
+ */
+ private $collations;
+
+ /**
+ * CollationsController constructor.
+ *
+ * @param Response $response Response object
+ * @param DatabaseInterface $dbi DatabaseInterface object
+ * @param Template $template Template object
+ * @param array|null $charsets Array of charsets
+ * @param array|null $collations Array of collations
+ */
+ public function __construct(
+ $response,
+ $dbi,
+ Template $template,
+ ?array $charsets = null,
+ ?array $collations = null
+ ) {
+ global $cfg;
+
+ parent::__construct($response, $dbi, $template);
+
+ $this->charsets = $charsets ?? Charsets::getCharsets(
+ $this->dbi,
+ $cfg['Server']['DisableIS']
+ );
+ $this->collations = $collations ?? Charsets::getCollations(
+ $this->dbi,
+ $cfg['Server']['DisableIS']
+ );
+ }
+
+ /**
+ * Index action
+ *
+ * @return string HTML
+ */
+ public function indexAction(): string
+ {
+ include_once ROOT_PATH . 'libraries/server_common.inc.php';
+
+ $charsets = [];
+ /** @var Charset $charset */
+ foreach ($this->charsets as $charset) {
+ $charsetCollations = [];
+ /** @var Collation $collation */
+ foreach ($this->collations[$charset->getName()] as $collation) {
+ $charsetCollations[] = [
+ 'name' => $collation->getName(),
+ 'description' => $collation->getDescription(),
+ 'is_default' => $collation->isDefault(),
+ ];
+ }
+
+ $charsets[] = [
+ 'name' => $charset->getName(),
+ 'description' => $charset->getDescription(),
+ 'collations' => $charsetCollations,
+ ];
+ }
+
+ return $this->template->render('server/collations/index', [
+ 'charsets' => $charsets,
+ ]);
+ }
+}
diff --git a/srcs/phpmyadmin/libraries/classes/Controllers/Server/DatabasesController.php b/srcs/phpmyadmin/libraries/classes/Controllers/Server/DatabasesController.php
new file mode 100644
index 0000000..a601137
--- /dev/null
+++ b/srcs/phpmyadmin/libraries/classes/Controllers/Server/DatabasesController.php
@@ -0,0 +1,424 @@
+<?php
+/* vim: set expandtab sw=4 ts=4 sts=4: */
+/**
+ * Holds the PhpMyAdmin\Controllers\Server\DatabasesController
+ *
+ * @package PhpMyAdmin\Controllers
+ */
+declare(strict_types=1);
+
+namespace PhpMyAdmin\Controllers\Server;
+
+use PhpMyAdmin\Charsets;
+use PhpMyAdmin\Charsets\Charset;
+use PhpMyAdmin\Charsets\Collation;
+use PhpMyAdmin\Controllers\AbstractController;
+use PhpMyAdmin\DatabaseInterface;
+use PhpMyAdmin\Message;
+use PhpMyAdmin\Url;
+use PhpMyAdmin\Util;
+
+/**
+ * Handles viewing and creating and deleting databases
+ *
+ * @package PhpMyAdmin\Controllers
+ */
+class DatabasesController extends AbstractController
+{
+ /**
+ * @var array array of database details
+ */
+ private $databases = [];
+
+ /**
+ * @var int number of databases
+ */
+ private $databaseCount = 0;
+
+ /**
+ * @var string sort by column
+ */
+ private $sortBy;
+
+ /**
+ * @var string sort order of databases
+ */
+ private $sortOrder;
+
+ /**
+ * @var boolean whether to show database statistics
+ */
+ private $hasStatistics;
+
+ /**
+ * @var int position in list navigation
+ */
+ private $position;
+
+ /**
+ * Index action
+ *
+ * @param array $params Request parameters
+ *
+ * @return string HTML
+ */
+ public function indexAction(array $params): string
+ {
+ 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';
+ include_once ROOT_PATH . 'libraries/server_common.inc.php';
+
+ $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 ($server > 0) {
+ $this->databases = $this->dbi->getDatabasesFull(
+ null,
+ $this->hasStatistics,
+ DatabaseInterface::CONNECT_USER,
+ $this->sortBy,
+ $this->sortOrder,
+ $this->position,
+ true
+ );
+ $this->databaseCount = count($dblist->databases);
+ }
+
+ $urlParams = [
+ 'statistics' => $this->hasStatistics,
+ 'pos' => $this->position,
+ 'sort_by' => $this->sortBy,
+ 'sort_order' => $this->sortOrder,
+ ];
+
+ $databases = $this->getDatabases($replication_types ?? []);
+
+ $charsetsList = [];
+ if ($cfg['ShowCreateDb'] && $is_create_db_priv) {
+ $charsets = Charsets::getCharsets($this->dbi, $cfg['Server']['DisableIS']);
+ $collations = Charsets::getCollations($this->dbi, $cfg['Server']['DisableIS']);
+ $serverCollation = $this->dbi->getServerCollation();
+ /** @var Charset $charset */
+ foreach ($charsets as $charset) {
+ $collationsList = [];
+ /** @var Collation $collation */
+ foreach ($collations[$charset->getName()] as $collation) {
+ $collationsList[] = [
+ 'name' => $collation->getName(),
+ 'description' => $collation->getDescription(),
+ 'is_selected' => $serverCollation === $collation->getName(),
+ ];
+ }
+ $charsetsList[] = [
+ 'name' => $charset->getName(),
+ 'description' => $charset->getDescription(),
+ 'collations' => $collationsList,
+ ];
+ }
+ }
+
+ $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,
+ 'charsets' => $charsetsList,
+ '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
+ *
+ * @param array $params Request parameters
+ *
+ * @return array JSON
+ */
+ public function createDatabaseAction(array $params): array
+ {
+ global $cfg, $db;
+
+ // lower_case_table_names=1 `DB` becomes `db`
+ if ($this->dbi->getLowerCaseNames() === '1') {
+ $params['new_db'] = mb_strtolower(
+ $params['new_db']
+ );
+ }
+
+ /**
+ * Builds and executes the db creation sql query
+ */
+ $sqlQuery = 'CREATE DATABASE ' . Util::backquote($params['new_db']);
+ if (! empty($params['db_collation'])) {
+ list($databaseCharset) = explode('_', $params['db_collation']);
+ $charsets = Charsets::getCharsets(
+ $this->dbi,
+ $cfg['Server']['DisableIS']
+ );
+ $collations = Charsets::getCollations(
+ $this->dbi,
+ $cfg['Server']['DisableIS']
+ );
+ if (in_array($databaseCharset, array_keys($charsets))
+ && in_array($params['db_collation'], array_keys($collations[$databaseCharset]))
+ ) {
+ $sqlQuery .= ' DEFAULT'
+ . Util::getCharsetQueryPart($params['db_collation']);
+ }
+ }
+ $sqlQuery .= ';';
+
+ $result = $this->dbi->tryQuery($sqlQuery);
+
+ if (! $result) {
+ // avoid displaying the not-created db name in header or navi panel
+ $db = '';
+
+ $message = Message::rawError($this->dbi->getError());
+ $json = ['message' => $message];
+
+ $this->response->setRequestStatus(false);
+ } else {
+ $db = $params['new_db'];
+
+ $message = Message::success(__('Database %1$s has been created.'));
+ $message->addParam($params['new_db']);
+
+ $json = [
+ 'message' => $message,
+ 'sql_query' => Util::getMessage(null, $sqlQuery, 'success'),
+ 'url_query' => Util::getScriptNameForOption(
+ $cfg['DefaultTabDatabase'],
+ 'database'
+ ) . Url::getCommon(['db' => $params['new_db']]),
+ ];
+ }
+
+ return $json;
+ }
+
+ /**
+ * Handles dropping multiple databases
+ *
+ * @param array $params Request parameters
+ *
+ * @return array JSON
+ */
+ public function dropDatabasesAction(array $params): array
+ {
+ 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();
+
+ $submit_mult = 'drop_db';
+ $mult_btn = __('Yes');
+
+ include ROOT_PATH . 'libraries/mult_submits.inc.php';
+
+ if (empty($message)) { // no error message
+ $numberOfDatabases = count($selected);
+ $message = Message::success(
+ _ngettext(
+ '%1$d database has been dropped successfully.',
+ '%1$d databases have been dropped successfully.',
+ $numberOfDatabases
+ )
+ );
+ $message->addParam($numberOfDatabases);
+ }
+ }
+
+ $json = [];
+ if ($message instanceof Message) {
+ $json = ['message' => $message];
+ $this->response->setRequestStatus($message->isSuccess());
+ }
+
+ return $json;
+ }
+
+ /**
+ * Extracts parameters sort order and sort by
+ *
+ * @param string|null $sortBy sort by
+ * @param string|null $sortOrder sort order
+ *
+ * @return void
+ */
+ private function setSortDetails(?string $sortBy, ?string $sortOrder): void
+ {
+ if (empty($sortBy)) {
+ $this->sortBy = 'SCHEMA_NAME';
+ } else {
+ $sortByWhitelist = [
+ 'SCHEMA_NAME',
+ 'DEFAULT_COLLATION_NAME',
+ 'SCHEMA_TABLES',
+ 'SCHEMA_TABLE_ROWS',
+ 'SCHEMA_DATA_LENGTH',
+ 'SCHEMA_INDEX_LENGTH',
+ 'SCHEMA_LENGTH',
+ 'SCHEMA_DATA_FREE',
+ ];
+ $this->sortBy = 'SCHEMA_NAME';
+ if (in_array($sortBy, $sortByWhitelist)) {
+ $this->sortBy = $sortBy;
+ }
+ }
+
+ $this->sortOrder = 'asc';
+ if (isset($sortOrder)
+ && mb_strtolower($sortOrder) === 'desc'
+ ) {
+ $this->sortOrder = 'desc';
+ }
+ }
+
+ /**
+ * Returns database list
+ *
+ * @param array $replicationTypes replication types
+ *
+ * @return array
+ */
+ private function getDatabases(array $replicationTypes): array
+ {
+ global $cfg, $replication_info;
+
+ $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(
+ $database["SCHEMA_NAME"],
+ $replication_info[$type]['Ignore_DB']
+ );
+ 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;
+ }
+ }
+ }
+ }
+
+ $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[$database['SCHEMA_NAME']] = [
+ 'name' => $database['SCHEMA_NAME'],
+ 'collation' => [],
+ 'statistics' => $statistics,
+ 'replication' => $replication,
+ 'is_system_schema' => $this->dbi->isSystemSchema(
+ $database['SCHEMA_NAME'],
+ true
+ ),
+ ];
+ $collation = Charsets::findCollationByName(
+ $this->dbi,
+ $cfg['Server']['DisableIS'],
+ $database['DEFAULT_COLLATION_NAME']
+ );
+ if ($collation !== null) {
+ $databases[$database['SCHEMA_NAME']]['collation'] = [
+ 'name' => $collation->getName(),
+ 'description' => $collation->getDescription(),
+ ];
+ }
+ }
+
+ return [
+ 'databases' => $databases,
+ 'total_statistics' => $totalStatistics,
+ ];
+ }
+
+ /**
+ * 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,
+ ],
+ ];
+ }
+}
diff --git a/srcs/phpmyadmin/libraries/classes/Controllers/Server/EnginesController.php b/srcs/phpmyadmin/libraries/classes/Controllers/Server/EnginesController.php
new file mode 100644
index 0000000..1170551
--- /dev/null
+++ b/srcs/phpmyadmin/libraries/classes/Controllers/Server/EnginesController.php
@@ -0,0 +1,69 @@
+<?php
+/* vim: set expandtab sw=4 ts=4 sts=4: */
+/**
+ * Holds the PhpMyAdmin\Controllers\Server\EnginesController
+ *
+ * @package PhpMyAdmin\Controllers
+ */
+declare(strict_types=1);
+
+namespace PhpMyAdmin\Controllers\Server;
+
+use PhpMyAdmin\Controllers\AbstractController;
+use PhpMyAdmin\StorageEngine;
+
+/**
+ * Handles viewing storage engine details
+ *
+ * @package PhpMyAdmin\Controllers
+ */
+class EnginesController extends AbstractController
+{
+ /**
+ * Index action
+ *
+ * @return string
+ */
+ public function index(): string
+ {
+ require ROOT_PATH . 'libraries/server_common.inc.php';
+
+ return $this->template->render('server/engines/index', [
+ 'engines' => StorageEngine::getStorageEngines(),
+ ]);
+ }
+
+ /**
+ * Displays details about a given Storage Engine
+ *
+ * @param array $params Request params
+ *
+ * @return string
+ */
+ public function show(array $params): string
+ {
+ require ROOT_PATH . 'libraries/server_common.inc.php';
+
+ $page = $params['page'] ?? '';
+
+ $engine = [];
+ if (StorageEngine::isValid($params['engine'])) {
+ $storageEngine = StorageEngine::getEngine($params['engine']);
+ $engine = [
+ 'engine' => $params['engine'],
+ 'title' => $storageEngine->getTitle(),
+ 'help_page' => $storageEngine->getMysqlHelpPage(),
+ 'comment' => $storageEngine->getComment(),
+ 'info_pages' => $storageEngine->getInfoPages(),
+ 'support' => $storageEngine->getSupportInformationMessage(),
+ 'variables' => $storageEngine->getHtmlVariables(),
+ 'page' => ! empty($page) ? $storageEngine->getPage($page) : '',
+ ];
+ }
+
+ return $this->template->render('server/engines/show', [
+ 'engine' => $engine,
+ 'page' => $page,
+ ]);
+ }
+}
diff --git a/srcs/phpmyadmin/libraries/classes/Controllers/Server/PluginsController.php b/srcs/phpmyadmin/libraries/classes/Controllers/Server/PluginsController.php
new file mode 100644
index 0000000..dce48a6
--- /dev/null
+++ b/srcs/phpmyadmin/libraries/classes/Controllers/Server/PluginsController.php
@@ -0,0 +1,77 @@
+<?php
+/* vim: set expandtab sw=4 ts=4 sts=4: */
+
+/**
+ * Holds the PhpMyAdmin\Controllers\Server\PluginsController
+ *
+ * @package PhpMyAdmin\Controllers
+ */
+declare(strict_types=1);
+
+namespace PhpMyAdmin\Controllers\Server;
+
+use PhpMyAdmin\Controllers\AbstractController;
+use PhpMyAdmin\DatabaseInterface;
+use PhpMyAdmin\Response;
+use PhpMyAdmin\Server\Plugins;
+use PhpMyAdmin\Template;
+
+/**
+ * Handles viewing server plugin details
+ *
+ * @package PhpMyAdmin\Controllers
+ */
+class PluginsController extends AbstractController
+{
+ /**
+ * @var Plugins
+ */
+ private $plugins;
+
+ /**
+ * @param Response $response Response object
+ * @param DatabaseInterface $dbi DatabaseInterface object
+ * @param Template $template Template object
+ * @param Plugins $plugins Plugins object
+ */
+ public function __construct($response, $dbi, Template $template, Plugins $plugins)
+ {
+ parent::__construct($response, $dbi, $template);
+ $this->plugins = $plugins;
+ }
+
+ /**
+ * Index action
+ *
+ * @return string
+ */
+ public function index(): string
+ {
+ include ROOT_PATH . 'libraries/server_common.inc.php';
+
+ $header = $this->response->getHeader();
+ $scripts = $header->getScripts();
+ $scripts->addFile('vendor/jquery/jquery.tablesorter.js');
+ $scripts->addFile('server/plugins.js');
+
+ $plugins = [];
+ $serverPlugins = $this->plugins->getAll();
+ foreach ($serverPlugins as $plugin) {
+ $plugins[$plugin->getType()][] = $plugin->toArray();
+ }
+ ksort($plugins);
+
+ $cleanTypes = [];
+ foreach (array_keys($plugins) as $type) {
+ $cleanTypes[$type] = preg_replace(
+ '/[^a-z]/',
+ '',
+ mb_strtolower($type)
+ );
+ }
+ return $this->template->render('server/plugins/index', [
+ 'plugins' => $plugins,
+ 'clean_types' => $cleanTypes,
+ ]);
+ }
+}
diff --git a/srcs/phpmyadmin/libraries/classes/Controllers/Server/ReplicationController.php b/srcs/phpmyadmin/libraries/classes/Controllers/Server/ReplicationController.php
new file mode 100644
index 0000000..dd48411
--- /dev/null
+++ b/srcs/phpmyadmin/libraries/classes/Controllers/Server/ReplicationController.php
@@ -0,0 +1,72 @@
+<?php
+/* vim: set expandtab sw=4 ts=4 sts=4: */
+/**
+ * Server replications
+ * @package PhpMyAdmin\Controllers\Server
+ */
+declare(strict_types=1);
+
+namespace PhpMyAdmin\Controllers\Server;
+
+use PhpMyAdmin\Controllers\AbstractController;
+use PhpMyAdmin\ReplicationGui;
+use Throwable;
+use Twig_Error_Loader;
+use Twig_Error_Runtime;
+use Twig_Error_Syntax;
+
+/**
+ * Server replications
+ * @package PhpMyAdmin\Controllers\Server
+ */
+class ReplicationController extends AbstractController
+{
+ /**
+ * @param array $params Request parameters
+ * @param ReplicationGui $replicationGui ReplicationGui instance
+ *
+ * @return string HTML
+ * @throws Throwable
+ * @throws Twig_Error_Loader
+ * @throws Twig_Error_Runtime
+ * @throws Twig_Error_Syntax
+ */
+ public function index(array $params, ReplicationGui $replicationGui): string
+ {
+ global $replication_info, $server_slave_replication, $url_params;
+
+ $errorMessages = $replicationGui->getHtmlForErrorMessage();
+
+ if ($replication_info['master']['status']) {
+ $masterReplicationHtml = $replicationGui->getHtmlForMasterReplication();
+ }
+
+ if (isset($params['mr_configure'])) {
+ $masterConfigurationHtml = $replicationGui->getHtmlForMasterConfiguration();
+ } else {
+ if (! isset($params['repl_clear_scr'])) {
+ $slaveConfigurationHtml = $replicationGui->getHtmlForSlaveConfiguration(
+ $replication_info['slave']['status'],
+ $server_slave_replication
+ );
+ }
+ if (isset($params['sl_configure'])) {
+ $changeMasterHtml = $replicationGui->getHtmlForReplicationChangeMaster('slave_changemaster');
+ }
+ }
+
+ return $this->template->render('server/replication/index', [
+ 'url_params' => $url_params,
+ 'is_super_user' => $this->dbi->isSuperuser(),
+ 'error_messages' => $errorMessages,
+ 'is_master' => $replication_info['master']['status'],