diff --git a/src/Entity/Base/AbstractStructuralDBElement.php b/src/Entity/Base/AbstractStructuralDBElement.php
index cbe2c7be..921826b0 100644
--- a/src/Entity/Base/AbstractStructuralDBElement.php
+++ b/src/Entity/Base/AbstractStructuralDBElement.php
@@ -282,6 +282,12 @@ abstract class AbstractStructuralDBElement extends AttachmentContainingDBElement
*/
public function getSubelements(): iterable
{
+ //If the parent is equal to this object, we would get an endless loop, so just return an empty array
+ //This is just a workaround, as validator should prevent this behaviour, before it gets written to the database
+ if ($this->parent === $this) {
+ return new ArrayCollection();
+ }
+
return $this->children ?? new ArrayCollection();
}
diff --git a/src/Repository/AbstractPartsContainingRepository.php b/src/Repository/AbstractPartsContainingRepository.php
index eab2c26c..1bf4c31c 100644
--- a/src/Repository/AbstractPartsContainingRepository.php
+++ b/src/Repository/AbstractPartsContainingRepository.php
@@ -27,6 +27,8 @@ use InvalidArgumentException;
abstract class AbstractPartsContainingRepository extends StructuralDBElementRepository implements PartsContainingRepositoryInterface
{
+ private const RECURSION_LIMIT = 50;
+
/**
* Returns all parts associated with this element.
*
@@ -55,8 +57,17 @@ abstract class AbstractPartsContainingRepository extends StructuralDBElementRepo
{
$count = $this->getPartsCount($element);
+ //If the element is its own parent, we have a loop in the tree, so we stop here.
+ if ($element->getParent() === $element) {
+ return 0;
+ }
+
+ $n = 0;
foreach ($element->getChildren() as $child) {
$count += $this->getPartsCountRecursive($child);
+ if ($n++ > self::RECURSION_LIMIT) {
+ throw new \RuntimeException('Recursion limit reached!');
+ }
}
return $count;
diff --git a/tests/Entity/Base/AbstractStructuralDBElementTest.php b/tests/Entity/Base/AbstractStructuralDBElementTest.php
index 4b124053..9a4104e5 100644
--- a/tests/Entity/Base/AbstractStructuralDBElementTest.php
+++ b/tests/Entity/Base/AbstractStructuralDBElementTest.php
@@ -144,4 +144,15 @@ class AbstractStructuralDBElementTest extends TestCase
$this->assertSame([$this->root, $this->child1], $this->child1->getPathArray());
$this->assertSame([$this->root], $this->root->getPathArray());
}
+
+ public function testGetSubelements(): void
+ {
+ $this->assertSame([$this->child1, $this->child2, $this->child3], $this->root->getSubelements()->toArray());
+ $this->assertSame([$this->child1_1, $this->child1_2], $this->child1->getSubelements()->toArray());
+ $this->assertSame([], $this->child1_1->getSubelements()->toArray());
+
+ //If a element is set as its own parent, it should not be returned as a subelement
+ $this->child1->setParent($this->child1);
+ $this->assertSame([], $this->child1->getSubelements()->toArray());
+ }
}
diff --git a/translations/validators.de.xlf b/translations/validators.de.xlf
index abdd0886..47ee7322 100644
--- a/translations/validators.de.xlf
+++ b/translations/validators.de.xlf
@@ -173,7 +173,7 @@
validator.noneofitschild.self
- Ein Element kann nicht sein eigenenes übergeordnetes Element sein.
+ Ein Element kann nicht sein eigenenes übergeordnetes Element sein!
diff --git a/translations/validators.en.xlf b/translations/validators.en.xlf
index e639fa67..51549395 100644
--- a/translations/validators.en.xlf
+++ b/translations/validators.en.xlf
@@ -164,7 +164,7 @@
user.invalid_username
- The username must contain only letters, numbers, underscores, dots, pluses or minuses.
+ The username must contain only letters, numbers, underscores, dots, pluses or minuses!
@@ -173,7 +173,7 @@
validator.noneofitschild.self
- An element can not be its own parent.
+ An element can not be its own parent!
@@ -182,7 +182,7 @@
validator.noneofitschild.children
- You can not assign children element as parent (This would cause loops).
+ You can not assign children element as parent (This would cause loops)!