Hooks and Events
When to Use
Reference this when looking for extension points to react to Group events without altering core Group logic.
Decision
| Need | Use | Why |
|---|---|---|
| Alter group operations block | hook_group_operations_alter() |
Only Group-specific hook |
| React to relationship create/delete | hook_ENTITY_TYPE_insert/delete on group_relationship |
No dedicated Group event for relationship CRUD |
| Dynamic permissions | permission_callbacks in .group.permissions.yml |
Called at permission cache build time |
| Alter routes | Event subscriber on RoutingEvents::ALTER |
Standard Symfony routing |
| Custom permission source | AccessPolicyBase subclass tagged access_policy |
4.x replaces flexible_permissions_calculator |
Pattern
// React to an article being added to a group.
function mymodule_group_relationship_insert(GroupRelationshipInterface $relationship) {
if ($relationship->getPluginId() === 'group_node:article') {
$group = $relationship->getGroup();
$node = $relationship->getEntity();
// custom logic...
}
}
// Alter group operations block.
function mymodule_group_operations_alter(array &$operations, GroupInterface $group) {
if ($group->bundle() === 'company') {
unset($operations['group-leave']);
}
}
// Dynamic permissions callback.
class MyModuleGroupPermissions {
public function permissions(): array {
$permissions = [];
foreach (MyEntityType::loadMultiple() as $id => $type) {
$permissions["manage $id content"] = [
'title' => t('Manage @type content', ['@type' => $type->label()]),
'allowed for' => ['member'],
];
}
return $permissions;
}
}
4.x note: Group 4.x has no .module file. All hook implementations are OOP methods in src/Hook/ (CoreHooks, EntityHooks, FieldHooks, FormHooks, QueryHooks, etc.), each tagged with #[Hook('hook_name')]. Your own module can still use either procedural .module functions or OOP hook classes — the change only affects Group's own hooks.
Registered event subscribers by Group core:
| Service ID | Listens to | Purpose |
|---|---|---|
group.anonymous_user_response_subscriber |
KernelEvents::RESPONSE |
Adds permission cache tags for anonymous users |
group.config_subscriber |
ConfigEvents::SAVE |
Clears plugin caches on group type config changes |
Common Mistakes
- Wrong: Listening to Group-specific Symfony events for relationship changes → Right: Group does not dispatch custom Symfony events for relationship changes. Use entity hooks instead.
- Wrong: Not reacting before deletion → Right: If you need pre-deletion logic, implement
hook_ENTITY_TYPE_predeleteon the entity type being removed from the group (not ongroup_relationship). - Wrong: Calling
group_entity_access()directly in 4.x → Right: The procedural function no longer exists in 4.x. The equivalent isEntityHooks::entityAccess()inside Group's codebase, which you should not call directly.
See Also
- Plugin System
- PHP API
- Reference:
web/modules/contrib/group/group.api.php