Architectural Notes

Why login/nicename convention writes bypass wp_update_user()

ensure_login_matches_email() and ensure_nicename_matches_id() both write via a direct SQL UPDATE rather than wp_update_user(). wp_insert_user()/wp_update_user() runs its own nicename-uniqueness dedup logic, built for human-chosen slugs that can legitimately collide (john-smith vs john-smith-2). That logic was found to treat a user’s own already-correct numeric nicename as a foreign collision and “resolve” it by appending -2, compounding further on every subsequent call into values like 1015925-2-2. A nicename that is always just the numeric ID can never legitimately collide with anyone by construction, so there is nothing for that dedup logic to usefully do — going around it removes the failure mode entirely rather than working around it. It also means these writes don’t fire profile_update, so they can’t trigger other plugins’ profile_update handlers or create hook re-entrancy.

Both methods are guarded — they compare against the current value first and skip the write entirely when it’s already correct — so a no-op check costs a single cached read, and a real fix costs one row update.

Identity resolution / alias awareness

resolve_existing_user_by_email() follows lh-user-identity‘s documented alias-resolution pattern: check wp_users first, then fall back to the lh_user_identity_get_user_by_email_fallback filter (a documented no-op if lh-user-identity isn’t active). This matters because ensure_user() is the canonical entry point several other LH plugins delegate to — without alias-aware resolution, provisioning by an email that is a registered alias (rather than an account’s primary email) would return a false “no such user” result and create a duplicate account instead of recognising the existing one.

Provenance tracking

Every newly provisioned user gets usermeta recording their origin, keyed as follows:

KeyDescription
lh_provisioning_sourceCalling plugin slug, e.g. lh-membership
lh_provisioning_actionWhat triggered it, e.g. registration, checkin
lh_provisioning_refOptional reference ID, e.g. event ID
lh_provisioning_site_idWhich site triggered creation

No custom database tables — all provenance data lives in wp_usermeta. lh_provisioning_source and lh_provisioning_action are surfaced as a “Provisioned Via” column on the Network Admin → Users screen; lh_provisioning_ref and lh_provisioning_site_id are not currently shown in any UI. Provenance is only recorded on first creation, not on subsequent ensure_user() calls against an existing account, unless explicitly requested via args['source'].

Supersedes “LH Email Usernames”

The old standalone “LH Email Usernames” plugin partially provided real-time login-matches-email enforcement (login only, via wp_update_user() plus an unconditional site-wide wp_cache_flush() on every profile update). That plugin is fully superseded by this one’s user_register/profile_update hooks and can be deactivated/removed.