I have looked through the drupal.org website and drupal code for convenient ways to utilize display names instead of usernames. One possible way I found was to edit format_name in common.inc, but many references to the user do not use this format routine.

I found a quick and easy way to meet this need for my site. I have attached a patch that simply looks up the displayName and overwrites $name immediately after login. It appears to work very well. Should this be incorporated, someone would need to make this feature optional via the ldap_integration module settings.

Hope this helps others with the same issue as me.

Comments

2root4u’s picture

StatusFileSize
new275 bytes

Goofed on the attachment....

2nd try.

pablobm’s picture

My knowledge of LDAP is very limited, but I presume the attribute displayName will not be present in every configuration, so I don't think it is appropriate to include that code in the standard distribution of this module.

jredding’s picture

Priority: Normal » Minor
Status: Active » Needs review

This is similiar to the DisplayName as Username patch.

I am using the LDAP auth module to authenticate against an OS X Open Directory. Members are stored in
cn=users, dc=example,dc=com

and they each have 1 or more UIDs. Unfortunately a new drupal account would be created for each one of the UIDs used to log into the site.

I modified ldap_integration.module to change the name BEFORE the user account is loaded (or created) so that it reflects the 1st UID present. This is also the only UID present in group membership (which I'm also having problems getting working).

The code I am using is
$dn = _ldap_integration_login2dn("$name$at$server");
$name = $ldap->retrieveAttribute($dn, 'uid');

which is two NEW lines of code that go in at line 886 of ldap_integration.module BEFORE the line of code that reads

$user = user_load(array('name' => "$name$at$server"));

I'm using the code on the Wiki dated March 11th.

Thanks for the good work!

bwgames’s picture

Status: Needs review » Active

Is there a way to modify the rewritten version (ldapauth.module etc) to replace $user with the displayName attribute? The patch only works with the old version of ldapintegration
Ideally I'd like users to be able to login using the attribute uid, but have all future occurences of $user replaced with the displayName attribute, so that when something gets posted, it says "Posted by Joe Bloggs" instead of "Posted by jbloggs" - i.e. changing the $user attribute after login.

I've had a look, and tried adding the below to the function _ldapauth_ldap_login in ldapauth.module, but it didn't work:

$entry = $ldap->retrieveAttributes($user->ldap_dn);
$ldap->disconnect();
$name = $entry['cn'];

$user = user_save('', array('name' => $name, 'pass' => $pass, 'mail' => $mail, 'init' => $init, 'status' => 1, 'authname_ldapauth' => $login_string, 'roles' => array(DRUPAL_AUTHENTICATED_RID), 'ldap_authentified' => TRUE, 'ldap_dn' => $dn)); //this line has been unchanged

aclight’s picture

I don't know about Drupal 4.6, but with 4.7 I think this is better done by theming the username display, unless I'm misunderstanding what you are trying to do. If you use the ldapdata module to synchronize user profile fields with ldap attributes, you can store a user's LDAP displayName in, for example, a field profile_displayname, and then use a function in the template.php file of the theme to change the way the username is displayed. I know that Drupal 4.6 doesn't use phptemplate themes as a default, so I don't know if this is actually possible with 4.6, but I'm running 4.7.4 and it works for me. Here is a slightly edited version of the relevant function in my template.php file:

/**
 * Catch the theme_username function and link to the usernode instead of linking to the userpage
 */

function phptemplate_username(&$object) {

  if ($object->uid && $object->name) {
   	

  	// we want to display
  	// the user's real name. 7
		
  	$user->uid = $object->uid;
  	profile_load_profile($user);
  	//$user = user_load(array('uid' => $object->uid));     // comment the above line and uncomment this line to load the user instead of the user's profile
  	if (!empty($user->profile_displayname)) {
  		$object->name = $profile_displayname;
  	}
  	else {
  		$object->name = 'Unknown';
  	}


   	
    // Shorten the name when it is too long or it will break many tables.
    if (drupal_strlen($object->name) > 20) {
      $name = drupal_substr($object->name, 0, 15) .'...';
    }
    else {
      $name = $object->name;
    }
    $output = check_plain($name);

    if (user_access('access user profiles')) {			 
      $output = l($name, 'user/'. $user->uid, array('title' => t('View user details.')));
     }
     else {
      $output = check_plain($name);
    }
  }
  else if ($object->name) {
    // Sometimes modules display content composed by people who are
    // not registered members of the site (e.g. mailing list or news
    // aggregator modules). This clause enables modules to display
    // the true author of the content.
    if ($object->homepage) {
      $output = l($object->name, $object->homepage);
    }
    else {
      $output = check_plain($object->name);
    }

    $output .= ' ('. t('not verified') .')';
  }
  else {
    $output = variable_get('anonymous', 'Anonymous');
  }

  return $output;
}

This function will display the displayname of the user (if it is set in the user's profile) and will provide a link to the user page of that user, but only if the viewer of the page has permission to access user profiles.

Notice that the function as I've written it will load the user's profile, and not the user itself. This is (at least on my system) much faster, but has the disadvantage that changes in the LDAP database will not be reflected in your Drupal system until a user logs in again. I doubt that this would be a big problem in many situations, but it could be a problem for some. If so, just swap out which line is active and which one is commented out.

I think this solution is much better than patching the module code itself, unless 4.6 just won't work with this solution at all.

AC

nealparr’s picture

Based on aclight's code, I modified it to show the displayname if it exists and the regular username if they haven't entered a displayname (plus I fixed a typo: where it says $object->name = $profile_displayname;... it should read $object->name = $user->profile_displayname; to work properly)

<?php
/**
 * Catch the theme_username function and link to the usernode instead of linking to the userpage
 */

function phptemplate_username($object) {

  if ($object->uid && $object->name) {

      // we want to display
      // the user's real name. 7
        
      $user->uid = $object->uid;
      profile_load_profile($user);
      //$user = user_load(array('uid' => $object->uid));     // comment the above line and uncomment this line to load the user instead of the user's profile
      if (!empty($user->profile_displayname)) {
          $object->name = $user->profile_displayname;
      }
       
    // Shorten the name when it is too long or it will break many tables.
    if (drupal_strlen($object->name) > 20) {
      $name = drupal_substr($object->name, 0, 15) .'...';
    }
    else {
      $name = $object->name;
    }
    $output = check_plain($name);

    if (user_access('access user profiles')) {             
      $output = l($name, 'user/'. $user->uid, array('title' => t('View user details.')));
     }
     else {
      $output = check_plain($name);
    }
  }
  else if ($object->name) {
    // Sometimes modules display content composed by people who are
    // not registered members of the site (e.g. mailing list or news
    // aggregator modules). This clause enables modules to display
    // the true author of the content.
    if ($object->homepage) {
      $output = l($object->name, $object->homepage);
    }
    else {
      $output = check_plain($object->name);
    }

    $output .= ' ('. t('not verified') .')';
  }
  else {
    $output = variable_get('anonymous', 'Anonymous');
  }

  return $output;
}
?>
Pjeirke’s picture

Hi everyone,

Can I use this solution for drupal 5.1 aswell?

I would like to get rid of the drupal username being the samaccountname.

Thx
Peter

geste’s picture

I am interested to see this discussion, and I am pretty ignorant of Drupal "architecture", but when I read the first part of this discussion I asked myself "Is this the right place/way to be doing this?" (i.e in ldap integration module code).

I am also interested in using displayName in stead of UID in many cases, but, in my case, uid is my one, single, guaranteed unique identifier so I have no interest in displacing it "under the hood". And as pablobm pointed out, some directories may not store dispalyName. I'd like to be able pick and choose and use uid and displayName as appropriate. The template approach of aclight/nealparr using profile_displayname when present seems like a cleaner approach.

Jim

scafmac’s picture

Indeed this is something for the theming layer, not the ldap_integration module.

Pjeirke’s picture

Hello everyone.

Is their any new information about this issue?

Just a tought.
So I install the ldap module with the ldap data module.
Users log in and a user profile is created. If you go to administer -> user management -> Users.
Their you can see a profile is create using the uid/samaccountname as username.

So i'm just thinking. What if we place the displayname there (would make things easier to search for users as well).
I don't think that's a theming problem then.

Am I so far off or does it make any sence?

Pjeirke’s picture

I just forgot to mension I'm using drupal 5.1

scarer’s picture

I am also searching for a solution for 5.1 Do you think the solution for 4.7 might work for 5.1? Sorry I'm not too familiar with the API.

Cheers,

Sarah

scarer’s picture

/**
* Catch the theme_profile_profile function, and redirect through the template api
*/
function phptemplate_user_profile($user, $fields = array()) {
  // Pass to phptemplate, including translating the parameters to an associative array. The element names are the names that the variables
  // will be assigned within your template.
  /* potential need for other code to extract field info */
return _phptemplate_callback('user_profile', array('user' => $user, 'fields' => $fields));
  }
?>

Is this the function that should be modified in Drupal 5.1?

scarer’s picture

in the drupal API it says that the user name display is controlled by the theme.inc file. The following function controls the display of the username:

function theme_username($object) {

  if ($object->uid && $object->name) {
    // Shorten the name when it is too long or it will break many tables.
    if (drupal_strlen($object->name) > 20) {
      $name = drupal_substr($object->name, 0, 15) .'...';
    }
    else {
      $name = $object->name;
    }

    if (user_access('access user profiles')) {
      $output = l($name, 'user/'. $object->uid, array('title' => t('View user profile.')));
    }
    else {
      $output = check_plain($name);
    }
  }
  else if ($object->name) {
    // Sometimes modules display content composed by people who are
    // not registered members of the site (e.g. mailing list or news
    // aggregator modules). This clause enables modules to display
    // the true author of the content.
    if ($object->homepage) {
      $output = l($object->name, $object->homepage);
    }
    else {
      $output = check_plain($object->name);
    }

    $output .= ' ('. t('not verified') .')';
  }
  else {
    $output = variable_get('anonymous', t('Anonymous'));
  }

  return $output;
}
}

I have set up a user profile field called "profile_displayName"

If I replaced $object->name with $user->profile_displayName would this show the user's display name instead of their user name? Should I be modifying this file at all?

Any help would be great :)

Cheers,

Sarah

scarer’s picture

/**
 * Format a username.
 *
 * @param $object
 *   The user object to format, usually returned from user_load().
 * @return
 *   A string containing an HTML link to the user's page if the passed object
 *   suggests that this is a site user. Otherwise, only the username is returned.
 */
function theme_username($object) {

  if ($object->uid && $object->name) {
    // Shorten the name when it is too long or it will break many tables.
    if (drupal_strlen($object->name) > 20) {
      $name = drupal_substr($object->name, 0, 15) .'...';
    }
    else {
      $name = $object->name;
    }

    if (user_access('access user profiles')) {
      $output = l($object->profile_displayName, 'user/'. $object->uid, array('title' => t('View user profile.')));
    }
    else {
      $output = check_plain($name);
    }
  }
  else if ($object->name) {
    // Sometimes modules display content composed by people who are
    // not registered members of the site (e.g. mailing list or news
    // aggregator modules). This clause enables modules to display
    // the true author of the content.
    if ($object->homepage) {
      $output = l($object->name, $object->homepage);
    }
    else {
      $output = check_plain($object->name);
    }

    $output .= ' ('. t('not verified') .')';
  }
  else {
    $output = variable_get('anonymous', t('Anonymous'));
  }

  return $output;
}

I changed the part of the function for displaying the username on the profile to display their displayName instead but now the author's of content will not appear on content. Please help!

scarer’s picture

I eventually figured it out lol...

This is the guide for idiots like me.

First create a profile field called profile_displayName through your administer panel and then profiles, add field.

If you are running 5.1 you need to change the function theme_username in includes/theme.inc to read something like this:

function theme_username($object) {

if ($object->uid && $object->name) {

// we want to display
// the user's real name. 7

$user->uid = $object->uid;
profile_load_profile($user);
//$user = user_load(array('uid' => $object->uid)); // comment the above line and uncomment this line to load the user instead of the user's profile
if (!empty($user->profile_displayName)) {
$object->name = $user->profile_displayName;
}
else {
$object->name = 'Unknown';
}

// Shorten the name when it is too long or it will break many tables.
if (drupal_strlen($object->name) > 20) {
$name = drupal_substr($object->name, 0, 15) .'...';
}
else {
$name = $object->name;
}
$output = check_plain($name);

if (user_access('access user profiles')) {
$output = l($name, 'user/'. $user->uid, array('title' => t('View user details.')));
}
else {
$output = check_plain($name);
}
}
else if ($object->name) {
// Sometimes modules display content composed by people who are
// not registered members of the site (e.g. mailing list or news
// aggregator modules). This clause enables modules to display
// the true author of the content.
if ($object->homepage) {
$output = l($object->name, $object->homepage);
}
else {
$output = check_plain($object->name);
}

$output .= ' ('. t('not verified') .')';
}
else {
$output = variable_get('anonymous', 'Anonymous');
}

return $output;
}

Thanks for all you help :) Great work with the code guys.

Cheers,

Sarah

scarer’s picture

by the way it wont work on blog posts not too sure what else yet...

nevets’s picture

A couple of comments, it does not work on blog post because the module does not use the theme function.

Also, one should not replace theme_username in theme.inc, it makes upgrades a possible problem. Instead one should override the theme function by adding the function as phptemplate_username to the template.php which is part of the theme

g011um’s picture

Version: 4.6.x-1.x-dev » 5.x-1.x-dev

On my 5.1 site it does not affect the username displayed on the top of the Nav menu, the browser title, or the user's account page. I assume this is due to the same reason it doesn't affect blog posts.

This seems like an excellent first stab at things, but Drupal itself doesn't seem to consistently use the theme functions. Any other thoughts on a universal solution?

scafmac’s picture

Status: Active » Closed (fixed)

This is not really an LDAP issue so I'm closing this. More info at - http://drupal.org/node/119815

As many have noticed, no solution is ideal - some modules & core that use theming don't work with one solution while the ones that use theming don't work with the other solution. Ultimately though since theming is integral to Drupal - I believe the theming solution will prove to be the best choice.

Also as nevet pointed out, do not hack core as many of these posts suggest. It is not the right way to do it. If you are unclear what I mean, start with the post I mentioned - 119815 . It will get you started with a basic solution, then return to this one to cherry pick pieces.