diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon
index 1a37173ff0..14582dc513 100644
--- a/phpstan-baseline.neon
+++ b/phpstan-baseline.neon
@@ -11037,7 +11037,7 @@ parameters:
-
message: '#^Construct empty\(\) is not allowed\. Use more strict comparison\.$#'
identifier: empty.notAllowed
- count: 13
+ count: 12
path: src/Server/Privileges.php
-
@@ -11073,7 +11073,7 @@ parameters:
-
message: '#^Only booleans are allowed in a negated boolean, PhpMyAdmin\\Dbal\\ResultInterface\|false given\.$#'
identifier: booleanNot.exprNotBoolean
- count: 13
+ count: 11
path: src/Server/Privileges.php
-
diff --git a/psalm-baseline.xml b/psalm-baseline.xml
index d489b3bf59..f9377479e0 100644
--- a/psalm-baseline.xml
+++ b/psalm-baseline.xml
@@ -7275,6 +7275,10 @@
+
+
+
+
@@ -7519,7 +7523,6 @@
-
diff --git a/src/Controllers/Server/PrivilegesController.php b/src/Controllers/Server/PrivilegesController.php
index f69aaac6b6..92de55b47d 100644
--- a/src/Controllers/Server/PrivilegesController.php
+++ b/src/Controllers/Server/PrivilegesController.php
@@ -10,6 +10,8 @@ use PhpMyAdmin\ConfigStorage\RelationCleanup;
use PhpMyAdmin\Controllers\InvocableController;
use PhpMyAdmin\Current;
use PhpMyAdmin\Dbal\DatabaseInterface;
+use PhpMyAdmin\Exceptions\UpdateAuthPluginFailure;
+use PhpMyAdmin\Exceptions\UserPasswordUpdateFailure;
use PhpMyAdmin\Html\Generator;
use PhpMyAdmin\Http\Response;
use PhpMyAdmin\Http\ServerRequest;
@@ -262,11 +264,23 @@ final class PrivilegesController implements InvocableController
* Updates the password
*/
if ($request->hasBodyParam('change_pw')) {
- Current::$message = $serverPrivileges->updatePassword(
- $errorUrl,
- $serverPrivileges->username ?? '',
- $serverPrivileges->hostname ?? '',
- );
+ try {
+ Current::$message = $serverPrivileges->updatePassword(
+ $serverPrivileges->username ?? '',
+ $serverPrivileges->hostname ?? '',
+ );
+ } catch (UpdateAuthPluginFailure | UserPasswordUpdateFailure $exception) {
+ if ($request->isAjax()) {
+ $this->response->setRequestStatus(false);
+ $this->response->addJSON('message', $exception->getMessage());
+
+ return $this->response->response();
+ }
+
+ $this->response->addHTML($exception->getMessage() . Generator::getBackUrlHtml($errorUrl));
+
+ return $this->response->response();
+ }
}
/**
@@ -392,6 +406,8 @@ final class PrivilegesController implements InvocableController
$this->response->addHTML($serverPrivileges->getHtmlForUserOverview(
$userPrivileges,
$request->getQueryParam('initial'),
+ $request->isAjax(),
+ $request->has('ajax_page_request'),
));
} elseif ($routinename !== '') {
$this->response->addHTML(
diff --git a/src/Controllers/Server/ReplicationController.php b/src/Controllers/Server/ReplicationController.php
index 5f56d4489b..c8b24f63ca 100644
--- a/src/Controllers/Server/ReplicationController.php
+++ b/src/Controllers/Server/ReplicationController.php
@@ -11,10 +11,12 @@ use PhpMyAdmin\Controllers\InvocableController;
use PhpMyAdmin\Dbal\DatabaseInterface;
use PhpMyAdmin\Http\Response;
use PhpMyAdmin\Http\ServerRequest;
+use PhpMyAdmin\Message;
use PhpMyAdmin\Replication\ReplicationGui;
use PhpMyAdmin\Replication\ReplicationInfo;
use PhpMyAdmin\ResponseRenderer;
use PhpMyAdmin\Routing\Route;
+use PhpMyAdmin\Url;
use PhpMyAdmin\UrlParams;
use function is_array;
@@ -61,7 +63,7 @@ final class ReplicationController implements InvocableController
$srSkipErrorsCount = $request->getParsedBodyParamAsStringOrNull('sr_skip_errors_count', '1');
$srReplicaControlParam = $request->getParsedBodyParamAsStringOrNull('sr_replica_control_param');
- $this->replicationGui->handleControlRequest(
+ $message = $this->replicationGui->handleControlRequest(
$request->getParsedBodyParam('sr_take_action') !== null,
$request->getParsedBodyParam('replica_changeprimary') !== null,
$request->getParsedBodyParam('sr_replica_server_control') !== null,
@@ -74,6 +76,16 @@ final class ReplicationController implements InvocableController
$request->getParsedBodyParamAsString('hostname', ''),
(int) $request->getParsedBodyParamAsStringOrNull('text_port'),
);
+ if ($message instanceof Message) {
+ if ($request->isAjax()) {
+ $this->response->setRequestStatus($message->isSuccess());
+ $this->response->addJSON('message', $message);
+ } else {
+ $this->response->redirect(
+ './index.php?route=/server/replication' . Url::getCommonRaw(UrlParams::$params, '&'),
+ );
+ }
+ }
}
$errorMessages = $this->replicationGui->getHtmlForErrorMessage();
diff --git a/src/Controllers/Table/AddFieldController.php b/src/Controllers/Table/AddFieldController.php
index f4f6bf3908..9944d11f24 100644
--- a/src/Controllers/Table/AddFieldController.php
+++ b/src/Controllers/Table/AddFieldController.php
@@ -101,15 +101,12 @@ final readonly class AddFieldController implements InvocableController
return $this->response->response();
}
- $result = $createAddField->tryColumnCreationQuery(
+ $errorMessageHtml = $createAddField->tryColumnCreationQuery(
DatabaseName::from(Current::$database),
Current::$sqlQuery,
- $errorUrl,
);
-
- if (! $result) {
- $errorMessageHtml = Generator::mysqlDie('', '', false);
- $this->response->addHTML($errorMessageHtml);
+ if ($errorMessageHtml !== null) {
+ $this->response->addHTML($errorMessageHtml . Generator::getBackUrlHtml($errorUrl));
$this->response->setRequestStatus(false);
return $this->response->response();
diff --git a/src/CreateAddField.php b/src/CreateAddField.php
index f1c7aa9e92..b640cbb32f 100644
--- a/src/CreateAddField.php
+++ b/src/CreateAddField.php
@@ -436,33 +436,18 @@ class CreateAddField
*
* @param DatabaseName $db current database
* @param string $sqlQuery the query to run
- * @param string $errorUrl error page url
*/
- public function tryColumnCreationQuery(
- DatabaseName $db,
- string $sqlQuery,
- string $errorUrl,
- ): bool {
- // To allow replication, we first select the db to use and then run queries
- // on this db.
+ public function tryColumnCreationQuery(DatabaseName $db, string $sqlQuery): string|null
+ {
+ // To allow replication, we first select the db to use and then run queries on this db.
if (! $this->dbi->selectDb($db)) {
- $errorMessage = Generator::mysqlDie(
- $this->dbi->getError(),
- 'USE ' . Util::backquote($db->getName()),
- false,
- );
-
- $response = ResponseRenderer::getInstance();
- if ($response->isAjax()) {
- $response->setRequestStatus(false);
- $response->addJSON('message', $errorMessage);
- $response->callExit();
- }
-
- $response->addHTML($errorMessage . Generator::getBackUrlHtml($errorUrl));
- $response->callExit();
+ return Generator::mysqlDie($this->dbi->getError(), 'USE ' . Util::backquote($db->getName()), false);
}
- return (bool) $this->dbi->tryQuery($sqlQuery);
+ if ($this->dbi->tryQuery($sqlQuery) === false) {
+ return Generator::mysqlDie($this->dbi->getError(), $sqlQuery, false);
+ }
+
+ return null;
}
}
diff --git a/src/Exceptions/PdfCreationFailure.php b/src/Exceptions/PdfCreationFailure.php
new file mode 100644
index 0000000000..46b9d62176
--- /dev/null
+++ b/src/Exceptions/PdfCreationFailure.php
@@ -0,0 +1,11 @@
+getDisplay();
- ResponseRenderer::getInstance()->callExit();
+ throw new PdfCreationFailure(__('Error while creating PDF:') . ' ' . $msg);
}
}
diff --git a/src/Replication/ReplicationGui.php b/src/Replication/ReplicationGui.php
index b373c5e6a2..8bbc800d92 100644
--- a/src/Replication/ReplicationGui.php
+++ b/src/Replication/ReplicationGui.php
@@ -12,7 +12,6 @@ use PhpMyAdmin\Dbal\ConnectionType;
use PhpMyAdmin\Dbal\DatabaseInterface;
use PhpMyAdmin\Message;
use PhpMyAdmin\Query\Utilities;
-use PhpMyAdmin\ResponseRenderer;
use PhpMyAdmin\Template;
use PhpMyAdmin\Url;
use PhpMyAdmin\UrlParams;
@@ -425,16 +424,11 @@ class ReplicationGui
string $pmaPassword,
string $hostname,
int $port,
- ): void {
+ ): Message|null {
if (! $srTakeAction) {
- return;
+ return null;
}
- $refresh = false;
- $result = false;
- $messageSuccess = '';
- $messageError = '';
-
if ($replicaChangePrimary && ! Config::getInstance()->settings['AllowArbitraryServer']) {
$_SESSION['replication']['sr_action_status'] = 'error';
$_SESSION['replication']['sr_action_info'] = __(
@@ -442,10 +436,9 @@ class ReplicationGui
. ' $cfg[\'AllowArbitraryServer\'] in phpMyAdmin configuration.',
);
} elseif ($replicaChangePrimary) {
- $result = $this->handleRequestForReplicaChangePrimary($username, $pmaPassword, $hostname, $port);
+ $this->handleRequestForReplicaChangePrimary($username, $pmaPassword, $hostname, $port);
} elseif ($srReplicaServerControl) {
$result = $this->handleRequestForReplicaServerControl($srReplicaAction, $srReplicaControlParam);
- $refresh = true;
switch ($srReplicaAction) {
case 'start':
@@ -465,28 +458,13 @@ class ReplicationGui
$messageError = __('Error.');
break;
}
+
+ return $result ? Message::success($messageSuccess) : Message::error($messageError);
} elseif ($srReplicaSkipError) {
- $result = $this->handleRequestForReplicaSkipError($srSkipErrorsCount);
+ $this->handleRequestForReplicaSkipError($srSkipErrorsCount);
}
- if ($refresh) {
- $response = ResponseRenderer::getInstance();
- if ($response->isAjax()) {
- $response->setRequestStatus($result);
- $response->addJSON(
- 'message',
- $result
- ? Message::success($messageSuccess)
- : Message::error($messageError),
- );
- } else {
- $response->redirect(
- './index.php?route=/server/replication' . Url::getCommonRaw(UrlParams::$params, '&'),
- );
- }
- }
-
- unset($refresh);
+ return null;
}
public function handleRequestForReplicaChangePrimary(
diff --git a/src/Server/Privileges.php b/src/Server/Privileges.php
index 04ef6a8f2b..cc483d4aa6 100644
--- a/src/Server/Privileges.php
+++ b/src/Server/Privileges.php
@@ -16,6 +16,8 @@ use PhpMyAdmin\Database\Routines;
use PhpMyAdmin\Dbal\ConnectionType;
use PhpMyAdmin\Dbal\DatabaseInterface;
use PhpMyAdmin\Dbal\ResultInterface;
+use PhpMyAdmin\Exceptions\UpdateAuthPluginFailure;
+use PhpMyAdmin\Exceptions\UserPasswordUpdateFailure;
use PhpMyAdmin\Html\Generator;
use PhpMyAdmin\Html\MySQLDocumentation;
use PhpMyAdmin\Http\ServerRequest;
@@ -748,13 +750,9 @@ class Privileges
/**
* Update password and get message for password updating
*
- * @param string $errorUrl error url
- * @param string $username username
- * @param string $hostname hostname
- *
* @return Message success or error message after updating password
*/
- public function updatePassword(string $errorUrl, string $username, string $hostname): Message
+ public function updatePassword(string $username, string $hostname): Message
{
// similar logic in /user-password
$message = null;
@@ -841,22 +839,12 @@ class Privileges
. $this->getUserHostCondition($username, $hostname) . ';';
// Update the plugin for the user
- if (! $this->dbi->tryQuery($updatePluginQuery)) {
- $errorMessage = Generator::mysqlDie(
+ if ($this->dbi->tryQuery($updatePluginQuery) === false) {
+ throw new UpdateAuthPluginFailure(Generator::mysqlDie(
$this->dbi->getError(),
$updatePluginQuery,
false,
- );
-
- $response = ResponseRenderer::getInstance();
- if ($response->isAjax()) {
- $response->setRequestStatus(false);
- $response->addJSON('message', $errorMessage);
- $response->callExit();
- }
-
- $response->addHTML($errorMessage . Generator::getBackUrlHtml($errorUrl));
- $response->callExit();
+ ));
}
$this->dbi->tryQuery('FLUSH PRIVILEGES;');
@@ -886,22 +874,12 @@ class Privileges
. '(' . $this->dbi->quoteString($_POST['pma_pw']) . ')');
}
- if (! $this->dbi->tryQuery($localQuery)) {
- $errorMessage = Generator::mysqlDie(
+ if ($this->dbi->tryQuery($localQuery) === false) {
+ throw new UserPasswordUpdateFailure(Generator::mysqlDie(
$this->dbi->getError(),
$sqlQuery,
false,
- );
-
- $response = ResponseRenderer::getInstance();
- if ($response->isAjax()) {
- $response->setRequestStatus(false);
- $response->addJSON('message', $errorMessage);
- $response->callExit();
- }
-
- $response->addHTML($errorMessage . Generator::getBackUrlHtml($errorUrl));
- $response->callExit();
+ ));
}
// Flush privileges after successful password change
@@ -2456,8 +2434,12 @@ class Privileges
/**
* Get HTML snippet for display user overview page
*/
- public function getHtmlForUserOverview(UserPrivileges $userPrivileges, string|null $initial): string
- {
+ public function getHtmlForUserOverview(
+ UserPrivileges $userPrivileges,
+ string|null $initial,
+ bool $isAjax,
+ bool $isAjaxPageRequest,
+ ): string {
$serverVersion = $this->dbi->getVersion();
$passwordColumn = Compatibility::isMySqlOrPerconaDb($this->dbi) && $serverVersion >= 50706
? 'authentication_string'
@@ -2481,8 +2463,7 @@ class Privileges
$this->template->render('export_modal');
}
- $response = ResponseRenderer::getInstance();
- if (! $response->isAjax() || ! empty($_REQUEST['ajax_page_request'])) {
+ if (! $isAjax || $isAjaxPageRequest) {
if ($userPrivileges->isReload) {
$flushnote = new Message(
__(
diff --git a/tests/unit/Server/PrivilegesTest.php b/tests/unit/Server/PrivilegesTest.php
index 333a6b6ebe..a6306e5983 100644
--- a/tests/unit/Server/PrivilegesTest.php
+++ b/tests/unit/Server/PrivilegesTest.php
@@ -417,11 +417,10 @@ class PrivilegesTest extends AbstractTestCase
$username = 'pma_username';
$hostname = 'pma_hostname';
- $errUrl = 'error.php';
$_POST['pma_pw'] = 'pma_pw';
$_POST['authentication_plugin'] = 'mysql_native_password';
- $message = $serverPrivileges->updatePassword($errUrl, $username, $hostname);
+ $message = $serverPrivileges->updatePassword($username, $hostname);
self::assertSame(
'The password for \'pma_username\'@\'pma_hostname\' was changed successfully.',
@@ -1570,8 +1569,7 @@ class PrivilegesTest extends AbstractTestCase
$serverPrivileges = $this->getPrivileges($this->createDatabaseInterface($dummyDbi));
- $_REQUEST = ['ajax_page_request' => '1'];
- $actual = $serverPrivileges->getHtmlForUserOverview($userPrivileges, null);
+ $actual = $serverPrivileges->getHtmlForUserOverview($userPrivileges, null, false, true);
$dummyDbi->assertAllQueriesConsumed();
self::assertStringContainsString('Note: MySQL privilege names are expressed in English.', $actual);
self::assertStringContainsString(
@@ -1592,7 +1590,7 @@ class PrivilegesTest extends AbstractTestCase
);
$dummyDbi->addResult('SELECT 1 FROM `mysql`.`user`', false);
$serverPrivileges = $this->getPrivileges($this->createDatabaseInterface($dummyDbi));
- $html = $serverPrivileges->getHtmlForUserOverview($userPrivileges, null);
+ $html = $serverPrivileges->getHtmlForUserOverview($userPrivileges, null, false, true);
self::assertStringContainsString(
Url::getCommon(['adduser' => 1], ''),
@@ -1620,7 +1618,7 @@ class PrivilegesTest extends AbstractTestCase
);
$dummyDbi->addResult('SELECT 1 FROM `mysql`.`user`', [[1]]);
$serverPrivileges = $this->getPrivileges($this->createDatabaseInterface($dummyDbi));
- $actual = $serverPrivileges->getHtmlForUserOverview($userPrivileges, null);
+ $actual = $serverPrivileges->getHtmlForUserOverview($userPrivileges, null, false, true);
self::assertStringContainsString('Your privilege table structure seems to be older than'
. ' this MySQL version!
'