Skip to content

Commit 5ff44b5

Browse files
committed
DDC-1203, DDC-1204 - Fix problems with mapped superclasses in midth of inheritance hierachy and entities not mapped in discriminator map.
1 parent dd329c9 commit 5ff44b5

File tree

3 files changed

+111
-15
lines changed

3 files changed

+111
-15
lines changed

lib/Doctrine/ORM/Mapping/ClassMetadataFactory.php

+16-15
Original file line numberDiff line numberDiff line change
@@ -261,19 +261,15 @@ protected function loadMetadata($name)
261261
$class = $this->newClassMetadataInstance($className);
262262

263263
if ($parent) {
264-
if (!$parent->isMappedSuperclass) {
265-
$class->setInheritanceType($parent->inheritanceType);
266-
$class->setDiscriminatorColumn($parent->discriminatorColumn);
267-
}
264+
$class->setInheritanceType($parent->inheritanceType);
265+
$class->setDiscriminatorColumn($parent->discriminatorColumn);
268266
$class->setIdGeneratorType($parent->generatorType);
269267
$this->addInheritedFields($class, $parent);
270268
$this->addInheritedRelations($class, $parent);
271269
$class->setIdentifier($parent->identifier);
272270
$class->setVersioned($parent->isVersioned);
273271
$class->setVersionField($parent->versionField);
274-
if (!$parent->isMappedSuperclass) {
275-
$class->setDiscriminatorMap($parent->discriminatorMap);
276-
}
272+
$class->setDiscriminatorMap($parent->discriminatorMap);
277273
$class->setLifecycleCallbacks($parent->lifecycleCallbacks);
278274
$class->setChangeTrackingPolicy($parent->changeTrackingPolicy);
279275
}
@@ -285,7 +281,7 @@ protected function loadMetadata($name)
285281
throw MappingException::reflectionFailure($className, $e);
286282
}
287283

288-
if ($parent && ! $parent->isMappedSuperclass) {
284+
if ($parent) {
289285
if ($parent->isIdGeneratorSequence()) {
290286
$class->setSequenceGeneratorDefinition($parent->sequenceGeneratorDefinition);
291287
} else if ($parent->isIdGeneratorTable()) {
@@ -318,18 +314,23 @@ protected function loadMetadata($name)
318314
}
319315

320316
// verify inheritance
321-
if (!$parent && !$class->isMappedSuperclass && !$class->isInheritanceTypeNone()) {
322-
if (count($class->discriminatorMap) == 0) {
323-
throw MappingException::missingDiscriminatorMap($class->name);
324-
}
325-
if (!$class->discriminatorColumn) {
326-
throw MappingException::missingDiscriminatorColumn($class->name);
317+
if (!$class->isMappedSuperclass && !$class->isInheritanceTypeNone()) {
318+
if (!$parent) {
319+
if (count($class->discriminatorMap) == 0) {
320+
throw MappingException::missingDiscriminatorMap($class->name);
321+
}
322+
if (!$class->discriminatorColumn) {
323+
throw MappingException::missingDiscriminatorColumn($class->name);
324+
}
325+
} else if ($parent && !in_array($class->name, array_values($class->discriminatorMap))) {
326+
// enforce discriminator map for all entities of an inheritance hierachy, otherwise problems will occur.
327+
throw MappingException::mappedClassNotPartOfDiscriminatorMap($class->name, $class->rootEntityName);
327328
}
328329
} else if ($class->isMappedSuperclass && $class->name == $class->rootEntityName && (count($class->discriminatorMap) || $class->discriminatorColumn)) {
329330
// second condition is necessary for mapped superclasses in the middle of an inheritance hierachy
330331
throw MappingException::noInheritanceOnMappedSuperClass($class->name);
331332
}
332-
333+
333334
$this->loadedMetadata[$className] = $class;
334335

335336
$parent = $class;

lib/Doctrine/ORM/Mapping/MappingException.php

+8
Original file line numberDiff line numberDiff line change
@@ -284,4 +284,12 @@ public static function noInheritanceOnMappedSuperClass($className)
284284
{
285285
return new self("Its not supported to define inheritance information on a mapped superclass '" . $className . "'.");
286286
}
287+
288+
public static function mappedClassNotPartOfDiscriminatorMap($className, $rootClassName)
289+
{
290+
return new self(
291+
"Entity '" . $className . "' has to be part of the descriminator map of '" . $rootClassName . "' " .
292+
"to be properly mapped in the inheritance hierachy. If you want to avoid instantiation of this type mark it abstract."
293+
);
294+
}
287295
}

tests/Doctrine/Tests/ORM/Mapping/BasicInheritanceMappingTest.php

+87
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace Doctrine\Tests\ORM\Mapping;
44

55
use Doctrine\ORM\Mapping\ClassMetadataFactory;
6+
use Doctrine\ORM\Tools\SchemaTool;
67

78
require_once __DIR__ . '/../../TestInit.php';
89

@@ -66,6 +67,28 @@ public function testSerializationWithPrivateFieldsFromMappedSuperclass()
6667
$this->assertTrue(isset($class2->reflFields['mapped2']));
6768
$this->assertTrue(isset($class2->reflFields['mappedRelated1']));
6869
}
70+
71+
/**
72+
* @group DDC-1203
73+
*/
74+
public function testUnmappedSuperclassInHierachy()
75+
{
76+
$class = $this->_factory->getMetadataFor(__NAMESPACE__ . '\\HierachyD');
77+
78+
$this->assertTrue(isset($class->fieldMappings['id']));
79+
$this->assertTrue(isset($class->fieldMappings['a']));
80+
$this->assertTrue(isset($class->fieldMappings['d']));
81+
}
82+
83+
/**
84+
* @group DDC-1204
85+
*/
86+
public function testUnmappedEntityInHierachy()
87+
{
88+
$this->setExpectedException('Doctrine\ORM\Mapping\MappingException', "Entity 'Doctrine\Tests\ORM\Mapping\HierachyBEntity' has to be part of the descriminator map of 'Doctrine\Tests\ORM\Mapping\HierachyBase' to be properly mapped in the inheritance hierachy. If you want to avoid instantiation of this type mark it abstract.");
89+
90+
$class = $this->_factory->getMetadataFor(__NAMESPACE__ . '\\HierachyE');
91+
}
6992
}
7093

7194
class TransientBaseClass {
@@ -103,3 +126,67 @@ class EntitySubClass2 extends MappedSuperclassBase {
103126
/** @Column(type="string") */
104127
private $name;
105128
}
129+
130+
/**
131+
* @Entity
132+
* @InheritanceType("SINGLE_TABLE")
133+
* @DiscriminatorColumn(name="type", type="string", length=20)
134+
* @DiscriminatorMap({
135+
* "c" = "HierachyC",
136+
* "d" = "HierachyD",
137+
* "e" = "HierachyE"
138+
* })
139+
*/
140+
abstract class HierachyBase
141+
{
142+
/**
143+
* @Column(type="integer") @Id @GeneratedValue
144+
* @var int
145+
*/
146+
public $id;
147+
}
148+
149+
/**
150+
* @MappedSuperclass
151+
*/
152+
abstract class HierachyASuperclass extends HierachyBase
153+
{
154+
/** @Column(type="string") */
155+
public $a;
156+
}
157+
158+
/**
159+
* @Entity
160+
*/
161+
abstract class HierachyBEntity extends HierachyBase
162+
{
163+
/** @Column(type="string") */
164+
public $b;
165+
}
166+
167+
/**
168+
* @Entity
169+
*/
170+
class HierachyC extends HierachyBase
171+
{
172+
/** @Column(type="string") */
173+
public $c;
174+
}
175+
176+
/**
177+
* @Entity
178+
*/
179+
class HierachyD extends HierachyASuperclass
180+
{
181+
/** @Column(type="string") */
182+
public $d;
183+
}
184+
185+
/**
186+
* @Entity
187+
*/
188+
class HierachyE extends HierachyBEntity
189+
{
190+
/** @Column(type="string") */
191+
public $e;
192+
}

0 commit comments

Comments
 (0)