Skip to content

Commit 90989a4

Browse files
authored
Implement entity lookup in hierarchy, closes cycle#101
1 parent 8954c01 commit 90989a4

File tree

1 file changed

+31
-20
lines changed

1 file changed

+31
-20
lines changed

src/Configurator.php

Lines changed: 31 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -112,17 +112,17 @@ public function initFields(EntitySchema $entity, \ReflectionClass $class, string
112112
}
113113

114114
$field = $this->initField($property->getName(), $column, $class, $columnPrefix);
115-
$field->setEntityClass($property->getDeclaringClass()->getName());
115+
$field->setEntityClass($this->findOwningEntity($class, $property->getDeclaringClass())->getName());
116116
$entity->getFields()->set($property->getName(), $field);
117117
}
118118
}
119119

120120
public function initRelations(EntitySchema $entity, \ReflectionClass $class): void
121121
{
122122
foreach ($class->getProperties() as $property) {
123-
// ignore properties declared by parent class
123+
// ignore properties declared by parent entties
124124
// otherwise all the relation columns declared in parent would be duplicated across all child tables in JTI
125-
if ($this->propertyBelongsToOtherEntity($class, $property->getDeclaringClass())) {
125+
if ($this->findOwningEntity($class, $property->getDeclaringClass())->getName() !== $class->getName()) {
126126
continue;
127127
}
128128

@@ -420,26 +420,37 @@ private function isOnInsertGeneratedField(Field $field): bool
420420
};
421421
}
422422

423-
private function propertyBelongsToOtherEntity(\ReflectionClass $currentClass, \ReflectionClass $declaringClass): bool
423+
/**
424+
* Function to find an owning entity class in the inheritance hierarchy.
425+
*
426+
* Entity classes may extend a base class and this function is needed route the properties from declaring class to the entity class.
427+
* The function stops only when the declaring class is truly found, it does not naively stop on first entity.
428+
* This behaviour makes it also functional in cases of Joined Table Inheritance on theoretically any number of nesting levels.
429+
*/
430+
private function findOwningEntity(\ReflectionClass $currentClass, \ReflectionClass $declaringClass): \ReflectionClass
424431
{
425-
// if the current class is the same as declaring class, than the property belongs to current Entity
426-
if ($currentClass->getName() === $declaringClass->getName()) {
427-
return false;
428-
}
429-
430-
$parentClass = $currentClass->getParentClass();
432+
// latest found entityClass before declaringClass
433+
$latestEntityClass = $currentClass;
434+
435+
do {
436+
// we found declaringClass in the hierarchy
437+
// in most cases the execution will stop here in first loop
438+
if ($currentClass->getName() === $declaringClass->getName()) {
439+
return $latestEntityClass;
440+
}
431441

432-
// not possible to happen for logical reasons, but defensively check anyway
433-
if (!$parentClass instanceof \ReflectionClass) {
434-
return false;
435-
}
442+
$currentClass = $currentClass->getParentClass();
436443

437-
// if a parent class in hierarchy is an Entity on its own, the property belongs to that Entity
438-
if (\count($parentClass->getAttributes(Entity::class)) > 0) {
439-
return true;
440-
}
444+
// not possible to happen for logical reasons, but defensively check anyway
445+
if (!$currentClass instanceof \ReflectionClass) {
446+
return $latestEntityClass;
447+
}
441448

442-
// continue until we find a declaringClass or Entity attribute
443-
return $this->propertyBelongsToOtherEntity($parentClass, $declaringClass);
449+
// if a currentClass in hierarchy is an entity on its own, the property belongs to that entity
450+
if (\count($currentClass->getAttributes(Entity::class)) > 0) {
451+
$latestEntityClass = $currentClass;
452+
}
453+
} while (true); // the inheritance hierarchy cannot be infinite
444454
}
445455
}
456+

0 commit comments

Comments
 (0)