HackerOne users: Testing against this community violates our program's Terms of Service and will result in your bounty being denied.

Show a display name instead of username

jspautschjspautsch ✭✭✭
I'd like for users and their posts to be labeled with a display name (e.g. "Jon Smith") that's separate from the username they use to login (which is how our SSO works). I've searched around a bit, as I could've sworn I saw someone else ask as similar question, but I couldn't find anything, so I was wondering if anyone else had any ideas as to how best to go about doing this.

I'll be delving into myself in a couple days, but first I wanted to see what the community had to say. Also I'd really like to keep it confined to a plugin and thereby avoid modifying any of the core files, but I'm new to Vanilla development and am not sure if that will be possible for this particular feature.
«1

Answers

  • This is very doable as a plugin. Let us know if you get stuck!
  • Done! Definitely easier than I thought, although I did have to add an event trigger into the ActivityQuery() function in ActivityModel.

    For the rest, I made a plugin that did the following:
    1) Added another column to the User table called DisplayName
    2) Overrode the UserBuilder and UserAnchor functions to include DisplayName.
    3) Setup event handlers for AfterDiscussionSummaryQuery, BeforeGetID (discussion model), AfterCommentQuery, and AfterActivityQuery (which I had to add into the core code myself) to add select statements that mirrored the Name statements in each function, except replaced with DisplayName instead.

    This setup allowed me to change the link text to use display names, but left most of the links themselves intact (linking to usernames not display names). Mind you, even if the links to point to display names it doesn't seem to affect anything, seeing as the links really use User IDs.
  • jspautsch - are you going to make the plugin code available? I also need this feature for my users.
  • jspautschjspautsch ✭✭✭
    edited September 2011
    Sure thing, I'll see if I can get that done tomorrow. It will require some manual changes in the core code, and I've only tested it with 2.0.18b4.

    I also don't have a way to set the display name, that's done separately in the code for my SSO login.
  • That would be fantastic. We're running on the release version but if it's reasonably stable I'm willing to upgrade to the beta if need be.

    We're using SSO too, so that's not a problem.
  • jspautschjspautsch ✭✭✭
    edited September 2011
    Alright follow these steps and it SHOULD work. Let me know if it doesn't and what kind of errors you get. First, you need to make some modifications to the core code...

    Step 1: Make the following modifications...
    /applications/dashboard/models/class.usermodel.php

    FIND: $Join = GetValue('Join', $Options, array('Name', 'Email', 'Photo'));
    REPLACE WITH: $Join = GetValue('Join', $Options, array('Name', 'Email', 'Photo', 'DisplayName'));

    /applications/vanilla/models/class.commentmodel.php

    IN public function GetID
    FIND $this->CommentQuery(FALSE);
    REPLACE WITH $this->CommentQuery();

    IN public function GetIDData
    FIND $this->CommentQuery(FALSE);
    REPLACE WITH $this->CommentQuery();

    /applications/dashboard/models/class.activitymodel.php

    IN: public function ActivityQuery
    FIND: ->Join('User ru', 'a.RegardingUserID = ru.UserID', 'left');
    ADD AFTER: $this->FireEvent('AfterActivityQuery');

    /applications/conversations/models/class.conversationmodel.php

    IN: public function GetRecipients
    FIND: ->Select('uc.UserID, u.Name, uc.Deleted')
    REPLACE WITH: ->Select('uc.UserID, u.Name, u.DisplayName, uc.Deleted')
    See next comment for the plugin code...
  • jspautschjspautsch ✭✭✭
    edited September 2011
    Step 3: Create a plugin, in this example it's called "DisplayNameplugin". I separated this code out from another plugin of mine, so I'm not sure if it works on its own, I think I pulled over every relevant modification.

    Note that this plugin overrides two methods: UserAnchor and UserBuilder. If you're using another plugin that also overrides these methods (like Gravatar), I'm pretty sure you'll need to modify them to include DisplayName as well.
    <?php if (!defined('APPLICATION')) exit();
    // Define the plugin:
    $PluginInfo['DisplayNameplugin'] = array(
    'Description' => 'Plugin to implement support for display names',
    'Version' => '1.0',
    'Author' => "Jonathan Pautsch",
    'AuthorEmail' => 'jspautsch@gmail.com',
    'AuthorUrl' => 'http://vanillaforums.org/profile/32921/jspautsch'
    );

    class DisplayNameplugin extends Gdn_Plugin
    {
    public function Setup()
    {
    Gdn::Structure()
    ->Table('User')
    ->Column('DisplayName', 'text', NULL)
    ->Set();
    }

    public function CommentModel_AfterCommentQuery_Handler(&$Sender, $Args)
    {
    $Join = GetValue('Join', $Args);
    if ( $Join )
    {
    $Sender->SQL->Select('iu.DisplayName', '', 'InsertDisplayName')
    ->Select('uu.DisplayName', '', 'UpdateDisplayName');
    }
    }

    public function ActivityModel_AfterActivityQuery_Handler(&$Sender)
    {
    $Sender->SQL->Select('au.DisplayName', '', 'ActivityName')
    ->Select('ru.DisplayName', '', 'RegardingName')
    ->Select('au.DisplayName', '', 'ActivityDisplayName')
    ->Select('ru.DisplayName', '', 'RegardingDisplayName');
    }

    public function ConversationMessageModel_BeforeGet_Handler(&$Sender)
    {
    $Sender->SQL->Select('iu.DisplayName', '', 'InsertDisplayName');
    }
    }

    if (!function_exists('UserBuilder'))
    {
    //Override the default UserBuilder function
    function UserBuilder($Object, $UserPrefix = '')
    {
    $Object = (object)$Object;
    $User = new stdClass();
    $UserID = $UserPrefix.'UserID';
    $Name = $UserPrefix.'Name';
    $DisplayName = $UserPrefix.'DisplayName';
    $Photo = $UserPrefix.'Photo';
    $Gender = $UserPrefix.'Gender';
    $User->UserID = $Object->$UserID;
    $User->Name = $Object->$Name;
    $User->DisplayName = $Object->$DisplayName;
    $User->Photo = property_exists($Object, $Photo) ? $Object->$Photo : '';
    $User->Email = GetValue($UserPrefix.'Email', $Object, NULL);
    $User->Gender = property_exists($Object, $Gender) ? $Object->$Gender : NULL;
    return $User;
    }
    }

    if (!function_exists('UserAnchor'))
    {
    //Override the default UserAnchor function
    function UserAnchor($User, $CssClass = '', $Options = NULL)
    {
    static $NameUnique = NULL;
    if ($NameUnique === NULL)
    $NameUnique = C('Garden.Registration.NameUnique');

    $Px = $Options;
    $Name = GetValue($Px.'Name', $User, T('Unknown'));
    $DisplayName = GetValue($Px.'DisplayName', $User, T('Unknown'));
    $UserID = GetValue($Px.'UserID', $User, 0);

    if ($CssClass != '')
    $CssClass = ' class="'.$CssClass.'"';

    return ''.htmlspecialchars($DisplayName).'';
    }
    }

    ?>
  • So once that's done you just need to modify the code you're using to sync your SSO users to update each user's display name. Mine, for example, uses SOAP requests to authenticate each user and the user's display name is included in the response, so I just have to load that into a variable and issue a simple database update.
    Gdn::SQL()->Update('User')
    ->Set('DisplayName', $newdisplayname)
    ->Where('UserID', $userid)
    ->Put();
  • Hmmm looks like some of these functions have changed a lot in 2.0.18b4. I'll work on updating them, in the meantime it should work with b2.
  • Thanks heaps. I'm not likely to get to this today due to other commitments, but hopefully this week sometime I can suck down 2.0.18b4 and test your code changes. I'll let you know how it goes.
  • Updated the instructions for 2.0.18b4.
  • I'm trying to use this but apparently I'm missing something, I'm using 2.0.18.8 and it doesn't display the Display Name, just a blank spot, which is a problem. I've attempted to disable the plugin so I could at least go back and have the username display, but it looks like it's stuck in there pretty good and can't disable it. When I click jsConnect in the dashboard and run Test URL it shows the display name as well as the correct other information, so I know it's making its way into Vanilla. Any suggestions? I am guessing something changed in the coding in between versions that the plugin code need some adjusting, just not sure quite where to look as I am new to using this forum and still trying to figure out it's in's and out's.

  • peregrineperegrine MVP
    edited September 2013

    Are you using this plugin...

    http://vanillaforums.org/addon/firstlastnames-plugin

    or the instructions in this thread. Perhaps the plugin above is what you really want.

    I've attempted to disable the plugin so I could at least go back and have the username display, but it looks like it's stuck in there pretty good and can't disable it.

    you can disable the plugin in the conf/config.php - by removing the line that refers to the plugin in question.

    $Configuration['EnabledPlugins']['THEPLUGINNAMEYORARETRYINGTOREMOVE'] = ...

    I may not provide the completed solution you might desire, but I do try to provide honest suggestions to help you solve your issue.

  • anyone been successful with this in 2.0.18.8? I will give it a go later today and report the experience.

  • Ok, figured out how to disable it, I had actually renamed it within my file structure and that worked also, but I have used your suggestion, thank you. I've completely reinstalled this and still no luck. I actually have a displayname coming thru and was hoping to use that, so I was using the code above. I noticed some changes such as in class.activitymodel.php, $this->FireEvent('AfterActivityQuery'); was already there, and in class.conversationmodel.php there was an extra field in there of u.Email, but I don't see those being a big issue. I could very well use the firstlastnames plugin you referenced, but in the forum I'd much rather not allow users to change information, I'd like the SSO system to maintain that in my regular site to keep everything all the same. I did try that plugin and it works until a new user tries to register and I presume since I have this vanillaforums.org/discussion/22681/disable-edit-my-account-and-change-password-for-sso working in there it will not let the user enter the first or last name at the sign in screen, therefore they can't register. jspautsch references a simple database update, that may be the part I'm missing; I must confess MySQL and phpmyadmin tend to throw me for a loop. I'm thinking that may be where I'm going wrong.

  • Well I feel like I should have egg on my face, after thinking about this a bit I realized that I have the jsConnect plugin working, and in order for the Display name field to send into the database like the name, email, ect, I needed to add DisplayName into the class.jsconnect.plugin.php file, now when a user is automatically registered the display name field comes along and is added properly. It just randomly came to me today, and after a quick test that is all it was and it is now working. Thanks for the suggestions.

  • Anyone a solution for 2.4 with display names?

  • 2.4 hasn't been released for production, and now never will be (moving straight to 2.5)

  • @timme2707 said:
    Anyone a solution for 2.4 with display names?

    To my opinion the approach is somewhat borked, but I'm not 100% sure what the requirements are. Is it for security? Is it just for fun?

    I have just drafted* a small plugin which forces users to log into the forum with their mail address so that it wouldn't be possible to log into the forum with the user name displayed.
    If you have security concerns, than that would be your solution.

    If it is just for fun and you want to allow users to show cool names here and there, you might want to try the ProfileExtender plugin and learn how to add such a name to several places by making use of Vanillas event system.

    * = it is more than just a proof of concept and already fully usable but in order to not mess anything up, there need to be a check in the setup process for duplicate mail addresses in the database. If some users have registered more than one account with the same mail address, they wouldn't be able to access all of their accounts

  • Thanks for your quick answers!

    @whu606 said:
    2.4 hasn't been released for production, and now never will be (moving straight to 2.5)

    Sorry, I mean the current public 2.3.1...

    @R_J said:

    @timme2707 said:
    Anyone a solution for 2.4 with display names?

    To my opinion the approach is somewhat borked, but I'm not 100% sure what the requirements are. Is it for security? Is it just for fun?

    ...

    It's just because I want to display the full name of a user for a serious forum. The usernames cannot have white spaces or typically german letters like "ä" "ü" "ö" "ß" - That's ok, because of the login i guess, but in my case I looking for a way to do it.

    Currently I have found a way with the ProfileExtender plugin and a simple override based on the solution upward for the "UserAnchor" function, this is working on discussions but not in the activities or profile page. Have someone an Idea why? I guess for the profile page heading is another function to override required.

    (My php skills are not perfect)

    if (!function_exists('UserAnchor'))
    {
        //Override the default UserAnchor function
        function UserAnchor($User, $CssClass = null, $Options = NULL)
        {
            static $NameUnique = null;
            if ($NameUnique === null) {
                $NameUnique = c('Garden.Registration.NameUnique');
            }
            if (is_array($CssClass)) {
                $Options = $CssClass;
                $CssClass = null;
            } elseif (is_string($Options)) {
                $Options = array('Px' => $Options);
            }
            $Px = val('Px', $Options, '');
            $UserID = GetValue($Px.'UserID', $User, 0);
            $DisplayName = GetUserDisplayNamebyID($UserID);
            $Text = val('Text', $Options, htmlspecialchars($DisplayName));
            $Attributes = array(
                'class' => $CssClass,
                'rel' => val('Rel', $Options)
            );
            if (isset($Options['title'])) {
                $Attributes['title'] = $Options['title'];
            }
            $UserUrl = userUrl($User, $Px);
            return '<a href="'.htmlspecialchars(url($UserUrl)).'"'.attribute($Attributes).'>'.$Text.'</a>';
        }
    
        function GetUserDisplayNamebyID($UserID)
        {
            $SQL = Gdn::sql();
            $SQL
                    ->Select('u.Value')
                    ->From('UserMeta u')
                    ->Where('u.UserID', $UserID)
                    ->Where('u.Name', "Profile.Anzeigename");
    
            $UserMeta = $SQL->Get()->FirstRow();    
            if(isset($UserMeta->Value) and !empty($UserMeta->Value)){
            $DisplayName = $UserMeta->Value;
        }
    
            else{
                $DisplayName = T('Unknown');
            }
            return $DisplayName;
        }
    }
    
Sign In or Register to comment.