diff --git a/.gitattributes b/.gitattributes
index f6ab619e88..f5ca857d11 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -3,6 +3,7 @@
.gitattributes export-ignore
.gitignore export-ignore
.github export-ignore
+.phpstorm.meta.php export-ignore
.scrutinizer.yml export-ignore
.jshintrc export-ignore
.stylelintrc.json export-ignore
diff --git a/.phpstorm.meta.php b/.phpstorm.meta.php
new file mode 100644
index 0000000000..4060ecee36
--- /dev/null
+++ b/.phpstorm.meta.php
@@ -0,0 +1,5 @@
+ ['@http_request', '@relation', '@template', '@config'],
],
'events' => ['class' => Events::class, 'arguments' => ['@dbi']],
- 'export' => ['class' => Export::class, 'arguments' => ['@dbi']],
+ Export::class => ['class' => Export::class, 'arguments' => ['@dbi']],
+ 'export' => Export::class,
'export_options' => [
'class' => Options::class,
'arguments' => ['@relation', '@export_template_model'],
@@ -239,7 +240,8 @@ return [
'arguments' => ['$dbi' => '@dbi'],
],
AuthenticationPluginFactory::class => ['class' => AuthenticationPluginFactory::class],
- 'relation' => ['class' => Relation::class, 'arguments' => ['$dbi' => '@dbi', '$config' => '@config']],
+ Relation::class => ['class' => Relation::class, 'arguments' => ['$dbi' => '@dbi', '$config' => '@config']],
+ 'relation' => Relation::class,
'relation_cleanup' => ['class' => RelationCleanup::class, 'arguments' => ['@dbi', '@relation']],
'replication' => ['class' => Replication::class, 'arguments' => ['$dbi' => '@dbi']],
'replication_gui' => [
@@ -293,7 +295,8 @@ return [
],
'table_maintenance' => ['class' => PhpMyAdmin\Table\Maintenance::class, 'arguments' => ['$dbi' => '@dbi']],
'table_search' => ['class' => Search::class, 'arguments' => ['$dbi' => '@dbi']],
- 'template' => ['class' => Template::class, 'arguments' => ['$config' => '@config']],
+ Template::class => ['class' => Template::class, 'arguments' => ['$config' => '@config']],
+ 'template' => Template::class,
ThemeManager::class => ['class' => ThemeManager::class],
'tracking' => [
'class' => Tracking::class,
@@ -309,8 +312,8 @@ return [
'class' => TrackingChecker::class,
'arguments' => ['$dbi' => '@dbi', '$relation' => '@relation'],
],
- 'transformations' => ['class' => Transformations::class, 'arguments' => ['@dbi', '@relation']],
- Transformations::class => 'transformations',
+ Transformations::class => ['class' => Transformations::class, 'arguments' => ['@dbi', '@relation']],
+ 'transformations' => Transformations::class,
'triggers' => ['class' => Triggers::class, 'arguments' => ['@dbi']],
'user_password' => [
'class' => UserPassword::class,
diff --git a/phpstan.neon.dist b/phpstan.neon.dist
index 77840d8aa4..34262df8d2 100644
--- a/phpstan.neon.dist
+++ b/phpstan.neon.dist
@@ -13,6 +13,7 @@ parameters:
bootstrapFiles:
- tests/phpstan-constants.php
stubFiles:
+ - tests/stubs/psr.stub
- tests/stubs/uploadprogress.stub
excludePaths:
- app/cache/*
diff --git a/psalm.xml b/psalm.xml
index 717b1adfda..46c5e6fd58 100644
--- a/psalm.xml
+++ b/psalm.xml
@@ -34,6 +34,7 @@
+
diff --git a/src/Application.php b/src/Application.php
index c1786276cd..ca99d9cd06 100644
--- a/src/Application.php
+++ b/src/Application.php
@@ -51,7 +51,6 @@ use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Throwable;
-use function assert;
use function sprintf;
readonly class Application
@@ -62,10 +61,7 @@ readonly class Application
public static function init(): self
{
- $application = ContainerBuilder::getContainer()->get(self::class);
- assert($application instanceof self);
-
- return $application;
+ return ContainerBuilder::getContainer()->get(self::class);
}
public function run(bool $isSetupPage = false): void
diff --git a/src/Controllers/Export/ExportController.php b/src/Controllers/Export/ExportController.php
index 266d71aed6..d14394203d 100644
--- a/src/Controllers/Export/ExportController.php
+++ b/src/Controllers/Export/ExportController.php
@@ -289,7 +289,6 @@ final readonly class ExportController implements InvocableController
Current::$message = Message::error(
__('No tables found in database.'),
);
- /** @var DatabaseExportController $controller */
$controller = ContainerBuilder::getContainer()->get(DatabaseExportController::class);
return $controller($request);
diff --git a/src/Controllers/Table/IndexesController.php b/src/Controllers/Table/IndexesController.php
index d238826dd5..9aa0b3d507 100644
--- a/src/Controllers/Table/IndexesController.php
+++ b/src/Controllers/Table/IndexesController.php
@@ -159,7 +159,6 @@ final readonly class IndexesController implements InvocableController
return $this->response->response();
}
- /** @var StructureController $controller */
$controller = ContainerBuilder::getContainer()->get(StructureController::class);
return $controller($request);
diff --git a/src/Controllers/View/CreateController.php b/src/Controllers/View/CreateController.php
index 7bca872cb0..cbed23fccd 100644
--- a/src/Controllers/View/CreateController.php
+++ b/src/Controllers/View/CreateController.php
@@ -219,7 +219,6 @@ final class CreateController implements InvocableController
if ($ajaxdialog) {
Current::$message = Message::success();
- /** @var StructureController $controller */
$controller = ContainerBuilder::getContainer()->get(StructureController::class);
return $controller($request);
diff --git a/src/Display/Results.php b/src/Display/Results.php
index ac686d25ac..0db05567c2 100644
--- a/src/Display/Results.php
+++ b/src/Display/Results.php
@@ -1117,7 +1117,6 @@ class Results
$urlParamsFullText['pftext'] = self::DISPLAY_FULL_TEXT;
}
- /** @var ThemeManager $themeManager */
$themeManager = ContainerBuilder::getContainer()->get(ThemeManager::class);
$tmpImage = ': array
{
- /** @var ThemeManager $themeManager */
$themeManager = ContainerBuilder::getContainer()->get(ThemeManager::class);
$theme = $themeManager->theme;
diff --git a/src/Http/Handler/QueueRequestHandler.php b/src/Http/Handler/QueueRequestHandler.php
index 4dfeba924d..d216b90bb4 100644
--- a/src/Http/Handler/QueueRequestHandler.php
+++ b/src/Http/Handler/QueueRequestHandler.php
@@ -11,7 +11,6 @@ use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use function array_shift;
-use function assert;
final class QueueRequestHandler implements RequestHandlerInterface
{
@@ -37,7 +36,6 @@ final class QueueRequestHandler implements RequestHandlerInterface
}
$middleware = $this->container->get(array_shift($this->middleware));
- assert($middleware instanceof MiddlewareInterface);
return $middleware->process($request, $this);
}
diff --git a/src/Http/Middleware/Authentication.php b/src/Http/Middleware/Authentication.php
index cb861d4e66..ea4f595a17 100644
--- a/src/Http/Middleware/Authentication.php
+++ b/src/Http/Middleware/Authentication.php
@@ -46,7 +46,6 @@ final class Authentication implements MiddlewareInterface
return $handler->handle($request);
}
- /** @var AuthenticationPluginFactory $authPluginFactory */
$authPluginFactory = ContainerBuilder::getContainer()->get(AuthenticationPluginFactory::class);
try {
$authPlugin = $authPluginFactory->create();
@@ -93,8 +92,7 @@ final class Authentication implements MiddlewareInterface
}
// Relation should only be initialized after the connection is successful
- /** @var Relation $relation */
- $relation = ContainerBuilder::getContainer()->get('relation');
+ $relation = ContainerBuilder::getContainer()->get(Relation::class);
$relation->initRelationParamsCache();
// Tracker can only be activated after the relation has been initialized
diff --git a/src/Http/Middleware/LanguageAndThemeCookieSaving.php b/src/Http/Middleware/LanguageAndThemeCookieSaving.php
index b63b969437..11b1887ed6 100644
--- a/src/Http/Middleware/LanguageAndThemeCookieSaving.php
+++ b/src/Http/Middleware/LanguageAndThemeCookieSaving.php
@@ -22,7 +22,6 @@ final class LanguageAndThemeCookieSaving implements MiddlewareInterface
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
$this->config->setCookie('pma_lang', Current::$lang);
- /** @var ThemeManager $themeManager */
$themeManager = ContainerBuilder::getContainer()->get(ThemeManager::class);
$themeManager->setThemeCookie();
diff --git a/src/Http/Middleware/MinimumCommonRedirection.php b/src/Http/Middleware/MinimumCommonRedirection.php
index ebdc5ac966..e4158aaf53 100644
--- a/src/Http/Middleware/MinimumCommonRedirection.php
+++ b/src/Http/Middleware/MinimumCommonRedirection.php
@@ -32,7 +32,6 @@ final class MinimumCommonRedirection implements MiddlewareInterface
}
$container = ContainerBuilder::getContainer();
- /** @var ThemeManager $themeManager */
$themeManager = $container->get(ThemeManager::class);
$this->config->loadUserPreferences($themeManager, true);
assert($request instanceof ServerRequest);
diff --git a/src/Http/Middleware/SetupPageRedirection.php b/src/Http/Middleware/SetupPageRedirection.php
index fecdd94392..60356ccce9 100644
--- a/src/Http/Middleware/SetupPageRedirection.php
+++ b/src/Http/Middleware/SetupPageRedirection.php
@@ -35,7 +35,6 @@ final class SetupPageRedirection implements MiddlewareInterface
}
$container = ContainerBuilder::getContainer();
- /** @var ThemeManager $themeManager */
$themeManager = $container->get(ThemeManager::class);
$this->config->loadUserPreferences($themeManager, true);
$this->setupPageBootstrap();
diff --git a/src/Http/Middleware/ThemeInitialization.php b/src/Http/Middleware/ThemeInitialization.php
index 332698e0ee..944784d0cd 100644
--- a/src/Http/Middleware/ThemeInitialization.php
+++ b/src/Http/Middleware/ThemeInitialization.php
@@ -15,7 +15,6 @@ final class ThemeInitialization implements MiddlewareInterface
{
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
- /** @var ThemeManager $themeManager */
$themeManager = ContainerBuilder::getContainer()->get(ThemeManager::class);
$themeManager->initializeTheme();
diff --git a/src/Http/Middleware/UrlRedirection.php b/src/Http/Middleware/UrlRedirection.php
index 76a7e6c190..8e35d9cf75 100644
--- a/src/Http/Middleware/UrlRedirection.php
+++ b/src/Http/Middleware/UrlRedirection.php
@@ -32,7 +32,6 @@ final class UrlRedirection implements MiddlewareInterface
}
$container = ContainerBuilder::getContainer();
- /** @var ThemeManager $themeManager */
$themeManager = $container->get(ThemeManager::class);
$this->config->loadUserPreferences($themeManager, true);
diff --git a/src/Http/Middleware/UserPreferencesLoading.php b/src/Http/Middleware/UserPreferencesLoading.php
index 06dfa82d42..ccf279cc08 100644
--- a/src/Http/Middleware/UserPreferencesLoading.php
+++ b/src/Http/Middleware/UserPreferencesLoading.php
@@ -20,7 +20,6 @@ final class UserPreferencesLoading implements MiddlewareInterface
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
- /** @var ThemeManager $themeManager */
$themeManager = ContainerBuilder::getContainer()->get(ThemeManager::class);
$this->config->loadUserPreferences($themeManager);
diff --git a/src/Navigation/Navigation.php b/src/Navigation/Navigation.php
index 81a9be561d..ec34941026 100644
--- a/src/Navigation/Navigation.php
+++ b/src/Navigation/Navigation.php
@@ -262,7 +262,6 @@ class Navigation
/** @return string Logo source */
private function getLogoSource(): string
{
- /** @var ThemeManager $themeManager */
$themeManager = ContainerBuilder::getContainer()->get(ThemeManager::class);
$theme = $themeManager->theme;
diff --git a/src/Plugins.php b/src/Plugins.php
index e692124d22..4b03f9d2c2 100644
--- a/src/Plugins.php
+++ b/src/Plugins.php
@@ -5,7 +5,9 @@ declare(strict_types=1);
namespace PhpMyAdmin;
use FilesystemIterator;
+use PhpMyAdmin\ConfigStorage\Relation;
use PhpMyAdmin\Container\ContainerBuilder;
+use PhpMyAdmin\Export\Export;
use PhpMyAdmin\Html\MySQLDocumentation;
use PhpMyAdmin\Import\ImportSettings;
use PhpMyAdmin\Plugins\ExportPlugin;
@@ -74,9 +76,9 @@ class Plugins
/** @psalm-suppress MixedMethodCall */
return new $class(
- $container->get('relation'),
- $container->get('export'),
- $container->get('transformations'),
+ $container->get(Relation::class),
+ $container->get(Export::class),
+ $container->get(Transformations::class),
);
}
@@ -154,9 +156,9 @@ class Plugins
if ($type === 'Export' && is_subclass_of($class, ExportPlugin::class)) {
$container = ContainerBuilder::getContainer();
$plugins[] = new $class(
- $container->get('relation'),
- $container->get('export'),
- $container->get('transformations'),
+ $container->get(Relation::class),
+ $container->get(Export::class),
+ $container->get(Transformations::class),
);
} elseif ($type === 'Import' && is_subclass_of($class, ImportPlugin::class)) {
$plugins[] = new $class();
diff --git a/src/ResponseRenderer.php b/src/ResponseRenderer.php
index 846e811368..a3cef00fab 100644
--- a/src/ResponseRenderer.php
+++ b/src/ResponseRenderer.php
@@ -164,7 +164,6 @@ class ResponseRenderer
return self::$instance;
}
- /** @var Console $console */
$console = ContainerBuilder::getContainer()->get(Console::class);
$config = Config::getInstance();
diff --git a/src/Routing/Routing.php b/src/Routing/Routing.php
index 2ca6ef6cc4..a308bc58a0 100644
--- a/src/Routing/Routing.php
+++ b/src/Routing/Routing.php
@@ -29,7 +29,6 @@ use Psr\Container\ContainerInterface;
use function __;
use function array_pop;
-use function assert;
use function explode;
use function file_exists;
use function file_put_contents;
@@ -173,7 +172,6 @@ class Routing
$controllerName = $routeInfo[1];
$controller = $container->get($controllerName);
- assert($controller instanceof InvocableController);
return $controller($request->withAttribute('routeVars', $routeInfo[2]));
}
@@ -181,6 +179,7 @@ class Routing
public static function callSetupController(ServerRequest $request, ResponseFactory $responseFactory): Response
{
$route = $request->getRoute();
+ /** @psalm-var class-string<InvocableController>|null $controllerName */
$controllerName = match ($route) {
'/', '/setup' => MainController::class,
'/setup/show-config' => ShowConfigController::class,
@@ -190,8 +189,7 @@ class Routing
$container = ContainerBuilder::getContainer();
if ($controllerName === null) {
- $template = $container->get('template');
- assert($template instanceof Template);
+ $template = $container->get(Template::class);
$response = $responseFactory->createResponse(StatusCodeInterface::STATUS_NOT_FOUND);
return $response->write($template->render('error/generic', [
@@ -204,7 +202,6 @@ class Routing
}
$controller = $container->get($controllerName);
- assert($controller instanceof InvocableController);
return $controller($request);
}
diff --git a/tests/stubs/psr.stub b/tests/stubs/psr.stub
new file mode 100644
index 0000000000..156a3fc61b
--- /dev/null
+++ b/tests/stubs/psr.stub
@@ -0,0 +1,13 @@
+<?php
+
+namespace Psr\Container {
+ interface ContainerInterface
+ {
+ /**
+ * @template T of object
+ * @param class-string<T>|string $id
+ * @return ($id is class-string<T> ? T : mixed)
+ */
+ public function get(string $id): mixed;
+ }
+}
diff --git a/tests/unit/ApplicationTest.php b/tests/unit/ApplicationTest.php
index 5397e2bba1..0804f1e01b 100644
--- a/tests/unit/ApplicationTest.php
+++ b/tests/unit/ApplicationTest.php
@@ -19,7 +19,6 @@ final class ApplicationTest extends AbstractTestCase
public function testInit(): void
{
$application = ContainerBuilder::getContainer()->get(Application::class);
- self::assertInstanceOf(Application::class, $application);
self::assertSame($application, Application::init());
}
diff --git a/tests/unit/Controllers/Export/ExportControllerTest.php b/tests/unit/Controllers/Export/ExportControllerTest.php
index b06a6e83df..dfe5201e7f 100644
--- a/tests/unit/Controllers/Export/ExportControllerTest.php
+++ b/tests/unit/Controllers/Export/ExportControllerTest.php
@@ -504,8 +504,7 @@ final class ExportControllerTest extends AbstractTestCase
SQL;
$container = ContainerBuilder::getContainer();
- $export = $container->get('export');
- self::assertInstanceOf(Export::class, $export);
+ $export = $container->get(Export::class);
(new ReflectionProperty(Export::class, 'dbi'))->setValue($export, $dbi);
$exportController = new ExportController(new ResponseRenderer(), $export, ResponseFactory::create(), $config);
@@ -658,8 +657,7 @@ final class ExportControllerTest extends AbstractTestCase
SQL;
$container = ContainerBuilder::getContainer();
- $export = $container->get('export');
- self::assertInstanceOf(Export::class, $export);
+ $export = $container->get(Export::class);
(new ReflectionProperty(Export::class, 'dbi'))->setValue($export, $dbi);
$exportController = new ExportController(new ResponseRenderer(), $export, ResponseFactory::create(), $config);
)