Address latest PHPStan findings

This commit is contained in:
Grégoire Paris
2026-02-09 23:01:51 +01:00
parent 5d5cb902cb
commit 367551fe85
22 changed files with 132 additions and 76 deletions

View File

@@ -4,6 +4,8 @@ parameters:
- src
- tests
excludePaths:
# uses a trait that is not available on the most recent versions
- src/Provider/LazySchema.php
- tests/Configuration/ConfigurationTestSource/Migrations/Version123.php
- tests/Tools/Console/legacy-config-orm/cli-config.php
ignoreErrors:
@@ -38,9 +40,6 @@ parameters:
-
message: '~Doctrine\\ORM\\Tools\\Console\\Helper\\EntityManagerHelper~'
path: src/Tools/Console/ConsoleRunner.php
-
message: '#^Usage of deprecated trait Symfony\\Component\\VarExporter\\LazyProxyTrait in class Doctrine\\Migrations\\Provider\\LazySchema\:\nsince Symfony 7\.3, use native lazy objects instead$#'
path: src/Provider/LazySchema.php
-
message: '#^Call to deprecated method setPrimaryKey\(\) of class Doctrine\\DBAL\\Schema\\Table\:\nUse \{\@see addPrimaryKeyConstraint\(\)\} instead\.$#'
paths:
@@ -48,19 +47,8 @@ parameters:
- tests/Metadata/Storage/ExistingTableMetadataStorageTest.php
- tests/Metadata/Storage/TableMetadataStorageTest.php
-
message: '#^Call to deprecated method getName\(\) of class Doctrine\\DBAL\\Schema\\Schema\.$#'
path: src/Generator/DiffGenerator.php
-
message: '#^Call to deprecated method getQuotedName\(\) of class Doctrine\\DBAL\\Schema\\AbstractAsset\:\nUse \{@see NamedObject\:\:getObjectName\(\)\} or \{@see OptionallyQualifiedName\:\:getObjectName\(\)\} followed\nby \{@see Name\:\:toSQL\(\)\} instead\.$#'
path: src/SchemaDumper.php
message: '~^Parameter #1 \$array \(list<string>\) of array_values is already a list, call has no effect\.$~'
path: tests/Generator/DiffGeneratorTest.php
# Symfony 8 forward compatibility
-
message: '~^Call to an undefined method Symfony\\Component\\Console\\Application\:\:addCommand\(\)\.$~'
path: src/Tools/Console/ConsoleRunner.php
symfony:
consoleApplicationLoader: tests/doctrine-migrations-phpstan-app.php
includes:

View File

@@ -9,6 +9,8 @@ use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Schema\AbstractAsset;
use Doctrine\DBAL\Schema\AbstractSchemaManager;
use Doctrine\DBAL\Schema\ComparatorConfig;
use Doctrine\DBAL\Schema\NamedObject;
use Doctrine\DBAL\Schema\OptionallyNamedObject;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\Generator\Exception\NoChangesDetected;
use Doctrine\Migrations\Provider\SchemaProvider;
@@ -50,7 +52,14 @@ class DiffGenerator
if ($filterExpression !== null) {
$this->dbalConfiguration->setSchemaAssetsFilter(
static function ($assetName) use ($filterExpression) {
if ($assetName instanceof AbstractAsset) {
if ($assetName instanceof NamedObject || $assetName instanceof OptionallyNamedObject) {
if ($assetName->getObjectName() === null) {
return false;
}
$assetName = $assetName->getObjectName()->toString();
} elseif ($assetName instanceof AbstractAsset) {
/** @phpstan-ignore method.deprecated */
$assetName = $assetName->getName();
}
@@ -71,8 +80,10 @@ class DiffGenerator
! method_exists($this->schemaManager, 'getSchemaSearchPaths')
&& $this->platform->supportsSchemas()
) {
/** @phpstan-ignore method.deprecated */
$defaultNamespace = $toSchema->getName();
if ($defaultNamespace !== '') {
/* @phpstan-ignore method.deprecated */
$toSchema->createNamespace($defaultNamespace);
}
}
@@ -132,7 +143,12 @@ class DiffGenerator
if ($schemaAssetsFilter !== null) {
foreach ($toSchema->getTables() as $table) {
$tableName = $table->getName();
/** @phpstan-ignore instanceof.alwaysTrue */
if ($table instanceof NamedObject) {
$tableName = $table->getObjectName()->toString();
} else {
$tableName = $table->getName();
}
if ($schemaAssetsFilter($tableName)) {
continue;

View File

@@ -30,6 +30,7 @@ use InvalidArgumentException;
use function array_change_key_case;
use function class_exists;
use function floatval;
use function method_exists;
use function round;
use function sprintf;
use function strlen;
@@ -206,8 +207,15 @@ final class TableMetadataStorage implements MetadataStorage
$comparator = $this->schemaManager->createComparator();
}
$currentTable = $this->schemaManager->introspectTable($this->configuration->getTableName());
$diff = $comparator->compareTables($currentTable, $expectedTable);
/** @phpstan-ignore function.alreadyNarrowedType */
if (method_exists($this->schemaManager, 'introspectTableByUnquotedName')) {
$currentTable = $this->schemaManager->introspectTableByUnquotedName($this->configuration->getTableName());
} else {
/** @phpstan-ignore method.deprecated */
$currentTable = $this->schemaManager->introspectTable($this->configuration->getTableName());
}
$diff = $comparator->compareTables($currentTable, $expectedTable);
return $diff->isEmpty() ? null : $diff;
}

View File

@@ -6,6 +6,7 @@ namespace Doctrine\Migrations\Metadata\Storage;
final class TableMetadataStorageConfiguration implements MetadataStorageConfiguration
{
/** @var non-empty-string */
private string $tableName = 'doctrine_migration_versions';
/** @var non-empty-string */
@@ -17,11 +18,13 @@ final class TableMetadataStorageConfiguration implements MetadataStorageConfigur
private string $executionTimeColumnName = 'execution_time';
/** @return non-empty-string */
public function getTableName(): string
{
return $this->tableName;
}
/** @param non-empty-string $tableName */
public function setTableName(string $tableName): void
{
$this->tableName = $tableName;

View File

@@ -7,7 +7,11 @@ namespace Doctrine\Migrations\Provider;
use Doctrine\DBAL\Schema\Schema;
use Symfony\Component\VarExporter\LazyProxyTrait;
/** @internal */
/**
* @internal
*
* @phpstan-ignore class.extendsFinalByPhpDoc
*/
class LazySchema extends Schema
{
use LazyProxyTrait;

View File

@@ -27,6 +27,7 @@ class LazySchemaDiffProvider implements SchemaDiffProvider
$originalSchemaManipulator = $this->originalSchemaManipulator;
if (PHP_VERSION_ID < 80400) {
/** @phpstan-ignore staticMethod.notFound */
return LazySchema::createLazyProxy(static fn () => $originalSchemaManipulator->createFromSchema());
}
@@ -41,7 +42,9 @@ class LazySchemaDiffProvider implements SchemaDiffProvider
{
$originalSchemaManipulator = $this->originalSchemaManipulator;
/** @phpstan-ignore method.notFound */
if ($fromSchema instanceof LazySchema && ! $fromSchema->isLazyObjectInitialized()) {
/** @phpstan-ignore staticMethod.notFound */
return LazySchema::createLazyProxy(static fn () => $originalSchemaManipulator->createToSchema($fromSchema));
}
@@ -70,6 +73,7 @@ class LazySchemaDiffProvider implements SchemaDiffProvider
{
if (
$toSchema instanceof LazySchema
/** @phpstan-ignore method.notFound */
&& ! $toSchema->isLazyObjectInitialized()
) {
return [];

View File

@@ -16,7 +16,6 @@ use InvalidArgumentException;
use function array_merge;
use function count;
use function implode;
use function method_exists;
use function preg_last_error;
use function preg_last_error_msg;
use function preg_match;
@@ -88,7 +87,7 @@ class SchemaDumper
if ($table instanceof NamedObject) {
$tableName = $table->getObjectName()->toSQL($this->platform);
} else {
$tableName = $table->getQuotedName($this->platform);
$tableName = $table->getName();
}
$downSql = [$this->platform->getDropTableSQL($tableName)];
@@ -124,7 +123,15 @@ class SchemaDumper
private function shouldSkipTable(Table $table, array $excludedTablesRegexes): bool
{
foreach (array_merge($excludedTablesRegexes, $this->excludedTablesRegexes) as $regex) {
if (self::pregMatch($regex, $table->getName()) !== 0) {
if (
self::pregMatch(
$regex,
/** @phpstan-ignore instanceof.alwaysTrue */
$table instanceof NamedObject ?
$table->getObjectName()->toString() :
$table->getName(),
) !== 0
) {
return true;
}
}

View File

@@ -130,9 +130,11 @@ class ConsoleRunner
return;
}
/** @phpstan-ignore function.alreadyNarrowedType */
if (method_exists(Application::class, 'addCommand')) {
$cli->addCommand(new DiffCommand($dependencyFactory));
} else {
/** @phpstan-ignore method.notFound */
$cli->add(new DiffCommand($dependencyFactory));
}
}

View File

@@ -41,7 +41,6 @@ final class DependencyFactoryTest extends MigrationTestCase
$this->connection = $this->createMock(Connection::class);
$this->entityManager = $this->createMock(EntityManager::class);
$this->entityManager
->expects(self::any())
->method('getConnection')
->willReturn($this->connection);

View File

@@ -41,7 +41,7 @@ class ConcatenationFileBuilderTest extends TestCase
$now = new DateTime('2018-09-01');
$this->platform->expects(self::any())
$this->platform
->method('getCurrentTimestampSQL')
->willReturn('CURRENT_TIMESTAMP');

View File

@@ -8,6 +8,7 @@ use Doctrine\DBAL\Configuration as DBALConfiguration;
use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Schema\AbstractSchemaManager;
use Doctrine\DBAL\Schema\Comparator;
use Doctrine\DBAL\Schema\NamedObject;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\DBAL\Schema\SchemaDiff;
use Doctrine\DBAL\Schema\Table;
@@ -50,20 +51,9 @@ class DiffGeneratorTest extends TestCase
static fn ($name): bool => $name === 'schema.table_name1',
);
$table1 = $this->createMock(Table::class);
$table1->expects(self::once())
->method('getName')
->willReturn('schema.table_name1');
$table2 = $this->createMock(Table::class);
$table2->expects(self::once())
->method('getName')
->willReturn('schema.table_name2');
$table3 = $this->createMock(Table::class);
$table3->expects(self::once())
->method('getName')
->willReturn('schema.table_name3');
$table1 = new Table('schema.table_name1');
$table2 = new Table('schema.table_name2');
$table3 = new Table('schema.table_name3');
$toSchema->expects(self::once())
->method('getTables')
@@ -223,7 +213,13 @@ class DiffGeneratorTest extends TestCase
$this->migrationDiffGenerator->generate('Version1234', null);
$filteredTableNames = array_map(static fn (Table $table) => $table->getName(), $toSchema->getTables());
$filteredTableNames = array_map(
/** @phpstan-ignore instanceof.alwaysTrue */
static fn (Table $table) => $table instanceof NamedObject ?
$table->getObjectName()->toString() :
$table->getName(),
$toSchema->getTables(),
);
self::assertSame(['some_schema.table1', 'some_schema.table2'], array_values($filteredTableNames));
}

View File

@@ -69,7 +69,7 @@ class InlineParameterFormatterTest extends TestCase
{
$connection = $this->createMock(Connection::class);
$connection->expects(self::any())
$connection
->method('getDatabasePlatform')
->willReturn(self::createStub(AbstractPlatform::class));

View File

@@ -35,6 +35,7 @@ use Psr\Log\Test\TestLogger;
use ReflectionClass;
use function class_exists;
use function method_exists;
use function sprintf;
class TableMetadataStorageTest extends TestCase
@@ -142,7 +143,13 @@ class TableMetadataStorageTest extends TestCase
$storage->ensureInitialized();
$table = $this->schemaManager->introspectTable($config->getTableName());
/** @phpstan-ignore function.alreadyNarrowedType */
if (method_exists($this->schemaManager, 'introspectTableByUnquotedName')) {
$table = $this->schemaManager->introspectTableByUnquotedName($config->getTableName());
} else {
/** @phpstan-ignore method.deprecated */
$table = $this->schemaManager->introspectTable($config->getTableName());
}
self::assertInstanceOf(StringType::class, $table->getColumn('b')->getType());
self::assertInstanceOf(DateTimeType::class, $table->getColumn('c')->getType());
@@ -193,7 +200,13 @@ class TableMetadataStorageTest extends TestCase
$storage->ensureInitialized();
$table = $this->schemaManager->introspectTable($config->getTableName());
/** @phpstan-ignore function.alreadyNarrowedType */
if (method_exists($this->schemaManager, 'introspectTableByUnquotedName')) {
$table = $this->schemaManager->introspectTableByUnquotedName($config->getTableName());
} else {
/** @phpstan-ignore method.deprecated */
$table = $this->schemaManager->introspectTable($config->getTableName());
}
self::assertInstanceOf(StringType::class, $table->getColumn('b')->getType());
self::assertInstanceOf(DateTimeType::class, $table->getColumn('c')->getType());

View File

@@ -86,7 +86,6 @@ class RollupTest extends TestCase
public function testRollupNoMigrations(): void
{
$this->repository
->expects(self::any())
->method('getMigrations')
->willReturn(new AvailableMigrationsSet([]));

View File

@@ -6,6 +6,7 @@ namespace Doctrine\Migrations\Tests;
use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Schema\AbstractSchemaManager;
use Doctrine\DBAL\Schema\Name\UnquotedIdentifierFolding;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\DBAL\Schema\Table;
use Doctrine\Migrations\Generator\Generator;
@@ -16,6 +17,8 @@ use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use RuntimeException;
use function method_exists;
class SchemaDumperTest extends TestCase
{
/** @var AbstractPlatform&MockObject */
@@ -52,10 +55,7 @@ class SchemaDumperTest extends TestCase
public function testDump(): void
{
$table = $this->createMock(Table::class);
$table->expects(self::once())
->method('getName')
->willReturn('test');
$table = new Table('test');
$schema = $this->createMock(Schema::class);
@@ -71,6 +71,12 @@ class SchemaDumperTest extends TestCase
->method('getCreateTableSQL')
->willReturn(['CREATE TABLE test']);
/** @phpstan-ignore function.alreadyNarrowedType */
if (method_exists(AbstractPlatform::class, 'getUnquotedIdentifierFolding')) {
$this->platform->method('getUnquotedIdentifierFolding')
->willReturn(UnquotedIdentifierFolding::NONE);
}
$this->platform->expects(self::once())
->method('getDropTableSQL')
->willReturn('DROP TABLE test');
@@ -96,10 +102,7 @@ class SchemaDumperTest extends TestCase
$this->expectException(RuntimeException::class);
$this->expectExceptionMessage('Your database schema does not contain any tables.');
$table = $this->createMock(Table::class);
$table->expects(self::atLeastOnce())
->method('getName')
->willReturn('skipped_table_name');
$table = new Table('skipped_table_name');
$schema = $this->createMock(Schema::class);
@@ -131,10 +134,7 @@ class SchemaDumperTest extends TestCase
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessageMatches('/Internal PCRE error/');
$table = $this->createMock(Table::class);
$table->expects(self::atLeastOnce())
->method('getName')
->willReturn('other_skipped_table_name');
$table = new Table('other_skipped_table_name');
$schema = $this->createMock(Schema::class);
@@ -154,10 +154,7 @@ class SchemaDumperTest extends TestCase
$this->expectException(RuntimeException::class);
$this->expectExceptionMessage('Your database schema does not contain any tables.');
$table = $this->createMock(Table::class);
$table->expects(self::atLeastOnce())
->method('getName')
->willReturn('other_skipped_table_name');
$table = new Table('other_skipped_table_name');
$schema = $this->createMock(Schema::class);

View File

@@ -201,7 +201,7 @@ final class DiffCommandTest extends TestCase
->method('getConfiguration')
->willReturn($this->configuration);
$this->dependencyFactory->expects(self::any())
$this->dependencyFactory
->method('getDiffGenerator')
->willReturn($this->migrationDiffGenerator);

View File

@@ -379,7 +379,7 @@ class DoctrineCommandTest extends MigrationTestCase
$command->setHelperSet(new HelperSet(['question' => new QuestionHelper()]));
$commandTester = new CommandTester($command);
$commandTester->setInputs([1]);
$commandTester->setInputs(['1']);
$commandTester->execute([]);
}
}

View File

@@ -72,7 +72,7 @@ final class DumpSchemaCommandTest extends TestCase
->with('FooNs')
->willReturn('FooNs\\Version1234');
$this->dependencyFactory->expects(self::any())
$this->dependencyFactory
->method('getClassNameGenerator')
->willReturn($classNameGenerator);
@@ -146,15 +146,15 @@ final class DumpSchemaCommandTest extends TestCase
$this->migrationRepository = $this->createMock(FilesystemMigrationsRepository::class);
$this->schemaDumper = $this->createMock(SchemaDumper::class);
$this->dependencyFactory->expects(self::any())
$this->dependencyFactory
->method('getSchemaDumper')
->willReturn($this->schemaDumper);
$this->dependencyFactory->expects(self::any())
$this->dependencyFactory
->method('getConfiguration')
->willReturn($this->configuration);
$this->dependencyFactory->expects(self::any())
$this->dependencyFactory
->method('getMigrationRepository')
->willReturn($this->migrationRepository);

View File

@@ -101,7 +101,7 @@ final class GenerateCommandTest extends TestCase
$this->dependencyFactory = $this->createMock(DependencyFactory::class);
$this->migrationGenerator = $this->createMock(Generator::class);
$this->dependencyFactory->expects(self::any())
$this->dependencyFactory
->method('getConfiguration')
->willReturn($this->configuration);

View File

@@ -43,6 +43,7 @@ use Symfony\Component\Console\Tester\CommandTester;
use function class_exists;
use function getcwd;
use function in_array;
use function method_exists;
use function sprintf;
use function trim;
@@ -292,8 +293,16 @@ class MigrateCommandTest extends MigrationTestCase
$this->migrateCommandTester->execute([], ['interactive' => false]);
$refreshedTable = $this->connection->createSchemaManager()
->introspectTable($this->metadataConfiguration->getTableName());
$schemaManager = $this->connection->createSchemaManager();
/** @phpstan-ignore function.alreadyNarrowedType */
if (method_exists($schemaManager, 'introspectTableByUnquotedName')) {
$refreshedTable = $this->connection->createSchemaManager()
->introspectTableByUnquotedName($this->metadataConfiguration->getTableName());
} else {
/** @phpstan-ignore method.deprecated */
$refreshedTable = $schemaManager
->introspectTable($this->metadataConfiguration->getTableName());
}
self::assertFalse($refreshedTable->hasColumn('extra'));
}
@@ -306,8 +315,16 @@ class MigrateCommandTest extends MigrationTestCase
$this->migrateCommandTester->execute([]);
$refreshedTable = $this->connection->createSchemaManager()
->introspectTable($this->metadataConfiguration->getTableName());
$schemaManager = $this->connection->createSchemaManager();
/** @phpstan-ignore function.alreadyNarrowedType */
if (method_exists($schemaManager, 'introspectTableByUnquotedName')) {
$refreshedTable = $this->connection->createSchemaManager()
->introspectTableByUnquotedName($this->metadataConfiguration->getTableName());
} else {
/** @phpstan-ignore method.deprecated */
$refreshedTable = $schemaManager
->introspectTable($this->metadataConfiguration->getTableName());
}
self::assertTrue($refreshedTable->hasColumn('extra'));
}
@@ -500,8 +517,15 @@ class MigrateCommandTest extends MigrationTestCase
private function alterMetadataTable(): void
{
$schemaManager = $this->connection->createSchemaManager();
$originalTable = $schemaManager
->introspectTable($this->metadataConfiguration->getTableName());
/** @phpstan-ignore function.alreadyNarrowedType */
if (method_exists($schemaManager, 'introspectTableByUnquotedName')) {
$originalTable = $this->connection->createSchemaManager()
->introspectTableByUnquotedName($this->metadataConfiguration->getTableName());
} else {
/** @phpstan-ignore method.deprecated */
$originalTable = $schemaManager
->introspectTable($this->metadataConfiguration->getTableName());
}
$modifiedTable = clone $originalTable;
$modifiedTable->addColumn('extra', Types::STRING, ['notnull' => false]);

View File

@@ -53,12 +53,10 @@ final class MigrationPlanCalculatorTest extends TestCase
$migrationList = new AvailableMigrationsSet($m);
$this->migrationRepository
->expects(self::any())
->method('hasMigration')
->willReturnCallback(static fn ($version): bool => isset($m[$version]));
$this->migrationRepository
->expects(self::any())
->method('getMigrations')
->willReturn($migrationList);
}

View File

@@ -48,7 +48,6 @@ final class MigrationStatusCalculatorTest extends TestCase
$e1 = new ExecutedMigration(new Version('A'));
$this->migrationPlanCalculator
->expects(self::any())
->method('getMigrations')
->willReturn(new AvailableMigrationsList([$m1, $m2, $m3]));
@@ -71,7 +70,6 @@ final class MigrationStatusCalculatorTest extends TestCase
$e3 = new ExecutedMigration(new Version('C'));
$this->migrationPlanCalculator
->expects(self::any())
->method('getMigrations')
->willReturn(new AvailableMigrationsList([$a1]));