The concern of managing user group membership should be factored out of the User object (and the UserGroupMembership class), into a separate service.
The new UserGroupStore service should have the following low-level methods:
* newGroupMembership( UserIdentity $user, $group, $expiry = null ): UserGroupMembership;```lang=php
* add newGroup(pMembership( UserIdentity $userr, $group, $g$expiry = null ): UserGroup )Membership;
* addGroup( UserIdentity $user, $group )
removeGroup( UserIdentity $user, $group )
# needs knowledge of former groups table
listGroupNames( UserIdentity $user ): string[]
listGroupMemberships( UserIdentity $user ): GroupMembership[]
# cached, needs to check expiry
# need batch modefor listusers
purgeExpired()
getFormerGroups()
listDefinedGroups()
addUserGroupChangeListener( callable $listener )
# called from wiring
```
* listGroups( UserIdentity $user )
To allow other services (like PermissionManager) to react to changes in user groups, UserGroupStore needs a way to register listeners:
* * `addUserGroupChangeListener( callable $listener );`
Wiring code, not the services themselves, are responsible for registering the necessary callbacks.
In addition, a more high level UserGroupManagerservices could be created that offers the following methods:
```
AutoPromotionManager (refactoring Autopromote):
addAutopromoteOnceGroups
EffectiveUserGroupLookup:
getEffectiveGroups
# needed on page view, because we expose via JS
* addAutopromoteOnceGroups( UserIdentity $user, $event ) # cache in session?
* getEffectiveGroups( UserIdentity $user )```