Add static analysis stub for PSR ContainerInterface

Signed-off-by: Maurício Meneghini Fauth <mauricio@mfauth.net>
This commit is contained in:
Maurício Meneghini Fauth 2025-07-15 18:11:24 -03:00
parent 4ccd84bc02
commit a82b8e22a8
No known key found for this signature in database
GPG Key ID: 6A16FD38AFC89CC8
26 changed files with 43 additions and 44 deletions

1
.gitattributes vendored
View File

@ -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

5
.phpstorm.meta.php Normal file
View File

@ -0,0 +1,5 @@
<?php
namespace PHPSTORM_META {
override(\Psr\Container\ContainerInterface::get(0), map(['@']));
}

View File

@ -99,7 +99,8 @@ return [
'arguments' => ['@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,

View File

@ -13,6 +13,7 @@ parameters:
bootstrapFiles:
- tests/phpstan-constants.php
stubFiles:
- tests/stubs/psr.stub
- tests/stubs/uploadprogress.stub
excludePaths:
- app/cache/*

View File

@ -34,6 +34,7 @@
</projectFiles>
<stubs>
<file name="tests/stubs/psr.stub"/>
<file name="tests/stubs/uploadprogress.stub"/>
</stubs>

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -1117,7 +1117,6 @@ class Results
$urlParamsFullText['pftext'] = self::DISPLAY_FULL_TEXT;
}
/** @var ThemeManager $themeManager */
$themeManager = ContainerBuilder::getContainer()->get(ThemeManager::class);
$tmpImage = '<img class="fulltext" src="'

View File

@ -208,7 +208,6 @@ class Header
/** @return mixed[] */
public function getDisplay(): array
{
/** @var ThemeManager $themeManager */
$themeManager = ContainerBuilder::getContainer()->get(ThemeManager::class);
$theme = $themeManager->theme;

View File

@ -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);
}

View File

@ -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

View File

@ -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();

View File

@ -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);

View File

@ -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();

View File

@ -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();

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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();

View File

@ -164,7 +164,6 @@ class ResponseRenderer
return self::$instance;
}
/** @var Console $console */
$console = ContainerBuilder::getContainer()->get(Console::class);
$config = Config::getInstance();

View File

@ -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);
}

13
tests/stubs/psr.stub Normal file
View File

@ -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;
}
}

View File

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

View File

@ -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);