diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon
index 8e7d2bb5e8..ea011733d8 100644
--- a/phpstan-baseline.neon
+++ b/phpstan-baseline.neon
@@ -2127,12 +2127,6 @@ parameters:
count: 16
path: src/Controllers/Database/EventsController.php
- -
- message: '#^Only booleans are allowed in \|\|, int\<0, max\> given on the left side\.$#'
- identifier: booleanOr.leftNotBoolean
- count: 1
- path: src/Controllers/Database/EventsController.php
-
-
message: '#^Parameter \#1 \$identifier of static method PhpMyAdmin\\Util\:\:backquote\(\) expects string\|Stringable\|null, mixed given\.$#'
identifier: argument.type
@@ -2151,12 +2145,6 @@ parameters:
count: 1
path: src/Controllers/Database/EventsController.php
- -
- message: '#^Parameter \#1 \$value of function count expects array\|Countable, mixed given\.$#'
- identifier: argument.type
- count: 1
- path: src/Controllers/Database/EventsController.php
-
-
message: '#^Parameter \#2 \$name of method PhpMyAdmin\\Database\\Events\:\:getDetails\(\) expects string, mixed given\.$#'
identifier: argument.type
@@ -2304,12 +2292,6 @@ parameters:
count: 1
path: src/Controllers/Database/RoutinesController.php
- -
- message: '#^Only booleans are allowed in a negated boolean, mixed given\.$#'
- identifier: booleanNot.exprNotBoolean
- count: 1
- path: src/Controllers/Database/RoutinesController.php
-
-
message: '#^Parameter \#1 \$identifier of static method PhpMyAdmin\\Util\:\:backquote\(\) expects string\|Stringable\|null, mixed given\.$#'
identifier: argument.type
@@ -5745,12 +5727,6 @@ parameters:
count: 11
path: src/Controllers/Triggers/IndexController.php
- -
- message: '#^Only booleans are allowed in \|\|, int\<0, max\> given on the left side\.$#'
- identifier: booleanOr.leftNotBoolean
- count: 1
- path: src/Controllers/Triggers/IndexController.php
-
-
message: '#^Parameter \#1 \$identifier of static method PhpMyAdmin\\Util\:\:backquote\(\) expects string\|Stringable\|null, mixed given\.$#'
identifier: argument.type
@@ -5769,12 +5745,6 @@ parameters:
count: 1
path: src/Controllers/Triggers/IndexController.php
- -
- message: '#^Parameter \#1 \$value of function count expects array\|Countable, mixed given\.$#'
- identifier: argument.type
- count: 1
- path: src/Controllers/Triggers/IndexController.php
-
-
message: '#^Parameter \#3 \$name of method PhpMyAdmin\\Triggers\\Triggers\:\:getTriggerByName\(\) expects string, mixed given\.$#'
identifier: argument.type
@@ -6579,18 +6549,6 @@ parameters:
count: 1
path: src/Database/Designer/Common.php
- -
- message: '#^Argument of an invalid type mixed supplied for foreach, only iterables are supported\.$#'
- identifier: foreach.nonIterable
- count: 1
- path: src/Database/Events.php
-
- -
- message: '#^Binary operation "\." between ''\
'' and mixed results in an error\.$#'
- identifier: binaryOp.invalid
- count: 1
- path: src/Database/Events.php
-
-
message: '#^Binary operation "\.\=" between non\-falsy\-string and mixed results in an error\.$#'
identifier: assignOp.invalid
@@ -6606,12 +6564,6 @@ parameters:
count: 1
path: src/Database/Events.php
- -
- message: '#^Cannot access an offset on mixed\.$#'
- identifier: offsetAccess.nonOffsetAccessible
- count: 7
- path: src/Database/Events.php
-
-
message: '#^Cannot cast mixed to int\.$#'
identifier: cast.int
@@ -6705,7 +6657,7 @@ parameters:
-
message: '#^Argument of an invalid type mixed supplied for foreach, only iterables are supported\.$#'
identifier: foreach.nonIterable
- count: 3
+ count: 2
path: src/Database/Routines.php
-
@@ -6714,12 +6666,6 @@ parameters:
count: 2
path: src/Database/Routines.php
- -
- message: '#^Binary operation "\." between ''\'' and mixed results in an error\.$#'
- identifier: binaryOp.invalid
- count: 1
- path: src/Database/Routines.php
-
-
message: '#^Binary operation "\." between non\-falsy\-string and mixed results in an error\.$#'
identifier: binaryOp.invalid
@@ -6741,12 +6687,6 @@ parameters:
count: 3
path: src/Database/Routines.php
- -
- message: '#^Cannot access an offset on mixed\.$#'
- identifier: offsetAccess.nonOffsetAccessible
- count: 9
- path: src/Database/Routines.php
-
-
message: '#^Cannot access offset int\<0, max\> on mixed\.$#'
identifier: offsetAccess.nonOffsetAccessible
@@ -6804,7 +6744,7 @@ parameters:
-
message: '#^Construct empty\(\) is not allowed\. Use more strict comparison\.$#'
identifier: empty.notAllowed
- count: 22
+ count: 21
path: src/Database/Routines.php
-
@@ -6909,12 +6849,6 @@ parameters:
count: 4
path: src/Database/Routines.php
- -
- message: '#^Parameter \#1 \.\.\.\$arrays of function array_merge expects array, mixed given\.$#'
- identifier: argument.type
- count: 1
- path: src/Database/Routines.php
-
-
message: '#^Parameter \#2 \$array of function implode expects array\|null, list\\|string given\.$#'
identifier: argument.type
@@ -18111,18 +18045,6 @@ parameters:
count: 1
path: src/Transformations.php
- -
- message: '#^Argument of an invalid type mixed supplied for foreach, only iterables are supported\.$#'
- identifier: foreach.nonIterable
- count: 1
- path: src/Triggers/Triggers.php
-
- -
- message: '#^Binary operation "\." between ''\'' and mixed results in an error\.$#'
- identifier: binaryOp.invalid
- count: 1
- path: src/Triggers/Triggers.php
-
-
message: '#^Binary operation "\.\=" between non\-falsy\-string and mixed results in an error\.$#'
identifier: assignOp.invalid
@@ -18138,12 +18060,6 @@ parameters:
count: 1
path: src/Triggers/Triggers.php
- -
- message: '#^Cannot access an offset on mixed\.$#'
- identifier: offsetAccess.nonOffsetAccessible
- count: 7
- path: src/Triggers/Triggers.php
-
-
message: '#^Cannot call method getCreateSql\(\) on PhpMyAdmin\\Triggers\\Trigger\|null\.$#'
identifier: method.nonObject
diff --git a/psalm-baseline.xml b/psalm-baseline.xml
index f78452f5ce..85ee57d7d0 100644
--- a/psalm-baseline.xml
+++ b/psalm-baseline.xml
@@ -883,9 +883,6 @@
-
-
-
@@ -893,7 +890,6 @@
-
@@ -934,10 +930,6 @@
-
-
-
-
@@ -1019,9 +1011,6 @@
-
-
-
@@ -1063,7 +1052,6 @@
-
@@ -1119,10 +1107,6 @@
-
-
-
-
@@ -1148,9 +1132,6 @@
-
-
-
@@ -3630,9 +3611,6 @@
-
-
-
@@ -3642,9 +3620,6 @@
-
-
-
@@ -3681,10 +3656,6 @@
-
-
-
-
@@ -4112,29 +4083,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -4160,12 +4108,6 @@
-
-
-
-
-
-
@@ -4207,14 +4149,9 @@
-
-
-
-
-
@@ -4272,18 +4209,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
@@ -4300,15 +4225,11 @@
-
-
-
-
@@ -4317,7 +4238,6 @@
-
dbi->fetchResult($privilegesBackupQuery, 0)]]>
@@ -4374,7 +4294,6 @@
-
type->parameters]]>
@@ -4382,7 +4301,6 @@
return->parameters]]>
-
type->options->options]]>
return->options->options]]>
@@ -4403,7 +4321,6 @@
-
@@ -10604,29 +10521,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -10640,15 +10534,9 @@
-
-
-
-
-
-
diff --git a/src/Controllers/Database/EventsController.php b/src/Controllers/Database/EventsController.php
index 2fc25e9f4d..5b797b2ada 100644
--- a/src/Controllers/Database/EventsController.php
+++ b/src/Controllers/Database/EventsController.php
@@ -18,7 +18,6 @@ use PhpMyAdmin\Template;
use PhpMyAdmin\Util;
use function __;
-use function count;
use function htmlspecialchars;
use function mb_strtoupper;
use function sprintf;
@@ -37,8 +36,6 @@ final class EventsController implements InvocableController
public function __invoke(ServerRequest $request): Response
{
- $GLOBALS['errors'] ??= null;
-
$this->response->addScriptFiles(['database/events.js', 'sql.js']);
if (! $request->isAjax()) {
@@ -56,11 +53,6 @@ final class EventsController implements InvocableController
$this->dbi->selectDb(Current::$database);
}
- /**
- * Keep a list of errors that occurred while
- * processing an 'Add' or 'Edit' operation.
- */
- $GLOBALS['errors'] = [];
$GLOBALS['message'] ??= null;
if (! empty($_POST['editor_process_add']) || ! empty($_POST['editor_process_edit'])) {
@@ -109,7 +101,7 @@ final class EventsController implements InvocableController
* Display a form used to add/edit a trigger, if necessary
*/
if (
- count($GLOBALS['errors'])
+ $this->events->getErrorCount() > 0
|| empty($_POST['editor_process_add'])
&& empty($_POST['editor_process_edit'])
&& (
diff --git a/src/Controllers/Database/RoutinesController.php b/src/Controllers/Database/RoutinesController.php
index 07b7c4a86b..df754e24a4 100644
--- a/src/Controllers/Database/RoutinesController.php
+++ b/src/Controllers/Database/RoutinesController.php
@@ -49,8 +49,6 @@ final class RoutinesController implements InvocableController
public function __invoke(ServerRequest $request): Response
{
- $GLOBALS['errors'] ??= null;
-
$this->response->addScriptFiles(['database/routines.js', 'sql.js']);
$type = $_REQUEST['type'] ?? null;
@@ -102,11 +100,6 @@ final class RoutinesController implements InvocableController
$this->dbi->selectDb(Current::$database);
}
- /**
- * Keep a list of errors that occurred while
- * processing an 'Add' or 'Edit' operation.
- */
- $GLOBALS['errors'] = [];
$GLOBALS['message'] ??= null;
if (! empty($_POST['editor_process_add']) || ! empty($_POST['editor_process_edit'])) {
@@ -149,7 +142,7 @@ final class RoutinesController implements InvocableController
*/
// FIXME: this must be simpler than that
if (
- $GLOBALS['errors'] !== []
+ $this->routines->getErrorCount() > 0
|| empty($_POST['editor_process_add'])
&& empty($_POST['editor_process_edit'])
&& (
@@ -212,7 +205,7 @@ final class RoutinesController implements InvocableController
}
} elseif (
$operation === 'add'
- || ($routine['item_num_params'] == 0 && $mode === 'add' && ! $GLOBALS['errors'])
+ || ($routine['item_num_params'] == 0 && $mode === 'add' && $this->routines->getErrorCount() === 0)
) {
$routine['item_param_dir'][] = '';
$routine['item_param_name'][] = '';
diff --git a/src/Controllers/Triggers/IndexController.php b/src/Controllers/Triggers/IndexController.php
index bb84196bb8..3ef30a18ba 100644
--- a/src/Controllers/Triggers/IndexController.php
+++ b/src/Controllers/Triggers/IndexController.php
@@ -22,7 +22,6 @@ use PhpMyAdmin\UrlParams;
use PhpMyAdmin\Util;
use function __;
-use function count;
use function htmlspecialchars;
use function in_array;
use function mb_strtoupper;
@@ -45,8 +44,6 @@ final class IndexController implements InvocableController
public function __invoke(ServerRequest $request): Response
{
- $GLOBALS['errors'] ??= null;
-
$this->response->addScriptFiles(['triggers.js', 'sql.js']);
if (! $request->isAjax()) {
@@ -93,11 +90,6 @@ final class IndexController implements InvocableController
$this->dbi->selectDb(Current::$database);
}
- /**
- * Keep a list of errors that occurred while
- * processing an 'Add' or 'Edit' operation.
- */
- $GLOBALS['errors'] = [];
$GLOBALS['message'] ??= null;
if (! empty($_POST['editor_process_add']) || ! empty($_POST['editor_process_edit'])) {
@@ -160,7 +152,7 @@ final class IndexController implements InvocableController
* Display a form used to add/edit a trigger, if necessary
*/
if (
- count($GLOBALS['errors'])
+ $this->triggers->getErrorCount() > 0
|| empty($_POST['editor_process_add'])
&& empty($_POST['editor_process_edit'])
&& (! empty($_REQUEST['add_item']) || ! empty($_REQUEST['edit_item'])) // FIXME: must be simpler than that
diff --git a/src/Database/Events.php b/src/Database/Events.php
index 7512804a43..ca7f732c44 100644
--- a/src/Database/Events.php
+++ b/src/Database/Events.php
@@ -15,6 +15,7 @@ use PhpMyAdmin\Util;
use function __;
use function array_column;
use function array_multisort;
+use function count;
use function explode;
use function htmlspecialchars;
use function in_array;
@@ -39,6 +40,9 @@ class Events
/** @var array */
public readonly array $interval;
+ /** @var list */
+ private array $errors = [];
+
public function __construct(private DatabaseInterface $dbi)
{
$this->status = [
@@ -75,7 +79,7 @@ class Events
$itemQuery = $this->getQueryFromRequest();
// set by getQueryFromRequest()
- if ($GLOBALS['errors'] === []) {
+ if ($this->errors === []) {
// Execute the created query
if (! empty($_POST['editor_process_edit'])) {
// Backup the old trigger, in case something goes wrong
@@ -85,7 +89,7 @@ class Events
. ";\n";
$result = $this->dbi->tryQuery($dropItem);
if (! $result) {
- $GLOBALS['errors'][] = sprintf(
+ $this->errors[] = sprintf(
__('The following query has failed: "%s"'),
htmlspecialchars($dropItem),
)
@@ -94,7 +98,7 @@ class Events
} else {
$result = $this->dbi->tryQuery($itemQuery);
if (! $result) {
- $GLOBALS['errors'][] = sprintf(
+ $this->errors[] = sprintf(
__('The following query has failed: "%s"'),
htmlspecialchars($itemQuery),
)
@@ -109,7 +113,7 @@ class Events
// and now even the backup query does not execute!
// This should not happen, but we better handle
// this just in case.
- $GLOBALS['errors'][] = __('Sorry, we failed to restore the dropped event.') . '
'
+ $this->errors[] = __('Sorry, we failed to restore the dropped event.') . '
'
. __('The backed up query was:')
. '"' . htmlspecialchars($createItem) . '"
'
. __('MySQL said: ') . $this->dbi->getError();
@@ -128,7 +132,7 @@ class Events
// 'Add a new item' mode
$result = $this->dbi->tryQuery($itemQuery);
if (! $result) {
- $GLOBALS['errors'][] = sprintf(
+ $this->errors[] = sprintf(
__('The following query has failed: "%s"'),
htmlspecialchars($itemQuery),
)
@@ -146,7 +150,7 @@ class Events
}
}
- if ($GLOBALS['errors'] !== []) {
+ if ($this->errors !== []) {
$GLOBALS['message'] = Message::error(
''
. __(
@@ -155,7 +159,7 @@ class Events
. '',
);
$GLOBALS['message']->addHtml('');
- foreach ($GLOBALS['errors'] as $string) {
+ foreach ($this->errors as $string) {
$GLOBALS['message']->addHtml('- ' . $string . '
');
}
@@ -256,8 +260,6 @@ class Events
*/
public function getQueryFromRequest(): string
{
- $GLOBALS['errors'] ??= null;
-
$query = 'CREATE ';
if (! empty($_POST['item_definer'])) {
if (str_contains($_POST['item_definer'], '@')) {
@@ -265,7 +267,7 @@ class Events
$query .= 'DEFINER=' . Util::backquote($arr[0]);
$query .= '@' . Util::backquote($arr[1]) . ' ';
} else {
- $GLOBALS['errors'][] = __('The definer must be in the "username@hostname" format!');
+ $this->errors[] = __('The definer must be in the "username@hostname" format!');
}
}
@@ -273,7 +275,7 @@ class Events
if (! empty($_POST['item_name'])) {
$query .= Util::backquote($_POST['item_name']) . ' ';
} else {
- $GLOBALS['errors'][] = __('You must provide an event name!');
+ $this->errors[] = __('You must provide an event name!');
}
$query .= 'ON SCHEDULE ';
@@ -287,7 +289,7 @@ class Events
$query .= 'EVERY ' . (int) $_POST['item_interval_value'] . ' ';
$query .= $_POST['item_interval_field'] . ' ';
} else {
- $GLOBALS['errors'][] = __('You must provide a valid interval value for the event.');
+ $this->errors[] = __('You must provide a valid interval value for the event.');
}
if (! empty($_POST['item_starts'])) {
@@ -300,10 +302,10 @@ class Events
} elseif (! empty($_POST['item_execute_at'])) {
$query .= 'AT ' . $this->dbi->quoteString($_POST['item_execute_at']) . ' ';
} else {
- $GLOBALS['errors'][] = __('You must provide a valid execution time for the event.');
+ $this->errors[] = __('You must provide a valid execution time for the event.');
}
} else {
- $GLOBALS['errors'][] = __('You must provide a valid type for the event.');
+ $this->errors[] = __('You must provide a valid type for the event.');
}
$query .= 'ON COMPLETION ';
@@ -329,7 +331,7 @@ class Events
if (! empty($_POST['item_definition'])) {
$query .= $_POST['item_definition'];
} else {
- $GLOBALS['errors'][] = __('You must provide an event definition.');
+ $this->errors[] = __('You must provide an event definition.');
}
return $query;
@@ -388,4 +390,9 @@ class Events
return is_string($result) ? $result : null;
}
+
+ public function getErrorCount(): int
+ {
+ return count($this->errors);
+ }
}
diff --git a/src/Database/Routines.php b/src/Database/Routines.php
index c302a636f4..655ec85884 100644
--- a/src/Database/Routines.php
+++ b/src/Database/Routines.php
@@ -58,6 +58,9 @@ class Routines
/** @var array */
public readonly array $numericOptions;
+ /** @var array */
+ private array $errors = [];
+
public function __construct(private DatabaseInterface $dbi)
{
$this->directions = ['IN', 'OUT', 'INOUT'];
@@ -74,11 +77,11 @@ class Routines
$routineQuery = $this->getQueryFromRequest();
// set by getQueryFromRequest()
- if ($GLOBALS['errors'] === []) {
+ if ($this->errors === []) {
// Execute the created query
if (! empty($_POST['editor_process_edit'])) {
if (! in_array($_POST['item_original_type'], ['PROCEDURE', 'FUNCTION'], true)) {
- $GLOBALS['errors'][] = sprintf(
+ $this->errors[] = sprintf(
__('Invalid routine type: "%s"'),
htmlspecialchars($_POST['item_original_type']),
);
@@ -97,7 +100,7 @@ class Routines
. ";\n";
$result = $this->dbi->tryQuery($dropRoutine);
if (! $result) {
- $GLOBALS['errors'][] = sprintf(
+ $this->errors[] = sprintf(
__('The following query has failed: "%s"'),
htmlspecialchars($dropRoutine),
)
@@ -110,10 +113,10 @@ class Routines
$createRoutine,
$privilegesBackup,
);
- if (empty($newErrors)) {
+ if ($newErrors === []) {
$sqlQuery = $dropRoutine . $routineQuery;
} else {
- $GLOBALS['errors'] = array_merge($GLOBALS['errors'], $newErrors);
+ $this->errors = array_merge($this->errors, $newErrors);
}
unset($newErrors);
@@ -123,7 +126,7 @@ class Routines
// 'Add a new routine' mode
$result = $this->dbi->tryQuery($routineQuery);
if (! $result) {
- $GLOBALS['errors'][] = sprintf(
+ $this->errors[] = sprintf(
__('The following query has failed: "%s"'),
htmlspecialchars($routineQuery),
)
@@ -141,14 +144,14 @@ class Routines
}
}
- if ($GLOBALS['errors'] !== []) {
+ if ($this->errors !== []) {
$GLOBALS['message'] = Message::error(
__(
'One or more errors have occurred while processing your request:',
),
);
$GLOBALS['message']->addHtml('');
- foreach ($GLOBALS['errors'] as $string) {
+ foreach ($this->errors as $string) {
$GLOBALS['message']->addHtml('- ' . $string . '
');
}
@@ -640,14 +643,12 @@ class Routines
string $itemType,
bool &$warnedAboutLength,
): string {
- $GLOBALS['errors'] ??= null;
-
$params = '';
$warnedAboutDir = false;
for ($i = 0, $nb = count($itemParamName); $i < $nb; $i++) {
if (empty($itemParamName[$i]) || empty($itemParamType[$i])) {
- $GLOBALS['errors'][] = __('You must provide a name and a type for each routine parameter.');
+ $this->errors[] = __('You must provide a name and a type for each routine parameter.');
break;
}
@@ -664,7 +665,7 @@ class Routines
. ' ' . $itemParamType[$i];
} elseif (! $warnedAboutDir) {
$warnedAboutDir = true;
- $GLOBALS['errors'][] = sprintf(
+ $this->errors[] = sprintf(
__('Invalid direction "%s" given for parameter.'),
htmlspecialchars($itemParamDir[$i]),
);
@@ -684,7 +685,7 @@ class Routines
) {
if (! $warnedAboutLength) {
$warnedAboutLength = true;
- $GLOBALS['errors'][] = __(
+ $this->errors[] = __(
'You must provide length/values for routine parameters'
. ' of type ENUM, SET, VARCHAR and VARBINARY.',
);
@@ -727,14 +728,12 @@ class Routines
string $query,
bool $warnedAboutLength,
): string {
- $GLOBALS['errors'] ??= null;
-
$itemReturnType = $_POST['item_returntype'] ?? null;
if ($itemReturnType !== '' && in_array($itemReturnType, Util::getSupportedDatatypes(), true)) {
$query .= 'RETURNS ' . $itemReturnType;
} else {
- $GLOBALS['errors'][] = __('You must provide a valid return type for the routine.');
+ $this->errors[] = __('You must provide a valid return type for the routine.');
}
if (
@@ -751,7 +750,7 @@ class Routines
&& preg_match('@^(ENUM|SET|VARCHAR|VARBINARY)$@i', $itemReturnType) === 1
) {
if (! $warnedAboutLength) {
- $GLOBALS['errors'][] = __(
+ $this->errors[] = __(
'You must provide length/values for routine parameters of type ENUM, SET, VARCHAR and VARBINARY.',
);
}
@@ -781,8 +780,6 @@ class Routines
*/
public function getQueryFromRequest(): string
{
- $GLOBALS['errors'] ??= null;
-
$itemType = $_POST['item_type'] ?? '';
$itemDefiner = $_POST['item_definer'] ?? '';
$itemName = $_POST['item_name'] ?? '';
@@ -806,14 +803,14 @@ class Routines
$query .= '@' . Util::backquoteCompat($arr[1], 'NONE', $doBackquote) . ' ';
} else {
- $GLOBALS['errors'][] = __('The definer must be in the "username@hostname" format!');
+ $this->errors[] = __('The definer must be in the "username@hostname" format!');
}
}
if ($itemType === 'FUNCTION' || $itemType === 'PROCEDURE') {
$query .= $itemType . ' ';
} else {
- $GLOBALS['errors'][] = sprintf(
+ $this->errors[] = sprintf(
__('Invalid routine type: "%s"'),
htmlspecialchars($itemType),
);
@@ -822,7 +819,7 @@ class Routines
if (! empty($itemName)) {
$query .= Util::backquote($itemName);
} else {
- $GLOBALS['errors'][] = __('You must provide a routine name!');
+ $this->errors[] = __('You must provide a routine name!');
}
$warnedAboutLength = false;
@@ -886,7 +883,7 @@ class Routines
if (! empty($itemDefinition)) {
$query .= $itemDefinition;
} else {
- $GLOBALS['errors'][] = __('You must provide a routine definition.');
+ $this->errors[] = __('You must provide a routine definition.');
}
return $query;
@@ -1354,4 +1351,9 @@ class Routines
return $names;
}
+
+ public function getErrorCount(): int
+ {
+ return count($this->errors);
+ }
}
diff --git a/src/Triggers/Triggers.php b/src/Triggers/Triggers.php
index f98a721293..1756d8868d 100644
--- a/src/Triggers/Triggers.php
+++ b/src/Triggers/Triggers.php
@@ -16,6 +16,7 @@ use Webmozart\Assert\Assert;
use function __;
use function array_column;
use function array_multisort;
+use function count;
use function explode;
use function htmlspecialchars;
use function in_array;
@@ -34,6 +35,9 @@ class Triggers
private const EVENTS = ['INSERT', 'UPDATE', 'DELETE'];
+ /** @var list */
+ private array $errors = [];
+
public function __construct(private DatabaseInterface $dbi)
{
}
@@ -69,7 +73,7 @@ class Triggers
$itemQuery = $this->getQueryFromRequest();
// set by getQueryFromRequest()
- if ($GLOBALS['errors'] === []) {
+ if ($this->errors === []) {
// Execute the created query
if (! empty($_POST['editor_process_edit'])) {
// Backup the old trigger, in case something goes wrong
@@ -78,7 +82,7 @@ class Triggers
$dropItem = $trigger->getDropSql();
$result = $this->dbi->tryQuery($dropItem);
if (! $result) {
- $GLOBALS['errors'][] = sprintf(
+ $this->errors[] = sprintf(
__('The following query has failed: "%s"'),
htmlspecialchars($dropItem),
)
@@ -87,7 +91,7 @@ class Triggers
} else {
$result = $this->dbi->tryQuery($itemQuery);
if (! $result) {
- $GLOBALS['errors'][] = sprintf(
+ $this->errors[] = sprintf(
__('The following query has failed: "%s"'),
htmlspecialchars($itemQuery),
)
@@ -103,7 +107,7 @@ class Triggers
// and now even the backup query does not execute!
// This should not happen, but we better handle
// this just in case.
- $GLOBALS['errors'][] = __('Sorry, we failed to restore the dropped trigger.') . '
'
+ $this->errors[] = __('Sorry, we failed to restore the dropped trigger.') . '
'
. __('The backed up query was:')
. '"' . htmlspecialchars($createItem) . '"
'
. __('MySQL said: ') . $this->dbi->getError();
@@ -122,7 +126,7 @@ class Triggers
// 'Add a new item' mode
$result = $this->dbi->tryQuery($itemQuery);
if (! $result) {
- $GLOBALS['errors'][] = sprintf(
+ $this->errors[] = sprintf(
__('The following query has failed: "%s"'),
htmlspecialchars($itemQuery),
)
@@ -140,7 +144,7 @@ class Triggers
}
}
- if ($GLOBALS['errors'] !== []) {
+ if ($this->errors !== []) {
$GLOBALS['message'] = Message::error(
''
. __(
@@ -149,7 +153,7 @@ class Triggers
. '',
);
$GLOBALS['message']->addHtml('');
- foreach ($GLOBALS['errors'] as $string) {
+ foreach ($this->errors as $string) {
$GLOBALS['message']->addHtml('- ' . $string . '
');
}
@@ -179,8 +183,6 @@ class Triggers
*/
public function getQueryFromRequest(): string
{
- $GLOBALS['errors'] ??= null;
-
$query = 'CREATE ';
if (! empty($_POST['item_definer'])) {
if (str_contains($_POST['item_definer'], '@')) {
@@ -188,7 +190,7 @@ class Triggers
$query .= 'DEFINER=' . Util::backquote($arr[0]);
$query .= '@' . Util::backquote($arr[1]) . ' ';
} else {
- $GLOBALS['errors'][] = __('The definer must be in the "username@hostname" format!');
+ $this->errors[] = __('The definer must be in the "username@hostname" format!');
}
}
@@ -196,19 +198,19 @@ class Triggers
if (! empty($_POST['item_name'])) {
$query .= Util::backquote($_POST['item_name']) . ' ';
} else {
- $GLOBALS['errors'][] = __('You must provide a trigger name!');
+ $this->errors[] = __('You must provide a trigger name!');
}
if (! empty($_POST['item_timing']) && in_array($_POST['item_timing'], $this->time, true)) {
$query .= $_POST['item_timing'] . ' ';
} else {
- $GLOBALS['errors'][] = __('You must provide a valid timing for the trigger!');
+ $this->errors[] = __('You must provide a valid timing for the trigger!');
}
if (! empty($_POST['item_event']) && in_array($_POST['item_event'], self::EVENTS, true)) {
$query .= $_POST['item_event'] . ' ';
} else {
- $GLOBALS['errors'][] = __('You must provide a valid event for the trigger!');
+ $this->errors[] = __('You must provide a valid event for the trigger!');
}
$query .= 'ON ';
@@ -218,14 +220,14 @@ class Triggers
) {
$query .= Util::backquote($_POST['item_table']);
} else {
- $GLOBALS['errors'][] = __('You must provide a valid table name!');
+ $this->errors[] = __('You must provide a valid table name!');
}
$query .= ' FOR EACH ROW ';
if (! empty($_POST['item_definition'])) {
$query .= $_POST['item_definition'];
} else {
- $GLOBALS['errors'][] = __('You must provide a trigger definition.');
+ $this->errors[] = __('You must provide a trigger definition.');
}
return $query;
@@ -274,4 +276,9 @@ class Triggers
return $tables;
}
+
+ public function getErrorCount(): int
+ {
+ return count($this->errors);
+ }
}
diff --git a/tests/unit/Database/EventsTest.php b/tests/unit/Database/EventsTest.php
index c3db69b8cb..d5d245b064 100644
--- a/tests/unit/Database/EventsTest.php
+++ b/tests/unit/Database/EventsTest.php
@@ -144,8 +144,6 @@ class EventsTest extends AbstractTestCase
#[DataProvider('providerGetQueryFromRequest')]
public function testGetQueryFromRequest(array $request, string $query, int $numErr): void
{
- $GLOBALS['errors'] = [];
-
unset($_POST);
$_POST = $request;
@@ -155,7 +153,7 @@ class EventsTest extends AbstractTestCase
DatabaseInterface::$instance = $dbi;
self::assertSame($query, $this->events->getQueryFromRequest());
- self::assertCount($numErr, $GLOBALS['errors']);
+ self::assertSame($numErr, $this->events->getErrorCount());
}
/**
diff --git a/tests/unit/Database/RoutinesTest.php b/tests/unit/Database/RoutinesTest.php
index 7d3cbfed70..2e1b37c5ec 100644
--- a/tests/unit/Database/RoutinesTest.php
+++ b/tests/unit/Database/RoutinesTest.php
@@ -36,7 +36,6 @@ class RoutinesTest extends AbstractTestCase
$config->settings['ActionLinksMode'] = 'icons';
Current::$database = 'db';
Current::$table = 'table';
- $GLOBALS['errors'] = [];
$this->routines = new Routines(DatabaseInterface::getInstance());
}
@@ -237,8 +236,6 @@ class RoutinesTest extends AbstractTestCase
{
Config::getInstance()->settings['ShowFunctionFields'] = false;
- $GLOBALS['errors'] = [];
-
$oldDbi = DatabaseInterface::getInstance();
$dbi = $this->getMockBuilder(DatabaseInterface::class)
->disableOriginalConstructor()
@@ -257,7 +254,7 @@ class RoutinesTest extends AbstractTestCase
unset($_POST);
$_POST = $request;
self::assertSame($query, $routines->getQueryFromRequest());
- self::assertCount($numErr, $GLOBALS['errors']);
+ self::assertSame($numErr, $routines->getErrorCount());
// reset
DatabaseInterface::$instance = $oldDbi;
diff --git a/tests/unit/Triggers/TriggersTest.php b/tests/unit/Triggers/TriggersTest.php
index 01ab240a3c..2c3ac4bd75 100644
--- a/tests/unit/Triggers/TriggersTest.php
+++ b/tests/unit/Triggers/TriggersTest.php
@@ -61,8 +61,6 @@ class TriggersTest extends AbstractTestCase
string $query,
int $numErr,
): void {
- $GLOBALS['errors'] = [];
-
$_POST['item_definer'] = $definer;
$_POST['item_name'] = $name;
$_POST['item_timing'] = $timing;
@@ -71,7 +69,7 @@ class TriggersTest extends AbstractTestCase
$_POST['item_definition'] = $definition;
self::assertSame($query, $this->triggers->getQueryFromRequest());
- self::assertCount($numErr, $GLOBALS['errors']);
+ self::assertSame($numErr, $this->triggers->getErrorCount());
}
/**