From da51234d5aaba3901e91461982c07e54d97cce9c Mon Sep 17 00:00:00 2001 From: Benjamin Eberlei Date: Thu, 12 May 2022 22:26:34 +0200 Subject: [PATCH] [GH-3519] Deprecate passing the same class with different discriminator values. --- UPGRADE.md | 9 +++++++-- src/Mapping/ClassMetadata.php | 20 +++++++++++++++++++ tests/Tests/ORM/Mapping/ClassMetadataTest.php | 8 ++++++++ 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/UPGRADE.md b/UPGRADE.md index 6da5e0be57c..12e67dee2cd 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -1,3 +1,8 @@ +# Upgrade to 3.4 + +Using the same class several times in a discriminator map is deprecated. +In 4.0, this will be an error. + # Upgrade to 3.3 ## Deprecate `DatabaseDriver` @@ -737,7 +742,7 @@ Use `toIterable()` instead. Output walkers should implement the new `\Doctrine\ORM\Query\OutputWalker` interface and create `Doctrine\ORM\Query\Exec\SqlFinalizer` instances instead of `Doctrine\ORM\Query\Exec\AbstractSqlExecutor`s. -The output walker must not base its workings on the query `firstResult`/`maxResult` values, so that the +The output walker must not base its workings on the query `firstResult`/`maxResult` values, so that the `SqlFinalizer` can be kept in the query cache and used regardless of the actual `firstResult`/`maxResult` values. Any operation dependent on `firstResult`/`maxResult` should take place within the `SqlFinalizer::createExecutor()` method. Details can be found at https://github.com/doctrine/orm/pull/11188. @@ -750,7 +755,7 @@ change in behavior. Progress on this is tracked at https://github.com/doctrine/orm/issues/11624 . -## PARTIAL DQL syntax is undeprecated +## PARTIAL DQL syntax is undeprecated Use of the PARTIAL keyword is not deprecated anymore in DQL, because we will be able to support PARTIAL objects with PHP 8.4 Lazy Objects and diff --git a/src/Mapping/ClassMetadata.php b/src/Mapping/ClassMetadata.php index b91bd9b5ac1..a72099bd4d8 100644 --- a/src/Mapping/ClassMetadata.php +++ b/src/Mapping/ClassMetadata.php @@ -25,7 +25,10 @@ use Stringable; use function array_column; +use function array_count_values; use function array_diff; +use function array_filter; +use function array_flip; use function array_intersect; use function array_key_exists; use function array_keys; @@ -39,6 +42,7 @@ use function defined; use function enum_exists; use function explode; +use function implode; use function in_array; use function interface_exists; use function is_string; @@ -2178,6 +2182,22 @@ final public function getDiscriminatorColumn(): DiscriminatorColumnMapping */ public function setDiscriminatorMap(array $map): void { + 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 60b1bc1822f..57736cc68a8 100644 --- a/tests/Tests/ORM/Mapping/ClassMetadataTest.php +++ b/tests/Tests/ORM/Mapping/ClassMetadataTest.php @@ -1101,6 +1101,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]