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()); } /**