To replace the "smart record" behavior in User, we need to introduce a data access service (DAO layer) for accessing the user and actor tables.
Interface draft:
interface ActorLookup { public function getActor( int $actorId, int $queryFlags = 0 ): UserIdentity; // throw if actor is not known (fall back to master?) public function getActorByName( string $name, int $queryFlags = 0 ): ?UserIdentity; // return null if unknown public function getActorByUserId( int $userId, int $queryFlags = 0 ): ?UserIdentity;; // return null if unknown } interface UserLookup { public function getUser( UserIdentity $user, int $queryFlags = 0 ): ?UserAccount; // return null if $user is not registered } class UserStore implements ActorLookup, UserLookup { public function registerActor( UserIdentity $actor ): UserIdentity; // returns a UserIdentity that has an actor id (just $actor, if that already has an ID) public function createUser( UserIdentity $user, array $info = [] ): UserAccount; // creates a user account, throws if the name is taken or $user has an ID public function updateUserRecord( UserAccount $user ); // fails if user does not exist (do we need UserRecord?) }