diff --git a/UPGRADE.md b/UPGRADE.md index 9de8af04d38..45c222f3caf 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -1,3 +1,8 @@ +# Upgrade to 2.21 + +Using the same class several times in a discriminator map is deprecated. +In 4.0, this will be an error. + # Upgrade to 2.20 ## Add `Doctrine\ORM\Query\OutputWalker` interface, deprecate `Doctrine\ORM\Query\SqlWalker::getExecutor()` diff --git a/src/Mapping/ClassMetadataInfo.php b/src/Mapping/ClassMetadataInfo.php index cb17b8983d4..14a7d665349 100644 --- a/src/Mapping/ClassMetadataInfo.php +++ b/src/Mapping/ClassMetadataInfo.php @@ -23,7 +23,9 @@ use ReflectionProperty; use RuntimeException; +use function array_count_values; use function array_diff; +use function array_filter; use function array_flip; use function array_intersect; use function array_keys; @@ -37,6 +39,7 @@ use function enum_exists; use function explode; use function gettype; +use function implode; use function in_array; use function interface_exists; use function is_array; @@ -3207,6 +3210,22 @@ final public function getDiscriminatorColumn(): array */ public function setDiscriminatorMap(array $map) { + if (count(array_flip($map)) !== count($map)) { + Deprecation::trigger( + 'doctrine/orm', + 'https://github.com/doctrine/orm/issues/3519', + <<<'DEPRECATION' + Mapping a class to multiple discriminator values is deprecated, + and the discriminator mapping of %s contains duplicate values + for the following discriminator values: %s. + DEPRECATION, + $this->name, + implode(', ', array_keys(array_filter(array_count_values($map), static function (int $value): bool { + return $value > 1; + }))) + ); + } + foreach ($map as $value => $className) { $this->addDiscriminatorMapClass($value, $className); } diff --git a/tests/Tests/ORM/Mapping/ClassMetadataTest.php b/tests/Tests/ORM/Mapping/ClassMetadataTest.php index fcd4cffc35f..4cd3abd06d8 100644 --- a/tests/Tests/ORM/Mapping/ClassMetadataTest.php +++ b/tests/Tests/ORM/Mapping/ClassMetadataTest.php @@ -1408,6 +1408,14 @@ public function testClassNameMappingDiscriminatorValue(): void $xmlElement->children()->{'discriminator-map'}->{'discriminator-mapping'}[0]->attributes()['value'] ); } + + public function testDiscriminatorMapWithSameClassMultipleTimesDeprecated(): void + { + $this->expectDeprecationWithIdentifier('https://github.com/doctrine/orm/issues/3519'); + + $cm = new ClassMetadata(CMS\CmsUser::class); + $cm->setDiscriminatorMap(['foo' => CMS\CmsUser::class, 'bar' => CMS\CmsUser::class]); + } } /** @MappedSuperclass */