Problem/Motivation
With "Restrict the amount of hierarchies per group to one" (limit_group_hierarchy_count) enabled, the parent field becomes effectively required once a group already has a root entity. This is enforced by GroupHierarchyParentConstraintValidator, which calls EntityHierarchyGroupHelper::currentHierarchyHasRoot().
However, the group-context branch of currentHierarchyHasRoot() queries group_relationship entities only by relationship type, not by the current group's gid. Since the relationship type (e.g. community-group_node-wiki_page) is shared across all groups of the same group type, a root entity in any group is detected as a root for every group.
Result: as soon as one group has a root hierarchy entity, you can no longer create the first (root) entity in any other group of the same type — the validator demands a parent, but the (correctly group-filtered) parent selection offers none. Deadlock. For closed groups this also leaks the existence of content across group boundaries.
Steps to reproduce
- Enable
limit_group_hierarchy_count(andlimit_group). - In Group A, create the first hierarchy node (becomes root, no parent) — works.
- In Group B, try to create the first hierarchy node.
- Validation fails with the "root already exists, select a parent" violation, although Group B has no hierarchy content at all.
Root cause
src/EntityHierarchyGroupHelper.php, currentHierarchyHasRoot(), group branch:
$root_entity_relationships = $group_relationship_storage ->getQuery() ->condition('type', $group->getGroupType()->id() . '-group_' . $entity->getEntityTypeId() . '-' . $entity->getType()) ->notExists('entity_id.entity:' . $entity->getEntityTypeId() . '.' . $field) ->accessCheck(TRUE) ->execute();
The query is missing a condition on the group id, so it returns root relationships from all groups of that type.
Proposed resolution
Scope the query to the current group:
$root_entity_relationships = $group_relationship_storage ->getQuery() ->condition('gid', $group_id) ->condition('type', $group->getGroupType()->id() . '-group_' . $entity->getEntityTypeId() . '-' . $entity->getType()) ->notExists('entity_id.entity:' . $entity->getEntityTypeId() . '.' . $field) ->accessCheck(TRUE) ->execute();
Secondary note: accessCheck(TRUE) makes the existence check depend on the current user's access to other entities. For a pure "does a root already exist in this group" check, accessCheck(FALSE) would be more deterministic. The gid filter is the primary fix.
Issue fork entity_hierarchy_group-3593197
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #3
atropoidesComment #4
djanik commentedGood point, thanks!
Comment #6
atropoidesComment #7
atropoides