Skip to content

Commit 23ae208

Browse files
committed
Make SchemaTool use the new DBAL API
1 parent 64444dc commit 23ae208

File tree

3 files changed

+162
-80
lines changed

3 files changed

+162
-80
lines changed

phpstan-baseline.neon

Lines changed: 2 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -3150,7 +3150,7 @@ parameters:
31503150
Use \{@see getPrimaryKeyConstraint\(\)\} instead\.$#
31513151
'''
31523152
identifier: method.deprecated
3153-
count: 1
3153+
count: 2
31543154
path: src/Tools/SchemaTool.php
31553155

31563156
-
@@ -3255,12 +3255,6 @@ parameters:
32553255
count: 1
32563256
path: src/Tools/SchemaTool.php
32573257

3258-
-
3259-
message: '#^Method Doctrine\\ORM\\Tools\\SchemaTool\:\:getIndexColumns\(\) has parameter \$class with generic class Doctrine\\ORM\\Mapping\\ClassMetadata but does not specify its types\: T$#'
3260-
identifier: missingType.generics
3261-
count: 1
3262-
path: src/Tools/SchemaTool.php
3263-
32643258
-
32653259
message: '#^Method Doctrine\\ORM\\Tools\\SchemaTool\:\:getSchemaFromMetadata\(\) has parameter \$classes with generic class Doctrine\\ORM\\Mapping\\ClassMetadata but does not specify its types\: T$#'
32663260
identifier: missingType.generics
@@ -3291,38 +3285,14 @@ parameters:
32913285
count: 1
32923286
path: src/Tools/SchemaTool.php
32933287

3294-
-
3295-
message: '#^Parameter \#1 \$columnNames of method Doctrine\\DBAL\\Schema\\Table\:\:addIndex\(\) expects non\-empty\-list\<string\>, list\<string\> given\.$#'
3296-
identifier: argument.type
3297-
count: 1
3298-
path: src/Tools/SchemaTool.php
3299-
3300-
-
3301-
message: '#^Parameter \#1 \$columnNames of method Doctrine\\DBAL\\Schema\\Table\:\:addUniqueIndex\(\) expects non\-empty\-list\<string\>, array\<string\> given\.$#'
3302-
identifier: argument.type
3303-
count: 1
3304-
path: src/Tools/SchemaTool.php
3305-
33063288
-
33073289
message: '#^Parameter \#1 \$columnNames of method Doctrine\\DBAL\\Schema\\Table\:\:setPrimaryKey\(\) expects non\-empty\-list\<string\>, array\<string\> given\.$#'
33083290
identifier: argument.type
33093291
count: 1
33103292
path: src/Tools/SchemaTool.php
33113293

33123294
-
3313-
message: '#^Parameter \#1 \$value of static method Doctrine\\DBAL\\Schema\\Name\\Identifier\:\:unquoted\(\) expects non\-empty\-string, string given\.$#'
3314-
identifier: argument.type
3315-
count: 1
3316-
path: src/Tools/SchemaTool.php
3317-
3318-
-
3319-
message: '#^Parameter \#2 \$columnNames of class Doctrine\\DBAL\\Schema\\PrimaryKeyConstraint constructor expects non\-empty\-list\<Doctrine\\DBAL\\Schema\\Name\\UnqualifiedName\>, list\<Doctrine\\DBAL\\Schema\\Name\\UnqualifiedName\> given\.$#'
3320-
identifier: argument.type
3321-
count: 1
3322-
path: src/Tools/SchemaTool.php
3323-
3324-
-
3325-
message: '#^Parameter \#2 \$columns of class Doctrine\\DBAL\\Schema\\Index constructor expects non\-empty\-list\<string\>, list\<string\> given\.$#'
3295+
message: '#^Parameter \#1 \$firstColumnName of method Doctrine\\DBAL\\Schema\\PrimaryKeyConstraintEditor\:\:setUnquotedColumnNames\(\) expects non\-empty\-string, string given\.$#'
33263296
identifier: argument.type
33273297
count: 1
33283298
path: src/Tools/SchemaTool.php
@@ -3339,12 +3309,6 @@ parameters:
33393309
count: 1
33403310
path: src/Tools/SchemaTool.php
33413311

3342-
-
3343-
message: '#^Property Doctrine\\ORM\\Tools\\SchemaTool\:\:\$schemaManager with generic class Doctrine\\DBAL\\Schema\\AbstractSchemaManager does not specify its types\: T$#'
3344-
identifier: missingType.generics
3345-
count: 1
3346-
path: src/Tools/SchemaTool.php
3347-
33483312
-
33493313
message: '#^Access to an undefined property Doctrine\\ORM\\Mapping\\ManyToManyInverseSideMapping\|Doctrine\\ORM\\Mapping\\ManyToManyOwningSideMapping\|Doctrine\\ORM\\Mapping\\ManyToOneAssociationMapping\|Doctrine\\ORM\\Mapping\\OneToManyAssociationMapping\|Doctrine\\ORM\\Mapping\\OneToOneInverseSideMapping\|Doctrine\\ORM\\Mapping\\OneToOneOwningSideMapping\:\:\$inversedBy\.$#'
33503314
identifier: property.notFound

src/Tools/SchemaTool.php

Lines changed: 85 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
use Doctrine\DBAL\Schema\ForeignKeyConstraintEditor;
1313
use Doctrine\DBAL\Schema\Index;
1414
use Doctrine\DBAL\Schema\Index\IndexedColumn;
15-
use Doctrine\DBAL\Schema\Name\Identifier;
15+
use Doctrine\DBAL\Schema\IndexEditor;
1616
use Doctrine\DBAL\Schema\Name\UnqualifiedName;
1717
use Doctrine\DBAL\Schema\PrimaryKeyConstraint;
1818
use Doctrine\DBAL\Schema\Schema;
@@ -38,6 +38,7 @@
3838
use function array_flip;
3939
use function array_intersect_key;
4040
use function array_map;
41+
use function array_values;
4142
use function assert;
4243
use function class_exists;
4344
use function count;
@@ -60,6 +61,7 @@ class SchemaTool
6061

6162
private readonly AbstractPlatform $platform;
6263
private readonly QuoteStrategy $quoteStrategy;
64+
/** @var AbstractSchemaManager<AbstractPlatform> */
6365
private readonly AbstractSchemaManager $schemaManager;
6466

6567
/**
@@ -128,9 +130,10 @@ private function processingNotRequired(
128130
/**
129131
* Resolves fields in index mapping to column names
130132
*
131-
* @param mixed[] $indexData index or unique constraint data
133+
* @param ClassMetadata<object> $class
134+
* @param mixed[] $indexData index or unique constraint data
132135
*
133-
* @return list<string> Column names from combined fields and columns mappings
136+
* @return non-empty-list<non-empty-string> Column names from combined fields and columns mappings
134137
*/
135138
private function getIndexColumns(ClassMetadata $class, array $indexData): array
136139
{
@@ -167,6 +170,13 @@ private function getIndexColumns(ClassMetadata $class, array $indexData): array
167170
}
168171
}
169172

173+
if ($columns === []) {
174+
throw MappingException::invalidIndexConfiguration(
175+
(string) $class,
176+
$indexData['name'] ?? 'unnamed',
177+
);
178+
}
179+
170180
return $columns;
171181
}
172182

@@ -314,17 +324,13 @@ public function getSchemaFromMetadata(array $classes): Schema
314324
}
315325
}
316326

317-
if (! $table->hasIndex('primary')) {
318-
self::addPrimaryKeyConstraint($table, $pkColumns);
319-
}
327+
$primaryKey = $this->getPrimaryKeyConstraint($table) ?? $this->addPrimaryKeyConstraint($table, $pkColumns);
320328

321329
// there can be unique indexes automatically created for join column
322330
// if join column is also primary key we should keep only primary key on this column
323331
// so, remove indexes overruled by primary key
324-
$primaryKey = $table->getIndex('primary');
325-
326332
foreach ($table->getIndexes() as $idxKey => $existingIndex) {
327-
if ($existingIndex !== $primaryKey && $primaryKey->spansColumns(self::getIndexedColumns($existingIndex))) {
333+
if ($idxKey !== 'primary' && $this->doesIndexOverlapWithPrimaryKey($existingIndex, $primaryKey)) {
328334
$table->dropIndex($idxKey);
329335
}
330336
}
@@ -346,7 +352,7 @@ public function getSchemaFromMetadata(array $classes): Schema
346352

347353
if (isset($class->table['uniqueConstraints'])) {
348354
foreach ($class->table['uniqueConstraints'] as $indexName => $indexData) {
349-
$uniqIndex = new Index('tmp__' . $indexName, $this->getIndexColumns($class, $indexData), true, false, [], $indexData['options'] ?? []);
355+
$uniqIndex = $this->createIndexForComparison('tmp__' . $indexName, $this->getIndexColumns($class, $indexData), $indexData['options'] ?? []);
350356

351357
foreach ($table->getIndexes() as $tableIndexName => $tableIndex) {
352358
if ($tableIndex->isFulfilledBy($uniqIndex)) {
@@ -872,11 +878,7 @@ public function getDropSchemaSQL(array $classes): array
872878
}
873879

874880
foreach ($schema->getTables() as $table) {
875-
if (method_exists($table, 'getPrimaryKeyConstraint')) {
876-
$primaryKey = $table->getPrimaryKeyConstraint();
877-
} else {
878-
$primaryKey = $table->getPrimaryKey();
879-
}
881+
$primaryKey = $this->getPrimaryKeyConstraint($table);
880882

881883
if ($primaryKey === null) {
882884
continue;
@@ -969,29 +971,84 @@ private function createSchemaForComparison(Schema $toSchema): Schema
969971
}
970972
}
971973

972-
/** @param string[] $primaryKeyColumns */
973-
private function addPrimaryKeyConstraint(Table $table, array $primaryKeyColumns): void
974+
private function getPrimaryKeyConstraint(Table $table): PrimaryKeyConstraint|Index|null
974975
{
975-
if (class_exists(PrimaryKeyConstraint::class)) {
976-
$primaryKeyColumnNames = [];
976+
// DBAL < 4.3
977+
if (! method_exists($table, 'getPrimaryKeyConstraint')) {
978+
return $table->getPrimaryKey();
979+
}
977980

978-
foreach ($primaryKeyColumns as $primaryKeyColumn) {
979-
$primaryKeyColumnNames[] = new UnqualifiedName(Identifier::unquoted($primaryKeyColumn));
980-
}
981+
return $table->getPrimaryKeyConstraint();
982+
}
981983

982-
$table->addPrimaryKeyConstraint(new PrimaryKeyConstraint(null, $primaryKeyColumnNames, true));
983-
} else {
984+
/** @param string[] $primaryKeyColumns */
985+
private function addPrimaryKeyConstraint(Table $table, array $primaryKeyColumns): PrimaryKeyConstraint|Index
986+
{
987+
// DBAL < 4.3
988+
if (! class_exists(PrimaryKeyConstraint::class)) {
984989
$table->setPrimaryKey($primaryKeyColumns);
990+
991+
return $table->getPrimaryKey();
985992
}
993+
994+
$primaryKeyConstraint = PrimaryKeyConstraint::editor()
995+
->setUnquotedColumnNames(...array_values($primaryKeyColumns))
996+
->setIsClustered(true)
997+
->create();
998+
999+
$table->addPrimaryKeyConstraint($primaryKeyConstraint);
1000+
1001+
return $table->getPrimaryKeyConstraint();
9861002
}
9871003

988-
/** @return string[] */
1004+
/** @return non-empty-list<string> */
9891005
private static function getIndexedColumns(Index $index): array
9901006
{
991-
if (method_exists(Index::class, 'getIndexedColumns')) {
992-
return array_map(static fn (IndexedColumn $indexedColumn) => $indexedColumn->getColumnName()->toString(), $index->getIndexedColumns());
1007+
// DBAL < 4.3
1008+
if (! method_exists(Index::class, 'getIndexedColumns')) {
1009+
return $index->getColumns();
1010+
}
1011+
1012+
return array_map(static fn (IndexedColumn $indexedColumn) => $indexedColumn->getColumnName()->getIdentifier()->getValue(), $index->getIndexedColumns());
1013+
}
1014+
1015+
private function doesIndexOverlapWithPrimaryKey(Index $index, PrimaryKeyConstraint|Index $primaryKey): bool
1016+
{
1017+
// DBAL < 4.3
1018+
if ($primaryKey instanceof Index) {
1019+
return $index !== $primaryKey && $primaryKey->spansColumns(self::getIndexedColumns($index));
1020+
}
1021+
1022+
$indexedColumns = $index->getIndexedColumns();
1023+
foreach ($primaryKey->getColumnNames() as $i => $column) {
1024+
if (
1025+
! isset($indexedColumns[$i])
1026+
|| strtolower($column->getIdentifier()->getValue())
1027+
!== strtolower($indexedColumns[$i]->getColumnName()->getIdentifier()->getValue())
1028+
) {
1029+
return false;
1030+
}
1031+
}
1032+
1033+
return true;
1034+
}
1035+
1036+
/**
1037+
* @param non-empty-string $indexName
1038+
* @param non-empty-list<non-empty-string> $indexColumns
1039+
* @param array<string, mixed> $indexOptions
1040+
*/
1041+
private function createIndexForComparison(string $indexName, array $indexColumns, mixed $indexOptions): Index
1042+
{
1043+
// DBAL < 4.3
1044+
if (! class_exists(IndexEditor::class)) {
1045+
return new Index($indexName, $indexColumns, true, false, [], $indexOptions);
9931046
}
9941047

995-
return $index->getColumns();
1048+
return Index::editor()
1049+
->setUnquotedName($indexName)
1050+
->setUnquotedColumnNames(...$indexColumns)
1051+
->setType(Index\IndexType::UNIQUE)
1052+
->create();
9961053
}
9971054
}

0 commit comments

Comments
 (0)