Problem/Motivation
When deleting the first subgroup in a hierarchy level, , the group leaf data can get incorrectly erased thus leading to broken subgroup hierarchies.
Steps to reproduce
(Partially copied from
#3182801-2: An existing subgroup cannot be deleted →
)
- Created 2 group types Sub 1, and Sub 2 as a tree (Sub 1 is parent to Sub 2)
- Added group Test 1 of type Sub 1
-Aadded subgroup Test 2 of type Sub 2 to group Test 1
- Added subgroup Test 3 of type Sub 2 to group Test 1
- Call programatically to \Drupal\subgroup\Entity\SubgroupHandlerBase::getChildren() with "Test 1" as parameter. You will get 2 result: "Test 2" and "Test 3". Visit any subgroup listing (i.e. a view): you will see Test2 and Test 3.
- Delete Test 2
- Call programatically to \Drupal\subgroup\Entity\SubgroupHandlerBase::getChildren() with "Test 1" as parameter. You will get an empty result.
Proposed resolution
Don't rely on the child "left" and "right" values to undo a tree structure.
See comment
#4
🐛
doRemoveLeaf() incorrectly clears leaf data and breaks subgroup trees
Fixed
The problem is related to this code on function doRemoveLeaf() on /src/Entity/SubgroupHandlerBase.php
// If the left and right values are 2 and 3 respectively it means we're
// removing the last child of a tree root. In this case, we unset the tree
// altogether.
if ($leaf->getLeft() === 2 && $leaf->getRight() === 3) {
$root = $this->storage->load($leaf->getTree());
$this->clearLeafData($root, TRUE);
}
The code states that "If the left and right values are 2 and 3 respectively it means we're removing the last child", but this is not true: it means we are removing the first
So, every time the first subgroup of a tree is removed, it will wipe the structure of the whole tree leading to unexpected results if there were any siblings still alive.
The proposed resolution is either to check wether there are more siblings left before calling clearLeafData or check the presence of descendants of the root
Remaining tasks
Test and review.
Fix failing tests.
User interface changes
None
API changes
None
Data model changes
None