diff --git a/lib/Doctrine/ORM/Query.php b/lib/Doctrine/ORM/Query.php index 385b8c8ea..a86cf6201 100644 --- a/lib/Doctrine/ORM/Query.php +++ b/lib/Doctrine/ORM/Query.php @@ -371,6 +371,25 @@ final class Query extends AbstractQuery $this->_em->getCache()->evictEntityRegion($className); } + private function getAllDiscriminators(ClassMetadata $classMetadata) + { + // FIXME: this code is copied from SqlWalker->getAllDiscriminators() + $hierarchyClasses = $classMetadata->subClasses; + $hierarchyClasses[] = $classMetadata->name; + + $discriminators = []; + foreach ($hierarchyClasses as $class) { + $currentMetadata = $this->getEntityManager()->getClassMetadata($class); + $currentDiscriminator = $currentMetadata->discriminatorValue; + + if (null !== $currentDiscriminator) { + $discriminators[$currentDiscriminator] = null; + } + } + + return $discriminators; + } + /** * Processes query parameter mappings. * @@ -398,6 +417,10 @@ final class Query extends AbstractQuery $value = $value->getMetadataValue($rsm->metadataParameterMapping[$key]); } + if (isset($rsm->discriminatorParameters[$key]) && $value instanceof ClassMetadata) { + $value = array_keys($this->getAllDiscriminators($value)); + } + $value = $this->processParameterValue($value); $type = ($parameter->getValue() === $value) ? $parameter->getType() diff --git a/lib/Doctrine/ORM/Query/ResultSetMapping.php b/lib/Doctrine/ORM/Query/ResultSetMapping.php index 5c4550980..058ae8d4c 100644 --- a/lib/Doctrine/ORM/Query/ResultSetMapping.php +++ b/lib/Doctrine/ORM/Query/ResultSetMapping.php @@ -168,6 +168,13 @@ class ResultSetMapping */ public $metadataParameterMapping = []; + /** + * Contains query parameter names to be resolved as discriminator values + * + * @var array + */ + public $discriminatorParameters = []; + /** * Adds an entity result to this ResultSetMapping. * diff --git a/lib/Doctrine/ORM/Query/SqlWalker.php b/lib/Doctrine/ORM/Query/SqlWalker.php index 8c8ef30d1..3407b0a8b 100644 --- a/lib/Doctrine/ORM/Query/SqlWalker.php +++ b/lib/Doctrine/ORM/Query/SqlWalker.php @@ -2270,42 +2270,29 @@ class SqlWalker implements TreeWalker } /** - * @param ClassMetadataInfo $discrClass + * @param ClassMetadataInfo $rootClass * @param AST\InstanceOfExpression $instanceOfExpr * @return string The list in parentheses of valid child discriminators from the given class * @throws QueryException */ - private function getChildDiscriminatorsFromClassMetadata(ClassMetadataInfo $discrClass, AST\InstanceOfExpression $instanceOfExpr) + private function getChildDiscriminatorsFromClassMetadata(ClassMetadataInfo $rootClass, AST\InstanceOfExpression $instanceOfExpr) { $sqlParameterList = []; $discriminators = []; foreach ($instanceOfExpr->value as $parameter) { if ($parameter instanceof AST\InputParameter) { - $this->rsm->addMetadataParameterMapping($parameter->name, 'discriminatorValue'); - - $sqlParameterList[] = $this->walkInputParameter($parameter); - + $this->rsm->discriminatorParameters[$parameter->name] = $parameter->name; + $sqlParameterList[] = $this->walkInParameter($parameter); continue; } $metadata = $this->em->getClassMetadata($parameter); - if ($metadata->getName() !== $discrClass->name && ! $metadata->getReflectionClass()->isSubclassOf($discrClass->name)) { - throw QueryException::instanceOfUnrelatedClass($parameter, $discrClass->name); + if ($metadata->getName() !== $rootClass->name && ! $metadata->getReflectionClass()->isSubclassOf($rootClass->name)) { + throw QueryException::instanceOfUnrelatedClass($parameter, $rootClass->name); } - // Include discriminators for parameter class and its subclass - $hierarchyClasses = $metadata->subClasses; - $hierarchyClasses[] = $metadata->name; - - foreach ($hierarchyClasses as $class) { - $currentMetadata = $this->em->getClassMetadata($class); - $currentDiscriminator = $currentMetadata->discriminatorValue; - - if (null !== $currentDiscriminator) { - $discriminators[$currentDiscriminator] = null; - } - } + $discriminators = $discriminators + $this->getAllDiscriminators($metadata); } foreach (array_keys($discriminators) as $dis) { @@ -2314,4 +2301,23 @@ class SqlWalker implements TreeWalker return '(' . implode(', ', $sqlParameterList) . ')'; } + + private function getAllDiscriminators(ClassMetadata $classMetadata) + { + // FIXME: this code is identical to Query->getAllDiscriminators() + $hierarchyClasses = $classMetadata->subClasses; + $hierarchyClasses[] = $classMetadata->name; + + $discriminators = []; + foreach ($hierarchyClasses as $class) { + $currentMetadata = $this->em->getClassMetadata($class); + $currentDiscriminator = $currentMetadata->discriminatorValue; + + if (null !== $currentDiscriminator) { + $discriminators[$currentDiscriminator] = null; + } + } + + return $discriminators; + } } diff --git a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1995Test.php b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1995Test.php index fb32b99fe..8bb975a05 100644 --- a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1995Test.php +++ b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC1995Test.php @@ -72,10 +72,9 @@ class DDC1995Test extends \Doctrine\Tests\OrmFunctionalTestCase ->getResult(); $this->assertCount(1, $result1); - $this->assertCount(1, $result2); + $this->assertCount(2, $result2); $this->assertInstanceOf(CompanyEmployee::class, $result1[0]); - $this->assertInstanceOf(CompanyPerson::class, $result2[0]); - $this->assertNotInstanceOf(CompanyEmployee::class, $result2[0]); + $this->assertContainsOnlyInstancesOf(CompanyPerson::class, $result2); } }