The concern of managing user group membership should be factored out of the User object, into a separate service.
The new UserGroupStore service should have the following low-level methods:
* newGroupMembership( UserIdentity $user, $group, $expiry = null ): UserGroupMembership;
* addGroup( UserIdentity $user, $group )
* removeGroup( UserIdentity $user, $group )
* listGroups( UserIdentity $user )
To allow other services (like PermissionMannage) 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 UserGroupManager could be created that offers the following methods:
* addAutopromoteOnceGroups( UserIdentity $user, $event )
* getEffectiveGroups( UserIdentity $user )