Unique User Name per Multisite instance

In a server I'm setting up, any given user will need to have a site-specific identity. All of us are familiar with the concept: At home I'm Tony. In business I'm Anthony. In one game I could be TheGreatOne, and in another game I could be "TotalNewb". I was taking a class where a woman named Toni was sitting right next to me so I asked the teacher to call me TJ. People identify us differently based on context and preferences.

So, does anyone know a good plugin that will allow a user to change their visible user display name for each site, while of course maintaining a single network-wide username and email ID?

I was surprised a while back when I was looking for this (in BuddyPress) that there wasn't a hook for returning the display name, but maybe I missed something. I might be able to code this myself with shortcuts to replace hard-coded displayname queries. But with every plugin and every software update I'll need to hunt and make this change. :slight_frown:

I was also thinking that if I forced the display name for every user to internally be set to something like !!UNAME!!99999!! (where 99999 is the user's ID#), then I could set a sitewide filter that looks for instances of !!UNAME!!, and where it's found remove that and the trailing ID, parse the ID, concatenate it with the site name, and then do a lookup for the site-specific display name. So siteID_userID would be used as a key to a custom table. And that table would be updated from each user's profile.

I don't know if text filters like that are not applied to specific pages or in specific contexts. If so then I'd either need to hook multiple filters or, once again, to hack code where this doesn't happen. But for translation purposes I have to believe that everything gets put through a filter somewhere, no?

I'm open to better approaches to any of this. Thanks!!

  • Adam Czajczyk

    Hello Tony,

    I hope you're well today and thank you for your question!

    I agree that's a nice idea. However, I've just conducted a brief web research and although similar questions has been asked many times across the net, there seem to be no "ready-to-use" solutions available and no good answers, unfortunately.

    The main issue here is that there's a common user table for all site's in Multisite and by design WP allows a single "display name" per user to be used. Therefore when a "display name" is changed, it is changed "globally".

    I think your solution with "automatically created" unique names could be done with a bit of custom coding. Another one would be to create a plugin that would add a section on user's profile page that would let them add additional "display names". For example, by default it would be the same display name for all sites and then user would be able to add another one (that would be act as, let's call it, exception) for selected sub-site of the network. This would be nice as it would give users "freedom of choice".

    That said, this would require quite a bit of custom codining. Therefore I'm moving this to our "Features and feedback" forum and if more members of our community will support the idea, our developers may consider creating plugin like this. I cannot give you any guarantee on this though.

    You may also want to post a question on our "Jobs & Pros" job board (please note: no WPMU DEV staff members involved!) here:

    https://premium.wpmudev.org/wordpress-development/

    Having said that all, let me just add that if you feel like coding yourself, please feel free to ask any further questions and I'll be glad to assist you on this and possibly share some tips/knowledge with you.

    Best regards,
    Adam

  • Tony G

    Thanks Adam. Well, we've done similar homework and come up with similar answers. So at least we know where we're starting. Sincere thanks for the personal initiative there to look this up.

    I've looked up a number of functions, and requests for the display_name field. I'm convinced that most or all methods of returning a display_name go through a filter immediately prior to returning. For example:

    $display_name = get_the_author(); //only field is the display name
    At the bottom of that function is this:
    return apply_filters('the_author', is_object($authordata) ? $authordata->display_name : null);
    Since $authordata is global, a filter can use it to retrieve a custom display_name.

    Another example:

    For a post by someone (maybe) other than the current user:
    $display_name = get_the_author_meta( 'display_name', $id);
    That also returns with this:
    return apply_filters( 'get_the_author_' . $field, $value, $user_id, $original_user_id );

    The get_currentuserinfo function (pluggable deprecated in 4.5, use wp_get_current_user()) loads global $display_name
    Since that's pluggable it can overridden.

    For $value=$userdata->display_name, the WP_User object gets fields using "magic" functions, and then calls sanitize_user_field(). That function also calls a number of filters.

    I'm convinced that a small series of filter functions can be written to modify the value based on the site or specific conditions. I'll think on it for a bit and will try my hand at some code, then post notes back here.

  • Adam Czajczyk

    Hello Tony!

    Great findings indeed. I think that's the path I'd follow as well. Once more function I'd add to you list would be the

    get_current_blog_id()

    It should help you determine the blog for which you should fetch selected "display name".

    I'll think on it for a bit and will try my hand at some code, then post notes back here.

    I'm very interested in what will you come up with and will be happy to "review" your code if necessary and/or assist you further.

    Have a nice day!
    Adam

  • Tony G

    I'm considering another approach that might be simpler. It's similar to my original note about storing something like !!UNAME!!99999!!, and then parsing that at runtime.

    What if the display name is set in the database from the Profile page to the text of a shortcode:
    [dname site='00' id='00']
    The Profile page also needs to be modified to save a selected display name in wp_user_meta, keyed as site_id. (That's required for the filter option too.) Then all that's required at runtime is one simple shortcode function rather than a bunch of filters.

    The Profile page UI doesn't change at all. When the member posts their display name, rather than storing the entered field the shortcode is created and stored, and the entered field is saved as metadata. At Profile display time I will need to pre-process the shortcode, since I don't think an input field will be processed by text content filters.

    Doesn't that seem more elegant?

  • Adam Czajczyk

    Hey Tony!

    My reflections on this, if you don't mind :slight_smile:

    1. Depending on what approach will you take, it's possible that you could even avoid customization of profile "engine". The question is whether you want to add users some "freedom" in terms o choice of their display names or you'd prefer to automatically create display names using some fixed, pre-defined structure.

    2. I'm not quite convinced to that "shortcode" way. That surely would be simple to use and quite "elegant" but I'm not sure whether it would be equally "universal". There are many places across themes (and note please that there may be many themes used at once across entire network) where you cannot put shortcode "out of the box" (without changing theme files).

    Don't get me wrong, I'm not trying to "talk you into" anything :slight_smile: I think however that in case you'd like to go with "automatic, pre-structurized" display names you don't even need to implement any customization to user profiles. Instead you could create unique display name simply by creating some string with PHP (based on selected criteria) and then use it to create shortcode.

    A brief example (note please that this is a "pseudo code"):

    function my_unique_displayname() {
    $userID = current_user_id();
    $siteID = current_site_id();
    $displayname = 'User" . $userID . $siteID;
    return $displayname;
    }

    For user with an ID of 12 on a site with an ID of 7 it would produce a unique display name: User127.

    Having that, you could now either go with your "shortcode" way or - which would be a bit more universal IMHO - apply filters to e.g. "get_the_author" and other necessary template tags.

    But that are just my ideas :slight_smile:

    Best regards,
    Adam

  • Tony G

    Thanks Adam - I'm enjoying this process, where there has been no solution for years, and we're now discussing nuances of an easy/elegant solution. :slight_smile: We're still on the same page. (This thread is as much for anyone else looking for this functionality as it is to work through it for my own purposes, and to get some practice figuring out how to implement new functionality. So this thread is "multi-purpose". :slight_smile:

    In this environment, I own the site and all multi-sites will be "Pro Site" instances. So themes will be completely under super admin control - and as we see below that shouldn't be an issue. For users, the net result is, for example, that you can be "Adam" in one site, "Adam C" in another, and "Mr StudPress" in another.

    Based on our exchanges, I was just researching again and I think this is even simpler...

    Requests to insert and update WP_User records go through user.php. To save a site-specific display name, the user just enters it into their unmodified Profile page while in the site. The wp_insert_user function applies the filter pre_user_display_name where the name can be re-saved to user meta as displayName_Site_UID or similar. (Updates go through Insert.) So only one filter is required to save the data.

    Similarly, reads can go even lower than get_the_author and similar functions. WP_User is also invoked to read all user data and user metadata. The __get magic function is executed for almost all requests for display_name. That gets data from get_user_meta. In there, the data comes from cache or the database. When it comes back to __get, it's passed to sanitize_user_field. And that calls to a small number of filters which are easily hooked.

    The only issue I see so far involves queries which sort or filter on the display name. There are hooks for those too, and I'll look into them shortly.

  • Adam Czajczyk

    Hey Tom,

    Thanks for your response!

    The idea of saving "pre-processed" user display name automatically as a user meta sounds really great.That would be quite a simple solution and - that's even bigger advantage - easy to upgrade/enhance in future! I haven't thought of that, nice shot indeed!

    I'm really curious what more you will come up with!

    Keep up the great work and feel free to get back to me anytime with new ideas and/or question!

    Best regards,
    Adam

Thank NAME, for their help.

Let NAME know exactly why they deserved these points.

Gift a custom amount of points.